{"record":{"id":"84b1f019c2520962","repo":"Hmbown/CodeWhale","slug":"review-receipt-and-pr-coverage-manifest-fingerprints-differ","errorCode":null,"errorMessage":"Review receipt and PR coverage manifest fingerprints differ","messagePattern":"Review receipt and PR coverage manifest fingerprints differ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/review.rs","lineNumber":1082,"sourceCode":"                    line: issue.line,\n                })\n                .collect(),\n        },\n        unresolved_risk: ReviewReceiptRisk {\n            unresolved,\n            level: risk_level,\n            summary: risk_summary,\n        },\n        review_content_sha256: sha256_hex(review_content.as_bytes()),\n        coverage: None,\n    }\n}\n\npub(crate) fn attach_pr_review_coverage(\n    receipt: &mut ReviewReceipt,\n    coverage: ReviewReceiptCoverage,\n) -> anyhow::Result<()> {\n    anyhow::ensure!(\n        receipt.diff_fingerprint == coverage.manifest.diff_fingerprint,\n        \"Review receipt and PR coverage manifest fingerprints differ\"\n    );\n    anyhow::ensure!(\n        coverage.completed_passes.len() == coverage.manifest.passes.len()\n            && coverage\n                .completed_passes\n                .iter()\n                .enumerate()\n                .all(|(index, pass)| pass.number == index + 1),\n        \"Review receipt does not cover every planned PR pass\"\n    );\n    receipt.schema_version = PR_COVERAGE_RECEIPT_SCHEMA_VERSION;\n    receipt.coverage = Some(coverage);\n    Ok(())\n}\n\npub fn write_review_receipt(","sourceCodeStart":1064,"sourceCodeEnd":1100,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/review.rs#L1064-L1100","documentation":"`attach_pr_review_coverage` binds a `ReviewReceipt` to a `ReviewReceiptCoverage` only when both refer to the same diff — checked via the diff fingerprint. A mismatch means the receipt was produced against a different version of the PR diff than the coverage manifest, so attaching coverage would misrepresent what was reviewed.","triggerScenarios":"Calling `attach_pr_review_coverage(&mut receipt, coverage)` where `receipt.diff_fingerprint != coverage.manifest.diff_fingerprint`, e.g. the receipt came from an earlier review run or a re-fetched diff after the PR changed.","commonSituations":"Re-attaching a stored receipt after the PR moved; mixing receipts and coverage from two review runs; rebuilding the manifest from a fresh diff while reusing an old receipt.","solutions":["Regenerate both the receipt and the coverage manifest from the same review run and diff","Compare `receipt.diff_fingerprint` and `coverage.manifest.diff_fingerprint` before attaching","Re-run the review if the PR changed since the receipt was produced"],"exampleFix":"// before\nattach_pr_review_coverage(&mut old_receipt, new_coverage)?;\n// after\nif old_receipt.diff_fingerprint != new_coverage.manifest.diff_fingerprint {\n    let (_, _, coverage) = rerun_review(&complete_diff)?; // fresh receipt + coverage\n}\nattach_pr_review_coverage(&mut old_receipt, new_coverage)?;","handlingStrategy":"validation","validationCode":"if receipt.diff_fingerprint != coverage.manifest.diff_fingerprint { return Err(anyhow!(\"receipt/coverage fingerprint mismatch\")); }","typeGuard":null,"tryCatchPattern":"match attach_pr_review_coverage(&mut receipt, coverage) { Err(e) if e.to_string().contains(\"fingerprints differ\") => regenerate_receipt_and_coverage(), Err(e) => return Err(e), Ok(()) => {} }","preventionTips":["Always generate receipt and coverage in the same run and persist them together","Never reuse a stored receipt with a freshly rebuilt manifest","Include the diff fingerprint in persisted artifacts so mismatches are detectable"],"tags":["review","fingerprint","receipt","mismatch"],"backgroundTag":"checksum-mismatch","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}