Tagout

v2.6.0: a day the fleet spent fixing the fleet

Released 2026-09-13, a day after 2.5.0. Five features and fifteen fixes, almost all of them found by running the kit against its own backlog rather than by reading it.

What we were trying to fix

The queue had reached twenty-eight open issues, and most were defects the kit had discovered about itself on earlier runs: write gate blind spots, a base verdict that could not tell an awaiting-approval run from a failed one, a worker whose BLOCKED verdict was dropped instead of recorded. The plan was to drain that queue with a fleet of six workers, each driving one issue from its plan to a merged pull request.

What we decided

To start the tracker contract, so the lifecycle skills stop assuming GitHub: the profile now names GitLab and Azure DevOps trackers (#504), and scripts/tracker.sh routes each verb to the backend the profile names, answering capable at Step 1 (#505). To make a worker’s BLOCKED verdict durable as a hold the survey reads, rather than a sentence in a report that dies with the session (#511). To send lifecycle hand-offs to a fresh session and shrink inline runs to a single task (#523), which is a cost decision as much as a correctness one. And to close the GitHub Enterprise host-resolution gaps left over from #514 (#530).

The fifteen fixes are mostly the kit’s own gates catching the kit. The write gate learned to see command substitution inside double-quoted arguments (#559) and launcher option forms (#562), to deny a named-path checkout that would discard an uncommitted edit (#560), and to let a supervisor end a turn while it is actively cycling (#548). merge-pr learned that a run awaiting approval is not a failed check (#495), which is the fix that makes the release pull request landable at all.

What got cut

The second and third tracker backends. create-issue files through the contract now (#506) and its decomposition is being wired through it, but the GitLab and Azure DevOps backends (#508, #509) stayed open, and so did the tracking parent (#503). A contract with one implementation is a contract on probation: nothing yet proves the abstraction survives a backend that is not gh.

What bit us

The journal gate, for the third release running, and this time it cost a whole session. Tagging 2.5.0 moved the one-release exemption forward, 2.4.0 had no article, and main went red on tests/skills/test.sh for every open pull request at once. A red kit check on a two-line documentation change reads as that change’s fault, so the diagnosis came long before the one-file fix. This article, like 2.5.0’s, was written while the next release pull request was still open.

Two defects in the review seam cost more than they should have. Every review was handed main...HEAD, which resolves against a local main that nothing in the kit advances, so reviewers were handed diffs of already-merged work, growing to a hundred and fifteen files as the day went on; each one recovered only because it noticed unaided, and a reviewer that does not notice reports a clean bill on code nobody changed. Separately, because every agent commits under one canonical identity, a worker that had lost track of its own writes reported them as another process’s, three reviewers escalated their own sibling as a rogue writer, and one filed an issue about it. The reflog answers this in one command, since its per-worktree HEAD entry names the tree that made the commit, and nothing in the kit says so.