fix: receipt freshness binds to tree content instead of commit reachability - #144
Merged
Conversation
Scope digests and the exported exclusion boundary make receipt freshness merge-strategy-agnostic and designation-legal equal to receipt-neutral.
Verify now records scope digests and refuses dirty tracked trees so a receipt cannot attest bytes that no commit holds.
Delete the commit-walk freshness path so every clone yields the same typed verdict under squash, rebase, or cohort peers.
Bare exit-status failures hid the cause; capture stderr and render folder/cause/remedy blocks from the typed freshness verdict.
Submodule ignore=all and porcelain arrow-path parsing could hide dirt or strip report-mask exemptions; HEAD advances mid-verify could record a clean receipt for an unattested commit. Make status ignore-submodules=untracked with NUL parsing, void on HEAD movement, and annotate ADR-023/024.
levifig
marked this pull request as ready for review
July 30, 2026 11:01
levifig
added a commit
that referenced
this pull request
Jul 30, 2026
The release artifact rebuild changed the native binary after #144's Go changes, staling the installed-smoke receipts that pin its SHA-256. Re-recorded claude-code 2.1.220, codex 0.146.0 (client upgraded from 0.145.0), and opencode 1.18.7 smokes against the new binary; updated the capability record and contract-test identity pins accordingly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change
docs/changes/20260728-receipt-tree-binding/ —
target_release: 2.0.0What & Why
Shapes the receipt freshness rebinding: validity moves from commit reachability to content digests. Today
receipts/verify.jsonrecords averified_commitand the gate walksverified_commit..HEAD— after a squash or rebase merge plus branch deletion that commit is unreachable on every machine but the author's, so the same repo content blocks with a clean reason locally and crashes with a bareexit status 128on CI. The council also proved two deeper defects: cohorts of N≥2 are unsatisfiable under the current rule (each member's receipt commit stales the others, in every ordering), and verify attests worktree results under a HEAD label. The fix: a masked root-tree digest over a declared exclusion set (receipts repo-wide ∪ report boards ∪ the exportedreleaseMetadataAllowlist), making designation-legal ⟺ receipt-neutral; schema v2 receipts; a pure freshness predicate with typed reasoned verdicts; reachability retired from the verdict entirely.Review focus
The gating-scope decision (masked root tree over folder scope — 3:2 council split, owner-settled; board committed in
reports/), the exact digest serialization (Decision 8 — quotePath/sort/mode/case pinned), the deliberate drop of touch-then-revert detection (Decision 4), and the dirty-worktree refusal at verify.Verification
All four V-entries green via
loaf change verifywith the schema-v2 receipt committed at HEAD — this change's own receipt is the first v2 receipt, and it survived a post-verify amend intact (verified_commit no longer exists; the content-bound verdict did not change).loaf change check: zero violations, derivesverified. Five review rounds are recorded as boards inreports/: initial review (six findings), Codex gpt-5.6-sol xhigh continued-thread (three findings, incl. the mid-verify mutation and re-verify sweep defects), and Codex fresh-thread (four findings, incl. the submodule-ignore and HEAD-move bypasses) — thirteen findings total, all dispositioned, fixed, and re-verified. The council board (five lenses, decision recorded) is atreports/20260728-222942-council-receipt-freshness.html.Migration / breaking changes
Schema v2 is a clean break: v1 receipts are refused with a named re-verify remedy (zero receipts exist anywhere today, so nothing is grandfathered). The
cannot inspect receipterror path is deleted, not just avoided.Deferred
CI-green-at-HEAD assertion, rc-cut gating, and the designation diff check — the release-promotion-model Change consumes this change's exported boundary for them (PR #143); per-change
evidence_paths(only if a real case appears); rc-sweep command dedup (only when a cohort is big enough to feel it).