Skip to content

v1.23.0 ·

Four gates that lied, and the one rule under them

Four lifecycle automations were reporting something that was not true. Two blocked work they should have allowed. Two passed over a problem in silence.

The review gate required a findings file for every required artifact of the phase it guards, while the review skill told reviewers not to write one for the task breakdown. Following the docs exactly produced a blocked phase and the file the docs forbade. Three instances hit it in six days, and each wrote a file containing only a pointer to where the review really was.

The concurrency gate asked "is another session live?" when it meant "does another session share my working directory?", and the line comparing directories was inverted. It excluded claims from this path and blocked claims from other paths. Its own first advice is to start in a separate worktree, so taking that advice guaranteed every later start in the main checkout hit the same block and got offered a worktree it did not need.

The action that files a roadmap item on completion looked in the primary checkout. An instance finishing on a worktree branch has its item on that branch, so it found nothing, said nothing, and the transition printed a clean tick. That happened twice in three days, and the first time's lesson was already in the guidance file: an action that can find nothing has to say so. The lesson was recorded and the code was not changed.

The blog manifest could name a post that was never committed, because validation checked entries against tags but not against the files they promise. It surfaced as a test dying on main, which read as somebody else's problem.

Three of the four sit on the worktree path, the framework's recommended answer to two sessions sharing a checkout. The recommended path was the under-supported one.

What changed

The concurrency gate now compares each claim's directory with this session's. A missing worktree path means the primary checkout, and so does a worktree that has since been removed. I almost removed the own-worktree exclusion too. Without a declared session id every command resolves a fresh one, so a session would block on its own earlier claim. It stays, with the reason written beside it.

The review skill moved, not the gate. Splitting findings by artifact had separated one instance's notes on an architecture diagram from its notes on the design, and two of those were real defects. Now it says one findings file per required artifact, read from the phase state.

Roadmap filing searches this working tree as well as the primary checkout and prints one line for every outcome. The move no longer derives its destination from the current directory, since a cross-checkout lookup would otherwise relocate the item into the wrong tree.

Manifest validation asks whether a post will exist once the run finishes, not whether it is on disk now, or it would reject the very post a release is about to write. And it only demands the post once the tag exists. An entry committed ahead of its release is prepared, not broken.

One rule, applied by inventory

I filed four items as one because they split into exactly two failure modes, and the second fits in a sentence: an automation that can succeed without doing the thing must say which case it hit. Four instances for about three days of fixes was the overhead this project warns about.

The rule is written where the handlers are defined, with an inventory of each built-in handler as applies or exempt. A test asserts the inventory covers the handler map. Writing it down found a fifth case: the branch-creation action exits quietly when a worktree already made the branch, while aidlc start printed a tick for it. It also found an exemption. The handler that marks an instance as owing a retrospective stays quiet when one already exists, which is work done, not nothing found. Applying the rule uniformly would have regressed an earlier fix.

What it does not fix

I did not take the suggested git worktree list cross-check, because the module has a no-subprocess constraint and an existence test answers the same question.