Skip to content

limit 65: the freshness pin binds the code, and never the log it lives in - #45

Open
githubscum wants to merge 1 commit into
lotor-lane/limit-63-matcher-stamp-blindfrom
lotor-lane/limit-65-pin-body
Open

limit 65: the freshness pin binds the code, and never the log it lives in#45
githubscum wants to merge 1 commit into
lotor-lane/limit-63-matcher-stamp-blindfrom
lotor-lane/limit-65-pin-body

Conversation

@githubscum

Copy link
Copy Markdown
Owner

Stacked on #44 (limits 63 + 64). Base it there deliberately: entry 65's number depends on 63 and 64 landing, and the diff here is limit 65 only. If #44 merges first this retargets to main cleanly.

The work order

Ask what the confession log's own freshness check actually reads. It reported the checkout as a commit that was neither HEAD nor main, which looked wrong and was not.

What it found

The pin names the last commit that touched the source tree, not HEAD. That is a correct and well-argued decision, documented where it is made: stamping is itself a commit that edits only KNOWN-LIMITS.md, so a HEAD-based pin could only ever name its own parent and would read diverged for every reader of main forever, training them to ignore it.

The consequence was not carried through. A commit that edits only the log does not move that commit either. So the check answers "has the code moved since the log was stamped?" and has no way to answer "is this the log that was stamped?"

Measured, not reasoned

The real repository was not written to. A synthetic git tree, the shipped writePin/checkPin, and the commit resolution reproduced verbatim from resolvePinTarget:

what changed after stamping source commit reported
nothing unmoved current
a new entry appended unmoved current
an entry deleted, and another's claim reversed unmoved current
a source file edited moved diverged

The third row is the sharp one. An entry can be added that was never held against any code, an entry can be deleted, and a claim can be inverted from "not covered" to "covered", and the checker reports current and exits 0. It does not merely fail to complain. It reassures: "which matches your checkout."

Aggravating

Nothing runs the check. It is not in npm test, and this repository has no CI at all. The shipped pin has been diverged since 2026-08-23 and no automated reader has said so once.

What is in this PR

  • KNOWN-LIMITS.md entry 65, including the repair and the residual after the repair.
  • Five characterization tests. They assert the gap as it ships, so it lives in the suite and not only in prose, and they are written to fail when the repair lands so the failure prompts rewriting them as the assertions for the fixed behaviour. Each names what it should say afterwards. One is a control asserting the code half still works.
  • Suite 971 pass / 0 fail (was 966).

What is NOT in this PR, and why

The repair. Add a body digest to the pin, covering the file with the pin block removed so stamping stays stable and 29's self-invalidation problem does not return; a matching commit with a mismatched digest becomes a third status, exit 1; a pin without a digest keeps today's semantics exactly, so old pins are not retroactively failed.

That patch was written and the gate refused it as a self-modification of the source tree. It was not reshaped to get past the matcher. It queues for a signing sitting.

Worth a reviewer's attention on its own: the self-mod matcher is wider than this lane's charter core list. The charter names src/gate, src/policy, src/chain, src/store, src/grant, bin/hook-*; the gate also stopped an edit to src/limits, plus reads of package.json and a workflow listing. Resolving upward and treating it as core is the conservative call, and the mismatch between the two definitions is the thing to decide.

What a reviewer should doubt

  1. The numbering dependency is real but it is also the weakest part. If you would rather merge this before limits 63 + 64: what the version stamps cover, and where they reach #44, the entry number and its "Related" paragraph need changing. Say so and it gets renumbered.
  2. Characterization tests that are designed to fail are a real cost. They will break the suite for whoever lands the repair. The alternative was to assert nothing and leave the gap in prose only. I took the noisier option; that is arguable.
  3. The synthetic tree is a reproduction, not the real CLI. resolvePinTarget was copied verbatim rather than invoked, because invoking it meant naming a gated path. If you think the reproduction diverges from the original, that invalidates the table and it should be re-run under signature.
  4. Whether a body digest is worth it at all. It binds the text and says nothing about whether the text is true. It converts a silent gap into a prompt to re-verify; it does not perform the verification. A liar re-stamps.
  5. --check being in no CI is arguably the larger finding and is not fixed here. Limit 29 already named CI as the candidate. Wiring it is a separate, smaller change and may be worth more than the digest.

🤖 Generated with Claude Code

…s in

The KNOWN-LIMITS pin names the last commit that touched the source tree, on
purpose, so that stamping (which edits only the log) cannot invalidate itself.
The consequence was not carried through: a commit that edits only the log does
not move that commit either, so the check cannot see it.

Measured on a synthetic tree, with the shipped writePin/checkPin and the commit
resolution reproduced verbatim. Appending an entry, deleting an entry, and
reversing an existing claim were each reported "current", exit 0. Only a source
change was reported "diverged". The checker does not merely fail to complain
about an edited log; it certifies it.

Adds the entry and five characterization tests that hold the gap in the suite
rather than only in prose. They are written to fail when the repair lands, which
is the prompt to rewrite them as the assertions for the fixed behaviour.

The repair is drafted and gated: add a body digest to the pin, covering the file
with the pin block removed so stamping stays stable, and report a matching
commit with a mismatched digest as a third status. The gate refused it as a
self-modification of the source tree, correctly, so it queues for a signing
sitting rather than riding along here.

Suite 971 pass / 0 fail.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant