Repository navigation
porch: BUGFIX should have a pr gate (closes the v3.1.4 pr_ready_for_human timing gap) #887
Description
Background
v3.1.4 (PR #874) added a canonical pr_ready_for_human signal so Needs Attention could gate on a single boolean instead of protocol-specific derivations. The setter design baked in a special case for BUGFIX: every other protocol (SPIR / ASPIR / PIR / AIR) has a pr gate that fires the signal via index.ts:418 when the builder calls porch done after CMAP; BUGFIX has no pr gate, so the signal was wired to fire at the advanceProtocolPhase terminal-exit setter (index.ts:453) instead.
That set-point is too late: it only fires when porch done runs on the pr phase. BUGFIX builders only call porch done after merging, by which time the human has already acted and the "PR is ready for human" signal is meaningless. Verified empirically: BUGFIX projects sit at phase: pr, pr_ready_for_human: false indefinitely after their PR is opened and CMAP completes, and never surface in Needs Attention until after merge (when the PR is closed anyway and the row no longer matters).
The architect originally chose "leave BUGFIX gateless" without considering this interaction. Adding a pr gate to BUGFIX makes it semantically identical to AIR — and AIR's flow demonstrably gets the signal timing right.
Fix shape (Option G)
Add "gate": "pr" to BUGFIX's pr phase. The existing index.ts:418 gate-request setter then fires automatically when the builder calls porch done after CMAP. Architect approves the gate via porch approve <id> pr. Builder merges. Builder calls porch done again to advance to verified.
No new porch commands. No semantic shift in verified (still means "merged, work complete"). The BUGFIX-without-gate branches added in v3.1.4 become redundant and can be cleaned up.
Scope
Protocol JSON
codev/protocols/bugfix/protocol.json— add"gate": "pr"to the pr phasecodev-skeleton/protocols/bugfix/protocol.json— same
Porch code cleanup (BUGFIX-no-gate branches now redundant)
packages/codev/src/commands/porch/next.tsline ~617 — comment that references the "BUGFIX no gate" case is now stale; update or removepackages/codev/src/commands/porch/index.tslines 443-465 (advanceProtocolPhase): theadvancingFromPrPhasesnapshot + the terminal-exit setter was added specifically for the BUGFIX-no-gate case. With BUGFIX having a gate, this code path is no longer reachable for any current protocol. Recommend dropping the snapshot + the conditional setter (lines 448, 452-453, 463-464) and the JSDoc comment that calls out BUGFIX as the no-gate case. Keep theadvanceProtocolPhasefunction itself; just remove the BUGFIX-specific conditional.packages/codev/src/commands/porch/protocol.ts—isPrCreatingPhase()currently checksgate === 'pr' || hasPrConsultation. With BUGFIX getting the gate, every PR-creating phase hasgate === 'pr'and thehasPrConsultationbranch is dead. Drop the branch AND thehasPrConsultationfield onProtocolPhaseAND its computation innormalizePhase. Tighter type, fewer moving parts. The JSDoc onisPrCreatingPhaseneeds updating to reflect the simpler invariant.
Builder prompt
- BUGFIX builder prompt (template in
codev-skeleton/protocols/bugfix/builder-prompt.md, or wherever the BUGFIX prompt lives) — update the pr-phase guidance: "After CMAP completes, runporch done <id>to request the pr gate. Wait for the architect to callporch approve <id> pr. Then merge the PR. Then runporch done <id>again to advance to verified." - Match the prompt language to AIR's pr-phase prompt for consistency. The AIR prompt is the gold reference here.
Tests
packages/codev/src/commands/porch/__tests__/pr-ready-872.test.ts— the BUGFIX test case exercises the now-removed terminal-exit setter. Rewrite it to exercise the gate-request setter (line 418), matching how the AIR test case is written. The architect's iter-2 fix to that file (the RESEARCH false-classification regression test) stays in.- Search the repo for tests that assert BUGFIX's final
gates: {}and update — BUGFIX terminal state now hasgates: { pr: { status: 'approved', requested_at, approved_at } }. derivePrReadyinoverview.tscarries a BUGFIX special case (phase === 'verified' && protocol === 'bugfix') as a v3.1.4-compat fallback. Once the new code rolls out and existing in-flight BUGFIX projects cycle through, this fallback path becomes dead code — but leave it for now as a graceful-degradation path for projects mid-flight when the upgrade lands. Flag for removal in a future cleanup pass (v3.2+).
Docs
CLAUDE.mdandAGENTS.md— anywhere they describe BUGFIX as gateless or list BUGFIX's flow. Update to reflect the gate.docs/releases/v3.1.4-jacobean.md— note the BUGFIX-specific set-point was an interim design; v3.1.5 supersedes it with the gate. Consider adding a "Known issue / superseded by v3.1.5" callout. Optional but useful for someone reading the v3.1.4 notes after the fact.
Acceptance criteria
- BUGFIX protocol.json (both copies) carries
"gate": "pr"on the pr phase - BUGFIX builder reaches
phase: prwithgates: { pr: { status: 'pending', requested_at: <timestamp> } }andpr_ready_for_human: trueafter runningporch donepost-CMAP, mirroring AIR's behavior -
porch approve <id> prsetsgates.pr.status: 'approved'andpr_ready_for_human: false - Second
porch doneadvances toverified(terminal state); the PR is by then merged - BUGFIX PRs surface in Needs Attention from the moment of
porch done(gate-request) until the moment ofporch approve(architect action) - BUGFIX-no-gate branches removed from
advanceProtocolPhaseandisPrCreatingPhase;hasPrConsultationfield removed -
pr-ready-872.test.tsBUGFIX case rewritten to test gate-request path; passes - Builder prompt updated (BUGFIX builders know to call
porch doneafter CMAP) - Manual smoke: spawn a fresh BUGFIX builder, let it run through investigate → fix → pr → CMAP →
porch done. Verify status.yaml at each step; verify Needs Attention surfaces the PR at the right moment
Out of scope
- Removing the
derivePrReadyBUGFIX-fallback inoverview.ts— leave for graceful degradation of in-flight v3.1.4 projects. Track for v3.2+ removal. - Re-examining whether AIR's terminal-exit also has the timing wrong — out of scope; AIR's setter is at the gate-request point which is correct.
References
- v3.1.4 PR that introduced the BUGFIX special case: [Bugfix #872] Fix: emit canonical pr_ready_for_human signal across all protocols #874
- Set-points:
index.ts:418(gate-request, correct for AIR),index.ts:453(terminal-exit, the BUGFIX special case being removed) - AIR's pr phase config (the reference):
codev-skeleton/protocols/air/protocol.json
Activity
waleedkadous commentedon May 27, 2026
On it! Working on a fix now.
[Bugfix #887] BUGFIX: add pr gate (close v3.1.4 pr_ready timing gap)
[Bugfix #887] Update approve() comment to reflect BUGFIX pr-gate landing
[Bugfix #887] Update thread: PR opened, CMAP done, gate requested
Merge pull request #888 from cluesmith/builder/bugfix-887
[Spec 927][Phase: dashboard-surfacing] fix: affiliated PR wait time u…