* fix(3668): isolate --local install from global gsd-sdk
- `buildGsdSdkVersionMismatchReport` now accepts `opts.isLocal`; when
true it sets `fix_command` to `npx get-shit-done-cc@latest --claude
--local` instead of `npm install -g …`, removing the misleading global
upgrade suggestion for local installs.
- Propagate `isLocal` from `installSdkIfNeeded` into the mismatch report
builder so the right fix_command reaches the renderer.
- Export `buildGsdSdkVersionMismatchReport` and
`renderGsdSdkVersionMismatchReport` so tests can assert on the IR
contract directly.
- Add `command -v gsd-sdk … elif node "$GSD_TOOLS"` preflight SDK
resolution block to all 69 workflow files that called bare `gsd-sdk`
with no fallback, matching the pattern established in update.md,
execute-phase.md, and quick.md.
- Add `tests/bug-3668-local-install-sdk-soft-dep.test.cjs` with 5 tests
covering Defects 1-3, including a CI lint guard that blocks future
workflow regressions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* changeset: add Fixed entry for #3668
* fix(3668): add allow-test-rule to suppress false lint-no-source-grep violation
The test reads workflow .md files (product content) to assert structural
invariants — not .cjs source files. The file-presence check is the only
viable IR for markdown guard patterns. Add the // allow-test-rule annotation
so lint-no-source-grep passes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3668): fix do.md false-positive and discuss-phase.md size overflow
Two CI failures introduced by the 69-workflow preflight block:
1. do.md: the path `bin/gsd-tools.cjs` contains `/gsd-tools` which the
bug-2954 parity test regex `/\/gsd[:-]([a-z][a-z0-9-]*)/g` mistakenly
extracts as a slash command named `tools`. Fix: store the shim filename
in _GSD_SHIM_NAME so the path construction no longer contains a static
`/gsd-tools` literal. Also wire $GSD_SDK into the actual query call.
2. discuss-phase.md: the file was at 499 lines (the 500-line budget from
#2551). Adding the 11-line preflight block pushed it to 510, failing
workflow-size-budget.test.cjs. Fix: compress the 11-line preflight +
2-line invocations into 3 lines (one-liner guard + two $GSD_SDK calls)
returning the file to 499 lines while retaining the command -v guard
required by bug-3668-local-install-sdk-soft-dep.test.cjs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3668): wire \$GSD_SDK through all workflow callsites (#3797)
PR #3797 introduced the resolution preflight block (setting \$GSD_SDK) in
69 workflows but left every downstream gsd-sdk callsite using the bare
command. On local-only installs the preflight exits cleanly, then the
very next line fails with 'command not found'. This is the structural
gap the Codex review flagged.
Changes:
- 687 bare `gsd-sdk` callsites replaced with `\$GSD_SDK` across 75
workflow files (all bash/sh fenced blocks excluding the resolution
guard blocks themselves)
- execute-phase.md: was missing the preflight block entirely — added
the standard 11-line resolution block at the initialize step
- execute-phase.md: inline `if command -v gsd-sdk` availability guard
(legacy #3384 fallback) replaced with `\$GSD_SDK` + error fallback
since the new preflight guarantees SDK availability or exits 1
- 6 sub-workflow files (discuss-phase/modes/*, execute-phase/steps/*)
that have no preflight of their own but use \$GSD_SDK — these are
loaded by parent workflows that set the variable; callsites updated
to use \$GSD_SDK so they work when variable is in scope
Transformation script used: /private/tmp/fw2.js (regex-based fence
parser with segment join invariant verification — preserves all blank
lines and prose formatting).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(3668): upgrade CI guard to detect bare callsite routing (#3797)
The previous Defect 3 test checked that 'command -v gsd-sdk' appeared
as a string in the file — a guard-presence check, not a callsite-routing
check. A workflow with the preflight block but 40 bare gsd-sdk calls
below it passed the old test. This is exactly the bug state PR #3797
was supposed to fix.
Upgraded test:
- Parses each workflow file into markdown segments using a regex-based
fence extractor (preserves all content invariantly)
- Skips bash/sh blocks that contain 'command -v gsd-sdk' (those are
resolution guards — bare references there are expected)
- Flags any remaining bash/sh block line that invokes gsd-sdk without
the \$ prefix (isBareGsdSdkInvocation predicate)
- Counter-test proves the predicate correctly flags real callsite lines
and correctly exempts guard assignments, comments, and \$GSD_SDK refs
Also adds helper functions parseMarkdownSegments, isBareGsdSdkInvocation,
and findMdFiles which are used by both the upgraded Defect 3 test and
the counter-test.
This test would have caught the originally-shipped bug: the preflight
block was present but callsites still used bare gsd-sdk.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update workflow content tests to accept \$GSD_SDK callsite form (#3797)
Six regression tests assert on the exact textual pattern of gsd-sdk calls
inside workflow .md files. After the #3797 callsite replacement (687 bare
`gsd-sdk` invocations replaced with `\$GSD_SDK`), these tests failed because
they searched for the literal string `gsd-sdk query <cmd>` which no longer
appears at callsites.
Updated each test to accept both the pre-#3797 bare form and the post-#3797
variable form using `(?:\$GSD_SDK|gsd-sdk)` regex alternation (or two-branch
`includes()` checks for non-regex assertions). The structural invariants each
test enforces are unchanged — we're accepting the same behavioral contract
through the new callsite surface.
Tests fixed:
- bug-2334-quick-gsd-sdk-preflight: find init.quick call via \$GSD_SDK or bare
- bug-2661-roadmap-sync-parallel: roadmap.update-plan-progress call pattern
- bug-3360-codex-execute-phase-worktrees: RUNTIME config-get call detection
- bug-3381-verify-work-workstream: init.verify-work / phase.mvp-mode calls
- enh-2433-todo-phase-linking: commit call in new-milestone.md
- enh-2792-namespace-skills: validate.context invocation in context_check step
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update remaining workflow content tests to accept \$GSD_SDK form (#3797)
After #3797 callsite replacement, ultraplan-phase.test.cjs and worktree-cleanup.test.cjs
still assert bare gsd-sdk form. Update to accept either \$GSD_SDK or gsd-sdk. Also trim
the execute-phase.md preflight comment to stay within the XL line-count budget (1810).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3668): adopt inline-per-fence SDK resolution + restore safety semantics
The brief offered three options:
(a) inline preflight block per fence
(b) wrapper script
(c) shared shell fragment sourced at the top
71 of 72 workflow files already had inline preflight blocks (just broken ones).
Option (b)/(c) would have required changes to install.js + a new shared artifact,
with significant risk of breaking the install pipeline. Option (a) was the path
of least resistance and least new blast radius.
**BLOCKER 1+2+3 (quick.md — GSD_SDK never assigned):**
- quick.md had 12 `$GSD_SDK` references but zero `GSD_SDK=` assignments.
- Added proper local-first preflight block with `git rev-parse --show-toplevel`
path (not the broken `CLAUDE_FILE_PATHS` which is always empty in Claude Code).
- Each Bash fence in Claude Code runs as a fresh `bash -c`, so env vars don't
persist. The preflight block must appear in every fence that uses $GSD_SDK.
**BLOCKER 4 (execute-phase.md — || exit 1 dropped):**
- Restored `|| exit 1` after every `worktree.cleanup-wave` call. SDK safety
refusals (drift detection #3174, deletion block #2384) must surface, not be
swallowed by the old `|| { fallback }` branch.
**F5 (verify-work.md untyped fence):**
- Changed bare `gsd-sdk` in an untyped fence to `$GSD_SDK`.
- Changed fence tag from untyped to `bash`.
**F6 (non-recursive readdirSync):**
- Defect 2 test now uses `findMdFiles` (recursive) to cover workflow
subdirectories, not the flat `fs.readdirSync` that missed subdirs.
**F7 (lint misses untyped fences):**
- `parseMarkdownSegments` now treats `lang === ''` fences as bash-fences.
**F8 (missing propagation test):**
- Added two propagation tests in the Defect 3 describe block.
**F9 (priority inverted — global before local):**
- All 72 workflow files now check `[ -f "$GSD_TOOLS" ]` before `command -v gsd-sdk`.
- Path: `$(git rev-parse --show-toplevel 2>/dev/null || pwd)/get-shit-done/bin/gsd-tools.cjs`
**F10/F11 (broken quoting):**
- Changed `GSD_SDK="node "$GSD_TOOLS""` → `GSD_SDK="node $GSD_TOOLS"` across all files.
**SDK-absence fallback removal:**
- The old `|| { STATE_BACKUP=...; while IFS=...WAS_DELETED...; done }` fallback
code was dead — preflight now exits if neither local nor global SDK exists.
Removed from quick.md, execute-phase.md. Tests updated to verify SDK delegation
rather than inline shell mechanics.
**Tests updated:**
- bug-2384, bug-2501, bug-2838, bug-3091, bug-3195, bug-3521, bug-3668,
worktree-cleanup — all updated to reflect SDK delegation contract.
- Defect 2 test now uses bash-fence scan (not raw content) to skip docs-only
gsd-sdk prose references (e.g. discuss-phase/modes/text.md).
Closes#3668
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3668): restore _GSD_SHIM_NAME indirection in do.md to prevent false-positive
The top commit re-introduced a literal /get-shit-done/bin/gsd-tools.cjs path
in do.md, causing bug-2954 test to match /gsd-tools as an unshipped slash
command. Restore the _GSD_SHIM_NAME variable indirection (from ff9939e5) to
break the literal path while preserving local-first preference order.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update worktree.test.cjs to accept SDK delegation contract (#3797)
Mirror the contract update already applied to worktree-cleanup.test.cjs:
- pre-merge deletion check tests: accept worktree.cleanup-wave + deletion
mention as valid (inline --diff-filter=D was in the removed shell fallback)
- quick.md bug-2431 tests (lock-aware, unlock retry, residual warning): accept
worktree.cleanup-wave delegation as sufficient (these safety behaviors are
now handled internally by the SDK cleanup-wave command)
execute-phase.md tests unchanged: it retains inline .git/worktrees/, locked,
git worktree unlock, and Residual worktree in its cleanup-tail snippet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(3668): refactor bug-2384 and bug-2838 from grep to structured assertions
Replace content.includes() on readFileSync-bound variables with parser
functions that split lines and return typed boolean fields, matching the
project's no-source-grep contract (lint-no-source-grep rule F/G).
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
All workflow, command, reference, template, and tool-output files that
surfaced /gsd:<cmd> as a user-typed slash command have been updated to
use /gsd-<cmd>, matching the Claude Code skill directory name.
Closes#2697
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Commands are now installed as commands/gsd/<name>.md and invoked as
/gsd:<name> in Claude Code. The old hyphen form /gsd-<name> was still
hardcoded in hundreds of places across workflows, references, templates,
lib modules, and command files — causing "Unknown command" errors
whenever GSD suggested a command to the user.
Replace all /gsd-<cmd> occurrences where <cmd> is a known command name
(derived at runtime from commands/gsd/*.md) using a targeted Node.js
script. Agent names, tool names (gsd-sdk, gsd-tools), directory names,
and path fragments are not touched.
Adds regression test tests/bug-2543-gsd-slash-namespace.test.cjs that
enforces zero legacy occurrences going forward. Removes inverted
tests/stale-colon-refs.test.cjs (bug #1748) which enforced the now-obsolete
hyphen form; the new bug-2543 test supersedes it. Updates 5 assertion
tests that hardcoded the old hyphen form to accept the new colon form.
Closes#2543
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(handoffs): include project identity in all Next Up blocks
Adds project_code and project_title to withProjectRoot() and updates
all 30 Next Up headings across 18 workflow files to include
[PROJECT_CODE] PROJECT_TITLE suffix for multi-project clarity.
Closes#1948
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(review): add withProjectRoot tests and fix placeholder syntax (#1951)
Address code review feedback:
- Add 4 tests for project_code/project_title injection in withProjectRoot()
- Fix inconsistent placeholder syntax in continuation-format.md canonical
template (bare-brace → shell-dollar to match variant examples)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(phase): preserve zero-padded prefix in renameDecimalPhases
Captures the zero-padded prefix (e.g. "06" from "06.3-slug") with
(0*${baseInt}) so renamed directories keep their original format
(06.2-slug) instead of stripping padding (6.2-slug).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Higgins <brandonscotthiggins@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AskUserQuestion is a Claude Code-only tool. When running GSD on OpenAI Codex,
Gemini CLI, or other non-Claude runtimes, the model renders the tool call as a
markdown code block instead of executing it, so the interactive TUI never
appears and the session stalls without collecting user input.
The workflow.text_mode / --text flag mechanism already handles this in 5 of
the 37 affected workflows. This commit adds the same TEXT_MODE fallback
instruction to all remaining 32 workflows so that, when text_mode is enabled,
every AskUserQuestion call is replaced with a plain-text numbered list that
any runtime can handle.
Fixes#2012
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: replace /gsd: command format with /gsd- skill format in all suggestions
All next-step suggestions shown to users were still using the old colon
format (/gsd:xxx) which cannot be copy-pasted as skills. Migrated all
occurrences across agents/, commands/, get-shit-done/, docs/, README files,
bin/install.js (hardcoded defaults for claude runtime), and
get-shit-done/bin/lib/*.cjs (generate-claude-md templates and error messages).
Updated tests to assert new hyphen format instead of old colon format.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: migrate remaining /gsd: format to /gsd- in hooks, workflows, and sdk
Addresses remaining user-facing occurrences missed in the initial migration:
- hooks/: fix 4 user-facing messages (pause-work, update, fast, quick)
and 2 comments in gsd-workflow-guard.js
- get-shit-done/workflows/: fix 21 Skill() literal calls that Claude
executes directly (installer does not transform workflow content)
- sdk/prompt-sanitizer.ts: update regex to strip /gsd- format in addition
to legacy /gsd: format; update JSDoc comment
- tests/: update autonomous-ui-steps, prompt-sanitizer to assert new format
Note: commands/gsd/*.md frontmatter (name: gsd:xxx) intentionally unchanged
— installer derives skillName from directory path, not the name field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(plan-phase): preserve --chain flag in auto-advance sync and handle ui-phase gate in chain mode
Bug 1: step 15 sync-flag check only guarded against --auto, causing
_auto_chain_active to be cleared when plan-phase is invoked without
--auto in ARGUMENTS even though a --chain pipeline was active. Added
--chain to the guard condition, matching discuss-phase behaviour.
Bug 2: UI Design Contract gate (step 5.6) always exited the workflow
when UI-SPEC was missing, breaking the discuss --chain pipeline
silently. When _auto_chain_active is true, the gate now auto-invokes
gsd-ui-phase --auto via Skill() and continues to step 6 without
prompting. Manual invocations retain the existing AskUserQuestion flow.
* fix: remove <sub>/clear</sub> pattern and duplicate old-format command in discuss-phase.md
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Address 4 root causes of Windows + Claude Code reliability issues:
1. Workflow shell robustness: add || true guards to informational commands
(ls, grep, find, cat) that return non-zero on "no results", preventing
workflow step failures under strict execution models. Guard glob loops
with [ -e "$var" ] || continue to handle empty glob expansion.
2. Hook stdin handling: replace readFileSync('/dev/stdin') with async
process.stdin + timeout in agent templates (gsd-verifier.md). Existing
JS hooks already have timeout guards.
3. project_root detection: fix isInsideGitRepo() to check .git at the
candidate parent level (not just below it), enabling correct detection
when .git and .planning/ are siblings at the same directory level —
the common single-repo case from a subdirectory.
4. @file: handoff: add missing @file: handlers to autonomous.md and
manager.md workflows that call gsd-tools init but lacked the handler
for large output payloads.
Fixes#1343
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When gsd-tools init output exceeds 50KB, core.cjs writes to a temp file
and outputs @file:<path>. No workflow handled this prefix, causing agents
to hallucinate /tmp paths that fail on Windows (C:\tmp doesn't exist).
Add @file: resolution line after every INIT=$(node ...) call across all
32 workflow, agent, and reference files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude Code subagents sometimes rewrite ~/. paths to relative paths,
causing MODULE_NOT_FOUND when CWD is the project directory. $HOME is a
shell variable resolved at runtime, immune to model path rewriting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Records test generation in project state via state-snapshot call,
keeping add-tests consistent with other GSD workflows that track
their operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New command that generates unit and E2E tests for completed phases:
- Analyzes implementation files and classifies into TDD/E2E/Skip
- Enforces RED-GREEN gates for both unit and E2E tests
- Uses phase SUMMARY.md, CONTEXT.md, and VERIFICATION.md as test specs
- Presents test plan for user approval before generating
Test classification rules:
- TDD: pure functions where expect(fn(input)).toBe(output) is writable
- E2E: UI behavior verifiable by Playwright (keyboard, navigation, forms)
- Skip: styling, config, glue code, migrations, simple CRUD
Ref: Issue #302