{"record":{"id":"8cd0d4fd33b45547","repo":"paperclipai/paperclip","slug":"semantic-result-completion-contract-revision-does","errorCode":null,"errorMessage":"Semantic result completion contract revision does not match","messagePattern":"Semantic result completion contract revision does not match","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts","lineNumber":905,"sourceCode":"      { turnId, itemId: call.callId },\n    );\n    if (tool === PRP_COMPLETION_TOOL_NAME || tool === PRP_BLOCK_TOOL_NAME) {\n      const validation = validatePrpStructuredRunResult(call.arguments);\n      if (!validation.ok) throw new Error(\"Invalid semantic result\");\n      if (\n        (tool === PRP_BLOCK_TOOL_NAME &&\n          validation.result.reportedWorkDisposition !== \"blocked\") ||\n        (tool === PRP_COMPLETION_TOOL_NAME &&\n          validation.result.reportedWorkDisposition === \"blocked\")\n      )\n        throw new Error(\n          \"Semantic result disposition does not match the terminal tool\",\n        );\n      if (\n        validation.result.completionClaim.contractRevision !==\n        this.#taskEnvelope.completionContract.revision\n      ) {\n        throw new Error(\n          \"Semantic result completion contract revision does not match\",\n        );\n      }\n      const fingerprint = canonicalJson(validation.result);\n      if (this.#resultFingerprint && this.#resultFingerprint !== fingerprint)\n        throw new Error(\"A different semantic result was already committed\");\n      if (!this.#resultFingerprint) {\n        this.#result = structuredClone(validation.result);\n        this.#resultFingerprint = fingerprint;\n        this.#resultCallId = call.callId;\n        this.#resultTurnId = turnId;\n        this.#semanticResultTextBoundary = this.#completedTextParts.length;\n        this.#emit(\"run.result.proposed\", validation.result, {\n          turnId,\n          itemId: call.callId,\n        });\n      }\n      this.#emit(","sourceCodeStart":887,"sourceCodeEnd":923,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts#L887-L923","documentation":"The structured result's `completionClaim.contractRevision` must equal the revision in the driver's task envelope completion contract (`#taskEnvelope.completionContract.revision`). If the agent claims a result against a different contract revision, the driver rejects it so results cannot be accepted against a stale or future contract.","triggerScenarios":"Agent emits a terminal tool call whose `completionClaim.contractRevision` differs from the envelope revision — e.g. the agent echoed a revision from an old prompt, the envelope was re-issued with a bumped revision mid-run, or a resumed session replays an old result after the contract was revised.","commonSituations":"Task envelope regenerated (revision bumped) between retries while the agent still holds cached instructions with the old revision; a resumed OpenCode session answers with a result minted before the envelope update; instruction template pinned to a fixed revision number.","solutions":["Re-send the current task envelope (full-context turn) so the agent holds the latest completion contract revision, then let it re-emit the terminal call.","Verify the failing call's `completionClaim.contractRevision` (visible in the `item.started` event arguments) against the envelope's revision and correct the agent prompt.","If a mid-run envelope update bumped the revision, abort and restart the turn so the agent works against one contract revision only.","Ensure the driver instance constructing the envelope is the same one the agent session was seeded from — mismatched instances carry different revisions."],"exampleFix":"// before (agent arguments)\ncompletionClaim: { contractRevision: 1, ... } // envelope revision is 2 -> mismatch\n\n// after\n// re-issue prompt with current envelope, agent then emits:\ncompletionClaim: { contractRevision: 2, ... }","handlingStrategy":"validation","validationCode":"const snap = await session.snapshot();\nif (claim.contractRevision !== envelope.completionContract.revision) throw new RevisionMismatchError();","typeGuard":"function revisionMatches(claim, envelope) { return claim.contractRevision === envelope.completionContract.revision; }","tryCatchPattern":"try {\n  await session.dispatchTool({ tool, callId, arguments });\n} catch (e) {\n  if (e.message.includes('contract revision does not match')) {\n    // restart the turn with the current task envelope\n  } else throw e;\n}","preventionTips":["Always send the current task envelope (full-context) after any revision bump.","Never hardcode revision numbers in agent instructions.","Abort and restart turns when the envelope changes mid-run.","Verify driver and agent session share the same envelope instance."],"tags":["contract-revision","semantic-result","opencode","task-envelope"],"backgroundTag":"schema-validation-failed","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}