From 26fd50b20b28f03af331b7793660a5ecedd6b27c Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:30:28 +1000 Subject: [PATCH 1/9] chore(porch): bugfix-1431 init bugfix --- .../status.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml diff --git a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml new file mode 100644 index 000000000..2f95eaa93 --- /dev/null +++ b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml @@ -0,0 +1,14 @@ +id: bugfix-1431 +title: stream-deck-phaseartifactverb- +protocol: bugfix +phase: investigate +plan_phases: [] +current_plan_phase: null +gates: + pr: + status: pending +iteration: 1 +build_complete: false +history: [] +started_at: '2026-08-13T01:30:28.426Z' +updated_at: '2026-08-13T01:30:28.427Z' From 825b1c6b9daa9a03ae804bcb358c17ba932c2d5c Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:31:21 +1000 Subject: [PATCH 2/9] chore(porch): bugfix-1431 fix phase-transition --- .../bugfix-1431-stream-deck-phaseartifactverb-/status.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml index 2f95eaa93..120789518 100644 --- a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml +++ b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml @@ -1,7 +1,7 @@ id: bugfix-1431 title: stream-deck-phaseartifactverb- protocol: bugfix -phase: investigate +phase: fix plan_phases: [] current_plan_phase: null gates: @@ -11,4 +11,4 @@ iteration: 1 build_complete: false history: [] started_at: '2026-08-13T01:30:28.426Z' -updated_at: '2026-08-13T01:30:28.427Z' +updated_at: '2026-08-13T01:31:21.684Z' From 71de358778587071d8b84614886307b4d9d0162a Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:32:11 +1000 Subject: [PATCH 3/9] Fix #1431: map verify-approval gate to view-diff in phaseArtifactVerb Stream Deck's phaseArtifactVerb mapped the spec/plan/dev-approval/pr gates but not verify-approval, so a builder blocked there returned undefined and the Builder Action Automatic press fell back to a terminal instead of the review diff (the #1428 faces already render the gate as blocked, so the key looked gate-blocked but behaved otherwise). Add verify-approval to the gate branch returning view-diff (same as dev-approval/pr: the human is reviewing finished work); the press then resolves view-diff to open-diff-first via BuilderAction.resolveVerb (#1414). Also drop the now-stale face.ts comment noting the resolver gap. --- apps/streamdeck/src/__tests__/actions.test.ts | 1 + apps/streamdeck/src/actions.ts | 2 +- apps/streamdeck/src/face.ts | 3 +- codev/state/bugfix-1431_thread.md | 30 +++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 codev/state/bugfix-1431_thread.md diff --git a/apps/streamdeck/src/__tests__/actions.test.ts b/apps/streamdeck/src/__tests__/actions.test.ts index 329c7979a..3f3c0e46b 100644 --- a/apps/streamdeck/src/__tests__/actions.test.ts +++ b/apps/streamdeck/src/__tests__/actions.test.ts @@ -640,6 +640,7 @@ describe('phaseArtifactVerb (shared resolver — recognised verb or undefined)', expect(phaseArtifactVerb(b({ protocolPhase: 'verify' }))).toBe('view-diff'); expect(phaseArtifactVerb(b({ blockedGate: 'dev-approval' }))).toBe('view-diff'); expect(phaseArtifactVerb(b({ blockedGate: 'pr' }))).toBe('view-diff'); + expect(phaseArtifactVerb(b({ blockedGate: 'verify-approval' }))).toBe('view-diff'); // #1431: human reviewing finished work }); it('gate beats phase (the stronger signal)', () => { expect(phaseArtifactVerb(b({ blockedGate: 'plan-approval', protocolPhase: 'implement' }))).toBe('open-plan'); diff --git a/apps/streamdeck/src/actions.ts b/apps/streamdeck/src/actions.ts index 97ccbe036..6d59fc0ee 100644 --- a/apps/streamdeck/src/actions.ts +++ b/apps/streamdeck/src/actions.ts @@ -328,7 +328,7 @@ export function phaseArtifactVerb(b: OverviewBuilder): string | undefined { const gate = b.blockedGate ?? ''; if (gate === 'spec-approval') return 'open-spec'; if (gate === 'plan-approval') return 'open-plan'; - if (gate === 'dev-approval' || gate === 'pr') return 'view-diff'; + if (gate === 'dev-approval' || gate === 'pr' || gate === 'verify-approval') return 'view-diff'; const phase = b.protocolPhase ?? ''; if (phase === 'specify') return 'open-spec'; if (phase === 'plan') return 'open-plan'; diff --git a/apps/streamdeck/src/face.ts b/apps/streamdeck/src/face.ts index 1a2776717..50bcd1eb1 100644 --- a/apps/streamdeck/src/face.ts +++ b/apps/streamdeck/src/face.ts @@ -49,8 +49,7 @@ export type GlyphKey = 'bolt' | 'book' | 'checklist' | 'code' | 'pull-request' | /** * Gate id → glyph. The streamdeck twin of `gateIconFor` in `apps/vscode/src/views/builder-row.ts` * — keep in sync. A blocked builder whose gate isn't mapped falls back to `bell` (see - * `faceForBuilder`), matching the sidebar. `verify-approval` renders here even though the press - * resolver doesn't handle it yet (that gap is BUGFIX #1431). + * `faceForBuilder`), matching the sidebar. */ const GATE_ICONS: Record = { 'spec-approval': 'book', diff --git a/codev/state/bugfix-1431_thread.md b/codev/state/bugfix-1431_thread.md new file mode 100644 index 000000000..7691c8089 --- /dev/null +++ b/codev/state/bugfix-1431_thread.md @@ -0,0 +1,30 @@ +# Builder thread — bugfix-1431 + +## Issue #1431 — phaseArtifactVerb missing verify-approval gate mapping + +Stream Deck's `phaseArtifactVerb` (apps/streamdeck/src/actions.ts:327) maps the +`spec-approval`, `plan-approval`, `dev-approval`, and `pr` gates but not +`verify-approval`. A builder blocked at `verify-approval` therefore returns +`undefined`, and the Builder Action Automatic press falls back to `open-terminal` +instead of opening the review diff. Meanwhile the #1428 faces already render this +gate (yellow + `verified` glyph + `Verify` label) — so the key looks gate-blocked +but the press opens a terminal: a face/behaviour contradiction. + +## Root cause (investigate phase — no code) + +Single missing branch in the gate section of `phaseArtifactVerb`. The VS Code +sidebar's `gateIconFor` (apps/vscode/src/views/builder-row.ts) already knows +`verify-approval` → `verified`; the Stream Deck resolver never caught up. + +## Fix (architect-scoped: strictly one line + one test + one comment cleanup) + +1. actions.ts `phaseArtifactVerb` gate branch: add `verify-approval` returning + `'view-diff'` (same as dev-approval/pr — human reviewing finished work). The + Automatic press then resolves view-diff → open-diff-first via + BuilderAction.resolveVerb (#1414), which is correct and intended. +2. actions.test.ts: assertion beside the existing dev-approval/pr gate cases. +3. face.ts ~line 52: delete the doc-comment clause saying the resolver "doesn't + handle it yet (that gap is BUGFIX #1431)" — this lane closes that gap. + +Do NOT touch anything else in face.ts/actions.ts (#1410 just landed a large change; +keep this diff trivially reviewable). From ed0256b9273c7148e0396c8e216ae98101413f8d Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:33:37 +1000 Subject: [PATCH 4/9] chore(porch): bugfix-1431 pr phase-transition --- .../bugfix-1431-stream-deck-phaseartifactverb-/status.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml index 120789518..33d51bee5 100644 --- a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml +++ b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml @@ -1,7 +1,7 @@ id: bugfix-1431 title: stream-deck-phaseartifactverb- protocol: bugfix -phase: fix +phase: pr plan_phases: [] current_plan_phase: null gates: @@ -11,4 +11,4 @@ iteration: 1 build_complete: false history: [] started_at: '2026-08-13T01:30:28.426Z' -updated_at: '2026-08-13T01:31:21.684Z' +updated_at: '2026-08-13T01:33:37.600Z' From b7d89bfedc296ca9c581fd0ed1ada5700838926c Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:36:44 +1000 Subject: [PATCH 5/9] [Bugfix #1431] Update thread: fix + CMAP verdicts --- codev/state/bugfix-1431_thread.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/codev/state/bugfix-1431_thread.md b/codev/state/bugfix-1431_thread.md index 7691c8089..4126a3053 100644 --- a/codev/state/bugfix-1431_thread.md +++ b/codev/state/bugfix-1431_thread.md @@ -28,3 +28,28 @@ sidebar's `gateIconFor` (apps/vscode/src/views/builder-row.ts) already knows Do NOT touch anything else in face.ts/actions.ts (#1410 just landed a large change; keep this diff trivially reviewable). + +## Fix phase — done + +Made the three scoped edits. Regression test confirmed to fail without the fix +(returns `undefined`) and pass with it (`view-diff`). Full suite 125/125, +check-types clean, esbuild build clean (after building the `@cluesmith/codev-sdk` +workspace dep first — the type/build errors before that were the unbuilt dep, not +my change). Committed as `Fix #1431: ...`. + +## PR phase + +PR #1442 opened (Fixes #1431). CMAP consult needs `--project-id bugfix-1431` — +auto-detect fails because the worktree's `codev/projects/` holds every project. +Running all three (gemini/codex/claude) in the background. + +## CMAP verdicts + +- gemini = APPROVE (HIGH) — "clean, minimal fix … with unit test coverage." +- claude = APPROVE (HIGH) — "correct one-line gate mapping … backed by a genuine + regression test; scope and hygiene are clean." +- codex = UNAVAILABLE — the codex lane errored on OpenAI billing ("no credits + remaining"), not a review verdict. Environment issue, unrelated to this change. + +Two independent APPROVEs, no requested changes. Notifying architect and firing the +pr gate; codex reported honestly as unavailable rather than a fabricated verdict. From fd7c1a1825340482d90f8942cf71a46efaeeedc6 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:36:52 +1000 Subject: [PATCH 6/9] chore(porch): bugfix-1431 pr gate-requested --- .../bugfix-1431-stream-deck-phaseartifactverb-/status.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml index 33d51bee5..fdf2a2cd1 100644 --- a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml +++ b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml @@ -7,8 +7,10 @@ current_plan_phase: null gates: pr: status: pending + requested_at: '2026-08-13T01:36:52.822Z' iteration: 1 build_complete: false history: [] started_at: '2026-08-13T01:30:28.426Z' -updated_at: '2026-08-13T01:33:37.600Z' +updated_at: '2026-08-13T01:36:52.823Z' +pr_ready_for_human: true From 2dfbd81a87e66ecc74e756cd0aed97c501e7723a Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:38:34 +1000 Subject: [PATCH 7/9] [Bugfix #1431] Pin reviewMode dial-mode effect for verify-approval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The verify-approval → view-diff mapping also flips reviewMode from 'none' to 'diff' (reviewMode derives from phaseArtifactVerb: view-diff → diff), so a verify-approval-blocked builder's review dials navigate the diff — symmetric with dev-approval/pr and correct while a human reviews finished work. Pin it with an assertion beside the existing dev-approval/pr reviewMode cases. --- apps/streamdeck/src/__tests__/actions.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/streamdeck/src/__tests__/actions.test.ts b/apps/streamdeck/src/__tests__/actions.test.ts index 3f3c0e46b..c23eece72 100644 --- a/apps/streamdeck/src/__tests__/actions.test.ts +++ b/apps/streamdeck/src/__tests__/actions.test.ts @@ -667,6 +667,7 @@ describe('reviewMode (dial mode from the shared resolver)', () => { expect(reviewMode(b({ protocolPhase: 'review' }))).toBe('diff'); expect(reviewMode(b({ blockedGate: 'dev-approval' }))).toBe('diff'); expect(reviewMode(b({ blockedGate: 'pr' }))).toBe('diff'); + expect(reviewMode(b({ blockedGate: 'verify-approval' }))).toBe('diff'); // #1431: dials navigate the diff while the human reviews finished work }); it('an unknown phase, no live status, or no builder → none', () => { expect(reviewMode(b({}))).toBe('none'); From 3603d63ef848b6bba9ea8aa7129ba38c426172d9 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 11:39:05 +1000 Subject: [PATCH 8/9] [Bugfix #1431] Update thread: architect review + reviewMode test --- codev/state/bugfix-1431_thread.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/codev/state/bugfix-1431_thread.md b/codev/state/bugfix-1431_thread.md index 4126a3053..567e33c44 100644 --- a/codev/state/bugfix-1431_thread.md +++ b/codev/state/bugfix-1431_thread.md @@ -53,3 +53,13 @@ Running all three (gemini/codex/claude) in the background. Two independent APPROVEs, no requested changes. Notifying architect and firing the pr gate; codex reported honestly as unavailable rather than a fabricated verdict. + +## Architect review of PR #1442 (compensating for codex being down) + +Flagged a real gap: the fix has a second behavioural effect neither the issue nor +my tests covered — `reviewMode()` derives from `phaseArtifactVerb` (`view-diff` → +`diff`), so a verify-approval-blocked builder's review dials flip from `none` +(dead) to `diff` (navigating the diff). Correct and desirable (symmetric with +dev-approval/pr), but was untested + undocumented. Added a `reviewMode` assertion +beside the dev-approval/pr cases and documented the dial-mode consequence in the PR +body. 125/125 pass. Still exactly in scope. Holding at the pr gate. From c94712101e925eba5211e7dc29bdab4b02e957a1 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Thu, 13 Aug 2026 17:19:28 +1000 Subject: [PATCH 9/9] chore(porch): bugfix-1431 pr gate-approved --- .../bugfix-1431-stream-deck-phaseartifactverb-/status.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml index fdf2a2cd1..9e2e81a9c 100644 --- a/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml +++ b/codev/projects/bugfix-1431-stream-deck-phaseartifactverb-/status.yaml @@ -6,11 +6,12 @@ plan_phases: [] current_plan_phase: null gates: pr: - status: pending + status: approved requested_at: '2026-08-13T01:36:52.822Z' + approved_at: '2026-08-13T07:19:28.351Z' iteration: 1 build_complete: false history: [] started_at: '2026-08-13T01:30:28.426Z' -updated_at: '2026-08-13T01:36:52.823Z' -pr_ready_for_human: true +updated_at: '2026-08-13T07:19:28.352Z' +pr_ready_for_human: false