Skip to content

Setlist 2.3.0 (edition v1.11, the attestation edition)

Latest

Choose a tag to compare

@AlexCiortan AlexCiortan released this 30 Aug 01:08

Edition v1.11 (the attestation edition). The headless build integrity chain: the one item on this project's Known-limitations list whose absence was a missing mechanism rather than a hole in one.

What it does

Declare an attestation block in .claude/sdd.json and /setlist:checkpoint writes and signs an approval when a spec goes ACTIVE, binding it to that spec's exact bytes. The git hooks then refuse a build commit, a push, or a close whose spec has drifted since that approval. Spec-hash and its session-start warning are layered underneath and unchanged: the two answer different questions, and a spec whose hash was quietly recomputed by hand passes the first and fails the second.

Nothing changes unless you turn it on. No block means off, and off is byte-for-byte the behaviour you have today, proven by a differential against the 2.2.0 hook bytes rather than asserted. An upgrade delivers the key set to false and migrates nothing.

What it is worth, which the mechanism prints rather than leaving you to work out. A signature proves a key was used, not that a person decided. If your signing key sits where the build can read it, a headless run can sign its own approval and the chain will verify, establishing that the run had the key, which is not the question. So Setlist makes you declare where your key lives and names that declaration in every verification it emits, including the ones that pass.

forge custody is designed and NOT BUILT. Verification would be a query your forge answers, and it arrives with the forge-side required check this list already names as a candidate rather than a promise. Declaring it today refuses and says so. signer custody is the model that works now.

The 2.2.0 commitment, answered by identifier

The 2.2.0 notes named five findings and said this release would carry them. Four shipped:

  • F3-2026 a broken or missing git can no longer make the commit gate report every staged line clean having read nothing.
  • F4-2026 a correctly wired hook is no longer certified NOT WIRED when its matcher is * or absent, so /setlist:upgrade on a working instance no longer exits INCOMPLETE forever.
  • F6-2026 the Architecture-diagram field is read as an answer rather than as a sentence containing one, and is decided by the first such field rather than the last.
  • F7-2026 the QA verdict block is decided by the first block, so an illustrative example after a real verdict no longer replaces it.

F5-2026 is deferred, and the measurement is published rather than the promise renewed. A compliant chore close spelled --ff or --squash is still accepted at commit and refused at push. Its scoped fix was measured during this release's own adversarial review to widen a more serious exemption in the same code, so taking it would have traded a disclosed gap for an undisclosed one. It is entangled with the exemption below and both are scheduled together, into the next cycle's design intake.

A limitation found by this release's own review, disclosed at real width

A single-parent trunk commit that closes a spec is content-exempt at the push-time audit. When a commit on the trunk has one parent and compliantly closes a spec, the audit accepts the whole commit without asking which role-path files it introduced, so such a commit can also carry feature code belonging to a spec that is still open. Reproduced with a negative control: the byte-identical commit without the row flip is refused.

What limits it, stated as precisely as the gap. The default close /setlist:checkpoint performs is a --no-ff merge, and merges take a different arm that does ask which files no parent supplied; a --no-ff close carrying injected code is refused. The exposed surface is single-parent closes specifically, meaning --squash and fast-forward. Like every hook it is a local check: a boundary that must hold against deliberate evasion belongs on your forge, in branch protection and required checks.

Three previous Known-limitations bullets are corrected in this release because the review showed them false in composition. The rebase, reset --hard and checkout -- <path> bullets each said "Measured: the push is refused with the same VIOLATION, remote unchanged". That holds for the bare form; composed with a compliant single-parent close in the same commit, the push succeeds. Each bullet now says so.

Why it is not fixed here. The obvious narrow fix was measured and refused: a squash has no parent carrying its legitimate content, so the merge arm's provenance question cannot separate an honest squash close from this one. Separating them needs a recorded fact this framework does not yet keep, which file belongs to which spec, and that is the subject of the next cycle's design intake.

Also in this release

A secret on an added line whose text begins ++ is no longer deleted from the scanners' own input at either layer. The advisory session gates carry a machine-readable code on every refusal, not only on some. The advisory commit gate now says that path exclusions are evaluated at the git-hook layer and that it does not read them, so you can tell from the message whether a commit will actually be blocked. The Known-limitations list gains the empty-remote trunk-audit boundary, which the framework document described and this list did not.

The rest of what the review found, with homes

  • A scaffolded value that is present and not a boolean still stands the session scope gate down silently instead of reporting itself. The one-line fix was written this cycle and cut: it needs a new refusal code, a new code is a new question, and a new question under this project's own release rules requires a full adversarial review that a repair round does not get. Scheduled for a cycle that owes one anyway. The layer affected is the advisory gate; the git hooks, which are what refuse, are unaffected.
  • Two defects in this project's private checking tools were found and are deferred under the rule that a defect in a checker never blocks a release. They do not affect anything you install.

A correction to an earlier draft of these notes

A draft of the changelog entry claimed four repairs as shipped that were not written. The claim was false when it was made. It was caught before release by this project's own adversarial review, which reads the changelog as ground truth and reported the code as contradicting it. The repairs above are the ones that then actually landed, and the one that did not is named as deferred rather than promised again. A release note is a claim about bytes, and this one was audited against the bytes before it shipped.

Attestation

One adversarial review read tree b7d57565, returned PASS-WITH-FINDINGS with ten surviving findings, and fix round 1 answered it. This release is attested by the mechanical evidence set under the project's A2 rule, verifying tree c1fdb7ea. That proves the known corpus still holds and that the fix diff survived a cold adversary; it proves nothing about classes nobody has enumerated, and the record says so out loud.