{"record":{"id":"d008cb036f390983","repo":"JuliusBrussee/caveman","slug":"caveman-code-no-tool-output-recorded-yet-to-prove","errorCode":null,"errorMessage":"caveman-code: no tool output recorded yet to prove recovery on","messagePattern":"caveman-code: no tool output recorded yet to prove recovery on","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/code.ts","lineNumber":957,"sourceCode":"  ];\n}\n\n// ---------------------------------------------------------------------------\n// Recovery proof\n// ---------------------------------------------------------------------------\n\nexport interface CodingRecoveryProof extends SegmentRecoveryProof {\n  segment: string;\n}\n\n/**\n * Take the largest raw tool output this session produced, push it through the\n * same engine compress/retrieve pair the plan and `cave_retrieve` use, and\n * compare bytes. This is the reversibility proof, not a savings claim.\n */\nexport async function proveRecovery(session: CodingSession): Promise<CodingRecoveryProof> {\n  const sample = session.agent.samples[0];\n  if (!sample) throw new Error(\"caveman-code: no tool output recorded yet to prove recovery on\");\n  const proof = await proveSegmentRecovery({\n    body: new TextEncoder().encode(sample.text),\n    transformID: TOOL_RESULT_TRANSFORM,\n    ...(session.options.engineBin === undefined ? {} : { engineBin: session.options.engineBin }),\n  });\n  return { ...proof, segment: sample.label };\n}\n\nexport function formatRecoveryProof(proof: CodingRecoveryProof): string {\n  if (proof.outcome === \"recovered\") {\n    return `recovery proof: ${proof.segment} round-trip OK (sha256 match ${proof.originalSHA256.slice(0, 12)})`;\n  }\n  if (proof.outcome === \"not_smaller\") {\n    return `recovery proof: ${proof.segment} not compressed — the engine kept the original bytes, nothing to recover`;\n  }\n  return `recovery proof: ${proof.segment} FAILED (sha256 mismatch) — the plan falls back to the original body`;\n}\n","sourceCodeStart":939,"sourceCodeEnd":975,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/code.ts#L939-L975","documentation":"proveRecovery demonstrates reversibility of compression by round-tripping the largest recorded raw tool output. It reads session.agent.samples[0]; if the session has not recorded any tool output yet, there is nothing to prove recovery on and the call fails.","triggerScenarios":"Calling proveRecovery(session) immediately after creating a session, before any tool (bash/grep/edit_file/read/write) has executed and recorded a sample.","commonSituations":"Test harnesses constructing a session and asserting the recovery proof without first running a tool; CLI flows that print a proof unconditionally at startup.","solutions":["Run at least one tool call (e.g. a grep or bash command) through the session before calling proveRecovery","Guard the call: check `session.agent.samples.length > 0` (or an accessor like hasSamples) first","In tests, seed the session with a recorded sample before asserting on the proof"],"exampleFix":"// before\nconst session = await createSession(opts);\nconst proof = await proveRecovery(session); // throws\n\n// after\nawait session.tools.bash.execute({ command: \"ls\" }, signal);\nif (session.agent.samples.length > 0) {\n  const proof = await proveRecovery(session);\n}","handlingStrategy":"type-guard","validationCode":"const hasSamples = session.agent.samples.length > 0;\nif (!hasSamples) {\n  await session.tools.bash.execute({ command: \"pwd\" }, signal); // record one sample\n}","typeGuard":"function canProveRecovery(session: CodingSession): boolean {\n  return Array.isArray(session.agent.samples) && session.agent.samples.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Only call proveRecovery after at least one tool execution in the session","In test suites, seed a recorded sample before asserting on recovery proofs"],"tags":["compression","recovery-proof","lifecycle","session-state"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}