Fix #40: porch's phase-handoff box tells the builder to start - #42
Merged
Conversation
A builder ended its turn at a plan-phase boundary with nothing blocking it and idled for two hours. Its own account of why names two things porch and the role doc actually told it: it read "DO NOT start phase_2 until you run porch again" as a general stop-and-wait, and it treated the handoff as a reporting checkpoint. The box porch marks CRITICAL held one prohibition, one conditional (run porch done WHEN complete), and one imperative the builder cannot perform: /compact, a slash command a human types into a composer. Nothing in the codebase consumed it — grep returned the two console.log lines and nothing else. So the only unconditional instruction in the box was unsatisfiable, and no line said "begin the phase you were just handed." The box is now rendered by a helper that wraps, which is what makes a full sentence affordable; the old hand-padded lines capped every rule at what fit and that cap is why the box held only prohibitions. Rule 1 is affirmative and names the phase to start now. Rule 4 names the three things that do justify stopping, so "should I stop here?" has a written answer instead of being settled by whichever reading looks safest. The role doc gets the matching section. It said "porch drives the loop" once inside a table cell, then attached ceremony to the boundary twice — write the thread at phase boundaries, message the architect at these four moments — without ever saying that reporting is not ending your turn. This makes the misread harder. It does not detect a builder that stops anyway; that needs the watchdog in #41. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Hard-break a word wider than the box before wrapping. Phase ids come from plan headings via extractPlanPhases, so a long slug arrives as one unbreakable word and ran straight through the border. The existing border test only exercised short ids; a new test uses a 128-character id. Scope the rule-order assertion to boxText() like its siblings. Asserting on the whole status output happened to work only because "DO NOT start" appears nowhere else in it, which is a fact about today's output rather than about the ordering this test exists to pin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Owner
Author
|
Merging on one review lane, stated plainly rather than dressed up as a clean cmap.
So this merges on one substantive review. Recording that as the actual basis, because "cmap passed" would be false. 511 porch tests pass, including the pre-existing spec-1470 regression tests that assert the box still renders. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #40.
The failure
A builder ended its turn at a plan-phase boundary with nothing blocking it and idled for two hours. Asked why:
Both readings were available in text we hand the builder.
Before
Rule 1 is a prohibition. Rule 3 is conditional on being done. Rule 2 is the only unconditional imperative in the box, and a builder cannot perform it —
/compactis a slash command a human types into a composer, andgrep -rn compact packages/codev/srcreturns these twoconsole.loglines and nothing that consumes them.So the box porch marks CRITICAL told the builder what not to do, gave it one action it could not take, and never said to begin the phase it had just been handed.
After
Rule 4 exists because "should I stop here?" needs a written answer. Without one it gets settled by whichever reading looks safest, and stopping always looks safest.
Why a renderer instead of editing the strings
The old box hand-padded every line with
.padEnd(63), so each rule was capped at what fit on one line. That cap is why the box held only prohibitions — a prohibition fits, an explanation does not.criticalRulesBox()wraps at the box width and aligns continuations under the rule text, which is what makes a full sentence affordable.Role doc
roles/builder.mdsaid "porch drives the loop — run it, do the work it hands you, run it again" once, inside a table cell. Against that, two later sections attach ceremony to the boundary: write the thread at phase boundaries, and a four-row table of message-the-architect triggers. Neither said reporting does not mean ending your turn.Adds a section stating that a handoff is begun in the same turn, that porch's DO-NOT-start line forbids skipping ahead and has never meant stop-and-wait, and the three conditions that justify ending a turn. Mirrored into
codev/roles/builder.md(verified byte-identical).Tests
issue-40-phase-handoff-rules.test.ts— 8 tests. They assert content, not formatting, since content is what failed. Two are worth calling out:510 porch tests pass, including the pre-existing
spec-1470regression tests that assert the box still renders.Scope
Wording. It makes the misread harder; it does not detect a builder that stops anyway. That is #41 (idle-builder watchdog), which crosses Tower's existing render-gate idle classification with porch's phase state.
🤖 Generated with Claude Code