From 2df700eb816ec799558936e42252a026bec4a978 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Thu, 16 Apr 2026 17:08:30 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20add=20/gsd-spec-phase=20=E2=80=94=20Soc?= =?UTF-8?q?ratic=20spec=20refinement=20with=20ambiguity=20scoring=20(#2213?= =?UTF-8?q?)=20(#2322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces `/gsd-spec-phase ` as an optional pre-step before discuss-phase. Clarifies WHAT a phase delivers (requirements, boundaries, acceptance criteria) with quantitative ambiguity scoring before discuss-phase handles HOW to implement. - `commands/gsd/spec-phase.md` — slash command routing to workflow - `get-shit-done/workflows/spec-phase.md` — full Socratic interview loop (up to 6 rounds, 5 rotating perspectives: Researcher, Simplifier, Boundary Keeper, Failure Analyst, Seed Closer) with weighted 4-dimension ambiguity gate (≤ 0.20 to write SPEC.md) - `get-shit-done/templates/spec.md` — SPEC.md template with falsifiable requirements (Current/Target/Acceptance per requirement), Boundaries, Acceptance Criteria, Ambiguity Report, and Interview Log; includes two full worked examples - `get-shit-done/workflows/discuss-phase.md` — new `check_spec` step detects `{padded_phase}-SPEC.md` at startup; displays "Found SPEC.md — N requirements locked. Focusing on implementation decisions."; `analyze_phase` respects `spec_loaded` flag to skip "what/why" gray areas; `write_context` emits `` section with boundary summary and canonical ref to SPEC.md - `docs/ARCHITECTURE.md` — update command/workflow counts (74→75, 71→72) Closes #2213 Co-authored-by: Claude Sonnet 4.6 --- commands/gsd/spec-phase.md | 62 +++++ docs/ARCHITECTURE.md | 8 +- get-shit-done/templates/spec.md | 307 +++++++++++++++++++++++ get-shit-done/workflows/discuss-phase.md | 50 +++- get-shit-done/workflows/spec-phase.md | 262 +++++++++++++++++++ 5 files changed, 684 insertions(+), 5 deletions(-) create mode 100644 commands/gsd/spec-phase.md create mode 100644 get-shit-done/templates/spec.md create mode 100644 get-shit-done/workflows/spec-phase.md diff --git a/commands/gsd/spec-phase.md b/commands/gsd/spec-phase.md new file mode 100644 index 000000000..a38916ffb --- /dev/null +++ b/commands/gsd/spec-phase.md @@ -0,0 +1,62 @@ +--- +name: gsd:spec-phase +description: Socratic spec refinement — clarify WHAT a phase delivers with ambiguity scoring before discuss-phase. Produces a SPEC.md with falsifiable requirements locked before implementation decisions begin. +argument-hint: " [--auto] [--text]" +allowed-tools: + - Read + - Write + - Bash + - Glob + - Grep + - AskUserQuestion +--- + + +Clarify phase requirements through structured Socratic questioning with quantitative ambiguity scoring. + +**Position in workflow:** `spec-phase → discuss-phase → plan-phase → execute-phase → verify` + +**How it works:** +1. Load phase context (PROJECT.md, REQUIREMENTS.md, ROADMAP.md, STATE.md) +2. Scout the codebase — understand current state before asking questions +3. Run Socratic interview loop (up to 6 rounds, rotating perspectives) +4. Score ambiguity across 4 weighted dimensions after each round +5. Gate: ambiguity ≤ 0.20 AND all dimensions meet minimums → write SPEC.md +6. Commit SPEC.md — discuss-phase picks it up automatically on next run + +**Output:** `{phase_dir}/{padded_phase}-SPEC.md` — falsifiable requirements that lock "what/why" before discuss-phase handles "how" + + + +@~/.claude/get-shit-done/workflows/spec-phase.md +@~/.claude/get-shit-done/templates/spec.md + + + +**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent. + + + +Phase number: $ARGUMENTS (required) + +**Flags:** +- `--auto` — Skip interactive questions; Claude selects recommended defaults and writes SPEC.md +- `--text` — Use plain-text numbered lists instead of TUI menus (required for `/rc` remote sessions) + +Context files are resolved in-workflow using `init phase-op`. + + + +Execute the spec-phase workflow from @~/.claude/get-shit-done/workflows/spec-phase.md end-to-end. + +**MANDATORY:** Read the workflow file BEFORE taking any action. The workflow contains the complete step-by-step process including the Socratic interview loop, ambiguity scoring gate, and SPEC.md generation. Do not improvise from the objective summary above. + + + +- Codebase scouted for current state before questioning begins +- All 4 ambiguity dimensions scored after each interview round +- Gate passed: ambiguity ≤ 0.20 AND all dimension minimums met +- SPEC.md written with falsifiable requirements, explicit boundaries, and acceptance criteria +- SPEC.md committed atomically +- User knows they can now run /gsd-discuss-phase which will load SPEC.md automatically + diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 0a943890f..6ed365ba0 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -113,7 +113,7 @@ User-facing entry points. Each file contains YAML frontmatter (name, description - **Copilot:** Slash commands (`/gsd-command-name`) - **Antigravity:** Skills -**Total commands:** 74 +**Total commands:** 75 ### Workflows (`get-shit-done/workflows/*.md`) @@ -124,7 +124,7 @@ Orchestration logic that commands reference. Contains the step-by-step process i - State update patterns - Error handling and recovery -**Total workflows:** 71 +**Total workflows:** 72 ### Agents (`agents/*.md`) @@ -409,11 +409,11 @@ UI-SPEC.md (per phase) ─────────────────── ``` ~/.claude/ # Claude Code (global install) -├── commands/gsd/*.md # 74 slash commands +├── commands/gsd/*.md # 75 slash commands ├── get-shit-done/ │ ├── bin/gsd-tools.cjs # CLI utility │ ├── bin/lib/*.cjs # 19 domain modules -│ ├── workflows/*.md # 71 workflow definitions +│ ├── workflows/*.md # 72 workflow definitions │ ├── references/*.md # 35 shared reference docs │ └── templates/ # Planning artifact templates ├── agents/*.md # 31 agent definitions diff --git a/get-shit-done/templates/spec.md b/get-shit-done/templates/spec.md new file mode 100644 index 000000000..99b615533 --- /dev/null +++ b/get-shit-done/templates/spec.md @@ -0,0 +1,307 @@ +# Phase Spec Template + +Template for `.planning/phases/XX-name/{phase_num}-SPEC.md` — locks requirements before discuss-phase. + +**Purpose:** Capture WHAT a phase delivers and WHY, with enough precision that requirements are falsifiable. discuss-phase reads this file and focuses on HOW to implement (skipping "what/why" questions already answered here). + +**Key principle:** Every requirement must be falsifiable — you can write a test or check that proves it was met or not. Vague requirements like "improve performance" are not allowed. + +**Downstream consumers:** +- `discuss-phase` — reads SPEC.md at startup; treats Requirements, Boundaries, and Acceptance Criteria as locked; skips "what/why" questions +- `gsd-planner` — reads locked requirements to constrain plan scope +- `gsd-verifier` — uses acceptance criteria as explicit pass/fail checks + +--- + +## File Template + +```markdown +# Phase [X]: [Name] — Specification + +**Created:** [date] +**Ambiguity score:** [score] (gate: ≤ 0.20) +**Requirements:** [N] locked + +## Goal + +[One precise sentence — specific and measurable. NOT "improve X" — instead "X changes from A to B".] + +## Background + +[Current state from codebase — what exists today, what's broken or missing, what triggers this work. Grounded in code reality, not abstract description.] + +## Requirements + +1. **[Short label]**: [Specific, testable statement.] + - Current: [what exists or does NOT exist today] + - Target: [what it should become after this phase] + - Acceptance: [concrete pass/fail check — how a verifier confirms this was met] + +2. **[Short label]**: [Specific, testable statement.] + - Current: [what exists or does NOT exist today] + - Target: [what it should become after this phase] + - Acceptance: [concrete pass/fail check] + +[Continue for all requirements. Each must have Current/Target/Acceptance.] + +## Boundaries + +**In scope:** +- [Explicit list of what this phase produces] +- [Each item is a concrete deliverable or behavior] + +**Out of scope:** +- [Explicit list of what this phase does NOT do] — [brief reason why it's excluded] +- [Adjacent problems excluded from this phase] — [brief reason] + +## Constraints + +[Performance, compatibility, data volume, dependency, or platform constraints. +If none: "No additional constraints beyond standard project conventions."] + +## Acceptance Criteria + +- [ ] [Pass/fail criterion — unambiguous, verifiable] +- [ ] [Pass/fail criterion] +- [ ] [Pass/fail criterion] + +[Every acceptance criterion must be a checkbox that resolves to PASS or FAIL. +No "should feel good", "looks reasonable", or "generally works" — those are not checkboxes.] + +## Ambiguity Report + +| Dimension | Score | Min | Status | Notes | +|--------------------|-------|------|--------|------------------------------------| +| Goal Clarity | | 0.75 | | | +| Boundary Clarity | | 0.70 | | | +| Constraint Clarity | | 0.65 | | | +| Acceptance Criteria| | 0.70 | | | +| **Ambiguity** | | ≤0.20| | | + +Status: ✓ = met minimum, ⚠ = below minimum (planner treats as assumption) + +## Interview Log + +[Key decisions made during the Socratic interview. Format: round → question → answer → decision locked.] + +| Round | Perspective | Question summary | Decision locked | +|-------|----------------|-------------------------|------------------------------------| +| 1 | Researcher | [what was asked] | [what was decided] | +| 2 | Simplifier | [what was asked] | [what was decided] | +| 3 | Boundary Keeper| [what was asked] | [what was decided] | + +[If --auto mode: note "auto-selected" decisions with the reasoning Claude used.] + +--- + +*Phase: [XX-name]* +*Spec created: [date]* +*Next step: /gsd-discuss-phase [X] — implementation decisions (how to build what's specified above)* +``` + + + +**Example 1: Feature addition (Post Feed)** + +```markdown +# Phase 3: Post Feed — Specification + +**Created:** 2025-01-20 +**Ambiguity score:** 0.12 +**Requirements:** 4 locked + +## Goal + +Users can scroll through posts from accounts they follow, with new posts available after pull-to-refresh. + +## Background + +The database has a `posts` table and `follows` table. No feed query or feed UI exists today. The home screen shows a placeholder "Your feed will appear here." This phase builds the feed query, API endpoint, and the feed list component. + +## Requirements + +1. **Feed query**: Returns posts from followed accounts ordered by creation time, descending. + - Current: No feed query exists — `posts` table is queried directly only from profile pages + - Target: `GET /api/feed` returns paginated posts from followed accounts, newest first, max 20 per page + - Acceptance: Query returns correct posts for a user who follows 3 accounts with known post counts; cursor-based pagination advances correctly + +2. **Feed display**: Posts display in a scrollable card list. + - Current: Home screen shows static placeholder text + - Target: Home screen renders feed cards with author, timestamp, post content, and reaction count + - Acceptance: Feed renders without error for 0 posts (empty state shown), 1 post, and 20+ posts + +3. **Pull-to-refresh**: User can refresh the feed manually. + - Current: No refresh mechanism exists + - Target: Pull-down gesture triggers refetch; new posts appear at top of list + - Acceptance: After a new post is created in test, pull-to-refresh shows the new post without full app restart + +4. **New posts indicator**: When new posts arrive, a banner appears instead of auto-scrolling. + - Current: No such mechanism + - Target: "3 new posts" banner appears when refetch returns posts newer than the oldest visible post; tapping banner scrolls to top and shows new posts + - Acceptance: Banner appears for ≥1 new post, does not appear when no new posts, tap navigates to top + +## Boundaries + +**In scope:** +- Feed query (backend) — posts from followed accounts, paginated +- Feed list UI (frontend) — post cards with author, timestamp, content, reaction counts +- Pull-to-refresh gesture +- New posts indicator banner +- Empty state when user follows no one or no posts exist + +**Out of scope:** +- Creating posts — that is Phase 4 +- Reacting to posts — that is Phase 5 +- Following/unfollowing accounts — that is Phase 2 (already done) +- Push notifications for new posts — separate backlog item + +## Constraints + +- Feed query must use cursor-based pagination (not offset) — the database has 500K+ posts and offset pagination is unacceptably slow beyond page 3 +- The feed card component must reuse the existing `` component from Phase 2 + +## Acceptance Criteria + +- [ ] `GET /api/feed` returns posts only from followed accounts (not all posts) +- [ ] `GET /api/feed` supports `cursor` parameter for pagination +- [ ] Feed renders correctly at 0, 1, and 20+ posts +- [ ] Pull-to-refresh triggers refetch +- [ ] New posts indicator appears when posts newer than current view exist +- [ ] Empty state renders when user follows no one + +## Ambiguity Report + +| Dimension | Score | Min | Status | Notes | +|--------------------|-------|------|--------|----------------------------------| +| Goal Clarity | 0.92 | 0.75 | ✓ | | +| Boundary Clarity | 0.95 | 0.70 | ✓ | Explicit out-of-scope list | +| Constraint Clarity | 0.80 | 0.65 | ✓ | Cursor pagination required | +| Acceptance Criteria| 0.85 | 0.70 | ✓ | 6 pass/fail criteria | +| **Ambiguity** | 0.12 | ≤0.20| ✓ | | + +## Interview Log + +| Round | Perspective | Question summary | Decision locked | +|-------|-----------------|------------------------------|-----------------------------------------| +| 1 | Researcher | What exists in posts today? | posts + follows tables exist, no feed | +| 2 | Simplifier | Minimum viable feed? | Cards + pull-refresh, no auto-scroll | +| 3 | Boundary Keeper | What's NOT this phase? | Creating posts, reactions out of scope | +| 3 | Boundary Keeper | What does done look like? | Scrollable feed with 4 card fields | + +--- + +*Phase: 03-post-feed* +*Spec created: 2025-01-20* +*Next step: /gsd-discuss-phase 3 — implementation decisions (card layout, loading skeleton, etc.)* +``` + +**Example 2: CLI tool (Database backup)** + +```markdown +# Phase 2: Backup Command — Specification + +**Created:** 2025-01-20 +**Ambiguity score:** 0.15 +**Requirements:** 3 locked + +## Goal + +A `gsd backup` CLI command creates a reproducible database snapshot that can be restored by `gsd restore` (a separate phase). + +## Background + +No backup tooling exists. The project uses PostgreSQL. Developers currently use `pg_dump` manually — there is no standardized process, no output naming convention, and no CI integration. Three incidents in the last quarter involved restoring from wrong or corrupt dumps. + +## Requirements + +1. **Backup creation**: CLI command executes a full database backup. + - Current: No `backup` subcommand exists in the CLI + - Target: `gsd backup` connects to the database (via `DATABASE_URL` env or `--db` flag), runs pg_dump, writes output to `./backups/YYYY-MM-DD_HH-MM-SS.dump` + - Acceptance: Running `gsd backup` on a test database creates a `.dump` file; running `pg_restore` on that file recreates the database without error + +2. **Network retry**: Transient network failures are retried automatically. + - Current: pg_dump fails immediately on network error + - Target: Backup retries up to 3 times with 5-second delay; 4th failure exits with code 1 and a message to stderr + - Acceptance: Simulating 2 sequential network failures causes 2 retries then success; simulating 4 failures causes exit code 1 and stderr message + +3. **Partial cleanup**: Failed backups do not leave corrupt files. + - Current: Manual pg_dump leaves partial files on failure + - Target: If backup fails after starting, the partial `.dump` file is deleted before exit + - Acceptance: After a simulated failure mid-dump, no `.dump` file exists in `./backups/` + +## Boundaries + +**In scope:** +- `gsd backup` subcommand (full dump only) +- Output to `./backups/` directory (created if missing) +- Network retry (3 attempts) +- Partial file cleanup on failure + +**Out of scope:** +- `gsd restore` — that is Phase 3 +- Incremental backups — separate backlog item (full dump only for now) +- S3 or remote storage — separate backlog item +- Encryption — separate backlog item +- Scheduled/cron backups — separate backlog item + +## Constraints + +- Must use `pg_dump` (not a custom query) — ensures compatibility with standard `pg_restore` +- `--no-retry` flag must be available for CI use (fail fast, no retries) + +## Acceptance Criteria + +- [ ] `gsd backup` creates a `.dump` file in `./backups/YYYY-MM-DD_HH-MM-SS.dump` format +- [ ] `gsd backup` uses `DATABASE_URL` env var or `--db` flag for connection +- [ ] 3 retries on network failure, then exit code 1 with stderr message +- [ ] `--no-retry` flag skips retries and fails immediately on first error +- [ ] No partial `.dump` file left after a failed backup + +## Ambiguity Report + +| Dimension | Score | Min | Status | Notes | +|--------------------|-------|------|--------|--------------------------------| +| Goal Clarity | 0.90 | 0.75 | ✓ | | +| Boundary Clarity | 0.95 | 0.70 | ✓ | Explicit out-of-scope list | +| Constraint Clarity | 0.75 | 0.65 | ✓ | pg_dump required | +| Acceptance Criteria| 0.80 | 0.70 | ✓ | 5 pass/fail criteria | +| **Ambiguity** | 0.15 | ≤0.20| ✓ | | + +## Interview Log + +| Round | Perspective | Question summary | Decision locked | +|-------|-----------------|------------------------------|-----------------------------------------| +| 1 | Researcher | What backup tooling exists? | None — pg_dump manual only | +| 2 | Simplifier | Minimum viable backup? | Full dump only, local only | +| 3 | Boundary Keeper | What's NOT this phase? | Restore, S3, encryption excluded | +| 4 | Failure Analyst | What goes wrong on failure? | Partial files, CI fail-fast needed | + +--- + +*Phase: 02-backup-command* +*Spec created: 2025-01-20* +*Next step: /gsd-discuss-phase 2 — implementation decisions (progress reporting, flag design, etc.)* +``` + + + + +**Every requirement needs all three fields:** +- Current: grounds the requirement in reality — what exists today? +- Target: the concrete change — not "improve X" but "X becomes Y" +- Acceptance: the falsifiable check — how does a verifier confirm this? + +**Ambiguity Report must reflect the actual interview.** If a dimension is below minimum, mark it ⚠ — the planner knows to treat it as an assumption rather than a locked requirement. + +**Interview Log is evidence of rigor.** Don't skip it. It shows that requirements came from discovery, not assumption. + +**Boundaries protect the phase from scope creep.** The out-of-scope list with reasoning is as important as the in-scope list. Future phases that touch adjacent areas can point to this SPEC.md to understand what was intentionally excluded. + +**SPEC.md is a one-way door for requirements.** discuss-phase will treat these as locked. If requirements change after SPEC.md is written, the user should update SPEC.md first, then re-run discuss-phase. + +**SPEC.md does NOT replace CONTEXT.md.** They serve different purposes: +- SPEC.md: what the phase delivers (requirements, boundaries, acceptance criteria) +- CONTEXT.md: how the phase will be implemented (decisions, patterns, tradeoffs) + +discuss-phase generates CONTEXT.md after reading SPEC.md. + diff --git a/get-shit-done/workflows/discuss-phase.md b/get-shit-done/workflows/discuss-phase.md index 46d0cded0..d85e46b2b 100644 --- a/get-shit-done/workflows/discuss-phase.md +++ b/get-shit-done/workflows/discuss-phase.md @@ -212,7 +212,30 @@ This step cannot be skipped. Before proceeding to `check_existing` or any other Write these answers inline before continuing. If a blocking anti-pattern cannot be answered from the context in `.continue-here.md`, stop and ask the user for clarification. -**If no `.continue-here.md` exists, or no `blocking` rows are found:** Proceed directly to `check_existing`. +**If no `.continue-here.md` exists, or no `blocking` rows are found:** Proceed directly to `check_spec`. + + + +Check if a SPEC.md (from `/gsd-spec-phase`) exists for this phase. SPEC.md locks requirements before implementation decisions — if present, this discussion focuses on HOW to implement, not WHAT to build. + +```bash +ls ${phase_dir}/*-SPEC.md 2>/dev/null | grep -v AI-SPEC | head -1 || true +``` + +**If SPEC.md is found:** +1. Read the SPEC.md file. +2. Count the number of requirements (numbered items in the `## Requirements` section). +3. Display: + ``` + Found SPEC.md — {N} requirements locked. Focusing on implementation decisions. + ``` +4. Set internal flag `spec_loaded = true`. +5. Store the requirements, boundaries, and acceptance criteria from SPEC.md as `` — these flow directly into CONTEXT.md without re-asking. +6. Continue to `check_existing`. + +**If no SPEC.md is found:** Continue to `check_existing` with `spec_loaded = false` (default behavior unchanged). + +**Note:** SPEC.md files named `AI-SPEC.md` (from `/gsd-ai-integration-phase`) are excluded — those serve a different purpose. @@ -437,6 +460,12 @@ Analyze the phase to identify gray areas worth discussing. **Use both `prior_dec - These are **pre-answered** — don't re-ask unless this phase has conflicting needs - Note applicable prior decisions for use in presentation +2b. **SPEC.md awareness** — If `spec_loaded = true` (SPEC.md was found in `check_spec`): + - The `` from SPEC.md are pre-answered: Goal, Boundaries, Constraints, Acceptance Criteria. + - Do NOT generate gray areas about WHAT to build or WHY — those are locked. + - Only generate gray areas about HOW to implement: technical approach, library choices, UX/UI patterns, interaction details, error handling style. + - When presenting gray areas, include a note: "Requirements are locked by SPEC.md — discussing implementation decisions only." + 3. **Gray areas by category** — For each relevant category (UI, UX, Behavior, Empty States, Content), identify 1-2 specific ambiguities that would change implementation. **Annotate with code context where relevant** (e.g., "You already have a Card component" or "No existing pattern for this"). 4. **Skip assessment** — If no meaningful gray areas exist (pure infrastructure, clear-cut implementation, or all already decided in prior phases), the phase may not need discussion. @@ -915,6 +944,12 @@ mkdir -p ".planning/phases/${padded_phase}-${phase_slug}" **File location:** `${phase_dir}/${padded_phase}-CONTEXT.md` +**SPEC.md integration** — If `spec_loaded = true`: +- Add a `` section immediately after `` (see template below). +- Add the SPEC.md file to `` with note "Locked requirements — MUST read before planning". +- Do NOT duplicate requirements text from SPEC.md into `` — agents read SPEC.md directly. +- The `` section contains only implementation decisions from this discussion. + **Structure the content by what was discussed:** ```markdown @@ -930,6 +965,19 @@ mkdir -p ".planning/phases/${padded_phase}-${phase_slug}" +[If spec_loaded = true, insert this section:] + +## Requirements (locked via SPEC.md) + +**{N} requirements are locked.** See `{padded_phase}-SPEC.md` for full requirements, boundaries, and acceptance criteria. + +Downstream agents MUST read `{padded_phase}-SPEC.md` before planning or implementing. Requirements are not duplicated here. + +**In scope (from SPEC.md):** [copy the "In scope" bullet list from SPEC.md Boundaries] +**Out of scope (from SPEC.md):** [copy the "Out of scope" bullet list from SPEC.md Boundaries] + + + ## Implementation Decisions diff --git a/get-shit-done/workflows/spec-phase.md b/get-shit-done/workflows/spec-phase.md new file mode 100644 index 000000000..46aca520e --- /dev/null +++ b/get-shit-done/workflows/spec-phase.md @@ -0,0 +1,262 @@ + +Clarify WHAT a phase delivers through a Socratic interview loop with quantitative ambiguity scoring. +Produces a SPEC.md with falsifiable requirements that discuss-phase treats as locked decisions. + +This workflow handles "what" and "why" — discuss-phase handles "how". + + + +Score each dimension 0.0 (completely unclear) to 1.0 (crystal clear): + +| Dimension | Weight | Minimum | What it measures | +|-------------------|--------|---------|---------------------------------------------------| +| Goal Clarity | 35% | 0.75 | Is the outcome specific and measurable? | +| Boundary Clarity | 25% | 0.70 | What's in scope vs out of scope? | +| Constraint Clarity| 20% | 0.65 | Performance, compatibility, data requirements? | +| Acceptance Criteria| 20% | 0.70 | How do we know it's done? | + +**Ambiguity score** = 1.0 − (0.35×goal + 0.25×boundary + 0.20×constraint + 0.20×acceptance) + +**Gate:** ambiguity ≤ 0.20 AND all dimensions ≥ their minimums → ready to write SPEC.md. + +A score of 0.20 means 80% weighted clarity — enough precision that the planner won't silently make wrong assumptions. + + + +Rotate through these perspectives — each naturally surfaces different blindspots: + +**Researcher (rounds 1–2):** Ground the discussion in current reality. +- "What exists in the codebase today related to this phase?" +- "What's the delta between today and the target state?" +- "What triggers this work — what's broken or missing?" + +**Simplifier (round 2):** Surface minimum viable scope. +- "What's the simplest version that solves the core problem?" +- "If you had to cut 50%, what's the irreducible core?" +- "What would make this phase a success even without the nice-to-haves?" + +**Boundary Keeper (round 3):** Lock the perimeter. +- "What explicitly will NOT be done in this phase?" +- "What adjacent problems is it tempting to solve but shouldn't?" +- "What does 'done' look like — what's the final deliverable?" + +**Failure Analyst (round 4):** Find the edge cases that invalidate requirements. +- "What's the worst thing that could go wrong if we get the requirements wrong?" +- "What does a broken version of this look like?" +- "What would cause a verifier to reject the output?" + +**Seed Closer (rounds 5–6):** Lock remaining undecided territory. +- "We have [dimension] at [score] — what would make it completely clear?" +- "The remaining ambiguity is in [area] — can we make a decision now?" +- "Is there anything you'd regret not specifying before planning starts?" + + + + +## Step 1: Initialize + +```bash +INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE}") +if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi +``` + +Parse JSON for: `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `state_path`, `requirements_path`, `roadmap_path`, `planning_path`, `response_language`, `commit_docs`. + +**If `response_language` is set:** All user-facing text in this workflow MUST be in `{response_language}`. Technical terms, code, and file paths stay in English. + +**If `phase_found` is false:** +``` +Phase [X] not found in roadmap. +Use /gsd-progress to see available phases. +``` +Exit. + +**Check for existing SPEC.md:** +```bash +ls ${phase_dir}/*-SPEC.md 2>/dev/null | grep -v AI-SPEC | head -1 || true +``` + +If SPEC.md already exists: + +**If `--auto`:** Auto-select "Update it". Log: `[auto] SPEC.md exists — updating.` + +**Otherwise:** Use AskUserQuestion: +- header: "Spec" +- question: "Phase [X] already has a SPEC.md. What do you want to do?" +- options: + - "Update it" — Revise and re-score + - "View it" — Show current spec + - "Skip" — Exit (use existing spec as-is) + +If "View": Display SPEC.md, then offer Update/Skip. +If "Skip": Exit with message: "Existing SPEC.md unchanged. Run /gsd-discuss-phase [X] to continue." +If "Update": Load existing SPEC.md, continue to Step 3. + +## Step 2: Scout Codebase + +**Read these files before any questions:** +- `{requirements_path}` — Project requirements +- `{state_path}` — Decisions already made, current phase, blockers +- ROADMAP.md phase entry — Phase description, goals, canonical refs + +**Grep the codebase** for code/files relevant to this phase goal. Look for: +- Existing implementations of similar functionality +- Integration points where new code will connect +- Test coverage gaps relevant to the phase +- Prior phase artifacts (SUMMARY.md, VERIFICATION.md) that inform current state + +**Synthesize current state** — the grounded baseline for the interview: +- What exists today related to this phase +- The gap between current state and the phase goal +- The primary deliverable: what file/behavior/capability does NOT exist yet? + +Confirm your current state synthesis internally. Do not present it to the user yet — you'll use it to ask precise, grounded questions. + +## Step 3: First Ambiguity Assessment + +Before questioning begins, score the phase's current ambiguity based only on what ROADMAP.md and REQUIREMENTS.md say: + +``` +Goal Clarity: [score 0.0–1.0] +Boundary Clarity: [score 0.0–1.0] +Constraint Clarity: [score 0.0–1.0] +Acceptance Criteria:[score 0.0–1.0] + +Ambiguity: [score] ([calculate]) +``` + +**If `--auto` and initial ambiguity already ≤ 0.20 with all minimums met:** Skip interview — derive SPEC.md directly from roadmap + requirements. Log: `[auto] Phase requirements are already sufficiently clear — generating SPEC.md from existing context.` Jump to Step 6. + +**Otherwise:** Continue to Step 4. + +## Step 4: Socratic Interview Loop + +**Max 6 rounds.** Each round: 2–3 questions max. End round after user responds. + +**Round selection by perspective:** +- Round 1: Researcher +- Round 2: Researcher + Simplifier +- Round 3: Boundary Keeper +- Round 4: Failure Analyst +- Rounds 5–6: Seed Closer (focus on lowest-scoring dimensions) + +**After each round:** +1. Update all 4 dimension scores from the user's answers +2. Calculate new ambiguity score +3. Display the updated scoring: + +``` +After round [N]: + Goal Clarity: [score] (min 0.75) [✓ or ↑ needed] + Boundary Clarity: [score] (min 0.70) [✓ or ↑ needed] + Constraint Clarity: [score] (min 0.65) [✓ or ↑ needed] + Acceptance Criteria:[score] (min 0.70) [✓ or ↑ needed] + Ambiguity: [score] (gate: ≤ 0.20) +``` + +**Gate check after each round:** + +If gate passes (ambiguity ≤ 0.20 AND all minimums met): + +**If `--auto`:** Jump to Step 6. + +**Otherwise:** AskUserQuestion: +- header: "Spec Gate Passed" +- question: "Ambiguity is [score] — requirements are clear enough to write SPEC.md. Proceed?" +- options: + - "Yes — write SPEC.md" → Jump to Step 6 + - "One more round" → Continue interview + - "Done talking — write it" → Jump to Step 6 + +**If max rounds reached (6) and gate not passed:** + +**If `--auto`:** Write SPEC.md anyway — flag unresolved dimensions. Log: `[auto] Max rounds reached. Writing SPEC.md with [N] dimensions below minimum. Planner will need to treat these as assumptions.` + +**Otherwise:** AskUserQuestion: +- header: "Max Rounds" +- question: "After 6 rounds, ambiguity is [score]. [List dimensions still below minimum.] What would you like to do?" +- options: + - "Write SPEC.md anyway — flag gaps" → Write SPEC.md, mark unresolved dimensions in Ambiguity Report + - "Keep talking" → Continue (no round limit from here) + - "Abandon" → Exit without writing + +**If `--auto` mode throughout:** Replace all AskUserQuestion calls above with Claude's recommended choice. Log decisions inline. Apply the same logic as `--auto` in discuss-phase. + +**Text mode (`workflow.text_mode: true` or `--text` flag):** Use plain-text numbered lists instead of AskUserQuestion TUI menus. + +## Step 5: (covered inline — ambiguity scoring is per-round) + +## Step 6: Generate SPEC.md + +Use the SPEC.md template from @~/.claude/get-shit-done/templates/spec.md. + +**Requirements for every requirement entry:** +- One specific, testable statement +- Current state (what exists now) +- Target state (what it should become) +- Acceptance criterion (how to verify it was met) + +**Vague requirements are rejected:** +- ✗ "The system should be fast" +- ✗ "Improve user experience" +- ✓ "API endpoint responds in < 200ms at p95 under 100 concurrent requests" +- ✓ "CLI command exits with code 1 and prints to stderr on invalid input" + +**Count requirements.** The display in discuss-phase reads: "Found SPEC.md — {N} requirements locked." + +**Boundaries must be explicit lists:** +- "In scope" — what this phase produces +- "Out of scope" — what it explicitly does NOT do (with brief reasoning) + +**Acceptance criteria must be pass/fail checkboxes** — no "should feel good" or "looks reasonable." + +**If any dimensions are below minimum**, mark them in the Ambiguity Report with: `⚠ Below minimum — planner must treat as assumption`. + +Write to: `{phase_dir}/{padded_phase}-SPEC.md` + +## Step 7: Commit + +```bash +git add "${phase_dir}/${padded_phase}-SPEC.md" +git commit -m "spec(phase-${phase_number}): add SPEC.md for ${phase_name} — ${requirement_count} requirements (#2213)" +``` + +If `commit_docs` is false: Skip commit. Note that SPEC.md was written but not committed. + +## Step 8: Wrap Up + +Display: + +``` +SPEC.md written — {N} requirements locked. + + Phase {X}: {name} + Ambiguity: {final_score} (gate: ≤ 0.20) + +Next: /gsd-discuss-phase {X} + discuss-phase will detect SPEC.md and focus on implementation decisions only. +``` + + + + +- Every requirement MUST have current state, target state, and acceptance criterion +- Boundaries section is MANDATORY — cannot be empty +- "In scope" and "Out of scope" must be explicit lists, not narrative prose +- Acceptance criteria must be pass/fail — no subjective criteria +- SPEC.md is NEVER written if the user selects "Abandon" +- Do NOT ask about HOW to implement — that is discuss-phase territory +- Scout the codebase BEFORE the first question — grounded questions only +- Max 2–3 questions per round — do not frontload all questions at once + + + +- Codebase scouted and current state understood before questioning +- All 4 dimensions scored after every round +- Gate passed OR user explicitly chose to write despite gaps +- SPEC.md contains only falsifiable requirements +- Boundaries are explicit (in scope / out of scope with reasoning) +- Acceptance criteria are pass/fail checkboxes +- SPEC.md committed atomically (when commit_docs is true) +- User directed to /gsd-discuss-phase as next step +