Skip to content

Setlist 2.1.0 (edition v1.9)

Choose a tag to compare

@AlexCiortan AlexCiortan released this 25 Aug 23:49
· 3 commits to main since this release

Setlist 2.1.0 (edition v1.9, the reckoning edition)

Setlist turns Claude Code into a spec-driven engineering partner: you direct as architect
and reviewer, the agent writes the code, and a spec, not the keyboard, is the control
surface. 2.1.0 changes no command, no hook and no gate. It is a corrections release, and
the corrections are of the framework document's own claims about itself: five places where
the text said something the shipped bytes did not, or named a hole by the wrong name, or
pointed at a document no reader outside this project can open. It is called the reckoning
edition because that is what it does, and because a framework whose whole argument is that
claims should be checkable owes the same standard to its own prose before it asks for it
anywhere else.

What changed in the document

  • Part 8c now names the git-hook boundary explicitly. Upgrading a pre-v1.8 instance
    delivers the .githooks/ files and turns on two git settings, and the text says which
    ones instead of describing "a hook and a config key" in the abstract.
  • The "pathspec hole" gets its narrow meaning back. It means git commit <file> and
    nothing else. The nested-repository hole and the GIT_INDEX_FILE hole are now named as
    their own separate limitations, because the fix for one is not the fix for another.
  • Two citations of an unpublished internal design document are gone from the edition
    text.
    Those passages now name the mechanism directly, so every reference in the
    document resolves to something a reader can actually reach.
  • A stale README bullet is corrected. It told readers the shipped gate messages still
    promise a denial and to believe the bullet over the bytes. The bytes have been advisory
    for two editions; the bullet was the stale copy, and it taught exactly the wrong reflex.
  • The changelog's own 1.1.0 entry says what it was. An internal milestone, never
    tagged here, shipped as part of 2.0.0. An outside reader had to work that out.

New doctrine, in Part 6

Part 6's doctrine for anything that checks anything gains two rules, and both came from
defects found in this project's own checking tools rather than from theory.

  • A comparison asserts the size of what it compares, and refuses on zero. An empty
    list matches anything, so a coverage check whose extraction quietly fails compares
    nothing and reports every row covered. Assert the size of each side before comparing,
    treat zero as a refusal rather than a pass, and mutate the thing under test once to watch
    the check go red. A comparison that has never been seen to fail has not been shown to
    compare anything.
  • Label every green with what it is evidence OF. This is the more dangerous cousin,
    because it survives the negative test: the check is real, it does go red under mutation,
    and its result is filed under a claim it does not test. No mechanical guard catches it,
    since the defect sits one level above the check. The habit that does: say what each green
    is evidence of, in the report, and when every row passes, construct the input that should
    fail. If you cannot construct one, the name of the check is what is wrong.

Upgrading from 2.0.x: run /setlist:upgrade in your instance. Because no enforcement
file changes in this release, the upgrade moves the framework document and leaves your
hooks exactly as they are; the wiring check still verifies the enforcement is live before
it reports success. Full per-version deltas are in CHANGELOG.md; the framework document
ships as setlist.md (edition v1.9).

Known open issues in this release

This release was reviewed by an adversarial pass against these exact bytes, and the
result is published rather than summarised.
The review returned PASS WITH FINDINGS:
no blockers, six major findings, five minor. Twenty-three distinct candidates were
raised, twelve were refuted, and the eleven below survived a refuter whose instruction was
to disprove them. Every one is recorded, with a disposition and a trigger, and none of them
puts unreviewed code on a shared trunk. This is the first Setlist release whose evidence
gate was satisfied by rule rather than by a decision to proceed past it, which is worth
saying plainly given that the previous one was not.

1. One of the findings is a false denial, and it is not fixed in this release. In one
narrow shape, pre-commit refuses an honest commit: a spec that QUOTES the closing-report
template inside a fenced code block, changes no lifecycle state, and does not stage
specs/STATUS.md, is refused with [SLH-STATUS-MISSING]. The detector reads the raw
staged diff and does not strip fences, so quoted text is read as if it were live. The same
regex is why an indented ## Closing report heading is not matched at all, while three
other readers in this same release do accept it.

It is disclosed rather than fixed for two reasons, both of which are decisions rather than
oversights. It is pre-existing: the detector has not changed since before 2.0.0, so
anyone running 2.0.0 has this defect today, and holding this release back would leave them
with both the defect and the documentation errors this edition exists to correct. And
fixing it inside this release would change what a guarantee check ASKS, which under this
project's own rules requires a fresh adversarial review of the changed bytes before they
ship. That is the right thing to spend on the fix, and the wrong thing to spend on a
release whose only other change is documentation. It is scheduled for the next cycle's
guarantee-layer batch.
If you hit it, the workaround is to stage specs/STATUS.md in the
same commit, which is what the message asks for.

2. The remaining findings are major and minor, not blocking, and several are in this
project's own checking tools rather than in the gates you install.
Two are advisory-layer
gaps where an unusable git or an unusual command spelling makes a session-level check
allow rather than refuse. One is a per-merge-hook route where an illustrative inventory row
written as a blockquote or a list item satisfies a closed-spec check. Two are in the
upgrade certification, which can report a correctly protected instance as unprotected or an
under-protected one as clean. The rest are reporting and documentation defects. In every
case the push-time trunk audit is unaffected: it reads history rather than commands, and it
is the layer the guarantee rests on.

3. A compliant fast-forward or --squash close is still permanently unpushable.
--no-ff is required, which is what /setlist:checkpoint does for you. The commit-time
gate and the push-time audit read a fast-forward differently, and rather than add a defence
that would refuse ordinary work, it stays documented.

4. A stale remote-tracking ref can deny an ordinary merge. (Corrected 2026-08-26: item 4 as published described PRE-ADVISORY behaviour. Measured on the shipped 2.1.0 bytes, the close gate emits permissionDecision: "allow" and carries the verdict only in its machine-readable setlistAdvisory field, so it does not deny the merge. The cost is a misleading advisory, not a blocked merge. The rest of this item, including the remedy, stands. This note is added at the record rather than the item being rewritten, which is this project's convention for a published correction.) If you rename a spec branch
while a remote-tracking ref for the old name still exists, the close gate denies the merge
with CG-SPEC-MISSING. It is a false denial rather than a way past the gate. The remedy is
one command:

git update-ref -d refs/remotes/origin/spec/0004-thing

5. The gates are verified on the platforms that are actually tested. That is Linux and
macOS on every push, plus a local bash 3.2 and BWK awk run before each release. It is not a
claim about every shell, every awk or every BSD. A platform difference nobody had tested for
once turned two gates off for an entire release, and the honest statement is that the set of
tested platforms is a list, not a proof.

6. Three limitations the test suite pins are not yet in the Known limitations list.
git rebase, git reset --hard and a pathspec git checkout are all pinned as known holes
in the suite and named in none of the published bullets. All three are refused at push by
the guarantee layer, so the remote is not reached; what is missing is the documentation, and
it lands in the next documentation pass rather than being written into a release whose bytes
are already frozen.

The standing framing has not changed and is worth repeating: these hooks are a backstop
against ordinary mistakes, not a sandbox. Anything that can run a shell can reach the trunk,
and the gates have never claimed otherwise. A merge performed in a forge's web UI is not
reached by them at all. The trunk audit (scripts/trunk-audit.sh) reads history rather than
commands and is the designed catch for that whole family.