From fd3a808b7e8f94f265bdc821e2faeb6a61900857 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Fri, 10 Apr 2026 12:41:59 -0400 Subject: [PATCH] fix(workflow): offer recommendation instead of hard redirect for missing UI-SPEC.md (#2039) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(workflow): offer recommendation instead of hard redirect when UI-SPEC.md missing When plan-phase detects frontend indicators but no UI-SPEC.md, replace the AskUserQuestion hard-exit block with an offer_next-style recommendation that displays /gsd-ui-phase as the primary next step and /gsd-plan-phase --skip-ui as the bypass option. Also registers --skip-ui as a parsed flag so it silently bypasses the UI gate. Closes #2011 Co-Authored-By: Claude Sonnet 4.6 * ci: retrigger CI — resolve stale macOS check --------- Co-authored-by: Claude Sonnet 4.6 --- get-shit-done/workflows/plan-phase.md | 28 +++++++-------- tests/plan-phase-ui-redirect.test.cjs | 51 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 tests/plan-phase-ui-redirect.test.cjs diff --git a/get-shit-done/workflows/plan-phase.md b/get-shit-done/workflows/plan-phase.md index 2f8ae2cbc..6903e3529 100644 --- a/get-shit-done/workflows/plan-phase.md +++ b/get-shit-done/workflows/plan-phase.md @@ -46,7 +46,7 @@ Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_ ## 2. Parse and Normalize Arguments -Extract from $ARGUMENTS: phase number (integer or decimal like `2.1`), flags (`--research`, `--skip-research`, `--gaps`, `--skip-verify`, `--prd `, `--reviews`, `--text`). +Extract from $ARGUMENTS: phase number (integer or decimal like `2.1`), flags (`--research`, `--skip-research`, `--gaps`, `--skip-verify`, `--skip-ui`, `--prd `, `--reviews`, `--text`). Set `TEXT_MODE=true` if `--text` is present in $ARGUMENTS OR `text_mode` from init JSON is `true`. When `TEXT_MODE` is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for Claude Code remote sessions (`/rc` mode) where TUI menus don't work through the Claude App. @@ -463,6 +463,8 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1) **If UI-SPEC.md found:** Set `UI_SPEC_PATH=$UI_SPEC_FILE`. Display: `Using UI design contract: ${UI_SPEC_PATH}` +**If UI-SPEC.md missing AND `--skip-ui` flag is present in $ARGUMENTS:** Skip silently to step 6. + **If UI-SPEC.md missing AND `UI_GATE_CFG` is `true`:** Read auto-chain state: @@ -485,24 +487,18 @@ Continue to step 6. **If `AUTO_CHAIN` is `false` (manual invocation):** -If `TEXT_MODE` is true, present as a plain-text numbered list: +Output this markdown directly (not as a code block): + ``` -Phase {N} has frontend indicators but no UI-SPEC.md. Generate a design contract before planning? - -1. Generate UI-SPEC first — Run /gsd-ui-phase {N} then re-run /gsd-plan-phase {N} -2. Continue without UI-SPEC -3. Not a frontend phase - -Enter number: +## ⚠ UI-SPEC.md missing for Phase {N} +▶ Recommended next step: +`/gsd-ui-phase {N} ${GSD_WS}` — generate UI design contract before planning +─────────────────────────────────────────────── +Also available: +- `/gsd-plan-phase {N} --skip-ui ${GSD_WS}` — plan without UI-SPEC (not recommended for frontend phases) ``` -Otherwise use AskUserQuestion: -- header: "UI Design Contract" -- question: "Phase {N} has frontend indicators but no UI-SPEC.md. Generate a design contract before planning?" -- options: - - "Generate UI-SPEC first" → Display: "Run `/gsd-ui-phase {N} ${GSD_WS}` then re-run `/gsd-plan-phase {N} ${GSD_WS}`". Exit workflow. - - "Continue without UI-SPEC" → Continue to step 6. - - "Not a frontend phase" → Continue to step 6. +**Exit the plan-phase workflow. Do not continue.** **If `HAS_UI` is 1 (no frontend indicators):** Skip silently to step 5.7. diff --git a/tests/plan-phase-ui-redirect.test.cjs b/tests/plan-phase-ui-redirect.test.cjs new file mode 100644 index 000000000..368e49d22 --- /dev/null +++ b/tests/plan-phase-ui-redirect.test.cjs @@ -0,0 +1,51 @@ +'use strict'; + +const { describe, test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); + +describe('plan-phase UI-SPEC missing behavior', () => { + const workflowPath = path.join( + __dirname, + '..', + 'get-shit-done', + 'workflows', + 'plan-phase.md' + ); + + test('workflow file exists', () => { + assert.ok(fs.existsSync(workflowPath), `Expected workflow file at ${workflowPath}`); + }); + + test('does NOT contain hard-blocking exit redirect to /gsd-ui-phase', () => { + const text = fs.readFileSync(workflowPath, 'utf8'); + // The hard redirect pattern: AskUserQuestion option exits with "Run /gsd-ui-phase... Exit workflow." + // This is the pattern from line ~503 in the original file + const hardExitPattern = /Generate UI-SPEC first.*Exit workflow/s; + assert.ok( + !hardExitPattern.test(text), + 'plan-phase.md must NOT contain a hard "Generate UI-SPEC first → Exit workflow" redirect. ' + + 'It should offer a primary recommendation with --skip-ui bypass option instead.' + ); + }); + + test('contains --skip-ui bypass option when UI-SPEC.md is missing', () => { + const text = fs.readFileSync(workflowPath, 'utf8'); + assert.ok( + text.includes('--skip-ui'), + 'plan-phase.md must include --skip-ui as a bypass option when UI-SPEC.md is missing' + ); + }); + + test('contains a primary recommendation block for missing UI-SPEC', () => { + const text = fs.readFileSync(workflowPath, 'utf8'); + const hasRecommendationPattern = + text.includes('Recommended next step') && + text.includes('gsd-ui-phase'); + assert.ok( + hasRecommendationPattern, + 'plan-phase.md must include a "Recommended next step" recommendation for /gsd-ui-phase when UI-SPEC.md is missing' + ); + }); +});