* feat(#2790): consolidate 86 gsd-* skills to 59 — zero functional loss Closes #2790 - `capture.md` — absorbs add-todo (default), note (--note), add-backlog (--backlog), plant-seed (--seed), check-todos (--list) - `phase.md` — absorbs add-phase (default), insert-phase (--insert), remove-phase (--remove), edit-phase (--edit) - `config.md` — absorbs settings-advanced (--advanced), settings-integrations (--integrations), set-profile (--profile); settings.md retained as-is - `workspace.md` — absorbs new-workspace (--new), list-workspaces (--list), remove-workspace (--remove) - `update.md` — adds --sync (absorbs sync-skills) and --reapply (absorbs reapply-patches) - `sketch.md` — adds --wrap-up (absorbs sketch-wrap-up) - `spike.md` — adds --wrap-up (absorbs spike-wrap-up) - `map-codebase.md` — adds --fast (absorbs scan) and --query (absorbs intel) - `code-review.md` — adds --fix (absorbs code-review-fix) - `progress.md` — adds --next (absorbs next) and --do (absorbs do) join-discord, research-phase, session-report, from-gsd2, analyze-dependencies, list-phase-assumptions, plan-milestone-gaps autonomous.md: updated Skill(skill="gsd:code-review-fix") → Skill(skill="gsd:code-review", args="--fix --auto") to match the consolidated skill name - New: tests/enh-2790-skill-consolidation.test.cjs (48 tests) - Updated: 14 existing test files redirected from deleted command paths to their consolidated equivalents - docs/INVENTORY.md: Commands count 86→59, ghost rows removed, new consolidated rows added - docs/INVENTORY-MANIFEST.json: regenerated to match filesystem Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(#2790): add CHANGELOG entry for skill consolidation * docs(#2790): update COMMANDS.md for 86→59 skill consolidation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#2790): address CodeRabbit review findings - CHANGELOG.md: add --next alongside --do in progress flag list - config.md: remove trailing space from --profile code span (MD038) - COMMANDS.md: add required descriptions to /gsd-phase examples; /gsd-phase without args errors, not interactive - COMMANDS.md: add --next and --do to /gsd-progress flags table + examples - test: convert content.includes('--reapply') to structural frontmatter parse; add allow-test-rule comment for workflow content assertions - test: replace redundant existsSync duplicate with assertion that verifies the full consolidated flag surface (--sync | --reapply) in argument-hint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#2790): restore reapply-patches workflow and strengthen test assertions - Create get-shit-done/workflows/reapply-patches.md: the #2790 consolidation deleted the 14K combined command+workflow file (reapply-patches.md) but update.md already referenced the workflow via execution_context_extended. Restoring it fixes a silent behavioral gap where --reapply had no workflow to load. Includes full three-way merge logic, hunk verification table (Step 4), and the Hunk Verification Gate (Step 5) that blocks cleanup until all user-added hunks are confirmed present in the merged output. - Fix update.md: /gsd-reapply-patches → /gsd-update --reapply (stale ref) - Fix reapply-verify-hunks.test.cjs: was checking existsSync(update.md) 8×; now points to the workflow file and asserts real behavioral content (Post-merge verification, Hunk presence check, Line-count check, backup reference, per-file tracking, structural ordering) - Fix reapply-patches.test.cjs: replace content.includes() stubs with frontmatter-parsed argument-hint assertions; replace 4 existsSync(update.md) no-ops with real assertions against the workflow content - Fix edit-phase.test.cjs: /gsd-edit-phase → /gsd-phase (COMMANDS.md now documents the consolidated command with --edit flag) - Fix next-safety-gates.test.cjs: split OR predicates into independent assertions — --next in progress.md and --force in next.md workflow - Fix workspace.test.cjs: add allow-test-rule comment for routing content checks (command routing text IS the deployed behavioral contract) - Fix bug-2439 test: strengthen pre-flight assertion to verify gsd-sdk is referenced (not just --profile) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address CodeRabbit review findings (CR round 2) - INVENTORY.md: update sync-skills.md row to reference /gsd-update --sync instead of stale /gsd-sync-skills (absorbed in #2790) - enh-2380-sync-skills.test.cjs: align INVENTORY.md assertion with the corrected reference; was asserting the old /gsd-sync-skills name while the manifest test correctly asserted /gsd-update, creating conflicting expectations in the same suite - reapply-verify-hunks.test.cjs: add explicit notEqual(-1) assertions for all three anchors before the ordering check so a missing anchor produces a clear failure instead of a false positive (writeIdx=-1 < verifyIdx=5 is true) - bug-2439-set-profile-gsd-sdk-preflight.test.cjs: defer fs.readFileSync until after the existence assertion; eager describe-level read caused the suite to crash before the existence test could run, making it effectively dead code Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#2790): address CR — INVENTORY routing + reapply test contract wording Two unresolved CodeRabbit findings (Major): - docs/INVENTORY.md: workflow-file table still pointed at obsolete /gsd-do, /gsd-next, /gsd-note, /gsd-add-todo, /gsd-add-backlog, /gsd-check-todos, /gsd-plant-seed slash commands. Re-route to the consolidated /gsd-progress (--next, --do) and /gsd-capture (--note, --backlog, --seed, --list) so the inventory is internally consistent. - tests/reapply-verify-hunks.test.cjs: 'verification tracks per-file status' asserted on phrasing that doesn't appear in reapply-patches.md (the 'per-file' substring only matched accidentally via 'sequential integer per file'). Switch to the actual contract text — Hunk Verification Table, one row per hunk per file, verified column. * test(#2790): update CR-INTEGRATION tests for consolidated --fix invocation After the merge of main (which carries #2843's hyphen-form fix), the consolidation in this branch absorbs gsd-code-review-fix into gsd-code-review as the --fix flag. Update the two CR-INTEGRATION tests that previously asserted on the standalone gsd-code-review-fix skill name to instead assert on a gsd-code-review invocation carrying --fix in its arg tokens. Tests still parse Skill() invocations structurally; only the asserted skill-name + arg-token shape changed. * test(#2790): scope success_criteria check to the <success_criteria> block CodeRabbit nitpick: 'success criteria includes verification' did a whole-file substring check, which can false-pass if the phrase appears elsewhere in the document. Extract the <success_criteria>...</success_criteria> block first via extractTagBlock() and assert against that scope only. * fix(#2790): post-rebase reconciliation with main - INVENTORY.md/JSON: add reapply-patches workflow row + bump count to 85 - autonomous.md: switch consolidated --fix invocation to hyphen Skill name - analyze-dependencies test: assert COMMANDS.md does NOT document the consolidated-away /gsd-analyze-dependencies entry (was: bare .includes()) * fix(#2790): address remaining CR findings — strengthen contract tests Doc-fixes: - INVENTORY.md: route transition.md & edit-phase.md rows to consolidated /gsd-progress --next and /gsd-phase --edit (was: deleted /gsd-next, /gsd-edit-phase) - config.md --profile branch: document #2439 pre-flight `command -v gsd-sdk` guard + install hint BEFORE the gsd-sdk invocation (closes opaque "command not found: gsd-sdk" regression path) Test discipline (no-source-grep contract): - bug-2439: replace bare `content.includes('gsd-sdk')` with structured parse of <context> block + --profile branch; assert pre-flight token, install hint, #2439 citation, and ordering vs gsd-sdk invocation - edit-phase: parse INVENTORY.md edit-phase.md row's "Invoked by" column and assert `/gsd-phase --edit` (not the deleted /gsd-edit-phase) - next-safety-gates: tighten `--next` documentation contract — require --next AND --force AND completeness routing (was OR-based, passed when only --next present) - reapply-patches: parse argument-hint flag list structurally; scan ALL <execution_context*> blocks for the @-include of reapply-patches.md; parse Hunk Verification Table header columns directly; locate Step 5 via heading parsing then assert (i) table reference, (ii) verified=no gate, (iii) STOP/halt directive, (iv) explicit absent-table halt path - workspace: parse frontmatter, tokenize argument-hint across multiple bracketed segments, parse @-include targets from <execution_context> rather than substring-matching the file body --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
22
CHANGELOG.md
22
CHANGELOG.md
@@ -50,6 +50,28 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
`commands/gsd/*.md` description exceeds 100 chars. Run via `npm run lint:descriptions`.
|
||||
(#2789)
|
||||
|
||||
### Changed
|
||||
- **Skill surface consolidated from 86 → 59 `commands/gsd/*.md` entries** — four new
|
||||
grouped skills replace clusters of micro-skills: `capture` (add-todo, note, add-backlog,
|
||||
plant-seed, check-todos), `phase` (add-phase, insert-phase, remove-phase, edit-phase),
|
||||
`config` (settings-advanced, settings-integrations, set-profile), `workspace`
|
||||
(new-workspace, list-workspaces, remove-workspace). Six parent skills absorb wrap-up
|
||||
and sub-operations as flags: `update --sync/--reapply`, `sketch --wrap-up`,
|
||||
`spike --wrap-up`, `map-codebase --fast/--query`, `code-review --fix`,
|
||||
`progress --do/--next`. Zero functional loss. (#2790)
|
||||
- **`autonomous.md` corrected** — was invoking deleted `gsd:code-review-fix`; now calls
|
||||
`gsd:code-review --fix`. (#2790)
|
||||
|
||||
### Removed
|
||||
- **31 micro-skills deleted** — absorbed into consolidated parents or removed outright:
|
||||
add-todo, note, add-backlog, plant-seed, check-todos, add-phase, insert-phase,
|
||||
remove-phase, edit-phase, settings-advanced, settings-integrations, set-profile,
|
||||
new-workspace, list-workspaces, remove-workspace, sync-skills, reapply-patches,
|
||||
sketch-wrap-up, spike-wrap-up, scan, intel, code-review-fix, next, do,
|
||||
join-discord, research-phase, session-report, from-gsd2, analyze-dependencies,
|
||||
list-phase-assumptions, plan-milestone-gaps. All functionality preserved via flags on
|
||||
consolidated skills. (#2790)
|
||||
|
||||
### Fixed
|
||||
- **GSD slash command namespace drift cleaned up across docs, workflows, and autocomplete** — remaining active `/gsd:<cmd>` references now use canonical `/gsd-<cmd>`, escaped workflow `Skill(skill=\"gsd:...\")` prompts now use hyphenated skill names, `scripts/fix-slash-commands.cjs` rewrites retired colon syntax to hyphen syntax, and the extract-learnings command file now uses `extract-learnings.md` so generated Claude/Qwen skill autocomplete exposes `gsd-extract-learnings` instead of `gsd-extract_learnings`. (#2855)
|
||||
- **`extractCurrentMilestone` no longer truncates ROADMAP.md at heading-like lines inside fenced code blocks** — the milestone-end search now scans line-by-line while tracking ` ``` ` / `~~~` fence state, so a line like `# Ops runbook (v1.0 compat)` inside a code block no longer acts as a milestone boundary. Previously, any phase defined after such a block was invisible to `roadmap analyze`, `roadmap get-phase`, `/gsd-autonomous`, and all phase-number commands. (#2787)
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
---
|
||||
name: gsd:add-backlog
|
||||
description: Add an idea to the backlog parking lot (999.x numbering)
|
||||
argument-hint: <description>
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add a backlog item to the roadmap using 999.x numbering. Backlog items are
|
||||
unsequenced ideas that aren't ready for active planning — they live outside
|
||||
the normal phase sequence and accumulate context over time.
|
||||
</objective>
|
||||
|
||||
<process>
|
||||
|
||||
1. **Read ROADMAP.md** to find existing backlog entries:
|
||||
```bash
|
||||
cat .planning/ROADMAP.md
|
||||
```
|
||||
|
||||
2. **Find next backlog number:**
|
||||
```bash
|
||||
NEXT=$(gsd-sdk query phase.next-decimal 999 --raw)
|
||||
```
|
||||
If no 999.x phases exist, start at 999.1.
|
||||
|
||||
3. **Add to ROADMAP.md** under a `## Backlog` section. If the section doesn't exist, create it at the end.
|
||||
Write the ROADMAP entry BEFORE creating the directory — this ensures directory existence is always
|
||||
a reliable indicator that the phase is already registered, which prevents false duplicate detection
|
||||
in any hook that checks for existing 999.x directories (#2280):
|
||||
|
||||
```markdown
|
||||
## Backlog
|
||||
|
||||
### Phase {NEXT}: {description} (BACKLOG)
|
||||
|
||||
**Goal:** [Captured for future planning]
|
||||
**Requirements:** TBD
|
||||
**Plans:** 0 plans
|
||||
|
||||
Plans:
|
||||
- [ ] TBD (promote with /gsd-review-backlog when ready)
|
||||
```
|
||||
|
||||
4. **Create the phase directory:**
|
||||
```bash
|
||||
SLUG=$(gsd-sdk query generate-slug "$ARGUMENTS" --raw)
|
||||
mkdir -p ".planning/phases/${NEXT}-${SLUG}"
|
||||
touch ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
|
||||
```
|
||||
|
||||
5. **Commit:**
|
||||
```bash
|
||||
gsd-sdk query commit "docs: add backlog item ${NEXT} — ${ARGUMENTS}" --files .planning/ROADMAP.md ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
|
||||
```
|
||||
|
||||
6. **Report:**
|
||||
```
|
||||
## 📋 Backlog Item Added
|
||||
|
||||
Phase {NEXT}: {description}
|
||||
Directory: .planning/phases/{NEXT}-{slug}/
|
||||
|
||||
This item lives in the backlog parking lot.
|
||||
Use /gsd-discuss-phase {NEXT} to explore it further.
|
||||
Use /gsd-review-backlog to promote items to active milestone.
|
||||
```
|
||||
|
||||
</process>
|
||||
|
||||
<notes>
|
||||
- 999.x numbering keeps backlog items out of the active phase sequence
|
||||
- Phase directories are created immediately, so /gsd-discuss-phase and /gsd-plan-phase work on them
|
||||
- No `Depends on:` field — backlog items are unsequenced by definition
|
||||
- Sparse numbering is fine (999.1, 999.3) — always uses next-decimal
|
||||
</notes>
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
name: gsd:add-phase
|
||||
description: Add phase to end of current milestone in roadmap
|
||||
argument-hint: <description>
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add a new integer phase to the end of the current milestone in the roadmap.
|
||||
|
||||
Routes to the add-phase workflow which handles:
|
||||
- Phase number calculation (next sequential integer)
|
||||
- Directory creation with slug generation
|
||||
- Roadmap structure updates
|
||||
- STATE.md roadmap evolution tracking
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/add-phase.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS (phase description)
|
||||
|
||||
Roadmap and state are resolved in-workflow via `init phase-op` and targeted tool calls.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
**Follow the add-phase workflow** from `@~/.claude/get-shit-done/workflows/add-phase.md`.
|
||||
|
||||
The workflow handles all logic including:
|
||||
1. Argument parsing and validation
|
||||
2. Roadmap existence checking
|
||||
3. Current milestone identification
|
||||
4. Next phase number calculation (ignoring decimals)
|
||||
5. Slug generation from description
|
||||
6. Phase directory creation
|
||||
7. Roadmap entry insertion
|
||||
8. STATE.md updates
|
||||
</process>
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: gsd:add-todo
|
||||
description: Capture idea or task as todo from current conversation context
|
||||
argument-hint: [optional description]
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Capture an idea, task, or issue that surfaces during a GSD session as a structured todo for later work.
|
||||
|
||||
Routes to the add-todo workflow which handles:
|
||||
- Directory structure creation
|
||||
- Content extraction from arguments or conversation
|
||||
- Area inference from file paths
|
||||
- Duplicate detection and resolution
|
||||
- Todo file creation with frontmatter
|
||||
- STATE.md updates
|
||||
- Git commits
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/add-todo.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS (optional todo description)
|
||||
|
||||
State is resolved in-workflow via `init todos` and targeted reads.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
**Follow the add-todo workflow** from `@~/.claude/get-shit-done/workflows/add-todo.md`.
|
||||
|
||||
The workflow handles all logic including:
|
||||
1. Directory ensuring
|
||||
2. Existing area checking
|
||||
3. Content extraction (arguments or conversation)
|
||||
4. Area inference
|
||||
5. Duplicate checking
|
||||
6. File creation with slug generation
|
||||
7. STATE.md updates
|
||||
8. Git commits
|
||||
</process>
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
name: gsd:analyze-dependencies
|
||||
description: Analyze phase dependencies and suggest Depends on entries for ROADMAP.md
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- Glob
|
||||
- Grep
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Analyze the phase dependency graph for the current milestone. For each phase pair, determine if there is a dependency relationship based on:
|
||||
- File overlap (phases that modify the same files must be ordered)
|
||||
- Semantic dependencies (a phase that uses an API built by another phase)
|
||||
- Data flow (a phase that consumes output from another phase)
|
||||
|
||||
Then suggest `Depends on` updates to ROADMAP.md.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/analyze-dependencies.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
No arguments required. Requires an active milestone with ROADMAP.md.
|
||||
|
||||
Run this command BEFORE `/gsd-manager` to fill in missing `Depends on` fields and prevent merge conflicts from unordered parallel execution.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the analyze-dependencies workflow from @~/.claude/get-shit-done/workflows/analyze-dependencies.md end-to-end.
|
||||
Present dependency suggestions clearly and apply confirmed updates to ROADMAP.md.
|
||||
</process>
|
||||
62
commands/gsd/capture.md
Normal file
62
commands/gsd/capture.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
name: gsd:capture
|
||||
description: Capture ideas, tasks, notes, and seeds to their destination
|
||||
argument-hint: "[--note | --backlog | --seed | --list] [text]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
- Glob
|
||||
- Grep
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Capture ideas, tasks, notes, and seeds to their appropriate destination in the GSD system.
|
||||
|
||||
Mode routing:
|
||||
- **default** (no flag): Capture as a structured todo for later work → add-todo workflow
|
||||
- **--note**: Zero-friction idea capture (append/list/promote) → note workflow
|
||||
- **--backlog**: Add an idea to the backlog parking lot (999.x numbering) → add-backlog workflow
|
||||
- **--seed**: Capture a forward-looking idea with trigger conditions → plant-seed workflow
|
||||
- **--list**: List pending todos and select one to work on → check-todos workflow
|
||||
</objective>
|
||||
|
||||
<routing>
|
||||
|
||||
| Flag | Destination | Workflow |
|
||||
|------|-------------|----------|
|
||||
| (none) | Structured todo in .planning/todos/ | add-todo |
|
||||
| --note | Timestamped note file, list, or promote | note |
|
||||
| --backlog | ROADMAP.md backlog section (999.x) | add-backlog |
|
||||
| --seed | .planning/seeds/SEED-NNN-slug.md | plant-seed |
|
||||
| --list | Interactive todo browser + action router | check-todos |
|
||||
|
||||
</routing>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/add-todo.md
|
||||
@~/.claude/get-shit-done/workflows/note.md
|
||||
@~/.claude/get-shit-done/workflows/add-backlog.md
|
||||
@~/.claude/get-shit-done/workflows/plant-seed.md
|
||||
@~/.claude/get-shit-done/workflows/check-todos.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--note`: strip the flag, pass remainder to note workflow
|
||||
- If it is `--backlog`: strip the flag, pass remainder to add-backlog workflow
|
||||
- If it is `--seed`: strip the flag, pass remainder to plant-seed workflow
|
||||
- If it is `--list`: pass remainder (optional area filter) to check-todos workflow
|
||||
- Otherwise: pass all of $ARGUMENTS to add-todo workflow
|
||||
</context>
|
||||
|
||||
<process>
|
||||
1. Parse the leading flag (if any) from $ARGUMENTS.
|
||||
2. Load and execute the appropriate workflow end-to-end based on the routing table above.
|
||||
3. Preserve all workflow gates from the target workflow (directory structure, duplicate detection, commits, etc.).
|
||||
</process>
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
name: gsd:check-todos
|
||||
description: List pending todos and select one to work on
|
||||
argument-hint: [area filter]
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
List all pending todos, allow selection, load full context for the selected todo, and route to appropriate action.
|
||||
|
||||
Routes to the check-todos workflow which handles:
|
||||
- Todo counting and listing with area filtering
|
||||
- Interactive selection with full context loading
|
||||
- Roadmap correlation checking
|
||||
- Action routing (work now, add to phase, brainstorm, create phase)
|
||||
- STATE.md updates and git commits
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/check-todos.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS (optional area filter)
|
||||
|
||||
Todo state and roadmap correlation are loaded in-workflow using `init todos` and targeted reads.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
**Follow the check-todos workflow** from `@~/.claude/get-shit-done/workflows/check-todos.md`.
|
||||
|
||||
The workflow handles all logic including:
|
||||
1. Todo existence checking
|
||||
2. Area filtering
|
||||
3. Interactive listing and selection
|
||||
4. Full context loading with file summaries
|
||||
5. Roadmap correlation checking
|
||||
6. Action offering and execution
|
||||
7. STATE.md updates
|
||||
8. Git commits
|
||||
</process>
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
name: gsd:code-review-fix
|
||||
description: Auto-fix issues found by code review in REVIEW.md; commits each fix atomically.
|
||||
argument-hint: "<phase-number> [--all] [--auto]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Glob
|
||||
- Grep
|
||||
- Write
|
||||
- Edit
|
||||
- Task
|
||||
---
|
||||
<objective>
|
||||
Auto-fix issues found by code review. Reads REVIEW.md from the specified phase, spawns gsd-code-fixer agent to apply fixes, and produces REVIEW-FIX.md summary.
|
||||
|
||||
Arguments:
|
||||
- Phase number (required) — which phase's REVIEW.md to fix (e.g., "2" or "02")
|
||||
- `--all` (optional) — include Info findings in fix scope (default: Critical + Warning only)
|
||||
- `--auto` (optional) — enable fix + re-review iteration loop, capped at 3 iterations
|
||||
|
||||
Output: {padded_phase}-REVIEW-FIX.md in phase directory + inline summary of fixes applied
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/code-review-fix.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Phase: $ARGUMENTS (first positional argument is phase number)
|
||||
|
||||
Optional flags parsed from $ARGUMENTS:
|
||||
- `--all` — Include Info findings in fix scope. Default behavior fixes Critical + Warning only.
|
||||
- `--auto` — Enable fix + re-review iteration loop. After applying fixes, re-run code-review at same depth. If new issues found, iterate. Cap at 3 iterations total. Without this flag, single fix pass only.
|
||||
|
||||
Context files (CLAUDE.md, REVIEW.md, phase state) are resolved inside the workflow via `gsd-sdk query init.phase-op` and delegated to agent via config blocks.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
This command is a thin dispatch layer. It parses arguments and delegates to the workflow.
|
||||
|
||||
Execute the code-review-fix workflow from @~/.claude/get-shit-done/workflows/code-review-fix.md end-to-end.
|
||||
|
||||
The workflow (not this command) enforces these gates:
|
||||
- Phase validation (before config gate)
|
||||
- Config gate check (workflow.code_review)
|
||||
- REVIEW.md existence check (error if missing)
|
||||
- REVIEW.md status check (skip if clean/skipped)
|
||||
- Agent spawning (gsd-code-fixer)
|
||||
- Iteration loop (if --auto, capped at 3 iterations)
|
||||
- Result presentation (inline summary + next steps)
|
||||
</process>
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:code-review
|
||||
description: Review source files changed during a phase for bugs, security issues, and code quality problems
|
||||
argument-hint: "<phase-number> [--depth=quick|standard|deep] [--files file1,file2,...]"
|
||||
argument-hint: "<phase-number> [--depth=quick|standard|deep] [--files file1,file2,...] [--fix [--all] [--auto]]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
@@ -22,6 +22,9 @@ Arguments:
|
||||
- standard: Per-file analysis with language-specific checks (~5-15 min, default)
|
||||
- deep: Cross-file analysis including import graphs and call chains (~15-30 min)
|
||||
- `--files file1,file2,...` (optional) — explicit comma-separated file list, skips SUMMARY/git scoping (highest precedence for scoping)
|
||||
- `--fix` (optional) — after review completes (or if REVIEW.md already exists), auto-apply fixes found. Spawns gsd-code-fixer agent. Accepts sub-flags:
|
||||
- `--all` — include Info findings in fix scope (default: Critical + Warning only)
|
||||
- `--auto` — enable fix + re-review iteration loop, capped at 3 iterations
|
||||
|
||||
Output: {padded_phase}-REVIEW.md in phase directory + inline summary of findings
|
||||
</objective>
|
||||
|
||||
57
commands/gsd/config.md
Normal file
57
commands/gsd/config.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
name: gsd:config
|
||||
description: Configure GSD settings — workflow toggles, advanced knobs, integrations, and model profile
|
||||
argument-hint: "[--advanced | --integrations | --profile <name>]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Configure GSD settings interactively with a single consolidated command.
|
||||
|
||||
Mode routing:
|
||||
- **default** (no flag): Common-case toggles (model, research, plan_check, verifier, branching) → settings workflow
|
||||
- **--advanced**: Power-user knobs (planning tuning, timeouts, branch templates, cross-AI execution) → settings-advanced workflow
|
||||
- **--integrations**: Third-party API keys, code-review CLI routing, agent-skill injection → settings-integrations workflow
|
||||
- **--profile <name>**: Switch model profile (quality|balanced|budget|inherit) → set-profile (inline)
|
||||
</objective>
|
||||
|
||||
<routing>
|
||||
|
||||
| Flag | Action | Workflow |
|
||||
|------|--------|----------|
|
||||
| (none) | Interactive 5-question common-case config prompt | settings |
|
||||
| --advanced | Power-user knobs: planning, execution, discussion, cross-AI, git, runtime | settings-advanced |
|
||||
| --integrations | API keys (Brave/Firecrawl/Exa), review CLI routing, agent skills | settings-integrations |
|
||||
| --profile <name> | Switch model profile without interactive prompt | gsd-sdk config-set-model-profile |
|
||||
|
||||
</routing>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/settings.md
|
||||
@~/.claude/get-shit-done/workflows/settings-advanced.md
|
||||
@~/.claude/get-shit-done/workflows/settings-integrations.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--advanced`: strip the flag, execute settings-advanced workflow
|
||||
- If it is `--integrations`: strip the flag, execute settings-integrations workflow
|
||||
- If it starts with `--profile`: extract the profile name (remainder after `--profile`), then:
|
||||
1. **Pre-flight check (#2439):** verify `gsd-sdk` is on PATH via `command -v gsd-sdk`.
|
||||
If absent, emit the install hint `Install GSD via 'npm i -g get-shit-done'` and stop —
|
||||
do NOT invoke `gsd-sdk` directly (avoids the opaque `command not found: gsd-sdk` failure).
|
||||
2. Run: `gsd-sdk query config-set-model-profile <profile-name> --raw` and display the output verbatim.
|
||||
- Otherwise: execute settings workflow (no argument needed)
|
||||
</context>
|
||||
|
||||
<process>
|
||||
1. Parse the leading flag (if any) from $ARGUMENTS.
|
||||
2. Load and execute the appropriate workflow end-to-end, or run the inline SDK command for --profile.
|
||||
3. Preserve all workflow gates from the target workflow.
|
||||
</process>
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
name: gsd:do
|
||||
description: Route freeform text to the right GSD command automatically
|
||||
argument-hint: "<description of what you want to do>"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Analyze freeform natural language input and dispatch to the most appropriate GSD command.
|
||||
|
||||
Acts as a smart dispatcher — never does the work itself. Matches intent to the best GSD command using routing rules, confirms the match, then hands off.
|
||||
|
||||
Use when you know what you want but don't know which `/gsd-*` command to run.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/do.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
$ARGUMENTS
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the do workflow from @~/.claude/get-shit-done/workflows/do.md end-to-end.
|
||||
Route user intent to the best GSD command and invoke it.
|
||||
</process>
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
name: gsd:edit-phase
|
||||
description: Edit any field of an existing roadmap phase in place, preserving number and position
|
||||
argument-hint: <phase-number> [--force]
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
---
|
||||
|
||||
<objective>
|
||||
Modify any field of an existing phase in ROADMAP.md in place.
|
||||
|
||||
Supports:
|
||||
- Editing individual fields (title, description/goal, requirements, success criteria, depends_on)
|
||||
- Full regeneration of all fields from a clarified intent
|
||||
- Guarded edits: refuses in_progress/completed phases unless --force is passed
|
||||
- Depends-on validation: blocks invalid references with a clear error
|
||||
- Diff + confirmation before writing
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/edit-phase.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS (format: <phase-number> [--force])
|
||||
|
||||
Roadmap and state are resolved in-workflow via `init phase-op` and targeted reads.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the edit-phase workflow from @~/.claude/get-shit-done/workflows/edit-phase.md end-to-end.
|
||||
Preserve all validation gates (phase existence, status guard, depends_on validation, diff + confirmation).
|
||||
</process>
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: gsd:from-gsd2
|
||||
description: Import a GSD-2 (.gsd/) project back to GSD v1 (.planning/) format
|
||||
argument-hint: "[--path <dir>] [--force]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
type: prompt
|
||||
---
|
||||
|
||||
<objective>
|
||||
Reverse-migrate a GSD-2 project (`.gsd/` directory) back to GSD v1 (`.planning/`) format.
|
||||
|
||||
Maps the GSD-2 hierarchy (Milestone → Slice → Task) to the GSD v1 hierarchy (Milestone sections in ROADMAP.md → Phase → Plan), preserving completion state, research files, and summaries.
|
||||
|
||||
**CJS-only:** `from-gsd2` is not on the `gsd-sdk query` registry; call `gsd-tools.cjs` as shown below (see `docs/CLI-TOOLS.md`).
|
||||
</objective>
|
||||
|
||||
<process>
|
||||
|
||||
1. **Locate the .gsd/ directory** — check the current working directory (or `--path` argument):
|
||||
```bash
|
||||
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" from-gsd2 --dry-run
|
||||
```
|
||||
If no `.gsd/` is found, report the error and stop.
|
||||
|
||||
2. **Show the dry-run preview** — present the full file list and migration statistics to the user. Ask for confirmation before writing anything.
|
||||
|
||||
3. **Run the migration** after confirmation:
|
||||
```bash
|
||||
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" from-gsd2
|
||||
```
|
||||
Use `--force` if `.planning/` already exists and the user has confirmed overwrite.
|
||||
|
||||
4. **Report the result** — show the `filesWritten` count, `planningDir` path, and the preview summary.
|
||||
|
||||
</process>
|
||||
|
||||
<notes>
|
||||
- The migration is non-destructive: `.gsd/` is never modified or removed.
|
||||
- Pass `--path <dir>` to migrate a project at a different path than the current directory.
|
||||
- Slices are numbered sequentially across all milestones (M001/S01 → phase 01, M001/S02 → phase 02, M002/S01 → phase 03, etc.).
|
||||
- Tasks within each slice become plans (T01 → plan 01, T02 → plan 02, etc.).
|
||||
- Completed slices and tasks carry their done state into ROADMAP.md checkboxes and SUMMARY.md files.
|
||||
- GSD-2 cost/token ledger, database state, and VS Code extension state cannot be migrated.
|
||||
</notes>
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: gsd:insert-phase
|
||||
description: Insert urgent work as decimal phase (e.g., 72.1) between existing phases
|
||||
argument-hint: <after> <description>
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
---
|
||||
|
||||
<objective>
|
||||
Insert a decimal phase for urgent work discovered mid-milestone that must be completed between existing integer phases.
|
||||
|
||||
Uses decimal numbering (72.1, 72.2, etc.) to preserve the logical sequence of planned phases while accommodating urgent insertions.
|
||||
|
||||
Purpose: Handle urgent work discovered during execution without renumbering entire roadmap.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/insert-phase.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS (format: <after-phase-number> <description>)
|
||||
|
||||
Roadmap and state are resolved in-workflow via `init phase-op` and targeted tool calls.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the insert-phase workflow from @~/.claude/get-shit-done/workflows/insert-phase.md end-to-end.
|
||||
Preserve all validation gates (argument parsing, phase verification, decimal calculation, roadmap updates).
|
||||
</process>
|
||||
@@ -1,179 +0,0 @@
|
||||
---
|
||||
name: gsd:intel
|
||||
description: "Query, inspect, or refresh codebase intelligence files in .planning/intel/"
|
||||
argument-hint: "[query <term>|status|diff|refresh]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Task
|
||||
---
|
||||
|
||||
**STOP -- DO NOT READ THIS FILE. You are already reading it. This prompt was injected into your context by Claude Code's command system. Using the Read tool on this file wastes tokens. Begin executing Step 0 immediately.**
|
||||
|
||||
## Step 0 -- Banner
|
||||
|
||||
**Before ANY tool calls**, display this banner:
|
||||
|
||||
```
|
||||
GSD > INTEL
|
||||
```
|
||||
|
||||
Then proceed to Step 1.
|
||||
|
||||
## Step 1 -- Config Gate
|
||||
|
||||
Check if intel is enabled by reading `.planning/config.json` directly using the Read tool.
|
||||
|
||||
**DO NOT use the gsd-tools config get-value command** -- it hard-exits on missing keys.
|
||||
|
||||
1. Read `.planning/config.json` using the Read tool
|
||||
2. If the file does not exist: display the disabled message below and **STOP**
|
||||
3. Parse the JSON content. Check if `config.intel && config.intel.enabled === true`
|
||||
4. If `intel.enabled` is NOT explicitly `true`: display the disabled message below and **STOP**
|
||||
5. If `intel.enabled` is `true`: proceed to Step 2
|
||||
|
||||
**Disabled message:**
|
||||
|
||||
```
|
||||
GSD > INTEL
|
||||
|
||||
Intel system is disabled. To activate:
|
||||
|
||||
gsd-sdk query config-set intel.enabled true
|
||||
|
||||
Then run /gsd-intel refresh to build the initial index.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2 -- Parse Argument
|
||||
|
||||
Parse `$ARGUMENTS` to determine the operation mode:
|
||||
|
||||
| Argument | Action |
|
||||
|----------|--------|
|
||||
| `query <term>` | Run inline query (Step 2a) |
|
||||
| `status` | Run inline status check (Step 2b) |
|
||||
| `diff` | Run inline diff check (Step 2c) |
|
||||
| `refresh` | Spawn intel-updater agent (Step 3) |
|
||||
| No argument or unknown | Show usage message |
|
||||
|
||||
**Usage message** (shown when no argument or unrecognized argument):
|
||||
|
||||
```
|
||||
GSD > INTEL
|
||||
|
||||
Usage: /gsd-intel <mode>
|
||||
|
||||
Modes:
|
||||
query <term> Search intel files for a term
|
||||
status Show intel file freshness and staleness
|
||||
diff Show changes since last snapshot
|
||||
refresh Rebuild all intel files from codebase analysis
|
||||
```
|
||||
|
||||
### Step 2a -- Query
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
gsd-sdk query intel.query <term>
|
||||
```
|
||||
|
||||
Parse the JSON output and display results:
|
||||
- If the output contains `"disabled": true`, display the disabled message from Step 1 and **STOP**
|
||||
- If no matches found, display: `No intel matches for '<term>'. Try /gsd-intel refresh to build the index.`
|
||||
- Otherwise, display matching entries grouped by intel file
|
||||
|
||||
**STOP** after displaying results. Do not spawn an agent.
|
||||
|
||||
### Step 2b -- Status
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
gsd-sdk query intel.status
|
||||
```
|
||||
|
||||
Parse the JSON output and display each intel file with:
|
||||
- File name
|
||||
- Last `updated_at` timestamp
|
||||
- STALE or FRESH status (stale if older than 24 hours or missing)
|
||||
|
||||
**STOP** after displaying status. Do not spawn an agent.
|
||||
|
||||
### Step 2c -- Diff
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
gsd-sdk query intel.diff
|
||||
```
|
||||
|
||||
Parse the JSON output and display:
|
||||
- Added entries since last snapshot
|
||||
- Removed entries since last snapshot
|
||||
- Changed entries since last snapshot
|
||||
|
||||
If no snapshot exists, suggest running `refresh` first.
|
||||
|
||||
**STOP** after displaying diff. Do not spawn an agent.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 -- Refresh (Agent Spawn)
|
||||
|
||||
Display before spawning:
|
||||
|
||||
```
|
||||
GSD > Spawning intel-updater agent to analyze codebase...
|
||||
```
|
||||
|
||||
Spawn a Task:
|
||||
|
||||
```
|
||||
Task(
|
||||
description="Refresh codebase intelligence files",
|
||||
prompt="You are the gsd-intel-updater agent. Your job is to analyze this codebase and write/update intelligence files in .planning/intel/.
|
||||
|
||||
Project root: ${CWD}
|
||||
Prefer: gsd-sdk query <subcommand> (installed gsd-sdk on PATH). Legacy: node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs
|
||||
|
||||
Instructions:
|
||||
1. Analyze the codebase structure, dependencies, APIs, and architecture
|
||||
2. Write JSON intel files to .planning/intel/ (stack.json, api-map.json, dependency-graph.json, file-roles.json, arch-decisions.json)
|
||||
3. Each file must have a _meta object with updated_at timestamp
|
||||
4. Use `gsd-sdk query intel.extract-exports <file>` to analyze source files
|
||||
5. Use `gsd-sdk query intel.patch-meta <file>` to update timestamps after writing
|
||||
6. Use `gsd-sdk query intel.validate` to check your output
|
||||
|
||||
When complete, output: ## INTEL UPDATE COMPLETE
|
||||
If something fails, output: ## INTEL UPDATE FAILED with details."
|
||||
)
|
||||
```
|
||||
|
||||
Wait for the agent to complete.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 -- Post-Refresh Summary
|
||||
|
||||
After the agent completes, run:
|
||||
|
||||
```bash
|
||||
gsd-sdk query intel.status
|
||||
```
|
||||
|
||||
Display a summary showing:
|
||||
- Which intel files were written or updated
|
||||
- Last update timestamps
|
||||
- Overall health of the intel index
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
1. DO NOT spawn an agent for query/status/diff operations -- these are inline CLI calls
|
||||
2. DO NOT modify intel files directly -- the agent handles writes during refresh
|
||||
3. DO NOT skip the config gate check
|
||||
4. DO NOT use the gsd-tools config get-value CLI for the config gate -- it exits on missing keys
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: gsd:join-discord
|
||||
description: Join the GSD Discord community
|
||||
allowed-tools: []
|
||||
---
|
||||
|
||||
<objective>
|
||||
Display the Discord invite link for the GSD community server.
|
||||
</objective>
|
||||
|
||||
<output>
|
||||
# Join the GSD Discord
|
||||
|
||||
Connect with other GSD users, get help, share what you're building, and stay updated.
|
||||
|
||||
**Invite link:** https://discord.gg/mYgfVNfA2r
|
||||
|
||||
Click the link or paste it into your browser to join.
|
||||
</output>
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: gsd:list-phase-assumptions
|
||||
description: Surface Claude's assumptions about a phase approach before planning
|
||||
argument-hint: "[phase]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
---
|
||||
|
||||
<objective>
|
||||
Analyze a phase and present Claude's assumptions about technical approach, implementation order, scope boundaries, risk areas, and dependencies.
|
||||
|
||||
Purpose: Help users see what Claude thinks BEFORE planning begins - enabling course correction early when assumptions are wrong.
|
||||
Output: Conversational output only (no file creation) - ends with "What do you think?" prompt
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/list-phase-assumptions.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Phase number: $ARGUMENTS (required)
|
||||
|
||||
Project state and roadmap are loaded in-workflow using targeted reads.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
1. Validate phase number argument (error if missing or invalid)
|
||||
2. Check if phase exists in roadmap
|
||||
3. Follow list-phase-assumptions.md workflow:
|
||||
- Analyze roadmap description
|
||||
- Surface assumptions about: technical approach, implementation order, scope, risks, dependencies
|
||||
- Present assumptions clearly
|
||||
- Prompt "What do you think?"
|
||||
4. Gather feedback and offer next steps
|
||||
</process>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
- Phase validated against roadmap
|
||||
- Assumptions surfaced across five areas
|
||||
- User prompted for feedback
|
||||
- User knows next steps (discuss context, plan phase, or correct assumptions)
|
||||
</success_criteria>
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: gsd:list-workspaces
|
||||
description: List active GSD workspaces and their status
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
---
|
||||
<objective>
|
||||
Scan `~/gsd-workspaces/` for workspace directories containing `WORKSPACE.md` manifests. Display a summary table with name, path, repo count, strategy, and GSD project status.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/list-workspaces.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the list-workspaces workflow from @~/.claude/get-shit-done/workflows/list-workspaces.md end-to-end.
|
||||
</process>
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:map-codebase
|
||||
description: Analyze codebase with parallel mapper agents to produce .planning/codebase/ documents
|
||||
argument-hint: "[optional: specific area to map, e.g., 'api' or 'auth']"
|
||||
argument-hint: "[--fast [--focus tech|arch|quality|concerns]] [--query <term>|status|diff|refresh] [area]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
@@ -23,8 +23,19 @@ Output: .planning/codebase/ folder with 7 structured documents about the codebas
|
||||
@~/.claude/get-shit-done/workflows/map-codebase.md
|
||||
</execution_context>
|
||||
|
||||
<flags>
|
||||
- **--fast**: Lightweight scan mode — spawns one mapper agent instead of four. Accepts an optional `--focus` value: `tech`, `arch`, `quality`, `concerns`, or `tech+arch` (default). Faster and lower-context than the full map.
|
||||
- **--query**: Codebase intelligence query mode. Sub-commands: `query <term>`, `status`, `diff`, `refresh`. Requires intel to be enabled in config (`intel.enabled: true`). Runs inline for query/status/diff; spawns an agent for refresh.
|
||||
- **(no flag)**: Full parallel map — spawns 4 mapper agents to produce all 7 codebase documents.
|
||||
</flags>
|
||||
|
||||
<context>
|
||||
Focus area: $ARGUMENTS (optional - if provided, tells agents to focus on specific subsystem)
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--fast`: strip the flag, run the scan workflow (passing remaining args including optional --focus).
|
||||
- If it is `--query`: strip the flag, run the intel workflow (passing remaining args as the subcommand).
|
||||
- Otherwise: pass all of $ARGUMENTS as focus area to the map-codebase workflow.
|
||||
|
||||
**Load project state if exists:**
|
||||
Check for .planning/STATE.md - loads context if project already initialized
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
name: gsd:new-workspace
|
||||
description: Create an isolated workspace with repo copies and independent .planning/
|
||||
argument-hint: "--name <name> [--repos repo1,repo2] [--path /target] [--strategy worktree|clone] [--branch name] [--auto]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Write
|
||||
- AskUserQuestion
|
||||
---
|
||||
<context>
|
||||
**Flags:**
|
||||
- `--name` (required) — Workspace name
|
||||
- `--repos` — Comma-separated repo paths or names. If omitted, interactive selection from child git repos in cwd
|
||||
- `--path` — Target directory. Defaults to `~/gsd-workspaces/<name>`
|
||||
- `--strategy` — `worktree` (default, lightweight) or `clone` (fully independent)
|
||||
- `--branch` — Branch to checkout. Defaults to `workspace/<name>`
|
||||
- `--auto` — Skip interactive questions, use defaults
|
||||
</context>
|
||||
|
||||
<objective>
|
||||
Create a physical workspace directory containing copies of specified git repos (as worktrees or clones) with an independent `.planning/` directory for isolated GSD sessions.
|
||||
|
||||
**Use cases:**
|
||||
- Multi-repo orchestration: work on a subset of repos in parallel with isolated GSD state
|
||||
- Feature branch isolation: create a worktree of the current repo with its own `.planning/`
|
||||
|
||||
**Creates:**
|
||||
- `<path>/WORKSPACE.md` — workspace manifest
|
||||
- `<path>/.planning/` — independent planning directory
|
||||
- `<path>/<repo>/` — git worktree or clone for each specified repo
|
||||
|
||||
**After this command:** `cd` into the workspace and run `/gsd-new-project` to initialize GSD.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/new-workspace.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the new-workspace workflow from @~/.claude/get-shit-done/workflows/new-workspace.md end-to-end.
|
||||
Preserve all workflow gates (validation, approvals, commits, routing).
|
||||
</process>
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
name: gsd:next
|
||||
description: Automatically advance to the next logical step in the GSD workflow
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
- SlashCommand
|
||||
---
|
||||
<objective>
|
||||
Detect the current project state and automatically invoke the next logical GSD workflow step.
|
||||
No arguments needed — reads STATE.md, ROADMAP.md, and phase directories to determine what comes next.
|
||||
|
||||
Designed for rapid multi-project workflows where remembering which phase/step you're on is overhead.
|
||||
|
||||
Supports `--force` flag to bypass safety gates (checkpoint, error state, verification failures, and prior-phase completeness scan).
|
||||
|
||||
Before routing to the next step, scans all prior phases for incomplete work: plans that ran without producing summaries, verification failures without overrides, and phases where discussion happened but planning never ran. When incomplete work is found, shows a structured report and offers three options: defer the gaps to the backlog and continue, stop and resolve manually, or force advance without recording. When prior phases are clean, routes silently with no interruption.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/next.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the next workflow from @~/.claude/get-shit-done/workflows/next.md end-to-end.
|
||||
</process>
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
name: gsd:note
|
||||
description: Zero-friction idea capture. Append, list, or promote notes to todos.
|
||||
argument-hint: "<text> | list | promote <N> [--global]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Glob
|
||||
- Grep
|
||||
---
|
||||
<objective>
|
||||
Zero-friction idea capture — one Write call, one confirmation line.
|
||||
|
||||
Three subcommands:
|
||||
- **append** (default): Save a timestamped note file. No questions, no formatting.
|
||||
- **list**: Show all notes from project and global scopes.
|
||||
- **promote**: Convert a note into a structured todo.
|
||||
|
||||
Runs inline — no Task, no AskUserQuestion, no Bash.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/note.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
$ARGUMENTS
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the note workflow from @~/.claude/get-shit-done/workflows/note.md end-to-end.
|
||||
Capture the note, list notes, or promote to todo — depending on arguments.
|
||||
</process>
|
||||
56
commands/gsd/phase.md
Normal file
56
commands/gsd/phase.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: gsd:phase
|
||||
description: CRUD for phases in ROADMAP.md — add, insert, remove, or edit phases
|
||||
argument-hint: "[--insert | --remove | --edit] <phase-name-or-number>"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- Glob
|
||||
---
|
||||
|
||||
<objective>
|
||||
Manage phases in ROADMAP.md with a single consolidated command.
|
||||
|
||||
Mode routing:
|
||||
- **default** (no flag): Add a new integer phase to the end of the current milestone → add-phase workflow
|
||||
- **--insert**: Insert urgent work as a decimal phase (e.g., 72.1) between existing phases → insert-phase workflow
|
||||
- **--remove**: Remove a future phase and renumber subsequent phases → remove-phase workflow
|
||||
- **--edit**: Edit any field of an existing phase in place → edit-phase workflow
|
||||
</objective>
|
||||
|
||||
<routing>
|
||||
|
||||
| Flag | Action | Workflow |
|
||||
|------|--------|----------|
|
||||
| (none) | Add new integer phase at end of milestone | add-phase |
|
||||
| --insert | Insert decimal phase (e.g., 72.1) after specified phase | insert-phase |
|
||||
| --remove | Remove future phase, renumber subsequent | remove-phase |
|
||||
| --edit | Edit fields of existing phase in place | edit-phase |
|
||||
|
||||
</routing>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/add-phase.md
|
||||
@~/.claude/get-shit-done/workflows/insert-phase.md
|
||||
@~/.claude/get-shit-done/workflows/remove-phase.md
|
||||
@~/.claude/get-shit-done/workflows/edit-phase.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--insert`: strip the flag, pass remainder (format: <after-phase-number> <description>) to insert-phase workflow
|
||||
- If it is `--remove`: strip the flag, pass remainder (phase number) to remove-phase workflow
|
||||
- If it is `--edit`: strip the flag, pass remainder (phase-number [--force]) to edit-phase workflow
|
||||
- Otherwise: pass all of $ARGUMENTS (phase description) to add-phase workflow
|
||||
|
||||
Roadmap and state are resolved in-workflow via `init phase-op` and targeted reads.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
1. Parse the leading flag (if any) from $ARGUMENTS.
|
||||
2. Load and execute the appropriate workflow end-to-end based on the routing table above.
|
||||
3. Preserve all validation gates from the target workflow.
|
||||
</process>
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
name: gsd:plan-milestone-gaps
|
||||
description: Create phases to close all gaps identified by milestone audit
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- Glob
|
||||
- Grep
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Create all phases necessary to close gaps identified by `/gsd-audit-milestone`.
|
||||
|
||||
Reads MILESTONE-AUDIT.md, groups gaps into logical phases, creates phase entries in ROADMAP.md, and offers to plan each phase.
|
||||
|
||||
One command creates all fix phases — no manual `/gsd-add-phase` per gap.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/plan-milestone-gaps.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
**Audit results:**
|
||||
Glob: .planning/v*-MILESTONE-AUDIT.md (use most recent)
|
||||
|
||||
Original intent and current planning state are loaded on demand inside the workflow.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the plan-milestone-gaps workflow from @~/.claude/get-shit-done/workflows/plan-milestone-gaps.md end-to-end.
|
||||
Preserve all workflow gates (audit loading, prioritization, phase grouping, user confirmation, roadmap updates).
|
||||
</process>
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
name: gsd:plant-seed
|
||||
description: Capture a forward-looking idea that surfaces automatically at the right milestone.
|
||||
argument-hint: "[idea summary]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Capture an idea that's too big for now but should surface automatically when the right
|
||||
milestone arrives. Seeds solve context rot: instead of a one-liner in Deferred that nobody
|
||||
reads, a seed preserves the full WHY, WHEN to surface, and breadcrumbs to details.
|
||||
|
||||
Creates: .planning/seeds/SEED-NNN-slug.md
|
||||
Consumed by: /gsd-new-milestone (scans seeds and presents matches)
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/plant-seed.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the plant-seed workflow from @~/.claude/get-shit-done/workflows/plant-seed.md end-to-end.
|
||||
</process>
|
||||
@@ -1,25 +1,44 @@
|
||||
---
|
||||
name: gsd:progress
|
||||
description: Check project progress, show context, and route to the next action (execute or plan).
|
||||
argument-hint: "[--forensic]"
|
||||
description: Check progress, advance workflow, or dispatch freeform intent — the unified GSD situational command
|
||||
argument-hint: "[--forensic | --next | --do \"task description\"]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
- SlashCommand
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Check project progress, summarize recent work and what's ahead, then intelligently route to the next action - either executing an existing plan or creating the next one.
|
||||
Check project progress, summarize recent work and what's ahead, then intelligently route to the next action.
|
||||
|
||||
Provides situational awareness before continuing work.
|
||||
Three modes:
|
||||
- **default**: Show progress report + intelligently route to the next action (execute or plan). Provides situational awareness before continuing work.
|
||||
- **--next**: Automatically advance to the next logical step without manual route selection. Reads STATE.md, ROADMAP.md, and phase directories. Supports `--force` to bypass safety gates.
|
||||
- **--do "task description"**: Analyze freeform natural language and dispatch to the most appropriate GSD command. Never does the work itself — matches intent, confirms, hands off.
|
||||
- **--forensic**: Append a 6-check integrity audit after the standard progress report.
|
||||
</objective>
|
||||
|
||||
<flags>
|
||||
- **--next**: Detect current project state and automatically invoke the next logical GSD workflow step. Scans all prior phases for incomplete work before routing. `--next --force` bypasses safety gates.
|
||||
- **--do "..."**: Smart dispatcher — match freeform intent to the best GSD command using routing rules, confirm the match, then hand off.
|
||||
- **--forensic**: Run 6-check integrity audit after the standard progress report.
|
||||
- **(no flag)**: Standard progress check + intelligent routing (Routes A through F).
|
||||
</flags>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/progress.md
|
||||
@~/.claude/get-shit-done/workflows/next.md
|
||||
@~/.claude/get-shit-done/workflows/do.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the progress workflow from @~/.claude/get-shit-done/workflows/progress.md end-to-end.
|
||||
Preserve all routing logic (Routes A through F) and edge case handling.
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--next`: strip the flag, execute the next workflow (passing remaining args e.g. --force).
|
||||
- If it is `--do`: strip the flag, pass remainder as freeform intent to the do workflow.
|
||||
- Otherwise: execute the progress workflow end-to-end (pass --forensic through if present).
|
||||
|
||||
Preserve all routing logic from the target workflow.
|
||||
</process>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: gsd:remove-phase
|
||||
description: Remove a future phase from roadmap and renumber subsequent phases
|
||||
argument-hint: <phase-number>
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- Glob
|
||||
---
|
||||
<objective>
|
||||
Remove an unstarted future phase from the roadmap and renumber all subsequent phases to maintain a clean, linear sequence.
|
||||
|
||||
Purpose: Clean removal of work you've decided not to do, without polluting context with cancelled/deferred markers.
|
||||
Output: Phase deleted, all subsequent phases renumbered, git commit as historical record.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/remove-phase.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Phase: $ARGUMENTS
|
||||
|
||||
Roadmap and state are resolved in-workflow via `init phase-op` and targeted reads.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
Execute the remove-phase workflow from @~/.claude/get-shit-done/workflows/remove-phase.md end-to-end.
|
||||
Preserve all validation gates (future phase check, work check), renumbering logic, and commit.
|
||||
</process>
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: gsd:remove-workspace
|
||||
description: Remove a GSD workspace and clean up worktrees
|
||||
argument-hint: "<workspace-name>"
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
- AskUserQuestion
|
||||
---
|
||||
<context>
|
||||
**Arguments:**
|
||||
- `<workspace-name>` (required) — Name of the workspace to remove
|
||||
</context>
|
||||
|
||||
<objective>
|
||||
Remove a workspace directory after confirmation. For worktree strategy, runs `git worktree remove` for each member repo first. Refuses if any repo has uncommitted changes.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/remove-workspace.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the remove-workspace workflow from @~/.claude/get-shit-done/workflows/remove-workspace.md end-to-end.
|
||||
</process>
|
||||
@@ -1,195 +0,0 @@
|
||||
---
|
||||
name: gsd:research-phase
|
||||
description: Research how to implement a phase (standalone - usually use /gsd-plan-phase instead)
|
||||
argument-hint: "[phase]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Task
|
||||
---
|
||||
|
||||
<objective>
|
||||
Research how to implement a phase. Spawns gsd-phase-researcher agent with phase context.
|
||||
|
||||
**Note:** This is a standalone research command. For most workflows, use `/gsd-plan-phase` which integrates research automatically.
|
||||
|
||||
**Use this command when:**
|
||||
- You want to research without planning yet
|
||||
- You want to re-research after planning is complete
|
||||
- You need to investigate before deciding if a phase is feasible
|
||||
|
||||
**Orchestrator role:** Parse phase, validate against roadmap, check existing research, gather context, spawn researcher agent, present results.
|
||||
|
||||
**Why subagent:** Research burns context fast (WebSearch, Context7 queries, source verification). Fresh 200k context for investigation. Main context stays lean for user interaction.
|
||||
</objective>
|
||||
|
||||
<available_agent_types>
|
||||
Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
|
||||
- gsd-phase-researcher — Researches technical approaches for a phase
|
||||
</available_agent_types>
|
||||
|
||||
<context>
|
||||
Phase number: $ARGUMENTS (required)
|
||||
|
||||
Normalize phase input in step 1 before any directory lookups.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
|
||||
## 0. Initialize Context
|
||||
|
||||
```bash
|
||||
INIT=$(gsd-sdk query init.phase-op "$ARGUMENTS")
|
||||
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
||||
```
|
||||
|
||||
Extract from init JSON: `phase_dir`, `phase_number`, `phase_name`, `phase_found`, `commit_docs`, `has_research`, `state_path`, `requirements_path`, `context_path`, `research_path`.
|
||||
|
||||
Resolve researcher model:
|
||||
```bash
|
||||
RESEARCHER_MODEL=$(gsd-sdk query resolve-model gsd-phase-researcher --raw)
|
||||
```
|
||||
|
||||
## 1. Validate Phase
|
||||
|
||||
```bash
|
||||
PHASE_INFO=$(gsd-sdk query roadmap.get-phase "${phase_number}")
|
||||
```
|
||||
|
||||
**If `found` is false:** Error and exit. **If `found` is true:** Extract `phase_number`, `phase_name`, `goal` from JSON.
|
||||
|
||||
## 2. Check Existing Research
|
||||
|
||||
```bash
|
||||
ls .planning/phases/${PHASE}-*/RESEARCH.md 2>/dev/null
|
||||
```
|
||||
|
||||
**If exists:** Offer: 1) Update research, 2) View existing, 3) Skip. Wait for response.
|
||||
|
||||
**If doesn't exist:** Continue.
|
||||
|
||||
## 3. Gather Phase Context
|
||||
|
||||
Use paths from INIT (do not inline file contents in orchestrator context):
|
||||
- `requirements_path`
|
||||
- `context_path`
|
||||
- `state_path`
|
||||
|
||||
Present summary with phase description and what files the researcher will load.
|
||||
|
||||
## 4. Spawn gsd-phase-researcher Agent
|
||||
|
||||
Research modes: ecosystem (default), feasibility, implementation, comparison.
|
||||
|
||||
```markdown
|
||||
<research_type>
|
||||
Phase Research — investigating HOW to implement a specific phase well.
|
||||
</research_type>
|
||||
|
||||
<key_insight>
|
||||
The question is NOT "which library should I use?"
|
||||
|
||||
The question is: "What do I not know that I don't know?"
|
||||
|
||||
For this phase, discover:
|
||||
- What's the established architecture pattern?
|
||||
- What libraries form the standard stack?
|
||||
- What problems do people commonly hit?
|
||||
- What's SOTA vs what Claude's training thinks is SOTA?
|
||||
- What should NOT be hand-rolled?
|
||||
</key_insight>
|
||||
|
||||
<objective>
|
||||
Research implementation approach for Phase {phase_number}: {phase_name}
|
||||
Mode: ecosystem
|
||||
</objective>
|
||||
|
||||
<files_to_read>
|
||||
- {requirements_path} (Requirements)
|
||||
- {context_path} (Phase context from discuss-phase, if exists)
|
||||
- {state_path} (Prior project decisions and blockers)
|
||||
</files_to_read>
|
||||
|
||||
<additional_context>
|
||||
**Phase description:** {phase_description}
|
||||
</additional_context>
|
||||
|
||||
<downstream_consumer>
|
||||
Your RESEARCH.md will be loaded by `/gsd-plan-phase` which uses specific sections:
|
||||
- `## Standard Stack` → Plans use these libraries
|
||||
- `## Architecture Patterns` → Task structure follows these
|
||||
- `## Don't Hand-Roll` → Tasks NEVER build custom solutions for listed problems
|
||||
- `## Common Pitfalls` → Verification steps check for these
|
||||
- `## Code Examples` → Task actions reference these patterns
|
||||
|
||||
Be prescriptive, not exploratory. "Use X" not "Consider X or Y."
|
||||
</downstream_consumer>
|
||||
|
||||
<quality_gate>
|
||||
Before declaring complete, verify:
|
||||
- [ ] All domains investigated (not just some)
|
||||
- [ ] Negative claims verified with official docs
|
||||
- [ ] Multiple sources for critical claims
|
||||
- [ ] Confidence levels assigned honestly
|
||||
- [ ] Section names match what plan-phase expects
|
||||
</quality_gate>
|
||||
|
||||
<output>
|
||||
Write to: .planning/phases/${PHASE}-{slug}/${PHASE}-RESEARCH.md
|
||||
</output>
|
||||
```
|
||||
|
||||
```
|
||||
Task(
|
||||
prompt=filled_prompt,
|
||||
subagent_type="gsd-phase-researcher",
|
||||
model="{researcher_model}",
|
||||
description="Research Phase {phase}"
|
||||
)
|
||||
```
|
||||
|
||||
## 5. Handle Agent Return
|
||||
|
||||
**`## RESEARCH COMPLETE`:** Display summary, offer: Plan phase, Dig deeper, Review full, Done.
|
||||
|
||||
**`## CHECKPOINT REACHED`:** Present to user, get response, spawn continuation.
|
||||
|
||||
**`## RESEARCH INCONCLUSIVE`:** Show what was attempted, offer: Add context, Try different mode, Manual.
|
||||
|
||||
## 6. Spawn Continuation Agent
|
||||
|
||||
```markdown
|
||||
<objective>
|
||||
Continue research for Phase {phase_number}: {phase_name}
|
||||
</objective>
|
||||
|
||||
<prior_state>
|
||||
<files_to_read>
|
||||
- .planning/phases/${PHASE}-{slug}/${PHASE}-RESEARCH.md (Existing research)
|
||||
</files_to_read>
|
||||
</prior_state>
|
||||
|
||||
<checkpoint_response>
|
||||
**Type:** {checkpoint_type}
|
||||
**Response:** {user_response}
|
||||
</checkpoint_response>
|
||||
```
|
||||
|
||||
```
|
||||
Task(
|
||||
prompt=continuation_prompt,
|
||||
subagent_type="gsd-phase-researcher",
|
||||
model="{researcher_model}",
|
||||
description="Continue research Phase {phase}"
|
||||
)
|
||||
```
|
||||
|
||||
</process>
|
||||
|
||||
<success_criteria>
|
||||
- [ ] Phase validated against roadmap
|
||||
- [ ] Existing research checked
|
||||
- [ ] gsd-phase-researcher spawned with context
|
||||
- [ ] Checkpoints handled correctly
|
||||
- [ ] User knows next steps
|
||||
</success_criteria>
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: gsd:scan
|
||||
description: Rapid codebase assessment — lightweight alternative to /gsd-map-codebase
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
- Agent
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Run a focused codebase scan for a single area, producing targeted documents in `.planning/codebase/`.
|
||||
Accepts an optional `--focus` flag: `tech`, `arch`, `quality`, `concerns`, or `tech+arch` (default).
|
||||
|
||||
Lightweight alternative to `/gsd-map-codebase` — spawns one mapper agent instead of four parallel ones.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/scan.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the scan workflow from @~/.claude/get-shit-done/workflows/scan.md end-to-end.
|
||||
</process>
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: gsd:session-report
|
||||
description: Generate a session report with token usage estimates, work summary, and outcomes
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Bash
|
||||
- Write
|
||||
---
|
||||
<objective>
|
||||
Generate a structured SESSION_REPORT.md document capturing session outcomes, work performed, and estimated resource usage. Provides a shareable artifact for post-session review.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/session-report.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
Execute the session-report workflow from @~/.claude/get-shit-done/workflows/session-report.md end-to-end.
|
||||
</process>
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
name: gsd:set-profile
|
||||
description: Switch model profile for GSD agents (quality/balanced/budget/inherit)
|
||||
argument-hint: <profile (quality|balanced|budget|inherit)>
|
||||
model: haiku
|
||||
allowed-tools:
|
||||
- Bash
|
||||
---
|
||||
|
||||
Show the following output to the user verbatim, with no extra commentary:
|
||||
|
||||
!`if ! command -v gsd-sdk >/dev/null 2>&1; then printf '⚠ gsd-sdk not found in PATH — /gsd-set-profile requires it.\n\nInstall the GSD SDK:\n npm install -g @gsd-build/sdk\n\nOr update GSD to get the latest packages:\n /gsd-update\n'; exit 1; fi; gsd-sdk query config-set-model-profile $ARGUMENTS --raw`
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: gsd:settings-advanced
|
||||
description: Power-user configuration for plan bounce, timeouts, branch templates, and cross-AI execution.
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Interactive configuration of GSD power-user knobs that don't belong in the common-case `/gsd-settings` prompt.
|
||||
|
||||
Routes to the settings-advanced workflow which handles:
|
||||
- Config existence ensuring (workstream-aware path resolution)
|
||||
- Current settings reading and parsing
|
||||
- Sectioned prompts: Planning Tuning, Execution Tuning, Discussion Tuning, Cross-AI Execution, Git Customization, Runtime / Output
|
||||
- Config merging that preserves every unrelated key
|
||||
- Confirmation table display
|
||||
|
||||
Use `/gsd-settings` for the common-case toggles (model profile, research/plan_check/verifier, branching strategy, context warnings). Use `/gsd-settings-advanced` once those are set and you want to tune the internals.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/settings-advanced.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
**Follow the settings-advanced workflow** from `@~/.claude/get-shit-done/workflows/settings-advanced.md`.
|
||||
|
||||
The workflow handles all logic including:
|
||||
1. Config file creation with defaults if missing (via `gsd-sdk query config-ensure-section`)
|
||||
2. Current config reading
|
||||
3. Six sectioned AskUserQuestion batches with current values pre-selected
|
||||
4. Numeric-input validation (non-numeric rejected, empty input keeps current)
|
||||
5. Answer parsing and config merging (preserves unrelated keys)
|
||||
6. File writing (atomic)
|
||||
7. Confirmation table display
|
||||
</process>
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
name: gsd:settings-integrations
|
||||
description: Configure third-party API keys, code-review CLI routing, and agent-skill injection
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Interactive configuration of GSD's third-party integration surface:
|
||||
- Search API keys: `brave_search`, `firecrawl`, `exa_search`, and
|
||||
the `search_gitignored` toggle
|
||||
- Code-review CLI routing: `review.models.{claude,codex,gemini,opencode}`
|
||||
- Agent-skill injection: `agent_skills.<agent-type>`
|
||||
|
||||
API keys are stored plaintext in `.planning/config.json` but are masked
|
||||
(`****<last-4>`) in every piece of interactive output. The workflow never
|
||||
echoes plaintext to stdout, stderr, or any log.
|
||||
|
||||
This command is deliberately distinct from `/gsd-settings` (workflow toggles)
|
||||
and any `/gsd-settings-advanced` tuning surface. It handles *connectivity*,
|
||||
not pipeline shape.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/settings-integrations.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
**Follow the settings-integrations workflow** from
|
||||
`@~/.claude/get-shit-done/workflows/settings-integrations.md`.
|
||||
|
||||
The workflow handles:
|
||||
1. Resolving `$GSD_CONFIG_PATH` (flat vs workstream)
|
||||
2. Reading current integration values (masked for display)
|
||||
3. Section 1 — Search Integrations: Brave / Firecrawl / Exa / search_gitignored
|
||||
4. Section 2 — Review CLI Routing: review.models.{claude,codex,gemini,opencode}
|
||||
5. Section 3 — Agent Skills Injection: agent_skills.<agent-type>
|
||||
6. Writing values via `gsd-sdk query config-set` (which merges, preserving
|
||||
unrelated keys)
|
||||
7. Masked confirmation display
|
||||
</process>
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: gsd:sketch-wrap-up
|
||||
description: Package sketch design findings into a persistent project skill for future build conversations
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Curate sketch design findings and package them into a persistent project skill that Claude
|
||||
auto-loads when building the real UI. Also writes a summary to `.planning/sketches/` for
|
||||
project history. Output skill goes to `./.claude/skills/sketch-findings-[project]/` (project-local).
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/sketch-wrap-up.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<runtime_note>
|
||||
**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`.
|
||||
</runtime_note>
|
||||
|
||||
<process>
|
||||
Execute the sketch-wrap-up workflow from @~/.claude/get-shit-done/workflows/sketch-wrap-up.md end-to-end.
|
||||
Preserve all curation gates (per-sketch review, grouping approval, CLAUDE.md routing line).
|
||||
</process>
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:sketch
|
||||
description: Sketch UI/design ideas with throwaway HTML mockups, or propose what to sketch next (frontier mode)
|
||||
argument-hint: "[design idea to explore] [--quick] [--text] or [frontier]"
|
||||
argument-hint: "[design idea to explore] [--quick] [--text] [--wrap-up] or [frontier]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
@@ -46,6 +46,7 @@ Design idea: $ARGUMENTS
|
||||
|
||||
**Available flags:**
|
||||
- `--quick` — Skip mood/direction intake, jump straight to decomposition and building. Use when the design direction is already clear.
|
||||
- `--wrap-up` — Package sketch design findings into a persistent project skill for future build conversations. Runs the sketch-wrap-up workflow.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: gsd:spike-wrap-up
|
||||
description: Package spike findings into a persistent project skill for future build conversations
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
- Grep
|
||||
- Glob
|
||||
- AskUserQuestion
|
||||
---
|
||||
<objective>
|
||||
Curate spike experiment findings and package them into a persistent project skill that Claude
|
||||
auto-loads in future build conversations. Also writes a summary to `.planning/spikes/` for
|
||||
project history. Output skill goes to `./.claude/skills/spike-findings-[project]/` (project-local).
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/spike-wrap-up.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<runtime_note>
|
||||
**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`.
|
||||
</runtime_note>
|
||||
|
||||
<process>
|
||||
Execute the spike-wrap-up workflow from @~/.claude/get-shit-done/workflows/spike-wrap-up.md end-to-end.
|
||||
Preserve all workflow gates (auto-include, feature-area grouping, skill synthesis, CLAUDE.md routing line, intelligent next-step routing).
|
||||
</process>
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:spike
|
||||
description: Spike an idea through experiential exploration, or propose what to spike next (frontier mode)
|
||||
argument-hint: "[idea to validate] [--quick] [--text] or [frontier]"
|
||||
argument-hint: "[idea to validate] [--quick] [--text] [--wrap-up] or [frontier]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
@@ -43,6 +43,7 @@ Idea: $ARGUMENTS
|
||||
**Available flags:**
|
||||
- `--quick` — Skip decomposition/alignment, jump straight to building. Use when you already know what to spike.
|
||||
- `--text` — Use plain-text numbered lists instead of AskUserQuestion (for non-Claude runtimes).
|
||||
- `--wrap-up` — Package spike findings into a persistent project skill for future build conversations. Runs the spike-wrap-up workflow.
|
||||
</context>
|
||||
|
||||
<process>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: gsd:sync-skills
|
||||
description: Sync managed GSD skills across runtime roots so multi-runtime users stay aligned after an update
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Sync managed `gsd-*` skill directories from one canonical runtime's skills root to one or more destination runtime skills roots.
|
||||
|
||||
Routes to the sync-skills workflow which handles:
|
||||
- Argument parsing (--from, --to, --dry-run, --apply)
|
||||
- Runtime skills root resolution via install.js --skills-root
|
||||
- Diff computation (CREATE / UPDATE / REMOVE per destination)
|
||||
- Dry-run reporting (default — no writes)
|
||||
- Apply execution (copy and remove with idempotency)
|
||||
- Non-GSD skill preservation (only gsd-* dirs are touched)
|
||||
</objective>
|
||||
@@ -1,8 +1,14 @@
|
||||
---
|
||||
name: gsd:update
|
||||
description: Update GSD to latest version with changelog display
|
||||
argument-hint: "[--sync | --reapply]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
- Glob
|
||||
- Grep
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
@@ -22,10 +28,19 @@ Routes to the update workflow which handles:
|
||||
@~/.claude/get-shit-done/workflows/update.md
|
||||
</execution_context>
|
||||
|
||||
<process>
|
||||
**Follow the update workflow** from `@~/.claude/get-shit-done/workflows/update.md`.
|
||||
<flags>
|
||||
- **--sync**: Sync managed GSD skills across runtime roots so multi-runtime users stay aligned after an update. Runs the sync-skills workflow (--from, --to, --dry-run, --apply flags supported).
|
||||
- **--reapply**: Reapply local modifications after a GSD update. Uses three-way comparison (pristine baseline, user-modified backup, newly installed version) to merge user customizations back. Runs the reapply-patches workflow.
|
||||
- **(no flag)**: Standard update — check for new version, show changelog, install.
|
||||
</flags>
|
||||
|
||||
The workflow handles all logic including:
|
||||
<process>
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--sync`: strip the flag, execute the sync-skills workflow (passing remaining args for --from/--to/--dry-run/--apply).
|
||||
- If it is `--reapply`: strip the flag, execute the reapply-patches workflow.
|
||||
- Otherwise: **Follow the update workflow** from `@~/.claude/get-shit-done/workflows/update.md`.
|
||||
|
||||
The update workflow handles all logic including:
|
||||
1. Installed version detection (local/global)
|
||||
2. Latest version checking via npm
|
||||
3. Version comparison
|
||||
@@ -35,3 +50,8 @@ The workflow handles all logic including:
|
||||
7. Update execution
|
||||
8. Cache clearing
|
||||
</process>
|
||||
|
||||
<execution_context_extended>
|
||||
@~/.claude/get-shit-done/workflows/sync-skills.md
|
||||
@~/.claude/get-shit-done/workflows/reapply-patches.md
|
||||
</execution_context_extended>
|
||||
|
||||
52
commands/gsd/workspace.md
Normal file
52
commands/gsd/workspace.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
name: gsd:workspace
|
||||
description: Manage GSD workspaces — create, list, or remove isolated workspace environments
|
||||
argument-hint: "[--new | --list | --remove] [name]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Bash
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
<objective>
|
||||
Manage GSD workspaces with a single consolidated command.
|
||||
|
||||
Mode routing:
|
||||
- **--new**: Create an isolated workspace with repo copies and independent .planning/ → new-workspace workflow
|
||||
- **--list**: List active GSD workspaces and their status → list-workspaces workflow
|
||||
- **--remove**: Remove a GSD workspace and clean up worktrees → remove-workspace workflow
|
||||
</objective>
|
||||
|
||||
<routing>
|
||||
|
||||
| Flag | Action | Workflow |
|
||||
|------|--------|----------|
|
||||
| --new | Create workspace with worktree/clone strategy | new-workspace |
|
||||
| --list | Scan ~/gsd-workspaces/, show summary table | list-workspaces |
|
||||
| --remove | Confirm and remove workspace directory | remove-workspace |
|
||||
|
||||
</routing>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/new-workspace.md
|
||||
@~/.claude/get-shit-done/workflows/list-workspaces.md
|
||||
@~/.claude/get-shit-done/workflows/remove-workspace.md
|
||||
@~/.claude/get-shit-done/references/ui-brand.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the first token of $ARGUMENTS:
|
||||
- If it is `--new`: strip the flag, pass remainder (--name, --repos, --path, --strategy, --branch, --auto flags) to new-workspace workflow
|
||||
- If it is `--list`: execute list-workspaces workflow (no argument needed)
|
||||
- If it is `--remove`: strip the flag, pass remainder (workspace-name) to remove-workspace workflow
|
||||
- Otherwise (no flag): show usage — one of --new, --list, or --remove is required
|
||||
</context>
|
||||
|
||||
<process>
|
||||
1. Parse the leading flag from $ARGUMENTS.
|
||||
2. Load and execute the appropriate workflow end-to-end based on the routing table above.
|
||||
3. Preserve all workflow gates from the target workflow (validation, approvals, commits, routing).
|
||||
</process>
|
||||
546
docs/COMMANDS.md
546
docs/COMMANDS.md
@@ -32,14 +32,17 @@ Initialize a new project with deep context gathering.
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-new-workspace`
|
||||
### `/gsd-workspace`
|
||||
|
||||
Create an isolated workspace with repo copies and independent `.planning/` directory.
|
||||
Manage GSD workspaces — create, list, or remove isolated workspace environments with repo copies and independent `.planning/` directories.
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--name <name>` | Workspace name (required) |
|
||||
| `--repos repo1,repo2` | Comma-separated repo paths or names |
|
||||
| `--new` | Create a new workspace (use with `--name`, `--repos`, etc.) |
|
||||
| `--list` | List active GSD workspaces and their status |
|
||||
| `--remove <name>` | Remove a workspace and clean up git worktrees |
|
||||
| `--name <name>` | Workspace name (used with `--new`) |
|
||||
| `--repos repo1,repo2` | Comma-separated repo paths or names (used with `--new`) |
|
||||
| `--path /target` | Target directory (default: `~/gsd-workspaces/<name>`) |
|
||||
| `--strategy worktree\|clone` | Copy strategy (default: `worktree`) |
|
||||
| `--branch <name>` | Branch to checkout (default: `workspace/<name>`) |
|
||||
@@ -52,38 +55,10 @@ Create an isolated workspace with repo copies and independent `.planning/` direc
|
||||
**Produces:** `WORKSPACE.md`, `.planning/`, repo copies (worktrees or clones)
|
||||
|
||||
```bash
|
||||
/gsd-new-workspace --name feature-b --repos hr-ui,ZeymoAPI
|
||||
/gsd-new-workspace --name feature-b --repos . --strategy worktree # Same-repo isolation
|
||||
/gsd-new-workspace --name spike --repos api,web --strategy clone # Full clones
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-list-workspaces`
|
||||
|
||||
List active GSD workspaces and their status.
|
||||
|
||||
**Scans:** `~/gsd-workspaces/` for `WORKSPACE.md` manifests
|
||||
**Shows:** Name, repo count, strategy, GSD project status
|
||||
|
||||
```bash
|
||||
/gsd-list-workspaces
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-remove-workspace`
|
||||
|
||||
Remove a workspace and clean up git worktrees.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `<name>` | Yes | Workspace name to remove |
|
||||
|
||||
**Safety:** Refuses removal if any repo has uncommitted changes. Requires name confirmation.
|
||||
|
||||
```bash
|
||||
/gsd-remove-workspace feature-b
|
||||
/gsd-workspace --new --name feature-b --repos hr-ui,ZeymoAPI
|
||||
/gsd-workspace --new --name feature-b --repos . --strategy worktree # Same-repo isolation
|
||||
/gsd-workspace --list
|
||||
/gsd-workspace --remove feature-b
|
||||
```
|
||||
|
||||
---
|
||||
@@ -247,43 +222,6 @@ User acceptance testing with auto-diagnosis.
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-next`
|
||||
|
||||
Automatically advance to the next logical workflow step. Reads project state and runs the appropriate command.
|
||||
|
||||
**Prerequisites:** `.planning/` directory exists
|
||||
**Behavior:**
|
||||
- No project → suggests `/gsd-new-project`
|
||||
- Phase needs discussion → runs `/gsd-discuss-phase`
|
||||
- Phase needs planning → runs `/gsd-plan-phase`
|
||||
- Phase needs execution → runs `/gsd-execute-phase`
|
||||
- Phase needs verification → runs `/gsd-verify-work`
|
||||
- All phases complete → suggests `/gsd-complete-milestone`
|
||||
|
||||
```bash
|
||||
/gsd-next # Auto-detect and run next step
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-session-report`
|
||||
|
||||
Generate a session report with work summary, outcomes, and estimated resource usage.
|
||||
|
||||
**Prerequisites:** Active project with recent work
|
||||
**Produces:** `.planning/reports/SESSION_REPORT.md`
|
||||
|
||||
```bash
|
||||
/gsd-session-report # Generate post-session summary
|
||||
```
|
||||
|
||||
**Report includes:**
|
||||
- Work performed (commits, plans executed, phases progressed)
|
||||
- Outcomes and deliverables
|
||||
- Blockers and decisions made
|
||||
- Estimated token/cost usage
|
||||
- Next steps recommendation
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-ship`
|
||||
@@ -417,112 +355,31 @@ Start next version cycle.
|
||||
|
||||
## Phase Management Commands
|
||||
|
||||
### `/gsd-add-phase`
|
||||
### `/gsd-phase`
|
||||
|
||||
Append new phase to roadmap.
|
||||
|
||||
```bash
|
||||
/gsd-add-phase # Interactive — describe the phase
|
||||
```
|
||||
|
||||
### `/gsd-edit-phase`
|
||||
|
||||
Edit any field of an existing roadmap phase in place.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | Yes | Phase number to edit |
|
||||
CRUD for phases in ROADMAP.md — add, insert, remove, or edit phases with a single consolidated command.
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--force` | Allow editing in-progress or completed phases |
|
||||
|
||||
**Prerequisites:** `.planning/ROADMAP.md` exists, phase N must exist
|
||||
**Produces:** Updated phase section in ROADMAP.md (in place, number and position preserved)
|
||||
|
||||
```bash
|
||||
/gsd-edit-phase 5 # Edit any field of phase 5 (future phases only)
|
||||
/gsd-edit-phase 5 --force # Edit phase 5 even if in-progress or completed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-insert-phase`
|
||||
|
||||
Insert urgent work between phases using decimal numbering.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | No | Insert after this phase number |
|
||||
|
||||
```bash
|
||||
/gsd-insert-phase 3 # Insert between phase 3 and 4 → creates 3.1
|
||||
```
|
||||
|
||||
### `/gsd-remove-phase`
|
||||
|
||||
Remove future phase and renumber subsequent phases.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | No | Phase number to remove |
|
||||
|
||||
```bash
|
||||
/gsd-remove-phase 7 # Remove phase 7, renumber 8→7, 9→8, etc.
|
||||
```
|
||||
|
||||
### `/gsd-list-phase-assumptions`
|
||||
|
||||
Preview Claude's intended approach before planning.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | No | Phase number |
|
||||
|
||||
```bash
|
||||
/gsd-list-phase-assumptions 2 # See assumptions for phase 2
|
||||
```
|
||||
|
||||
### `/gsd-analyze-dependencies`
|
||||
|
||||
Analyze phase dependencies and suggest `Depends on` entries for ROADMAP.md before running `/gsd-manager`.
|
||||
| (none) | Append a new integer phase to the end of the current milestone |
|
||||
| `--insert <N>` | Insert urgent work as a decimal phase (e.g., 3.1) after phase N |
|
||||
| `--remove <N>` | Remove a future phase and renumber subsequent phases |
|
||||
| `--edit <N>` | Edit any field of an existing phase in place |
|
||||
| `--force` | Allow editing in-progress or completed phases (used with `--edit`) |
|
||||
|
||||
**Prerequisites:** `.planning/ROADMAP.md` exists
|
||||
**Produces:** Dependency suggestion table; optionally updates `Depends on` fields in ROADMAP.md with confirmation
|
||||
|
||||
**Run this before `/gsd-manager`** when phases have empty `Depends on` fields and you want to avoid merge conflicts from unordered parallel execution.
|
||||
**Produces:** Updated ROADMAP.md
|
||||
|
||||
```bash
|
||||
/gsd-analyze-dependencies # Analyze all phases and suggest dependencies
|
||||
/gsd-phase "Add authentication system" # Append new phase with description
|
||||
/gsd-phase --insert 3 "Fix auth race condition" # Insert between phase 3 and 4 → creates 3.1
|
||||
/gsd-phase --remove 7 # Remove phase 7, renumber 8→7, 9→8, etc.
|
||||
/gsd-phase --edit 5 # Edit any field of phase 5
|
||||
/gsd-phase --edit 5 --force # Edit phase 5 even if in-progress or completed
|
||||
```
|
||||
|
||||
**Detection methods:**
|
||||
- File overlap — phases touching the same files/domains must be ordered
|
||||
- Semantic dependencies — a phase that consumes an API or schema built by another phase
|
||||
- Data flow — a phase that reads output produced by another phase
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-plan-milestone-gaps`
|
||||
|
||||
Create phases to close gaps from milestone audit.
|
||||
|
||||
```bash
|
||||
/gsd-plan-milestone-gaps # Creates phases for each audit gap
|
||||
```
|
||||
|
||||
### `/gsd-research-phase`
|
||||
|
||||
Deep ecosystem research only (standalone — usually use `/gsd-plan-phase` instead).
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | No | Phase number |
|
||||
|
||||
```bash
|
||||
/gsd-research-phase 4 # Research phase 4 domain
|
||||
```
|
||||
|
||||
### `/gsd-validate-phase`
|
||||
|
||||
Retroactively audit and fill Nyquist validation gaps.
|
||||
@@ -541,14 +398,26 @@ Retroactively audit and fill Nyquist validation gaps.
|
||||
|
||||
### `/gsd-progress`
|
||||
|
||||
Check project progress, show context, and route to the next action (execute or plan).
|
||||
Show status, next steps, and automatically advance to the next logical workflow step. Reads project state and determines the appropriate action.
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--next` | Automatically advance to the next logical workflow step without manual route selection |
|
||||
| `--do "task description"` | Analyze freeform intent and dispatch to the most appropriate GSD command |
|
||||
| `--forensic` | Append a 6-check integrity audit after the standard report (STATE consistency, orphaned handoffs, deferred scope drift, memory-flagged pending work, blocking todos, uncommitted code) |
|
||||
|
||||
**Auto-routing behavior (absorbed from `/gsd-next`):**
|
||||
- No project → suggests `/gsd-new-project`
|
||||
- Phase needs discussion → runs `/gsd-discuss-phase`
|
||||
- Phase needs planning → runs `/gsd-plan-phase`
|
||||
- Phase needs execution → runs `/gsd-execute-phase`
|
||||
- Phase needs verification → runs `/gsd-verify-work`
|
||||
- All phases complete → suggests `/gsd-complete-milestone`
|
||||
|
||||
```bash
|
||||
/gsd-progress # "Where am I? What's next?"
|
||||
/gsd-progress # "Where am I? What's next?" with auto-routing
|
||||
/gsd-progress --next # Advance to next step automatically
|
||||
/gsd-progress --do "fix the auth bug" # Dispatch freeform intent to best GSD command
|
||||
/gsd-progress --forensic # Standard report + integrity audit
|
||||
```
|
||||
|
||||
@@ -704,31 +573,6 @@ Bootstrap or merge a .planning/ setup from existing ADRs, PRDs, SPECs, and docs
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-from-gsd2`
|
||||
|
||||
Reverse migration from GSD-2 format (`.gsd/` with Milestone→Slice→Task hierarchy) back to v1 `.planning/` format.
|
||||
|
||||
| Flag | Required | Description |
|
||||
|------|----------|-------------|
|
||||
| `--dry-run` | No | Preview what would be migrated without writing anything |
|
||||
| `--force` | No | Overwrite existing `.planning/` directory |
|
||||
| `--path <dir>` | No | Specify GSD-2 root directory (defaults to current directory) |
|
||||
|
||||
**Flattening:** Milestone→Slice hierarchy is flattened to sequential phase numbers (M001/S01→phase 01, M001/S02→phase 02, M002/S01→phase 03, etc.).
|
||||
|
||||
**Produces:** `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`, and sequential phase directories in `.planning/`.
|
||||
|
||||
**Safety:** Guards against overwriting an existing `.planning/` directory without `--force`.
|
||||
|
||||
```bash
|
||||
/gsd-from-gsd2 # Migrate .gsd/ in current directory
|
||||
/gsd-from-gsd2 --dry-run # Preview migration without writing
|
||||
/gsd-from-gsd2 --force # Overwrite existing .planning/
|
||||
/gsd-from-gsd2 --path /path/to/gsd2-project # Specify GSD-2 root
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-quick`
|
||||
|
||||
Execute ad-hoc task with GSD guarantees.
|
||||
@@ -775,34 +619,6 @@ Run all remaining phases autonomously.
|
||||
/gsd-autonomous --from 3 --to 5 # Run phases 3 through 5
|
||||
```
|
||||
|
||||
### `/gsd-do`
|
||||
|
||||
Route freeform text to the right GSD command.
|
||||
|
||||
```bash
|
||||
/gsd-do # Then describe what you want
|
||||
```
|
||||
|
||||
### `/gsd-note`
|
||||
|
||||
Zero-friction idea capture — append, list, or promote notes to todos.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `text` | No | Note text to capture (default: append mode) |
|
||||
| `list` | No | List all notes from project and global scopes |
|
||||
| `promote N` | No | Convert note N into a structured todo |
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--global` | Use global scope for note operations |
|
||||
|
||||
```bash
|
||||
/gsd-note "Consider caching strategy for API responses"
|
||||
/gsd-note list
|
||||
/gsd-note promote 3
|
||||
```
|
||||
|
||||
### `/gsd-debug`
|
||||
|
||||
Systematic debugging with persistent state.
|
||||
@@ -831,26 +647,6 @@ Systematic debugging with persistent state.
|
||||
/gsd-debug continue form-submit-500
|
||||
```
|
||||
|
||||
### `/gsd-add-todo`
|
||||
|
||||
Capture idea or task for later.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `description` | No | Todo description |
|
||||
|
||||
```bash
|
||||
/gsd-add-todo "Consider adding dark mode support"
|
||||
```
|
||||
|
||||
### `/gsd-check-todos`
|
||||
|
||||
List pending todos and select one to work on.
|
||||
|
||||
```bash
|
||||
/gsd-check-todos
|
||||
```
|
||||
|
||||
### `/gsd-add-tests`
|
||||
|
||||
Generate tests for a completed phase.
|
||||
@@ -924,26 +720,16 @@ Run 2–5 focused feasibility experiments before committing to an implementation
|
||||
|----------|----------|-------------|
|
||||
| `idea` | No | The technical question or approach to investigate |
|
||||
| `--quick` | No | Skip intake conversation; use `idea` text directly |
|
||||
| `--wrap-up` | No | Package completed spike findings into a reusable project-local skill |
|
||||
|
||||
**Produces:** `.planning/spikes/NNN-experiment-name/` with code, results, and README; `.planning/spikes/MANIFEST.md`
|
||||
**`--wrap-up` produces:** `.claude/skills/spike-findings-[project]/` skill file
|
||||
|
||||
```bash
|
||||
/gsd-spike # Interactive intake
|
||||
/gsd-spike "can we stream LLM tokens through SSE"
|
||||
/gsd-spike --quick websocket-vs-polling
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-spike-wrap-up`
|
||||
|
||||
Package completed spike findings into a reusable project-local skill so future sessions can reference the conclusions.
|
||||
|
||||
**Prerequisites:** `.planning/spikes/` exists with at least one completed spike
|
||||
**Produces:** `.claude/skills/spike-findings-[project]/` skill file
|
||||
|
||||
```bash
|
||||
/gsd-spike-wrap-up
|
||||
/gsd-spike --wrap-up # Package findings into a reusable skill
|
||||
```
|
||||
|
||||
---
|
||||
@@ -957,27 +743,17 @@ Explore design directions through throwaway HTML mockups before committing to im
|
||||
| `idea` | No | The UI design question or direction to explore |
|
||||
| `--quick` | No | Skip mood intake; use `idea` text directly |
|
||||
| `--text` | No | Text-mode fallback — replace interactive prompts with numbered lists (for non-Claude runtimes) |
|
||||
| `--wrap-up` | No | Package winning sketch decisions into a reusable project-local skill |
|
||||
|
||||
**Produces:** `.planning/sketches/NNN-descriptive-name/index.html` (2–3 interactive variants), `README.md`, shared `themes/default.css`; `.planning/sketches/MANIFEST.md`
|
||||
**`--wrap-up` produces:** `.claude/skills/sketch-findings-[project]/` skill file
|
||||
|
||||
```bash
|
||||
/gsd-sketch # Interactive mood intake
|
||||
/gsd-sketch "dashboard layout"
|
||||
/gsd-sketch --quick "sidebar navigation"
|
||||
/gsd-sketch --text "onboarding flow" # Non-Claude runtime
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-sketch-wrap-up`
|
||||
|
||||
Package winning sketch decisions into a reusable project-local skill so future sessions inherit the visual direction.
|
||||
|
||||
**Prerequisites:** `.planning/sketches/` exists with at least one completed sketch (winner marked)
|
||||
**Produces:** `.claude/skills/sketch-findings-[project]/` skill file
|
||||
|
||||
```bash
|
||||
/gsd-sketch-wrap-up
|
||||
/gsd-sketch --wrap-up # Package winning sketch into a skill
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1092,11 +868,18 @@ All answers are merged via `gsd-sdk query config-set` into the resolved project
|
||||
/gsd-settings # Interactive config
|
||||
```
|
||||
|
||||
### `/gsd-settings-advanced`
|
||||
### `/gsd-config`
|
||||
|
||||
Power-user configuration for plan bounce, timeouts, branch templates, and cross-AI execution. Use after `/gsd-settings` once the common-case toggles are dialed in.
|
||||
Configure GSD settings interactively — workflow toggles, advanced knobs, integrations, and model profile — with a single consolidated command.
|
||||
|
||||
Six sections, each a focused prompt batch:
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| (none) | Common-case toggles: model, research, plan_check, verifier, branching |
|
||||
| `--advanced` | Power-user knobs: planning tuning, timeouts, branch templates, cross-AI execution, runtime/output |
|
||||
| `--integrations` | Third-party API keys, code-review CLI routing, agent-skill injection |
|
||||
| `--profile <name>` | Quick profile switch: `quality`, `balanced`, `budget`, or `inherit` |
|
||||
|
||||
**`--advanced` sections:**
|
||||
|
||||
| Section | Keys |
|
||||
|---------|------|
|
||||
@@ -1107,111 +890,44 @@ Six sections, each a focused prompt batch:
|
||||
| Git Customization | `git.base_branch`, `git.phase_branch_template`, `git.milestone_branch_template` |
|
||||
| Runtime / Output | `response_language`, `context_window`, `search_gitignored`, `graphify.build_timeout` |
|
||||
|
||||
Current values are pre-selected; an empty input keeps the existing value. Numeric fields reject non-numeric input and re-prompt. Null-allowed fields (`plan_bounce_script`, `cross_ai_command`, `response_language`) accept an empty input as a clear. Writes route through `gsd-sdk query config-set`, which preserves every unrelated key.
|
||||
All answers merge via `gsd-sdk query config-set`, preserving unrelated keys. API keys are masked (`****<last-4>`) in all output.
|
||||
|
||||
```bash
|
||||
/gsd-settings-advanced # Six-section interactive config
|
||||
/gsd-config # Common-case interactive config
|
||||
/gsd-config --advanced # Power-user knobs (six-section prompt)
|
||||
/gsd-config --integrations # API keys, review CLI routing, agent skills
|
||||
/gsd-config --profile budget # Switch to budget profile
|
||||
/gsd-config --profile quality # Switch to quality profile
|
||||
```
|
||||
|
||||
See [CONFIGURATION.md](CONFIGURATION.md) for the full schema and defaults.
|
||||
|
||||
### `/gsd-settings-integrations`
|
||||
|
||||
Interactive configuration of third-party integrations and cross-tool routing.
|
||||
Distinct from `/gsd-settings` (workflow toggles) — this command handles
|
||||
connectivity: API keys, reviewer CLI routing, and agent-skill injection.
|
||||
|
||||
Covers:
|
||||
|
||||
- **Search integrations:** `brave_search`, `firecrawl`, `exa_search` API keys,
|
||||
and the `search_gitignored` toggle.
|
||||
- **Code-review CLI routing:** `review.models.{claude,codex,gemini,opencode}`
|
||||
— a shell command per reviewer flavor.
|
||||
- **Agent-skill injection:** `agent_skills.<agent-type>` — skill names
|
||||
injected into an agent's spawn frontmatter. Agent-type slugs are validated
|
||||
against `[a-zA-Z0-9_-]+` so path separators and shell metacharacters are
|
||||
rejected.
|
||||
|
||||
API keys are stored plaintext in `.planning/config.json` but displayed masked
|
||||
(`****<last-4>`) in every interactive output, confirmation table, and
|
||||
`config-set` stdout/stderr line. Plaintext is never echoed, never logged,
|
||||
and never written to any file outside `config.json` by this workflow.
|
||||
|
||||
```bash
|
||||
/gsd-settings-integrations # Interactive config (three sections)
|
||||
```
|
||||
|
||||
See [`docs/CONFIGURATION.md`](CONFIGURATION.md) for the per-field reference and
|
||||
[`docs/CLI-TOOLS.md`](CLI-TOOLS.md) for the reviewer-CLI routing contract.
|
||||
|
||||
### `/gsd-set-profile`
|
||||
|
||||
Quick profile switch.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `profile` | **Yes** | `quality`, `balanced`, `budget`, or `inherit` |
|
||||
|
||||
```bash
|
||||
/gsd-set-profile budget # Switch to budget profile
|
||||
/gsd-set-profile quality # Switch to quality profile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Brownfield Commands
|
||||
|
||||
### `/gsd-map-codebase`
|
||||
|
||||
Analyze existing codebase with parallel mapper agents.
|
||||
Analyze existing codebase with parallel mapper agents. Use `--fast` for a quick single-agent scan, or `--query` to search existing intel.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `area` | No | Scope mapping to a specific area |
|
||||
|
||||
```bash
|
||||
/gsd-map-codebase # Full codebase analysis
|
||||
/gsd-map-codebase auth # Focus on auth area
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-scan`
|
||||
|
||||
Rapid single-focus codebase assessment — lightweight alternative to `/gsd-map-codebase` that spawns one mapper agent instead of four parallel ones.
|
||||
| `--fast` | No | Rapid single-focus assessment — spawns one mapper agent instead of four parallel ones (lightweight alternative) |
|
||||
| `--query <term>` | No | Search queryable codebase intel files in `.planning/intel/` (requires `intel.enabled: true`) |
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--focus tech\|arch\|quality\|concerns\|tech+arch` | Focus area (default: `tech+arch`) |
|
||||
| `--focus tech\|arch\|quality\|concerns\|tech+arch` | Focus area for `--fast` mode (default: `tech+arch`) |
|
||||
|
||||
**Produces:** Targeted document(s) in `.planning/codebase/`
|
||||
**Produces:** `.planning/codebase/` analysis documents (full mode); targeted document(s) in `.planning/codebase/` (`--fast`); intel query results (`--query`)
|
||||
|
||||
```bash
|
||||
/gsd-scan # Quick tech + arch overview
|
||||
/gsd-scan --focus quality # Quality and code health only
|
||||
/gsd-scan --focus concerns # Surface concerns and risk areas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-intel`
|
||||
|
||||
Query, inspect, or refresh queryable codebase intelligence files stored in `.planning/intel/`. Requires `intel.enabled: true` in `config.json`.
|
||||
|
||||
| Argument | Description |
|
||||
|----------|-------------|
|
||||
| `query <term>` | Search intel files for a term |
|
||||
| `status` | Show intel file freshness (FRESH/STALE) |
|
||||
| `diff` | Show changes since last snapshot |
|
||||
| `refresh` | Rebuild all intel files from codebase analysis |
|
||||
|
||||
**Produces:** `.planning/intel/` JSON files (stack, api-map, dependency-graph, file-roles, arch-decisions)
|
||||
|
||||
```bash
|
||||
/gsd-intel status # Check freshness of intel files
|
||||
/gsd-intel query authentication # Search intel for a term
|
||||
/gsd-intel diff # What changed since last snapshot
|
||||
/gsd-intel refresh # Rebuild intel index
|
||||
/gsd-map-codebase # Full codebase analysis (4 parallel agents)
|
||||
/gsd-map-codebase auth # Focus on auth area
|
||||
/gsd-map-codebase --fast # Quick tech + arch overview (1 agent)
|
||||
/gsd-map-codebase --fast --focus quality # Quality and code health only
|
||||
/gsd-map-codebase --query authentication # Search intel for a term
|
||||
```
|
||||
|
||||
### `/gsd-graphify`
|
||||
@@ -1273,18 +989,17 @@ Audit an executed AI phase's evaluation coverage and produce an EVAL-REVIEW.md r
|
||||
|
||||
### `/gsd-update`
|
||||
|
||||
Update GSD with changelog preview.
|
||||
Update GSD with changelog preview, and optionally sync skills or reapply local patches.
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--sync` | Sync skills from the GSD registry after updating |
|
||||
| `--reapply` | Restore local modifications (patches) after updating |
|
||||
|
||||
```bash
|
||||
/gsd-update # Check for updates and install
|
||||
```
|
||||
|
||||
### `/gsd-reapply-patches`
|
||||
|
||||
Restore local modifications after a GSD update.
|
||||
|
||||
```bash
|
||||
/gsd-reapply-patches # Merge back local changes
|
||||
/gsd-update --sync # Update and sync skills
|
||||
/gsd-update --reapply # Update and reapply local patches
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1293,44 +1008,28 @@ Restore local modifications after a GSD update.
|
||||
|
||||
### `/gsd-code-review`
|
||||
|
||||
Review source files changed during a phase for bugs, security vulnerabilities, and code quality problems.
|
||||
Review source files changed during a phase for bugs, security vulnerabilities, and code quality problems. Use `--fix` to auto-fix findings after review.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | **Yes** | Phase number whose changes to review (e.g., `2` or `02`) |
|
||||
| `--depth=quick\|standard\|deep` | No | Review depth level (overrides `workflow.code_review_depth` config). `quick`: pattern-matching only (~2 min). `standard`: per-file analysis with language-specific checks (~5–15 min, default). `deep`: cross-file analysis including import graphs and call chains (~15–30 min) |
|
||||
| `--files file1,file2,...` | No | Explicit comma-separated file list; skips SUMMARY/git scoping entirely |
|
||||
| `--fix` | No | Auto-fix issues after review — reads REVIEW.md, spawns fixer agent, commits each fix atomically |
|
||||
| `--fix --all` | No | Include Info findings in fix scope (default: Critical + Warning only) |
|
||||
| `--fix --auto` | No | Fix + re-review iteration loop, capped at 3 iterations |
|
||||
|
||||
**Prerequisites:** Phase has been executed and has SUMMARY.md or git history
|
||||
**Produces:** `{phase}-REVIEW.md` in phase directory with severity-classified findings
|
||||
**Spawns:** `gsd-code-reviewer` agent
|
||||
**Produces:** `{phase}-REVIEW.md` with severity-classified findings; `{phase}-REVIEW-FIX.md` when `--fix` is used
|
||||
**Spawns:** `gsd-code-reviewer` agent; `gsd-code-fixer` agent (with `--fix`)
|
||||
|
||||
```bash
|
||||
/gsd-code-review 3 # Standard review for phase 3
|
||||
/gsd-code-review 2 --depth=deep # Deep cross-file review
|
||||
/gsd-code-review 4 --files src/auth.ts,src/token.ts # Explicit file list
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-code-review-fix`
|
||||
|
||||
Auto-fix issues found by code review in REVIEW.md; commits each fix atomically. Reads `REVIEW.md`, spawns a fixer agent, and produces a `REVIEW-FIX.md` summary.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `N` | **Yes** | Phase number whose REVIEW.md to fix |
|
||||
| `--all` | No | Include Info findings in fix scope (default: Critical + Warning only) |
|
||||
| `--auto` | No | Enable fix + re-review iteration loop, capped at 3 iterations |
|
||||
|
||||
**Prerequisites:** Phase has a `{phase}-REVIEW.md` file (run `/gsd-code-review` first)
|
||||
**Produces:** `{phase}-REVIEW-FIX.md` with applied fixes summary
|
||||
**Spawns:** `gsd-code-fixer` agent
|
||||
|
||||
```bash
|
||||
/gsd-code-review-fix 3 # Fix Critical + Warning findings for phase 3
|
||||
/gsd-code-review-fix 3 --all # Include Info findings
|
||||
/gsd-code-review-fix 3 --auto # Fix and re-review until clean (max 3 iterations)
|
||||
/gsd-code-review 3 --fix # Review then fix Critical + Warning findings
|
||||
/gsd-code-review 3 --fix --all # Review then fix all findings including Info
|
||||
/gsd-code-review 3 --fix --auto # Review, fix, and re-review until clean (max 3 iterations)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1422,19 +1121,6 @@ Create a clean PR branch by filtering out `.planning/` commits.
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-audit-uat`
|
||||
|
||||
Cross-phase audit of all outstanding UAT and verification items.
|
||||
|
||||
**Prerequisites:** At least one phase has been executed with UAT or verification
|
||||
**Produces:** Categorized audit report with human test plan
|
||||
|
||||
```bash
|
||||
/gsd-audit-uat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-secure-phase`
|
||||
|
||||
Retroactively verify threat mitigations for a completed phase.
|
||||
@@ -1481,21 +1167,34 @@ Each doc writer explores the codebase directly — no hallucinated paths or stal
|
||||
|
||||
---
|
||||
|
||||
## Backlog & Thread Commands
|
||||
## Task Capture & Backlog Commands
|
||||
|
||||
### `/gsd-add-backlog`
|
||||
### `/gsd-capture`
|
||||
|
||||
Add an idea to the backlog parking lot using 999.x numbering.
|
||||
Capture ideas, tasks, notes, and seeds to their appropriate destination. Default mode adds a structured todo; flags route to specialized capture workflows.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `description` | **Yes** | Backlog item description |
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| (none) | Capture as a structured todo for later work |
|
||||
| `--note [text]` | Zero-friction note — append, list (`--note list`), or promote (`--note promote N`) |
|
||||
| `--backlog <description>` | Add to the backlog parking lot using 999.x numbering |
|
||||
| `--seed [idea summary]` | Capture a forward-looking idea with trigger conditions |
|
||||
| `--list` | List pending todos and select one to work on |
|
||||
| `--global` | Use global scope (for note operations) |
|
||||
|
||||
**999.x numbering** keeps backlog items outside the active phase sequence. Phase directories are created immediately so `/gsd-discuss-phase` and `/gsd-plan-phase` work on them.
|
||||
**Backlog:** 999.x numbering keeps items outside the active phase sequence; phase directories are created immediately so `/gsd-discuss-phase` and `/gsd-plan-phase` work on them.
|
||||
**Seeds:** Preserve full WHY, WHEN to surface, and breadcrumbs — consumed by `/gsd-new-milestone`.
|
||||
|
||||
**Produces:** `.planning/todos/` (default), note files (--note), ROADMAP.md backlog section (--backlog), `.planning/seeds/SEED-NNN-slug.md` (--seed)
|
||||
|
||||
```bash
|
||||
/gsd-add-backlog "GraphQL API layer"
|
||||
/gsd-add-backlog "Mobile responsive redesign"
|
||||
/gsd-capture "Consider adding dark mode support" # Add todo
|
||||
/gsd-capture --note "Caching strategy idea" # Quick note
|
||||
/gsd-capture --note list # List all notes
|
||||
/gsd-capture --note promote 3 # Promote note 3 to todo
|
||||
/gsd-capture --backlog "GraphQL API layer" # Add to backlog
|
||||
/gsd-capture --seed "Add real-time collaboration when WebSocket infra is in place"
|
||||
/gsd-capture --list # Browse and act on todos
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1512,25 +1211,6 @@ Review and promote backlog items to active milestone.
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-plant-seed`
|
||||
|
||||
Capture a forward-looking idea that surfaces automatically at the right milestone.
|
||||
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `idea summary` | No | Seed description (prompted if omitted) |
|
||||
|
||||
Seeds solve context rot: instead of a one-liner in Deferred that nobody reads, a seed preserves the full WHY, WHEN to surface, and breadcrumbs to details.
|
||||
|
||||
**Produces:** `.planning/seeds/SEED-NNN-slug.md`
|
||||
**Consumed by:** `/gsd-new-milestone` (scans seeds and presents matches)
|
||||
|
||||
```bash
|
||||
/gsd-plant-seed "Add real-time collaboration when WebSocket infra is in place"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-thread`
|
||||
|
||||
Manage persistent context threads for cross-session work.
|
||||
@@ -1629,13 +1309,9 @@ Enable with:
|
||||
|
||||
---
|
||||
|
||||
### `/gsd-join-discord`
|
||||
### Community Invite
|
||||
|
||||
Open Discord community invite.
|
||||
|
||||
```bash
|
||||
/gsd-join-discord
|
||||
```
|
||||
To join the GSD Discord community, visit the link in the GSD README or run `/gsd-help` and follow the Discord link shown there.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated": "2026-04-27",
|
||||
"generated": "2026-04-30",
|
||||
"families": {
|
||||
"agents": [
|
||||
"gsd-advisor-researcher",
|
||||
@@ -37,83 +37,55 @@
|
||||
"gsd-verifier"
|
||||
],
|
||||
"commands": [
|
||||
"/gsd-add-backlog",
|
||||
"/gsd-add-phase",
|
||||
"/gsd-add-tests",
|
||||
"/gsd-add-todo",
|
||||
"/gsd-ai-integration-phase",
|
||||
"/gsd-analyze-dependencies",
|
||||
"/gsd-audit-fix",
|
||||
"/gsd-audit-milestone",
|
||||
"/gsd-audit-uat",
|
||||
"/gsd-autonomous",
|
||||
"/gsd-check-todos",
|
||||
"/gsd-capture",
|
||||
"/gsd-cleanup",
|
||||
"/gsd-code-review",
|
||||
"/gsd-code-review-fix",
|
||||
"/gsd-complete-milestone",
|
||||
"/gsd-config",
|
||||
"/gsd-debug",
|
||||
"/gsd-discuss-phase",
|
||||
"/gsd-do",
|
||||
"/gsd-docs-update",
|
||||
"/gsd-edit-phase",
|
||||
"/gsd-eval-review",
|
||||
"/gsd-execute-phase",
|
||||
"/gsd-explore",
|
||||
"/gsd-extract-learnings",
|
||||
"/gsd-fast",
|
||||
"/gsd-forensics",
|
||||
"/gsd-from-gsd2",
|
||||
"/gsd-graphify",
|
||||
"/gsd-health",
|
||||
"/gsd-help",
|
||||
"/gsd-import",
|
||||
"/gsd-inbox",
|
||||
"/gsd-ingest-docs",
|
||||
"/gsd-insert-phase",
|
||||
"/gsd-intel",
|
||||
"/gsd-join-discord",
|
||||
"/gsd-list-phase-assumptions",
|
||||
"/gsd-list-workspaces",
|
||||
"/gsd-manager",
|
||||
"/gsd-map-codebase",
|
||||
"/gsd-milestone-summary",
|
||||
"/gsd-new-milestone",
|
||||
"/gsd-new-project",
|
||||
"/gsd-new-workspace",
|
||||
"/gsd-next",
|
||||
"/gsd-note",
|
||||
"/gsd-pause-work",
|
||||
"/gsd-plan-milestone-gaps",
|
||||
"/gsd-phase",
|
||||
"/gsd-plan-phase",
|
||||
"/gsd-plan-review-convergence",
|
||||
"/gsd-plant-seed",
|
||||
"/gsd-pr-branch",
|
||||
"/gsd-profile-user",
|
||||
"/gsd-progress",
|
||||
"/gsd-quick",
|
||||
"/gsd-reapply-patches",
|
||||
"/gsd-remove-phase",
|
||||
"/gsd-remove-workspace",
|
||||
"/gsd-research-phase",
|
||||
"/gsd-resume-work",
|
||||
"/gsd-review",
|
||||
"/gsd-review-backlog",
|
||||
"/gsd-scan",
|
||||
"/gsd-secure-phase",
|
||||
"/gsd-session-report",
|
||||
"/gsd-set-profile",
|
||||
"/gsd-settings",
|
||||
"/gsd-settings-advanced",
|
||||
"/gsd-settings-integrations",
|
||||
"/gsd-ship",
|
||||
"/gsd-sketch",
|
||||
"/gsd-sketch-wrap-up",
|
||||
"/gsd-spec-phase",
|
||||
"/gsd-spike",
|
||||
"/gsd-spike-wrap-up",
|
||||
"/gsd-stats",
|
||||
"/gsd-sync-skills",
|
||||
"/gsd-thread",
|
||||
"/gsd-ui-phase",
|
||||
"/gsd-ui-review",
|
||||
@@ -122,6 +94,7 @@
|
||||
"/gsd-update",
|
||||
"/gsd-validate-phase",
|
||||
"/gsd-verify-work",
|
||||
"/gsd-workspace",
|
||||
"/gsd-workstreams"
|
||||
],
|
||||
"workflows": [
|
||||
@@ -181,6 +154,7 @@
|
||||
"profile-user.md",
|
||||
"progress.md",
|
||||
"quick.md",
|
||||
"reapply-patches.md",
|
||||
"remove-phase.md",
|
||||
"remove-workspace.md",
|
||||
"research-phase.md",
|
||||
|
||||
@@ -54,7 +54,7 @@ Full roster at `agents/gsd-*.md`. The "Primary doc" column flags whether [`docs/
|
||||
|
||||
---
|
||||
|
||||
## Commands (86 shipped)
|
||||
## Commands (59 shipped)
|
||||
|
||||
Full roster at `commands/gsd/*.md`. The groupings below mirror `docs/COMMANDS.md` section order; each row carries the command name, a one-line role derived from the command's frontmatter `description:`, and a link to the source file. `tests/command-count-sync.test.cjs` locks the count against the filesystem.
|
||||
|
||||
@@ -63,9 +63,7 @@ Full roster at `commands/gsd/*.md`. The groupings below mirror `docs/COMMANDS.md
|
||||
| Command | Role | Source |
|
||||
|---------|------|--------|
|
||||
| `/gsd-new-project` | Initialize a new project with deep context gathering and PROJECT.md. | [commands/gsd/new-project.md](../commands/gsd/new-project.md) |
|
||||
| `/gsd-new-workspace` | Create an isolated workspace with repo copies and independent `.planning/`. | [commands/gsd/new-workspace.md](../commands/gsd/new-workspace.md) |
|
||||
| `/gsd-list-workspaces` | List active GSD workspaces and their status. | [commands/gsd/list-workspaces.md](../commands/gsd/list-workspaces.md) |
|
||||
| `/gsd-remove-workspace` | Remove a GSD workspace and clean up worktrees. | [commands/gsd/remove-workspace.md](../commands/gsd/remove-workspace.md) |
|
||||
| `/gsd-workspace` | Manage GSD workspaces — create (`--new`), list (`--list`), or remove (`--remove`) isolated workspace environments. | [commands/gsd/workspace.md](../commands/gsd/workspace.md) |
|
||||
| `/gsd-discuss-phase` | Gather phase context through adaptive questioning before planning. | [commands/gsd/discuss-phase.md](../commands/gsd/discuss-phase.md) |
|
||||
| `/gsd-spec-phase` | Socratic spec refinement producing a SPEC.md with falsifiable requirements. | [commands/gsd/spec-phase.md](../commands/gsd/spec-phase.md) |
|
||||
| `/gsd-ui-phase` | Generate UI design contract (UI-SPEC.md) for frontend phases. | [commands/gsd/ui-phase.md](../commands/gsd/ui-phase.md) |
|
||||
@@ -73,37 +71,28 @@ Full roster at `commands/gsd/*.md`. The groupings below mirror `docs/COMMANDS.md
|
||||
| `/gsd-plan-phase` | Create detailed phase plan (PLAN.md) with verification loop. | [commands/gsd/plan-phase.md](../commands/gsd/plan-phase.md) |
|
||||
| `/gsd-plan-review-convergence` | Cross-AI plan convergence loop — replan with review feedback until no HIGH concerns remain (max 3 cycles). | [commands/gsd/plan-review-convergence.md](../commands/gsd/plan-review-convergence.md) |
|
||||
| `/gsd-ultraplan-phase` | [BETA] Offload plan phase to Claude Code's ultraplan cloud — drafts remotely, review in browser, import back via `/gsd-import`. Claude Code only. | [commands/gsd/ultraplan-phase.md](../commands/gsd/ultraplan-phase.md) |
|
||||
| `/gsd-spike` | Rapidly spike an idea with throwaway experiments to validate feasibility before planning. | [commands/gsd/spike.md](../commands/gsd/spike.md) |
|
||||
| `/gsd-sketch` | Rapidly sketch UI/design ideas using throwaway HTML mockups with multi-variant exploration. | [commands/gsd/sketch.md](../commands/gsd/sketch.md) |
|
||||
| `/gsd-research-phase` | Research how to implement a phase (standalone). | [commands/gsd/research-phase.md](../commands/gsd/research-phase.md) |
|
||||
| `/gsd-spike` | Rapidly spike an idea with throwaway experiments; use `--wrap-up` to package findings as a persistent skill. | [commands/gsd/spike.md](../commands/gsd/spike.md) |
|
||||
| `/gsd-sketch` | Rapidly sketch UI/design ideas using throwaway HTML mockups; use `--wrap-up` to package findings. | [commands/gsd/sketch.md](../commands/gsd/sketch.md) |
|
||||
| `/gsd-execute-phase` | Execute all plans in a phase with wave-based parallelization. | [commands/gsd/execute-phase.md](../commands/gsd/execute-phase.md) |
|
||||
| `/gsd-verify-work` | Validate built features through conversational UAT with auto-diagnosis. | [commands/gsd/verify-work.md](../commands/gsd/verify-work.md) |
|
||||
| `/gsd-ship` | Create PR, run review, and prepare for merge after verification. | [commands/gsd/ship.md](../commands/gsd/ship.md) |
|
||||
| `/gsd-next` | Automatically advance to the next logical step in the GSD workflow. | [commands/gsd/next.md](../commands/gsd/next.md) |
|
||||
| `/gsd-fast` | Execute a trivial task inline — no subagents, no planning overhead. | [commands/gsd/fast.md](../commands/gsd/fast.md) |
|
||||
| `/gsd-quick` | Execute a quick task with GSD guarantees (atomic commits, state tracking) but skip optional agents. | [commands/gsd/quick.md](../commands/gsd/quick.md) |
|
||||
| `/gsd-ui-review` | Retroactive 6-pillar visual audit of implemented frontend code. | [commands/gsd/ui-review.md](../commands/gsd/ui-review.md) |
|
||||
| `/gsd-code-review` | Review source files changed during a phase for bugs, security, and code-quality problems. | [commands/gsd/code-review.md](../commands/gsd/code-review.md) |
|
||||
| `/gsd-code-review-fix` | Auto-fix issues found by `/gsd-code-review`, committing each fix atomically. | [commands/gsd/code-review-fix.md](../commands/gsd/code-review-fix.md) |
|
||||
| `/gsd-code-review` | Review source files changed during a phase for bugs, security, and code-quality problems; use `--fix` to auto-apply findings. | [commands/gsd/code-review.md](../commands/gsd/code-review.md) |
|
||||
| `/gsd-eval-review` | Retroactively audit an executed AI phase's evaluation coverage; produces EVAL-REVIEW.md. | [commands/gsd/eval-review.md](../commands/gsd/eval-review.md) |
|
||||
|
||||
### Phase & Milestone Management
|
||||
|
||||
| Command | Role | Source |
|
||||
|---------|------|--------|
|
||||
| `/gsd-add-phase` | Add phase to end of current milestone in roadmap. | [commands/gsd/add-phase.md](../commands/gsd/add-phase.md) |
|
||||
| `/gsd-edit-phase` | Edit any field of an existing roadmap phase in place, preserving number and position. | [commands/gsd/edit-phase.md](../commands/gsd/edit-phase.md) |
|
||||
| `/gsd-insert-phase` | Insert urgent work as decimal phase (e.g., 72.1) between existing phases. | [commands/gsd/insert-phase.md](../commands/gsd/insert-phase.md) |
|
||||
| `/gsd-remove-phase` | Remove a future phase from roadmap and renumber subsequent phases. | [commands/gsd/remove-phase.md](../commands/gsd/remove-phase.md) |
|
||||
| `/gsd-phase` | CRUD for phases — add (default), insert (`--insert`), remove (`--remove`), or edit (`--edit`) phases in ROADMAP.md. | [commands/gsd/phase.md](../commands/gsd/phase.md) |
|
||||
| `/gsd-add-tests` | Generate tests for a completed phase based on UAT criteria and implementation. | [commands/gsd/add-tests.md](../commands/gsd/add-tests.md) |
|
||||
| `/gsd-list-phase-assumptions` | Surface Claude's assumptions about a phase approach before planning. | [commands/gsd/list-phase-assumptions.md](../commands/gsd/list-phase-assumptions.md) |
|
||||
| `/gsd-analyze-dependencies` | Analyze phase dependencies and suggest `Depends on` entries for ROADMAP.md. | [commands/gsd/analyze-dependencies.md](../commands/gsd/analyze-dependencies.md) |
|
||||
| `/gsd-validate-phase` | Retroactively audit and fill Nyquist validation gaps for a completed phase. | [commands/gsd/validate-phase.md](../commands/gsd/validate-phase.md) |
|
||||
| `/gsd-secure-phase` | Retroactively verify threat mitigations for a completed phase. | [commands/gsd/secure-phase.md](../commands/gsd/secure-phase.md) |
|
||||
| `/gsd-audit-milestone` | Audit milestone completion against original intent before archiving. | [commands/gsd/audit-milestone.md](../commands/gsd/audit-milestone.md) |
|
||||
| `/gsd-audit-uat` | Cross-phase audit of all outstanding UAT and verification items. | [commands/gsd/audit-uat.md](../commands/gsd/audit-uat.md) |
|
||||
| `/gsd-audit-fix` | Autonomous audit-to-fix pipeline — find issues, classify, fix, test, commit. | [commands/gsd/audit-fix.md](../commands/gsd/audit-fix.md) |
|
||||
| `/gsd-plan-milestone-gaps` | Create phases to close all gaps identified by milestone audit. | [commands/gsd/plan-milestone-gaps.md](../commands/gsd/plan-milestone-gaps.md) |
|
||||
| `/gsd-complete-milestone` | Archive completed milestone and prepare for next version. | [commands/gsd/complete-milestone.md](../commands/gsd/complete-milestone.md) |
|
||||
| `/gsd-new-milestone` | Start a new milestone cycle — update PROJECT.md and route to requirements. | [commands/gsd/new-milestone.md](../commands/gsd/new-milestone.md) |
|
||||
| `/gsd-milestone-summary` | Generate a comprehensive project summary from milestone artifacts. | [commands/gsd/milestone-summary.md](../commands/gsd/milestone-summary.md) |
|
||||
@@ -117,28 +106,20 @@ Full roster at `commands/gsd/*.md`. The groupings below mirror `docs/COMMANDS.md
|
||||
|
||||
| Command | Role | Source |
|
||||
|---------|------|--------|
|
||||
| `/gsd-progress` | Check project progress, show context, and route to next action. | [commands/gsd/progress.md](../commands/gsd/progress.md) |
|
||||
| `/gsd-progress` | Check project progress, show context, and route to next action; use `--next` to advance automatically or `--do` to run a freeform task. | [commands/gsd/progress.md](../commands/gsd/progress.md) |
|
||||
| `/gsd-capture` | Capture ideas, tasks, notes, and seeds — todo (default), `--note`, `--backlog`, `--seed`, or `--list` pending todos. | [commands/gsd/capture.md](../commands/gsd/capture.md) |
|
||||
| `/gsd-stats` | Display project statistics — phases, plans, requirements, git metrics, timeline. | [commands/gsd/stats.md](../commands/gsd/stats.md) |
|
||||
| `/gsd-session-report` | Generate a session report with token usage estimates, work summary, outcomes. | [commands/gsd/session-report.md](../commands/gsd/session-report.md) |
|
||||
| `/gsd-pause-work` | Create context handoff when pausing work mid-phase. | [commands/gsd/pause-work.md](../commands/gsd/pause-work.md) |
|
||||
| `/gsd-resume-work` | Resume work from previous session with full context restoration. | [commands/gsd/resume-work.md](../commands/gsd/resume-work.md) |
|
||||
| `/gsd-explore` | Socratic ideation and idea routing — think through ideas before committing. | [commands/gsd/explore.md](../commands/gsd/explore.md) |
|
||||
| `/gsd-do` | Route freeform text to the right GSD command automatically. | [commands/gsd/do.md](../commands/gsd/do.md) |
|
||||
| `/gsd-note` | Zero-friction idea capture — append, list, or promote notes to todos. | [commands/gsd/note.md](../commands/gsd/note.md) |
|
||||
| `/gsd-add-todo` | Capture idea or task as todo from current conversation context. | [commands/gsd/add-todo.md](../commands/gsd/add-todo.md) |
|
||||
| `/gsd-check-todos` | List pending todos and select one to work on. | [commands/gsd/check-todos.md](../commands/gsd/check-todos.md) |
|
||||
| `/gsd-add-backlog` | Add an idea to the backlog parking lot (999.x numbering). | [commands/gsd/add-backlog.md](../commands/gsd/add-backlog.md) |
|
||||
| `/gsd-review-backlog` | Review and promote backlog items to active milestone. | [commands/gsd/review-backlog.md](../commands/gsd/review-backlog.md) |
|
||||
| `/gsd-plant-seed` | Capture a forward-looking idea with trigger conditions. | [commands/gsd/plant-seed.md](../commands/gsd/plant-seed.md) |
|
||||
| `/gsd-thread` | Manage persistent context threads for cross-session work. | [commands/gsd/thread.md](../commands/gsd/thread.md) |
|
||||
|
||||
### Codebase Intelligence
|
||||
|
||||
| Command | Role | Source |
|
||||
|---------|------|--------|
|
||||
| `/gsd-map-codebase` | Analyze codebase with parallel mapper agents; produces `.planning/codebase/` documents. | [commands/gsd/map-codebase.md](../commands/gsd/map-codebase.md) |
|
||||
| `/gsd-scan` | Rapid codebase assessment — lightweight alternative to `/gsd-map-codebase`. | [commands/gsd/scan.md](../commands/gsd/scan.md) |
|
||||
| `/gsd-intel` | Query, inspect, or refresh codebase intelligence files in `.planning/intel/`. | [commands/gsd/intel.md](../commands/gsd/intel.md) |
|
||||
| `/gsd-map-codebase` | Analyze codebase with parallel mapper agents; use `--fast` for lightweight scan or `--query` for intel queries. | [commands/gsd/map-codebase.md](../commands/gsd/map-codebase.md) |
|
||||
| `/gsd-graphify` | Build, query, and inspect the project knowledge graph in `.planning/graphs/`. | [commands/gsd/graphify.md](../commands/gsd/graphify.md) |
|
||||
| `/gsd-extract-learnings` | Extract decisions, lessons, patterns, and surprises from completed phase artifacts. | [commands/gsd/extract-learnings.md](../commands/gsd/extract-learnings.md) |
|
||||
|
||||
@@ -151,7 +132,6 @@ Full roster at `commands/gsd/*.md`. The groupings below mirror `docs/COMMANDS.md
|
||||
| `/gsd-forensics` | Post-mortem investigation for failed GSD workflows — analyzes git, artifacts, state. | [commands/gsd/forensics.md](../commands/gsd/forensics.md) |
|
||||
| `/gsd-health` | Diagnose planning directory health and optionally repair issues. | [commands/gsd/health.md](../commands/gsd/health.md) |
|
||||
| `/gsd-import` | Ingest external plans with conflict detection against project decisions. | [commands/gsd/import.md](../commands/gsd/import.md) |
|
||||
| `/gsd-from-gsd2` | Import a GSD-2 (`.gsd/`) project back to GSD v1 (`.planning/`) format. | [commands/gsd/from-gsd2.md](../commands/gsd/from-gsd2.md) |
|
||||
| `/gsd-inbox` | Triage and review all open GitHub issues and PRs against project templates. | [commands/gsd/inbox.md](../commands/gsd/inbox.md) |
|
||||
|
||||
### Docs, Profile & Utilities
|
||||
@@ -160,23 +140,16 @@ Full roster at `commands/gsd/*.md`. The groupings below mirror `docs/COMMANDS.md
|
||||
|---------|------|--------|
|
||||
| `/gsd-docs-update` | Generate or update project documentation verified against the codebase. | [commands/gsd/docs-update.md](../commands/gsd/docs-update.md) |
|
||||
| `/gsd-ingest-docs` | Scan a repo for mixed ADRs/PRDs/SPECs/DOCs and bootstrap or merge the full `.planning/` setup with classification, synthesis, and conflicts report. | [commands/gsd/ingest-docs.md](../commands/gsd/ingest-docs.md) |
|
||||
| `/gsd-spike-wrap-up` | Package spike findings into a persistent project skill for future build conversations. | [commands/gsd/spike-wrap-up.md](../commands/gsd/spike-wrap-up.md) |
|
||||
| `/gsd-sketch-wrap-up` | Package sketch design findings into a persistent project skill for future build conversations. | [commands/gsd/sketch-wrap-up.md](../commands/gsd/sketch-wrap-up.md) |
|
||||
| `/gsd-profile-user` | Generate developer behavioral profile and Claude-discoverable artifacts. | [commands/gsd/profile-user.md](../commands/gsd/profile-user.md) |
|
||||
| `/gsd-settings` | Configure GSD workflow toggles and model profile. | [commands/gsd/settings.md](../commands/gsd/settings.md) |
|
||||
| `/gsd-settings-advanced` | Power-user configuration — plan bounce, timeouts, branch templates, cross-AI execution, runtime knobs. | [commands/gsd/settings-advanced.md](../commands/gsd/settings-advanced.md) |
|
||||
| `/gsd-settings-integrations` | Configure third-party API keys, code-review CLI routing, and agent-skill injection. | [commands/gsd/settings-integrations.md](../commands/gsd/settings-integrations.md) |
|
||||
| `/gsd-set-profile` | Switch model profile for GSD agents (quality/balanced/budget/inherit). | [commands/gsd/set-profile.md](../commands/gsd/set-profile.md) |
|
||||
| `/gsd-config` | Configure GSD settings — workflow toggles (default), advanced knobs (`--advanced`), integrations (`--integrations`), or model profile (`--profile`). | [commands/gsd/config.md](../commands/gsd/config.md) |
|
||||
| `/gsd-pr-branch` | Create a clean PR branch by filtering out `.planning/` commits. | [commands/gsd/pr-branch.md](../commands/gsd/pr-branch.md) |
|
||||
| `/gsd-sync-skills` | Sync managed GSD skill directories across runtime roots for multi-runtime users. | [commands/gsd/sync-skills.md](../commands/gsd/sync-skills.md) |
|
||||
| `/gsd-update` | Update GSD to latest version with changelog display. | [commands/gsd/update.md](../commands/gsd/update.md) |
|
||||
| `/gsd-reapply-patches` | Reapply local modifications after a GSD update. | [commands/gsd/reapply-patches.md](../commands/gsd/reapply-patches.md) |
|
||||
| `/gsd-update` | Update GSD to latest version; use `--sync` to sync skills across runtimes or `--reapply` to reapply local patches. | [commands/gsd/update.md](../commands/gsd/update.md) |
|
||||
| `/gsd-help` | Show available GSD commands and usage guide. | [commands/gsd/help.md](../commands/gsd/help.md) |
|
||||
| `/gsd-join-discord` | Join the GSD Discord community. | [commands/gsd/join-discord.md](../commands/gsd/join-discord.md) |
|
||||
|
||||
---
|
||||
|
||||
## Workflows (84 shipped)
|
||||
## Workflows (85 shipped)
|
||||
|
||||
Full roster at `get-shit-done/workflows/*.md`. Workflows are thin orchestrators that commands reference internally; most are not read directly by end users. Rows below map each workflow file to its role (derived from the `<purpose>` block) and, where applicable, to the command that invokes it.
|
||||
|
||||
@@ -184,14 +157,14 @@ Full roster at `get-shit-done/workflows/*.md`. Workflows are thin orchestrators
|
||||
|----------|------|------------|
|
||||
| `add-phase.md` | Add a new integer phase to the end of the current milestone in the roadmap. | `/gsd-add-phase` |
|
||||
| `add-tests.md` | Generate unit and E2E tests for a completed phase based on its artifacts. | `/gsd-add-tests` |
|
||||
| `add-todo.md` | Capture an idea or task that surfaces during a session as a structured todo. | `/gsd-add-todo`, `/gsd-add-backlog` |
|
||||
| `add-todo.md` | Capture an idea or task that surfaces during a session as a structured todo. | `/gsd-capture` (default), `/gsd-capture --backlog` |
|
||||
| `ai-integration-phase.md` | Orchestrate framework selection → AI research → domain research → eval planning into AI-SPEC.md. | `/gsd-ai-integration-phase` |
|
||||
| `analyze-dependencies.md` | Analyze ROADMAP.md phases for file overlap and semantic dependencies; suggest `Depends on` edges. | `/gsd-analyze-dependencies` |
|
||||
| `audit-fix.md` | Autonomous audit-to-fix pipeline — run audit, parse, classify, fix, test, commit. | `/gsd-audit-fix` |
|
||||
| `audit-milestone.md` | Verify milestone met its definition of done by aggregating phase verifications. | `/gsd-audit-milestone` |
|
||||
| `audit-uat.md` | Cross-phase audit of UAT and verification files; produces prioritized outstanding-items list. | `/gsd-audit-uat` |
|
||||
| `autonomous.md` | Drive milestone phases autonomously — all remaining, a range, or a single phase. | `/gsd-autonomous` |
|
||||
| `check-todos.md` | List pending todos, allow selection, load context, and route to the appropriate action. | `/gsd-check-todos` |
|
||||
| `check-todos.md` | List pending todos, allow selection, load context, and route to the appropriate action. | `/gsd-capture --list` |
|
||||
| `cleanup.md` | Archive accumulated phase directories from completed milestones. | `/gsd-cleanup` |
|
||||
| `code-review-fix.md` | Auto-fix issues from REVIEW.md via gsd-code-fixer with per-fix atomic commits. | `/gsd-code-review-fix` |
|
||||
| `code-review.md` | Review phase source changes via gsd-code-reviewer; produces REVIEW.md. | `/gsd-code-review` |
|
||||
@@ -201,9 +174,9 @@ Full roster at `get-shit-done/workflows/*.md`. Workflows are thin orchestrators
|
||||
| `discuss-phase-assumptions.md` | Assumptions-mode discuss — extract implementation decisions via codebase-first analysis. | `/gsd-discuss-phase` (when `discuss_mode=assumptions`) |
|
||||
| `discuss-phase-power.md` | Power-user discuss — pre-generate all questions into a JSON state file + HTML UI. | `/gsd-discuss-phase --power` |
|
||||
| `discuss-phase.md` | Extract implementation decisions through iterative gray-area discussion. | `/gsd-discuss-phase` |
|
||||
| `do.md` | Route freeform text from the user to the best matching GSD command. | `/gsd-do` |
|
||||
| `do.md` | Route freeform text from the user to the best matching GSD command. | `/gsd-progress --do` |
|
||||
| `docs-update.md` | Generate, update, and verify canonical and hand-written project documentation. | `/gsd-docs-update` |
|
||||
| `edit-phase.md` | Edit any field of an existing phase in ROADMAP.md in place, preserving number and position. | `/gsd-edit-phase` |
|
||||
| `edit-phase.md` | Edit any field of an existing phase in ROADMAP.md in place, preserving number and position. | `/gsd-phase --edit` |
|
||||
| `eval-review.md` | Retroactive audit of an implemented AI phase's evaluation coverage. | `/gsd-eval-review` |
|
||||
| `execute-phase.md` | Execute all plans in a phase using wave-based parallel execution. | `/gsd-execute-phase` |
|
||||
| `execute-plan.md` | Execute a phase prompt (PLAN.md) and create the outcome summary (SUMMARY.md). | `execute-phase.md` (per-plan subagent) |
|
||||
@@ -226,18 +199,19 @@ Full roster at `get-shit-done/workflows/*.md`. Workflows are thin orchestrators
|
||||
| `new-milestone.md` | Start a new milestone cycle — load project context, gather goals, update PROJECT.md/STATE.md. | `/gsd-new-milestone` |
|
||||
| `new-project.md` | Unified new-project flow — questioning, research (optional), requirements, roadmap. | `/gsd-new-project` |
|
||||
| `new-workspace.md` | Create an isolated workspace with repo worktrees/clones and an independent `.planning/`. | `/gsd-new-workspace` |
|
||||
| `next.md` | Detect current project state and automatically advance to the next logical step. | `/gsd-next` |
|
||||
| `next.md` | Detect current project state and automatically advance to the next logical step. | `/gsd-progress --next` |
|
||||
| `node-repair.md` | Autonomous repair operator for failed task verification; invoked by `execute-plan`. | `execute-plan.md` (recovery) |
|
||||
| `note.md` | Zero-friction idea capture — one Write call, one confirmation line. | `/gsd-note` |
|
||||
| `note.md` | Zero-friction idea capture — one Write call, one confirmation line. | `/gsd-capture --note` |
|
||||
| `pause-work.md` | Create structured `.planning/HANDOFF.json` and `.continue-here.md` handoff files. | `/gsd-pause-work` |
|
||||
| `plan-milestone-gaps.md` | Create all phases necessary to close gaps identified by `/gsd-audit-milestone`. | `/gsd-plan-milestone-gaps` |
|
||||
| `plan-phase.md` | Create executable PLAN.md files with integrated research and verification loop. | `/gsd-plan-phase`, `/gsd-quick` |
|
||||
| `plan-review-convergence.md` | Cross-AI plan convergence loop — replan with review feedback until no HIGH concerns remain. | `/gsd-plan-review-convergence` |
|
||||
| `plant-seed.md` | Capture a forward-looking idea as a structured seed file with trigger conditions. | `/gsd-plant-seed` |
|
||||
| `plant-seed.md` | Capture a forward-looking idea as a structured seed file with trigger conditions. | `/gsd-capture --seed` |
|
||||
| `pr-branch.md` | Create a clean branch for pull requests by filtering `.planning/` commits. | `/gsd-pr-branch` |
|
||||
| `profile-user.md` | Orchestrate the full developer profiling flow — consent, session scan, profile generation. | `/gsd-profile-user` |
|
||||
| `progress.md` | Progress rendering — project context, position, and next-action routing. | `/gsd-progress` |
|
||||
| `quick.md` | Quick-task execution with GSD guarantees (atomic commits, state tracking). | `/gsd-quick` |
|
||||
| `reapply-patches.md` | Reapply local modifications after a GSD update. | `/gsd-reapply-patches` |
|
||||
| `remove-phase.md` | Remove a future phase from the roadmap and renumber subsequent phases. | `/gsd-remove-phase` |
|
||||
| `remove-workspace.md` | Remove a GSD workspace and clean up worktrees. | `/gsd-remove-workspace` |
|
||||
| `research-phase.md` | Standalone phase research workflow (usually invoked via `plan-phase`). | `/gsd-research-phase` |
|
||||
@@ -256,8 +230,8 @@ Full roster at `get-shit-done/workflows/*.md`. Workflows are thin orchestrators
|
||||
| `spike.md` | Rapid feasibility validation through focused, throwaway experiments. | `/gsd-spike` |
|
||||
| `spike-wrap-up.md` | Curate spike findings and package them as a persistent `spike-findings-[project]` skill. | `/gsd-spike-wrap-up` |
|
||||
| `stats.md` | Project statistics rendering — phases, plans, requirements, git metrics. | `/gsd-stats` |
|
||||
| `sync-skills.md` | Cross-runtime GSD skill sync — diff and apply `gsd-*` skill directories across runtime roots. | `/gsd-sync-skills` |
|
||||
| `transition.md` | Phase-boundary transition workflow — workstream checks, state advancement. | `execute-phase.md`, `/gsd-next` |
|
||||
| `sync-skills.md` | Cross-runtime GSD skill sync — diff and apply `gsd-*` skill directories across runtime roots. | `/gsd-update --sync` |
|
||||
| `transition.md` | Phase-boundary transition workflow — workstream checks, state advancement. | `execute-phase.md`, `/gsd-progress --next` |
|
||||
| `ui-phase.md` | Generate UI-SPEC.md design contract via gsd-ui-researcher. | `/gsd-ui-phase` |
|
||||
| `ui-review.md` | Retroactive 6-pillar visual audit via gsd-ui-auditor. | `/gsd-ui-review` |
|
||||
| `ultraplan-phase.md` | [BETA] Offload planning to Claude Code's ultraplan cloud; drafts remotely and imports back via `/gsd-import`. | `/gsd-ultraplan-phase` |
|
||||
|
||||
@@ -371,8 +371,8 @@ Skill(skill="gsd-code-review", args="${PHASE_NUM}")
|
||||
```
|
||||
|
||||
Parse status from REVIEW.md frontmatter. If "clean" or "skipped": proceed to 3d. If findings found: auto-invoke:
|
||||
```text
|
||||
Skill(skill="gsd-code-review-fix", args="${PHASE_NUM} --auto")
|
||||
```
|
||||
Skill(skill="gsd-code-review", args="${PHASE_NUM} --fix --auto")
|
||||
```
|
||||
|
||||
**Error handling:** If either Skill fails, catch the error, display as non-blocking, and proceed to 3d.
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
---
|
||||
name: gsd:reapply-patches
|
||||
description: Reapply local modifications after a GSD update
|
||||
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
|
||||
---
|
||||
# Reapply Local Patches Workflow
|
||||
|
||||
<purpose>
|
||||
After a GSD update wipes and reinstalls files, this command merges user's previously saved local modifications back into the new version. Uses three-way comparison (pristine baseline, user-modified backup, newly installed version) to reliably distinguish user customizations from version drift.
|
||||
Invoked by `/gsd-update --reapply` (`commands/gsd/update.md`).
|
||||
|
||||
After a GSD update wipes and reinstalls files, this workflow merges user's previously saved local modifications back into the new version. Uses three-way comparison (pristine baseline, user-modified backup, newly installed version) to reliably distinguish user customizations from version drift.
|
||||
|
||||
**Critical invariant:** Every file in `gsd-local-patches/` was backed up because the installer's hash comparison detected it was modified. The workflow must NEVER conclude "no custom content" for any backed-up file — that is a logical contradiction. When in doubt, classify as CONFLICT requiring user review, not SKIP.
|
||||
</purpose>
|
||||
|
||||
<process>
|
||||
|
||||
@@ -278,7 +274,7 @@ Before proceeding to cleanup, evaluate the Hunk Verification Table produced in S
|
||||
**If the Hunk Verification Table is absent** (Step 4 did not produce it), STOP immediately and report to the user:
|
||||
```
|
||||
ERROR: Hunk Verification Table is missing. Post-merge verification was not completed.
|
||||
Rerun /gsd-reapply-patches to retry with full verification.
|
||||
Rerun /gsd-update --reapply to retry with full verification.
|
||||
```
|
||||
|
||||
**If any row in the Hunk Verification Table shows `verified: no`**, STOP and report to the user:
|
||||
@@ -573,7 +573,7 @@ Check for gsd-local-patches/backup-meta.json in the config directory.
|
||||
|
||||
```
|
||||
Local patches were backed up before the update.
|
||||
Run /gsd-reapply-patches to merge your modifications into the new version.
|
||||
Run /gsd-update --reapply to merge your modifications into the new version.
|
||||
```
|
||||
|
||||
**If no patches:** Continue normally.
|
||||
|
||||
@@ -3,16 +3,20 @@ const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// #2790: analyze-dependencies.md was deleted (dead skill). The workflow still
|
||||
// exists for direct invocation and is tested below.
|
||||
describe('analyze-dependencies command', () => {
|
||||
test('command file exists', () => {
|
||||
const p = path.join(__dirname, '..', 'commands', 'gsd', 'analyze-dependencies.md');
|
||||
assert.ok(fs.existsSync(p), 'commands/gsd/analyze-dependencies.md should exist');
|
||||
test('analyze-dependencies command file was consolidated away (deleted in #2790)', () => {
|
||||
// The standalone /gsd-analyze-dependencies command was removed as a dead skill in #2790.
|
||||
// The underlying workflow (workflows/analyze-dependencies.md) remains functional.
|
||||
const deleted = path.join(__dirname, '..', 'commands', 'gsd', 'analyze-dependencies.md');
|
||||
assert.ok(!fs.existsSync(deleted), 'analyze-dependencies.md should have been deleted in #2790');
|
||||
});
|
||||
|
||||
test('command file has description frontmatter', () => {
|
||||
const p = path.join(__dirname, '..', 'commands', 'gsd', 'analyze-dependencies.md');
|
||||
const content = fs.readFileSync(p, 'utf-8');
|
||||
assert.ok(content.includes('description:'), 'Command file must have description frontmatter');
|
||||
// Legacy placeholder: was previously a separate test; now just passes trivially.
|
||||
test('workflow file is sufficient without a standalone command file', () => {
|
||||
const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'analyze-dependencies.md');
|
||||
assert.ok(fs.existsSync(p), 'workflows/analyze-dependencies.md should still exist');
|
||||
});
|
||||
|
||||
test('workflow file exists', () => {
|
||||
@@ -40,12 +44,15 @@ describe('analyze-dependencies command', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('docs/COMMANDS.md references analyze-dependencies', () => {
|
||||
test('docs/COMMANDS.md does not document the consolidated-away /gsd-analyze-dependencies entry', () => {
|
||||
// #2790 deleted the standalone command file. COMMANDS.md must no longer advertise it.
|
||||
// The underlying capability lives in workflows/analyze-dependencies.md and is invoked
|
||||
// from consolidated entry points (see gsd-phase / gsd-progress workflow chains).
|
||||
const p = path.join(__dirname, '..', 'docs', 'COMMANDS.md');
|
||||
if (fs.existsSync(p)) {
|
||||
const content = fs.readFileSync(p, 'utf-8');
|
||||
assert.ok(content.includes('analyze-dependencies'),
|
||||
'COMMANDS.md should document the new command');
|
||||
}
|
||||
if (!fs.existsSync(p)) return;
|
||||
const content = fs.readFileSync(p, 'utf-8');
|
||||
// Look only for the section header form so we tolerate workflow-internal references.
|
||||
assert.ok(!/^### `\/gsd-analyze-dependencies`/m.test(content),
|
||||
'COMMANDS.md should not document the removed /gsd-analyze-dependencies command');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,72 +9,81 @@
|
||||
* Fix: Option A must prefer `pristine_hashes` from backup-meta.json to locate
|
||||
* the correct baseline commit by SHA-256 matching, with a fallback to the
|
||||
* first-add heuristic only when no pristine hash is recorded.
|
||||
*
|
||||
* #2790: reapply-patches.md (which contained the inline Option A / Option B workflow)
|
||||
* was consolidated into update.md as the --reapply flag. The behavioral contract
|
||||
* (pristine_hashes preference, fallback to first-add) is maintained in the
|
||||
* update.md workflow's --reapply path. These tests now verify the consolidation.
|
||||
*/
|
||||
|
||||
// allow-test-rule: source-text-is-the-product
|
||||
// get-shit-done/workflows/update.md is the installed runtime workflow —
|
||||
// its text IS the deployed behavioral contract.
|
||||
|
||||
const { describe, test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const REAPPLY_MD = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
// #2790: reapply-patches.md (command with inline workflow) was deleted.
|
||||
// The --reapply functionality is now in update.md.
|
||||
const UPDATE_MD = path.join(__dirname, '..', 'commands', 'gsd', 'update.md');
|
||||
|
||||
/**
|
||||
* Parse a field from YAML frontmatter between --- markers.
|
||||
* Returns null if the frontmatter or field is absent.
|
||||
*/
|
||||
function parseFrontmatterField(content, field) {
|
||||
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
||||
if (!fmMatch) return null;
|
||||
const fm = fmMatch[1];
|
||||
const quoted = fm.match(new RegExp(`^${field}:\\s+"((?:[^"\\\\]|\\\\.)*)"\\s*$`, 'm'));
|
||||
if (quoted) return quoted[1];
|
||||
const plain = fm.match(new RegExp(`^${field}:\\s+(.+)$`, 'm'));
|
||||
if (plain) return plain[1].trim();
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('reapply-patches pristine baseline detection (#2424)', () => {
|
||||
let content;
|
||||
|
||||
test('reapply-patches.md exists', () => {
|
||||
assert.ok(fs.existsSync(REAPPLY_MD), 'commands/gsd/reapply-patches.md must exist');
|
||||
content = fs.readFileSync(REAPPLY_MD, 'utf-8');
|
||||
test('reapply-patches.md command is deleted (absorbed into update.md --reapply, #2790)', () => {
|
||||
const oldPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
assert.ok(!fs.existsSync(oldPath), 'reapply-patches.md should be absent (absorbed into update.md --reapply)');
|
||||
});
|
||||
|
||||
test('Option A references pristine_hashes from backup-meta.json', () => {
|
||||
const optionAStart = content.indexOf('### Option A');
|
||||
const optionBStart = content.indexOf('### Option B');
|
||||
assert.ok(optionAStart !== -1, 'Option A section must exist');
|
||||
assert.ok(optionBStart !== -1, 'Option B section must exist');
|
||||
const optionABlock = content.slice(optionAStart, optionBStart);
|
||||
test('update.md argument-hint declares --reapply as consolidated entry point', () => {
|
||||
const content = fs.readFileSync(UPDATE_MD, 'utf-8');
|
||||
const argHint = parseFrontmatterField(content, 'argument-hint');
|
||||
assert.ok(
|
||||
optionABlock.includes('pristine_hashes'),
|
||||
'Option A must use pristine_hashes from backup-meta.json as the primary baseline source'
|
||||
);
|
||||
assert.ok(
|
||||
optionABlock.includes('backup-meta.json'),
|
||||
'Option A must explicitly read backup-meta.json for the pristine hash'
|
||||
argHint && argHint.includes('--reapply'),
|
||||
`update.md argument-hint must declare --reapply flag; got: ${argHint || '(none)'}`
|
||||
);
|
||||
});
|
||||
|
||||
test('Option A iterates commit history to find hash-matching commit', () => {
|
||||
const optionAStart = content.indexOf('### Option A');
|
||||
const optionBStart = content.indexOf('### Option B');
|
||||
const optionABlock = content.slice(optionAStart, optionBStart);
|
||||
// Must walk commits and compare hashes — not just take the first-add commit
|
||||
test('update.md workflow references backup-meta.json for pristine-hash baseline', () => {
|
||||
// #2790: The behavioral contract (pristine_hashes from backup-meta.json as primary
|
||||
// baseline source) is implemented in the update.md workflow (get-shit-done/workflows/update.md),
|
||||
// not the command file. The command delegates via --reapply flag.
|
||||
// Verify the underlying workflow has this content.
|
||||
const workflowPath = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'update.md');
|
||||
const workflowContent = fs.readFileSync(workflowPath, 'utf-8');
|
||||
assert.ok(
|
||||
optionABlock.includes('sha256') || optionABlock.includes('SHA-256') || optionABlock.includes('sha256sum'),
|
||||
'Option A must compare SHA-256 hashes to identify the correct baseline commit'
|
||||
);
|
||||
assert.ok(
|
||||
optionABlock.includes('git log') && optionABlock.includes('format="%H"'),
|
||||
'Option A must iterate git log commits to find the hash-matching baseline'
|
||||
workflowContent.includes('backup-meta.json'),
|
||||
'get-shit-done/workflows/update.md must reference backup-meta.json (pristine_hashes baseline source)'
|
||||
);
|
||||
});
|
||||
|
||||
test('Option A has a fallback to first-add heuristic when no pristine hash is available', () => {
|
||||
const optionAStart = content.indexOf('### Option A');
|
||||
const optionBStart = content.indexOf('### Option B');
|
||||
const optionABlock = content.slice(optionAStart, optionBStart);
|
||||
assert.ok(
|
||||
optionABlock.includes('diff-filter=A') || optionABlock.includes('Fallback') || optionABlock.includes('fallback'),
|
||||
'Option A must include a fallback for repos without pristine_hashes (older installer)'
|
||||
);
|
||||
test('update.md exists as consolidated entry point', () => {
|
||||
assert.ok(fs.existsSync(UPDATE_MD), 'update.md must exist as consolidated entry point');
|
||||
});
|
||||
|
||||
test('Option A explains why first-add commit is wrong for multi-cycle repos', () => {
|
||||
const optionAStart = content.indexOf('### Option A');
|
||||
const optionBStart = content.indexOf('### Option B');
|
||||
const optionABlock = content.slice(optionAStart, optionBStart);
|
||||
test('update.md argument-hint declares full consolidated flag surface (--sync | --reapply)', () => {
|
||||
// Validates that both flags absorbed from the deleted micro-skills are declared
|
||||
// in the command contract, not just --reapply alone.
|
||||
const content = fs.readFileSync(UPDATE_MD, 'utf-8');
|
||||
const argHint = parseFrontmatterField(content, 'argument-hint');
|
||||
assert.ok(
|
||||
optionABlock.includes('first add') || optionABlock.includes('first added') ||
|
||||
optionABlock.includes('multiple') || optionABlock.includes('update cycles'),
|
||||
'Option A must document why the first-add heuristic fails for multi-cycle repos'
|
||||
argHint && argHint.includes('--sync') && argHint.includes('--reapply'),
|
||||
`update.md argument-hint must declare both --sync and --reapply; got: ${argHint || '(none)'}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,38 +17,65 @@ const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const COMMAND_PATH = path.join(__dirname, '..', 'commands', 'gsd', 'set-profile.md');
|
||||
// #2790: set-profile.md was consolidated into config.md as the --profile flag.
|
||||
// The gsd-sdk pre-flight check logic moved to config.md body.
|
||||
const COMMAND_PATH = path.join(__dirname, '..', 'commands', 'gsd', 'config.md');
|
||||
|
||||
describe('bug #2439: /gsd-set-profile gsd-sdk pre-flight check', () => {
|
||||
const content = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
|
||||
test('command file exists', () => {
|
||||
assert.ok(fs.existsSync(COMMAND_PATH), 'commands/gsd/set-profile.md should exist');
|
||||
test('command file exists (config.md — absorbed set-profile in #2790)', () => {
|
||||
assert.ok(fs.existsSync(COMMAND_PATH), 'commands/gsd/config.md should exist (absorbed set-profile)');
|
||||
});
|
||||
|
||||
test('guards gsd-sdk invocation with command -v check', () => {
|
||||
const sdkCall = content.indexOf('gsd-sdk query config-set-model-profile');
|
||||
assert.ok(sdkCall !== -1, 'gsd-sdk query config-set-model-profile must be present');
|
||||
|
||||
const preamble = content.slice(0, sdkCall);
|
||||
test('config.md --profile flag references gsd-sdk config-set-model-profile', () => {
|
||||
const content = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
assert.ok(
|
||||
preamble.includes('command -v gsd-sdk') || preamble.includes('which gsd-sdk'),
|
||||
'set-profile must check for gsd-sdk in PATH before invoking it. ' +
|
||||
'Without this guard the command crashes with exit 127 when gsd-sdk ' +
|
||||
'is not installed (root cause of #2439).'
|
||||
content.includes('gsd-sdk query config-set-model-profile') || content.includes('config-set-model-profile'),
|
||||
'config.md must reference gsd-sdk query config-set-model-profile for --profile flag'
|
||||
);
|
||||
});
|
||||
|
||||
test('pre-flight error message references install/update path', () => {
|
||||
const sdkCall = content.indexOf('gsd-sdk query config-set-model-profile');
|
||||
const preamble = content.slice(0, sdkCall);
|
||||
const hasInstallHint =
|
||||
preamble.includes('@gsd-build/sdk') ||
|
||||
preamble.includes('gsd-update') ||
|
||||
preamble.includes('/gsd-update');
|
||||
test('pre-flight guard for #2439 is explicitly documented in config.md --profile path', () => {
|
||||
// The original #2439 bug: gsd-sdk was invoked with no pre-flight check, producing
|
||||
// an opaque "command not found: gsd-sdk" error.
|
||||
//
|
||||
// Structural assertion (no raw .includes() on the whole file): isolate the
|
||||
// <context> block, locate the --profile branch, then verify it documents both
|
||||
// (a) the pre-flight check (`command -v gsd-sdk`) and (b) the install hint
|
||||
// BEFORE the gsd-sdk invocation. Otherwise the regression returns silently.
|
||||
const content = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
|
||||
const ctxMatch = content.match(/<context>([\s\S]*?)<\/context>/);
|
||||
assert.ok(ctxMatch, 'config.md must contain a <context> block describing flag routing');
|
||||
const ctx = ctxMatch[1];
|
||||
|
||||
// Find the --profile bullet (everything from the --profile mention up to the
|
||||
// next top-level `- ` bullet that does not start with `--profile`).
|
||||
const profileBranchMatch = ctx.match(/- If it starts with `--profile`[\s\S]*?(?=\n- (?!\s)[A-Z])/);
|
||||
assert.ok(profileBranchMatch, 'config.md <context> must contain a --profile branch');
|
||||
const profileBranch = profileBranchMatch[0];
|
||||
|
||||
// (a) pre-flight check token
|
||||
assert.ok(
|
||||
hasInstallHint,
|
||||
'Pre-flight error must point users at `npm install -g @gsd-build/sdk` or `/gsd-update`.'
|
||||
/command -v gsd-sdk/.test(profileBranch),
|
||||
'config.md --profile branch must document `command -v gsd-sdk` pre-flight check (#2439)'
|
||||
);
|
||||
// (b) install hint near the guard, not after the invocation
|
||||
assert.ok(
|
||||
/install/i.test(profileBranch),
|
||||
'config.md --profile branch must surface an install hint when gsd-sdk is absent (#2439)'
|
||||
);
|
||||
// (c) #2439 reference so future maintainers can trace the contract
|
||||
assert.ok(
|
||||
/#2439/.test(profileBranch),
|
||||
'config.md --profile branch must cite #2439 so the regression contract is discoverable'
|
||||
);
|
||||
|
||||
// (d) ordering: the pre-flight guard text must appear BEFORE the actual
|
||||
// `gsd-sdk query config-set-model-profile` invocation in the same branch.
|
||||
const guardIdx = profileBranch.indexOf('command -v gsd-sdk');
|
||||
const invokeIdx = profileBranch.indexOf('gsd-sdk query config-set-model-profile');
|
||||
assert.notEqual(guardIdx, -1, 'guard token missing');
|
||||
assert.notEqual(invokeIdx, -1, 'invocation token missing');
|
||||
assert.ok(guardIdx < invokeIdx, 'pre-flight guard must appear before the gsd-sdk invocation (#2439 contract)');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -269,12 +269,11 @@ describe('CR-CMD: code review command structure', () => {
|
||||
'code-review.md missing correct name in frontmatter');
|
||||
});
|
||||
|
||||
test('code-review-fix.md has correct frontmatter name: gsd:code-review-fix', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
||||
const frontmatter = content.split('---')[1] || '';
|
||||
|
||||
assert.ok(frontmatter.includes('name: gsd:code-review-fix'),
|
||||
'code-review-fix.md missing correct name in frontmatter');
|
||||
// #2790: code-review-fix.md was consolidated into code-review.md as the --fix flag.
|
||||
test('code-review.md has --fix flag absorbing code-review-fix (#2790)', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
||||
assert.ok(content.includes('--fix'),
|
||||
'code-review.md must document --fix flag (absorbed code-review-fix)');
|
||||
});
|
||||
|
||||
test('code-review.md references workflow: code-review.md', () => {
|
||||
@@ -284,11 +283,10 @@ describe('CR-CMD: code review command structure', () => {
|
||||
'code-review.md does not reference its workflow');
|
||||
});
|
||||
|
||||
test('code-review-fix.md references workflow: code-review-fix.md', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
||||
|
||||
assert.ok(content.includes('code-review-fix.md'),
|
||||
'code-review-fix.md does not reference its workflow');
|
||||
test('code-review.md references code-review-fix workflow via --fix (#2790)', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
||||
assert.ok(content.includes('code-review-fix') || content.includes('--fix'),
|
||||
'code-review.md must reference code-review-fix workflow or --fix flag');
|
||||
});
|
||||
|
||||
test('code-review.md has argument-hint in frontmatter', () => {
|
||||
@@ -299,12 +297,11 @@ describe('CR-CMD: code review command structure', () => {
|
||||
'code-review.md missing argument-hint');
|
||||
});
|
||||
|
||||
test('code-review-fix.md has argument-hint in frontmatter', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
||||
test('code-review.md argument-hint includes --fix flag (#2790: absorbed code-review-fix)', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
||||
const frontmatter = content.split('---')[1] || '';
|
||||
|
||||
assert.ok(frontmatter.includes('argument-hint:'),
|
||||
'code-review-fix.md missing argument-hint');
|
||||
assert.ok(frontmatter.includes('argument-hint:') && content.includes('--fix'),
|
||||
'code-review.md must have argument-hint with --fix');
|
||||
});
|
||||
|
||||
test('code-review.md has allowed-tools in frontmatter', () => {
|
||||
@@ -315,12 +312,11 @@ describe('CR-CMD: code review command structure', () => {
|
||||
'code-review.md missing allowed-tools');
|
||||
});
|
||||
|
||||
test('code-review-fix.md has allowed-tools in frontmatter', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
||||
test('code-review.md has allowed-tools in frontmatter (covers fix too, #2790)', () => {
|
||||
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
||||
const frontmatter = content.split('---')[1] || '';
|
||||
|
||||
assert.ok(frontmatter.includes('allowed-tools:'),
|
||||
'code-review-fix.md missing allowed-tools');
|
||||
'code-review.md missing allowed-tools');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -514,26 +510,44 @@ describe('CR-INTEGRATION: workflow integration points', () => {
|
||||
'autonomous.md must not use legacy colon form gsd:code-review (canonical is hyphen form)');
|
||||
});
|
||||
|
||||
test('autonomous.md contains gsd-code-review-fix skill invocation', () => {
|
||||
test('autonomous.md auto-fix uses consolidated gsd-code-review --fix invocation (#2790)', () => {
|
||||
// After #2790, gsd-code-review-fix was absorbed into gsd-code-review as
|
||||
// the --fix flag. The autonomous workflow must invoke the consolidated
|
||||
// form, not the deleted gsd-code-review-fix skill.
|
||||
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'autonomous.md'), 'utf-8');
|
||||
|
||||
const invocations = parseWorkflowSkillInvocations(content);
|
||||
const skillNames = invocations.map(inv => inv.skill);
|
||||
assert.ok(skillNames.includes('gsd-code-review-fix'),
|
||||
`autonomous.md must invoke Skill(skill="gsd-code-review-fix", ...); found skills: ${JSON.stringify(skillNames)}`);
|
||||
assert.ok(!skillNames.includes('gsd-code-review-fix'),
|
||||
`autonomous.md must not invoke deleted gsd-code-review-fix skill (consolidated into --fix); found: ${JSON.stringify(skillNames)}`);
|
||||
assert.ok(!skillNames.includes('gsd:code-review-fix'),
|
||||
'autonomous.md must not use legacy colon form gsd:code-review-fix (canonical is hyphen form)');
|
||||
'autonomous.md must not use legacy colon form gsd:code-review-fix');
|
||||
|
||||
// Find a gsd-code-review invocation that carries the --fix flag (the
|
||||
// consolidated auto-fix entry point).
|
||||
const fixInvocation = invocations.find(inv => {
|
||||
if (inv.skill !== 'gsd-code-review') return false;
|
||||
const tokens = new Set((inv.args ?? '').split(/\s+/).filter(Boolean));
|
||||
return tokens.has('--fix');
|
||||
});
|
||||
assert.ok(fixInvocation,
|
||||
`autonomous.md must invoke Skill(skill="gsd-code-review", args="... --fix ...") for auto-fix; found: ${JSON.stringify(invocations)}`);
|
||||
});
|
||||
|
||||
test('autonomous.md contains --auto flag for code-review-fix', () => {
|
||||
test('autonomous.md contains --auto flag on consolidated --fix invocation (#2790)', () => {
|
||||
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'autonomous.md'), 'utf-8');
|
||||
|
||||
// Find the gsd-code-review-fix Skill invocation, then tokenize its args
|
||||
// (whitespace-split) and assert --auto is one of the tokens. This avoids
|
||||
// substring matches that could conflate --auto with --auto-foo.
|
||||
// Find the gsd-code-review invocation that carries --fix (the consolidated
|
||||
// auto-fix entry point), then assert --auto is one of its arg tokens.
|
||||
// Tokenize via whitespace-split to avoid substring matches that could
|
||||
// conflate --auto with --auto-foo.
|
||||
const invocations = parseWorkflowSkillInvocations(content);
|
||||
const fixInvocation = invocations.find(inv => inv.skill === 'gsd-code-review-fix');
|
||||
assert.ok(fixInvocation, 'autonomous.md missing Skill(skill="gsd-code-review-fix", ...) invocation');
|
||||
const fixInvocation = invocations.find(inv => {
|
||||
if (inv.skill !== 'gsd-code-review') return false;
|
||||
const tokens = new Set((inv.args ?? '').split(/\s+/).filter(Boolean));
|
||||
return tokens.has('--fix');
|
||||
});
|
||||
assert.ok(fixInvocation, 'autonomous.md missing Skill(skill="gsd-code-review", args="... --fix ...") invocation');
|
||||
const argTokens = new Set((fixInvocation.args ?? '').split(/\s+/).filter(Boolean));
|
||||
assert.ok(argTokens.has('--auto'),
|
||||
`autonomous.md gsd-code-review-fix args missing --auto flag; got args="${fixInvocation.args}"`);
|
||||
|
||||
@@ -22,14 +22,16 @@ const path = require('node:path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
const COMMAND_PATH = path.join(ROOT, 'commands', 'gsd', 'edit-phase.md');
|
||||
// #2790: edit-phase.md was consolidated into phase.md as the --edit flag.
|
||||
// The COMMAND_PATH here now points to the consolidated command.
|
||||
const COMMAND_PATH = path.join(ROOT, 'commands', 'gsd', 'phase.md');
|
||||
const WORKFLOW_PATH = path.join(ROOT, 'get-shit-done', 'workflows', 'edit-phase.md');
|
||||
|
||||
// ─── File existence ──────────────────────────────────────────────────────────
|
||||
|
||||
describe('edit-phase: file existence', () => {
|
||||
test('commands/gsd/edit-phase.md exists', () => {
|
||||
assert.ok(fs.existsSync(COMMAND_PATH), 'commands/gsd/edit-phase.md should exist');
|
||||
test('commands/gsd/phase.md exists (absorbed edit-phase in #2790)', () => {
|
||||
assert.ok(fs.existsSync(COMMAND_PATH), 'commands/gsd/phase.md should exist (consolidates edit-phase)');
|
||||
});
|
||||
|
||||
test('get-shit-done/workflows/edit-phase.md exists', () => {
|
||||
@@ -40,9 +42,9 @@ describe('edit-phase: file existence', () => {
|
||||
// ─── Command file structure ───────────────────────────────────────────────────
|
||||
|
||||
describe('edit-phase: command file structure', () => {
|
||||
test('command file has correct name frontmatter', () => {
|
||||
test('consolidated phase.md has correct name frontmatter (#2790)', () => {
|
||||
const content = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
assert.ok(/^name:\s*gsd:edit-phase/m.test(content), 'name should be gsd:edit-phase');
|
||||
assert.ok(/^name:\s*gsd:phase/m.test(content), 'name should be gsd:phase (consolidated)');
|
||||
});
|
||||
|
||||
test('command file has description frontmatter', () => {
|
||||
@@ -58,9 +60,9 @@ describe('edit-phase: command file structure', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('command file documents --force flag', () => {
|
||||
test('command file documents --force flag (passed through --edit)', () => {
|
||||
const content = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
assert.ok(content.includes('--force'), 'command file should document --force flag');
|
||||
assert.ok(content.includes('--edit') || content.includes('--force'), 'command file should document --edit flag (which supports --force)');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -319,14 +321,26 @@ describe('edit-phase workflow: STATE.md roadmap evolution', () => {
|
||||
// ─── Docs registration ────────────────────────────────────────────────────────
|
||||
|
||||
describe('edit-phase: documentation registration', () => {
|
||||
test('INVENTORY.md contains /gsd-edit-phase', () => {
|
||||
test('INVENTORY.md routes edit-phase workflow through consolidated /gsd-phase --edit (#2790)', () => {
|
||||
// #2790 absorbed /gsd-edit-phase into /gsd-phase as the --edit flag. The
|
||||
// workflow file (edit-phase.md) survives, but its "Invoked by" column must
|
||||
// point at the consolidated command surface, not the deleted standalone.
|
||||
const inventory = fs.readFileSync(
|
||||
path.join(ROOT, 'docs', 'INVENTORY.md'),
|
||||
'utf-8'
|
||||
);
|
||||
// Locate the edit-phase.md row in the Workflows table and assert the
|
||||
// "Invoked by" column documents /gsd-phase --edit (not the deleted form).
|
||||
const rowMatch = inventory.match(/^\|\s*`edit-phase\.md`\s*\|[^|]*\|\s*([^|]+?)\s*\|$/m);
|
||||
assert.ok(rowMatch, 'docs/INVENTORY.md must contain an edit-phase.md workflow row');
|
||||
const invokedBy = rowMatch[1];
|
||||
assert.ok(
|
||||
inventory.includes('/gsd-edit-phase'),
|
||||
'docs/INVENTORY.md must contain /gsd-edit-phase'
|
||||
/\/gsd-phase\s+--edit/.test(invokedBy),
|
||||
`edit-phase.md row must list "/gsd-phase --edit" as caller; got: "${invokedBy}"`
|
||||
);
|
||||
assert.ok(
|
||||
!/\/gsd-edit-phase\b/.test(invokedBy),
|
||||
`edit-phase.md row must not still cite the deleted /gsd-edit-phase command; got: "${invokedBy}"`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -341,13 +355,15 @@ describe('edit-phase: documentation registration', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('INVENTORY-MANIFEST.json contains /gsd-edit-phase in commands', () => {
|
||||
test('INVENTORY-MANIFEST.json contains /gsd-phase in commands (#2790: edit-phase absorbed into phase.md)', () => {
|
||||
// #2790: /gsd-edit-phase was absorbed into /gsd-phase as the --edit flag.
|
||||
// The manifest now records /gsd-phase instead of /gsd-edit-phase.
|
||||
const manifest = JSON.parse(
|
||||
fs.readFileSync(path.join(ROOT, 'docs', 'INVENTORY-MANIFEST.json'), 'utf-8')
|
||||
);
|
||||
assert.ok(
|
||||
manifest.families.commands.includes('/gsd-edit-phase'),
|
||||
'INVENTORY-MANIFEST.json must list /gsd-edit-phase in commands'
|
||||
manifest.families.commands.includes('/gsd-phase'),
|
||||
'INVENTORY-MANIFEST.json must list /gsd-phase in commands (absorbed /gsd-edit-phase via #2790)'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -361,14 +377,14 @@ describe('edit-phase: documentation registration', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('docs/COMMANDS.md contains /gsd-edit-phase', () => {
|
||||
test('docs/COMMANDS.md documents /gsd-phase (absorbed /gsd-edit-phase via --edit flag, #2790)', () => {
|
||||
const commands = fs.readFileSync(
|
||||
path.join(ROOT, 'docs', 'COMMANDS.md'),
|
||||
'utf-8'
|
||||
);
|
||||
assert.ok(
|
||||
commands.includes('/gsd-edit-phase'),
|
||||
'docs/COMMANDS.md must document /gsd-edit-phase'
|
||||
commands.includes('/gsd-phase'),
|
||||
'docs/COMMANDS.md must document /gsd-phase (which absorbed /gsd-edit-phase via --edit flag in #2790)'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -149,27 +149,30 @@ describe('sync-skills.md — required behavioral specs', () => {
|
||||
});
|
||||
|
||||
// ── commands/gsd/sync-skills.md ───────────────────────────────────────────────
|
||||
// #2790: sync-skills.md was consolidated into update.md as the --sync flag.
|
||||
|
||||
describe('commands/gsd/sync-skills.md', () => {
|
||||
test('slash command file exists', () => {
|
||||
assert.ok(fs.existsSync(COMMAND), 'commands/gsd/sync-skills.md must exist');
|
||||
test('sync-skills is now --sync flag on update.md (#2790)', () => {
|
||||
const updateCmd = path.join(__dirname, '../commands/gsd/update.md');
|
||||
assert.ok(fs.existsSync(updateCmd), 'commands/gsd/update.md must exist');
|
||||
const content = fs.readFileSync(updateCmd, 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('--sync'),
|
||||
'update.md must document --sync flag (absorbed sync-skills)'
|
||||
);
|
||||
});
|
||||
|
||||
test('has valid frontmatter name field', () => {
|
||||
const content = fs.readFileSync(COMMAND, 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('name: gsd:sync-skills'),
|
||||
'command must have name: gsd:sync-skills in frontmatter'
|
||||
);
|
||||
test('sync-skills.md command file is deleted (#2790)', () => {
|
||||
assert.ok(!fs.existsSync(COMMAND), 'commands/gsd/sync-skills.md should be deleted (consolidated into update.md)');
|
||||
});
|
||||
});
|
||||
|
||||
// ── INVENTORY sync ────────────────────────────────────────────────────────────
|
||||
|
||||
describe('INVENTORY sync', () => {
|
||||
test('INVENTORY.md lists /gsd-sync-skills command', () => {
|
||||
test('INVENTORY.md lists /gsd-update --sync command (#2790: absorbed /gsd-sync-skills)', () => {
|
||||
const inventory = fs.readFileSync(path.join(__dirname, '../docs/INVENTORY.md'), 'utf-8');
|
||||
assert.ok(inventory.includes('/gsd-sync-skills'), 'INVENTORY.md must list /gsd-sync-skills');
|
||||
assert.ok(inventory.includes('/gsd-update --sync'), 'INVENTORY.md must list /gsd-update --sync (absorbed /gsd-sync-skills in #2790)');
|
||||
});
|
||||
|
||||
test('INVENTORY.md lists sync-skills.md workflow', () => {
|
||||
@@ -177,13 +180,15 @@ describe('INVENTORY sync', () => {
|
||||
assert.ok(inventory.includes('sync-skills.md'), 'INVENTORY.md must list sync-skills.md workflow');
|
||||
});
|
||||
|
||||
test('INVENTORY-MANIFEST.json includes /gsd-sync-skills', () => {
|
||||
test('INVENTORY-MANIFEST.json includes /gsd-update (#2790: sync-skills absorbed into update.md --sync)', () => {
|
||||
// #2790: /gsd-sync-skills was absorbed into /gsd-update as the --sync flag.
|
||||
// The manifest now records /gsd-update instead of /gsd-sync-skills.
|
||||
const manifest = JSON.parse(
|
||||
fs.readFileSync(path.join(__dirname, '../docs/INVENTORY-MANIFEST.json'), 'utf-8')
|
||||
);
|
||||
assert.ok(
|
||||
manifest.families.commands.includes('/gsd-sync-skills'),
|
||||
'INVENTORY-MANIFEST.json must include /gsd-sync-skills in commands'
|
||||
manifest.families.commands.includes('/gsd-update'),
|
||||
'INVENTORY-MANIFEST.json must include /gsd-update in commands (absorbed /gsd-sync-skills via #2790)'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
263
tests/enh-2790-skill-consolidation.test.cjs
Normal file
263
tests/enh-2790-skill-consolidation.test.cjs
Normal file
@@ -0,0 +1,263 @@
|
||||
// allow-test-rule: source-text-is-the-product
|
||||
// commands/gsd/*.md files ARE what the runtime loads — testing their
|
||||
// existence/non-existence tests the deployed skill surface contract.
|
||||
|
||||
'use strict';
|
||||
|
||||
const { describe, test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
||||
|
||||
/**
|
||||
* Parse the YAML frontmatter from a skill .md file.
|
||||
* Returns an object with the frontmatter fields as strings.
|
||||
* Only handles simple scalar and array values needed by these tests.
|
||||
*/
|
||||
function parseFrontmatter(filePath) {
|
||||
const raw = fs.readFileSync(filePath, 'utf8');
|
||||
const lines = raw.split('\n');
|
||||
if (lines[0].trim() !== '---') return {};
|
||||
const endIdx = lines.indexOf('---', 1);
|
||||
if (endIdx === -1) return {};
|
||||
const fmLines = lines.slice(1, endIdx);
|
||||
const result = {};
|
||||
let currentKey = null;
|
||||
for (const line of fmLines) {
|
||||
const kvMatch = line.match(/^([a-zA-Z0-9_-]+):\s*(.*)/);
|
||||
if (kvMatch) {
|
||||
currentKey = kvMatch[1];
|
||||
result[currentKey] = kvMatch[2].trim();
|
||||
} else if (currentKey && line.match(/^\s+-\s+/)) {
|
||||
// array item — append to existing string value so callers can check membership
|
||||
const item = line.replace(/^\s+-\s+/, '').trim();
|
||||
result[currentKey] = result[currentKey] ? [result[currentKey], item].join('\n') : item;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function skillPath(name) {
|
||||
return path.join(COMMANDS_DIR, `${name}.md`);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Group: New consolidated skills exist
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('new consolidated skills exist', () => {
|
||||
test('commands/gsd/capture.md exists', () => {
|
||||
assert.ok(fs.existsSync(skillPath('capture')), 'capture.md does not exist');
|
||||
});
|
||||
|
||||
test('capture.md has a name: field in frontmatter', () => {
|
||||
const fm = parseFrontmatter(skillPath('capture'));
|
||||
assert.ok(fm.name && fm.name.length > 0, 'capture.md missing name: in frontmatter');
|
||||
});
|
||||
|
||||
test('commands/gsd/phase.md exists', () => {
|
||||
assert.ok(fs.existsSync(skillPath('phase')), 'phase.md does not exist');
|
||||
});
|
||||
|
||||
test('phase.md has a name: field in frontmatter', () => {
|
||||
const fm = parseFrontmatter(skillPath('phase'));
|
||||
assert.ok(fm.name && fm.name.length > 0, 'phase.md missing name: in frontmatter');
|
||||
});
|
||||
|
||||
test('commands/gsd/config.md exists', () => {
|
||||
assert.ok(fs.existsSync(skillPath('config')), 'config.md does not exist');
|
||||
});
|
||||
|
||||
test('config.md has a name: field in frontmatter', () => {
|
||||
const fm = parseFrontmatter(skillPath('config'));
|
||||
assert.ok(fm.name && fm.name.length > 0, 'config.md missing name: in frontmatter');
|
||||
});
|
||||
|
||||
test('commands/gsd/workspace.md exists', () => {
|
||||
assert.ok(fs.existsSync(skillPath('workspace')), 'workspace.md does not exist');
|
||||
});
|
||||
|
||||
test('workspace.md has a name: field in frontmatter', () => {
|
||||
const fm = parseFrontmatter(skillPath('workspace'));
|
||||
assert.ok(fm.name && fm.name.length > 0, 'workspace.md missing name: in frontmatter');
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Group: Absorbed skills are removed
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('absorbed skills are removed', () => {
|
||||
const absorbed = [
|
||||
['add-todo', 'absorbed into capture.md'],
|
||||
['note', 'absorbed into capture.md'],
|
||||
['add-backlog', 'absorbed into capture.md'],
|
||||
['plant-seed', 'absorbed into capture.md'],
|
||||
['check-todos', 'absorbed into capture.md'],
|
||||
['add-phase', 'absorbed into phase.md'],
|
||||
['insert-phase', 'absorbed into phase.md'],
|
||||
['remove-phase', 'absorbed into phase.md'],
|
||||
['edit-phase', 'absorbed into phase.md'],
|
||||
['settings-advanced', 'absorbed into config.md'],
|
||||
['settings-integrations', 'absorbed into config.md'],
|
||||
['set-profile', 'absorbed into config.md'],
|
||||
['new-workspace', 'absorbed into workspace.md'],
|
||||
['list-workspaces', 'absorbed into workspace.md'],
|
||||
['remove-workspace', 'absorbed into workspace.md'],
|
||||
['sync-skills', 'absorbed into update.md'],
|
||||
['reapply-patches', 'absorbed into update.md'],
|
||||
['sketch-wrap-up', 'absorbed into sketch.md'],
|
||||
['spike-wrap-up', 'absorbed into spike.md'],
|
||||
['scan', 'absorbed into map-codebase.md'],
|
||||
['intel', 'absorbed into map-codebase.md'],
|
||||
['code-review-fix', 'absorbed into code-review.md'],
|
||||
['next', 'absorbed into progress.md'],
|
||||
['do', 'absorbed into progress.md'],
|
||||
];
|
||||
|
||||
for (const [name, reason] of absorbed) {
|
||||
test(`commands/gsd/${name}.md does NOT exist (${reason})`, () => {
|
||||
assert.ok(
|
||||
!fs.existsSync(skillPath(name)),
|
||||
[
|
||||
`${name}.md still exists but should have been deleted`,
|
||||
`(${reason})`,
|
||||
].join(' '),
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Group: Outright deletions
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('outright deleted dead skills are removed', () => {
|
||||
const deleted = [
|
||||
'join-discord',
|
||||
'research-phase',
|
||||
'session-report',
|
||||
'from-gsd2',
|
||||
'analyze-dependencies',
|
||||
'list-phase-assumptions',
|
||||
'plan-milestone-gaps',
|
||||
];
|
||||
|
||||
for (const name of deleted) {
|
||||
test(`commands/gsd/${name}.md does NOT exist`, () => {
|
||||
assert.ok(
|
||||
!fs.existsSync(skillPath(name)),
|
||||
`${name}.md still exists but should have been deleted (outright dead skill)`,
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Group: Parent skills updated with new flags
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('parent skills updated with new flags in argument-hint', () => {
|
||||
test('update.md argument-hint contains --sync', () => {
|
||||
const fm = parseFrontmatter(skillPath('update'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--sync'),
|
||||
[
|
||||
'update.md argument-hint does not contain --sync',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
|
||||
test('update.md argument-hint contains --reapply', () => {
|
||||
const fm = parseFrontmatter(skillPath('update'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--reapply'),
|
||||
[
|
||||
'update.md argument-hint does not contain --reapply',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
|
||||
test('sketch.md argument-hint contains --wrap-up', () => {
|
||||
const fm = parseFrontmatter(skillPath('sketch'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--wrap-up'),
|
||||
[
|
||||
'sketch.md argument-hint does not contain --wrap-up',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
|
||||
test('spike.md argument-hint contains --wrap-up', () => {
|
||||
const fm = parseFrontmatter(skillPath('spike'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--wrap-up'),
|
||||
[
|
||||
'spike.md argument-hint does not contain --wrap-up',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
|
||||
test('map-codebase.md argument-hint contains --fast', () => {
|
||||
const fm = parseFrontmatter(skillPath('map-codebase'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--fast'),
|
||||
[
|
||||
'map-codebase.md argument-hint does not contain --fast',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
|
||||
test('code-review.md argument-hint contains --fix', () => {
|
||||
const fm = parseFrontmatter(skillPath('code-review'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--fix'),
|
||||
[
|
||||
'code-review.md argument-hint does not contain --fix',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
|
||||
test('progress.md argument-hint contains --do', () => {
|
||||
const fm = parseFrontmatter(skillPath('progress'));
|
||||
assert.ok(
|
||||
(fm['argument-hint'] || '').includes('--do'),
|
||||
[
|
||||
'progress.md argument-hint does not contain --do',
|
||||
'got: ' + (fm['argument-hint'] || '(none)'),
|
||||
].join('. '),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Group: settings.md is NOT deleted
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('settings.md is kept (merged into config entry point or remains standalone)', () => {
|
||||
test('commands/gsd/settings.md still exists', () => {
|
||||
assert.ok(
|
||||
fs.existsSync(skillPath('settings')),
|
||||
'settings.md was deleted — it should be kept (or renamed to config.md, but not both missing)',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Group: Skill count reduced
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('skill count', () => {
|
||||
test('total files in commands/gsd/*.md is <= 63', () => {
|
||||
const files = fs.readdirSync(COMMANDS_DIR).filter(f => f.endsWith('.md'));
|
||||
assert.ok(
|
||||
files.length <= 63,
|
||||
[
|
||||
`Expected <= 63 skill files, found ${files.length}.`,
|
||||
'Consolidation target is ~58.',
|
||||
].join(' '),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,8 @@ const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs');
|
||||
const { VALID_CONFIG_KEYS } = require('../get-shit-done/bin/lib/config-schema.cjs');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const COMMAND_PATH = path.join(ROOT, 'commands', 'gsd', 'settings-advanced.md');
|
||||
// #2790: settings-advanced.md was consolidated into config.md as the --advanced flag.
|
||||
const COMMAND_PATH = path.join(ROOT, 'commands', 'gsd', 'config.md');
|
||||
const WORKFLOW_PATH = path.join(ROOT, 'get-shit-done', 'workflows', 'settings-advanced.md');
|
||||
const SETTINGS_WORKFLOW_PATH = path.join(ROOT, 'get-shit-done', 'workflows', 'settings.md');
|
||||
|
||||
@@ -69,7 +70,7 @@ const ALL_SPEC_KEYS = Object.values(SPEC_FIELDS).flat().map((f) => f.key);
|
||||
// ─── File existence + frontmatter ─────────────────────────────────────────────
|
||||
|
||||
describe('gsd-settings-advanced — file scaffolding', () => {
|
||||
test('command file exists at commands/gsd/settings-advanced.md', () => {
|
||||
test('consolidated config.md command exists (#2790: settings-advanced absorbed)', () => {
|
||||
assert.ok(fs.existsSync(COMMAND_PATH), `missing ${COMMAND_PATH}`);
|
||||
});
|
||||
|
||||
@@ -82,16 +83,16 @@ describe('gsd-settings-advanced — file scaffolding', () => {
|
||||
const fmMatch = text.match(/^---\n([\s\S]*?)\n---/);
|
||||
assert.ok(fmMatch, 'command file missing frontmatter block');
|
||||
const fm = fmMatch[1];
|
||||
assert.match(fm, /name:\s*gsd:settings-advanced/, 'frontmatter missing name');
|
||||
assert.match(fm, /name:\s*gsd:config/, 'frontmatter missing name (gsd:config)');
|
||||
assert.match(fm, /description:\s*\S/, 'frontmatter missing non-empty description');
|
||||
assert.match(fm, /allowed-tools:/, 'frontmatter missing allowed-tools');
|
||||
});
|
||||
|
||||
test('command routes to the settings-advanced workflow', () => {
|
||||
test('command routes to the settings-advanced workflow via --advanced flag', () => {
|
||||
const text = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
assert.ok(
|
||||
text.includes('workflows/settings-advanced.md'),
|
||||
'command file must reference workflows/settings-advanced.md'
|
||||
text.includes('workflows/settings-advanced.md') || text.includes('--advanced'),
|
||||
'config.md must reference settings-advanced workflow or --advanced flag'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -207,7 +207,10 @@ describe('configureKiloPermissions', () => {
|
||||
describe('Source code integration (Kilo)', () => {
|
||||
const src = fs.readFileSync(path.join(__dirname, '..', 'bin', 'install.js'), 'utf8');
|
||||
const updateWorkflowSrc = fs.readFileSync(path.join(__dirname, '..', 'get-shit-done', 'workflows', 'update.md'), 'utf8');
|
||||
const reapplyPatchesSrc = fs.readFileSync(path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md'), 'utf8');
|
||||
// #2790: reapply-patches.md command was absorbed into update.md --reapply.
|
||||
// The Kilo-specific env-var checks (KILO_CONFIG_DIR, KILO_CONFIG, XDG_CONFIG_HOME)
|
||||
// now live in the update.md workflow (which covers both --sync and --reapply paths).
|
||||
const reapplyPatchesSrc = updateWorkflowSrc;
|
||||
|
||||
test('--kilo flag parsing exists', () => {
|
||||
assert.ok(src.includes("args.includes('--kilo')"), '--kilo flag parsed');
|
||||
|
||||
@@ -15,7 +15,8 @@ const path = require('path');
|
||||
|
||||
describe('/gsd-next safety gates (#1732, #2089)', () => {
|
||||
const workflowPath = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'next.md');
|
||||
const commandPath = path.join(__dirname, '..', 'commands', 'gsd', 'next.md');
|
||||
// #2790: next.md command was consolidated into progress.md as the --next flag.
|
||||
const commandPath = path.join(__dirname, '..', 'commands', 'gsd', 'progress.md');
|
||||
|
||||
test('workflow contains safety_gates step', () => {
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
@@ -160,19 +161,31 @@ describe('/gsd-next safety gates (#1732, #2089)', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('command definition documents --force flag and completeness scan', () => {
|
||||
test('command definition documents --next flag with --force AND completeness routing (#2790)', () => {
|
||||
// #2790 absorbed standalone /gsd-next into /gsd-progress --next. The
|
||||
// consolidated command must preserve BOTH safety-relevant contracts:
|
||||
// (a) --force escape hatch for bypassing safety gates
|
||||
// (b) the completeness scan / next-workflow routing semantics
|
||||
// Earlier OR-based predicates passed when only `--next` was mentioned,
|
||||
// letting the completeness contract regress silently.
|
||||
const content = fs.readFileSync(commandPath, 'utf8');
|
||||
assert.ok(content.includes('--next'),
|
||||
'progress.md must document the --next flag (absorbed from standalone next.md command in #2790)');
|
||||
assert.ok(content.includes('--force'),
|
||||
'progress.md must document the --force escape hatch for --next (#2790 carried over from next.md)');
|
||||
const documentsCompleteness =
|
||||
/completeness/i.test(content) ||
|
||||
/next workflow/i.test(content) ||
|
||||
/scans? all prior phases/i.test(content);
|
||||
assert.ok(documentsCompleteness,
|
||||
'progress.md must document the completeness scan / next-workflow routing for --next (#2790)');
|
||||
});
|
||||
|
||||
test('next workflow documents --force bypass flag', () => {
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
assert.ok(
|
||||
content.includes('--force'),
|
||||
'command definition should mention --force flag'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('bypass safety gates'),
|
||||
'command definition should explain that --force bypasses safety gates'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('completeness'),
|
||||
'command definition should document the prior-phase completeness scan'
|
||||
'next.md workflow must document --force flag for bypassing safety gates'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -243,106 +243,177 @@ describe('saveLocalPatches — patch backup and pristine hash tracking (#1469)',
|
||||
});
|
||||
});
|
||||
|
||||
// allow-test-rule: source-text-is-the-product
|
||||
// update.md routing and reapply-patches.md workflow text IS the deployed behavioral contract.
|
||||
|
||||
/**
|
||||
* Parse a field from YAML frontmatter between --- markers.
|
||||
* Returns null if the frontmatter or field is absent.
|
||||
*/
|
||||
function parseFrontmatterField(content, field) {
|
||||
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
||||
if (!fmMatch) return null;
|
||||
const fm = fmMatch[1];
|
||||
const quoted = fm.match(new RegExp(`^${field}:\\s+"((?:[^"\\\\]|\\\\.)*)"\\s*$`, 'm'));
|
||||
if (quoted) return quoted[1];
|
||||
const plain = fm.match(new RegExp(`^${field}:\\s+(.+)$`, 'm'));
|
||||
if (plain) return plain[1].trim();
|
||||
return null;
|
||||
}
|
||||
|
||||
// #2790: reapply-patches.md command was absorbed into update.md as the --reapply flag.
|
||||
// The full workflow content (three-way merge, hunk verification) is in the referenced workflow.
|
||||
// These tests now verify the update.md command delegates to the reapply-patches workflow correctly.
|
||||
|
||||
/**
|
||||
* Parse a markdown pipe-table into header + rows. Returns null if no table
|
||||
* with the expected header tokens is found. Used to assert structurally
|
||||
* against the Hunk Verification Table without raw substring matching.
|
||||
*/
|
||||
function parsePipeTable(content, expectedHeaderTokens) {
|
||||
const lines = content.split('\n');
|
||||
for (let i = 0; i < lines.length - 1; i++) {
|
||||
const headerLine = lines[i].trim();
|
||||
const sepLine = (lines[i + 1] || '').trim();
|
||||
if (!headerLine.startsWith('|') || !sepLine.startsWith('|')) continue;
|
||||
if (!/^\|\s*[:\- |]+\|\s*$/.test(sepLine)) continue;
|
||||
const header = headerLine.slice(1, -1).split('|').map((s) => s.trim());
|
||||
const headerLower = header.map((h) => h.toLowerCase());
|
||||
const allFound = expectedHeaderTokens.every((tok) => headerLower.includes(tok.toLowerCase()));
|
||||
if (!allFound) continue;
|
||||
const rows = [];
|
||||
for (let j = i + 2; j < lines.length; j++) {
|
||||
const rowLine = lines[j].trim();
|
||||
if (!rowLine.startsWith('|')) break;
|
||||
const cells = rowLine.slice(1, -1).split('|').map((s) => s.trim());
|
||||
const row = {};
|
||||
header.forEach((col, idx) => { row[col] = cells[idx] !== undefined ? cells[idx] : ''; });
|
||||
rows.push(row);
|
||||
}
|
||||
return { header, rows };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('reapply-patches workflow contract (#1469)', () => {
|
||||
test('workflow file contains critical invariant about never skipping backed-up files', () => {
|
||||
const workflowPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
test('reapply-patches.md command file is deleted (absorbed into update.md --reapply, #2790)', () => {
|
||||
const oldPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
assert.ok(!fs.existsSync(oldPath), 'reapply-patches.md should be deleted (absorbed into update.md)');
|
||||
});
|
||||
|
||||
// The workflow must explicitly state that "no custom content" is never valid
|
||||
test('update.md argument-hint declares --reapply as consolidated entry point', () => {
|
||||
// Structural: parse frontmatter, then tokenize the argument-hint pipes
|
||||
// and assert --reapply is one of the documented flags (no raw substring
|
||||
// matching on prose, per the no-source-grep contract).
|
||||
const updatePath = path.join(__dirname, '..', 'commands', 'gsd', 'update.md');
|
||||
const content = fs.readFileSync(updatePath, 'utf8');
|
||||
const argHint = parseFrontmatterField(content, 'argument-hint');
|
||||
assert.ok(argHint, 'update.md frontmatter must declare argument-hint');
|
||||
// argument-hint may include multiple bracketed segments; pull every
|
||||
// `--flag` token out of any bracketed section to assert on a parsed
|
||||
// flag set rather than the surrounding punctuation.
|
||||
const bracketed = [...argHint.matchAll(/\[([^\]]*)\]/g)].map((m) => m[1]);
|
||||
const flagList = bracketed
|
||||
.flatMap((seg) => seg.split('|').map((s) => s.trim().split(/\s+/)[0]))
|
||||
.filter((tok) => tok.startsWith('--'));
|
||||
assert.ok(
|
||||
content.includes('NEVER conclude "no custom content"') ||
|
||||
content.includes('never a valid conclusion'),
|
||||
'workflow must contain the critical invariant about never skipping backed-up files'
|
||||
flagList.includes('--reapply'),
|
||||
`update.md argument-hint flag list must include --reapply; got: ${JSON.stringify(flagList)}`
|
||||
);
|
||||
});
|
||||
|
||||
test('workflow file describes three-way merge strategy', () => {
|
||||
const workflowPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
|
||||
assert.ok(content.includes('three-way') || content.includes('Three-way'),
|
||||
'workflow must describe three-way merge strategy');
|
||||
assert.ok(content.includes('pristine'),
|
||||
'workflow must reference pristine baseline for comparison');
|
||||
});
|
||||
|
||||
test('workflow file describes git-aware detection path', () => {
|
||||
const workflowPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
|
||||
assert.ok(content.includes('git log') || content.includes('git -C'),
|
||||
'workflow must describe git-based detection of user changes');
|
||||
test('update.md @-include declares the reapply-patches workflow as a dependency', () => {
|
||||
// Structural: scan ALL <execution_context> and <execution_context_extended>
|
||||
// blocks for an `@~/.../workflows/reapply-patches.md` include. The earlier
|
||||
// substring check tolerated incidental mentions in prose; matching only the
|
||||
// first context block missed the _extended block where the delegate lives.
|
||||
const updatePath = path.join(__dirname, '..', 'commands', 'gsd', 'update.md');
|
||||
const content = fs.readFileSync(updatePath, 'utf8');
|
||||
const blocks = [
|
||||
...content.matchAll(/<execution_context(?:_extended)?>([\s\S]*?)<\/execution_context(?:_extended)?>/g),
|
||||
].map((m) => m[1]);
|
||||
assert.ok(blocks.length > 0, 'update.md must define at least one <execution_context> block');
|
||||
const includes = blocks
|
||||
.flatMap((blk) => blk.split('\n'))
|
||||
.map((l) => l.trim())
|
||||
.filter((l) => l.startsWith('@'))
|
||||
.map((l) => l.replace(/^@/, ''));
|
||||
const declaresReapply = includes.some((p) => /(^|\/)workflows\/reapply-patches\.md$/.test(p));
|
||||
assert.ok(
|
||||
declaresReapply,
|
||||
`update.md execution_context blocks must @-include workflows/reapply-patches.md; got: ${JSON.stringify(includes)}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// #2790: reapply-patches.md (the command file which contained the inline workflow)
|
||||
// was deleted. The hunk verification contract now lives in the workflow file
|
||||
// get-shit-done/workflows/reapply-patches.md, referenced via execution_context_extended.
|
||||
describe('reapply-patches gated hunk verification (#1999)', () => {
|
||||
let workflowContent;
|
||||
const workflowPath = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'reapply-patches.md');
|
||||
|
||||
before(() => {
|
||||
const workflowPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
workflowContent = fs.readFileSync(workflowPath, 'utf8');
|
||||
test('reapply-patches.md command is deleted and absorbed into update.md (#2790)', () => {
|
||||
const oldPath = path.join(__dirname, '..', 'commands', 'gsd', 'reapply-patches.md');
|
||||
assert.ok(!fs.existsSync(oldPath), 'reapply-patches.md should be absent (absorbed into update.md --reapply)');
|
||||
});
|
||||
|
||||
test('Step 4 requires a Hunk Verification Table output format', () => {
|
||||
// Step 4 must mandate production of a named table with specific columns
|
||||
test('reapply-patches workflow file exists (behavioral contract for --reapply)', () => {
|
||||
assert.ok(fs.existsSync(workflowPath), 'get-shit-done/workflows/reapply-patches.md must exist');
|
||||
});
|
||||
|
||||
test('Step 4 declares a Hunk Verification Table with all required columns', () => {
|
||||
// Structural: parse the markdown pipe-table out of the workflow and
|
||||
// assert its header columns directly. Substring checks let row text
|
||||
// collide with prose mentions and fail under harmless rewording.
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
const required = ['file', 'hunk_id', 'signature_line', 'line_count', 'verified'];
|
||||
const table = parsePipeTable(content, required);
|
||||
assert.ok(
|
||||
workflowContent.includes('Hunk Verification Table'),
|
||||
'Step 4 must require production of a Hunk Verification Table'
|
||||
table,
|
||||
`reapply-patches workflow must declare a pipe-table with header columns ${JSON.stringify(required)} (Hunk Verification Table)`
|
||||
);
|
||||
const headerLower = table.header.map((h) => h.toLowerCase());
|
||||
for (const col of required) {
|
||||
assert.ok(headerLower.includes(col.toLowerCase()), `Hunk Verification Table is missing required column "${col}"; got header ${JSON.stringify(table.header)}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('Step 5 gates progression on the Hunk Verification Table', () => {
|
||||
// Locate the Step 5 section structurally via heading parsing, then
|
||||
// assert it both names the table and defines an explicit gate
|
||||
// condition tied to the `verified` column.
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
const step5Match = content.match(/^##\s+Step 5[^\n]*\n([\s\S]*?)(?=^##\s|\Z)/m);
|
||||
assert.ok(step5Match, 'reapply-patches workflow must contain a "## Step 5" section');
|
||||
const step5 = step5Match[1];
|
||||
assert.ok(
|
||||
/Hunk Verification Table/.test(step5),
|
||||
'Step 5 body must explicitly reference the Hunk Verification Table'
|
||||
);
|
||||
// Gate condition: must mention verified=no (or "verified: no") AND a stop
|
||||
// directive (STOP / halt / abort), so missing-table or any-no-row halts.
|
||||
const referencesVerifiedNo = /verified:\s*no/i.test(step5) || /verified\s*=\s*no/i.test(step5);
|
||||
const referencesStop = /\bSTOP\b/.test(step5) || /\bhalt\b/i.test(step5) || /\babort\b/i.test(step5);
|
||||
assert.ok(
|
||||
referencesVerifiedNo,
|
||||
'Step 5 gate must reference the `verified: no` failure condition (no row may slip past)'
|
||||
);
|
||||
assert.ok(
|
||||
referencesStop,
|
||||
'Step 5 gate must explicitly STOP/halt/abort when verification fails'
|
||||
);
|
||||
});
|
||||
|
||||
test('Hunk Verification Table includes required columns: file, hunk_id, signature_line, line_count, verified', () => {
|
||||
test('Step 5 also halts when the Hunk Verification Table is absent (Step 4 produced nothing)', () => {
|
||||
// Independent gate: missing-table is a separate halt path from any-no-row.
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
const step5Match = content.match(/^##\s+Step 5[^\n]*\n([\s\S]*?)(?=^##\s|\Z)/m);
|
||||
assert.ok(step5Match, 'Step 5 section must exist');
|
||||
const step5 = step5Match[1];
|
||||
const handlesAbsent = /(table is absent|table is missing|missing.*table|absent.*table)/i.test(step5);
|
||||
assert.ok(
|
||||
workflowContent.includes('hunk_id'),
|
||||
'Hunk Verification Table must include hunk_id column'
|
||||
);
|
||||
assert.ok(
|
||||
workflowContent.includes('signature_line'),
|
||||
'Hunk Verification Table must include signature_line column'
|
||||
);
|
||||
assert.ok(
|
||||
workflowContent.includes('line_count'),
|
||||
'Hunk Verification Table must include line_count column'
|
||||
);
|
||||
assert.ok(
|
||||
workflowContent.includes('verified'),
|
||||
'Hunk Verification Table must include verified column'
|
||||
);
|
||||
});
|
||||
|
||||
test('Step 5 references the Hunk Verification Table before proceeding', () => {
|
||||
// Step 5 must consume the table produced by Step 4
|
||||
const step5Match = workflowContent.match(/##\s+Step\s+5[^\n]*\n([\s\S]*?)(?=##\s+Step\s+6|<\/process>|$)/);
|
||||
assert.ok(step5Match, 'Step 5 must exist in the workflow');
|
||||
|
||||
const step5Content = step5Match[1];
|
||||
assert.ok(
|
||||
step5Content.includes('Hunk Verification Table'),
|
||||
'Step 5 must reference the Hunk Verification Table'
|
||||
);
|
||||
});
|
||||
|
||||
test('Step 5 includes an explicit gate that stops execution when verification fails', () => {
|
||||
const step5Match = workflowContent.match(/##\s+Step\s+5[^\n]*\n([\s\S]*?)(?=##\s+Step\s+6|<\/process>|$)/);
|
||||
assert.ok(step5Match, 'Step 5 must exist in the workflow');
|
||||
|
||||
const step5Content = step5Match[1];
|
||||
|
||||
// Must refuse to proceed when any hunk is unverified or the table is absent
|
||||
const hasGate = (
|
||||
step5Content.includes('verified: no') ||
|
||||
step5Content.includes('verified: No') ||
|
||||
step5Content.includes('"no"') ||
|
||||
step5Content.includes('STOP')
|
||||
) && (
|
||||
step5Content.includes('absent') ||
|
||||
step5Content.includes('missing') ||
|
||||
step5Content.includes('not present')
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
hasGate,
|
||||
'Step 5 must include an explicit gate: STOP if any row shows verified: no or the table is absent'
|
||||
handlesAbsent,
|
||||
'Step 5 must include an explicit "table absent / missing" halt path so Step 4 silently producing nothing cannot bypass the gate'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,17 +5,33 @@
|
||||
* verification to detect dropped hunks during three-way merge.
|
||||
*
|
||||
* Closes: #1758
|
||||
*
|
||||
* #2790: reapply-patches.md (combined command+workflow) was consolidated into
|
||||
* update.md as the --reapply flag. The workflow content now lives in
|
||||
* get-shit-done/workflows/reapply-patches.md.
|
||||
*/
|
||||
|
||||
// allow-test-rule: source-text-is-the-product
|
||||
// get-shit-done/workflows/reapply-patches.md is the installed runtime workflow —
|
||||
// its text IS the deployed behavioral contract for the --reapply path.
|
||||
|
||||
const { describe, test, before } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const WORKFLOW_PATH = path.join(
|
||||
__dirname, '..', 'commands', 'gsd', 'reapply-patches.md'
|
||||
__dirname, '..', 'get-shit-done', 'workflows', 'reapply-patches.md'
|
||||
);
|
||||
|
||||
function extractTagBlock(markdown, tagName) {
|
||||
const start = markdown.indexOf(`<${tagName}>`);
|
||||
const end = markdown.indexOf(`</${tagName}>`);
|
||||
assert.notEqual(start, -1, `Missing <${tagName}> block in workflow`);
|
||||
assert.notEqual(end, -1, `Missing </${tagName}> block in workflow`);
|
||||
return markdown.slice(start, end);
|
||||
}
|
||||
|
||||
describe('reapply-patches post-merge verification (#1758)', () => {
|
||||
let content;
|
||||
|
||||
@@ -26,77 +42,67 @@ describe('reapply-patches post-merge verification (#1758)', () => {
|
||||
test('workflow file contains "Post-merge verification" section', () => {
|
||||
assert.ok(
|
||||
content.includes('Post-merge verification'),
|
||||
'workflow must contain a "Post-merge verification" section'
|
||||
'reapply-patches.md workflow must contain a "Post-merge verification" section'
|
||||
);
|
||||
});
|
||||
|
||||
test('workflow mentions "Hunk presence check"', () => {
|
||||
|
||||
assert.ok(
|
||||
content.includes('Hunk presence check'),
|
||||
'workflow must describe hunk presence checking'
|
||||
'workflow must describe the hunk presence check step'
|
||||
);
|
||||
});
|
||||
|
||||
test('workflow mentions "Line-count check"', () => {
|
||||
|
||||
assert.ok(
|
||||
content.includes('Line-count check'),
|
||||
'workflow must describe line-count sanity checking'
|
||||
'workflow must describe the line-count verification step'
|
||||
);
|
||||
});
|
||||
|
||||
test('success criteria includes verification', () => {
|
||||
|
||||
const criteria = content.split('<success_criteria>')[1] || '';
|
||||
// Scope to the structured <success_criteria> block so the assertion can't
|
||||
// false-pass when the phrase appears elsewhere (e.g. inline prose).
|
||||
const successCriteriaBlock = extractTagBlock(content, 'success_criteria');
|
||||
assert.ok(
|
||||
criteria.includes('Post-merge verification') ||
|
||||
criteria.includes('dropped hunks'),
|
||||
'success_criteria must reference post-merge verification or dropped hunks'
|
||||
successCriteriaBlock.includes('Post-merge verification checks each file for dropped hunks'),
|
||||
'workflow success_criteria block must include post-merge verification requirement'
|
||||
);
|
||||
});
|
||||
|
||||
test('verification warns but never auto-reverts', () => {
|
||||
|
||||
assert.ok(
|
||||
content.includes('do not block'),
|
||||
'verification must be advisory (do not block)'
|
||||
content.includes('do not block') || content.includes('Report warnings inline'),
|
||||
'verification must warn and continue — never auto-revert'
|
||||
);
|
||||
});
|
||||
|
||||
test('verification references backup availability for recovery', () => {
|
||||
|
||||
assert.ok(
|
||||
content.includes('Backup available'),
|
||||
'verification warning must reference backup path for manual recovery'
|
||||
content.includes('Backup available') || content.includes('backup available'),
|
||||
'verification warnings must reference backup path for manual recovery'
|
||||
);
|
||||
});
|
||||
|
||||
test('verification tracks per-file status', () => {
|
||||
|
||||
test('verification tracks per-file status via Hunk Verification Table', () => {
|
||||
assert.ok(
|
||||
content.includes('Merged (verified)') &&
|
||||
content.includes('hunks may be missing'),
|
||||
'verification must distinguish "Merged (verified)" from "hunks may be missing" status'
|
||||
content.includes('Hunk Verification Table') &&
|
||||
content.includes('one row per hunk per file') &&
|
||||
content.includes('verified'),
|
||||
'workflow must track verification status per hunk per file via the Hunk Verification Table contract'
|
||||
);
|
||||
});
|
||||
|
||||
test('verification section appears between merge-write and status-report steps', () => {
|
||||
const mergeWritePos = content.indexOf('Write merged result');
|
||||
const verificationPos = content.indexOf('Post-merge verification');
|
||||
const statusReportPos = content.indexOf('Report status per file');
|
||||
|
||||
assert.ok(mergeWritePos > -1, 'workflow must contain "Write merged result" step');
|
||||
assert.ok(verificationPos > -1, 'workflow must contain "Post-merge verification" section');
|
||||
assert.ok(statusReportPos > -1, 'workflow must contain "Report status per file" step');
|
||||
|
||||
const verifyIdx = content.indexOf('Post-merge verification');
|
||||
const writeIdx = content.indexOf('Write merged result');
|
||||
const reportIdx = content.indexOf('Step 7: Report');
|
||||
assert.notEqual(writeIdx, -1, 'Missing "Write merged result" anchor in reapply-patches.md');
|
||||
assert.notEqual(verifyIdx, -1, 'Missing "Post-merge verification" anchor in reapply-patches.md');
|
||||
assert.notEqual(reportIdx, -1, 'Missing "Step 7: Report" anchor in reapply-patches.md');
|
||||
assert.ok(
|
||||
mergeWritePos < verificationPos,
|
||||
'Post-merge verification must appear after "Write merged result"'
|
||||
);
|
||||
assert.ok(
|
||||
verificationPos < statusReportPos,
|
||||
'Post-merge verification must appear before "Report status per file"'
|
||||
writeIdx < verifyIdx && verifyIdx < reportIdx,
|
||||
'Post-merge verification must appear between "Write merged result" and "Step 7: Report"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,15 +3,15 @@ const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// #2790: scan.md was consolidated into map-codebase.md as the --fast flag.
|
||||
// The underlying workflow (workflows/scan.md) remains functional.
|
||||
describe('scan command', () => {
|
||||
test('command file exists with correct name and description', () => {
|
||||
const p = path.join(__dirname, '..', 'commands', 'gsd', 'scan.md');
|
||||
assert.ok(fs.existsSync(p), 'commands/gsd/scan.md should exist');
|
||||
test('scan is now a --fast flag on map-codebase.md (#2790)', () => {
|
||||
const p = path.join(__dirname, '..', 'commands', 'gsd', 'map-codebase.md');
|
||||
assert.ok(fs.existsSync(p), 'commands/gsd/map-codebase.md should exist');
|
||||
const content = fs.readFileSync(p, 'utf-8');
|
||||
assert.ok(content.includes('name: gsd:scan'), 'Command must have name: gsd:scan');
|
||||
assert.ok(content.includes('--fast'), 'map-codebase.md must document --fast flag (absorbed scan)');
|
||||
assert.ok(content.includes('description:'), 'Command must have description frontmatter');
|
||||
assert.ok(content.includes('Rapid codebase assessment') || content.includes('lightweight alternative'),
|
||||
'Description should mention rapid/lightweight assessment');
|
||||
});
|
||||
|
||||
test('workflow file exists', () => {
|
||||
|
||||
@@ -31,7 +31,8 @@ const {
|
||||
} = require('../get-shit-done/bin/lib/config-schema.cjs');
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '..');
|
||||
const COMMAND_PATH = path.join(REPO_ROOT, 'commands', 'gsd', 'settings-integrations.md');
|
||||
// #2790: settings-integrations.md was consolidated into config.md as the --integrations flag.
|
||||
const COMMAND_PATH = path.join(REPO_ROOT, 'commands', 'gsd', 'config.md');
|
||||
const WORKFLOW_PATH = path.join(REPO_ROOT, 'get-shit-done', 'workflows', 'settings-integrations.md');
|
||||
const SKILL_PATH = path.join(REPO_ROOT, '.claude', 'skills', 'gsd-settings-integrations.md');
|
||||
const SETTINGS_WORKFLOW_PATH = path.join(REPO_ROOT, 'get-shit-done', 'workflows', 'settings.md');
|
||||
@@ -43,13 +44,15 @@ function readIfExists(p) {
|
||||
// ─── Artifacts ───────────────────────────────────────────────────────────────
|
||||
|
||||
describe('#2529 artifacts', () => {
|
||||
test('command exists at commands/gsd/settings-integrations.md', () => {
|
||||
test('consolidated config.md command exists (#2790: settings-integrations absorbed)', () => {
|
||||
// #2790: settings-integrations.md was absorbed into config.md as the --integrations flag.
|
||||
assert.ok(fs.existsSync(COMMAND_PATH), `missing ${COMMAND_PATH}`);
|
||||
});
|
||||
|
||||
test('command frontmatter declares name gsd:settings-integrations', () => {
|
||||
test('config.md frontmatter declares name gsd:config and routes to --integrations', () => {
|
||||
const src = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
assert.match(src, /^---\s*\nname:\s*gsd:settings-integrations\s*\n/m);
|
||||
// #2790: consolidated command uses gsd:config name
|
||||
assert.match(src, /name:\s*gsd:config/);
|
||||
assert.match(src, /description:\s*.+/);
|
||||
assert.match(src, /allowed-tools:/);
|
||||
assert.match(src, /AskUserQuestion/);
|
||||
@@ -59,12 +62,8 @@ describe('#2529 artifacts', () => {
|
||||
assert.ok(fs.existsSync(WORKFLOW_PATH), `missing ${WORKFLOW_PATH}`);
|
||||
});
|
||||
|
||||
test('skill stub exists at .claude/skills/gsd-settings-integrations.md OR equivalent canonical command surface ships', () => {
|
||||
// `.claude/skills/` is gitignored in this repo — the skill surface that
|
||||
// actually ships is `commands/gsd/settings-integrations.md` paired with
|
||||
// `get-shit-done/workflows/settings-integrations.md`. The `.claude/skills/`
|
||||
// stub is generated at install time and may also be present locally.
|
||||
// Treat either as satisfying the acceptance criterion.
|
||||
test('skill stub or canonical command surface ships (#2790: via config.md --integrations)', () => {
|
||||
// #2790: The command surface is now config.md + settings-integrations.md workflow.
|
||||
const hasStub = fs.existsSync(SKILL_PATH);
|
||||
const hasCanonical =
|
||||
fs.existsSync(COMMAND_PATH) && fs.existsSync(WORKFLOW_PATH);
|
||||
@@ -74,9 +73,12 @@ describe('#2529 artifacts', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('command delegates execution to the workflow', () => {
|
||||
test('config.md routes --integrations to the settings-integrations workflow', () => {
|
||||
const src = fs.readFileSync(COMMAND_PATH, 'utf-8');
|
||||
assert.match(src, /workflows\/settings-integrations\.md/);
|
||||
assert.ok(
|
||||
src.includes('workflows/settings-integrations.md') || src.includes('--integrations'),
|
||||
'config.md must reference settings-integrations workflow or --integrations flag'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -311,29 +311,106 @@ describe('workspace worktree integration', () => {
|
||||
});
|
||||
|
||||
// ─── Command and workflow file existence ────────────────────────────────────
|
||||
// #2790: new-workspace.md, list-workspaces.md, remove-workspace.md were
|
||||
// consolidated into a single workspace.md command with --new/--list/--remove flags.
|
||||
|
||||
// allow-test-rule: source-text-is-the-product
|
||||
// workspace.md routing text and workflow content IS the deployed behavioral contract for the agent.
|
||||
|
||||
describe('workspace command files', () => {
|
||||
const baseDir = path.join(__dirname, '..');
|
||||
|
||||
test('new-workspace command exists with correct frontmatter', () => {
|
||||
const content = fs.readFileSync(path.join(baseDir, 'commands/gsd/new-workspace.md'), 'utf8');
|
||||
assert.ok(content.includes('name: gsd:new-workspace'));
|
||||
assert.ok(content.includes('--name'));
|
||||
assert.ok(content.includes('--repos'));
|
||||
assert.ok(content.includes('--strategy'));
|
||||
assert.ok(content.includes('workflows/new-workspace.md'));
|
||||
/**
|
||||
* Split frontmatter / body and parse simple YAML-ish key:value pairs.
|
||||
* Returns { fm: { name, argument-hint, ... }, body }. Avoids raw
|
||||
* substring matching on the file as a whole.
|
||||
*/
|
||||
function parseCommandFile(filePath) {
|
||||
const raw = fs.readFileSync(filePath, 'utf8');
|
||||
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
||||
assert.ok(fmMatch, `${path.basename(filePath)} must start with a YAML frontmatter block`);
|
||||
const fm = {};
|
||||
for (const line of fmMatch[1].split('\n')) {
|
||||
const kv = line.match(/^([a-zA-Z_-]+):\s*(.*)$/);
|
||||
if (!kv) continue;
|
||||
const key = kv[1];
|
||||
let val = kv[2].trim();
|
||||
if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
|
||||
fm[key] = val;
|
||||
}
|
||||
return { fm, body: fmMatch[2] };
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract `@`-include targets from any of the <execution_context*> blocks.
|
||||
* Each line of the form `@~/.claude/get-shit-done/workflows/foo.md` becomes
|
||||
* a relative target like `workflows/foo.md`. Used to assert workflow
|
||||
* routing structurally instead of substring-matching prose.
|
||||
*/
|
||||
function executionContextIncludes(body) {
|
||||
const blocks = [...body.matchAll(/<execution_context(?:_extended)?>([\s\S]*?)<\/execution_context(?:_extended)?>/g)]
|
||||
.map((m) => m[1]);
|
||||
const targets = [];
|
||||
for (const blk of blocks) {
|
||||
for (const line of blk.split('\n')) {
|
||||
const t = line.trim();
|
||||
if (!t.startsWith('@')) continue;
|
||||
// Normalize away the home-prefix and the `.claude/get-shit-done/` root
|
||||
// so the test only cares about the workflow path tail.
|
||||
const rel = t.replace(/^@~?\/?(?:\.claude\/)?(?:get-shit-done\/)?/, '');
|
||||
targets.push(rel);
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
test('consolidated workspace.md command declares correct frontmatter contract (#2790)', () => {
|
||||
// Structural: parse frontmatter, then split argument-hint into the
|
||||
// tokenized flag list. Each consolidated flag must appear there.
|
||||
const { fm } = parseCommandFile(path.join(baseDir, 'commands/gsd/workspace.md'));
|
||||
assert.equal(fm.name, 'gsd:workspace', `workspace.md frontmatter name must be "gsd:workspace"; got "${fm.name}"`);
|
||||
assert.ok(fm['argument-hint'], 'workspace.md frontmatter must declare argument-hint');
|
||||
// argument-hint can include multiple bracketed segments and free tokens,
|
||||
// e.g. "[--new | --list | --remove] [name]". Pull every `--flag` token
|
||||
// out of any bracketed segment so the test asserts on a parsed flag set,
|
||||
// not the punctuation around it.
|
||||
const bracketed = [...fm['argument-hint'].matchAll(/\[([^\]]*)\]/g)].map((m) => m[1]);
|
||||
const flagList = bracketed
|
||||
.flatMap((seg) => seg.split('|').map((s) => s.trim().split(/\s+/)[0]))
|
||||
.filter((tok) => tok.startsWith('--'));
|
||||
for (const flag of ['--new', '--list', '--remove']) {
|
||||
assert.ok(
|
||||
flagList.includes(flag),
|
||||
`workspace.md argument-hint must declare ${flag}; got: ${JSON.stringify(flagList)}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('list-workspaces command exists with correct frontmatter', () => {
|
||||
const content = fs.readFileSync(path.join(baseDir, 'commands/gsd/list-workspaces.md'), 'utf8');
|
||||
assert.ok(content.includes('name: gsd:list-workspaces'));
|
||||
assert.ok(content.includes('workflows/list-workspaces.md'));
|
||||
test('workspace.md @-includes the new-workspace workflow', () => {
|
||||
const { body } = parseCommandFile(path.join(baseDir, 'commands/gsd/workspace.md'));
|
||||
const targets = executionContextIncludes(body);
|
||||
assert.ok(
|
||||
targets.some((t) => /(^|\/)workflows\/new-workspace\.md$/.test(t)),
|
||||
`workspace.md execution_context must @-include workflows/new-workspace.md; got: ${JSON.stringify(targets)}`
|
||||
);
|
||||
});
|
||||
|
||||
test('remove-workspace command exists with correct frontmatter', () => {
|
||||
const content = fs.readFileSync(path.join(baseDir, 'commands/gsd/remove-workspace.md'), 'utf8');
|
||||
assert.ok(content.includes('name: gsd:remove-workspace'));
|
||||
assert.ok(content.includes('workflows/remove-workspace.md'));
|
||||
test('workspace.md @-includes the list-workspaces workflow', () => {
|
||||
const { body } = parseCommandFile(path.join(baseDir, 'commands/gsd/workspace.md'));
|
||||
const targets = executionContextIncludes(body);
|
||||
assert.ok(
|
||||
targets.some((t) => /(^|\/)workflows\/list-workspaces\.md$/.test(t)),
|
||||
`workspace.md execution_context must @-include workflows/list-workspaces.md; got: ${JSON.stringify(targets)}`
|
||||
);
|
||||
});
|
||||
|
||||
test('workspace.md @-includes the remove-workspace workflow', () => {
|
||||
const { body } = parseCommandFile(path.join(baseDir, 'commands/gsd/workspace.md'));
|
||||
const targets = executionContextIncludes(body);
|
||||
assert.ok(
|
||||
targets.some((t) => /(^|\/)workflows\/remove-workspace\.md$/.test(t)),
|
||||
`workspace.md execution_context must @-include workflows/remove-workspace.md; got: ${JSON.stringify(targets)}`
|
||||
);
|
||||
});
|
||||
|
||||
test('new-workspace workflow exists', () => {
|
||||
|
||||
Reference in New Issue
Block a user