{"record":{"id":"84172acef61fb107","repo":"JuliusBrussee/caveman","slug":"cave-harness-plan-mismatch","errorCode":"cave_harness_plan_mismatch","errorMessage":"cave_harness_plan_mismatch","messagePattern":"cave_harness_plan_mismatch","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/execution-kernel.ts","lineNumber":82,"sourceCode":"  build: CaveBuildLock;\n  harness: string;\n  adapterVersion: string;\n  upstreamVersion: string;\n  agentId?: string;\n  contextIR: ContextIR;\n  plan: CavePlan;\n}): LockedHarnessPreparation {\n  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,","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/execution-kernel.ts#L64-L100","documentation":"Thrown while preparing a locked harness (packages/agent/src/execution-kernel.ts:82): the plan object supplied at execution time does not stringify-equal the build.selected_plan stored in the CaveBuildLock. Locked execution must run byte-identical plans; any difference (model, reasoning, tool set, context) between the supplied plan and the locked one fails closed.","triggerScenarios":"Passing a re-computed or edited CavePlan to prepareLockedHarness while using an older lock; changing model/reasoning settings in code after the lock was generated; plan objects whose JSON key order or content differs from the locked snapshot.","commonSituations":"Editing agent or plan configuration without rebuilding the lock; CI reusing a committed lock with fresh plan computation; hand-modifying plan fields (model string, reasoning level) to 'tune' a locked run.","solutions":["Pass the plan exactly as recorded in the lock (use build.selected_plan) instead of re-deriving it.","If the plan legitimately changed, re-run the build/compile step to produce a new lock containing the new selected_plan.","Diff the supplied plan against lock.selected_plan (stable stringify both) to find which field drifted."],"exampleFix":"// before\nprepareLockedHarness({ build: lock, plan: recomputedPlan, /* ... */ });\n\n// after\nprepareLockedHarness({ build: lock, plan: lock.selected_plan, /* ... */ });","handlingStrategy":"validation","validationCode":"import { stableStringify } from \"@caveman-ai/agent\"; // or local stable stringify\nif (stableStringify(input.plan) !== stableStringify(lock.selected_plan)) {\n  // either adopt the locked plan or rebuild the lock\n  input = { ...input, plan: lock.selected_plan };\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always execute with lock.selected_plan rather than a re-derived plan object.","Rebuild the lock after every change to model, reasoning, tools, or contexts.","Treat plan-vs-lock drift as a build pipeline bug: fix the pipeline, never edit the plan at run time."],"tags":["lockfile","plan","reproducibility","drift"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}