{"record":{"id":"f0dc4542e81fbf53","repo":"JuliusBrussee/caveman","slug":"cave-harness-context-ir-mismatch","errorCode":"cave_harness_context_ir_mismatch","errorMessage":"cave_harness_context_ir_mismatch","messagePattern":"cave_harness_context_ir_mismatch","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/execution-kernel.ts","lineNumber":90,"sourceCode":"  const build = parseCaveBuildLock(input.build);\n  if (build.harness.id !== input.harness ||\n      build.harness.adapter_version !== input.adapterVersion ||\n      build.harness.upstream_version !== input.upstreamVersion) {\n    throw new Error(\"cave_harness_build_mismatch\");\n  }\n  if (input.agentId !== undefined && build.agent_id !== input.agentId) {\n    throw new Error(\"cave_harness_agent_mismatch\");\n  }\n  if (stableStringify(input.plan) !== stableStringify(build.selected_plan)) {\n    throw new Error(\"cave_harness_plan_mismatch\");\n  }\n  const planSHA256 = sha256(stableStringify(input.plan));\n  if (planSHA256 !== build.plan_sha256) {\n    throw new Error(\"cave_harness_plan_digest_mismatch\");\n  }\n  const contextIRSHA256 = sha256(stableStringify(contextIRToWire(input.contextIR)));\n  if (contextIRSHA256 !== build.context_ir_sha256) {\n    throw new Error(\"cave_harness_context_ir_mismatch\");\n  }\n  const [provider, ...modelParts] = input.plan.model.split(\"/\");\n  const model = modelParts.join(\"/\");\n  if (!provider || !model) throw new Error(\"cave_harness_model_invalid\");\n  return Object.freeze({\n    build,\n    plan: build.selected_plan,\n    planSHA256,\n    contextIRSHA256,\n    provider,\n    model,\n  });\n}\n\nexport interface ProviderUsageEvidence {\n  provider: string;\n  model: string;\n  inputTokens: number;","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/execution-kernel.ts#L72-L108","documentation":"Thrown while preparing a locked harness (packages/agent/src/execution-kernel.ts:90): the SHA-256 of the wire-form Context IR supplied at run time does not match context_ir_sha256 in the CaveBuildLock. The lock pins the static context segments of the agent definition; if the lowered context IR changed after the lock was built, execution fails closed before any provider traffic.","triggerScenarios":"Changing an agent's instructions, contexts, tool definitions, or other static segments after the lock was generated, then running with the old lock; anything that alters contextIRToWire output (definition edits, framework upgrade changing lowering).","commonSituations":"Editing prompts/context files or the agent definition and forgetting to rebuild; upgrading @caveman-ai/agent so the Context IR lowering changed shape; note eval/user input, history, and tool results are runtime segments and never enter this digest — so the drift is always in static definition content.","solutions":["Rebuild the lock after any change to instructions, contexts, tools, or other static definition segments.","Confirm the file sources feeding the Context IR are unchanged since the build (FileSource contents are part of static segments).","After a framework upgrade, regenerate all locks — lowered IR shape may change between versions."],"exampleFix":"# before\n# edit prompts/system.md, then run with the old lock\ncaveman run --lock cave-build.lock # -> cave_harness_context_ir_mismatch\n\n# after\ncaveman build && caveman run --lock cave-build.lock","handlingStrategy":"validation","validationCode":"// Before running a locked build, recompute the Context IR digest:\nconst irDigest = sha256(stableStringify(contextIRToWire(lowerContextIR(definition))));\nif (irDigest !== lock.context_ir_sha256) {\n  await rebuildLock(); // static definition segments changed since build\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Rebuild the lock after any edit to instructions, contexts, tools, or FileSource contents.","Remember runtime segments (user input, history, tool results) never affect this digest — only static definition content does.","Automate lock regeneration in dev watch flows so prompt edits don't leave stale locks."],"tags":["lockfile","context-ir","drift","reproducibility"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}