diff --git a/commands/gsd/ultraplan-phase.md b/commands/gsd/ultraplan-phase.md new file mode 100644 index 00000000..1a5e3aab --- /dev/null +++ b/commands/gsd/ultraplan-phase.md @@ -0,0 +1,33 @@ +--- +name: gsd:ultraplan-phase +description: "[BETA] Offload plan phase to Claude Code's ultraplan cloud — drafts remotely while terminal stays free, review in browser with inline comments, import back via /gsd-import. Claude Code only." +argument-hint: "[phase-number]" +allowed-tools: + - Read + - Bash + - Glob + - Grep +--- + + +Offload GSD's plan phase to Claude Code's ultraplan cloud infrastructure. + +Ultraplan drafts the plan in a remote cloud session while your terminal stays free. +Review and comment on the plan in your browser, then import it back via /gsd-import --from. + +⚠ BETA: ultraplan is in research preview. Use /gsd-plan-phase for stable local planning. +Requirements: Claude Code v2.1.91+, claude.ai account, GitHub repository. + + + +@~/.claude/get-shit-done/workflows/ultraplan-phase.md +@~/.claude/get-shit-done/references/ui-brand.md + + + +$ARGUMENTS + + + +Execute the ultraplan-phase workflow end-to-end. + diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 8ddf308a..506f8452 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:** 79 +**Total commands:** 80 ### 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:** 76 +**Total workflows:** 77 ### Agents (`agents/*.md`) @@ -409,11 +409,11 @@ UI-SPEC.md (per phase) ─────────────────── ``` ~/.claude/ # Claude Code (global install) -├── commands/gsd/*.md # 79 slash commands +├── commands/gsd/*.md # 80 slash commands ├── get-shit-done/ │ ├── bin/gsd-tools.cjs # CLI utility │ ├── bin/lib/*.cjs # 19 domain modules -│ ├── workflows/*.md # 72 workflow definitions +│ ├── workflows/*.md # 77 workflow definitions │ ├── references/*.md # 35 shared reference docs │ └── templates/ # Planning artifact templates ├── agents/*.md # 31 agent definitions diff --git a/docs/BETA.md b/docs/BETA.md new file mode 100644 index 00000000..0e078eb3 --- /dev/null +++ b/docs/BETA.md @@ -0,0 +1,98 @@ +# GSD Beta Features + +> **Beta features are opt-in and may change or be removed without notice.** They are not covered by the stable API guarantees that apply to the rest of GSD. If a beta feature ships to stable, it will be documented in [COMMANDS.md](COMMANDS.md) and [FEATURES.md](FEATURES.md) with a changelog entry. + +--- + +## `/gsd-ultraplan-phase` — Ultraplan Integration [BETA] + +> **Claude Code only · Requires Claude Code v2.1.91+** +> Ultraplan is itself a Claude Code research preview — both this command and the underlying feature may change. + +### What it does + +`/gsd-ultraplan-phase` offloads GSD's plan-phase drafting to [Claude Code's ultraplan](https://code.claude.ai) cloud infrastructure. Instead of planning locally in the terminal, the plan is drafted in a browser-based session with: + +- An **outline sidebar** for navigating the plan structure +- **Inline comments** for annotating and refining tasks +- A persistent browser tab so your terminal stays free while the plan is being drafted + +When you're satisfied with the draft, you save it and import it back into GSD — conflict detection, format validation, and plan-checker verification all run automatically. + +### Why use it + +| Situation | Recommendation | +|-----------|---------------| +| Long, complex phases where you want to read and comment on the plan before it executes | Use `/gsd-ultraplan-phase` | +| Quick phases, familiar domain, or non-Claude Code runtimes | Use `/gsd-plan-phase` (stable) | +| You have a plan from another source (teammate, external AI) | Use `/gsd-import` | + +### Requirements + +- **Runtime:** Claude Code only. The command exits with an error on Gemini CLI, Copilot CLI, and other runtimes. +- **Version:** Claude Code v2.1.91 or later (the `$CLAUDE_CODE_VERSION` env var must be set). +- **Cost:** No extra charge for Pro and Max subscribers. Ultraplan is included at no additional cost. + +### Usage + +```bash +/gsd-ultraplan-phase # Ultraplan the next unplanned phase +/gsd-ultraplan-phase 2 # Ultraplan a specific phase number +``` + +| Argument | Required | Description | +|----------|----------|-------------| +| `N` | No | Phase number (defaults to next unplanned phase) | + +### How it works + +1. **Initialization** — GSD runs the standard plan-phase init, resolving which phase to plan and confirming prerequisites. + +2. **Context assembly** — GSD reads `ROADMAP.md`, `REQUIREMENTS.md`, and any existing `RESEARCH.md` for the phase. This context is bundled into a structured prompt so ultraplan has everything it needs without you copying anything manually. + +3. **Return-path instructions** — Before launching ultraplan, GSD prints the import command to your terminal so it's visible in your scroll-back buffer after the browser session ends: + ``` + When done: /gsd-import --from + ``` + +4. **Ultraplan launches** — The `/ultraplan` command hands off to the browser. Use the outline sidebar and inline comments to review and refine the draft. + +5. **Save the plan** — When satisfied, click **Cancel** in Claude Code. Claude Code saves the plan to a local file and returns you to the terminal. + +6. **Import back into GSD** — Run the import command that was printed in step 3: + ```bash + /gsd-import --from /path/to/saved-plan.md + ``` + This runs conflict detection against `PROJECT.md`, converts the plan to GSD format, validates it with `gsd-plan-checker`, updates `ROADMAP.md`, and commits — the same path as any external plan import. + +### What gets produced + +| Step | Output | +|------|--------| +| After ultraplan | External plan file (saved by Claude Code) | +| After `/gsd-import` | `{phase}-{N}-PLAN.md` in `.planning/phases/` | + +### What this command does NOT do + +- Write `PLAN.md` files directly — all writes go through `/gsd-import` +- Replace `/gsd-plan-phase` — local planning is unaffected and remains the default +- Run research agents — if you need `RESEARCH.md` first, run `/gsd-plan-phase --skip-verify` or a research-only pass before using this command + +### Troubleshooting + +**"ultraplan is not available in this runtime"** +You're running GSD outside of Claude Code. Switch to a Claude Code terminal session, or use `/gsd-plan-phase` instead. + +**Ultraplan browser session never opened** +Check your Claude Code version: `claude --version`. Requires v2.1.91+. Update with `claude update`. + +**`/gsd-import` reports conflicts** +Ultraplan may have proposed something that contradicts a decision in `PROJECT.md`. The import step will prompt you to resolve each conflict before writing anything. + +**Plan checker fails after import** +The imported plan has structural issues. Review the checker output, edit the saved file to fix them, and re-run `/gsd-import --from `. + +### Related commands + +- [`/gsd-plan-phase`](COMMANDS.md#gsd-plan-phase) — standard local planning (stable, all runtimes) +- [`/gsd-import`](COMMANDS.md#gsd-import) — import any external plan file into GSD diff --git a/docs/superpowers/specs/2026-04-17-ultraplan-phase-design.md b/docs/superpowers/specs/2026-04-17-ultraplan-phase-design.md new file mode 100644 index 00000000..277f7c2a --- /dev/null +++ b/docs/superpowers/specs/2026-04-17-ultraplan-phase-design.md @@ -0,0 +1,160 @@ +# Design: /gsd-ultraplan-phase [BETA] + +**Date:** 2026-04-17 +**Status:** Approved — ready for implementation +**Branch:** Beta feature, isolated from core plan pipeline + +--- + +## Summary + +A standalone `/gsd-ultraplan-phase` command that offloads GSD's research+plan phase to Claude Code's ultraplan cloud infrastructure. The plan drafts remotely while the terminal stays free, is reviewed in a rich browser UI with inline comments, then imports back into GSD via the existing `/gsd-import --from` workflow. + +This is a **beta of a beta**: ultraplan itself is in research preview, so this command is intentionally isolated from the core `/gsd-plan-phase` pipeline to prevent breakage if ultraplan changes. + +--- + +## Scope + +**In scope:** +- New `commands/gsd/ultraplan-phase.md` command +- New `get-shit-done/workflows/ultraplan-phase.md` workflow +- Runtime gate: Claude Code only (checks `$CLAUDE_CODE_VERSION`) +- Builds structured ultraplan prompt from GSD phase context +- Return path via existing `/gsd-import --from ` (no new import logic) + +**Out of scope (future):** +- Parallel next-phase planning during `/gsd-execute-phase` +- Auto-detection of ultraplan's saved file path +- Text mode / non-interactive fallback + +--- + +## Architecture + +```text +/gsd-ultraplan-phase [phase] + │ + ├─ Runtime gate (CLAUDE_CODE_VERSION check) + ├─ gsd-sdk query init.plan-phase → phase context + ├─ Build ultraplan prompt (phase scope + requirements + research) + ├─ Display return-path instructions card + └─ /ultraplan + │ + [cloud: user reviews, comments, revises] + │ + [browser: Approve → teleport back to terminal] + │ + [terminal: Cancel → saves to file] + │ + /gsd-import --from + │ + ├─ Conflict detection + ├─ GSD format conversion + ├─ gsd-plan-checker validation + ├─ ROADMAP.md update + └─ Commit +``` + +--- + +## Command File (`commands/gsd/ultraplan-phase.md`) + +Frontmatter: +- `name: gsd:ultraplan-phase` +- `description:` includes `[BETA]` marker +- `argument-hint: [phase-number]` +- `allowed-tools:` Read, Bash, Glob, Grep +- References: `@~/.claude/get-shit-done/workflows/ultraplan-phase.md`, ui-brand + +--- + +## Workflow Steps + +### 1. Banner +Display GSD `► ULTRAPLAN PHASE [BETA]` banner. + +### 2. Runtime Gate +```bash +echo $CLAUDE_CODE_VERSION +``` +If unset/empty: print error and exit. +```text +⚠ /gsd-ultraplan-phase requires Claude Code. + /ultraplan is not available in this runtime. + Use /gsd-plan-phase for local planning. +``` + +### 3. Initialize +```bash +INIT=$(gsd-sdk query init.plan-phase "$PHASE") +``` +Parse: phase number, phase name, phase slug, phase dir, roadmap path, requirements path, research path. + +If no `.planning/` exists: error — run `/gsd-new-project` first. + +### 4. Build Ultraplan Prompt +Construct a prompt that includes: +- Phase identification: `"Plan phase {N}: {phase name}"` +- Phase scope block from ROADMAP.md +- Requirements summary (if REQUIREMENTS.md exists) +- Research summary (if RESEARCH.md exists — reduces cloud redundancy) +- Output format instruction: produce a GSD PLAN.md with standard frontmatter fields + +### 5. Return-Path Instructions Card +Display prominently before triggering (visible in terminal scroll-back): +```text +When ◆ ultraplan ready: + 1. Open the session link in your browser + 2. Review, comment, and revise the plan + 3. When satisfied: "Approve plan and teleport back to terminal" + 4. At the terminal dialog: choose Cancel (saves plan to file) + 5. Run: /gsd-import --from +``` + +### 6. Trigger Ultraplan +```text +/ultraplan +``` + +--- + +## Return Path + +No new code needed. The user runs `/gsd-import --from ` after ultraplan saves the file. That workflow handles everything: conflict detection, GSD format conversion, plan-checker, ROADMAP update, commit. + +--- + +## Runtime Detection + +`$CLAUDE_CODE_VERSION` is set by Claude Code in the shell environment. If unset, the session is not Claude Code (Gemini CLI, Copilot, etc.) and `/ultraplan` does not exist. + +--- + +## Pricing + +Ultraplan runs as a standard Claude Code on the web session. For Pro/Max subscribers this is included in the subscription — no extra usage billing (unlike ultrareview which bills $5–20/run). No cost gate needed. + +--- + +## Beta Markers + +- `[BETA]` in command description +- `⚠ BETA` in workflow banner +- Comment in workflow noting ultraplan is in research preview + +--- + +## Test Coverage + +`tests/ultraplan-phase.test.cjs` — structural assertions covering: +- File existence (command + workflow) +- Command frontmatter completeness (name, description with `[BETA]`, argument-hint) +- Command references workflow +- Workflow has runtime gate (`CLAUDE_CODE_VERSION`) +- Workflow has beta warning +- Workflow has init step (gsd-sdk query) +- Workflow builds ultraplan prompt with phase context +- Workflow triggers `/ultraplan` +- Workflow has return-path instructions (Cancel path, `/gsd-import --from`) +- Workflow does NOT directly implement plan writing (delegates to `/gsd-import`) diff --git a/get-shit-done/workflows/sketch.md b/get-shit-done/workflows/sketch.md index 8efbd543..72f8e1bc 100644 --- a/get-shit-done/workflows/sketch.md +++ b/get-shit-done/workflows/sketch.md @@ -53,7 +53,9 @@ COMMIT_DOCS=$(gsd-sdk query config-get commit_docs 2>/dev/null || echo "true") **Otherwise:** -Before sketching anything, explore the design intent through conversation. Ask one question at a time using AskUserQuestion, with a paragraph of context and reasoning for each. +**Text mode:** If TEXT_MODE is enabled (set in the banner step), replace AskUserQuestion calls with plain-text numbered lists — emit the options and ask the user to type the number of their choice. + +Before sketching anything, explore the design intent through conversation. Ask one question at a time — using AskUserQuestion in normal mode, or a plain-text numbered list if TEXT_MODE is active — with a paragraph of context and reasoning for each. **Questions to cover (adapt to what the user has already shared):** diff --git a/get-shit-done/workflows/ultraplan-phase.md b/get-shit-done/workflows/ultraplan-phase.md new file mode 100644 index 00000000..f9fde052 --- /dev/null +++ b/get-shit-done/workflows/ultraplan-phase.md @@ -0,0 +1,189 @@ +# Ultraplan Phase Workflow [BETA] + +Offload GSD's plan phase to Claude Code's ultraplan cloud infrastructure. + +⚠ **BETA feature.** Ultraplan is in research preview and may change. This workflow is +intentionally isolated from /gsd-plan-phase so upstream changes to ultraplan cannot +affect the core planning pipeline. + +--- + + + +Display the stage banner: + +```text +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + GSD ► ULTRAPLAN PHASE ⚠ BETA +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +Ultraplan is in research preview (Claude Code v2.1.91+). +Use /gsd-plan-phase for stable local planning. +``` + + + +--- + + + +Check that the session is running inside Claude Code: + +```bash +echo "$CLAUDE_CODE_VERSION" +``` + +If the output is empty or unset, display the following error and exit: + +```text +╔══════════════════════════════════════════════════════════════╗ +║ RUNTIME ERROR ║ +╚══════════════════════════════════════════════════════════════╝ + +/gsd-ultraplan-phase requires Claude Code. +ultraplan is not available in this runtime. + +Use /gsd-plan-phase for local planning instead. +``` + + + +--- + + + +Parse phase number from `$ARGUMENTS`. If no phase number is provided, detect the next +unplanned phase from the roadmap (same logic as /gsd-plan-phase). + +Load GSD phase context: + +```bash +INIT=$(gsd-sdk query init.plan-phase "$PHASE") +if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi +``` + +Parse JSON for: `phase_found`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, +`phase_dir`, `roadmap_path`, `requirements_path`, `research_path`, `planning_exists`. + +**If `planning_exists` is false:** Error and exit: + +```text +No .planning directory found. Initialize the project first: + +/gsd-new-project +``` + +**If `phase_found` is false:** Error with the phase number provided and exit. + +Display detected phase: + +```text +Phase {N}: {phase name} +``` + + + +--- + + + +Build the ultraplan prompt from GSD context. + +1. Read the phase scope from ROADMAP.md — extract the goal, deliverables, and scope for + the target phase. + +2. Read REQUIREMENTS.md if it exists (`requirements_path` is not null) — extract a + concise summary (key requirements relevant to this phase, not the full document). + +3. Read RESEARCH.md if it exists (`research_path` is not null) — extract a concise + summary of technical findings. Including this reduces redundant cloud research. + +Construct the prompt: + +```text +Plan phase {phase_number}: {phase_name} + +## Phase Scope (from ROADMAP.md) + +{phase scope block extracted from ROADMAP.md} + +## Requirements Context + +{requirements summary, or "No REQUIREMENTS.md found — infer from phase scope."} + +## Existing Research + +{research summary, or "No RESEARCH.md found — research from scratch."} + +## Output Format + +Produce a GSD PLAN.md with the following YAML frontmatter: + +--- +phase: "{padded_phase}-{phase_slug}" +plan: "{padded_phase}-01" +type: "feature" +wave: 1 +depends_on: [] +files_modified: [] +autonomous: true +must_haves: + truths: [] + artifacts: [] +--- + +Then a ## Plan section with numbered tasks. Each task should have: +- A clear imperative title +- Files to create or modify +- Specific implementation steps + +Keep the plan focused and executable. +``` + + + +--- + + + +Display the return-path instructions **before** triggering ultraplan so they are visible +in the terminal scroll-back after ultraplan launches: + +```text +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + WHEN THE PLAN IS READY — WHAT TO DO +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +When ◆ ultraplan ready appears in your terminal: + + 1. Open the session link in your browser + 2. Review the plan — use inline comments and emoji reactions to give feedback + 3. Ask Claude to revise until you're satisfied + 4. Click "Approve plan and teleport back to terminal" + 5. At the terminal dialog, choose Cancel ← saves the plan to a file + 6. Note the file path Claude prints + 7. Run: /gsd-import --from + +/gsd-import will run conflict detection, convert to GSD format, +validate via plan-checker, update ROADMAP.md, and commit. + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +Launching ultraplan for Phase {N}: {phase_name}... +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +``` + + + +--- + + + +Trigger ultraplan with the constructed prompt: + +```text +/ultraplan {constructed prompt from build_prompt step} +``` + +Your terminal will show a `◇ ultraplan` status indicator while the remote session works. +Use `/tasks` to open the detail view with the session link, agent activity, and a stop action. + + diff --git a/tests/read-guard.test.cjs b/tests/read-guard.test.cjs index 5fa54578..182fe011 100644 --- a/tests/read-guard.test.cjs +++ b/tests/read-guard.test.cjs @@ -28,7 +28,7 @@ const HOOK_PATH = path.join(__dirname, '..', 'hooks', 'gsd-read-guard.js'); */ function runHook(payload, envOverrides = {}) { const input = JSON.stringify(payload); - // Sanitize CLAUDE_SESSION_ID so positive-path tests work inside Claude Code sessions + // Sanitize Claude Code env vars so positive-path tests work inside Claude Code sessions const env = { ...process.env, CLAUDE_SESSION_ID: '', CLAUDECODE: '', ...envOverrides }; try { const stdout = execFileSync(process.execPath, [HOOK_PATH], { diff --git a/tests/ultraplan-phase.test.cjs b/tests/ultraplan-phase.test.cjs new file mode 100644 index 00000000..660591e0 --- /dev/null +++ b/tests/ultraplan-phase.test.cjs @@ -0,0 +1,189 @@ +/** + * /gsd-ultraplan-phase [BETA] Tests + * + * Structural assertions for the ultraplan-phase command and workflow files. + * This command offloads GSD plan phase to Claude Code's ultraplan cloud infrastructure. + */ + +'use strict'; + +const { describe, test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); + +const CMD_PATH = path.join(__dirname, '..', 'commands', 'gsd', 'ultraplan-phase.md'); +const WF_PATH = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'ultraplan-phase.md'); + +// ─── File Existence ──────────────────────────────────────────────────────────── + +describe('ultraplan-phase file existence', () => { + test('command file exists', () => { + assert.ok(fs.existsSync(CMD_PATH), 'commands/gsd/ultraplan-phase.md should exist'); + }); + + test('workflow file exists', () => { + assert.ok(fs.existsSync(WF_PATH), 'get-shit-done/workflows/ultraplan-phase.md should exist'); + }); +}); + +// ─── Command Frontmatter ─────────────────────────────────────────────────────── + +describe('ultraplan-phase command frontmatter', () => { + const content = fs.readFileSync(CMD_PATH, 'utf-8'); + + test('has correct name field', () => { + assert.match(content, /^name:\s*gsd:ultraplan-phase$/m); + }); + + test('description marks feature as BETA', () => { + assert.match(content, /^description:.*\[BETA\]/m); + }); + + test('has argument-hint', () => { + assert.match(content, /^argument-hint:/m); + }); +}); + +// ─── Command References ──────────────────────────────────────────────────────── + +describe('ultraplan-phase command references', () => { + const content = fs.readFileSync(CMD_PATH, 'utf-8'); + + test('references the ultraplan-phase workflow', () => { + assert.ok( + content.includes('@~/.claude/get-shit-done/workflows/ultraplan-phase.md'), + 'command should reference ultraplan-phase workflow' + ); + }); + + test('references ui-brand', () => { + assert.ok(content.includes('ui-brand'), 'command should reference ui-brand'); + }); +}); + +// ─── Workflow: Beta Marker ───────────────────────────────────────────────────── + +describe('ultraplan-phase workflow beta marker', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('workflow displays a BETA warning', () => { + assert.ok(content.includes('BETA') || content.includes('beta'), 'workflow should display a BETA warning'); + }); + + test('workflow notes ultraplan is in research preview', () => { + assert.ok(content.includes('research preview') || content.includes('preview'), 'workflow should note ultraplan is in research preview'); + }); +}); + +// ─── Workflow: Runtime Gate ──────────────────────────────────────────────────── + +describe('ultraplan-phase workflow runtime gate', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('checks CLAUDE_CODE_VERSION to detect Claude Code runtime', () => { + assert.ok(content.includes('CLAUDE_CODE_VERSION'), 'workflow must gate on CLAUDE_CODE_VERSION env var'); + }); + + test('error message references /gsd-plan-phase as local alternative', () => { + assert.ok( + content.includes('gsd-plan-phase'), + 'error message should direct users to /gsd-plan-phase as the local alternative' + ); + }); +}); + +// ─── Workflow: Initialization ────────────────────────────────────────────────── + +describe('ultraplan-phase workflow initialization', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('loads GSD phase context via gsd-sdk query init.plan-phase', () => { + assert.ok(content.includes('gsd-sdk query init.plan-phase'), 'workflow must load phase context via gsd-sdk query init.plan-phase'); + }); + + test('handles missing .planning directory', () => { + assert.ok( + content.includes('gsd-new-project') || content.includes('/gsd-new-project'), + 'workflow should direct user to /gsd-new-project when .planning is missing' + ); + }); +}); + +// ─── Workflow: Ultraplan Prompt ──────────────────────────────────────────────── + +describe('ultraplan-phase workflow prompt construction', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('includes phase scope from ROADMAP in ultraplan prompt', () => { + assert.ok( + content.includes('ROADMAP') || content.includes('phase scope') || content.includes('phase_name'), + 'workflow should include phase scope from ROADMAP.md in the ultraplan prompt' + ); + }); + + test('includes REQUIREMENTS context in ultraplan prompt', () => { + assert.ok(content.includes('REQUIREMENTS'), 'workflow should include requirements context in the ultraplan prompt'); + }); + + test('includes existing RESEARCH when available', () => { + assert.ok( + content.includes('RESEARCH') || content.includes('research_path'), + 'workflow should include existing research in the ultraplan prompt' + ); + }); +}); + +// ─── Workflow: Ultraplan Trigger ─────────────────────────────────────────────── + +describe('ultraplan-phase workflow ultraplan trigger', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('triggers /ultraplan command', () => { + assert.ok(content.includes('/ultraplan'), 'workflow must trigger /ultraplan'); + }); +}); + +// ─── Workflow: Return Path Instructions ─────────────────────────────────────── + +describe('ultraplan-phase workflow return path', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('instructs user to choose Cancel to save plan to file', () => { + assert.ok(content.includes('Cancel'), 'workflow must instruct user to choose Cancel to save the plan to a file'); + }); + + test('directs user to run /gsd-import --from after ultraplan completes', () => { + assert.ok(content.includes('gsd-import'), 'workflow must direct user to run /gsd-import --from with the saved file path'); + }); + + test('mentions the --from flag for gsd-import', () => { + assert.ok(content.includes('--from'), 'workflow should reference /gsd-import --from '); + }); + + test('return-path instructions appear before the /ultraplan trigger', () => { + const ultraplanTriggerIndex = content.indexOf('/ultraplan'); + const importIndex = content.indexOf('gsd-import'); + assert.ok( + importIndex < ultraplanTriggerIndex, + 'return-path instructions (gsd-import) must appear before /ultraplan trigger so they are visible in scroll-back' + ); + }); +}); + +// ─── Workflow: Isolation from Core Pipeline ──────────────────────────────────── + +describe('ultraplan-phase workflow isolation', () => { + const content = fs.readFileSync(WF_PATH, 'utf-8'); + + test('does NOT directly write PLAN.md files', () => { + assert.ok( + !content.includes('write PLAN.md') && !content.includes('Write(\'.planning'), + 'workflow must NOT directly write PLAN.md — delegates to /gsd-import --from' + ); + }); + + test('does NOT reference ultrareview', () => { + assert.ok(!content.includes('ultrareview'), 'workflow must not reference ultrareview'); + }); +});