Skip to content

Setlist 1.0.5 (edition v1.6)

Choose a tag to compare

@AlexCiortan AlexCiortan released this 25 Jul 15:47
· 9 commits to main since this release

A release about how releases are checked, and one substantial fix that the new
checking found at a scale no human review had.

A merge into your trunk can no longer hide behind the shape of the command
line.
The close gate read a merge's arguments from the text after the LAST
occurrence of the word merge. Two consequences, both live in 1.0.4: a
compound like git merge --no-ff spec/0001-x && git merge main discarded the
first merge's arguments entirely and passed with no close condition checked,
and any commit message containing the word, -m "improve merge of main",
displaced the real arguments and did the same. The second matters most,
because it fires on ordinary usage with no intent behind it: a natural merge
message silently skipped the gate.

The gate now splits a command line on its connectors, judges each segment on
its own while tracking which branch that segment runs on, and reads a merge's
arguments from the first merge token in its own segment. The same treatment
went to the commit gate.

A corrupted config no longer switches the gates off in silence. The hooks
read .claude/sdd.json for your trunk name and role paths. If that file was
unparseable, a truncated write or a bad merge being the ordinary ways it
happens, every value read as empty, and the gates exited without checking
anything: feature code went onto the trunk and merges went through with no
message at all. Having jq installed is not the same as the file being
readable, and the hooks were only checking the former. They now refuse, naming
the file and the command that shows the parse error.

The trunk audit can run at push time, if you want it to. A sample git
pre-push hook ships alongside the audit. Copying it into .git/hooks/ runs
the audit at the last moment your history is still private, which is also the
only place a local hook can notice work that arrived through your forge's
merge button. It refuses the push rather than passing if it cannot find its
own tool, because a check that could not run has not passed. Nothing installs
it for you.

Generated tests, not just written ones. Every previous fix here was pinned
by examples somebody thought of, and every bypass lived in what nobody thought
of. The suite now generates its adversarial inputs: 504 spellings of a merge
naming an unclosed spec, all of which must deny, and a matching inverse corpus
so a gate that denies ordinary work also fails. On its first run it found 144
bypasses where two had been reported, and an over-denial nobody had noticed
(echo git merge spec/... was denied though nothing merges).

A trunk audit, advisory. scripts/trunk-audit.sh reads your trunk's
history and reports any commit that put code there outside a closed spec. It
answers a question no command parser can answer correctly: a shell command can
compute its own arguments, while history simply is what it is. So it catches
by construction what a parser misses, including chained merges, a branch
renamed to hide it, cherry-picks, and your forge's merge button. Nothing calls
it automatically in this release and a finding blocks nothing; run it when you
want to know. It was validated against 148 commits of real project history
before shipping, which is how two false-positive classes were found and fixed
rather than shipped.

Every documented limitation is now pinned or declared. The Known
limitations list and the test suite are kept in step mechanically, in both
directions: a limitation with no test, or a test for a limitation nobody
documented, blocks the release. Limitations that cannot be exercised by a test
suite carry the manual procedure that checks them instead of quietly
disappearing.

If you already have a project running Setlist

Run /setlist:upgrade once after updating the plugin. Nothing in this release
changes the settings wiring, so the refresh is hook files only.

/plugin marketplace update setlist

If a Claude Code session was open when you ran that update, restart it before
upgrading.