Nothing enumerates tools/*.swift, so every list of "the spool scripts" is hand-maintained — and it has now drifted three times in one day.
Two files already say this about themselves. Sources/HelmWire/Spool/SpoolRequest.swift:32-39:
A count that has to be incremented in three places is a count that will be wrong again on the seventh script, and unlike the wire bytes below nothing enumerates tools/*.swift in the test suite, so no gate catches the drift. Naming the canonical list once is the cheap half of that; a test that reads the directory is the durable half and is tracked separately.
It was not tracked separately. This is that ticket.
The three instances, all 2026-08-10
| where |
what it said |
found by |
Package.swift:44-45 |
four scripts, while there were five |
#316's seam review |
SpoolRequest.swift + SpoolWireConformanceTests.swift headers |
five, in a file spending six methods on the sixth |
#325's seam review |
SpoolWireConformanceTests.swift:1162 — Self.spoolScripts |
six, correct today |
#332's seam review |
The first two were prose and are fixed — both now point at AGENTS.md's list instead of restating a count. The third is different in kind and is why this ticket exists.
Why the third one matters more than the first two
Self.spoolScripts is not documentation. It is the array that drives the two tests proving #260's fix:
testEverySpoolScriptGatesItsIdWithHelmWiresOwnPattern
testEverySpoolScriptRefusesATraversalIdBeforeWritingAnything
So it is the enumeration of "every spool script" for the one property #260 was filed to guarantee — that an unvalidated id cannot write outside the spool root.
The failure mode is silent and it lands on the guarantee. A seventh script is added. Nothing forces its author to add a line to Self.spoolScripts. That script ships with its own hand-copied idPattern guard, per the six-script convention, and zero subprocess verification that the guard is present, correctly spelled, or wired in before any write. The suite stays green. That is exactly the "either alone is satisfiable by a script that does nothing" gap the test's own docstring warns about, one script wide.
And this is not hypothetical — Package.swift undercounting is the same repo's record of this list drifting once already.
What to build
The durable half both headers name: a test that enumerates tools/*.swift on disk and asserts its membership against Self.spoolScripts — or better, generates the script-name column from that enumeration so only the invocation arguments stay hand-written.
That turns a silently-skippable step into a red test.
One thing to decide rather than assume: not every file in tools/ is a spool script. focus.swift, winshot.swift, ticklog.swift and helm-spawn.swift deliberately are not — AGENTS.md says so and gives the reason (they touch no spool wire format). So the enumeration needs a rule for what counts, and the honest options are a naming convention, a marker inside the file, or an explicit exclusion list that is itself asserted to be complete. An exclusion list is another hand-maintained list, so prefer one of the first two if either works.
Acceptance
- Adding a seventh spool script without registering it fails a test rather than passing quietly.
- The rule for "what is a spool script" is stated once and checkable, not a second list to keep in step.
AGENTS.md's list stays the canonical prose one, and the test agrees with it or says why it cannot.
- The red run is the point: add a fake seventh script, watch the suite fail, remove it.
Nothing enumerates
tools/*.swift, so every list of "the spool scripts" is hand-maintained — and it has now drifted three times in one day.Two files already say this about themselves.
Sources/HelmWire/Spool/SpoolRequest.swift:32-39:It was not tracked separately. This is that ticket.
The three instances, all 2026-08-10
Package.swift:44-45SpoolRequest.swift+SpoolWireConformanceTests.swiftheadersSpoolWireConformanceTests.swift:1162—Self.spoolScriptsThe first two were prose and are fixed — both now point at
AGENTS.md's list instead of restating a count. The third is different in kind and is why this ticket exists.Why the third one matters more than the first two
Self.spoolScriptsis not documentation. It is the array that drives the two tests proving #260's fix:testEverySpoolScriptGatesItsIdWithHelmWiresOwnPatterntestEverySpoolScriptRefusesATraversalIdBeforeWritingAnythingSo it is the enumeration of "every spool script" for the one property #260 was filed to guarantee — that an unvalidated id cannot write outside the spool root.
The failure mode is silent and it lands on the guarantee. A seventh script is added. Nothing forces its author to add a line to
Self.spoolScripts. That script ships with its own hand-copiedidPatternguard, per the six-script convention, and zero subprocess verification that the guard is present, correctly spelled, or wired in before any write. The suite stays green. That is exactly the "either alone is satisfiable by a script that does nothing" gap the test's own docstring warns about, one script wide.And this is not hypothetical —
Package.swiftundercounting is the same repo's record of this list drifting once already.What to build
The durable half both headers name: a test that enumerates
tools/*.swifton disk and asserts its membership againstSelf.spoolScripts— or better, generates the script-name column from that enumeration so only the invocation arguments stay hand-written.That turns a silently-skippable step into a red test.
One thing to decide rather than assume: not every file in
tools/is a spool script.focus.swift,winshot.swift,ticklog.swiftandhelm-spawn.swiftdeliberately are not —AGENTS.mdsays so and gives the reason (they touch no spool wire format). So the enumeration needs a rule for what counts, and the honest options are a naming convention, a marker inside the file, or an explicit exclusion list that is itself asserted to be complete. An exclusion list is another hand-maintained list, so prefer one of the first two if either works.Acceptance
AGENTS.md's list stays the canonical prose one, and the test agrees with it or says why it cannot.