feat: /gsd-ultraplan-phase [BETA] — offload plan phase to Claude Code ultraplan (#2378)

* docs: add design spec for /gsd-ultraplan-phase beta command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add /gsd-ultraplan-phase [BETA] command

Offloads GSD plan phase to Claude Code's ultraplan cloud infrastructure.
Plan drafts remotely while terminal stays free; browser UI for inline
comments and revisions; imports back via existing /gsd-import --from.

Intentionally isolated from /gsd-plan-phase so upstream ultraplan changes
cannot break the core planning pipeline.

Closes #2374

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: resolve 5 pre-existing test failures before PR

- ARCHITECTURE.md: update command count 75→80 and workflow count 72→77
  (stale doc counts; also incremented by new ultraplan-phase files)
- sketch.md: add TEXT_MODE plain-text fallback for AskUserQuestion (#2012)
- read-guard.test.cjs: clear CLAUDECODE env var alongside CLAUDE_SESSION_ID
  so positive-path hook tests pass when run inside a Claude Code session

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add BETA.md with /gsd-ultraplan-phase user documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: address CodeRabbit review — MD040 fence labels and sketch.md TEXT_MODE duplicate

- Add language identifiers to all unlabeled fenced blocks in
  ultraplan-phase.md and design spec (resolves MD040)
- Remove duplicate TEXT_MODE explanation from sketch.md mood_intake step
  (was identical to the banner step definition)
- Make AskUserQuestion conditional explicit in mood_intake prose

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-04-17 14:45:03 -04:00
committed by GitHub
parent 2e97dee0d0
commit 794f7e1b0b
8 changed files with 677 additions and 6 deletions

View File

@@ -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
---
<objective>
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.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/ultraplan-phase.md
@~/.claude/get-shit-done/references/ui-brand.md
</execution_context>
<context>
$ARGUMENTS
</context>
<process>
Execute the ultraplan-phase workflow end-to-end.
</process>

View File

@@ -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

98
docs/BETA.md Normal file
View File

@@ -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 <path-to-saved-plan>
```
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 <same-file>`.
### 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

View File

@@ -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 <file>` (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 <prompt>
[cloud: user reviews, comments, revises]
[browser: Approve → teleport back to terminal]
[terminal: Cancel → saves to file]
/gsd-import --from <saved file path>
├─ 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 <the file path Claude prints>
```
### 6. Trigger Ultraplan
```text
/ultraplan <constructed prompt>
```
---
## Return Path
No new code needed. The user runs `/gsd-import --from <path>` 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 $520/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`)

View File

@@ -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):**

View File

@@ -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.
---
<step name="banner">
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.
```
</step>
---
<step name="runtime_gate">
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.
```
</step>
---
<step name="initialize">
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}
```
</step>
---
<step name="build_prompt">
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.
```
</step>
---
<step name="return_path_card">
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 <the file path>
/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}...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
</step>
---
<step name="trigger">
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.
</step>

View File

@@ -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], {

View File

@@ -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 <file-path>');
});
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');
});
});