Compare commits

...

29 Commits

Author SHA1 Message Date
Tom Boucher
53078d3f85 fix: scale context meter to usable window respecting CLAUDE_CODE_AUTO_COMPACT_WINDOW (#2219)
The autocompact buffer percentage was hardcoded to 16.5%. Users who set
CLAUDE_CODE_AUTO_COMPACT_WINDOW to a custom token count (e.g. 400000 on
a 1M-context model) saw a miscalibrated context meter and incorrect
warning thresholds in the context-monitor hook (which reads used_pct from
the bridge file the statusline writes).

Now reads CLAUDE_CODE_AUTO_COMPACT_WINDOW from the hook env and computes:
  buffer_pct = acw_tokens / total_tokens * 100
Defaults to 16.5% when the var is absent or zero, preserving existing
behavior.

Also applies the renameDecimalPhases zero-padding fix for clean CI.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 15:40:15 -04:00
Tom Boucher
712e381f13 docs: document required Bash permission patterns for executor subagents (#2071) (#2288)
* docs: document required Bash permission patterns for gsd-executor subagents (Closes #2071)

Adds a new "Executor Subagent Gets Permission denied on Bash Commands"
section to USER-GUIDE.md Troubleshooting. Documents the wildcard Bash
patterns that must be added to ~/.claude/settings.json (or per-project
.claude/settings.local.json) for each supported stack so fresh installs
aren't blocked mid-execution.

Covers: git write commands, gh, Rails/Ruby, Python/uv, Node/npm/pnpm/bun,
and Rust/Cargo. Includes a complete example settings.json snippet for Rails.

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

* fix(phase): preserve zero-padded prefix in renameDecimalPhases

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 22:47:12 -04:00
Tom Boucher
09e471188d fix(uat): accept bracketed result values and fix decimal phase renumber padding (#2283)
- uat.cjs: change result capture from \w+ to \[?(\w+)\]? so result: [pending],
  [blocked], [skipped] are parsed correctly (Closes #2273)
- phase.cjs: capture zero-padded prefix in renameDecimalPhases so renamed dirs
  preserve original format (e.g. 06.3-slug → 06.2-slug, not 6.2-slug)
- tests/uat.test.cjs: add regression test for bracketed result values (#2273)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 22:46:57 -04:00
Rezolv
d3a79917fa feat: Phase 2 caller migration — gsd-sdk query in workflows, agents, commands (#2179)
* feat: Phase 2 caller migration — gsd-sdk query in workflows (#2122)

Cherry-picked orchestration rewrites from feat/sdk-foundation (#2008, 4018fee) onto current main, resolving conflicts to keep upstream worktree guards and post-merge test gate. SDK stub registry omitted (out of Phase 2 scope per #2122).

Refs: #2122 #2008
Made-with: Cursor

* docs: add gsd-sdk query migration blurb

Made-with: Cursor

* docs(workflows): extend Phase 2 gsd-sdk query caller migration

- Swap node gsd-tools.cjs for gsd-sdk query in review, plan-phase, execute-plan,
  ship, extract_learnings, ai-integration-phase, eval-review, next, thread
- Document graphify CJS-only in gsd-planner; dual-path in CLI-TOOLS and ARCHITECTURE
- Update tests: workstreams gsd-sdk path, thread frontmatter.get, workspace init.*,
  CRLF-safe autonomous frontmatter parse
- CHANGELOG: Phase 2 caller migration scope

Made-with: Cursor

* docs(phase2): USER-GUIDE + remaining gsd-sdk query call sites

- USER-GUIDE: dual-path CLI section; state validate/sync use full CJS path
- Commands: debug (config-get+tdd), quick (security note), intel Task prompt
- Agent: gsd-debug-session-manager resolve-model via jq
- Workflows: milestone-summary, forensics, next, complete-milestone/verify-work
  (audit-open CJS notes), discuss-phase, progress, verify-phase, add/insert/remove
  phase, transition, manager, quick workflow; remove-phase commit without --files
- Test: quick-session-management accepts frontmatter.get
- CHANGELOG: Phase 2 follow-up bullet

Made-with: Cursor

* docs(phase2): align gsd-sdk query examples in commands and agents

- init.* query names; frontmatter.get uses positional field name
- state.* handlers use positional args; commit uses positional paths
- CJS-only notes for from-gsd2 and graphify; learnings.query wording
- CHANGELOG: Phase 2 orchestration doc pass

Made-with: Cursor

* docs(phase2): normalize gsd-sdk query commit to positional file paths

- Strip --files from commit examples in workflows, references, commands
- Keep commit-to-subrepo ... --files (separate handler)
- git-planning-commit.md: document positional args
- Tests: new-project commit line, state.record-session, gates CRLF, roadmap.analyze
- CHANGELOG [Unreleased]

Made-with: Cursor

* feat(sdk): gsd-sdk query parity with gsd-tools and PR 2179 registry fixes

- Route query via longest-prefix match and dotted single-token expansion; fall back
  to runGsdToolsQuery (same argv as node gsd-tools.cjs) for full CLI coverage.
- Parse gsd-sdk query permissively so gsd-tools flags (--json, --verify, etc.) are
  not rejected by strict parseArgs.
- resolveGsdToolsPath: honor GSD_TOOLS_PATH; prefer bundled get-shit-done copy
  over project .claude installs; export runGsdToolsQuery from the SDK.
- Fix gsd-tools audit-open (core.output; pass object for --json JSON).
- Register summary-extract as alias of summary.extract; fix audit-fix workflow to
  call audit-uat instead of invalid init.audit-uat (PR review).

Updates QUERY-HANDLERS.md and CHANGELOG [Unreleased].

Made-with: Cursor

* fix(sdk): Phase 2 scope — Trek-e review (#2179, #2122)

- Remove gsd-sdk query passthrough to gsd-tools.cjs; drop GSD_TOOLS_PATH
- Consolidate argv routing in resolveQueryArgv(); update USAGE and QUERY-HANDLERS
- Surface @file: read failures in GSDTools.parseOutput
- execute-plan: defer Task Commit Protocol to gsd-executor
- stale-colon-refs: skip .planning/ and root CLAUDE.md (gitignored overlays)
- CHANGELOG [Unreleased]: maintainer review and routing notes

Made-with: Cursor
2026-04-15 22:46:31 -04:00
Tom Boucher
762b8ed25b fix(add-backlog): write ROADMAP entry before directory creation to prevent false duplicate detection (#2286)
Swaps steps 3 and 4 in add-backlog.md so ROADMAP.md is updated before
the phase directory is created. Directory existence is now a reliable
indicator that a phase is already registered, preventing false duplicate
detection in hooks that check for existing 999.x directories (Closes #2280).

Also fixes renameDecimalPhases to preserve zero-padded directory prefixes
(e.g. "06.3-slug" → "06.2-slug" instead of "6.2-slug").

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 16:46:13 -04:00
Tom Boucher
5f521e0867 fix(settings): route /gsd-settings reads/writes through workstream-aware config path (#2285)
settings.md was reading and writing .planning/config.json directly while
gsd-tools config-get/config-set route to .planning/workstreams/<slug>/config.json
when GSD_WORKSTREAM is active, causing silent write-read drift (Closes #2282).

- config.cjs: add cmdConfigPath() — emits the planningDir-resolved config path as
  plain text (always raw, no JSON wrapping) so shell substitution works correctly
- gsd-tools.cjs: wire config-path subcommand
- settings.md: resolve GSD_CONFIG_PATH via config-path in ensure_and_load_config;
  replace hardcoded cat .planning/config.json and Write to .planning/config.json
  with $GSD_CONFIG_PATH throughout
- phase.cjs: fix renameDecimalPhases to preserve zero-padded prefix (06.3 → 06.2
  not 6.2) — pre-existing test failure on main
- tests/config.test.cjs: add config-path command tests (#2282)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 16:46:10 -04:00
Tom Boucher
55877d372f feat(handoffs): include project identity in all Next Up blocks (#1948) (#2287)
* 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>
2026-04-15 16:43:02 -04:00
Tom Boucher
779bd1a383 feat(progress): add --forensic flag for 6-check integrity audit after standard report (#2231)
Extends /gsd-progress with opt-in --forensic mode that appends a
6-check integrity audit after the standard routing report. Default
behavior is byte-for-byte unchanged — the audit only runs when
--forensic is explicitly passed.

Checks: (1) STATE vs artifact consistency, (2) orphaned handoff files,
(3) deferred scope drift, (4) memory-flagged pending work, (5) blocking
operational todos, (6) uncommitted source code. Emits CLEAN or
N INTEGRITY ISSUE(S) FOUND verdict with concrete next actions.

Closes #2189

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 16:23:18 -04:00
Tom Boucher
509a431438 feat(discuss-phase): add --all flag to skip area selection and discuss everything (#2230)
Adds --all to /gsd-discuss-phase so users can skip the AskUserQuestion
area-selection step and jump straight into discussing all gray areas
interactively. Unlike --auto, --all does NOT auto-advance to plan-phase —
it only eliminates the selection friction while keeping full interactive
control over each discussion.

Closes #2188

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 16:23:09 -04:00
Tom Boucher
a13c4cee3e fix(quick): normalize --discuss --research --validate combo to FULL_MODE (#2274)
After #1518 redefined --full as all three granular flags combined, passing
--discuss --research --validate individually bypassed $FULL_MODE and showed
a "DISCUSS + RESEARCH + VALIDATE" banner instead of "FULL".

Fix: add a normalization step in flag parsing — if all three granular flags
are set, promote to $FULL_MODE=true. Remove the now-unreachable banner case.

Closes #2181

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:00:47 -04:00
Tom Boucher
6ef3255f78 fix: normalize Windows paths in update scope detection (#2278)
* docs: sync ARCHITECTURE.md command count to 74

commands/gsd/ has 74 .md files; the two count references in
ARCHITECTURE.md still said 73. Fixes the command-count-sync
regression test.

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

* fix: normalize Windows paths in update scope detection (#2232)

On Windows with Git Bash, `pwd` returns POSIX-style /c/Users/... paths
while execution_context carries Windows-style C:/Users/... paths. The
string equality check for LOCAL vs GLOBAL install scope never matched,
so every local install on Windows was misdetected as GLOBAL and the
wrong (global) install was updated.

Fix: normalize both paths to POSIX drive-letter form before comparing,
using portable POSIX shell (case+printf+tr, no GNU extensions).

Closes #2232

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

* feat(commands): add gsd:inbox command for GitHub issue/PR triage

inbox.md was created but not committed, causing the command count
to read 73 in git while ARCHITECTURE.md correctly stated 74.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:00:26 -04:00
Tom Boucher
ef5b0c187f docs: sync ARCHITECTURE.md command count to 74 (#2270)
* docs: sync ARCHITECTURE.md command count to 74

commands/gsd/ has 74 .md files; the two count references in
ARCHITECTURE.md still said 73. Fixes the command-count-sync
regression test.

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

* feat(commands): add gsd:inbox command for GitHub issue/PR triage

inbox.md was created but not committed, causing the command count
to read 73 in git while ARCHITECTURE.md correctly stated 74.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:00:08 -04:00
Tom Boucher
262b395879 fix: embed model_overrides in Codex TOML and OpenCode agent files (#2279)
* docs: sync ARCHITECTURE.md command count to 74

commands/gsd/ has 74 .md files; the two count references in
ARCHITECTURE.md still said 73. Fixes the command-count-sync
regression test.

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

* fix: embed model_overrides in Codex TOML and OpenCode agent files (#2256)

Codex and OpenCode use static agent files (TOML / markdown frontmatter)
rather than inline Task(model=...) parameters, so model_overrides set in
~/.gsd/defaults.json was silently ignored — all subagents fell through to
the runtime's default model.

Fix: at install time, read model_overrides from ~/.gsd/defaults.json and
embed the matching model ID into each agent file:
  - Codex: model = "..." field in the agent TOML (generateCodexAgentToml)
  - OpenCode: model: ... field in agent frontmatter (convertClaudeToOpencodeFrontmatter)

Also adds readGsdGlobalModelOverrides() helper and passes the result
through installCodexConfig() and the OpenCode agent install loop.

Closes #2256

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

* feat(commands): add gsd:inbox command for GitHub issue/PR triage

inbox.md was created but not committed, causing the command count
to read 73 in git while ARCHITECTURE.md correctly stated 74.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:56 -04:00
Cocoon-Break
d9a4e5bf40 fix: parse baseInt to integer in renameDecimalPhases call to fix regex mismatch (Closes #2197) (#2198) 2026-04-15 14:59:38 -04:00
Tom Boucher
7b0a8b6237 fix: normalize phase numbers in stats Map to prevent duplicate rows (#2220)
When ROADMAP.md uses unpadded phase numbers (e.g. "Phase 1:") and
the phases/ directory uses zero-padded names (e.g. "01-auth"), the
phasesByNumber Map held two separate entries — one keyed "1" from the
ROADMAP heading scan and one keyed "01" from the directory scan —
doubling phases_total in /gsd-stats output.

Apply normalizePhaseName() to all Map keys in both the ROADMAP heading
scan and the directory scan so the two code paths always produce the
same canonical key and merge into a single entry.

Closes #2195

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:35 -04:00
Tom Boucher
899419ebec fix: pipe review prompts via stdin to prevent shell expansion (#2222)
When prompt files contain shell metacharacters (\$VAR, backticks,
\$(...)), passing them as -p "\$(cat file)" causes the shell to expand
those sequences before the CLI tool ever receives the text. This
silently corrupts prompts built from user-authored PLAN.md content.

Replace all -p "\$(cat /tmp/gsd-review-prompt-{phase}.md)" patterns
with cat file | cli -p - so the prompt bytes are passed verbatim via
stdin. Affected CLIs: gemini, claude, codex, qwen. OpenCode and cursor
already used the pipe-to-stdin pattern.

Closes #2200

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:31 -04:00
Tom Boucher
1005f02db2 fix(sdk): stop duplicating prompt in runPhaseStepSession user message (#2223)
runPhaseStepSession was passing the full prompt string as both the
user-visible prompt: argument and as systemPrompt.append, sending
the same (potentially large) text twice per invocation and doubling
the token cost for every phase step session.

runPlanSession correctly uses a short directive as the user message
and reserves the full content for systemPrompt.append only. Apply
the same pattern to runPhaseStepSession: use a brief
"Execute this phase step: <step>" directive as the user message.

Closes #2194

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:27 -04:00
Tom Boucher
4f5ffccec7 fix: align INTEL_FILES constant with actual agent output filenames (#2225)
The gsd-intel-updater agent writes file-roles.json, api-map.json,
dependency-graph.json, arch-decisions.json, and stack.json. But
INTEL_FILES in intel.cjs declared files.json, apis.json, deps.json,
arch.md, and stack.json. Only stack.json matched. Every query/status/
diff/validate call iterated INTEL_FILES and found nothing, reporting
all intel files as missing even after a successful refresh.

Update INTEL_FILES to use the agent's actual filenames. Remove the
arch.md special-case code paths (mtime-based staleness, text search,
.md skip in validate) since arch-decisions.json is JSON like the rest.
Update all intel tests to use the new canonical filenames.

Closes #2205

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:24 -04:00
Tom Boucher
62261a3166 fix: add --portable-hooks flag for WSL/Docker $HOME-relative settings.json paths (#2226)
Absolute hook paths in settings.json break when ~/.claude is bind-mounted
into a container at a different path, or when running under WSL with a
Windows Node.js that resolves a different home directory.

Add `--portable-hooks` CLI flag and `GSD_PORTABLE_HOOKS=1` env var opt-in.
When set, buildHookCommand() emits `$HOME`-relative paths instead of resolved
absolute paths, making the generated hook commands portable across bind mounts.

Fixes #2190

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:21 -04:00
Tom Boucher
8f1dd94495 fix: extract smart_discuss step to reference to reduce autonomous.md token count (#2227)
autonomous.md reported 11,748 tokens (over the Claude Code Read tool's 10K
limit), causing it to be read in 150-line chunks and generating a warning
on every /gsd-autonomous invocation.

Extract the 280-line smart_discuss step into a new reference file
(get-shit-done/references/autonomous-smart-discuss.md) and replace the
step body with a lean stub that directs the agent to read the reference.
This follows the established planner decomposition pattern.

autonomous.md: 38,750 → 29,411 chars (~7,350 tokens, well under 10K limit)

Fixes #2196

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:18 -04:00
Tom Boucher
875b257c18 fix(init): embed auto_advance/auto_chain_active/mode in init plan-phase output (#2228)
Prevents infinite config-get loops on Kimi K2.5 and other models that
re-execute bash tool calls when they encounter config-get subshell patterns.
Values are now bundled into the init plan-phase JSON so step 15 of
plan-phase.md can read them directly without separate shell calls.

Closes #2192

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:15 -04:00
Tom Boucher
7b85d9e689 fix(cli): audit-open crashes with ReferenceError: output is not defined (#2236) (#2238)
The audit-open case in gsd-tools.cjs called bare output() on both the --json
and text paths. output is never in scope at the call site — the entire core
module is imported as `const core`, so every other command uses core.output().

Two-part fix:
- Replace output(...) with core.output(...) on both branches
- Pass result (the raw object) on the --json path, not JSON.stringify(result)
  — core.output always calls JSON.stringify internally, so pre-serialising
  caused double-encoding and agents received a string instead of an object

Adds three CLI-level regression tests to milestone-audit.test.cjs that invoke
audit-open through runGsdTools (the same path the agent uses), so a recurrence
at the dispatch layer is caught even if lib-level tests continue to pass.

Closes #2236

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:12 -04:00
Tom Boucher
fa02cd2279 docs(references): use \$GSD_TOOLS variable in workstream-flag.md CLI examples (#2245) (#2255)
Replace bare `node gsd-tools.cjs` invocations with `node "\$GSD_TOOLS"` throughout
the CLI Usage section, and add a comment explaining that \$GSD_TOOLS resolves to the
full installed bin path (global or local). Bare relative paths only work from the
install directory and silently fail when run from a project root.

Closes #2245

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:59:09 -04:00
Tom Boucher
2f28c99db4 fix(init): include shipped-milestone phases in deps_satisfied check (#2269)
- Build completedNums from current milestone phases as before
- Also scan full rawContent for [x]-checked Phase lines across all
  milestone sections (including <details>-wrapped shipped milestones)
- Phases from prior milestones are complete by definition, so any
  dep on them should always resolve to deps_satisfied: true
- Add regression tests in tests/init-manager-deps.test.cjs

Closes #2267
2026-04-15 14:59:07 -04:00
Tom Boucher
e1fe12322c fix(worktree): add pre-merge deletion guard to quick.md; fix backup handling on conflict (#2275)
Three gaps in the orchestrator file-protection block (#1756, #2040):

1. quick.md never received the pre-merge deletion guard added to
   execute-phase.md in #2040. Added the same DELETIONS check: if the
   worktree branch deletes any tracked .planning/ files, block the merge
   with a clear message rather than silently losing those files.

2. Both workflows deleted STATE_BACKUP and ROADMAP_BACKUP on merge
   conflict — destroying the recovery files at exactly the moment they
   were needed. Changed conflict handler to: preserve both backup paths,
   print restore instructions, and break (halt) instead of continue
   (silently advancing to the next worktree).

3. Neither workflow used --no-ff. Without it a fast-forward merge
   produces no merge commit, so HEAD~1 in the resurrection check points
   to the worktree's parent rather than main's pre-merge HEAD. Added
   --no-ff to both git merge calls so HEAD~1 is always reliable.

Closes #2208

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:58:43 -04:00
Tom Boucher
32ab8ac77e fix: skip statusLine in repo settings.json on local install (#2248) (#2277)
Local installs write to .claude/settings.json inside the project, which
takes precedence over the user's global ~/.claude/settings.json. Writing
statusLine here silently clobbers any profile-level statusLine the user
configured. Guard the write with !isGlobal && !forceStatusline; pass
--force-statusline to override.

Closes #2248

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 14:58:41 -04:00
Tom Boucher
8b94f0370d test: guard ARCHITECTURE.md component counts against drift (#2260)
* test: guard ARCHITECTURE.md component counts against drift (#2258)

Add tests/architecture-counts.test.cjs — 3 tests that dynamically
verify the "Total commands/workflows/agents" counts in
docs/ARCHITECTURE.md match the actual *.md file counts on disk.
Both sides computed at runtime; zero hardcoded numbers.

Also corrects the stale counts in ARCHITECTURE.md:
- commands: 69 → 74
- workflows: 68 → 71
- agents: 24 → 31

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

* fix(init): remove literal ~/.claude/ from deprecated root identifiers to pass Cline path-leak test

The cline-install.test.cjs scans installed engine files for literal
~/.claude/(get-shit-done|commands|...) strings that should have been
substituted during install. Two deprecated-legacy entries added by #2261
used tilde-notation string literals for their root identifier, which
triggered this scan.

root is only a display/sort key — filesystem scanning always uses the
path property (already dynamic via path.join). Switching root to the
relative form '.claude/get-shit-done/skills' and '.claude/commands/gsd'
satisfies the Cline path-leak guard without changing runtime behaviour.

Update skill-manifest.test.cjs assertion to match the new root format.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:35:29 -04:00
TÂCHES
4a34745950 feat(skills): normalize skill discovery contract across runtimes (#2261) 2026-04-15 07:39:48 -06:00
Tom Boucher
c051e71851 test(docs): add command-count sync test; fix ARCHITECTURE.md drift (#2257) (#2259)
Add tests/command-count-sync.test.cjs which programmatically counts
.md files in commands/gsd/ and compares against the two count
occurrences in docs/ARCHITECTURE.md ("Total commands: N" prose line and
"# N slash commands" directory-tree comment). Counts are extracted from
the doc at runtime — never hardcoded — so future drift is caught
immediately in CI regardless of whether the doc or the filesystem moves.

Fix the current drift: ARCHITECTURE.md said 69 commands; the actual
committed count is 73. Both occurrences updated.

Closes #2257

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 08:58:13 -04:00
161 changed files with 3487 additions and 1317 deletions

View File

@@ -49,7 +49,16 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- **Agent specs standardization** — Standardized `required_reading` patterns across agent specs (#2176)
- **CI upgrades** — GitHub Actions upgraded to Node 22+ runtimes; release pipeline fixes (#2128, #1956)
- **Branch cleanup workflow** — Auto-delete on merge + weekly sweep (#2051)
- **SDK query follow-up** — Expanded mutation commands, PID-liveness lock cleanup, depth-bounded JSON search, and comprehensive unit tests
- **PR #2179 maintainer review (Trek-e)** — Scoped SDK to Phase 2 (#2122): removed `gsd-sdk query` passthrough to `gsd-tools.cjs` and `GSD_TOOLS_PATH` override; argv routing consolidated in `resolveQueryArgv()`. `GSDTools` JSON parsing now reports `@file:` indirection read failures instead of failing opaquely. `execute-plan.md` defers Task Commit Protocol to `agents/gsd-executor.md` (single source of truth). Stale `/gsd:` scan (#1748) skips `.planning/` and root `CLAUDE.md` so local gitignored overlays do not fail CI.
- **SDK query registry (PR #2179 review)** — Register `summary-extract` as an alias of `summary.extract` so workflows/agents match CJS naming. Correct `audit-fix.md` to call `audit-uat` instead of nonexistent `init.audit-uat`.
- **`gsd-tools audit-open`** — Use `core.output()` (was undefined `output()`), and pass the artifact object for `--json` so stdout is JSON (not double-stringified).
- **SDK query layer (PR review hardening)** — `commit-to-subrepo` uses realpath-aware path containment and sanitized commit messages; `state.planned-phase` uses the STATE.md lockfile; `verifyKeyLinks` mitigates ReDoS on frontmatter patterns; frontmatter handlers resolve paths under the real project root; phase directory names reject `..` and separators; `gsd-sdk` restores strict CLI parsing by stripping `--pick` before `parseArgs`; `QueryRegistry.commands()` for enumeration; `todoComplete` uses static error imports.
- **`gsd-sdk query` routing (Phase 2 scope)** — `resolveQueryArgv()` maps argv to registered handlers (longest-prefix match on dotted and spaced command keys; optional single-token dotted split). Unregistered commands are rejected at the CLI; use `node …/gsd-tools.cjs` for CJS-only subcommands. `resolveGsdToolsPath()` probes the SDK-bundled copy, then project and user `~/.claude/get-shit-done/` installs (no `GSD_TOOLS_PATH` override). Broader “CLI parity” passthrough is explicitly out of scope for #2122 and tracked separately for a future approved issue.
- **SDK query follow-up (tests, docs, registry)** — Expanded `QUERY_MUTATION_COMMANDS` for event emission; stale lock cleanup uses PID liveness (`process.kill(pid, 0)`) when a lock file exists; `searchJsonEntries` is depth-bounded (`MAX_JSON_SEARCH_DEPTH`); removed unnecessary `readdirSync`/`Dirent` casts across query handlers; added `sdk/src/query/QUERY-HANDLERS.md` (error vs `{ data.error }`, mutations, locks, intel limits); unit tests for intel, profile, uat, skills, summary, websearch, workstream, registry vs `QUERY_MUTATION_COMMANDS`, and frontmatter extract/splice round-trip.
- **Phase 2 caller migration (#2122)** — Workflows, agents, and commands prefer `gsd-sdk query` for registered handlers; extended migration to additional orchestration call sites (review, plan-phase, execute-plan, ship, extract_learnings, ai-integration-phase, eval-review, next, profile-user, autonomous, thread command) and researcher agents; dual-path and CJS-only exceptions documented in `docs/CLI-TOOLS.md` and `docs/ARCHITECTURE.md`; relaxed `tests/gsd-tools-path-refs.test.cjs` so `commands/gsd/workstreams.md` may document `gsd-sdk query` without `node` + `gsd-tools.cjs`. CJS `gsd-tools.cjs` remains on disk; graphify and other non-registry commands stay on CJS until registered. (#2008)
- **Phase 2 docs and call sites (follow-up)** — `docs/USER-GUIDE.md` now explains `gsd-sdk query` vs legacy CJS and lists CJS-only commands (`state validate`/`sync`, `audit-open`, `graphify`, `from-gsd2`). Updated `commands/gsd` (`debug`, `quick`, `intel`), `agents/gsd-debug-session-manager.md`, and workflows (`milestone-summary`, `forensics`, `next`, `complete-milestone`, `verify-work`, `discuss-phase`, `progress`, `verify-phase`, `add-phase`/`insert-phase`/`remove-phase`, `transition`, `manager`, `quick`) for `gsd-sdk query` or explicit CJS exceptions (`audit-open`).
- **Phase 2 orchestration doc pass (#2122)** — Aligned `commands/gsd` (`execute-phase`, `code-review`, `code-review-fix`, `from-gsd2`, `graphify`) and agents (`gsd-verifier`, `gsd-plan-checker`, `gsd-code-fixer`, `gsd-executor`, `gsd-planner`, researchers, debugger) so examples use `init.*` query names, correct `frontmatter.get` positional field, `state.*` positional args, and `commit` with positional file paths (not `--files`, except `commit-to-subrepo` which keeps `--files`).
- **Phase 2 `commit` example sweep (#2122)** — Normalized `gsd-sdk query commit` usage across `get-shit-done/workflows/**/*.md`, `get-shit-done/references/**/*.md`, and `commands/gsd/**/*.md` so file paths follow the message positionally (SDK `commit` handler); `gsd-sdk query commit-to-subrepo … --files …` unchanged. Updated `get-shit-done/references/git-planning-commit.md` prose; adjusted workflow contract tests (`claude-md`, forensics, milestone-summary, gates taxonomy CRLF-safe `required_reading`, verifier `roadmap.analyze`) for the new examples.
### Fixed
- **Init ignores archived phases** — Archived phases from prior milestones sharing a phase number no longer interfere (#2186)

View File

@@ -117,7 +117,9 @@ Verify with:
- Cline: GSD installs via `.clinerules` — verify by checking `.clinerules` exists
> [!NOTE]
> Claude Code 2.1.88+, Qwen Code, and Codex install as skills (`skills/gsd-*/SKILL.md`). Older Claude Code versions use `commands/gsd/`. Cline uses `.clinerules` for configuration. The installer handles all formats automatically.
> Claude Code 2.1.88+, Qwen Code, and Codex install as skills (`.claude/skills/`, `./.codex/skills/`, or the matching global `~/.claude/skills/` / `~/.codex/skills/` roots). Older Claude Code versions use `commands/gsd/`. `~/.claude/get-shit-done/skills/` is import-only for legacy migration. The installer handles all formats automatically.
The canonical discovery contract is documented in [docs/skills/discovery-contract.md](docs/skills/discovery-contract.md).
> [!TIP]
> For source-based installs or environments where npm is unavailable, see **[docs/manual-update.md](docs/manual-update.md)**.
@@ -818,8 +820,9 @@ This prevents Claude from reading these files entirely, regardless of what comma
**Commands not found after install?**
- Restart your runtime to reload commands/skills
- Verify files exist in `~/.claude/skills/gsd-*/SKILL.md` (Claude Code 2.1.88+) or `~/.claude/commands/gsd/` (legacy)
- For Codex, verify skills exist in `~/.codex/skills/gsd-*/SKILL.md` (global) or `./.codex/skills/gsd-*/SKILL.md` (local)
- Verify files exist in `~/.claude/skills/gsd-*/SKILL.md` or `~/.codex/skills/gsd-*/SKILL.md` for managed global installs
- For local installs, verify `.claude/skills/gsd-*/SKILL.md` or `./.codex/skills/gsd-*/SKILL.md`
- Legacy Claude Code installs still use `~/.claude/commands/gsd/`
**Commands not working as expected?**
- Run `/gsd-help` to verify installation

View File

@@ -194,7 +194,7 @@ The **Fix:** section may contain:
If a finding references multiple files (in Fix section or Issue section):
- Collect ALL file paths into `files` array
- Apply fix to each file
- Commit all modified files atomically (single commit, multiple files in `--files` list)
- Commit all modified files atomically (single commit, list every file path after the message — `commit` uses positional paths, not `--files`)
**Parsing Rules:**
@@ -308,20 +308,21 @@ For each finding in sorted order:
**If verification passed:**
Use gsd-tools commit command with conventional format:
Use `gsd-sdk query commit` with conventional format (message first, then every staged file path):
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit \
gsd-sdk query commit \
"fix({padded_phase}): {finding_id} {short_description}" \
--files {all_modified_files}
{all_modified_files}
```
Examples:
- `fix(02): CR-01 fix SQL injection in auth.py`
- `fix(03): WR-05 add null check before array access`
**Multiple files:** List ALL modified files in `--files` (space-separated):
**Multiple files:** List ALL modified files after the message (space-separated):
```bash
--files src/api/auth.ts src/types/user.ts tests/auth.test.ts
gsd-sdk query commit "fix(02): CR-01 ..." \
src/api/auth.ts src/types/user.ts tests/auth.test.ts
```
**Extract commit hash:**
@@ -442,7 +443,7 @@ _Iteration: {N}_
**DO record which files will be touched** before every fix attempt — this is your rollback list. Rollback is `git checkout -- {file}`, not content capture.
**DO commit each fix atomically** — one commit per finding, listing ALL modified files in `--files` argument.
**DO commit each fix atomically** — one commit per finding, listing ALL modified file paths after the commit message.
**DO use Edit tool (preferred)** over Write tool for targeted changes. Edit provides better diff visibility.
@@ -504,7 +505,7 @@ Fixes are committed **per-finding**. This has operational implications:
- [ ] All in-scope findings attempted (either fixed or skipped with reason)
- [ ] Each fix committed atomically with `fix({padded_phase}): {id} {description}` format
- [ ] All modified files listed in each commit's `--files` argument (multi-file fix support)
- [ ] All modified files listed after each commit message (multi-file fix support)
- [ ] REVIEW-FIX.md created with accurate counts, status, and iteration number
- [ ] No source files left in broken state (failed fixes rolled back via git checkout)
- [ ] No partial or uncommitted changes remain after execution

View File

@@ -93,7 +93,7 @@ Task(
Resolve the debugger model before spawning:
```bash
debugger_model=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-debugger --raw)
debugger_model=$(gsd-sdk query resolve-model gsd-debugger 2>/dev/null | jq -r '.model' 2>/dev/null || true)
```
## Step 3: Handle Agent Return

View File

@@ -1227,7 +1227,7 @@ mv .planning/debug/{slug}.md .planning/debug/resolved/
**Check planning config using state load (commit_docs is available from the output):**
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
INIT=$(gsd-sdk query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# commit_docs is in the JSON output
```
@@ -1245,7 +1245,7 @@ Root cause: {root_cause}"
Then commit planning docs via CLI (respects `commit_docs` config automatically):
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: resolve debug {slug}" --files .planning/debug/resolved/{slug}.md
gsd-sdk query commit "docs: resolve debug {slug}" .planning/debug/resolved/{slug}.md
```
**Append to knowledge base:**
@@ -1276,7 +1276,7 @@ Then append the entry:
Commit the knowledge base update alongside the resolved session:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: update debug knowledge base with {slug}" --files .planning/debug/knowledge-base.md
gsd-sdk query commit "docs: update debug knowledge base with {slug}" .planning/debug/knowledge-base.md
```
Report completion and offer next steps.

View File

@@ -72,7 +72,7 @@ This ensures project-specific patterns, conventions, and best practices are appl
Load execution context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "${PHASE}")
INIT=$(gsd-sdk query init.execute-phase "${PHASE}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -248,8 +248,8 @@ Do NOT continue reading. Analysis without action is a stuck signal.
Check if auto mode is active at executor start (chain flag or user preference):
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
```
Auto mode is active if either `AUTO_CHAIN` or `AUTO_CFG` is `"true"`. Store the result for checkpoint handling below.
@@ -388,7 +388,7 @@ git add src/types/user.ts
**If `sub_repos` is configured (non-empty array from init context):** Use `commit-to-subrepo` to route files to their correct sub-repo:
```bash
node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit-to-subrepo "{type}({phase}-{plan}): {concise task description}" --files file1 file2 ...
gsd-sdk query commit-to-subrepo "{type}({phase}-{plan}): {concise task description}" --files file1 file2 ...
```
Returns JSON with per-repo commit hashes: `{ committed: true, repos: { "backend": { hash: "abc", files: [...] }, ... } }`. Record all hashes for SUMMARY.
@@ -515,38 +515,36 @@ Do NOT skip. Do NOT proceed to state updates if self-check fails.
</self_check>
<state_updates>
After SUMMARY.md, update STATE.md using gsd-tools:
After SUMMARY.md, update STATE.md using `gsd-sdk query` state handlers (positional args; see `sdk/src/query/QUERY-HANDLERS.md`):
```bash
# Advance plan counter (handles edge cases automatically)
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state advance-plan
gsd-sdk query state.advance-plan
# Recalculate progress bar from disk state
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state update-progress
gsd-sdk query state.update-progress
# Record execution metrics
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-metric \
--phase "${PHASE}" --plan "${PLAN}" --duration "${DURATION}" \
--tasks "${TASK_COUNT}" --files "${FILE_COUNT}"
# Record execution metrics (phase, plan, duration, tasks, files)
gsd-sdk query state.record-metric \
"${PHASE}" "${PLAN}" "${DURATION}" "${TASK_COUNT}" "${FILE_COUNT}"
# Add decisions (extract from SUMMARY.md key-decisions)
for decision in "${DECISIONS[@]}"; do
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state add-decision \
--phase "${PHASE}" --summary "${decision}"
gsd-sdk query state.add-decision "${decision}"
done
# Update session info
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
--stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md"
# Update session info (timestamp, stopped-at, resume-file)
gsd-sdk query state.record-session \
"" "Completed ${PHASE}-${PLAN}-PLAN.md" "None"
```
```bash
# Update ROADMAP.md progress for this phase (plan counts, status)
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap update-plan-progress "${PHASE_NUMBER}"
gsd-sdk query roadmap.update-plan-progress "${PHASE_NUMBER}"
# Mark completed requirements from PLAN.md frontmatter
# Extract the `requirements` array from the plan's frontmatter, then mark each complete
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" requirements mark-complete ${REQ_IDS}
gsd-sdk query requirements.mark-complete ${REQ_IDS}
```
**Requirement IDs:** Extract from the PLAN.md frontmatter `requirements:` field (e.g., `requirements: [AUTH-01, AUTH-02]`). Pass all IDs to `requirements mark-complete`. If the plan has no requirements field, skip this step.
@@ -564,13 +562,14 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" requirements mark-complete
**For blockers found during execution:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state add-blocker "Blocker description"
gsd-sdk query state.add-blocker "Blocker description"
```
</state_updates>
<final_commit>
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
gsd-sdk query commit "docs({phase}-{plan}): complete [plan-name] plan" \
.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
```
Separate from per-task commits — captures execution results only.

View File

@@ -37,7 +37,7 @@ Write machine-parseable, evidence-based intelligence. Every claim references act
- **Always include file paths.** Every claim must reference the actual code location.
- **Write current state only.** No temporal language ("recently added", "will be changed").
- **Evidence-based.** Read the actual files. Do not guess from file names or directory structures.
- **Cross-platform.** Use Glob, Read, and Grep tools -- not Bash `ls`, `find`, or `cat`. Bash file commands fail on Windows. Only use Bash for `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel` CLI calls.
- **Cross-platform.** Use Glob, Read, and Grep tools -- not Bash `ls`, `find`, or `cat`. Bash file commands fail on Windows. Only use Bash for `gsd-sdk query intel` CLI calls.
- **ALWAYS use the Write tool to create files** — never use `Bash(cat << 'EOF')` or heredoc commands for file creation.
</role>
@@ -106,7 +106,7 @@ All JSON files include a `_meta` object with `updated_at` (ISO timestamp) and `v
}
```
**exports constraint:** Array of ACTUAL exported symbol names extracted from `module.exports` or `export` statements. MUST be real identifiers (e.g., `"configLoad"`, `"stateUpdate"`), NOT descriptions (e.g., `"config operations"`). If an export string contains a space, it is wrong -- extract the actual symbol name instead. Use `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel extract-exports <file>` to get accurate exports.
**exports constraint:** Array of ACTUAL exported symbol names extracted from `module.exports` or `export` statements. MUST be real identifiers (e.g., `"configLoad"`, `"stateUpdate"`), NOT descriptions (e.g., `"config operations"`). If an export string contains a space, it is wrong -- extract the actual symbol name instead. Use `gsd-sdk query intel.extract-exports <file>` to get accurate exports.
Types: `entry-point`, `module`, `config`, `test`, `script`, `type-def`, `style`, `template`, `data`.
@@ -202,7 +202,7 @@ Glob for project structure indicators:
Read package.json, configs, and build files. Write `stack.json`. Then patch its timestamp:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel patch-meta .planning/intel/stack.json --cwd <project_root>
gsd-sdk query intel.patch-meta .planning/intel/stack.json --cwd <project_root>
```
### Step 3: File Graph
@@ -211,7 +211,7 @@ Glob source files (`**/*.ts`, `**/*.js`, `**/*.py`, etc., excluding node_modules
Read key files (entry points, configs, core modules) for imports/exports.
Write `files.json`. Then patch its timestamp:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel patch-meta .planning/intel/files.json --cwd <project_root>
gsd-sdk query intel.patch-meta .planning/intel/files.json --cwd <project_root>
```
Focus on files that matter -- entry points, core modules, configs. Skip test files and generated code unless they reveal architecture.
@@ -222,7 +222,7 @@ Grep for route definitions, endpoint declarations, CLI command registrations.
Patterns to search: `app.get(`, `router.post(`, `@GetMapping`, `def route`, express route patterns.
Write `apis.json`. If no API endpoints found, write an empty entries object. Then patch its timestamp:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel patch-meta .planning/intel/apis.json --cwd <project_root>
gsd-sdk query intel.patch-meta .planning/intel/apis.json --cwd <project_root>
```
### Step 5: Dependencies
@@ -231,7 +231,7 @@ Read package.json (dependencies, devDependencies), requirements.txt, go.mod, Car
Cross-reference with actual imports to populate `used_by`.
Write `deps.json`. Then patch its timestamp:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel patch-meta .planning/intel/deps.json --cwd <project_root>
gsd-sdk query intel.patch-meta .planning/intel/deps.json --cwd <project_root>
```
### Step 6: Architecture
@@ -241,7 +241,7 @@ Write `arch.md`.
### Step 6.5: Self-Check
Run: `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel validate --cwd <project_root>`
Run: `gsd-sdk query intel.validate --cwd <project_root>`
Review the output:
@@ -253,7 +253,7 @@ This step is MANDATORY -- do not skip it.
### Step 7: Snapshot
Run: `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel snapshot --cwd <project_root>`
Run: `gsd-sdk query intel.snapshot --cwd <project_root>`
This writes `.last-refresh.json` with accurate timestamps and hashes. Do NOT write `.last-refresh.json` manually.
</execution_flow>

View File

@@ -158,7 +158,7 @@ When researching "best library for X": find what the ecosystem actually uses, do
Check `brave_search` from init context. If `true`, use Brave Search for higher quality results:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" websearch "your query" --limit 10
gsd-sdk query websearch "your query" --limit 10
```
**Options:**
@@ -514,7 +514,7 @@ Orchestrator provides: phase number/name, description/goal, requirements, constr
Load phase context using init command:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE}")
INIT=$(gsd-sdk query init.phase-op "${PHASE}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -761,7 +761,7 @@ Write to: `$PHASE_DIR/$PADDED_PHASE-RESEARCH.md`
## Step 7: Commit Research (optional)
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs($PHASE): research phase domain" --files "$PHASE_DIR/$PADDED_PHASE-RESEARCH.md"
gsd-sdk query commit "docs($PHASE): research phase domain" "$PHASE_DIR/$PADDED_PHASE-RESEARCH.md"
```
## Step 8: Return Structured Result

View File

@@ -630,7 +630,7 @@ issue:
Load phase operation context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
INIT=$(gsd-sdk query init.phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -642,7 +642,7 @@ Orchestrator provides CONTEXT.md content in the verification prompt. If provided
ls "$phase_dir"/*-PLAN.md 2>/dev/null
# Read research for Nyquist validation data
cat "$phase_dir"/*-RESEARCH.md 2>/dev/null
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$phase_number"
gsd-sdk query roadmap.get-phase "$phase_number"
ls "$phase_dir"/*-BRIEF.md 2>/dev/null
```
@@ -650,12 +650,12 @@ ls "$phase_dir"/*-BRIEF.md 2>/dev/null
## Step 2: Load All Plans
Use gsd-tools to validate plan structure:
Use `gsd-sdk query` to validate plan structure:
```bash
for plan in "$PHASE_DIR"/*-PLAN.md; do
echo "=== $plan ==="
PLAN_STRUCTURE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify plan-structure "$plan")
PLAN_STRUCTURE=$(gsd-sdk query verify.plan-structure "$plan")
echo "$PLAN_STRUCTURE"
done
```
@@ -670,10 +670,10 @@ Map errors/warnings to verification dimensions:
## Step 3: Parse must_haves
Extract must_haves from each plan using gsd-tools:
Extract must_haves from each plan using `gsd-sdk query`:
```bash
MUST_HAVES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter get "$PLAN_PATH" --field must_haves)
MUST_HAVES=$(gsd-sdk query frontmatter.get "$PLAN_PATH" must_haves)
```
Returns JSON: `{ truths: [...], artifacts: [...], key_links: [...] }`
@@ -715,10 +715,10 @@ For each requirement: find covering task(s), verify action is specific, flag gap
## Step 5: Validate Task Structure
Use gsd-tools plan-structure verification (already run in Step 2):
Use `verify.plan-structure` (already run in Step 2):
```bash
PLAN_STRUCTURE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify plan-structure "$PLAN_PATH")
PLAN_STRUCTURE=$(gsd-sdk query verify.plan-structure "$PLAN_PATH")
```
The `tasks` array in the result shows each task's completeness:
@@ -729,7 +729,7 @@ The `tasks` array in the result shows each task's completeness:
**Check:** valid task type (auto, checkpoint:*, tdd), auto tasks have files/action/verify/done, action is specific, verify is runnable, done is measurable.
**For manual validation of specificity** (gsd-tools checks structure, not content quality):
**For manual validation of specificity** (`verify.plan-structure` checks structure, not content quality):
```bash
grep -B5 "</task>" "$PHASE_DIR"/*-PLAN.md | grep -v "<verify>"
```

View File

@@ -828,7 +828,7 @@ start of execution when `--reviews` flag is present or reviews mode is active.
Load planning context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init plan-phase "${PHASE}")
INIT=$(gsd-sdk query init.plan-phase "${PHASE}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -896,6 +896,8 @@ Query the graph for phase-relevant dependency context (single query per D-06):
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" graphify query "<phase-goal-keyword>" --budget 2000
```
(graphify is not exposed on `gsd-sdk query` yet; use `gsd-tools.cjs` for graphify only.)
Use the keyword that best captures the phase goal. Examples:
- Phase "User Authentication" -> query term "auth"
- Phase "Payment Integration" -> query term "payment"
@@ -931,7 +933,7 @@ Apply discovery level protocol (see discovery_levels section).
**Step 1 — Generate digest index:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" history-digest
gsd-sdk query history-digest
```
**Step 2 — Select relevant phases (typically 2-4):**
@@ -976,7 +978,7 @@ Read the most recent milestone retrospective and cross-milestone trends. Extract
</step>
<step name="inject_global_learnings">
If `features.global_learnings` is `true`: run `gsd-tools learnings query --tag <phase_tags> --limit 5`, prefix matches with `[Prior learning from <project>]` as weak priors. Project-local decisions take precedence. Skip silently if disabled or no matches. For tags, use PLAN.md frontmatter `tags` field or keywords from the phase objective, comma-separated (e.g. `--tag auth,database,api`).
If `features.global_learnings` is `true`: run `gsd-sdk query learnings.query --tag <tag> --limit 5` once per tag from PLAN.md frontmatter `tags` (or use the single most specific keyword). The handler matches one `--tag` at a time. Prefix matches with `[Prior learning from <project>]` as weak priors. Project-local decisions take precedence. Skip silently if disabled or no matches.
</step>
<step name="gather_phase_context">
@@ -1090,7 +1092,7 @@ The filename MUST follow the exact pattern: `{padded_phase}-{NN}-PLAN.md`
- Phase 3, Plan 2 → `03-02-PLAN.md`
- Phase 2.1, Plan 1 → `02.1-01-PLAN.md`
**Incorrect (will break gsd-tools detection):**
**Incorrect (will break GSD plan filename conventions / tooling detection):**
-`PLAN-01-auth.md`
-`01-PLAN-01.md`
-`plan-01.md`
@@ -1102,10 +1104,10 @@ Include all frontmatter fields.
</step>
<step name="validate_plan">
Validate each created PLAN.md using gsd-tools:
Validate each created PLAN.md using `gsd-sdk query`:
```bash
VALID=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter validate "$PLAN_PATH" --schema plan)
VALID=$(gsd-sdk query frontmatter.validate "$PLAN_PATH" --schema plan)
```
Returns JSON: `{ valid, missing, present, schema }`
@@ -1118,7 +1120,7 @@ Required plan frontmatter fields:
Also validate plan structure:
```bash
STRUCTURE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify plan-structure "$PLAN_PATH")
STRUCTURE=$(gsd-sdk query verify.plan-structure "$PLAN_PATH")
```
Returns JSON: `{ valid, errors, warnings, task_count, tasks }`
@@ -1155,7 +1157,8 @@ Plans:
<step name="git_commit">
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs($PHASE): create phase plan" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md .planning/ROADMAP.md
gsd-sdk query commit "docs($PHASE): create phase plan" \
.planning/phases/$PHASE-*/$PHASE-*-PLAN.md .planning/ROADMAP.md
```
</step>

View File

@@ -128,7 +128,7 @@ Always include current year. Use multiple query variations. Mark WebSearch-only
Check `brave_search` from orchestrator context. If `true`, use Brave Search for higher quality results:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" websearch "your query" --limit 10
gsd-sdk query websearch "your query" --limit 10
```
**Options:**

View File

@@ -58,7 +58,7 @@ cat .planning/research/FEATURES.md
cat .planning/research/ARCHITECTURE.md
cat .planning/research/PITFALLS.md
# Planning config loaded via gsd-tools.cjs in commit step
# Planning config loaded via gsd-sdk query (or gsd-tools.cjs) in commit step
```
Parse each file to extract:
@@ -139,7 +139,7 @@ Write to `.planning/research/SUMMARY.md`
The 4 parallel researcher agents write files but do NOT commit. You commit everything together.
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: complete project research" --files .planning/research/
gsd-sdk query commit "docs: complete project research" .planning/research/
```
## Step 8: Return Summary

View File

@@ -292,7 +292,7 @@ Fill all sections. Write to `$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md`.
## Step 6: Commit (optional)
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs($PHASE): UI design contract" --files "$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md"
gsd-sdk query commit "docs($PHASE): UI design contract" "$PHASE_DIR/$PADDED_PHASE-UI-SPEC.md"
```
## Step 7: Return Structured Result

View File

@@ -91,7 +91,7 @@ Set `is_re_verification = false`, proceed with Step 1.
```bash
ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null
ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$PHASE_NUM"
gsd-sdk query roadmap.get-phase "$PHASE_NUM"
grep -E "^| $PHASE_NUM" .planning/REQUIREMENTS.md 2>/dev/null
```
@@ -104,7 +104,7 @@ In re-verification mode, must-haves come from Step 0.
**Step 2a: Always load ROADMAP Success Criteria**
```bash
PHASE_DATA=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$PHASE_NUM" --raw)
PHASE_DATA=$(gsd-sdk query roadmap.get-phase "$PHASE_NUM" --raw)
```
Parse the `success_criteria` array from the JSON output. These are the **roadmap contract** — they must always be verified regardless of what PLAN frontmatter says. Store them as `roadmap_truths`.
@@ -206,10 +206,10 @@ overrides:
## Step 4: Verify Artifacts (Three Levels)
Use gsd-tools for artifact verification against must_haves in PLAN frontmatter:
Use `gsd-sdk query` for artifact verification against must_haves in PLAN frontmatter:
```bash
ARTIFACT_RESULT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify artifacts "$PLAN_PATH")
ARTIFACT_RESULT=$(gsd-sdk query verify.artifacts "$PLAN_PATH")
```
Parse JSON result: `{ all_passed, passed, total, artifacts: [{path, exists, issues, passed}] }`
@@ -312,10 +312,10 @@ grep -r -A 3 "<${COMPONENT_NAME}" "${search_path:-src/}" --include="*.tsx" 2>/de
Key links are critical connections. If broken, the goal fails even with all artifacts present.
Use gsd-tools for key link verification against must_haves in PLAN frontmatter:
Use `gsd-sdk query` for key link verification against must_haves in PLAN frontmatter:
```bash
LINKS_RESULT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify key-links "$PLAN_PATH")
LINKS_RESULT=$(gsd-sdk query verify.key-links "$PLAN_PATH")
```
Parse JSON result: `{ all_verified, verified, total, links: [{from, to, via, verified, detail}] }`
@@ -397,12 +397,12 @@ Identify files modified in this phase from SUMMARY.md key-files section, or extr
```bash
# Option 1: Extract from SUMMARY frontmatter
SUMMARY_FILES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
SUMMARY_FILES=$(gsd-sdk query summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
# Option 2: Verify commits exist (if commit hashes documented)
COMMIT_HASHES=$(grep -oE "[a-f0-9]{7,40}" "$PHASE_DIR"/*-SUMMARY.md | head -10)
if [ -n "$COMMIT_HASHES" ]; then
COMMITS_VALID=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify commits $COMMIT_HASHES)
COMMITS_VALID=$(gsd-sdk query verify.commits $COMMIT_HASHES)
fi
# Fallback: grep for files
@@ -516,7 +516,7 @@ Before reporting gaps, check if any identified gaps are explicitly addressed in
**Load the full milestone roadmap:**
```bash
ROADMAP_DATA=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze --raw)
ROADMAP_DATA=$(gsd-sdk query roadmap.analyze --raw)
```
Parse the JSON to extract all phases. Identify phases with `number > current_phase_number` (later phases in the milestone). For each later phase, extract its `goal` and `success_criteria`.

View File

@@ -76,6 +76,7 @@ const hasCline = args.includes('--cline');
const hasBoth = args.includes('--both'); // Legacy flag, keeps working
const hasAll = args.includes('--all');
const hasUninstall = args.includes('--uninstall') || args.includes('-u');
const hasPortableHooks = args.includes('--portable-hooks') || process.env.GSD_PORTABLE_HOOKS === '1';
// Runtime selection - can be set by flags or interactive prompt
let selectedRuntimes = [];
@@ -436,7 +437,7 @@ if (hasUninstall) {
// Show help if requested
if (hasHelp) {
console.log(` ${yellow}Usage:${reset} npx get-shit-done-cc [options]\n\n ${yellow}Options:${reset}\n ${cyan}-g, --global${reset} Install globally (to config directory)\n ${cyan}-l, --local${reset} Install locally (to current directory)\n ${cyan}--claude${reset} Install for Claude Code only\n ${cyan}--opencode${reset} Install for OpenCode only\n ${cyan}--gemini${reset} Install for Gemini only\n ${cyan}--kilo${reset} Install for Kilo only\n ${cyan}--codex${reset} Install for Codex only\n ${cyan}--copilot${reset} Install for Copilot only\n ${cyan}--antigravity${reset} Install for Antigravity only\n ${cyan}--cursor${reset} Install for Cursor only\n ${cyan}--windsurf${reset} Install for Windsurf only\n ${cyan}--augment${reset} Install for Augment only\n ${cyan}--trae${reset} Install for Trae only\n ${cyan}--qwen${reset} Install for Qwen Code only\n ${cyan}--cline${reset} Install for Cline only\n ${cyan}--codebuddy${reset} Install for CodeBuddy only\n ${cyan}--all${reset} Install for all runtimes\n ${cyan}-u, --uninstall${reset} Uninstall GSD (remove all GSD files)\n ${cyan}-c, --config-dir <path>${reset} Specify custom config directory\n ${cyan}-h, --help${reset} Show this help message\n ${cyan}--force-statusline${reset} Replace existing statusline config\n\n ${yellow}Examples:${reset}\n ${dim}# Interactive install (prompts for runtime and location)${reset}\n npx get-shit-done-cc\n\n ${dim}# Install for Claude Code globally${reset}\n npx get-shit-done-cc --claude --global\n\n ${dim}# Install for Gemini globally${reset}\n npx get-shit-done-cc --gemini --global\n\n ${dim}# Install for Kilo globally${reset}\n npx get-shit-done-cc --kilo --global\n\n ${dim}# Install for Codex globally${reset}\n npx get-shit-done-cc --codex --global\n\n ${dim}# Install for Copilot globally${reset}\n npx get-shit-done-cc --copilot --global\n\n ${dim}# Install for Copilot locally${reset}\n npx get-shit-done-cc --copilot --local\n\n ${dim}# Install for Antigravity globally${reset}\n npx get-shit-done-cc --antigravity --global\n\n ${dim}# Install for Antigravity locally${reset}\n npx get-shit-done-cc --antigravity --local\n\n ${dim}# Install for Cursor globally${reset}\n npx get-shit-done-cc --cursor --global\n\n ${dim}# Install for Cursor locally${reset}\n npx get-shit-done-cc --cursor --local\n\n ${dim}# Install for Windsurf globally${reset}\n npx get-shit-done-cc --windsurf --global\n\n ${dim}# Install for Windsurf locally${reset}\n npx get-shit-done-cc --windsurf --local\n\n ${dim}# Install for Augment globally${reset}\n npx get-shit-done-cc --augment --global\n\n ${dim}# Install for Augment locally${reset}\n npx get-shit-done-cc --augment --local\n\n ${dim}# Install for Trae globally${reset}\n npx get-shit-done-cc --trae --global\n\n ${dim}# Install for Trae locally${reset}\n npx get-shit-done-cc --trae --local\n\n ${dim}# Install for Cline locally${reset}\n npx get-shit-done-cc --cline --local\n\n ${dim}# Install for CodeBuddy globally${reset}\n npx get-shit-done-cc --codebuddy --global\n\n ${dim}# Install for CodeBuddy locally${reset}\n npx get-shit-done-cc --codebuddy --local\n\n ${dim}# Install for all runtimes globally${reset}\n npx get-shit-done-cc --all --global\n\n ${dim}# Install to custom config directory${reset}\n npx get-shit-done-cc --kilo --global --config-dir ~/.kilo-work\n\n ${dim}# Install to current project only${reset}\n npx get-shit-done-cc --claude --local\n\n ${dim}# Uninstall GSD from Cursor globally${reset}\n npx get-shit-done-cc --cursor --global --uninstall\n\n ${yellow}Notes:${reset}\n The --config-dir option is useful when you have multiple configurations.\n It takes priority over CLAUDE_CONFIG_DIR / OPENCODE_CONFIG_DIR / GEMINI_CONFIG_DIR / KILO_CONFIG_DIR / CODEX_HOME / COPILOT_CONFIG_DIR / ANTIGRAVITY_CONFIG_DIR / CURSOR_CONFIG_DIR / WINDSURF_CONFIG_DIR / AUGMENT_CONFIG_DIR / TRAE_CONFIG_DIR / QWEN_CONFIG_DIR / CLINE_CONFIG_DIR / CODEBUDDY_CONFIG_DIR environment variables.\n`);
console.log(` ${yellow}Usage:${reset} npx get-shit-done-cc [options]\n\n ${yellow}Options:${reset}\n ${cyan}-g, --global${reset} Install globally (to config directory)\n ${cyan}-l, --local${reset} Install locally (to current directory)\n ${cyan}--claude${reset} Install for Claude Code only\n ${cyan}--opencode${reset} Install for OpenCode only\n ${cyan}--gemini${reset} Install for Gemini only\n ${cyan}--kilo${reset} Install for Kilo only\n ${cyan}--codex${reset} Install for Codex only\n ${cyan}--copilot${reset} Install for Copilot only\n ${cyan}--antigravity${reset} Install for Antigravity only\n ${cyan}--cursor${reset} Install for Cursor only\n ${cyan}--windsurf${reset} Install for Windsurf only\n ${cyan}--augment${reset} Install for Augment only\n ${cyan}--trae${reset} Install for Trae only\n ${cyan}--qwen${reset} Install for Qwen Code only\n ${cyan}--cline${reset} Install for Cline only\n ${cyan}--codebuddy${reset} Install for CodeBuddy only\n ${cyan}--all${reset} Install for all runtimes\n ${cyan}-u, --uninstall${reset} Uninstall GSD (remove all GSD files)\n ${cyan}-c, --config-dir <path>${reset} Specify custom config directory\n ${cyan}-h, --help${reset} Show this help message\n ${cyan}--force-statusline${reset} Replace existing statusline config\n ${cyan}--portable-hooks${reset} Emit \$HOME-relative hook paths in settings.json\n (for WSL/Docker bind-mount setups; also GSD_PORTABLE_HOOKS=1)\n\n ${yellow}Examples:${reset}\n ${dim}# Interactive install (prompts for runtime and location)${reset}\n npx get-shit-done-cc\n\n ${dim}# Install for Claude Code globally${reset}\n npx get-shit-done-cc --claude --global\n\n ${dim}# Install for Gemini globally${reset}\n npx get-shit-done-cc --gemini --global\n\n ${dim}# Install for Kilo globally${reset}\n npx get-shit-done-cc --kilo --global\n\n ${dim}# Install for Codex globally${reset}\n npx get-shit-done-cc --codex --global\n\n ${dim}# Install for Copilot globally${reset}\n npx get-shit-done-cc --copilot --global\n\n ${dim}# Install for Copilot locally${reset}\n npx get-shit-done-cc --copilot --local\n\n ${dim}# Install for Antigravity globally${reset}\n npx get-shit-done-cc --antigravity --global\n\n ${dim}# Install for Antigravity locally${reset}\n npx get-shit-done-cc --antigravity --local\n\n ${dim}# Install for Cursor globally${reset}\n npx get-shit-done-cc --cursor --global\n\n ${dim}# Install for Cursor locally${reset}\n npx get-shit-done-cc --cursor --local\n\n ${dim}# Install for Windsurf globally${reset}\n npx get-shit-done-cc --windsurf --global\n\n ${dim}# Install for Windsurf locally${reset}\n npx get-shit-done-cc --windsurf --local\n\n ${dim}# Install for Augment globally${reset}\n npx get-shit-done-cc --augment --global\n\n ${dim}# Install for Augment locally${reset}\n npx get-shit-done-cc --augment --local\n\n ${dim}# Install for Trae globally${reset}\n npx get-shit-done-cc --trae --global\n\n ${dim}# Install for Trae locally${reset}\n npx get-shit-done-cc --trae --local\n\n ${dim}# Install for Cline locally${reset}\n npx get-shit-done-cc --cline --local\n\n ${dim}# Install for CodeBuddy globally${reset}\n npx get-shit-done-cc --codebuddy --global\n\n ${dim}# Install for CodeBuddy locally${reset}\n npx get-shit-done-cc --codebuddy --local\n\n ${dim}# Install for all runtimes globally${reset}\n npx get-shit-done-cc --all --global\n\n ${dim}# Install to custom config directory${reset}\n npx get-shit-done-cc --kilo --global --config-dir ~/.kilo-work\n\n ${dim}# Install to current project only${reset}\n npx get-shit-done-cc --claude --local\n\n ${dim}# Uninstall GSD from Cursor globally${reset}\n npx get-shit-done-cc --cursor --global --uninstall\n\n ${yellow}Notes:${reset}\n The --config-dir option is useful when you have multiple configurations.\n It takes priority over CLAUDE_CONFIG_DIR / OPENCODE_CONFIG_DIR / GEMINI_CONFIG_DIR / KILO_CONFIG_DIR / CODEX_HOME / COPILOT_CONFIG_DIR / ANTIGRAVITY_CONFIG_DIR / CURSOR_CONFIG_DIR / WINDSURF_CONFIG_DIR / AUGMENT_CONFIG_DIR / TRAE_CONFIG_DIR / QWEN_CONFIG_DIR / CLINE_CONFIG_DIR / CODEBUDDY_CONFIG_DIR environment variables.\n`);
process.exit(0);
}
@@ -453,16 +454,31 @@ function expandTilde(filePath) {
/**
* Build a hook command path using forward slashes for cross-platform compatibility.
* On Windows, $HOME is not expanded by cmd.exe/PowerShell, so we use the actual path.
*
* @param {string} configDir - Resolved absolute config directory path
* @param {string} hookName - Hook filename (e.g. 'gsd-statusline.js')
* @param {{ portableHooks?: boolean }} [opts] - Options
* portableHooks: when true, emit $HOME-relative paths instead of absolute paths.
* Safe for Linux/macOS global installs and WSL/Docker bind-mount scenarios.
* Not suitable for pure Windows (cmd.exe/PowerShell do not expand $HOME).
*/
function buildHookCommand(configDir, hookName) {
// Use forward slashes for Node.js compatibility on all platforms
const hooksPath = configDir.replace(/\\/g, '/') + '/hooks/' + hookName;
// .sh hooks use bash; .js hooks use node. Both wrap the path in double quotes
// so that paths with spaces (e.g. Windows "C:/Users/First Last/") work correctly
// (fixes #2045). Routing .sh hooks through this function also ensures they always
// receive an absolute path rather than the bare relative string that the old manual
// concatenation produced (fixes #2046).
function buildHookCommand(configDir, hookName, opts) {
if (!opts) opts = {};
const runner = hookName.endsWith('.sh') ? 'bash' : 'node';
if (opts.portableHooks) {
// Replace the home directory prefix with $HOME so the path works when
// ~/.claude is bind-mounted into a container at a different absolute path.
const home = os.homedir().replace(/\\/g, '/');
const normalized = configDir.replace(/\\/g, '/');
const relative = normalized.startsWith(home)
? '$HOME' + normalized.slice(home.length)
: normalized;
return `${runner} "${relative}/hooks/${hookName}"`;
}
// Default: absolute path with forward slashes (Windows-safe, fixes #2045/#2046).
const hooksPath = configDir.replace(/\\/g, '/') + '/hooks/' + hookName;
return `${runner} "${hooksPath}"`;
}
@@ -573,6 +589,27 @@ function writeSettings(settingsPath, settings) {
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
}
/**
* Read model_overrides from ~/.gsd/defaults.json at install time.
* Returns an object mapping agent names to model IDs, or null if the file
* doesn't exist or has no model_overrides entry.
* Used by Codex TOML and OpenCode agent file generators to embed per-agent
* model assignments so that model_overrides is respected on non-Claude runtimes (#2256).
*/
function readGsdGlobalModelOverrides() {
try {
const defaultsPath = path.join(os.homedir(), '.gsd', 'defaults.json');
if (!fs.existsSync(defaultsPath)) return null;
const raw = fs.readFileSync(defaultsPath, 'utf-8');
const parsed = JSON.parse(raw);
const overrides = parsed.model_overrides;
if (!overrides || typeof overrides !== 'object') return null;
return overrides;
} catch {
return null;
}
}
// Cache for attribution settings (populated once per runtime during install)
const attributionCache = new Map();
@@ -1732,7 +1769,7 @@ purpose: ${toSingleLine(description)}
* Sets required agent metadata, sandbox_mode, and developer_instructions
* from the agent markdown content.
*/
function generateCodexAgentToml(agentName, agentContent) {
function generateCodexAgentToml(agentName, agentContent, modelOverrides = null) {
const sandboxMode = CODEX_AGENT_SANDBOX[agentName] || 'read-only';
const { frontmatter, body } = extractFrontmatterAndBody(agentContent);
const frontmatterText = frontmatter || '';
@@ -1746,12 +1783,22 @@ function generateCodexAgentToml(agentName, agentContent) {
`name = ${JSON.stringify(resolvedName)}`,
`description = ${JSON.stringify(resolvedDescription)}`,
`sandbox_mode = "${sandboxMode}"`,
// Agent prompts contain raw backslashes in regexes and shell snippets.
// TOML literal multiline strings preserve them without escape parsing.
`developer_instructions = '''`,
instructions,
`'''`,
];
// Embed model override when configured in ~/.gsd/defaults.json so that
// model_overrides is respected on Codex (which uses static TOML, not inline
// Task() model parameters). See #2256.
const modelOverride = modelOverrides?.[resolvedName] || modelOverrides?.[agentName];
if (modelOverride) {
lines.push(`model = ${JSON.stringify(modelOverride)}`);
}
// Agent prompts contain raw backslashes in regexes and shell snippets.
// TOML literal multiline strings preserve them without escape parsing.
lines.push(`developer_instructions = '''`);
lines.push(instructions);
lines.push(`'''`);
return lines.join('\n') + '\n';
}
@@ -2975,7 +3022,10 @@ function installCodexConfig(targetDir, agentsSrc) {
agents.push({ name, description: toSingleLine(description) });
const tomlContent = generateCodexAgentToml(name, content);
// Pass model overrides from ~/.gsd/defaults.json so Codex TOML files
// embed the configured model — Codex cannot receive model inline (#2256).
const modelOverrides = readGsdGlobalModelOverrides();
const tomlContent = generateCodexAgentToml(name, content, modelOverrides);
fs.writeFileSync(path.join(agentsTomlDir, `${name}.toml`), tomlContent);
}
@@ -3129,7 +3179,7 @@ function convertClaudeToGeminiAgent(content) {
return `---\n${newFrontmatter}\n---${stripSubTags(neutralBody)}`;
}
function convertClaudeToOpencodeFrontmatter(content, { isAgent = false } = {}) {
function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOverride = null } = {}) {
// Replace tool name references in content (applies to all files)
let convertedContent = content;
convertedContent = convertedContent.replace(/\bAskUserQuestion\b/g, 'question');
@@ -3264,6 +3314,12 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false } = {}) {
// use its default model for subagents. See #1156.
if (isAgent) {
newLines.push('mode: subagent');
// Embed model override from ~/.gsd/defaults.json so model_overrides is
// respected on OpenCode (which uses static agent frontmatter, not inline
// Task() model parameters). See #2256.
if (modelOverride) {
newLines.push(`model: ${modelOverride}`);
}
}
// For commands: add tools object if we had allowed-tools or tools
@@ -5666,7 +5722,11 @@ function install(isGlobal, runtime = 'claude') {
content = processAttribution(content, getCommitAttribution(runtime));
// Convert frontmatter for runtime compatibility (agents need different handling)
if (isOpencode) {
content = convertClaudeToOpencodeFrontmatter(content, { isAgent: true });
// Resolve per-agent model override from ~/.gsd/defaults.json (#2256)
const _ocAgentName = entry.name.replace(/\.md$/, '');
const _ocModelOverrides = readGsdGlobalModelOverrides();
const _ocModelOverride = _ocModelOverrides?.[_ocAgentName] || null;
content = convertClaudeToOpencodeFrontmatter(content, { isAgent: true, modelOverride: _ocModelOverride });
} else if (isKilo) {
content = convertClaudeToKiloFrontmatter(content, { isAgent: true });
} else if (isGemini) {
@@ -5991,20 +6051,21 @@ function install(isGlobal, runtime = 'claude') {
// Local installs anchor paths to $CLAUDE_PROJECT_DIR so hooks resolve
// correctly regardless of the shell's current working directory (#1906).
const localPrefix = '"$CLAUDE_PROJECT_DIR"/' + dirName;
const hookOpts = { portableHooks: hasPortableHooks };
const statuslineCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-statusline.js')
? buildHookCommand(targetDir, 'gsd-statusline.js', hookOpts)
: 'node ' + localPrefix + '/hooks/gsd-statusline.js';
const updateCheckCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-check-update.js')
? buildHookCommand(targetDir, 'gsd-check-update.js', hookOpts)
: 'node ' + localPrefix + '/hooks/gsd-check-update.js';
const contextMonitorCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-context-monitor.js')
? buildHookCommand(targetDir, 'gsd-context-monitor.js', hookOpts)
: 'node ' + localPrefix + '/hooks/gsd-context-monitor.js';
const promptGuardCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-prompt-guard.js')
? buildHookCommand(targetDir, 'gsd-prompt-guard.js', hookOpts)
: 'node ' + localPrefix + '/hooks/gsd-prompt-guard.js';
const readGuardCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-read-guard.js')
? buildHookCommand(targetDir, 'gsd-read-guard.js', hookOpts)
: 'node ' + localPrefix + '/hooks/gsd-read-guard.js';
// Enable experimental agents for Gemini CLI (required for custom sub-agents)
@@ -6157,7 +6218,7 @@ function install(isGlobal, runtime = 'claude') {
// Detects file edits outside GSD workflow context and advises using
// /gsd-quick or /gsd-fast for state-tracked changes. Advisory only.
const workflowGuardCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-workflow-guard.js')
? buildHookCommand(targetDir, 'gsd-workflow-guard.js', hookOpts)
: 'node ' + localPrefix + '/hooks/gsd-workflow-guard.js';
const hasWorkflowGuardHook = settings.hooks[preToolEvent].some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-workflow-guard'))
@@ -6182,7 +6243,7 @@ function install(isGlobal, runtime = 'claude') {
// Configure commit validation hook (Conventional Commits enforcement, opt-in)
const validateCommitCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-validate-commit.sh')
? buildHookCommand(targetDir, 'gsd-validate-commit.sh', hookOpts)
: 'bash ' + localPrefix + '/hooks/gsd-validate-commit.sh';
const hasValidateCommitHook = settings.hooks[preToolEvent].some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-validate-commit'))
@@ -6209,7 +6270,7 @@ function install(isGlobal, runtime = 'claude') {
// Configure session state orientation hook (opt-in)
const sessionStateCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-session-state.sh')
? buildHookCommand(targetDir, 'gsd-session-state.sh', hookOpts)
: 'bash ' + localPrefix + '/hooks/gsd-session-state.sh';
const hasSessionStateHook = settings.hooks.SessionStart.some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-session-state'))
@@ -6231,7 +6292,7 @@ function install(isGlobal, runtime = 'claude') {
// Configure phase boundary detection hook (opt-in)
const phaseBoundaryCommand = isGlobal
? buildHookCommand(targetDir, 'gsd-phase-boundary.sh')
? buildHookCommand(targetDir, 'gsd-phase-boundary.sh', hookOpts)
: 'bash ' + localPrefix + '/hooks/gsd-phase-boundary.sh';
const hasPhaseBoundaryHook = settings.hooks[postToolEvent].some(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-phase-boundary'))
@@ -6271,11 +6332,19 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
const isCline = runtime === 'cline';
if (shouldInstallStatusline && !isOpencode && !isKilo && !isCodex && !isCopilot && !isCursor && !isWindsurf && !isTrae) {
settings.statusLine = {
type: 'command',
command: statuslineCommand
};
console.log(` ${green}${reset} Configured statusline`);
if (!isGlobal && !forceStatusline) {
// Local installs skip statusLine by default: repo settings.json takes precedence over
// profile-level settings.json in Claude Code, so writing here would silently clobber
// any profile-level statusLine the user has configured (#2248).
// Pass --force-statusline to override this guard.
console.log(` ${yellow}${reset} Skipping statusLine for local install (avoids overriding profile-level settings; use --force-statusline to override)`);
} else {
settings.statusLine = {
type: 'command',
command: statuslineCommand
};
console.log(` ${green}${reset} Configured statusline`);
}
}
// Write settings when runtime supports settings.json

View File

@@ -23,18 +23,14 @@ the normal phase sequence and accumulate context over time.
2. **Find next backlog number:**
```bash
NEXT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase next-decimal 999 --raw)
NEXT=$(gsd-sdk query phase.next-decimal 999 --raw)
```
If no 999.x phases exist, start at 999.1.
3. **Create the phase directory:**
```bash
SLUG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" generate-slug "$ARGUMENTS" --raw)
mkdir -p ".planning/phases/${NEXT}-${SLUG}"
touch ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
```
4. **Add to ROADMAP.md** under a `## Backlog` section. If the section doesn't exist, create it at the end:
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
@@ -49,9 +45,16 @@ the normal phase sequence and accumulate context over time.
- [ ] 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
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: add backlog item ${NEXT} — ${ARGUMENTS}" --files .planning/ROADMAP.md ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
gsd-sdk query commit "docs: add backlog item ${NEXT} — ${ARGUMENTS}" .planning/ROADMAP.md ".planning/phases/${NEXT}-${SLUG}/.gitkeep"
```
6. **Report:**

View File

@@ -37,7 +37,7 @@ Optional flags:
- `--only N` — execute only phase N (single-phase mode).
- `--interactive` — run discuss inline with questions (not auto-answered), then dispatch plan→execute as background agents. Keeps the main context lean while preserving user input on decisions.
Project context, phase list, and state are resolved inside the workflow using init commands (`gsd-tools.cjs init milestone-op`, `gsd-tools.cjs roadmap analyze`). No upfront context loading needed.
Project context, phase list, and state are resolved inside the workflow using init commands (`gsd-sdk query init.milestone-op`, `gsd-sdk query roadmap.analyze`). No upfront context loading needed.
</context>
<process>

View File

@@ -33,7 +33,7 @@ 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-tools init phase-op` and delegated to agent via config blocks.
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>

View File

@@ -37,7 +37,7 @@ Optional flags parsed from $ARGUMENTS:
- `--depth=VALUE` — Depth override (quick|standard|deep). If provided, overrides workflow.code_review_depth config.
- `--files=file1,file2,...` — Explicit file list override. Has highest precedence for file scoping per D-08. When provided, workflow skips SUMMARY.md extraction and git diff fallback entirely.
Context files (CLAUDE.md, SUMMARY.md, phase state) are resolved inside the workflow via `gsd-tools init phase-op` and delegated to agent via `<files_to_read>` blocks.
Context files (CLAUDE.md, SUMMARY.md, phase state) are resolved inside the workflow via `gsd-sdk query init.phase-op` and delegated to agent via `<files_to_read>` blocks.
</context>
<process>

View File

@@ -52,18 +52,18 @@ ls .planning/debug/*.md 2>/dev/null | grep -v resolved | head -5
## 0. Initialize Context
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
INIT=$(gsd-sdk query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
Extract `commit_docs` from init JSON. Resolve debugger model:
```bash
debugger_model=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-debugger --raw)
debugger_model=$(gsd-sdk query resolve-model gsd-debugger 2>/dev/null | jq -r '.model' 2>/dev/null || true)
```
Read TDD mode from config:
```bash
TDD_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get tdd_mode 2>/dev/null || echo "false")
TDD_MODE=$(gsd-sdk query config-get tdd_mode 2>/dev/null | jq -r 'if type == "boolean" then tostring else . end' 2>/dev/null || echo "false")
```
## 1a. LIST subcommand

View File

@@ -1,7 +1,7 @@
---
name: gsd:discuss-phase
description: Gather phase context through adaptive questioning before planning. Use --auto to skip interactive questions (Claude picks recommended defaults). Use --chain for interactive discuss followed by automatic plan+execute. Use --power for bulk question generation into a file-based UI (answer at your own pace).
argument-hint: "<phase> [--auto] [--chain] [--batch] [--analyze] [--text] [--power]"
description: Gather phase context through adaptive questioning before planning. Use --all to skip area selection and discuss all gray areas interactively. Use --auto to skip interactive questions (Claude picks recommended defaults). Use --chain for interactive discuss followed by automatic plan+execute. Use --power for bulk question generation into a file-based UI (answer at your own pace).
argument-hint: "<phase> [--all] [--auto] [--chain] [--batch] [--analyze] [--text] [--power]"
allowed-tools:
- Read
- Write
@@ -48,7 +48,7 @@ Context files are resolved in-workflow using `init phase-op` and roadmap/state t
<process>
**Mode routing:**
```bash
DISCUSS_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.discuss_mode 2>/dev/null || echo "discuss")
DISCUSS_MODE=$(gsd-sdk query config-get workflow.discuss_mode 2>/dev/null || echo "discuss")
```
If `DISCUSS_MODE` is `"assumptions"`: Read and execute @~/.claude/get-shit-done/workflows/discuss-phase-assumptions.md end-to-end.

View File

@@ -54,7 +54,7 @@ Phase: $ARGUMENTS
- If none of these tokens appear, run the standard full-phase execution flow with no flag-specific filtering
- Do not infer that a flag is active just because it is documented in this prompt
Context files are resolved inside the workflow via `gsd-tools init execute-phase` and per-subagent `<files_to_read>` blocks.
Context files are resolved inside the workflow via `gsd-sdk query init.execute-phase` and per-subagent `<files_to_read>` blocks.
</context>
<process>

View File

@@ -13,6 +13,8 @@ type: prompt
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>

View File

@@ -10,6 +10,8 @@ allowed-tools:
**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.**
**CJS-only (graphify):** `graphify` subcommands are not registered on `gsd-sdk query`. Use `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs graphify …` as documented in this command and in `docs/CLI-TOOLS.md`. Other tooling may still use `gsd-sdk query` where a handler exists.
## Step 0 -- Banner
**Before ANY tool calls**, display this banner:

38
commands/gsd/inbox.md Normal file
View File

@@ -0,0 +1,38 @@
---
name: gsd:inbox
description: Triage and review all open GitHub issues and PRs against project templates and contribution guidelines
argument-hint: "[--issues] [--prs] [--label] [--close-incomplete] [--repo owner/repo]"
allowed-tools:
- Read
- Bash
- Write
- Grep
- Glob
- AskUserQuestion
---
<objective>
One-command triage of the project's GitHub inbox. Fetches all open issues and PRs,
reviews each against the corresponding template requirements (feature, enhancement,
bug, chore, fix PR, enhancement PR, feature PR), reports completeness and compliance,
and optionally applies labels or closes non-compliant submissions.
**Flow:** Detect repo → Fetch open issues + PRs → Classify each by type → Review against template → Report findings → Optionally act (label, comment, close)
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/inbox.md
</execution_context>
<context>
**Flags:**
- `--issues` — Review only issues (skip PRs)
- `--prs` — Review only PRs (skip issues)
- `--label` — Auto-apply recommended labels after review
- `--close-incomplete` — Close issues/PRs that fail template compliance (with comment explaining why)
- `--repo owner/repo` — Override auto-detected repository (defaults to current git remote)
</context>
<process>
Execute the inbox workflow from @~/.claude/get-shit-done/workflows/inbox.md end-to-end.
Parse flags from arguments and pass to workflow.
</process>

View File

@@ -39,7 +39,7 @@ GSD > INTEL
Intel system is disabled. To activate:
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs config-set intel.enabled true
gsd-sdk query config-set intel.enabled true
Then run /gsd-intel refresh to build the initial index.
```
@@ -77,7 +77,7 @@ Modes:
Run:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel query <term>
gsd-sdk query intel.query <term>
```
Parse the JSON output and display results:
@@ -92,7 +92,7 @@ Parse the JSON output and display results:
Run:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel status
gsd-sdk query intel.status
```
Parse the JSON output and display each intel file with:
@@ -107,7 +107,7 @@ Parse the JSON output and display each intel file with:
Run:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel diff
gsd-sdk query intel.diff
```
Parse the JSON output and display:
@@ -137,15 +137,15 @@ Task(
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}
gsd-tools path: $HOME/.claude/get-shit-done/bin/gsd-tools.cjs
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-tools intel extract-exports <file> to analyze source files
5. Use gsd-tools intel patch-meta <file> to update timestamps after writing
6. Use gsd-tools intel validate to check your output
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."
@@ -161,7 +161,7 @@ Wait for the agent to complete.
After the agent completes, run:
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs intel status
gsd-sdk query intel.status
```
Display a summary showing:

View File

@@ -31,7 +31,7 @@ Designed for power users who want to parallelize work across phases from one ter
<context>
No arguments required. Requires an active milestone with ROADMAP.md and STATE.md.
Project context, phase list, dependencies, and recommendations are resolved inside the workflow using `gsd-tools.cjs init manager`. No upfront context loading needed.
Project context, phase list, dependencies, and recommendations are resolved inside the workflow using `gsd-sdk query init.manager`. No upfront context loading needed.
</context>
<process>

View File

@@ -1,6 +1,7 @@
---
name: gsd:progress
description: Check project progress, show context, and route to next action (execute or plan)
description: Check project progress, show context, and route to next action (execute or plan). Use --forensic to append a 6-check integrity audit after the standard report.
argument-hint: "[--forensic]"
allowed-tools:
- Read
- Bash

View File

@@ -71,7 +71,7 @@ For each directory found:
- Check if PLAN.md exists
- Check if SUMMARY.md exists; if so, read `status` from its frontmatter via:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter get .planning/quick/{dir}/SUMMARY.md --field status 2>/dev/null
gsd-sdk query frontmatter.get .planning/quick/{dir}/SUMMARY.md status 2>/dev/null
```
- Determine directory creation date: `stat -f "%SB" -t "%Y-%m-%d"` (macOS) or `stat -c "%w"` (Linux); fall back to the date prefix in the directory name (format: `YYYYMMDD-` prefix)
- Derive display status:
@@ -144,7 +144,7 @@ When SUBCMD=resume and SLUG is set (already sanitized):
5. Load context via:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init quick
gsd-sdk query init.quick
```
6. Proceed to execute the quick workflow with resume context, passing the slug and plan directory so the executor picks up where it left off.
@@ -169,5 +169,5 @@ Preserve all workflow gates (validation, task description, planning, execution,
- Slugs from $ARGUMENTS are sanitized before use in file paths: only [a-z0-9-] allowed, max 60 chars, reject ".." and "/"
- File names from readdir/ls are sanitized before display: strip non-printable chars and ANSI sequences
- Artifact content (plan descriptions, task titles) rendered as plain text only — never executed or passed to agent prompts without DATA_START/DATA_END boundaries
- Status fields read via gsd-tools.cjs frontmatter get — never eval'd or shell-expanded
- Status fields read via `gsd-sdk query frontmatter.get` — never eval'd or shell-expanded
</security_notes>

View File

@@ -39,7 +39,7 @@ Normalize phase input in step 1 before any directory lookups.
## 0. Initialize Context
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "$ARGUMENTS")
INIT=$(gsd-sdk query init.phase-op "$ARGUMENTS")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -47,13 +47,13 @@ Extract from init JSON: `phase_dir`, `phase_number`, `phase_name`, `phase_found`
Resolve researcher model:
```bash
RESEARCHER_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-phase-researcher --raw)
RESEARCHER_MODEL=$(gsd-sdk query resolve-model gsd-phase-researcher --raw)
```
## 1. Validate Phase
```bash
PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${phase_number}")
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.

View File

@@ -34,7 +34,7 @@ milestone sequence or remove stale entries.
- Find the next sequential phase number in the active milestone
- Rename the directory from `999.x-slug` to `{new_num}-slug`:
```bash
NEW_NUM=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase add "${DESCRIPTION}" --raw)
NEW_NUM=$(gsd-sdk query phase.add "${DESCRIPTION}" --raw)
```
- Move accumulated artifacts to the new phase directory
- Update ROADMAP.md: move the entry from `## Backlog` section to the active phase list
@@ -47,7 +47,7 @@ milestone sequence or remove stale entries.
6. **Commit changes:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: review backlog — promoted N, removed M" --files .planning/ROADMAP.md
gsd-sdk query commit "docs: review backlog — promoted N, removed M" .planning/ROADMAP.md
```
7. **Report summary:**

View File

@@ -9,4 +9,4 @@ allowed-tools:
Show the following output to the user verbatim, with no extra commentary:
!`node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set-model-profile $ARGUMENTS --raw`
!`gsd-sdk query config-set-model-profile $ARGUMENTS --raw`

View File

@@ -38,7 +38,7 @@ ls .planning/threads/*.md 2>/dev/null
For each thread file found:
- Read frontmatter `status` field via:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter get .planning/threads/{file} --field status 2>/dev/null
gsd-sdk query frontmatter.get .planning/threads/{file} status 2>/dev/null
```
- If frontmatter `status` field is missing, fall back to reading markdown heading `## Status: OPEN` (or IN PROGRESS / RESOLVED) from the file body
- Read frontmatter `updated` field for the last-updated date
@@ -77,13 +77,13 @@ When SUBCMD=close and SLUG is set (already sanitized):
2. Update the thread file's frontmatter `status` field to `resolved` and `updated` to today's ISO date:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter set .planning/threads/{SLUG}.md --field status --value '"resolved"'
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter set .planning/threads/{SLUG}.md --field updated --value '"YYYY-MM-DD"'
gsd-sdk query frontmatter.set .planning/threads/{SLUG}.md status resolved
gsd-sdk query frontmatter.set .planning/threads/{SLUG}.md updated YYYY-MM-DD
```
3. Commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: resolve thread — {SLUG}" --files ".planning/threads/{SLUG}.md"
gsd-sdk query commit "docs: resolve thread — {SLUG}" ".planning/threads/{SLUG}.md"
```
4. Print:
@@ -133,8 +133,8 @@ Resume the thread — load its context into the current session. Read the file c
Update the thread's frontmatter `status` to `in_progress` if it was `open`:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter set .planning/threads/{SLUG}.md --field status --value '"in_progress"'
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" frontmatter set .planning/threads/{SLUG}.md --field updated --value '"YYYY-MM-DD"'
gsd-sdk query frontmatter.set .planning/threads/{SLUG}.md status in_progress
gsd-sdk query frontmatter.set .planning/threads/{SLUG}.md updated YYYY-MM-DD
```
Thread content is displayed as plain text only — never executed or passed to agent prompts without DATA_START/DATA_END markers.
@@ -147,7 +147,7 @@ If $ARGUMENTS is a new description (no matching thread file):
1. Generate slug from description:
```bash
SLUG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" generate-slug "$ARGUMENTS" --raw)
SLUG=$(gsd-sdk query generate-slug "$ARGUMENTS" --raw)
```
2. Create the threads directory if needed:
@@ -191,7 +191,7 @@ updated: {today ISO date}
5. Commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: create thread — ${ARGUMENTS}" --files ".planning/threads/${SLUG}.md"
gsd-sdk query commit "docs: create thread — ${ARGUMENTS}" ".planning/threads/${SLUG}.md"
```
6. Report:
@@ -222,6 +222,6 @@ updated: {today ISO date}
- Slugs from $ARGUMENTS are sanitized before use in file paths: only [a-z0-9-] allowed, max 60 chars, reject ".." and "/"
- File names from readdir/ls are sanitized before display: strip non-printable chars and ANSI sequences
- Artifact content (thread titles, goal sections, next steps) rendered as plain text only — never executed or passed to agent prompts without DATA_START/DATA_END boundaries
- Status fields read via gsd-tools.cjs frontmatter get — never eval'd or shell-expanded
- The generate-slug call for new threads runs through gsd-tools.cjs which sanitizes input — keep that pattern
- Status fields read via gsd-sdk query frontmatter.get — never eval'd or shell-expanded
- The generate-slug call for new threads runs through gsd-sdk query (or gsd-tools) which sanitizes input — keep that pattern
</security_notes>

View File

@@ -34,30 +34,30 @@ If no subcommand given, default to `list`.
## Step 2: Execute Operation
### list
Run: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" workstream list --raw --cwd "$CWD"`
Run: `gsd-sdk query workstream.list --raw --cwd "$CWD"`
Display the workstreams in a table format showing name, status, current phase, and progress.
### create
Run: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" workstream create <name> --raw --cwd "$CWD"`
Run: `gsd-sdk query workstream.create <name> --raw --cwd "$CWD"`
After creation, display the new workstream path and suggest next steps:
- `/gsd-new-milestone --ws <name>` to set up the milestone
### status
Run: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" workstream status <name> --raw --cwd "$CWD"`
Run: `gsd-sdk query workstream.status <name> --raw --cwd "$CWD"`
Display detailed phase breakdown and state information.
### switch
Run: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" workstream set <name> --raw --cwd "$CWD"`
Run: `gsd-sdk query workstream.set <name> --raw --cwd "$CWD"`
Also set `GSD_WORKSTREAM` for the current session when the runtime supports it.
If the runtime exposes a session identifier, GSD also stores the active workstream
session-locally so concurrent sessions do not overwrite each other.
### progress
Run: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" workstream progress --raw --cwd "$CWD"`
Run: `gsd-sdk query workstream.progress --raw --cwd "$CWD"`
Display a progress overview across all workstreams.
### complete
Run: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" workstream complete <name> --raw --cwd "$CWD"`
Run: `gsd-sdk query workstream.complete <name> --raw --cwd "$CWD"`
Archive the workstream to milestones/.
### resume
@@ -65,5 +65,5 @@ Set the workstream as active and suggest `/gsd-resume-work --ws <name>`.
## Step 3: Display Results
Format the JSON output from gsd-tools into a human-readable display.
Format the JSON output from gsd-sdk query into a human-readable display.
Include the `${GSD_WS}` flag in any routing suggestions.

View File

@@ -54,7 +54,7 @@ GSD is a **meta-prompting framework** that sits between the user and AI coding a
│ │ │
┌──────▼──────────────▼─────────────────▼──────────────┐
│ CLI TOOLS LAYER │
│ get-shit-done/bin/gsd-tools.cjs
│ gsd-sdk query (sdk/src/query) + gsd-tools.cjs
│ (State, config, phase, roadmap, verify, templates) │
└──────────────────────┬───────────────────────────────┘
@@ -76,7 +76,7 @@ Every agent spawned by an orchestrator gets a clean context window (up to 200K t
### 2. Thin Orchestrators
Workflow files (`get-shit-done/workflows/*.md`) never do heavy lifting. They:
- Load context via `gsd-tools.cjs init <workflow>`
- Load context via `gsd-sdk query init.<workflow>` (or legacy `gsd-tools.cjs init <workflow>`)
- Spawn specialized agents with focused prompts
- Collect results and route to the next step
- Update state between steps
@@ -113,18 +113,18 @@ User-facing entry points. Each file contains YAML frontmatter (name, description
- **Copilot:** Slash commands (`/gsd-command-name`)
- **Antigravity:** Skills
**Total commands:** 69
**Total commands:** 74
### Workflows (`get-shit-done/workflows/*.md`)
Orchestration logic that commands reference. Contains the step-by-step process including:
- Context loading via `gsd-tools.cjs init`
- Context loading via `gsd-sdk query` init handlers (or legacy `gsd-tools.cjs init`)
- Agent spawn instructions with model resolution
- Gate/checkpoint definitions
- State update patterns
- Error handling and recovery
**Total workflows:** 68
**Total workflows:** 71
### Agents (`agents/*.md`)
@@ -134,7 +134,7 @@ Specialized agent definitions with frontmatter specifying:
- `tools` — Allowed tool access (Read, Write, Edit, Bash, Grep, Glob, WebSearch, etc.)
- `color` — Terminal output color for visual distinction
**Total agents:** 24
**Total agents:** 31
### References (`get-shit-done/references/*.md`)
@@ -409,14 +409,14 @@ UI-SPEC.md (per phase) ───────────────────
```
~/.claude/ # Claude Code (global install)
├── commands/gsd/*.md # 69 slash commands
├── commands/gsd/*.md # 74 slash commands
├── get-shit-done/
│ ├── bin/gsd-tools.cjs # CLI utility
│ ├── bin/lib/*.cjs # 19 domain modules
│ ├── workflows/*.md # 68 workflow definitions
│ ├── workflows/*.md # 71 workflow definitions
│ ├── references/*.md # 35 shared reference docs
│ └── templates/ # Planning artifact templates
├── agents/*.md # 24 agent definitions
├── agents/*.md # 31 agent definitions
├── hooks/
│ ├── gsd-statusline.js # Statusline hook
│ ├── gsd-context-monitor.js # Context warning hook

View File

@@ -8,6 +8,8 @@
`gsd-tools.cjs` is a Node.js CLI utility that replaces repetitive inline bash patterns across GSD's ~50 command, workflow, and agent files. It centralizes: config parsing, model resolution, phase lookup, git commits, summary verification, state management, and template operations.
**Preferred for new orchestration:** Many of the same operations are available as `gsd-sdk query <command>` (see `sdk/src/query/index.ts` and `docs/QUERY-HANDLERS.md`). Use that in workflows and examples where the handler exists; keep `node … gsd-tools.cjs` for commands not yet in the registry (for example graphify) or when you need CJS-only flags.
**Location:** `get-shit-done/bin/gsd-tools.cjs`
**Modules:** 15 domain modules in `get-shit-done/bin/lib/`

View File

@@ -98,6 +98,7 @@ Capture implementation decisions before planning.
| Flag | Description |
|------|-------------|
| `--all` | Skip area selection — discuss all gray areas interactively (no auto-advance) |
| `--auto` | Auto-select recommended defaults for all questions |
| `--batch` | Group questions for batch intake instead of one-by-one |
| `--analyze` | Add trade-off analysis during discussion |
@@ -108,6 +109,7 @@ Capture implementation decisions before planning.
```bash
/gsd-discuss-phase 1 # Interactive discussion for phase 1
/gsd-discuss-phase 1 --all # Discuss all gray areas without selection step
/gsd-discuss-phase 3 --auto # Auto-select defaults for phase 3
/gsd-discuss-phase --batch # Batch mode for current phase
/gsd-discuss-phase 2 --analyze # Discussion with trade-off analysis
@@ -482,8 +484,13 @@ Retroactively audit and fill Nyquist validation gaps.
Show status and next steps.
| Flag | Description |
|------|-------------|
| `--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) |
```bash
/gsd-progress # "Where am I? What's next?"
/gsd-progress --forensic # Standard report + integrity audit
```
### `/gsd-resume-work`

View File

@@ -798,14 +798,20 @@ Each workspace gets:
## Troubleshooting
### Programmatic CLI (`gsd-sdk query` vs `gsd-tools.cjs`)
For automation and copy-paste from docs, prefer **`gsd-sdk query`** with a registered subcommand (see [CLI-TOOLS.md](CLI-TOOLS.md) and [QUERY-HANDLERS.md](../sdk/src/query/QUERY-HANDLERS.md)). The legacy **`node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs`** CLI remains supported for dual-mode operation.
**Not yet on `gsd-sdk query` (use CJS):** `state validate`, `state sync`, `audit-open`, `graphify`, `from-gsd2`, and any subcommand not listed in the registry.
### STATE.md Out of Sync
If STATE.md shows incorrect phase status or position, use the state consistency commands:
If STATE.md shows incorrect phase status or position, use the state consistency commands (**CJS-only** until ported to the query layer):
```bash
node gsd-tools.cjs state validate # Detect drift between STATE.md and filesystem
node gsd-tools.cjs state sync --verify # Preview what sync would change
node gsd-tools.cjs state sync # Reconstruct STATE.md from disk
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state validate # Detect drift between STATE.md and filesystem
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state sync --verify # Preview what sync would change
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state sync # Reconstruct STATE.md from disk
```
These commands are new in v1.32 and replace manual STATE.md editing.
@@ -935,6 +941,111 @@ When a workflow fails in a way that isn't obvious -- plans reference nonexistent
**Output:** A diagnostic report written to `.planning/forensics/` with findings and suggested remediation steps.
### Executor Subagent Gets "Permission denied" on Bash Commands
GSD's `gsd-executor` subagents need write-capable Bash access to a project's standard tooling — `git commit`, `bin/rails`, `bundle exec`, `npm run`, `uv run`, and similar commands. Claude Code's default `~/.claude/settings.json` only allows a narrow set of read-only git commands, so a fresh install will hit "Permission to use Bash has been denied" the first time an executor tries to make a commit or run a build tool.
**Fix: add the required patterns to `~/.claude/settings.json`.**
The patterns you need depend on your stack. Copy the block for your stack and add it to the `permissions.allow` array.
#### Required for all stacks (git + gh)
```json
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git merge:*)",
"Bash(git worktree:*)",
"Bash(git rebase:*)",
"Bash(git reset:*)",
"Bash(git checkout:*)",
"Bash(git switch:*)",
"Bash(git restore:*)",
"Bash(git stash:*)",
"Bash(git rm:*)",
"Bash(git mv:*)",
"Bash(git fetch:*)",
"Bash(git cherry-pick:*)",
"Bash(git apply:*)",
"Bash(gh:*)"
```
#### Rails / Ruby
```json
"Bash(bin/rails:*)",
"Bash(bin/brakeman:*)",
"Bash(bin/bundler-audit:*)",
"Bash(bin/importmap:*)",
"Bash(bundle:*)",
"Bash(rubocop:*)",
"Bash(erb_lint:*)"
```
#### Python / uv
```json
"Bash(uv:*)",
"Bash(python:*)",
"Bash(pytest:*)",
"Bash(ruff:*)",
"Bash(mypy:*)"
```
#### Node / npm / pnpm / bun
```json
"Bash(npm:*)",
"Bash(npx:*)",
"Bash(pnpm:*)",
"Bash(bun:*)",
"Bash(node:*)"
```
#### Rust / Cargo
```json
"Bash(cargo:*)"
```
**Example `~/.claude/settings.json` snippet (Rails project):**
```json
{
"permissions": {
"allow": [
"Write",
"Edit",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git merge:*)",
"Bash(git worktree:*)",
"Bash(git rebase:*)",
"Bash(git reset:*)",
"Bash(git checkout:*)",
"Bash(git switch:*)",
"Bash(git restore:*)",
"Bash(git stash:*)",
"Bash(git rm:*)",
"Bash(git mv:*)",
"Bash(git fetch:*)",
"Bash(git cherry-pick:*)",
"Bash(git apply:*)",
"Bash(gh:*)",
"Bash(bin/rails:*)",
"Bash(bin/brakeman:*)",
"Bash(bin/bundler-audit:*)",
"Bash(bundle:*)",
"Bash(rubocop:*)"
]
}
}
```
**Per-project permissions (scoped to one repo):** If you prefer to allow these patterns for a single project rather than globally, add the same `permissions.allow` block to `.claude/settings.local.json` in your project root instead of `~/.claude/settings.json`. Claude Code checks project-local settings first.
**Interactive guidance:** When an executor is blocked mid-phase, it will identify the exact pattern needed (e.g. `"Bash(bin/rails:*)"`) so you can add it and re-run `/gsd-execute-phase`.
### Subagent Appears to Fail but Work Was Done
A known workaround exists for a Claude Code classification bug. GSD's orchestrators (execute-phase, quick) spot-check actual output before reporting failure. If you see a failure message but commits were made, check `git log` -- the work may have succeeded.

View File

@@ -0,0 +1,22 @@
# GSD SDK query migration (summary blurb)
Copy-paste friendly for Discord and GitHub comments.
---
**@gsd-build/sdk** replaces the untyped, monolithic `gsd-tools.cjs` subprocess with a typed, tested, registry-based query system and **`gsd-sdk query`**, giving GSD structured results, classified errors (`GSDQueryError`), and golden-verified parity with the old CLI. That gives the framework one stable contract instead of a fragile, very large CLI that every workflow had to spawn and parse by hand.
**What users can expect**
- Same GSD commands and workflows they already use.
- Snappier runs (less Node startup on chained tool calls).
- Fewer mysterious mid-workflow failures and safer upgrades, because behavior is covered by tests and a single stable contract.
- Stronger predictability: outputs and failure modes are consistent and explicit.
**Cost and tokens**
The SDK does not automatically reduce LLM tokens per model call. Savings show up indirectly: fewer ambiguous tool results and fewer retry or recovery loops, which often lowers real-world session cost and wall time.
**Agents then vs now**
Agents always followed workflow instructions. What improved is the surface those steps run on. Before, workflows effectively said to shell out to `gsd-tools.cjs` and interpret stdout or JSON with brittle assumptions. Now they point at **`gsd-sdk query`** and typed handlers that return the shapes prompts expect, with clearer error reasons when something must stop or be fixed, so instruction following holds end to end with less thrash from bad parses or silent output drift.

View File

@@ -0,0 +1,92 @@
# Skill Discovery Contract
> Canonical rules for scanning, inventorying, and rendering GSD skills.
## Root Categories
### Project Roots
Scan these roots relative to the project root:
- `.claude/skills/`
- `.agents/skills/`
- `.cursor/skills/`
- `.github/skills/`
- `./.codex/skills/`
These roots are used for project-specific skills and for the project `CLAUDE.md` skills section.
### Managed Global Roots
Scan these roots relative to the user home directory:
- `~/.claude/skills/`
- `~/.codex/skills/`
These roots are used for managed runtime installs and inventory reporting.
### Deprecated Import-Only Root
- `~/.claude/get-shit-done/skills/`
This root is kept for legacy migration only. Inventory code may report it, but new installs should not write here.
### Legacy Claude Commands
- `~/.claude/commands/gsd/`
This is not a skills root. Discovery code only checks whether it exists so inventory can report legacy Claude installs.
## Normalization Rules
- Scan only subdirectories that contain `SKILL.md`.
- Read `name` and `description` from YAML frontmatter.
- Use the directory name when `name` is missing.
- Extract trigger hints from body lines that match `TRIGGER when: ...`.
- Treat `gsd-*` directories as installed framework skills.
- Treat `~/.claude/get-shit-done/skills/` entries as deprecated/import-only.
- Treat `~/.claude/commands/gsd/` as legacy command installation metadata, not skills.
## Scanner Behavior
### `sdk/src/query/skills.ts`
- Returns a de-duplicated list of discovered skill names.
- Scans project roots plus managed global roots.
- Does not scan the deprecated import-only root.
### `get-shit-done/bin/lib/profile-output.cjs`
- Builds the project `CLAUDE.md` skills section.
- Scans project roots only.
- Skips `gsd-*` directories so the project section stays focused on user/project skills.
- Adds `.codex/skills/` to the project discovery set.
### `get-shit-done/bin/lib/init.cjs`
- Generates the skill inventory object for `skill-manifest`.
- Reports `skills`, `roots`, `installation`, and `counts`.
- Marks `gsd_skills_installed` when any discovered skill name starts with `gsd-`.
- Marks `legacy_claude_commands_installed` when `~/.claude/commands/gsd/` contains `.md` command files.
## Inventory Shape
`skill-manifest` returns a JSON object with:
- `skills`: normalized skill entries
- `roots`: the canonical roots that were checked
- `installation`: summary booleans for installed GSD skills and legacy Claude commands
- `counts`: small inventory counts for downstream consumers
Each skill entry includes:
- `name`
- `description`
- `triggers`
- `path`
- `file_path`
- `root`
- `scope`
- `installed`
- `deprecated`

View File

@@ -639,6 +639,11 @@ async function runCommand(command, args, cwd, raw, defaultValue) {
break;
}
case 'config-path': {
config.cmdConfigPath(cwd, raw);
break;
}
case 'agent-skills': {
init.cmdAgentSkills(cwd, args[1], raw);
break;
@@ -781,9 +786,9 @@ async function runCommand(command, args, cwd, raw, defaultValue) {
const includeRaw = args.includes('--json');
const result = auditOpenArtifacts(cwd);
if (includeRaw) {
output(JSON.stringify(result, null, 2), raw);
core.output(result, raw);
} else {
output(formatAuditReport(result), raw);
core.output(formatAuditReport(result), raw);
}
break;
}

View File

@@ -831,8 +831,9 @@ function cmdStats(cwd, format, raw) {
const headingPattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi;
let match;
while ((match = headingPattern.exec(roadmapContent)) !== null) {
phasesByNumber.set(match[1], {
number: match[1],
const key = normalizePhaseName(match[1]);
phasesByNumber.set(key, {
number: key,
name: match[2].replace(/\(INSERTED\)/i, '').trim(),
plans: 0,
summaries: 0,
@@ -862,9 +863,10 @@ function cmdStats(cwd, format, raw) {
const status = determinePhaseStatus(plans, summaries, path.join(phasesDir, dir), 'Not Started');
const existing = phasesByNumber.get(phaseNum);
phasesByNumber.set(phaseNum, {
number: phaseNum,
const normalizedNum = normalizePhaseName(phaseNum);
const existing = phasesByNumber.get(normalizedNum);
phasesByNumber.set(normalizedNum, {
number: normalizedNum,
name: existing?.name || phaseName,
plans: (existing?.plans || 0) + plans,
summaries: (existing?.summaries || 0) + summaries,

View File

@@ -495,6 +495,17 @@ function getCmdConfigSetModelProfileResultMessage(
return paragraphs.join('\n\n');
}
/**
* Print the resolved config.json path (workstream-aware). Used by settings.md
* so the workflow writes/reads the correct file when a workstream is active (#2282).
*/
function cmdConfigPath(cwd) {
// Always emit as plain text — a file path is used via shell substitution,
// never consumed as JSON. Passing raw=true forces plain-text output.
const configPath = path.join(planningDir(cwd), 'config.json');
output(configPath, true, configPath);
}
module.exports = {
VALID_CONFIG_KEYS,
cmdConfigEnsureSection,
@@ -502,4 +513,5 @@ module.exports = {
cmdConfigGet,
cmdConfigSetModelProfile,
cmdConfigNewProject,
cmdConfigPath,
};

View File

@@ -377,6 +377,9 @@ function loadConfig(cwd) {
exa_search: get('exa_search') ?? defaults.exa_search,
tdd_mode: get('tdd_mode', { section: 'workflow', field: 'tdd_mode' }) ?? false,
text_mode: get('text_mode', { section: 'workflow', field: 'text_mode' }) ?? defaults.text_mode,
auto_advance: get('auto_advance', { section: 'workflow', field: 'auto_advance' }) ?? false,
_auto_chain_active: get('_auto_chain_active', { section: 'workflow', field: '_auto_chain_active' }) ?? false,
mode: get('mode') ?? 'interactive',
sub_repos: get('sub_repos', { section: 'planning', field: 'sub_repos' }) ?? defaults.sub_repos,
resolve_model_ids: get('resolve_model_ids') ?? defaults.resolve_model_ids,
context_window: get('context_window') ?? defaults.context_window,

View File

@@ -44,6 +44,22 @@ function withProjectRoot(cwd, result) {
if (config.response_language) {
result.response_language = config.response_language;
}
// Inject project identity into all init outputs so handoff blocks
// can include project context for cross-session continuity.
if (config.project_code) {
result.project_code = config.project_code;
}
// Extract project title from PROJECT.md first H1 heading.
const projectMdPath = path.join(planningDir(cwd), 'PROJECT.md');
try {
if (fs.existsSync(projectMdPath)) {
const content = fs.readFileSync(projectMdPath, 'utf8');
const h1Match = content.match(/^#\s+(.+)$/m);
if (h1Match) {
result.project_title = h1Match[1].trim();
}
}
} catch { /* intentionally empty */ }
return result;
}
@@ -238,6 +254,12 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
nyquist_validation_enabled: config.nyquist_validation,
commit_docs: config.commit_docs,
text_mode: config.text_mode,
// Auto-advance config — included so workflows don't need separate config-get
// calls for these values, which causes infinite config-read loops on some models
// (e.g. Kimi K2.5). See #2192.
auto_advance: !!(config.auto_advance),
auto_chain_active: !!(config._auto_chain_active),
mode: config.mode || 'interactive',
// Phase info
phase_found: !!phaseInfo,
@@ -1024,6 +1046,17 @@ function cmdInitManager(cwd, raw) {
// Dependency satisfaction: check if all depends_on phases are complete
const completedNums = new Set(phases.filter(p => p.disk_status === 'complete').map(p => p.number));
// Also include phases from previously shipped milestones — they are all
// complete by definition (a milestone only ships when all phases are done).
// rawContent is the full ROADMAP.md (including <details>-wrapped shipped
// milestone sections that extractCurrentMilestone strips out).
const _allCompletedPattern = /-\s*\[x\]\s*.*Phase\s+(\d+[A-Z]?(?:\.\d+)*)[:\s]/gi;
let _allMatch;
while ((_allMatch = _allCompletedPattern.exec(rawContent)) !== null) {
completedNums.add(_allMatch[1]);
}
for (const phase of phases) {
if (!phase.depends_on || /^none$/i.test(phase.depends_on.trim())) {
phase.deps_satisfied = true;
@@ -1590,75 +1623,207 @@ function cmdAgentSkills(cwd, agentType, raw) {
/**
* Generate a skill manifest from a skills directory.
*
* Scans the given skills directory for subdirectories containing SKILL.md,
* extracts frontmatter (name, description) and trigger conditions from the
* body text, and returns an array of skill descriptors.
* Scans the canonical skill discovery roots and returns a normalized
* inventory object with discovered skills, root metadata, and installation
* summary flags. A legacy `skillsDir` override is still accepted for focused
* scans, but the default mode is multi-root discovery.
*
* @param {string} skillsDir - Absolute path to the skills directory
* @returns {Array<{name: string, description: string, triggers: string[], path: string}>}
* @param {string} cwd - Project root directory
* @param {string|null} [skillsDir] - Optional absolute path to a specific skills directory
* @returns {{
* skills: Array<{name: string, description: string, triggers: string[], path: string, file_path: string, root: string, scope: string, installed: boolean, deprecated: boolean}>,
* roots: Array<{root: string, path: string, scope: string, present: boolean, skill_count?: number, command_count?: number, deprecated?: boolean}>,
* installation: { gsd_skills_installed: boolean, legacy_claude_commands_installed: boolean },
* counts: { skills: number, roots: number }
* }}
*/
function buildSkillManifest(skillsDir) {
function buildSkillManifest(cwd, skillsDir = null) {
const { extractFrontmatter } = require('./frontmatter.cjs');
const os = require('os');
if (!fs.existsSync(skillsDir)) return [];
const canonicalRoots = skillsDir ? [{
root: path.resolve(skillsDir),
path: path.resolve(skillsDir),
scope: 'custom',
present: fs.existsSync(skillsDir),
kind: 'skills',
}] : [
{
root: '.claude/skills',
path: path.join(cwd, '.claude', 'skills'),
scope: 'project',
kind: 'skills',
},
{
root: '.agents/skills',
path: path.join(cwd, '.agents', 'skills'),
scope: 'project',
kind: 'skills',
},
{
root: '.cursor/skills',
path: path.join(cwd, '.cursor', 'skills'),
scope: 'project',
kind: 'skills',
},
{
root: '.github/skills',
path: path.join(cwd, '.github', 'skills'),
scope: 'project',
kind: 'skills',
},
{
root: '.codex/skills',
path: path.join(cwd, '.codex', 'skills'),
scope: 'project',
kind: 'skills',
},
{
root: '~/.claude/skills',
path: path.join(os.homedir(), '.claude', 'skills'),
scope: 'global',
kind: 'skills',
},
{
root: '~/.codex/skills',
path: path.join(os.homedir(), '.codex', 'skills'),
scope: 'global',
kind: 'skills',
},
{
root: '.claude/get-shit-done/skills',
path: path.join(os.homedir(), '.claude', 'get-shit-done', 'skills'),
scope: 'import-only',
kind: 'skills',
deprecated: true,
},
{
root: '.claude/commands/gsd',
path: path.join(os.homedir(), '.claude', 'commands', 'gsd'),
scope: 'legacy-commands',
kind: 'commands',
deprecated: true,
},
];
let entries;
try {
entries = fs.readdirSync(skillsDir, { withFileTypes: true });
} catch {
return [];
}
const skills = [];
const roots = [];
let legacyClaudeCommandsInstalled = false;
for (const rootInfo of canonicalRoots) {
const rootPath = rootInfo.path;
const rootSummary = {
root: rootInfo.root,
path: rootPath,
scope: rootInfo.scope,
present: fs.existsSync(rootPath),
deprecated: !!rootInfo.deprecated,
};
const manifest = [];
for (const entry of entries) {
if (!entry.isDirectory()) continue;
const skillMdPath = path.join(skillsDir, entry.name, 'SKILL.md');
if (!fs.existsSync(skillMdPath)) continue;
let content;
try {
content = fs.readFileSync(skillMdPath, 'utf-8');
} catch {
if (!rootSummary.present) {
roots.push(rootSummary);
continue;
}
const frontmatter = extractFrontmatter(content);
const name = frontmatter.name || entry.name;
const description = frontmatter.description || '';
// Extract trigger lines from body text (after frontmatter)
const triggers = [];
const bodyMatch = content.match(/^---[\s\S]*?---\s*\n([\s\S]*)$/);
if (bodyMatch) {
const body = bodyMatch[1];
const triggerLines = body.match(/^TRIGGER\s+when:\s*(.+)$/gmi);
if (triggerLines) {
for (const line of triggerLines) {
const m = line.match(/^TRIGGER\s+when:\s*(.+)$/i);
if (m) triggers.push(m[1].trim());
}
if (rootInfo.kind === 'commands') {
let entries = [];
try {
entries = fs.readdirSync(rootPath, { withFileTypes: true });
} catch {
roots.push(rootSummary);
continue;
}
const commandFiles = entries.filter(entry => entry.isFile() && entry.name.endsWith('.md'));
rootSummary.command_count = commandFiles.length;
if (rootSummary.command_count > 0) legacyClaudeCommandsInstalled = true;
roots.push(rootSummary);
continue;
}
manifest.push({
name,
description,
triggers,
path: entry.name,
});
let entries;
try {
entries = fs.readdirSync(rootPath, { withFileTypes: true });
} catch {
roots.push(rootSummary);
continue;
}
let skillCount = 0;
for (const entry of entries) {
if (!entry.isDirectory()) continue;
const skillMdPath = path.join(rootPath, entry.name, 'SKILL.md');
if (!fs.existsSync(skillMdPath)) continue;
let content;
try {
content = fs.readFileSync(skillMdPath, 'utf-8');
} catch {
continue;
}
const frontmatter = extractFrontmatter(content);
const name = frontmatter.name || entry.name;
const description = frontmatter.description || '';
// Extract trigger lines from body text (after frontmatter)
const triggers = [];
const bodyMatch = content.match(/^---[\s\S]*?---\s*\n([\s\S]*)$/);
if (bodyMatch) {
const body = bodyMatch[1];
const triggerLines = body.match(/^TRIGGER\s+when:\s*(.+)$/gmi);
if (triggerLines) {
for (const line of triggerLines) {
const m = line.match(/^TRIGGER\s+when:\s*(.+)$/i);
if (m) triggers.push(m[1].trim());
}
}
}
skills.push({
name,
description,
triggers,
path: entry.name,
file_path: `${entry.name}/SKILL.md`,
root: rootInfo.root,
scope: rootInfo.scope,
installed: rootInfo.scope !== 'import-only',
deprecated: !!rootInfo.deprecated,
});
skillCount++;
}
rootSummary.skill_count = skillCount;
roots.push(rootSummary);
}
// Sort by name for deterministic output
manifest.sort((a, b) => a.name.localeCompare(b.name));
return manifest;
skills.sort((a, b) => {
const rootCmp = a.root.localeCompare(b.root);
return rootCmp !== 0 ? rootCmp : a.name.localeCompare(b.name);
});
const gsdSkillsInstalled = skills.some(skill => skill.name.startsWith('gsd-'));
return {
skills,
roots,
installation: {
gsd_skills_installed: gsdSkillsInstalled,
legacy_claude_commands_installed: legacyClaudeCommandsInstalled,
},
counts: {
skills: skills.length,
roots: roots.length,
},
};
}
/**
* Command: generate skill manifest JSON.
*
* Options:
* --skills-dir <path> Path to skills directory (required)
* --skills-dir <path> Optional absolute path to a single skills directory
* --write Also write to .planning/skill-manifest.json
*/
function cmdSkillManifest(cwd, args, raw) {
@@ -1667,12 +1832,7 @@ function cmdSkillManifest(cwd, args, raw) {
? args[skillsDirIdx + 1]
: null;
if (!skillsDir) {
output([], raw);
return;
}
const manifest = buildSkillManifest(skillsDir);
const manifest = buildSkillManifest(cwd, skillsDir);
// Optionally write to .planning/skill-manifest.json
if (args.includes('--write')) {

View File

@@ -19,10 +19,10 @@ const crypto = require('crypto');
const INTEL_DIR = '.planning/intel';
const INTEL_FILES = {
files: 'files.json',
apis: 'apis.json',
deps: 'deps.json',
arch: 'arch.md',
files: 'file-roles.json',
apis: 'api-map.json',
deps: 'dependency-graph.json',
arch: 'arch-decisions.json',
stack: 'stack.json'
};
@@ -204,10 +204,8 @@ function intelQuery(term, planningDir) {
const matches = [];
let total = 0;
// Search JSON intel files
// Search all JSON intel files
for (const [_key, filename] of Object.entries(INTEL_FILES)) {
if (filename.endsWith('.md')) continue; // Skip arch.md here
const filePath = intelFilePath(planningDir, filename);
const data = safeReadJson(filePath);
if (!data) continue;
@@ -219,14 +217,6 @@ function intelQuery(term, planningDir) {
}
}
// Search arch.md
const archPath = intelFilePath(planningDir, INTEL_FILES.arch);
const archMatches = searchArchMd(archPath, term);
if (archMatches.length > 0) {
matches.push({ source: INTEL_FILES.arch, entries: archMatches });
total += archMatches.length;
}
return { matches, term, total };
}
@@ -257,20 +247,10 @@ function intelStatus(planningDir) {
let updatedAt = null;
if (filename.endsWith('.md')) {
// For arch.md, use file mtime
try {
const stat = fs.statSync(filePath);
updatedAt = stat.mtime.toISOString();
} catch (_e) {
// intentionally silent: fall through on error
}
} else {
// For JSON files, read _meta.updated_at
const data = safeReadJson(filePath);
if (data && data._meta && data._meta.updated_at) {
updatedAt = data._meta.updated_at;
}
// All intel files are JSON — read _meta.updated_at
const data = safeReadJson(filePath);
if (data && data._meta && data._meta.updated_at) {
updatedAt = data._meta.updated_at;
}
let stale = true;
@@ -409,8 +389,7 @@ function intelValidate(planningDir) {
continue;
}
// Skip non-JSON files (arch.md)
if (filename.endsWith('.md')) continue;
// All intel files are JSON — validate _meta and entries structure
// Parse JSON
let data;

View File

@@ -585,10 +585,12 @@ function cmdPhaseInsert(cwd, afterPhase, description, raw) {
*/
function renameDecimalPhases(phasesDir, baseInt, removedDecimal) {
const renamedDirs = [], renamedFiles = [];
const decPattern = new RegExp(`^${baseInt}\\.(\\d+)-(.+)$`);
// Capture the zero-padded prefix (e.g. "06" from "06.3-slug") so the renamed
// directory preserves the original padding format.
const decPattern = new RegExp(`^(0*${baseInt})\\.(\\d+)-(.+)$`);
const dirs = readSubdirectories(phasesDir, true);
const toRename = dirs
.map(dir => { const m = dir.match(decPattern); return m ? { dir, oldDecimal: parseInt(m[1], 10), slug: m[2] } : null; })
.map(dir => { const m = dir.match(decPattern); return m ? { dir, prefix: m[1], oldDecimal: parseInt(m[2], 10), slug: m[3] } : null; })
.filter(item => item && item.oldDecimal > removedDecimal)
.sort((a, b) => b.oldDecimal - a.oldDecimal); // descending to avoid conflicts
@@ -596,7 +598,7 @@ function renameDecimalPhases(phasesDir, baseInt, removedDecimal) {
const newDecimal = item.oldDecimal - 1;
const oldPhaseId = `${baseInt}.${item.oldDecimal}`;
const newPhaseId = `${baseInt}.${newDecimal}`;
const newDirName = `${baseInt}.${newDecimal}-${item.slug}`;
const newDirName = `${item.prefix}.${newDecimal}-${item.slug}`;
fs.renameSync(path.join(phasesDir, item.dir), path.join(phasesDir, newDirName));
renamedDirs.push({ from: item.dir, to: newDirName });
for (const f of fs.readdirSync(path.join(phasesDir, newDirName))) {
@@ -712,7 +714,7 @@ function cmdPhaseRemove(cwd, targetPhase, options, raw) {
let renamedDirs = [], renamedFiles = [];
try {
const renamed = isDecimal
? renameDecimalPhases(phasesDir, normalized.split('.')[0], parseInt(normalized.split('.')[1], 10))
? renameDecimalPhases(phasesDir, parseInt(normalized.split('.')[0], 10), parseInt(normalized.split('.')[1], 10))
: renameIntegerPhases(phasesDir, parseInt(normalized, 10));
renamedDirs = renamed.renamedDirs;
renamedFiles = renamed.renamedFiles;

View File

@@ -177,11 +177,11 @@ const CLAUDE_MD_FALLBACKS = {
stack: 'Technology stack not yet documented. Will populate after codebase mapping or first phase.',
conventions: 'Conventions not yet established. Will populate as patterns emerge during development.',
architecture: 'Architecture not yet mapped. Follow existing patterns found in the codebase.',
skills: 'No project skills found. Add skills to any of: `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, or `.github/skills/` with a `SKILL.md` index file.',
skills: 'No project skills found. Add skills to any of: `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, `.github/skills/`, or `.codex/skills/` with a `SKILL.md` index file.',
};
// Directories where project skills may live (checked in order)
const SKILL_SEARCH_DIRS = ['.claude/skills', '.agents/skills', '.cursor/skills', '.github/skills'];
const SKILL_SEARCH_DIRS = ['.claude/skills', '.agents/skills', '.cursor/skills', '.github/skills', '.codex/skills'];
const CLAUDE_MD_WORKFLOW_ENFORCEMENT = [
'Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.',

View File

@@ -181,7 +181,8 @@ function buildCheckpoint(currentTest) {
function parseUatItems(content) {
const items = [];
// Match test blocks: ### N. Name\nexpected: ...\nresult: ...\n
const testPattern = /###\s*(\d+)\.\s*([^\n]+)\nexpected:\s*([^\n]+)\nresult:\s*(\w+)(?:\n(?:reported|reason|blocked_by):\s*[^\n]*)?/g;
// Accept both bare (result: pending) and bracketed (result: [pending]) formats (#2273)
const testPattern = /###\s*(\d+)\.\s*([^\n]+)\nexpected:\s*([^\n]+)\nresult:\s*\[?(\w+)\]?(?:\n(?:reported|reason|blocked_by):\s*[^\n]*)?/g;
let match;
while ((match = testPattern.exec(content)) !== null) {
const [, num, name, expected, result] = match;

View File

@@ -0,0 +1,277 @@
# Smart Discuss — Autonomous Mode
Smart discuss is the autonomous-optimized variant of `gsd-discuss-phase`. It proposes grey area answers in batch tables — the user accepts or overrides per area — then writes an identical CONTEXT.md to what discuss-phase produces.
**Inputs:** `PHASE_NUM` from execute_phase. Run init to get phase paths:
```bash
PHASE_STATE=$(gsd-sdk query init.phase-op ${PHASE_NUM})
```
Parse from JSON: `phase_dir`, `phase_slug`, `padded_phase`, `phase_name`.
---
## Sub-step 1: Load prior context
Read project-level and prior phase context to avoid re-asking decided questions.
**Read project files:**
```bash
cat .planning/PROJECT.md 2>/dev/null || true
cat .planning/REQUIREMENTS.md 2>/dev/null || true
cat .planning/STATE.md 2>/dev/null || true
```
Extract from these:
- **PROJECT.md** — Vision, principles, non-negotiables, user preferences
- **REQUIREMENTS.md** — Acceptance criteria, constraints, must-haves vs nice-to-haves
- **STATE.md** — Current progress, decisions logged so far
**Read all prior CONTEXT.md files:**
```bash
(find .planning/phases -name "*-CONTEXT.md" 2>/dev/null || true) | sort
```
For each CONTEXT.md where phase number < current phase:
- Read the `<decisions>` section — these are locked preferences
- Read `<specifics>` — particular references or "I want it like X" moments
- Note patterns (e.g., "user consistently prefers minimal UI", "user rejected verbose output")
**Build internal prior_decisions context** (do not write to file):
```
<prior_decisions>
## Project-Level
- [Key principle or constraint from PROJECT.md]
- [Requirement affecting this phase from REQUIREMENTS.md]
## From Prior Phases
### Phase N: [Name]
- [Decision relevant to current phase]
- [Preference that establishes a pattern]
</prior_decisions>
```
If no prior context exists, continue without — expected for early phases.
---
## Sub-step 2: Scout Codebase
Lightweight codebase scan to inform grey area identification and proposals. Keep under ~5% context.
**Check for existing codebase maps:**
```bash
ls .planning/codebase/*.md 2>/dev/null || true
```
**If codebase maps exist:** Read the most relevant ones (CONVENTIONS.md, STRUCTURE.md, STACK.md based on phase type). Extract reusable components, established patterns, integration points. Skip to building context below.
**If no codebase maps, do targeted grep:**
Extract key terms from the phase goal. Search for related files:
```bash
grep -rl "{term1}\|{term2}" src/ app/ --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | head -10 || true
ls src/components/ src/hooks/ src/lib/ src/utils/ 2>/dev/null || true
```
Read the 3-5 most relevant files to understand existing patterns.
**Build internal codebase_context** (do not write to file):
- **Reusable assets** — existing components, hooks, utilities usable in this phase
- **Established patterns** — how the codebase does state management, styling, data fetching
- **Integration points** — where new code connects (routes, nav, providers)
---
## Sub-step 3: Analyze Phase and Generate Proposals
**Get phase details:**
```bash
DETAIL=$(gsd-sdk query roadmap.get-phase ${PHASE_NUM})
```
Extract `goal`, `requirements`, `success_criteria` from the JSON response.
**Infrastructure detection — check FIRST before generating grey areas:**
A phase is pure infrastructure when ALL of these are true:
1. Goal keywords match: "scaffolding", "plumbing", "setup", "configuration", "migration", "refactor", "rename", "restructure", "upgrade", "infrastructure"
2. AND success criteria are all technical: "file exists", "test passes", "config valid", "command runs"
3. AND no user-facing behavior is described (no "users can", "displays", "shows", "presents")
**If infrastructure-only:** Skip Sub-step 4. Jump directly to Sub-step 5 with minimal CONTEXT.md. Display:
```
Phase ${PHASE_NUM}: Infrastructure phase — skipping discuss, writing minimal context.
```
Use these defaults for the CONTEXT.md:
- `<domain>`: Phase boundary from ROADMAP goal
- `<decisions>`: Single "### Claude's Discretion" subsection — "All implementation choices are at Claude's discretion — pure infrastructure phase"
- `<code_context>`: Whatever the codebase scout found
- `<specifics>`: "No specific requirements — infrastructure phase"
- `<deferred>`: "None"
**If NOT infrastructure — generate grey area proposals:**
Determine domain type from the phase goal:
- Something users **SEE** → visual: layout, interactions, states, density
- Something users **CALL** → interface: contracts, responses, errors, auth
- Something users **RUN** → execution: invocation, output, behavior modes, flags
- Something users **READ** → content: structure, tone, depth, flow
- Something being **ORGANIZED** → organization: criteria, grouping, exceptions, naming
Check prior_decisions — skip grey areas already decided in prior phases.
Generate **3-4 grey areas** with **~4 questions each**. For each question:
- **Pre-select a recommended answer** based on: prior decisions (consistency), codebase patterns (reuse), domain conventions (standard approaches), ROADMAP success criteria
- Generate **1-2 alternatives** per question
- **Annotate** with prior decision context ("You decided X in Phase N") and code context ("Component Y exists with Z variants") where relevant
---
## Sub-step 4: Present Proposals Per Area
Present grey areas **one at a time**. For each area (M of N):
Display a table:
```
### Grey Area {M}/{N}: {Area Name}
| # | Question | ✅ Recommended | Alternative(s) |
|---|----------|---------------|-----------------|
| 1 | {question} | {answer} — {rationale} | {alt1}; {alt2} |
| 2 | {question} | {answer} — {rationale} | {alt1} |
| 3 | {question} | {answer} — {rationale} | {alt1}; {alt2} |
| 4 | {question} | {answer} — {rationale} | {alt1} |
```
Then prompt the user via **AskUserQuestion**:
- **header:** "Area {M}/{N}"
- **question:** "Accept these answers for {Area Name}?"
- **options:** Build dynamically — always "Accept all" first, then "Change Q1" through "Change QN" for each question (up to 4), then "Discuss deeper" last. Cap at 6 explicit options max (AskUserQuestion adds "Other" automatically).
**On "Accept all":** Record all recommended answers for this area. Move to next area.
**On "Change QN":** Use AskUserQuestion with the alternatives for that specific question:
- **header:** "{Area Name}"
- **question:** "Q{N}: {question text}"
- **options:** List the 1-2 alternatives plus "You decide" (maps to Claude's Discretion)
Record the user's choice. Re-display the updated table with the change reflected. Re-present the full acceptance prompt so the user can make additional changes or accept.
**On "Discuss deeper":** Switch to interactive mode for this area only — ask questions one at a time using AskUserQuestion with 2-3 concrete options per question plus "You decide". After 4 questions, prompt:
- **header:** "{Area Name}"
- **question:** "More questions about {area name}, or move to next?"
- **options:** "More questions" / "Next area"
If "More questions", ask 4 more. If "Next area", display final summary table of captured answers for this area and move on.
**On "Other" (free text):** Interpret as either a specific change request or general feedback. Incorporate into the area's decisions, re-display updated table, re-present acceptance prompt.
**Scope creep handling:** If user mentions something outside the phase domain:
```
"{Feature} sounds like a new capability — that belongs in its own phase.
I'll note it as a deferred idea.
Back to {current area}: {return to current question}"
```
Track deferred ideas internally for inclusion in CONTEXT.md.
---
## Sub-step 5: Write CONTEXT.md
After all areas are resolved (or infrastructure skip), write the CONTEXT.md file.
**File path:** `${phase_dir}/${padded_phase}-CONTEXT.md`
Use **exactly** this structure (identical to discuss-phase output):
```markdown
# Phase {PHASE_NUM}: {Phase Name} - Context
**Gathered:** {date}
**Status:** Ready for planning
<domain>
## Phase Boundary
{Domain boundary statement from analysis — what this phase delivers}
</domain>
<decisions>
## Implementation Decisions
### {Area 1 Name}
- {Accepted/chosen answer for Q1}
- {Accepted/chosen answer for Q2}
- {Accepted/chosen answer for Q3}
- {Accepted/chosen answer for Q4}
### {Area 2 Name}
- {Accepted/chosen answer for Q1}
- {Accepted/chosen answer for Q2}
...
### Claude's Discretion
{Any "You decide" answers collected — note Claude has flexibility here}
</decisions>
<code_context>
## Existing Code Insights
### Reusable Assets
- {From codebase scout — components, hooks, utilities}
### Established Patterns
- {From codebase scout — state management, styling, data fetching}
### Integration Points
- {From codebase scout — where new code connects}
</code_context>
<specifics>
## Specific Ideas
{Any specific references or "I want it like X" from discussion}
{If none: "No specific requirements — open to standard approaches"}
</specifics>
<deferred>
## Deferred Ideas
{Ideas captured but out of scope for this phase}
{If none: "None — discussion stayed within phase scope"}
</deferred>
```
Write the file.
**Commit:**
```bash
gsd-sdk query commit "docs(${PADDED_PHASE}): smart discuss context" "${phase_dir}/${padded_phase}-CONTEXT.md"
```
Display confirmation:
```
Created: {path}
Decisions captured: {count} across {area_count} areas
```

View File

@@ -7,7 +7,7 @@ Standard format for presenting next steps after completing a command or workflow
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**{identifier}: {name}** — {one-line description}
@@ -24,6 +24,9 @@ Standard format for presenting next steps after completing a command or workflow
---
```
> If `project_code` is not set in the init context, omit the project identity suffix:
> `## ▶ Next Up` (no ` — [CODE] Title`).
## Format Rules
1. **Always show what it is** — name + description, never just a command path
@@ -32,6 +35,7 @@ Standard format for presenting next steps after completing a command or workflow
4. **`/clear` first** — always show `/clear` before the command so users run it in the correct order
5. **"Also available" not "Other options"** — sounds more app-like
6. **Visual separators**`---` above and below to make it stand out
7. **Project identity in heading** — include `[PROJECT_CODE] PROJECT_TITLE` from init context so handoffs are self-identifying across sessions. If `project_code` is not set, omit the suffix entirely (just `## ▶ Next Up`)
## Variants
@@ -40,7 +44,7 @@ Standard format for presenting next steps after completing a command or workflow
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry
@@ -64,7 +68,7 @@ Add note that this is the last plan and what comes after:
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**02-03: Refresh Token Rotation** — Add /api/auth/refresh with sliding expiry
<sub>Final plan in Phase 2</sub>
@@ -87,7 +91,7 @@ Add note that this is the last plan and what comes after:
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase 2: Authentication** — JWT login flow with refresh tokens
@@ -116,7 +120,7 @@ Show completion status before next action:
3/3 plans executed
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase 3: Core Features** — User dashboard, settings, and data export
@@ -141,7 +145,7 @@ When there's no clear primary action:
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase 3: Core Features** — User dashboard, settings, and data export
@@ -165,7 +169,7 @@ When there's no clear primary action:
All 4 phases shipped
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Start v1.1** — questioning → research → requirements → roadmap

View File

@@ -6,7 +6,7 @@ Calculate the next decimal phase number for urgent insertions.
```bash
# Get next decimal phase after phase 6
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase next-decimal 6
gsd-sdk query phase.next-decimal 6
```
Output:
@@ -32,13 +32,13 @@ With existing decimals:
## Extract Values
```bash
DECIMAL_PHASE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase next-decimal "${AFTER_PHASE}" --pick next)
BASE_PHASE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase next-decimal "${AFTER_PHASE}" --pick base_phase)
DECIMAL_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --pick next)
BASE_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --pick base_phase)
```
Or with --raw flag:
```bash
DECIMAL_PHASE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase next-decimal "${AFTER_PHASE}" --raw)
DECIMAL_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --raw)
# Returns just: 06.1
```
@@ -56,7 +56,7 @@ DECIMAL_PHASE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase next-
Decimal phase directories use the full decimal number:
```bash
SLUG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" generate-slug "$DESCRIPTION" --raw)
SLUG=$(gsd-sdk query generate-slug "$DESCRIPTION" --raw)
PHASE_DIR=".planning/phases/${DECIMAL_PHASE}-${SLUG}"
mkdir -p "$PHASE_DIR"
```

View File

@@ -51,7 +51,7 @@ Phases:
What to commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: initialize [project-name] ([N] phases)" --files .planning/
gsd-sdk query commit "docs: initialize [project-name] ([N] phases)" .planning/
```
</format>
@@ -133,7 +133,7 @@ SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
What to commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md
gsd-sdk query commit "docs({phase}-{plan}): complete [plan-name] plan" .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md
```
**Note:** Code files NOT included - already committed per-task.
@@ -153,7 +153,7 @@ Current: [task name]
What to commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/
gsd-sdk query commit "wip: [phase-name] paused at task [X]/[Y]" .planning/
```
</format>
@@ -284,7 +284,7 @@ Set `commit_docs: false` so planning docs stay local and are not committed to an
Instead of the standard `commit` command, use `commit-to-subrepo` when `sub_repos` is configured:
```bash
node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit-to-subrepo "feat(02-01): add user API" \
gsd-sdk query commit-to-subrepo "feat(02-01): add user API" \
--files backend/src/api/users.ts backend/src/types/user.ts frontend/src/components/UserForm.tsx
```

View File

@@ -1,13 +1,15 @@
# Git Planning Commit
Commit planning artifacts using the gsd-tools CLI, which automatically checks `commit_docs` config and gitignore status.
Commit planning artifacts via `gsd-sdk query commit`, which checks `commit_docs` config and gitignore status (same behavior as legacy `gsd-tools.cjs commit`).
## Commit via CLI
Always use `gsd-tools.cjs commit` for `.planning/` files — it handles `commit_docs` and gitignore checks automatically:
Pass the message first, then file paths (positional). Do not use `--files` for `commit` (that flag is only for `commit-to-subrepo`).
Always use this for `.planning/` files — it handles `commit_docs` and gitignore checks automatically:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({scope}): {description}" --files .planning/STATE.md .planning/ROADMAP.md
gsd-sdk query commit "docs({scope}): {description}" .planning/STATE.md .planning/ROADMAP.md
```
The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.planning/` is gitignored. No manual conditional checks needed.
@@ -17,7 +19,7 @@ The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.pla
To fold `.planning/` file changes into the previous commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "" --files .planning/codebase/*.md --amend
gsd-sdk query commit "" .planning/codebase/*.md --amend
```
## Commit Message Patterns

View File

@@ -14,7 +14,7 @@ From `$ARGUMENTS`:
The `find-phase` command handles normalization and validation in one step:
```bash
PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" find-phase "${PHASE}")
PHASE_INFO=$(gsd-sdk query find-phase "${PHASE}")
```
Returns JSON with:
@@ -45,7 +45,7 @@ fi
Use `roadmap get-phase` to validate phase exists:
```bash
PHASE_CHECK=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}" --pick found)
PHASE_CHECK=$(gsd-sdk query roadmap.get-phase "${PHASE}" --pick found)
if [ "$PHASE_CHECK" = "false" ]; then
echo "ERROR: Phase ${PHASE} not found in roadmap"
exit 1
@@ -57,5 +57,5 @@ fi
Use `find-phase` for directory lookup:
```bash
PHASE_DIR=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" find-phase "${PHASE}" --raw)
PHASE_DIR=$(gsd-sdk query find-phase "${PHASE}" --raw)
```

View File

@@ -55,7 +55,7 @@ Group by plan, dimension, severity.
### Step 6: Commit
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "fix($PHASE): revise plans based on checker feedback" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
gsd-sdk query commit "fix($PHASE): revise plans based on checker feedback" .planning/phases/$PHASE-*/$PHASE-*-PLAN.md
```
### Step 7: Return Revision Summary

View File

@@ -58,15 +58,15 @@ Configuration options for `.planning/` directory behavior.
```bash
# Commit with automatic commit_docs + gitignore checks:
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: update state" --files .planning/STATE.md
gsd-sdk query commit "docs: update state" .planning/STATE.md
# Load config via state load (returns JSON):
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
INIT=$(gsd-sdk query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# commit_docs is available in the JSON output
# Or use init commands which include commit_docs:
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "1")
INIT=$(gsd-sdk query init.execute-phase "1")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# commit_docs is included in all init command outputs
```
@@ -76,7 +76,7 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
**Commit via CLI (handles checks automatically):**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: update state" --files .planning/STATE.md
gsd-sdk query commit "docs: update state" .planning/STATE.md
```
The CLI checks `commit_docs` config and gitignore status internally — no manual conditionals needed.
@@ -164,14 +164,14 @@ To use uncommitted mode:
Use `init execute-phase` which returns all config as JSON:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "1")
INIT=$(gsd-sdk query init.execute-phase "1")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# JSON output includes: branching_strategy, phase_branch_template, milestone_branch_template
```
Or use `state load` for the config values:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
INIT=$(gsd-sdk query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# Parse branching_strategy, phase_branch_template, milestone_branch_template from JSON
```

View File

@@ -93,19 +93,19 @@ This ensures workstream scope chains automatically through the workflow:
## CLI Usage
```bash
# All gsd-tools commands accept --ws
node gsd-tools.cjs state json --ws feature-a
node gsd-tools.cjs find-phase 3 --ws feature-b
# All gsd-sdk query commands accept --ws
gsd-sdk query state.json --ws feature-a
gsd-sdk query find-phase 3 --ws feature-b
# Session-local switching without --ws on every command
GSD_SESSION_KEY=my-terminal-a node gsd-tools.cjs workstream set feature-a
GSD_SESSION_KEY=my-terminal-a node gsd-tools.cjs state json
GSD_SESSION_KEY=my-terminal-b node gsd-tools.cjs workstream set feature-b
GSD_SESSION_KEY=my-terminal-b node gsd-tools.cjs state json
GSD_SESSION_KEY=my-terminal-a gsd-sdk query workstream.set feature-a
GSD_SESSION_KEY=my-terminal-a gsd-sdk query state.json
GSD_SESSION_KEY=my-terminal-b gsd-sdk query workstream.set feature-b
GSD_SESSION_KEY=my-terminal-b gsd-sdk query state.json
# Workstream CRUD
node gsd-tools.cjs workstream create <name>
node gsd-tools.cjs workstream list
node gsd-tools.cjs workstream status <name>
node gsd-tools.cjs workstream complete <name>
gsd-sdk query workstream.create <name>
gsd-sdk query workstream.list
gsd-sdk query workstream.status <name>
gsd-sdk query workstream.complete <name>
```

View File

@@ -29,7 +29,7 @@ Exit.
Load phase operation context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "0")
INIT=$(gsd-sdk query init.phase-op "0")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -42,10 +42,10 @@ Exit.
</step>
<step name="add_phase">
**Delegate the phase addition to gsd-tools:**
**Delegate the phase addition to `gsd-sdk query phase.add`:**
```bash
RESULT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase add "${description}")
RESULT=$(gsd-sdk query phase.add "${description}")
```
The CLI handles:
@@ -83,7 +83,7 @@ Roadmap updated: .planning/ROADMAP.md
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase {N}: {description}**
@@ -104,7 +104,7 @@ Roadmap updated: .planning/ROADMAP.md
</process>
<success_criteria>
- [ ] `gsd-tools phase add` executed successfully
- [ ] `gsd-sdk query phase.add` executed successfully
- [ ] Phase directory created
- [ ] Roadmap updated with new phase entry
- [ ] STATE.md updated with roadmap evolution note

View File

@@ -33,7 +33,7 @@ Exit.
Load phase operation context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
INIT=$(gsd-sdk query init.phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -300,7 +300,7 @@ Create a test coverage report and present to user:
Record test generation in project state:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state-snapshot
gsd-sdk query state-snapshot
```
If there are passing tests to commit:
@@ -315,7 +315,7 @@ Present next steps:
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
{if bugs discovered:}
**Fix discovered bugs:** `/gsd-quick fix the {N} test failures discovered in phase ${phase_number}`

View File

@@ -12,7 +12,7 @@ Read all files referenced by the invoking prompt's execution_context before star
Load todo context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init todos)
INIT=$(gsd-sdk query init.todos)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -86,7 +86,7 @@ Use values from init context: `timestamp` and `date` are already available.
Generate slug for the title:
```bash
slug=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" generate-slug "$title" --raw)
slug=$(gsd-sdk query generate-slug "$title" --raw)
```
Write to `.planning/todos/pending/${date}-${slug}.md`:
@@ -121,7 +121,7 @@ If `.planning/STATE.md` exists:
Commit the todo and any updated state:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: capture todo - [title]" --files .planning/todos/pending/[filename] .planning/STATE.md
gsd-sdk query commit "docs: capture todo - [title]" .planning/todos/pending/[filename] .planning/STATE.md
```
Tool respects `commit_docs` config and gitignore automatically.

View File

@@ -20,7 +20,7 @@ This prevents the two most common AI development failures: choosing the wrong fr
## 1. Initialize
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init plan-phase "$PHASE")
INIT=$(gsd-sdk query init.plan-phase "$PHASE")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -30,15 +30,15 @@ Parse JSON for: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded
Resolve agent models:
```bash
SELECTOR_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-framework-selector --raw)
RESEARCHER_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-ai-researcher --raw)
DOMAIN_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-domain-researcher --raw)
PLANNER_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-eval-planner --raw)
SELECTOR_MODEL=$(gsd-sdk query resolve-model gsd-framework-selector 2>/dev/null | jq -r '.model' 2>/dev/null || true)
RESEARCHER_MODEL=$(gsd-sdk query resolve-model gsd-ai-researcher 2>/dev/null | jq -r '.model' 2>/dev/null || true)
DOMAIN_MODEL=$(gsd-sdk query resolve-model gsd-domain-researcher 2>/dev/null | jq -r '.model' 2>/dev/null || true)
PLANNER_MODEL=$(gsd-sdk query resolve-model gsd-eval-planner 2>/dev/null | jq -r '.model' 2>/dev/null || true)
```
Check config:
```bash
AI_PHASE_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ai_integration_phase 2>/dev/null || echo "true")
AI_PHASE_ENABLED=$(gsd-sdk query config-get workflow.ai_integration_phase 2>/dev/null || echo "true")
```
**If `AI_PHASE_ENABLED` is `false`:**
@@ -54,7 +54,7 @@ Exit workflow.
Extract phase number from $ARGUMENTS. If not provided, detect next unplanned phase.
```bash
PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}")
PHASE_INFO=$(gsd-sdk query roadmap.get-phase "${PHASE}")
```
**If `found` is false:** Error with available phases.

View File

@@ -32,7 +32,7 @@ Invoke the source audit command and capture output.
For `audit-uat` source:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init audit-uat 2>/dev/null || echo "{}")
INIT=$(gsd-sdk query audit-uat 2>/dev/null || echo "{}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```

View File

@@ -16,23 +16,23 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
## 0. Initialize Milestone Context
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init milestone-op)
INIT=$(gsd-sdk query init.milestone-op)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_CHECKER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-integration-checker 2>/dev/null)
AGENT_SKILLS_CHECKER=$(gsd-sdk query agent-skills gsd-integration-checker 2>/dev/null)
```
Extract from init JSON: `milestone_version`, `milestone_name`, `phase_count`, `completed_phases`, `commit_docs`.
Resolve integration checker model:
```bash
integration_checker_model=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-integration-checker --raw)
integration_checker_model=$(gsd-sdk query resolve-model gsd-integration-checker --raw)
```
## 1. Determine Milestone Scope
```bash
# Get phases in milestone (sorted numerically, handles decimals)
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phases list
gsd-sdk query phases.list
```
- Parse version from arguments or detect current from ROADMAP.md
@@ -46,7 +46,7 @@ For each phase directory, read the VERIFICATION.md:
```bash
# For each phase, use find-phase to resolve the directory (handles archived phases)
PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" find-phase 01 --raw)
PHASE_INFO=$(gsd-sdk query find-phase 01 --raw)
# Extract directory from JSON, then read VERIFICATION.md from that directory
# Repeat for each phase number from ROADMAP.md
```
@@ -113,7 +113,7 @@ For each phase's SUMMARY.md, extract `requirements-completed` from YAML frontmat
```bash
for summary in .planning/phases/*-*/*-SUMMARY.md; do
[ -e "$summary" ] || continue
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" summary-extract "$summary" --fields requirements_completed --pick requirements_completed
gsd-sdk query summary-extract "$summary" --fields requirements_completed --pick requirements_completed
done
```
@@ -141,7 +141,7 @@ For each REQ-ID, determine status using all three sources:
Skip if `workflow.nyquist_validation` is explicitly `false` (absent = enabled).
```bash
NYQUIST_CONFIG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.nyquist_validation --raw 2>/dev/null)
NYQUIST_CONFIG=$(gsd-sdk query config-get workflow.nyquist_validation --raw 2>/dev/null)
```
If `false`: skip entirely.
@@ -225,7 +225,7 @@ All requirements covered. Cross-phase integration verified. E2E flows complete.
───────────────────────────────────────────────────────────────
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Complete milestone** — archive and tag
@@ -270,7 +270,7 @@ Phases needing validation: run `/gsd-validate-phase {N}` for each flagged phase.
───────────────────────────────────────────────────────────────
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Plan gap closure** — create phases to complete milestone

View File

@@ -8,7 +8,7 @@ Cross-phase audit of all UAT and verification files. Finds every outstanding ite
Run the CLI audit:
```bash
AUDIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" audit-uat --raw)
AUDIT=$(gsd-sdk query audit-uat --raw)
```
Parse JSON for `results` array and `summary` object.

View File

@@ -48,7 +48,7 @@ When `--interactive` is set, discuss runs inline with questions (not auto-answer
Bootstrap via milestone-level init:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init milestone-op)
INIT=$(gsd-sdk query init.milestone-op)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -82,7 +82,7 @@ If `INTERACTIVE` is set, display: `Mode: Interactive (discuss inline, plan+execu
Run phase discovery:
```bash
ROADMAP=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze)
ROADMAP=$(gsd-sdk query roadmap.analyze)
```
Parse the JSON `phases` array.
@@ -141,7 +141,7 @@ Exit cleanly.
**Fetch details for each phase:**
```bash
DETAIL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase ${PHASE_NUM})
DETAIL=$(gsd-sdk query roadmap.get-phase ${PHASE_NUM})
```
Extract `phase_name`, `goal`, `success_criteria` from each. Store for use in execute_phase and transition messages.
@@ -169,7 +169,7 @@ Where N = current phase number (from the ROADMAP, e.g., 63), T = total milestone
Check if CONTEXT.md already exists for this phase:
```bash
PHASE_STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op ${PHASE_NUM})
PHASE_STATE=$(gsd-sdk query init.phase-op ${PHASE_NUM})
```
Parse `has_context` from JSON.
@@ -185,7 +185,7 @@ Proceed to 3b.
**If has_context is false:** Check if discuss is disabled via settings:
```bash
SKIP_DISCUSS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.skip_discuss 2>/dev/null || echo "false")
SKIP_DISCUSS=$(gsd-sdk query config-get workflow.skip_discuss 2>/dev/null || echo "false")
```
**If SKIP_DISCUSS is `true`:** Skip discuss entirely — the ROADMAP phase description is the spec. Display:
@@ -197,7 +197,7 @@ Phase ${PHASE_NUM}: Discuss skipped (workflow.skip_discuss=true) — using ROADM
Write a minimal CONTEXT.md so downstream plan-phase has valid input. Get phase details:
```bash
DETAIL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase ${PHASE_NUM})
DETAIL=$(gsd-sdk query roadmap.get-phase ${PHASE_NUM})
```
Extract `goal` and `requirements` from JSON. Write `${phase_dir}/${padded_phase}-CONTEXT.md` with:
@@ -249,7 +249,7 @@ None — discuss phase skipped.
Commit the minimal context:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${PADDED_PHASE}): auto-generated context (discuss skipped)" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
gsd-sdk query commit "docs(${PADDED_PHASE}): auto-generated context (discuss skipped)" "${phase_dir}/${padded_phase}-CONTEXT.md"
```
Proceed to 3b.
@@ -270,7 +270,7 @@ Skill(skill="gsd:discuss-phase", args="${PHASE_NUM}")
After discuss completes (either mode), verify context was written:
```bash
PHASE_STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op ${PHASE_NUM})
PHASE_STATE=$(gsd-sdk query init.phase-op ${PHASE_NUM})
```
Check `has_context`. If false → go to handle_blocker: "Discuss for phase ${PHASE_NUM} did not produce CONTEXT.md."
@@ -280,7 +280,7 @@ Check `has_context`. If false → go to handle_blocker: "Discuss for phase ${PHA
Check if this phase has frontend indicators and whether a UI-SPEC already exists:
```bash
PHASE_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase ${PHASE_NUM} 2>/dev/null)
PHASE_SECTION=$(gsd-sdk query roadmap.get-phase ${PHASE_NUM} 2>/dev/null)
echo "$PHASE_SECTION" | grep -iE "UI|interface|frontend|component|layout|page|screen|view|form|dashboard|widget" > /dev/null 2>&1
HAS_UI=$?
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
@@ -289,7 +289,7 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
Check if UI phase workflow is enabled:
```bash
UI_PHASE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_phase 2>/dev/null || echo "true")
UI_PHASE_CFG=$(gsd-sdk query config-get workflow.ui_phase 2>/dev/null || echo "true")
```
**If `HAS_UI` is 0 (frontend indicators found) AND `UI_SPEC_FILE` is empty (no UI-SPEC exists) AND `UI_PHASE_CFG` is not `false`:**
@@ -362,7 +362,7 @@ Auto-invoke code review and fix chain. Autonomous mode chains both review and fi
**Config gate:**
```bash
CODE_REVIEW_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review 2>/dev/null || echo "true")
CODE_REVIEW_ENABLED=$(gsd-sdk query config-get workflow.code_review 2>/dev/null || echo "true")
```
If `"false"`: display "Code review skipped (workflow.code_review=false)" and proceed to 3d.
@@ -390,7 +390,7 @@ VERIFY_STATUS=$(grep "^status:" "${PHASE_DIR}"/*-VERIFICATION.md 2>/dev/null | h
Where `PHASE_DIR` comes from the `init phase-op` call already made in step 3a. If the variable is not in scope, re-fetch:
```bash
PHASE_STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op ${PHASE_NUM})
PHASE_STATE=$(gsd-sdk query init.phase-op ${PHASE_NUM})
```
Parse `phase_dir` from the JSON.
@@ -486,7 +486,7 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
Check if UI review is enabled:
```bash
UI_REVIEW_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_review 2>/dev/null || echo "true")
UI_REVIEW_CFG=$(gsd-sdk query config-get workflow.ui_review 2>/dev/null || echo "true")
```
**If `UI_SPEC_FILE` is not empty AND `UI_REVIEW_CFG` is not `false`:**
@@ -511,283 +511,13 @@ Display the review result summary (score from UI-REVIEW.md if produced). Continu
## Smart Discuss
Run smart discuss for the current phase. Proposes grey area answers in batch tables — the user accepts or overrides per area. Produces identical CONTEXT.md output to regular discuss-phase.
> Full instructions are in `get-shit-done/references/autonomous-smart-discuss.md`. Read that file now and follow it exactly.
> **Note:** Smart discuss is an autonomous-optimized variant of the `gsd-discuss-phase` skill. It produces identical CONTEXT.md output but uses batch table proposals instead of sequential questioning. The original `gsd-discuss-phase` skill remains unchanged (per CTRL-03). Future milestones may extract this to a separate skill file.
Smart discuss is an autonomous-optimized variant of `gsd-discuss-phase`. It proposes grey area answers in batch tables — the user accepts or overrides per area — and writes an identical CONTEXT.md to what discuss-phase produces.
**Inputs:** `PHASE_NUM` from execute_phase. Run init to get phase paths:
**Inputs:** `PHASE_NUM` from execute_phase.
```bash
PHASE_STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op ${PHASE_NUM})
```
Parse from JSON: `phase_dir`, `phase_slug`, `padded_phase`, `phase_name`.
---
### Sub-step 1: Load prior context
Read project-level and prior phase context to avoid re-asking decided questions.
**Read project files:**
```bash
cat .planning/PROJECT.md 2>/dev/null || true
cat .planning/REQUIREMENTS.md 2>/dev/null || true
cat .planning/STATE.md 2>/dev/null || true
```
Extract from these:
- **PROJECT.md** — Vision, principles, non-negotiables, user preferences
- **REQUIREMENTS.md** — Acceptance criteria, constraints, must-haves vs nice-to-haves
- **STATE.md** — Current progress, decisions logged so far
**Read all prior CONTEXT.md files:**
```bash
(find .planning/phases -name "*-CONTEXT.md" 2>/dev/null || true) | sort
```
For each CONTEXT.md where phase number < current phase:
- Read the `<decisions>` section — these are locked preferences
- Read `<specifics>` — particular references or "I want it like X" moments
- Note patterns (e.g., "user consistently prefers minimal UI", "user rejected verbose output")
**Build internal prior_decisions context** (do not write to file):
```
<prior_decisions>
## Project-Level
- [Key principle or constraint from PROJECT.md]
- [Requirement affecting this phase from REQUIREMENTS.md]
## From Prior Phases
### Phase N: [Name]
- [Decision relevant to current phase]
- [Preference that establishes a pattern]
</prior_decisions>
```
If no prior context exists, continue without — expected for early phases.
---
### Sub-step 2: Scout Codebase
Lightweight codebase scan to inform grey area identification and proposals. Keep under ~5% context.
**Check for existing codebase maps:**
```bash
ls .planning/codebase/*.md 2>/dev/null || true
```
**If codebase maps exist:** Read the most relevant ones (CONVENTIONS.md, STRUCTURE.md, STACK.md based on phase type). Extract reusable components, established patterns, integration points. Skip to building context below.
**If no codebase maps, do targeted grep:**
Extract key terms from the phase goal. Search for related files:
```bash
grep -rl "{term1}\|{term2}" src/ app/ --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | head -10 || true
ls src/components/ src/hooks/ src/lib/ src/utils/ 2>/dev/null || true
```
Read the 3-5 most relevant files to understand existing patterns.
**Build internal codebase_context** (do not write to file):
- **Reusable assets** — existing components, hooks, utilities usable in this phase
- **Established patterns** — how the codebase does state management, styling, data fetching
- **Integration points** — where new code connects (routes, nav, providers)
---
### Sub-step 3: Analyze Phase and Generate Proposals
**Get phase details:**
```bash
DETAIL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase ${PHASE_NUM})
```
Extract `goal`, `requirements`, `success_criteria` from the JSON response.
**Infrastructure detection — check FIRST before generating grey areas:**
A phase is pure infrastructure when ALL of these are true:
1. Goal keywords match: "scaffolding", "plumbing", "setup", "configuration", "migration", "refactor", "rename", "restructure", "upgrade", "infrastructure"
2. AND success criteria are all technical: "file exists", "test passes", "config valid", "command runs"
3. AND no user-facing behavior is described (no "users can", "displays", "shows", "presents")
**If infrastructure-only:** Skip Sub-step 4. Jump directly to Sub-step 5 with minimal CONTEXT.md. Display:
```
Phase ${PHASE_NUM}: Infrastructure phase — skipping discuss, writing minimal context.
```
Use these defaults for the CONTEXT.md:
- `<domain>`: Phase boundary from ROADMAP goal
- `<decisions>`: Single "### Claude's Discretion" subsection — "All implementation choices are at Claude's discretion — pure infrastructure phase"
- `<code_context>`: Whatever the codebase scout found
- `<specifics>`: "No specific requirements — infrastructure phase"
- `<deferred>`: "None"
**If NOT infrastructure — generate grey area proposals:**
Determine domain type from the phase goal:
- Something users **SEE** → visual: layout, interactions, states, density
- Something users **CALL** → interface: contracts, responses, errors, auth
- Something users **RUN** → execution: invocation, output, behavior modes, flags
- Something users **READ** → content: structure, tone, depth, flow
- Something being **ORGANIZED** → organization: criteria, grouping, exceptions, naming
Check prior_decisions — skip grey areas already decided in prior phases.
Generate **3-4 grey areas** with **~4 questions each**. For each question:
- **Pre-select a recommended answer** based on: prior decisions (consistency), codebase patterns (reuse), domain conventions (standard approaches), ROADMAP success criteria
- Generate **1-2 alternatives** per question
- **Annotate** with prior decision context ("You decided X in Phase N") and code context ("Component Y exists with Z variants") where relevant
---
### Sub-step 4: Present Proposals Per Area
Present grey areas **one at a time**. For each area (M of N):
Display a table:
```
### Grey Area {M}/{N}: {Area Name}
| # | Question | ✅ Recommended | Alternative(s) |
|---|----------|---------------|-----------------|
| 1 | {question} | {answer} — {rationale} | {alt1}; {alt2} |
| 2 | {question} | {answer} — {rationale} | {alt1} |
| 3 | {question} | {answer} — {rationale} | {alt1}; {alt2} |
| 4 | {question} | {answer} — {rationale} | {alt1} |
```
Then prompt the user via **AskUserQuestion**:
- **header:** "Area {M}/{N}"
- **question:** "Accept these answers for {Area Name}?"
- **options:** Build dynamically — always "Accept all" first, then "Change Q1" through "Change QN" for each question (up to 4), then "Discuss deeper" last. Cap at 6 explicit options max (AskUserQuestion adds "Other" automatically).
**On "Accept all":** Record all recommended answers for this area. Move to next area.
**On "Change QN":** Use AskUserQuestion with the alternatives for that specific question:
- **header:** "{Area Name}"
- **question:** "Q{N}: {question text}"
- **options:** List the 1-2 alternatives plus "You decide" (maps to Claude's Discretion)
Record the user's choice. Re-display the updated table with the change reflected. Re-present the full acceptance prompt so the user can make additional changes or accept.
**On "Discuss deeper":** Switch to interactive mode for this area only — ask questions one at a time using AskUserQuestion with 2-3 concrete options per question plus "You decide". After 4 questions, prompt:
- **header:** "{Area Name}"
- **question:** "More questions about {area name}, or move to next?"
- **options:** "More questions" / "Next area"
If "More questions", ask 4 more. If "Next area", display final summary table of captured answers for this area and move on.
**On "Other" (free text):** Interpret as either a specific change request or general feedback. Incorporate into the area's decisions, re-display updated table, re-present acceptance prompt.
**Scope creep handling:** If user mentions something outside the phase domain:
```
"{Feature} sounds like a new capability — that belongs in its own phase.
I'll note it as a deferred idea.
Back to {current area}: {return to current question}"
```
Track deferred ideas internally for inclusion in CONTEXT.md.
---
### Sub-step 5: Write CONTEXT.md
After all areas are resolved (or infrastructure skip), write the CONTEXT.md file.
**File path:** `${phase_dir}/${padded_phase}-CONTEXT.md`
Use **exactly** this structure (identical to discuss-phase output):
```markdown
# Phase {PHASE_NUM}: {Phase Name} - Context
**Gathered:** {date}
**Status:** Ready for planning
<domain>
## Phase Boundary
{Domain boundary statement from analysis — what this phase delivers}
</domain>
<decisions>
## Implementation Decisions
### {Area 1 Name}
- {Accepted/chosen answer for Q1}
- {Accepted/chosen answer for Q2}
- {Accepted/chosen answer for Q3}
- {Accepted/chosen answer for Q4}
### {Area 2 Name}
- {Accepted/chosen answer for Q1}
- {Accepted/chosen answer for Q2}
...
### Claude's Discretion
{Any "You decide" answers collected — note Claude has flexibility here}
</decisions>
<code_context>
## Existing Code Insights
### Reusable Assets
- {From codebase scout — components, hooks, utilities}
### Established Patterns
- {From codebase scout — state management, styling, data fetching}
### Integration Points
- {From codebase scout — where new code connects}
</code_context>
<specifics>
## Specific Ideas
{Any specific references or "I want it like X" from discussion}
{If none: "No specific requirements — open to standard approaches"}
</specifics>
<deferred>
## Deferred Ideas
{Ideas captured but out of scope for this phase}
{If none: "None — discussion stayed within phase scope"}
</deferred>
```
Write the file.
**Commit:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${PADDED_PHASE}): smart discuss context" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
```
Display confirmation:
```
Created: {path}
Decisions captured: {count} across {area_count} areas
```
Read and execute: `$HOME/.claude/get-shit-done/references/autonomous-smart-discuss.md`
</step>
@@ -815,7 +545,7 @@ Proceed directly to lifecycle step (which handles partial completion — skips a
**Otherwise:** After each phase completes, re-read ROADMAP.md to catch phases inserted mid-execution (decimal phases like 5.1):
```bash
ROADMAP=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze)
ROADMAP=$(gsd-sdk query roadmap.analyze)
```
Re-filter incomplete phases using the same logic as discover_phases:

View File

@@ -12,7 +12,7 @@ Read all files referenced by the invoking prompt's execution_context before star
Load todo context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init todos)
INIT=$(gsd-sdk query init.todos)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -157,7 +157,7 @@ If todo was moved to done/, commit the change:
```bash
git rm --cached .planning/todos/pending/[filename] 2>/dev/null || true
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: start work on todo - [title]" --files .planning/todos/completed/[filename] .planning/STATE.md
gsd-sdk query commit "docs: start work on todo - [title]" .planning/todos/completed/[filename] .planning/STATE.md
```
Tool respects `commit_docs` config and gitignore automatically.

View File

@@ -124,7 +124,7 @@ Repeat for all milestones in the cleanup set.
Commit the changes:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "chore: archive phase directories from completed milestones" --files .planning/milestones/ .planning/phases/
gsd-sdk query commit "chore: archive phase directories from completed milestones" .planning/milestones/ .planning/phases/
```
</step>

View File

@@ -18,7 +18,7 @@ Parse arguments and load project state:
```bash
PHASE_ARG="${1}"
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
INIT=$(gsd-sdk query init.phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -74,7 +74,7 @@ FIX_REPORT_PATH="${PHASE_DIR}/${PADDED_PHASE}-REVIEW-FIX.md"
Check if code review is enabled via config:
```bash
CODE_REVIEW_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review 2>/dev/null || echo "true")
CODE_REVIEW_ENABLED=$(gsd-sdk query config-get workflow.code_review 2>/dev/null || echo "true")
```
If CODE_REVIEW_ENABLED is "false":
@@ -359,7 +359,7 @@ if [ -f "${FIX_REPORT_PATH}" ]; then
echo "REVIEW-FIX.md created at ${FIX_REPORT_PATH}"
if [ "$COMMIT_DOCS" = "true" ]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit \
gsd-sdk query commit \
"docs(${PADDED_PHASE}): add code review fix report" \
--files "${FIX_REPORT_PATH}"
fi

View File

@@ -17,7 +17,7 @@ Parse arguments and load project state:
```bash
PHASE_ARG="${1}"
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
INIT=$(gsd-sdk query init.phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -74,7 +74,7 @@ fi
Check if code review is enabled via config:
```bash
CODE_REVIEW_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review 2>/dev/null || echo "true")
CODE_REVIEW_ENABLED=$(gsd-sdk query config-get workflow.code_review 2>/dev/null || echo "true")
```
If CODE_REVIEW_ENABLED is "false":
@@ -90,14 +90,14 @@ Default is true — only skip on explicit false. This check runs AFTER phase val
Determine review depth with priority order:
1. DEPTH_OVERRIDE from --depth flag (highest priority)
2. Config value: `node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review_depth 2>/dev/null`
2. Config value: `gsd-sdk query config-get workflow.code_review_depth 2>/dev/null`
3. Default: "standard"
```bash
if [ -n "$DEPTH_OVERRIDE" ]; then
REVIEW_DEPTH="$DEPTH_OVERRIDE"
else
CONFIG_DEPTH=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review_depth 2>/dev/null || echo "")
CONFIG_DEPTH=$(gsd-sdk query config-get workflow.code_review_depth 2>/dev/null || echo "")
REVIEW_DEPTH="${CONFIG_DEPTH:-standard}"
fi
```
@@ -395,7 +395,7 @@ if [ -f "${REVIEW_PATH}" ]; then
echo "REVIEW.md created at ${REVIEW_PATH}"
if [ "$COMMIT_DOCS" = "true" ]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit \
gsd-sdk query commit \
"docs(${PADDED_PHASE}): add code review report" \
--files "${REVIEW_PATH}"
fi

View File

@@ -38,7 +38,9 @@ When a milestone completes:
<process>
<step name="pre_close_artifact_audit">
Before proceeding with milestone close, run the comprehensive open artifact audit:
Before proceeding with milestone close, run the comprehensive open artifact audit.
`audit-open` is not registered on `gsd-sdk query` yet; use the installed CJS CLI:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" audit-open 2>/dev/null
@@ -76,7 +78,7 @@ If user chooses [A] (Acknowledge):
If output shows all clear (no open items): print `All artifact types clear.` and proceed.
SECURITY: Audit JSON output is structured data from gsd-tools.cjs — validated and sanitized at source. When writing to STATE.md, item slugs and descriptions are sanitized via `sanitizeForDisplay()` before inclusion. Never inject raw user-supplied content into STATE.md without sanitization.
SECURITY: Audit JSON output is structured data from `audit-open` (gsd-tools.cjs) — validated and sanitized at source. When writing to STATE.md, item slugs and descriptions are sanitized via `sanitizeForDisplay()` before inclusion. Never inject raw user-supplied content into STATE.md without sanitization.
</step>
<step name="verify_readiness">
@@ -84,7 +86,7 @@ SECURITY: Audit JSON output is structured data from gsd-tools.cjs — validated
**Use `roadmap analyze` for comprehensive readiness check:**
```bash
ROADMAP=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze)
ROADMAP=$(gsd-sdk query roadmap.analyze)
```
This returns all phases with plan/summary counts and disk status. Use this to verify:
@@ -199,7 +201,7 @@ Extract one-liners from SUMMARY.md files using summary-extract:
# For each phase in milestone, extract one-liner
for summary in .planning/phases/*-*/*-SUMMARY.md; do
[ -e "$summary" ] || continue
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" summary-extract "$summary" --fields one_liner --pick one_liner
gsd-sdk query summary-extract "$summary" --fields one_liner --pick one_liner
done
```
@@ -218,7 +220,7 @@ Key accomplishments for this milestone:
<step name="create_milestone_entry">
**Note:** MILESTONES.md entry is now created automatically by `gsd-tools milestone complete` in the archive_milestone step. The entry includes version, date, phase/plan/task counts, and accomplishments extracted from SUMMARY.md files.
**Note:** MILESTONES.md entry is now created automatically by `gsd-sdk query milestone.complete` in the archive_milestone step. The entry includes version, date, phase/plan/task counts, and accomplishments extracted from SUMMARY.md files.
If additional details are needed (e.g., user-provided "Delivered" summary, git range, LOC stats), add them manually after the CLI creates the base entry.
@@ -409,10 +411,10 @@ Update `.planning/ROADMAP.md` — group completed milestone phases:
<step name="archive_milestone">
**Delegate archival to gsd-tools:**
**Delegate archival to `gsd-sdk query milestone.complete`:**
```bash
ARCHIVE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" milestone complete "v[X.Y]" --name "[Milestone Name]")
ARCHIVE=$(gsd-sdk query milestone.complete "v[X.Y]" --name "[Milestone Name]")
```
The CLI handles:
@@ -494,7 +496,7 @@ Append the extracted Backlog content verbatim to the end of the newly written RO
**Safety commit — commit archive files BEFORE deleting any originals:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "chore: archive v[X.Y] milestone files" --files .planning/milestones/v[X.Y]-ROADMAP.md .planning/milestones/v[X.Y]-REQUIREMENTS.md .planning/milestones/v[X.Y]-MILESTONE-AUDIT.md .planning/MILESTONES.md .planning/PROJECT.md .planning/STATE.md .planning/ROADMAP.md
gsd-sdk query commit "chore: archive v[X.Y] milestone files" .planning/milestones/v[X.Y]-ROADMAP.md .planning/milestones/v[X.Y]-REQUIREMENTS.md .planning/milestones/v[X.Y]-MILESTONE-AUDIT.md .planning/MILESTONES.md .planning/PROJECT.md .planning/STATE.md .planning/ROADMAP.md
```
This creates a durable checkpoint in git history. If anything fails after this point, the working tree can be reconstructed from git.
@@ -563,7 +565,7 @@ If the "## Cross-Milestone Trends" section exists, update the tables with new da
**Commit:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: update retrospective for v${VERSION}" --files .planning/RETROSPECTIVE.md
gsd-sdk query commit "docs: update retrospective for v${VERSION}" .planning/RETROSPECTIVE.md
```
</step>
@@ -597,7 +599,7 @@ Check branching strategy and offer merge options.
Use `init milestone-op` for context, or load config directly:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "1")
INIT=$(gsd-sdk query init.execute-phase "1")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -605,7 +607,7 @@ Extract `branching_strategy`, `phase_branch_template`, `milestone_branch_templat
Detect base branch:
```bash
BASE_BRANCH=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get git.base_branch 2>/dev/null || echo "")
BASE_BRANCH=$(gsd-sdk query config-get git.base_branch 2>/dev/null || echo "")
if [ -z "$BASE_BRANCH" ] || [ "$BASE_BRANCH" = "null" ]; then
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|^refs/remotes/origin/||')
BASE_BRANCH="${BASE_BRANCH:-main}"
@@ -780,7 +782,7 @@ Tag: v[X.Y]
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Start Next Milestone** — questioning → research → requirements → roadmap

View File

@@ -58,7 +58,7 @@ gaps = [
**Read worktree config:**
```bash
USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.use_worktrees 2>/dev/null || echo "true")
USE_WORKTREES=$(gsd-sdk query config-get workflow.use_worktrees 2>/dev/null || echo "true")
```
**Report diagnosis plan to user:**
@@ -87,7 +87,7 @@ This runs in parallel - all gaps investigated simultaneously.
**Load agent skills:**
```bash
AGENT_SKILLS_DEBUGGER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-debugger 2>/dev/null)
AGENT_SKILLS_DEBUGGER=$(gsd-sdk query agent-skills gsd-debugger 2>/dev/null)
EXPECTED_BASE=$(git rev-parse HEAD)
```
@@ -177,7 +177,7 @@ Update status in frontmatter to "diagnosed".
Commit the updated UAT.md:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase_num}): add root causes from diagnosis" --files ".planning/phases/XX-name/{phase_num}-UAT.md"
gsd-sdk query commit "docs({phase_num}): add root causes from diagnosis" ".planning/phases/XX-name/{phase_num}-UAT.md"
```
</step>

View File

@@ -64,9 +64,9 @@ plain-text numbered list and ask the user to type their choice number.
Phase number from argument (required).
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE}")
INIT=$(gsd-sdk query init.phase-op "${PHASE}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_ANALYZER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-assumptions-analyzer 2>/dev/null)
AGENT_SKILLS_ANALYZER=$(gsd-sdk query agent-skills gsd-assumptions-analyzer 2>/dev/null)
```
Parse JSON for: `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`,
@@ -171,7 +171,7 @@ Structure the extracted information for use in assumption generation.
Check if any pending todos are relevant to this phase's scope.
```bash
TODO_MATCHES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" todo match-phase "${PHASE_NUMBER}")
TODO_MATCHES=$(gsd-sdk query todo.match-phase "${PHASE_NUMBER}")
```
Parse JSON for: `todo_count`, `matches[]`.
@@ -548,7 +548,7 @@ Write file.
Commit phase context and discussion log:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${padded_phase}): capture phase context (assumptions mode)" --files "${phase_dir}/${padded_phase}-CONTEXT.md" "${phase_dir}/${padded_phase}-DISCUSSION-LOG.md"
gsd-sdk query commit "docs(${padded_phase}): capture phase context (assumptions mode)" "${phase_dir}/${padded_phase}-CONTEXT.md" "${phase_dir}/${padded_phase}-DISCUSSION-LOG.md"
```
Confirm: "Committed: docs(${padded_phase}): capture phase context (assumptions mode)"
@@ -558,7 +558,7 @@ Confirm: "Committed: docs(${padded_phase}): capture phase context (assumptions m
Update STATE.md with session info:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
gsd-sdk query state.record-session \
--stopped-at "Phase ${PHASE} context gathered (assumptions mode)" \
--resume-file "${phase_dir}/${padded_phase}-CONTEXT.md"
```
@@ -566,7 +566,7 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
Commit STATE.md:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(state): record phase ${PHASE} context session" --files .planning/STATE.md
gsd-sdk query commit "docs(state): record phase ${PHASE} context session" .planning/STATE.md
```
</step>
@@ -593,7 +593,7 @@ Created: .planning/phases/${PADDED_PHASE}-${SLUG}/${PADDED_PHASE}-CONTEXT.md
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase ${PHASE}: {phase_name}** — {Goal from ROADMAP.md}
@@ -619,18 +619,18 @@ Check for auto-advance trigger:
2. Sync chain flag:
```bash
if [[ ! "$ARGUMENTS" =~ --auto ]]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active false 2>/dev/null
gsd-sdk query config-set workflow._auto_chain_active false 2>/dev/null
fi
```
3. Read chain flag and user preference:
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
```
**If `--auto` flag present AND `AUTO_CHAIN` is not true:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active true
gsd-sdk query config-set workflow._auto_chain_active true
```
**If `--auto` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**

View File

@@ -134,7 +134,7 @@ cannot forward TUI menu selections back to the host.
Enable text mode:
- Per-session: pass `--text` flag to any command (e.g., `/gsd-discuss-phase --text`)
- Per-project: `gsd-tools config-set workflow.text_mode true`
- Per-project: `gsd-sdk query config-set workflow.text_mode true`
Text mode applies to ALL workflows in the session, not just discuss-phase.
</answer_validation>
@@ -147,9 +147,9 @@ Text mode applies to ALL workflows in the session, not just discuss-phase.
Phase number from argument (required).
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE}")
INIT=$(gsd-sdk query init.phase-op "${PHASE}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_ADVISOR=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-advisor 2>/dev/null)
AGENT_SKILLS_ADVISOR=$(gsd-sdk query agent-skills gsd-advisor 2>/dev/null)
```
Parse JSON for: `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_plans`, `has_verification`, `plan_count`, `roadmap_exists`, `planning_exists`, `response_language`.
@@ -171,6 +171,13 @@ Exit workflow.
- Read and execute @~/.claude/get-shit-done/workflows/discuss-phase-power.md end-to-end
- Do not continue with the steps below
**All mode** — If `--all` is present in ARGUMENTS:
- In `present_gray_areas`: auto-select ALL gray areas without asking the user (skips the AskUserQuestion selection step)
- Discussion for each area proceeds fully interactively (user drives the conversation for every area)
- Does NOT auto-advance to plan-phase afterward — use `--chain` or `--auto` if you want auto-advance
- Log: `[--all] Auto-selected all gray areas: [list area names].`
- This is the "discuss everything" shortcut: skip the selection friction, keep full interactive control
**Auto mode** — If `--auto` is present in ARGUMENTS:
- In `check_existing`: auto-select "Skip" (if context exists) or continue without prompting (if no context/plans)
- In `present_gray_areas`: auto-select ALL gray areas without asking the user
@@ -331,7 +338,7 @@ Check if any pending todos are relevant to this phase's scope. Surfaces backlog
**Load and match todos:**
```bash
TODO_MATCHES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" todo match-phase "${PHASE_NUMBER}")
TODO_MATCHES=$(gsd-sdk query todo.match-phase "${PHASE_NUMBER}")
```
Parse JSON for: `todo_count`, `matches[]` (each with `file`, `title`, `area`, `score`, `reasons`).
@@ -456,7 +463,7 @@ Check if advisor mode should activate:
3. Resolve model for advisor agents:
```bash
ADVISOR_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-advisor-researcher --raw)
ADVISOR_MODEL=$(gsd-sdk query resolve-model gsd-advisor-researcher --raw)
```
If ADVISOR_MODE is false, skip all advisor-specific steps — workflow proceeds with existing conversational flow unchanged.
@@ -522,7 +529,7 @@ We'll clarify HOW to implement this.
- [Decision from Phase M that applies here]
```
**If `--auto`:** Auto-select ALL gray areas. Log: `[auto] Selected all gray areas: [list area names].` Skip the AskUserQuestion below and continue directly to discuss_areas with all areas selected.
**If `--auto` or `--all`:** Auto-select ALL gray areas. Log: `[--auto/--all] Selected all gray areas: [list area names].` Skip the AskUserQuestion below and continue directly to discuss_areas with all areas selected.
**Otherwise, use AskUserQuestion (multiSelect: true):**
- header: "Discuss"
@@ -759,7 +766,7 @@ In `--auto` mode, the discuss step MUST complete in a **single pass**. After wri
Check the pass cap from config:
```bash
MAX_PASSES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.max_discuss_passes 2>/dev/null || echo "3")
MAX_PASSES=$(gsd-sdk query config-get workflow.max_discuss_passes 2>/dev/null || echo "3")
```
If you have already written and committed CONTEXT.md, the discuss step is complete. Move on.
@@ -1031,7 +1038,7 @@ Created: .planning/phases/${PADDED_PHASE}-${SLUG}/${PADDED_PHASE}-CONTEXT.md
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase ${PHASE}: [Name]** — [Goal from ROADMAP.md]
@@ -1105,7 +1112,7 @@ rm -f "${phase_dir}/${padded_phase}-DISCUSS-CHECKPOINT.json"
Commit phase context and discussion log:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${padded_phase}): capture phase context" --files "${phase_dir}/${padded_phase}-CONTEXT.md" "${phase_dir}/${padded_phase}-DISCUSSION-LOG.md"
gsd-sdk query commit "docs(${padded_phase}): capture phase context" "${phase_dir}/${padded_phase}-CONTEXT.md" "${phase_dir}/${padded_phase}-DISCUSSION-LOG.md"
```
Confirm: "Committed: docs(${padded_phase}): capture phase context"
@@ -1115,7 +1122,7 @@ Confirm: "Committed: docs(${padded_phase}): capture phase context"
Update STATE.md with session info:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
gsd-sdk query state.record-session \
--stopped-at "Phase ${PHASE} context gathered" \
--resume-file "${phase_dir}/${padded_phase}-CONTEXT.md"
```
@@ -1123,29 +1130,29 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
Commit STATE.md:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(state): record phase ${PHASE} context session" --files .planning/STATE.md
gsd-sdk query commit "docs(state): record phase ${PHASE} context session" .planning/STATE.md
```
</step>
<step name="auto_advance">
Check for auto-advance trigger:
1. Parse `--auto` and `--chain` flags from $ARGUMENTS
1. Parse `--auto` and `--chain` flags from $ARGUMENTS. Note: --all is NOT an auto-advance trigger — it only affects area selection. A session with `--all` but without `--auto` or `--chain` returns to manual next-steps after discussion completes.
2. **Sync chain flag with intent** — if user invoked manually (no `--auto` and no `--chain`), clear the ephemeral chain flag from any previous interrupted `--auto` chain. This does NOT touch `workflow.auto_advance` (the user's persistent settings preference):
```bash
if [[ ! "$ARGUMENTS" =~ --auto ]] && [[ ! "$ARGUMENTS" =~ --chain ]]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active false 2>/dev/null
gsd-sdk query config-set workflow._auto_chain_active false 2>/dev/null
fi
```
3. Read both the chain flag and user preference:
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
```
**If `--auto` or `--chain` flag present AND `AUTO_CHAIN` is not true:** Persist chain flag to config (handles direct usage without new-project):
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active true
gsd-sdk query config-set workflow._auto_chain_active true
```
**If `--auto` flag present OR `--chain` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**

View File

@@ -26,7 +26,7 @@ Wait for response before continuing.
**Check if project exists.**
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load 2>/dev/null)
INIT=$(gsd-sdk query state.load 2>/dev/null)
```
Track whether `.planning/` exists — some routes require it, others don't.

View File

@@ -14,9 +14,9 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
Load docs-update context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" docs-init)
INIT=$(gsd-sdk query docs-init)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-doc-writer 2>/dev/null)
AGENT_SKILLS=$(gsd-sdk query agent-skills gsd-doc-writer 2>/dev/null)
```
Extract from init JSON:
@@ -1054,7 +1054,7 @@ Only run this step if `commit_docs` is `true` from the init JSON. If `commit_doc
Assemble the list of files that were actually generated (do not include files that failed or were skipped):
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: generate project documentation" \
gsd-sdk query commit "docs: generate project documentation" \
--files README.md docs/ARCHITECTURE.md docs/CONFIGURATION.md docs/GETTING-STARTED.md docs/DEVELOPMENT.md docs/TESTING.md
# Append any conditional docs that were generated:
# --files ... docs/API.md docs/DEPLOYMENT.md CONTRIBUTING.md

View File

@@ -13,14 +13,14 @@ Use after /gsd-execute-phase to verify that the evaluation strategy from AI-SPEC
## 0. Initialize
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
INIT=$(gsd-sdk query init.phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
Parse: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `commit_docs`.
```bash
AUDITOR_MODEL=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" resolve-model gsd-eval-auditor --raw)
AUDITOR_MODEL=$(gsd-sdk query resolve-model gsd-eval-auditor 2>/dev/null | jq -r '.model' 2>/dev/null || true)
```
Display banner:

View File

@@ -67,9 +67,9 @@ If `--wave` is absent, preserve the current behavior of executing all incomplete
Load all context in one call:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "${PHASE_ARG}")
INIT=$(gsd-sdk query init.execute-phase "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-executor 2>/dev/null)
AGENT_SKILLS=$(gsd-sdk query agent-skills gsd-executor 2>/dev/null)
```
Parse JSON for: `executor_model`, `verifier_model`, `commit_docs`, `parallelization`, `branching_strategy`, `branch_name`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `plans`, `incomplete_plans`, `plan_count`, `incomplete_count`, `state_exists`, `roadmap_exists`, `phase_req_ids`, `response_language`.
@@ -79,7 +79,7 @@ Parse JSON for: `executor_model`, `verifier_model`, `commit_docs`, `parallelizat
Read worktree config:
```bash
USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.use_worktrees 2>/dev/null || echo "true")
USE_WORKTREES=$(gsd-sdk query config-get workflow.use_worktrees 2>/dev/null || echo "true")
```
If the project uses git submodules, worktree isolation is skipped regardless of the `workflow.use_worktrees` config — the executor commit protocol cannot correctly handle submodule commits inside isolated worktrees. Sequential execution handles submodules transparently.
@@ -96,7 +96,7 @@ When `USE_WORKTREES` is `false`, all executor agents run without `isolation="wor
Read context window size for adaptive prompt enrichment:
```bash
CONTEXT_WINDOW=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get context_window 2>/dev/null || echo "200000")
CONTEXT_WINDOW=$(gsd-sdk query config-get context_window 2>/dev/null || echo "200000")
```
When `CONTEXT_WINDOW >= 500000` (1M-class models), subagent prompts include richer context:
@@ -128,7 +128,7 @@ inline path for each plan.
```bash
# REQUIRED: prevents stale auto-chain from previous --auto runs
if [[ ! "$ARGUMENTS" =~ --auto ]]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active false 2>/dev/null
gsd-sdk query config-set workflow._auto_chain_active false 2>/dev/null
fi
```
</step>
@@ -225,7 +225,7 @@ Report: "Found {plan_count} plans in {phase_dir} ({incomplete_count} incomplete)
**Update STATE.md for phase start:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state begin-phase --phase "${PHASE_NUMBER}" --name "${PHASE_NAME}" --plans "${PLAN_COUNT}"
gsd-sdk query state.begin-phase --phase "${PHASE_NUMBER}" --name "${PHASE_NAME}" --plans "${PLAN_COUNT}"
```
This updates Status, Last Activity, Current focus, Current Position, and plan counts in STATE.md so frontmatter and body text reflect the active phase immediately.
</step>
@@ -234,7 +234,7 @@ This updates Status, Last Activity, Current focus, Current Position, and plan co
Load plan inventory with wave grouping in one call:
```bash
PLAN_INDEX=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase-plan-index "${PHASE_NUMBER}")
PLAN_INDEX=$(gsd-sdk query phase-plan-index "${PHASE_NUMBER}")
```
Parse JSON for: `phase`, `plans[]` (each with `id`, `wave`, `autonomous`, `objective`, `files_modified`, `task_count`, `has_summary`), `waves` (map of wave number → plan IDs), `incomplete`, `has_checkpoints`.
@@ -276,15 +276,15 @@ executor skips them.
`workflow.cross_ai_execution` is `true`. Plans matching both conditions are marked for cross-AI.
```bash
CROSS_AI_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.cross_ai_execution --default false 2>/dev/null)
CROSS_AI_CMD=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.cross_ai_command --default "" 2>/dev/null)
CROSS_AI_TIMEOUT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.cross_ai_timeout --default 300 2>/dev/null)
CROSS_AI_ENABLED=$(gsd-sdk query config-get workflow.cross_ai_execution 2>/dev/null || echo "false")
CROSS_AI_CMD=$(gsd-sdk query config-get workflow.cross_ai_command 2>/dev/null || echo "")
CROSS_AI_TIMEOUT=$(gsd-sdk query config-get workflow.cross_ai_timeout 2>/dev/null || echo "300")
```
**If no plans are marked for cross-AI:** Skip to execute_waves.
**If plans are marked but `cross_ai_command` is empty:** Error — tell user to set
`workflow.cross_ai_command` via `gsd-tools.cjs config-set workflow.cross_ai_command "<command>"`.
`workflow.cross_ai_command` via `gsd-sdk query config-set workflow.cross_ai_command "<command>"`.
**For each cross-AI plan (sequentially):**
@@ -463,7 +463,7 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
You are running as a PARALLEL executor agent in a git worktree.
Use --no-verify on all git commits to avoid pre-commit hook contention
with other agents. The orchestrator validates hooks once after all agents complete.
For gsd-tools commits: add --no-verify flag.
For `gsd-sdk query commit` (or legacy `gsd-tools.cjs` commit): add --no-verify flag when needed.
For direct git commits: use git commit --no-verify -m "..."
IMPORTANT: Do NOT modify STATE.md or ROADMAP.md. execute-plan.md
@@ -614,11 +614,13 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
continue
fi
# Merge the worktree branch into the current branch
git merge "$WT_BRANCH" --no-edit -m "chore: merge executor worktree ($WT_BRANCH)" 2>&1 || {
# Merge the worktree branch into the current branch (--no-ff ensures a merge commit so HEAD~1 is reliable)
git merge "$WT_BRANCH" --no-ff --no-edit -m "chore: merge executor worktree ($WT_BRANCH)" 2>&1 || {
echo "⚠ Merge conflict from worktree $WT_BRANCH — resolve manually"
rm -f "$STATE_BACKUP" "$ROADMAP_BACKUP"
continue
echo " STATE.md backup: $STATE_BACKUP"
echo " ROADMAP.md backup: $ROADMAP_BACKUP"
echo " Restore with: cp \$STATE_BACKUP .planning/STATE.md && cp \$ROADMAP_BACKUP .planning/ROADMAP.md"
break
}
# Restore orchestrator-owned files (main always wins)
@@ -644,7 +646,7 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
if ! git diff --quiet .planning/STATE.md .planning/ROADMAP.md 2>/dev/null || \
[ -n "$DELETED_FILES" ]; then
# Only amend the commit with .planning/ files if commit_docs is enabled (#1783)
COMMIT_DOCS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get commit_docs 2>/dev/null || echo "true")
COMMIT_DOCS=$(gsd-sdk query config-get commit_docs 2>/dev/null || echo "true")
if [ "$COMMIT_DOCS" != "false" ]; then
git add .planning/STATE.md .planning/ROADMAP.md 2>/dev/null || true
git commit --amend --no-edit 2>/dev/null || true
@@ -735,12 +737,12 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
if [ "${TEST_EXIT}" -eq 0 ]; then
# Update ROADMAP plan progress for each completed plan in this wave
for plan_id in {completed_plan_ids}; do
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap update-plan-progress "${PHASE_NUMBER}" "${plan_id}" "complete"
gsd-sdk query roadmap.update-plan-progress "${PHASE_NUMBER}" "${plan_id}" "complete"
done
# Only commit tracking files if they actually changed
if ! git diff --quiet .planning/ROADMAP.md .planning/STATE.md 2>/dev/null; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(phase-${PHASE_NUMBER}): update tracking after wave ${N}" --files .planning/ROADMAP.md .planning/STATE.md
gsd-sdk query commit "docs(phase-${PHASE_NUMBER}): update tracking after wave ${N}" .planning/ROADMAP.md .planning/STATE.md
fi
elif [ "${TEST_EXIT}" -eq 124 ]; then
echo "⚠ Skipping tracking update — test suite timed out. Plans remain in-progress. Run tests manually to confirm."
@@ -817,7 +819,7 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
Before spawning wave N+1, for each plan in the upcoming wave:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify key-links {phase_dir}/{plan}-PLAN.md
gsd-sdk query verify.key-links {phase_dir}/{plan}-PLAN.md
```
If any key-link from a PRIOR wave's artifact fails verification:
@@ -846,8 +848,8 @@ Plans with `autonomous: false` require user interaction.
Read auto-advance config (chain flag + user preference):
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
```
When executor returns a checkpoint AND (`AUTO_CHAIN` is `"true"` OR `AUTO_CFG` is `"true"`):
@@ -908,7 +910,7 @@ After all waves:
**Security gate check:**
```bash
SECURITY_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.security_enforcement --raw 2>/dev/null || echo "true")
SECURITY_CFG=$(gsd-sdk query config-get workflow.security_enforcement --raw 2>/dev/null || echo "true")
SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
```
@@ -932,7 +934,7 @@ If `SECURITY_CFG` is `true` AND SECURITY.md exists: check frontmatter `threats_o
**Optional step — TDD collaborative review.**
```bash
TDD_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.tdd_mode --default false 2>/dev/null)
TDD_MODE=$(gsd-sdk query config-get workflow.tdd_mode 2>/dev/null || echo "false")
```
**Skip if `TDD_MODE` is `false`.**
@@ -976,7 +978,7 @@ TDD_PLANS=$(grep -rl "^type: tdd" "${PHASE_DIR}"/*-PLAN.md 2>/dev/null | wc -l |
If `WAVE_FILTER` was used, re-run plan discovery after execution:
```bash
POST_PLAN_INDEX=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase-plan-index "${PHASE_NUMBER}")
POST_PLAN_INDEX=$(gsd-sdk query phase-plan-index "${PHASE_NUMBER}")
```
Apply the same "incomplete" filtering rules as earlier:
@@ -1008,7 +1010,7 @@ Selected wave finished successfully. This phase still has incomplete plans, so p
**Config gate:**
```bash
CODE_REVIEW_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review 2>/dev/null || echo "true")
CODE_REVIEW_ENABLED=$(gsd-sdk query config-get workflow.code_review 2>/dev/null || echo "true")
```
If `CODE_REVIEW_ENABLED` is `"false"`: display "Code review skipped (workflow.code_review=false)" and proceed to next step.
@@ -1051,7 +1053,7 @@ fi
**2. Find parent UAT file:**
```bash
PARENT_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" find-phase "${PARENT_PHASE}" --raw)
PARENT_INFO=$(gsd-sdk query find-phase "${PARENT_PHASE}" --raw)
# Extract directory from PARENT_INFO JSON, then find UAT file in that directory
```
@@ -1082,7 +1084,7 @@ mv .planning/debug/{slug}.md .planning/debug/resolved/
**6. Commit updated artifacts:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(phase-${PARENT_PHASE}): resolve UAT gaps and debug sessions after ${PHASE_NUMBER} gap closure" --files .planning/phases/*${PARENT_PHASE}*/*-UAT.md .planning/debug/resolved/*.md
gsd-sdk query commit "docs(phase-${PARENT_PHASE}): resolve UAT gaps and debug sessions after ${PHASE_NUMBER} gap closure" .planning/phases/*${PARENT_PHASE}*/*-UAT.md .planning/debug/resolved/*.md
```
</step>
@@ -1155,7 +1157,7 @@ build/types pass because TypeScript types come from config, not the live databas
**Run after execution completes but BEFORE verification marks success.**
```bash
SCHEMA_DRIFT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" verify schema-drift "${PHASE_NUMBER}" 2>/dev/null)
SCHEMA_DRIFT=$(gsd-sdk query verify.schema-drift "${PHASE_NUMBER}" 2>/dev/null)
```
Parse JSON result for: `drift_detected`, `blocking`, `schema_files`, `orms`, `unpushed_orms`, `message`.
@@ -1218,7 +1220,7 @@ If `TEXT_MODE` is true, present as a plain-text numbered list. Otherwise use Ask
Verify phase achieved its GOAL, not just completed tasks.
```bash
VERIFIER_SKILLS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-verifier 2>/dev/null)
VERIFIER_SKILLS=$(gsd-sdk query agent-skills gsd-verifier 2>/dev/null)
```
```
@@ -1301,7 +1303,7 @@ blocked: 0
Commit the file:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "test({phase_num}): persist human verification items as UAT" --files "{phase_dir}/{phase_num}-HUMAN-UAT.md"
gsd-sdk query commit "test({phase_num}): persist human verification items as UAT" "{phase_dir}/{phase_num}-HUMAN-UAT.md"
```
**Step B: Present to user:**
@@ -1333,7 +1335,7 @@ Items saved to `{phase_num}-HUMAN-UAT.md` — they will appear in `/gsd-progress
{Gap summaries from VERIFICATION.md}
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
`/clear` then:
@@ -1350,7 +1352,7 @@ Gap closure cycle: `/gsd-plan-phase {X} --gaps ${GSD_WS}` reads VERIFICATION.md
**Mark phase complete and update all tracking files:**
```bash
COMPLETION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase complete "${PHASE_NUMBER}")
COMPLETION=$(gsd-sdk query phase.complete "${PHASE_NUMBER}")
```
The CLI handles:
@@ -1373,7 +1375,7 @@ These items are tracked and will appear in `/gsd-progress` and `/gsd-audit-uat`.
```
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(phase-{X}): complete phase execution" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md {phase_dir}/*-VERIFICATION.md
gsd-sdk query commit "docs(phase-{X}): complete phase execution" .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md {phase_dir}/*-VERIFICATION.md
```
</step>
@@ -1385,7 +1387,7 @@ entries from the completed phase to the global learnings store at `~/.gsd/knowle
**Check config gate:**
```bash
GL_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get features.global_learnings --raw 2>/dev/null || echo "false")
GL_ENABLED=$(gsd-sdk query config-get features.global_learnings --raw 2>/dev/null || echo "false")
```
**If `GL_ENABLED` is not `true`:** Skip this step entirely (feature disabled by default).
@@ -1395,7 +1397,7 @@ GL_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get fea
1. Check if LEARNINGS.md exists in the phase directory (use the `phase_dir` value from init context)
2. If found, copy to global store:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" learnings copy 2>/dev/null || echo "⚠ Learnings copy failed — continuing"
gsd-sdk query learnings.copy 2>/dev/null || echo "⚠ Learnings copy failed — continuing"
```
Copy failure must NOT block phase completion.
</step>
@@ -1416,7 +1418,7 @@ PROJECT.md falls behind silently over multiple phases.
5. Commit the change:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(phase-{X}): evolve PROJECT.md after phase completion" --files .planning/PROJECT.md
gsd-sdk query commit "docs(phase-{X}): evolve PROJECT.md after phase completion" .planning/PROJECT.md
```
**Skip this step if** `.planning/PROJECT.md` does not exist.
@@ -1454,8 +1456,8 @@ STOP. Do not proceed to auto-advance or transition.
1. Parse `--auto` flag from $ARGUMENTS
2. Read both the chain flag and user preference (chain flag already synced in init step):
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
```
**If `--auto` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true (AND verification passed with no gaps):**

View File

@@ -20,7 +20,7 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
Load execution context (paths only to minimize orchestrator context):
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init execute-phase "${PHASE}")
INIT=$(gsd-sdk query init.execute-phase "${PHASE}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -40,7 +40,7 @@ Find first PLAN without matching SUMMARY. Decimal phases supported (`01.1-hotfix
```bash
PHASE=$(echo "$PLAN_PATH" | grep -oE '[0-9]+(\.[0-9]+)?-[0-9]+')
# config settings can be fetched via gsd-tools config-get if needed
# config settings can be fetched via gsd-sdk query config-get if needed
```
<if mode="yolo">
@@ -63,7 +63,7 @@ PLAN_START_EPOCH=$(date +%s)
```bash
# Count tasks — match <task tag at any indentation level
TASK_COUNT=$(grep -cE '^\s*<task[[:space:]>]' .planning/phases/XX-name/{phase}-{plan}-PLAN.md 2>/dev/null || echo "0")
INLINE_THRESHOLD=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.inline_plan_threshold --default 2 2>/dev/null || echo "2")
INLINE_THRESHOLD=$(gsd-sdk query config-get workflow.inline_plan_threshold 2>/dev/null || echo "2")
grep -n "type=\"checkpoint" .planning/phases/XX-name/{phase}-{plan}-PLAN.md
```
@@ -141,7 +141,7 @@ This IS the execution instructions. Follow exactly. If plan references CONTEXT.m
<step name="previous_phase_check">
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phases list --type summaries --raw
gsd-sdk query phases.list --type summaries --raw
# Extract the second-to-last summary from the JSON result
```
@@ -255,13 +255,9 @@ If a commit is BLOCKED by a hook:
<task_commit>
## Task Commit Protocol
Follow the task commit protocol from the gsd-executor agent definition (single source of truth):
- Stage files individually (NEVER `git add .` or `git add -A`)
- Format: `{type}({phase}-{plan}): {concise description}` with bullet points for key changes
- Types: feat, fix, test, refactor, perf, docs, style, chore
- Sub-repos: use `commit-to-subrepo` when `sub_repos` is configured
- Record commit hash for SUMMARY tracking
- Check for untracked generated files after each commit
Canonical per-task commit rules live in **`agents/gsd-executor.md`** (`<task_commit_protocol>`). Follow that section for staging, `{type}({phase}-{plan})` messages, `commit-to-subrepo` when `sub_repos` is set, post-commit checks, and untracked-file handling — do not duplicate or paraphrase the full protocol here (single source of truth).
**Orchestrator note:** After each task, the spawned executor reports commit hashes; this workflow does not re-specify commit semantics beyond pointing at the executor.
</task_commit>
@@ -294,7 +290,7 @@ If verification fails:
**Check if node repair is enabled** (default: on):
```bash
NODE_REPAIR=$(node "./.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.node_repair 2>/dev/null || echo "true")
NODE_REPAIR=$(gsd-sdk query config-get workflow.node_repair 2>/dev/null || echo "true")
```
If `NODE_REPAIR` is `true`: invoke `@./.claude/get-shit-done/workflows/node-repair.md` with:
@@ -353,7 +349,7 @@ Next: more plans → "Ready for {next-plan}" | last → "Phase complete, ready f
handles STATE.md/ROADMAP.md updates centrally after merging worktrees to avoid
merge conflicts).
Update STATE.md using gsd-tools:
Update STATE.md using gsd-sdk query (or legacy gsd-tools) state mutations:
```bash
# Auto-detect parallel mode: .git is a file in worktrees, a directory in main repo
@@ -362,13 +358,13 @@ IS_WORKTREE=$([ -f .git ] && echo "true" || echo "false")
# Skip in parallel mode — orchestrator handles STATE.md centrally
if [ "$IS_WORKTREE" != "true" ]; then
# Advance plan counter (handles last-plan edge case)
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state advance-plan
gsd-sdk query state.advance-plan
# Recalculate progress bar from disk state
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state update-progress
gsd-sdk query state.update-progress
# Record execution metrics
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-metric \
gsd-sdk query state.record-metric \
--phase "${PHASE}" --plan "${PLAN}" --duration "${DURATION}" \
--tasks "${TASK_COUNT}" --files "${FILE_COUNT}"
fi
@@ -381,19 +377,19 @@ From SUMMARY: Extract decisions and add to STATE.md:
```bash
# Add each decision from SUMMARY key-decisions
# Prefer file inputs for shell-safe text (preserves `$`, `*`, etc. exactly)
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state add-decision \
gsd-sdk query state.add-decision \
--phase "${PHASE}" --summary-file "${DECISION_TEXT_FILE}" --rationale-file "${RATIONALE_FILE}"
# Add blockers if any found
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state add-blocker --text-file "${BLOCKER_TEXT_FILE}"
gsd-sdk query state.add-blocker --text-file "${BLOCKER_TEXT_FILE}"
```
</step>
<step name="update_session_continuity">
Update session info using gsd-tools:
Update session info using gsd-sdk query (or legacy gsd-tools):
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state record-session \
gsd-sdk query state.record-session \
--stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md" \
--resume-file "None"
```
@@ -415,7 +411,7 @@ IS_WORKTREE=$([ -f .git ] && echo "true" || echo "false")
# Skip in parallel mode — orchestrator handles ROADMAP.md centrally
if [ "$IS_WORKTREE" != "true" ]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap update-plan-progress "${PHASE}"
gsd-sdk query roadmap.update-plan-progress "${PHASE}"
fi
```
Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct count and status (`In Progress` or `Complete` with date).
@@ -425,7 +421,7 @@ Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct co
Mark completed requirements from the PLAN.md frontmatter `requirements:` field:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" requirements mark-complete ${REQ_IDS}
gsd-sdk query requirements.mark-complete ${REQ_IDS}
```
Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`). If no requirements field, skip.
@@ -440,9 +436,9 @@ IS_WORKTREE=$([ -f .git ] && echo "true" || echo "false")
# In parallel mode: exclude STATE.md and ROADMAP.md (orchestrator commits these)
if [ "$IS_WORKTREE" = "true" ]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/REQUIREMENTS.md
gsd-sdk query commit "docs({phase}-{plan}): complete [plan-name] plan" .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/REQUIREMENTS.md
else
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
gsd-sdk query commit "docs({phase}-{plan}): complete [plan-name] plan" .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
fi
```
</step>
@@ -458,7 +454,7 @@ git diff --name-only ${FIRST_TASK}^..HEAD 2>/dev/null || true
Update only structural changes: new src/ dir → STRUCTURE.md | deps → STACK.md | file pattern → CONVENTIONS.md | API client → INTEGRATIONS.md | config → STACK.md | renamed → update paths. Skip code-only/bugfix/content changes.
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "" --files .planning/codebase/*.md --amend
gsd-sdk query commit "" .planning/codebase/*.md --amend
```
</step>

View File

@@ -111,7 +111,7 @@ For each selected output, write the file:
Commit if `commit_docs` is enabled:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: capture exploration — {topic_slug}" --files {file_list}
gsd-sdk query commit "docs: capture exploration — {topic_slug}" {file_list}
```
## Step 6: Close

View File

@@ -16,7 +16,7 @@ Analyze completed phase artifacts (PLAN.md, SUMMARY.md, VERIFICATION.md, UAT.md,
Parse arguments and load project state:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${PHASE_ARG}")
INIT=$(gsd-sdk query init.phase-op "${PHASE_ARG}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -179,7 +179,7 @@ The body follows this structure:
Update STATE.md to reflect the learning extraction:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state update "Last Activity" "$(date +%Y-%m-%d)"
gsd-sdk query state.update "Last Activity" "$(date +%Y-%m-%d)"
```
</step>

View File

@@ -259,7 +259,7 @@ gh issue create \
## Step 8: Update STATE.md
```bash
gsd-tools.cjs state record-session \
--stopped-at "Forensic investigation complete" \
--resume-file ".planning/forensics/report-{timestamp}.md"
gsd-sdk query state.record-session "" \
"Forensic investigation complete" \
".planning/forensics/report-{timestamp}.md"
```

View File

@@ -25,7 +25,7 @@ fi
**Run health validation:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" validate health $REPAIR_FLAG
gsd-sdk query validate.health $REPAIR_FLAG
```
Parse JSON output:
@@ -112,7 +112,7 @@ If yes, re-run with --repair flag and display results.
Re-run health check without --repair to confirm issues are resolved:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" validate health
gsd-sdk query validate.health
```
Report final status.

View File

@@ -248,7 +248,7 @@ Update `.planning/STATE.md` if appropriate (e.g., increment total plan count).
Commit the imported plan and updated files:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs({phase}): import plan from {basename FILEPATH}" --files .planning/phases/{phase}/{plan}-PLAN.md .planning/ROADMAP.md
gsd-sdk query commit "docs({phase}): import plan from {basename FILEPATH}" .planning/phases/{phase}/{plan}-PLAN.md .planning/ROADMAP.md
```
Display completion:

View File

@@ -34,7 +34,7 @@ Validate first argument is an integer.
Load phase operation context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op "${after_phase}")
INIT=$(gsd-sdk query init.phase-op "${after_phase}")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -46,10 +46,10 @@ Exit.
</step>
<step name="insert_phase">
**Delegate the phase insertion to gsd-tools:**
**Delegate the phase insertion to `gsd-sdk query phase.insert`:**
```bash
RESULT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phase insert "${after_phase}" "${description}")
RESULT=$(gsd-sdk query phase.insert "${after_phase}" "${description}")
```
The CLI handles:
@@ -122,7 +122,7 @@ Project state updated: .planning/STATE.md
<success_criteria>
Phase insertion is complete when:
- [ ] `gsd-tools phase insert` executed successfully
- [ ] `gsd-sdk query phase.insert` executed successfully
- [ ] Phase directory created
- [ ] Roadmap updated with new phase entry (includes "(INSERTED)" marker)
- [ ] STATE.md updated with roadmap evolution note

View File

@@ -11,7 +11,7 @@ Read all files referenced by the invoking prompt's execution_context before star
## 1. Setup
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init list-workspaces)
INIT=$(gsd-sdk query init.list-workspaces)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```

View File

@@ -19,7 +19,7 @@ Read all files referenced by the invoking prompt's execution_context before star
Bootstrap via manager init:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init manager)
INIT=$(gsd-sdk query init.manager)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
@@ -30,7 +30,7 @@ Parse JSON for: `milestone_version`, `milestone_name`, `phase_count`, `completed
- `manager_flags.plan` — appended to plan agent init command
- `manager_flags.execute` — appended to execute agent init command
These are empty strings by default. Set via: `gsd-tools config-set manager.flags.discuss "--auto --analyze"`
These are empty strings by default. Set via: `gsd-sdk query config-set manager.flags.discuss "--auto --analyze"`
**If error:** Display the error message and exit.
@@ -60,7 +60,7 @@ Proceed to dashboard step.
**Every time this step is reached**, re-read state from disk to pick up changes from background agents:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init manager)
INIT=$(gsd-sdk query init.manager)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```

View File

@@ -31,9 +31,9 @@ Documents are reference material for Claude when planning/executing. Always incl
Load codebase mapping context:
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init map-codebase)
INIT=$(gsd-sdk query init.map-codebase)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_MAPPER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-codebase-mapper 2>/dev/null)
AGENT_SKILLS_MAPPER=$(gsd-sdk query agent-skills gsd-codebase-mapper 2>/dev/null)
```
Extract from init JSON: `mapper_model`, `commit_docs`, `codebase_dir`, `existing_maps`, `has_maps`, `codebase_dir_exists`, `subagent_timeout`.
@@ -314,7 +314,7 @@ Continue to commit_codebase_map.
Commit the codebase map:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: map existing codebase" --files .planning/codebase/*.md
gsd-sdk query commit "docs: map existing codebase" .planning/codebase/*.md
```
Continue to offer_next.
@@ -345,7 +345,7 @@ Created .planning/codebase/:
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Initialize project** — use codebase context for planning

View File

@@ -53,7 +53,7 @@ Read all files that exist. Missing files are fine — the summary adapts to what
Find all phase directories:
```bash
gsd-tools.cjs init progress
gsd-sdk query init.progress
```
This returns phase metadata. For each phase in the milestone scope:
@@ -189,8 +189,8 @@ mkdir -p .planning/reports
Write the summary, then commit:
```bash
gsd-tools.cjs commit "docs(v${VERSION}): generate milestone summary for onboarding" \
--files ".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
gsd-sdk query commit "docs(v${VERSION}): generate milestone summary for onboarding" \
".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
```
## Step 7: Present Summary
@@ -217,7 +217,7 @@ If the user is done:
## Step 9: Update STATE.md
```bash
gsd-tools.cjs state record-session \
--stopped-at "Milestone v${VERSION} summary generated" \
--resume-file ".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
gsd-sdk query state.record-session "" \
"Milestone v${VERSION} summary generated" \
".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
```

View File

@@ -191,21 +191,21 @@ Delete MILESTONE-CONTEXT.md if exists (consumed).
Clear leftover phase directories from the previous milestone:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phases clear --confirm
gsd-sdk query phases.clear --confirm
```
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: start milestone v[X.Y] [Name]" --files .planning/PROJECT.md .planning/STATE.md
gsd-sdk query commit "docs: start milestone v[X.Y] [Name]" .planning/PROJECT.md .planning/STATE.md
```
## 7. Load Context and Resolve Models
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init new-milestone)
INIT=$(gsd-sdk query init.new-milestone)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_RESEARCHER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-project-researcher 2>/dev/null)
AGENT_SKILLS_SYNTHESIZER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-synthesizer 2>/dev/null)
AGENT_SKILLS_ROADMAPPER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-roadmapper 2>/dev/null)
AGENT_SKILLS_RESEARCHER=$(gsd-sdk query agent-skills gsd-project-researcher 2>/dev/null)
AGENT_SKILLS_SYNTHESIZER=$(gsd-sdk query agent-skills gsd-synthesizer 2>/dev/null)
AGENT_SKILLS_ROADMAPPER=$(gsd-sdk query agent-skills gsd-roadmapper 2>/dev/null)
```
Extract from init JSON: `researcher_model`, `synthesizer_model`, `roadmapper_model`, `commit_docs`, `research_enabled`, `current_milestone`, `project_exists`, `roadmap_exists`, `latest_completed_milestone`, `phase_dir_count`, `phase_archive_path`.
@@ -409,7 +409,7 @@ If "adjust": Return to scoping.
**Commit requirements:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: define milestone v[X.Y] requirements" --files .planning/REQUIREMENTS.md
gsd-sdk query commit "docs: define milestone v[X.Y] requirements" .planning/REQUIREMENTS.md
```
## 10. Create Roadmap
@@ -493,7 +493,7 @@ Success criteria:
**Commit roadmap** (after approval):
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: create milestone v[X.Y] roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md
gsd-sdk query commit "docs: create milestone v[X.Y] roadmap ([N] phases)" .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md
```
## 11. Done
@@ -514,7 +514,7 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: create milest
**[N] phases** | **[X] requirements** | Ready to build ✓
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase [N]: [Phase Name]** — [Goal]

View File

@@ -57,11 +57,11 @@ The document should describe what you want to build.
**MANDATORY FIRST STEP — Execute these checks before ANY user interaction:**
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init new-project)
INIT=$(gsd-sdk query init.new-project)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_RESEARCHER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-project-researcher 2>/dev/null)
AGENT_SKILLS_SYNTHESIZER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-synthesizer 2>/dev/null)
AGENT_SKILLS_ROADMAPPER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-roadmapper 2>/dev/null)
AGENT_SKILLS_RESEARCHER=$(gsd-sdk query agent-skills gsd-project-researcher 2>/dev/null)
AGENT_SKILLS_SYNTHESIZER=$(gsd-sdk query agent-skills gsd-synthesizer 2>/dev/null)
AGENT_SKILLS_ROADMAPPER=$(gsd-sdk query agent-skills gsd-roadmapper 2>/dev/null)
```
Parse JSON for: `researcher_model`, `synthesizer_model`, `roadmapper_model`, `commit_docs`, `project_exists`, `has_codebase_map`, `planning_exists`, `has_existing_code`, `has_package_file`, `is_brownfield`, `needs_codebase_map`, `has_git`, `project_path`.
@@ -213,7 +213,7 @@ Create `.planning/config.json` with all settings (CLI fills in remaining default
```bash
mkdir -p .planning
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-new-project '{"mode":"yolo","granularity":"[selected]","parallelization":true|false,"commit_docs":true|false,"model_profile":"quality|balanced|budget|inherit","workflow":{"research":true|false,"plan_check":true|false,"verifier":true|false,"nyquist_validation":true|false,"auto_advance":true}}'
gsd-sdk query config-new-project '{"mode":"yolo","granularity":"[selected]","parallelization":true|false,"commit_docs":true|false,"model_profile":"quality|balanced|budget|inherit","workflow":{"research":true|false,"plan_check":true|false,"verifier":true|false,"nyquist_validation":true|false,"auto_advance":true}}'
```
**If commit_docs = No:** Add `.planning/` to `.gitignore`.
@@ -222,13 +222,13 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-new-project '{"mode"
```bash
mkdir -p .planning
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "chore: add project config" --files .planning/config.json
gsd-sdk query commit "chore: add project config" .planning/config.json
```
**Persist auto-advance chain flag to config (survives context compaction):**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active true
gsd-sdk query config-set workflow._auto_chain_active true
```
Proceed to Step 4 (skip Steps 3 and 5).
@@ -403,7 +403,7 @@ Do not compress. Capture everything gathered.
```bash
mkdir -p .planning
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: initialize project" --files .planning/PROJECT.md
gsd-sdk query commit "docs: initialize project" .planning/PROJECT.md
```
## 5. Workflow Preferences
@@ -533,7 +533,7 @@ Create `.planning/config.json` with all settings (CLI fills in remaining default
```bash
mkdir -p .planning
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-new-project '{"mode":"[yolo|interactive]","granularity":"[selected]","parallelization":true|false,"commit_docs":true|false,"model_profile":"quality|balanced|budget|inherit","workflow":{"research":true|false,"plan_check":true|false,"verifier":true|false,"nyquist_validation":[false if granularity=coarse, true otherwise]}}'
gsd-sdk query config-new-project '{"mode":"[yolo|interactive]","granularity":"[selected]","parallelization":true|false,"commit_docs":true|false,"model_profile":"quality|balanced|budget|inherit","workflow":{"research":true|false,"plan_check":true|false,"verifier":true|false,"nyquist_validation":[false if granularity=coarse, true otherwise]}}'
```
**Note:** Run `/gsd-settings` anytime to update model profile, workflow agents, branching strategy, and other preferences.
@@ -550,7 +550,7 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-new-project '{"mode"
**Commit config.json:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "chore: add project config" --files .planning/config.json
gsd-sdk query commit "chore: add project config" .planning/config.json
```
## 5.1. Sub-Repo Detection
@@ -994,7 +994,7 @@ If "adjust": Return to scoping.
**Commit requirements:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: define v1 requirements" --files .planning/REQUIREMENTS.md
gsd-sdk query commit "docs: define v1 requirements" .planning/REQUIREMENTS.md
```
## 8. Create Roadmap
@@ -1134,7 +1134,7 @@ Use AskUserQuestion:
**Generate or refresh project instruction file before final commit:**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" generate-claude-md --output "$INSTRUCTION_FILE"
gsd-sdk query generate-claude-md --output "$INSTRUCTION_FILE"
```
This ensures new projects get the default GSD workflow-enforcement guidance and current project context in `$INSTRUCTION_FILE`.
@@ -1142,7 +1142,7 @@ This ensures new projects get the default GSD workflow-enforcement guidance and
**Commit roadmap (after approval or auto mode):**
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md "$INSTRUCTION_FILE"
gsd-sdk query commit "docs: create roadmap ([N] phases)" .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md "$INSTRUCTION_FILE"
```
## 9. Done
@@ -1183,7 +1183,7 @@ Exit skill and invoke SlashCommand("/gsd-discuss-phase 1 --auto")
Check if Phase 1 has UI indicators (look for `**UI hint**: yes` in Phase 1 detail section of ROADMAP.md):
```bash
PHASE1_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase 1 2>/dev/null)
PHASE1_SECTION=$(gsd-sdk query roadmap.get-phase 1 2>/dev/null)
PHASE1_HAS_UI=$(echo "$PHASE1_SECTION" | grep -qi "UI hint.*yes" && echo "true" || echo "false")
```
@@ -1192,7 +1192,7 @@ PHASE1_HAS_UI=$(echo "$PHASE1_SECTION" | grep -qi "UI hint.*yes" && echo "true"
```
───────────────────────────────────────────────────────────────
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase 1: [Phase Name]** — [Goal from ROADMAP.md]
@@ -1214,7 +1214,7 @@ PHASE1_HAS_UI=$(echo "$PHASE1_SECTION" | grep -qi "UI hint.*yes" && echo "true"
```
───────────────────────────────────────────────────────────────
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase 1: [Phase Name]** — [Goal from ROADMAP.md]

View File

@@ -13,7 +13,7 @@ Read all files referenced by the invoking prompt's execution_context before star
**MANDATORY FIRST STEP — Execute init command:**
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init new-workspace)
INIT=$(gsd-sdk query init.new-workspace)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```

View File

@@ -14,7 +14,7 @@ Read project state to determine current position:
```bash
# Get state snapshot
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state json 2>/dev/null || echo "{}"
gsd-sdk query state.json 2>/dev/null || echo "{}"
```
Also read:
@@ -83,7 +83,7 @@ Use `--force` to bypass this check.
Exit.
**Prior-phase completeness scan:**
After passing all three hard-stop gates, scan all phases that precede the current phase in ROADMAP.md order for incomplete work. Use the existing `gsd-tools.cjs phase json <N>` output to inspect each prior phase.
After passing all three hard-stop gates, scan all phases that precede the current phase in ROADMAP.md order for incomplete work. For each prior phase number `N`, use `gsd-sdk query find-phase <N>` JSON (plans, summaries, incomplete_plans, etc.) to inspect that phase.
Detect three categories of incomplete work:
1. **Plans without summaries** — a PLAN.md exists in a prior phase directory but no matching SUMMARY.md exists (execution started but not completed).
@@ -127,7 +127,7 @@ Choice [S]:
```
2. Commit the deferral record:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: defer incomplete Phase {src} items to backlog"
gsd-sdk query commit "docs: defer incomplete Phase {src} items to backlog"
```
3. Continue routing to `determine_next_action` immediately — no second prompt.

View File

@@ -62,7 +62,7 @@ Report any summaries with placeholder content as incomplete items.
**Write structured handoff to `.planning/HANDOFF.json`:**
```bash
timestamp=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" current-timestamp full --raw)
timestamp=$(gsd-sdk query current-timestamp full --raw)
```
```json
@@ -197,13 +197,13 @@ Be specific enough for a fresh Claude to understand immediately.
Use `current-timestamp` for last_updated field. You can use init todos (which provides timestamps) or call directly:
```bash
timestamp=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" current-timestamp full --raw)
timestamp=$(gsd-sdk query current-timestamp full --raw)
```
</step>
<step name="commit">
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "wip: [context-name] paused at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
gsd-sdk query commit "wip: [context-name] paused at [X]/[Y]" [handoff-path] .planning/HANDOFF.json
```
</step>

View File

@@ -65,7 +65,7 @@ Gap: Flow "View dashboard" broken at data fetch
Find highest existing phase:
```bash
# Get sorted phase list, extract last one
HIGHEST=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" phases list --pick directories[-1])
HIGHEST=$(gsd-sdk query phases.list --pick directories[-1])
```
New phases continue from there:
@@ -146,7 +146,7 @@ mkdir -p ".planning/phases/{NN}-{name}"
## 9. Commit Roadmap and Requirements Update
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(roadmap): add gap closure phases {N}-{M}" --files .planning/ROADMAP.md .planning/REQUIREMENTS.md
gsd-sdk query commit "docs(roadmap): add gap closure phases {N}-{M}" .planning/ROADMAP.md .planning/REQUIREMENTS.md
```
## 10. Offer Next Steps
@@ -159,7 +159,7 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(roadmap): add
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Plan first gap closure phase**

View File

@@ -27,13 +27,13 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
Load all context in one call (paths only to minimize orchestrator context):
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init plan-phase "$PHASE")
INIT=$(gsd-sdk query init.plan-phase "$PHASE")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_RESEARCHER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-researcher 2>/dev/null)
AGENT_SKILLS_PLANNER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-planner 2>/dev/null)
AGENT_SKILLS_CHECKER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-checker 2>/dev/null)
CONTEXT_WINDOW=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get context_window 2>/dev/null || echo "200000")
TDD_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.tdd_mode 2>/dev/null || echo "false")
AGENT_SKILLS_RESEARCHER=$(gsd-sdk query agent-skills gsd-researcher 2>/dev/null)
AGENT_SKILLS_PLANNER=$(gsd-sdk query agent-skills gsd-planner 2>/dev/null)
AGENT_SKILLS_CHECKER=$(gsd-sdk query agent-skills gsd-checker 2>/dev/null)
CONTEXT_WINDOW=$(gsd-sdk query config-get context_window 2>/dev/null || echo "200000")
TDD_MODE=$(gsd-sdk query config-get workflow.tdd_mode 2>/dev/null || echo "false")
```
When `TDD_MODE` is `true`, the planner agent is instructed to apply `type: tdd` to eligible tasks using heuristics from `references/tdd.md`. The planner's `<required_reading>` is extended to include `@~/.claude/get-shit-done/references/tdd.md` so gate enforcement rules are available during planning.
@@ -86,7 +86,7 @@ Exit workflow.
## 3. Validate Phase
```bash
PHASE_INFO=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}")
PHASE_INFO=$(gsd-sdk query roadmap.get-phase "${PHASE}")
```
**If `found` is false:** Error with available phases. **If `found` is true:** Extract `phase_number`, `phase_name`, `goal` from JSON.
@@ -188,7 +188,7 @@ Use full relative paths. Group by topic area.]
5. Commit:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${padded_phase}): generate context from PRD" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
gsd-sdk query commit "docs(${padded_phase}): generate context from PRD" "${phase_dir}/${padded_phase}-CONTEXT.md"
```
6. Set `context_content` to the generated CONTEXT.md content and continue to step 5 (Handle Research).
@@ -207,7 +207,7 @@ If `context_path` is not null, display: `Using phase context from: ${context_pat
Read discuss mode for context gate label:
```bash
DISCUSS_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.discuss_mode 2>/dev/null || echo "discuss")
DISCUSS_MODE=$(gsd-sdk query config-get workflow.discuss_mode 2>/dev/null || echo "discuss")
```
If `TEXT_MODE` is true, present as a plain-text numbered list:
@@ -251,7 +251,7 @@ If "Run discuss-phase first":
```bash
AI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-AI-SPEC.md 2>/dev/null | head -1)
AI_PHASE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ai_integration_phase 2>/dev/null || echo "true")
AI_PHASE_CFG=$(gsd-sdk query config-get workflow.ai_integration_phase 2>/dev/null || echo "true")
```
**Skip if `AI_PHASE_CFG` is `false`.**
@@ -337,7 +337,7 @@ Display banner:
### Spawn gsd-phase-researcher
```bash
PHASE_DESC=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}" --pick section)
PHASE_DESC=$(gsd-sdk query roadmap.get-phase "${PHASE}" --pick section)
```
Research prompt:
@@ -418,9 +418,9 @@ test -f "${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md" && echo "VALIDATION_CREATED
> Skip if `workflow.security_enforcement` is explicitly `false`. Absent = enabled.
```bash
SECURITY_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.security_enforcement --raw 2>/dev/null || echo "true")
SECURITY_ASVS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.security_asvs_level --raw 2>/dev/null || echo "1")
SECURITY_BLOCK=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.security_block_on --raw 2>/dev/null || echo "high")
SECURITY_CFG=$(gsd-sdk query config-get workflow.security_enforcement --raw 2>/dev/null || echo "true")
SECURITY_ASVS=$(gsd-sdk query config-get workflow.security_asvs_level --raw 2>/dev/null || echo "1")
SECURITY_BLOCK=$(gsd-sdk query config-get workflow.security_block_on --raw 2>/dev/null || echo "high")
```
**If `SECURITY_CFG` is `false`:** Skip to step 5.6.
@@ -444,8 +444,8 @@ Continue to step 5.6. Security config is passed to the planner in step 8.
> Skip if `workflow.ui_phase` is explicitly `false` AND `workflow.ui_safety_gate` is explicitly `false` in `.planning/config.json`. If keys are absent, treat as enabled.
```bash
UI_PHASE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_phase 2>/dev/null || echo "true")
UI_GATE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.ui_safety_gate 2>/dev/null || echo "true")
UI_PHASE_CFG=$(gsd-sdk query config-get workflow.ui_phase 2>/dev/null || echo "true")
UI_GATE_CFG=$(gsd-sdk query config-get workflow.ui_safety_gate 2>/dev/null || echo "true")
```
**If both are `false`:** Skip to step 6.
@@ -453,7 +453,7 @@ UI_GATE_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get wo
Check if phase has frontend indicators:
```bash
PHASE_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}" 2>/dev/null)
PHASE_SECTION=$(gsd-sdk query roadmap.get-phase "${PHASE}" 2>/dev/null)
echo "$PHASE_SECTION" | grep -iE "UI|interface|frontend|component|layout|page|screen|view|form|dashboard|widget" > /dev/null 2>&1
HAS_UI=$?
```
@@ -473,7 +473,7 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
Read auto-chain state:
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
```
**If `AUTO_CHAIN` is `true` (running inside a `--chain` or `--auto` pipeline):**
@@ -513,7 +513,7 @@ Also available:
Check if any files in the phase scope match schema patterns:
```bash
PHASE_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${PHASE}" --pick section 2>/dev/null)
PHASE_SECTION=$(gsd-sdk query roadmap.get-phase "${PHASE}" --pick section 2>/dev/null)
```
Scan `PHASE_SECTION`, `CONTEXT.md` (if loaded), and `RESEARCH.md` (if exists) for file paths matching these ORM patterns:
@@ -613,7 +613,7 @@ VALIDATION_EXISTS=$(ls "${PHASE_DIR}"/*-VALIDATION.md 2>/dev/null | head -1)
If missing and Nyquist is still enabled/applicable — ask user:
1. Re-run: `/gsd-plan-phase {PHASE} --research ${GSD_WS}`
2. Disable Nyquist with the exact command:
`node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow.nyquist_validation false`
`gsd-sdk query config-set workflow.nyquist_validation false`
3. Continue anyway (plans fail Dimension 8)
Proceed to Step 7.8 (or Step 8 if pattern mapper is disabled) only if user selects 2 or 3.
@@ -624,7 +624,7 @@ Proceed to Step 7.8 (or Step 8 if pattern mapper is disabled) only if user selec
Check config:
```bash
PATTERN_MAPPER_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.pattern_mapper --default true 2>/dev/null)
PATTERN_MAPPER_CFG=$(gsd-sdk query config-get workflow.pattern_mapper 2>/dev/null || echo "true")
```
**If `PATTERN_MAPPER_CFG` is `false`:** Skip to step 8.
@@ -1022,8 +1022,8 @@ Skipping bounce step.
**Read pass count:**
```bash
BOUNCE_PASSES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.plan_bounce_passes --default 2)
BOUNCE_SCRIPT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.plan_bounce_script)
BOUNCE_PASSES=$(gsd-sdk query config-get workflow.plan_bounce_passes 2>/dev/null || echo "2")
BOUNCE_SCRIPT=$(gsd-sdk query config-get workflow.plan_bounce_script 2>/dev/null | jq -r '.' 2>/dev/null || true)
```
Display banner:
@@ -1068,7 +1068,7 @@ After the script returns, check that the bounced file still has valid YAML front
6. **Commit surviving bounced plans:** If at least one plan survived both the frontmatter validation and the checker re-run, commit the changes:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "refactor(${padded_phase}): bounce plans through external refinement" --files "${PHASE_DIR}/*-PLAN.md"
gsd-sdk query commit "refactor(${padded_phase}): bounce plans through external refinement" "${PHASE_DIR}/*-PLAN.md"
```
Display summary:
@@ -1134,7 +1134,7 @@ If `TEXT_MODE` is true, present as a plain-text numbered list (options already s
After plans pass all gates, record that planning is complete so STATE.md reflects the new phase status:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state planned-phase --phase "${PHASE_NUMBER}" --name "${PHASE_NAME}" --plans "${PLAN_COUNT}"
gsd-sdk query state.planned-phase --phase "${PHASE_NUMBER}" --name "${PHASE_NAME}" --plans "${PLAN_COUNT}"
```
This updates STATUS to "Ready to execute", sets the correct plan count, and timestamps Last Activity.
@@ -1145,25 +1145,25 @@ Route to `<offer_next>` OR `auto_advance` depending on flags/config.
## 15. Auto-Advance Check
Check for auto-advance trigger:
Check for auto-advance trigger using values already loaded in step 1:
1. Parse `--auto` and `--chain` flags from $ARGUMENTS
2. **Sync chain flag with intent** — if user invoked manually (no `--auto` and no `--chain`), clear the ephemeral chain flag from any previous interrupted `--auto` chain. This does NOT touch `workflow.auto_advance` (the user's persistent settings preference):
2. Use `auto_chain_active` and `auto_advance` from the INIT JSON parsed in step 1 — **do not issue additional `config-get` calls for these values** (they are already present in the init output). Issuing redundant `config-get` calls for values already in INIT can cause infinite read loops on some runtimes.
3. **Sync chain flag with intent** — if user invoked manually (no `--auto` and no `--chain`), clear the ephemeral chain flag from any previous interrupted `--auto` chain. This does NOT touch `workflow.auto_advance` (the user's persistent settings preference):
```bash
if [[ ! "$ARGUMENTS" =~ --auto ]] && [[ ! "$ARGUMENTS" =~ --chain ]]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active false 2>/dev/null
gsd-sdk query config-set workflow._auto_chain_active false 2>/dev/null
fi
```
3. Read both the chain flag and user preference:
```bash
AUTO_CHAIN=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
```
Set local variables from INIT (parsed once in step 1):
- `AUTO_CHAIN` = `auto_chain_active` from INIT JSON (boolean, default false)
- `AUTO_CFG` = `auto_advance` from INIT JSON (boolean, default false)
**If `--auto` or `--chain` flag present AND `AUTO_CHAIN` is not true:** Persist chain flag to config (handles direct invocation without prior discuss-phase):
```bash
if ([[ "$ARGUMENTS" =~ --auto ]] || [[ "$ARGUMENTS" =~ --chain ]]) && [[ "$AUTO_CHAIN" != "true" ]]; then
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-set workflow._auto_chain_active true
gsd-sdk query config-set workflow._auto_chain_active true
fi
```
@@ -1228,7 +1228,7 @@ Verification: {Passed | Passed with override | Skipped}
───────────────────────────────────────────────────────────────
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Execute Phase {X}** — run all {N} plans

View File

@@ -143,7 +143,7 @@ Related code and decisions found in the current codebase:
<step name="commit_seed">
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
gsd-sdk query commit "docs: plant seed — {$IDEA}" .planning/seeds/SEED-{PADDED}-{slug}.md
```
</step>

View File

@@ -1,7 +1,7 @@
<purpose>
Orchestrate the full developer profiling flow: consent, session analysis (or questionnaire fallback), profile generation, result display, and artifact creation.
This workflow wires Phase 1 (session pipeline) and Phase 2 (profiling engine) into a cohesive user-facing experience. All heavy lifting is done by existing gsd-tools.cjs subcommands and the gsd-user-profiler agent -- this workflow orchestrates the sequence, handles branching, and provides the UX.
This workflow wires Phase 1 (session pipeline) and Phase 2 (profiling engine) into a cohesive user-facing experience. All heavy lifting is done by existing `gsd-sdk query` handlers (with legacy `gsd-tools.cjs` parity where needed) and the gsd-user-profiler agent -- this workflow orchestrates the sequence, handles branching, and provides the UX.
</purpose>
<required_reading>
@@ -130,7 +130,7 @@ Display: "◆ Scanning sessions..."
Run session scan:
```bash
SCAN_RESULT=$(node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs scan-sessions --json 2>/dev/null)
SCAN_RESULT=$(gsd-sdk query scan-sessions --json 2>/dev/null)
```
Parse the JSON output to get session count and project count.
@@ -150,7 +150,7 @@ Display: "◆ Sampling messages..."
Run profile sampling:
```bash
SAMPLE_RESULT=$(node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs profile-sample --json 2>/dev/null)
SAMPLE_RESULT=$(gsd-sdk query profile-sample --json 2>/dev/null)
```
Parse the JSON output to get the temp directory path and message count.
@@ -201,7 +201,7 @@ Display: "Using questionnaire to build your profile."
**Get questions:**
```bash
QUESTIONS=$(node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs profile-questionnaire --json 2>/dev/null)
QUESTIONS=$(gsd-sdk query profile-questionnaire --json 2>/dev/null)
```
Parse the questions JSON. It contains 8 questions, one per dimension.
@@ -224,7 +224,7 @@ Write the answers JSON to `$ANSWERS_PATH`.
**Convert answers to analysis:**
```bash
ANALYSIS_RESULT=$(node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs profile-questionnaire --answers "$ANSWERS_PATH" --json 2>/dev/null)
ANALYSIS_RESULT=$(gsd-sdk query profile-questionnaire --answers "$ANSWERS_PATH" --json 2>/dev/null)
```
Parse the analysis JSON from the result.
@@ -271,7 +271,7 @@ Write updated analysis JSON back to `$ANALYSIS_PATH`.
Display: "◆ Writing profile..."
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs write-profile --input "$ANALYSIS_PATH" --json 2>/dev/null
gsd-sdk query write-profile --input "$ANALYSIS_PATH" --json 2>/dev/null
```
Display: "✓ Profile written to $HOME/.claude/get-shit-done/USER-PROFILE.md"
@@ -350,7 +350,7 @@ Generate selected artifacts sequentially (file I/O is fast, no benefit from para
**For /gsd-dev-preferences (if selected):**
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs generate-dev-preferences --analysis "$ANALYSIS_PATH" --json 2>/dev/null
gsd-sdk query generate-dev-preferences --analysis "$ANALYSIS_PATH" --json 2>/dev/null
```
Display: "✓ Generated /gsd-dev-preferences at $HOME/.claude/commands/gsd/dev-preferences.md"
@@ -358,7 +358,7 @@ Display: "✓ Generated /gsd-dev-preferences at $HOME/.claude/commands/gsd/dev-p
**For CLAUDE.md profile section (if selected):**
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs generate-claude-profile --analysis "$ANALYSIS_PATH" --json 2>/dev/null
gsd-sdk query generate-claude-profile --analysis "$ANALYSIS_PATH" --json 2>/dev/null
```
Display: "✓ Added profile section to CLAUDE.md"
@@ -366,12 +366,12 @@ Display: "✓ Added profile section to CLAUDE.md"
**For Global CLAUDE.md (if selected):**
```bash
node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs generate-claude-profile --analysis "$ANALYSIS_PATH" --global --json 2>/dev/null
gsd-sdk query generate-claude-profile --analysis "$ANALYSIS_PATH" --global --json 2>/dev/null
```
Display: "✓ Added profile section to $HOME/.claude/CLAUDE.md"
**Error handling:** If any gsd-tools.cjs call fails, display the error message and use AskUserQuestion to offer "Retry" or "Skip this artifact". On retry, re-run the command. On skip, continue to next artifact.
**Error handling:** If any `gsd-sdk query` or gsd-tools.cjs call fails, display the error message and use AskUserQuestion to offer "Retry" or "Skip this artifact". On retry, re-run the command. On skip, continue to next artifact.
---
@@ -446,7 +446,7 @@ rm -f "$ANALYSIS_PATH" 2>/dev/null
- [ ] Profile written to USER-PROFILE.md via write-profile subcommand
- [ ] Result display shows report card table and highlight reel with evidence
- [ ] Artifact selection uses multiSelect with all options pre-selected
- [ ] Artifacts generated sequentially via gsd-tools.cjs subcommands
- [ ] Artifacts generated sequentially via gsd-sdk query (or gsd-tools.cjs) subcommands
- [ ] Refresh diff shows changed dimensions when --refresh was used
- [ ] Temp files cleaned up on completion
</success_criteria>

View File

@@ -12,14 +12,14 @@ Read all files referenced by the invoking prompt's execution_context before star
**Load progress context (paths only):**
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init progress)
INIT=$(gsd-sdk query init.progress)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```
Extract from init JSON: `project_exists`, `roadmap_exists`, `state_exists`, `phases`, `current_phase`, `next_phase`, `milestone_version`, `completed_count`, `phase_count`, `paused_at`, `state_path`, `roadmap_path`, `project_path`, `config_path`.
```bash
DISCUSS_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.discuss_mode 2>/dev/null || echo "discuss")
DISCUSS_MODE=$(gsd-sdk query config-get workflow.discuss_mode 2>/dev/null || echo "discuss")
```
If `project_exists` is false (no `.planning/` directory):
@@ -42,11 +42,11 @@ If missing both ROADMAP.md and PROJECT.md: suggest `/gsd-new-project`.
</step>
<step name="load">
**Use structured extraction from gsd-tools:**
**Use structured extraction from `gsd-sdk query` (or legacy gsd-tools.cjs):**
Instead of reading full files, use targeted tools to get only the data needed for the report:
- `ROADMAP=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze)`
- `STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state-snapshot)`
- `ROADMAP=$(gsd-sdk query roadmap.analyze)`
- `STATE=$(gsd-sdk query state-snapshot)`
This minimizes orchestrator context usage.
</step>
@@ -55,7 +55,7 @@ This minimizes orchestrator context usage.
**Get comprehensive roadmap analysis (replaces manual parsing):**
```bash
ROADMAP=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze)
ROADMAP=$(gsd-sdk query roadmap.analyze)
```
This returns structured JSON with:
@@ -74,7 +74,7 @@ Use this instead of manually reading/parsing ROADMAP.md.
- Find the 2-3 most recent SUMMARY.md files
- Use `summary-extract` for efficient parsing:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" summary-extract <path> --fields one_liner
gsd-sdk query summary-extract <path> --fields one_liner
```
- This shows "what we've been working on"
</step>
@@ -89,11 +89,11 @@ Use this instead of manually reading/parsing ROADMAP.md.
</step>
<step name="report">
**Generate progress bar from gsd-tools, then present rich status report:**
**Generate progress bar from `gsd-sdk query progress` / `progress.json`, then present rich status report:**
```bash
# Get formatted progress bar
PROGRESS_BAR=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" progress bar --raw)
PROGRESS_BAR=$(gsd-sdk query progress.bar --raw)
```
Present:
@@ -168,7 +168,7 @@ Track:
Scan ALL phases in the current milestone for outstanding verification debt using the CLI (which respects milestone boundaries via `getMilestonePhaseFilter`):
```bash
DEBT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" audit-uat --raw 2>/dev/null)
DEBT=$(gsd-sdk query audit-uat --raw 2>/dev/null)
```
Parse JSON for `summary.total_items` and `summary.total_files`.
@@ -211,7 +211,7 @@ Read its `<objective>` section.
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**{phase}-{plan}: [Plan Name]** — [objective summary from PLAN.md]
@@ -231,7 +231,7 @@ Check if `{phase_num}-CONTEXT.md` exists in phase directory.
Check if current phase has UI indicators:
```bash
PHASE_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "${CURRENT_PHASE}" 2>/dev/null)
PHASE_SECTION=$(gsd-sdk query roadmap.get-phase "${CURRENT_PHASE}" 2>/dev/null)
PHASE_HAS_UI=$(echo "$PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true" || echo "false")
```
@@ -240,7 +240,7 @@ PHASE_HAS_UI=$(echo "$PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true" ||
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
<sub>✓ Context gathered, ready to plan</sub>
@@ -257,7 +257,7 @@ PHASE_HAS_UI=$(echo "$PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true" ||
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
@@ -280,7 +280,7 @@ PHASE_HAS_UI=$(echo "$PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true" ||
```
---
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
@@ -377,7 +377,7 @@ Read ROADMAP.md to get the next phase's name and goal.
Check if next phase has UI indicators:
```bash
NEXT_PHASE_SECTION=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap get-phase "$((Z+1))" 2>/dev/null)
NEXT_PHASE_SECTION=$(gsd-sdk query roadmap.get-phase "$((Z+1))" 2>/dev/null)
NEXT_HAS_UI=$(echo "$NEXT_PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true" || echo "false")
```
@@ -388,7 +388,7 @@ NEXT_HAS_UI=$(echo "$NEXT_PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true
## ✓ Phase {Z} Complete
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase {Z+1}: {Name}** — {Goal from ROADMAP.md}
@@ -413,7 +413,7 @@ NEXT_HAS_UI=$(echo "$NEXT_PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true
## ✓ Phase {Z} Complete
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Phase {Z+1}: {Name}** — {Goal from ROADMAP.md}
@@ -441,7 +441,7 @@ NEXT_HAS_UI=$(echo "$NEXT_PHASE_SECTION" | grep -qi "UI hint.*yes" && echo "true
All {N} phases finished!
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Complete Milestone** — archive and prepare for next
@@ -472,7 +472,7 @@ Read MILESTONES.md to find the last completed milestone version.
Ready to plan the next milestone.
## ▶ Next Up
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Start Next Milestone** — questioning → research → requirements → roadmap
@@ -492,7 +492,119 @@ Ready to plan the next milestone.
- All work complete → offer milestone completion
- Blockers present → highlight before offering to continue
- Handoff file exists → mention it, offer `/gsd-resume-work ${GSD_WS}`
</step>
</step>
<step name="forensic_audit">
**Forensic Integrity Audit** — only runs when `--forensic` is present in ARGUMENTS.
If `--forensic` is NOT present in ARGUMENTS: skip this step entirely. Default progress behavior (standard report + routing) is unchanged.
If `--forensic` IS present: after the standard report and routing suggestion have been displayed, append the following audit section.
---
## Forensic Integrity Audit
Running 6 deep checks against project state...
Run each check in order. For each check, emit ✓ (pass) or ⚠ (warning) with concrete evidence when a problem is found.
**Check 1 — STATE vs artifact consistency**
Read STATE.md `status` / `stopped_at` fields (from the STATE snapshot already loaded). Compare against the artifact count from the roadmap analysis. If STATE.md claims the current phase is pending/mid-flight but the artifact count shows it as complete (all PLAN.md files have matching SUMMARY.md files), flag inconsistency. Emit:
- ✓ `STATE.md consistent with artifact count` — if both agree
- ⚠ `STATE.md claims [status] but artifact count shows phase complete` — with the specific values
**Check 2 — Orphaned handoff files**
Check for existence of:
```bash
ls .planning/HANDOFF.json .planning/phases/*/.continue-here.md .planning/phases/*/*HANDOFF*.md 2>/dev/null || true
```
Also check `.planning/continue-here.md`.
Emit:
- ✓ `No orphaned handoff files` — if none found
- ⚠ `Orphaned handoff files found` — list each file path, add: `→ Work was paused mid-flight. Read the handoff before continuing.`
**Check 3 — Deferred scope drift**
Search phase artifacts (CONTEXT.md, DISCUSSION-LOG.md, BUG-BRIEF.md, VERIFICATION.md, SUMMARY.md, HANDOFF.md files under `.planning/phases/`) for patterns:
```bash
grep -rl "defer to Phase\|future phase\|out of scope Phase\|deferred to Phase" .planning/phases/ 2>/dev/null || true
```
For each match, extract the referenced phase number. Cross-reference against ROADMAP.md phase list. If the referenced phase number is NOT in ROADMAP.md, flag as deferred scope not captured.
Emit:
- ✓ `All deferred scope captured in ROADMAP` — if no mismatches
- ⚠ `Deferred scope references phase(s) not in ROADMAP` — list: file, reference text, missing phase number
**Check 4 — Memory-flagged pending work**
Check if `.planning/MEMORY.md` or `.planning/memory/` exists:
```bash
ls .planning/MEMORY.md .planning/memory/*.md 2>/dev/null || true
```
If found, grep for entries containing: `pending`, `status`, `deferred`, `not yet run`, `backfill`, `blocking`.
Emit:
- ✓ `No memory entries flagging pending work` — if none found or no MEMORY.md
- ⚠ `Memory entries flag pending/deferred work` — list the matching lines (max 5, truncated at 80 chars)
**Check 5 — Blocking operational todos**
Check for pending todos:
```bash
ls .planning/todos/pending/*.md 2>/dev/null || true
```
For files found, scan for keywords indicating operational blockers: `script`, `credential`, `API key`, `manual`, `verification`, `setup`, `configure`, `run `.
Emit:
- ✓ `No blocking operational todos` — if no pending todos or none match operational keywords
- ⚠ `Blocking operational todos found` — list the file names and matching keywords (max 5)
**Check 6 — Uncommitted code**
```bash
git status --porcelain 2>/dev/null | grep -v "^??" | grep -v "^.planning\/" | grep -v "^\.\." | head -10
```
If output is non-empty (modified/staged files outside `.planning/`), flag as uncommitted code.
Emit:
- ✓ `Working tree clean` — if no modified files outside `.planning/`
- ⚠ `Uncommitted changes in source files` — list up to 10 file paths
---
After all 6 checks, display the verdict:
**If all 6 checks passed:**
```
### Verdict: CLEAN
The standard progress report is trustworthy — proceed with the routing suggestion above.
```
**If 1 or more checks failed:**
```
### Verdict: N INTEGRITY ISSUE(S) FOUND
The standard progress report may not reflect true project state.
Review the flagged items above before acting on the routing suggestion.
```
Then for each failed check, add a concrete next action:
- Check 2 (orphaned handoff): `Read the handoff file(s) and resume from where work was paused: /gsd-resume-work ${GSD_WS}`
- Check 3 (deferred scope): `Add the missing phases to ROADMAP.md or update the deferred references`
- Check 4 (memory pending): `Review the flagged memory entries and resolve or clear them`
- Check 5 (blocking todos): `Complete the operational steps in .planning/todos/pending/ before continuing`
- Check 6 (uncommitted code): `Commit or stash the uncommitted changes before advancing`
- Check 1 (STATE inconsistency): `Run /gsd-verify-work ${PHASE} ${GSD_WS} to reconcile state`
</step>
</process>

View File

@@ -36,6 +36,8 @@ Parse `$ARGUMENTS` for:
- `--research` flag → store `$RESEARCH_MODE=true`
- Remaining text → use as `$DESCRIPTION` if non-empty
After parsing, normalize: if `$DISCUSS_MODE` and `$RESEARCH_MODE` and `$VALIDATE_MODE` are all true, set `$FULL_MODE=true`. This ensures `--discuss --research --validate` is treated identically to `--full`.
If `$DESCRIPTION` is empty after parsing, prompt user interactively:
@@ -64,15 +66,6 @@ If `$FULL_MODE` (all phases enabled — `--full` or all granular flags):
◆ Discussion + research + plan checking + verification enabled
```
If `$DISCUSS_MODE` and `$RESEARCH_MODE` and `$VALIDATE_MODE` (no `$FULL_MODE` — composed granularly):
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► QUICK TASK (DISCUSS + RESEARCH + VALIDATE)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ Discussion + research + plan checking + verification enabled
```
If `$DISCUSS_MODE` and `$VALIDATE_MODE` (no research):
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -132,18 +125,18 @@ If `$VALIDATE_MODE` only:
**Step 2: Initialize**
```bash
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init quick "$DESCRIPTION")
INIT=$(gsd-sdk query init.quick "$DESCRIPTION")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_PLANNER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-planner 2>/dev/null)
AGENT_SKILLS_EXECUTOR=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-executor 2>/dev/null)
AGENT_SKILLS_CHECKER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-checker 2>/dev/null)
AGENT_SKILLS_VERIFIER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-verifier 2>/dev/null)
AGENT_SKILLS_PLANNER=$(gsd-sdk query agent-skills gsd-planner 2>/dev/null)
AGENT_SKILLS_EXECUTOR=$(gsd-sdk query agent-skills gsd-executor 2>/dev/null)
AGENT_SKILLS_CHECKER=$(gsd-sdk query agent-skills gsd-checker 2>/dev/null)
AGENT_SKILLS_VERIFIER=$(gsd-sdk query agent-skills gsd-verifier 2>/dev/null)
```
Parse JSON for: `planner_model`, `executor_model`, `checker_model`, `verifier_model`, `commit_docs`, `branch_name`, `quick_id`, `slug`, `date`, `timestamp`, `quick_dir`, `task_dir`, `roadmap_exists`, `planning_exists`.
```bash
USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.use_worktrees 2>/dev/null || echo "true")
USE_WORKTREES=$(gsd-sdk query config-get workflow.use_worktrees 2>/dev/null || echo "true")
```
If the project uses git submodules, worktree isolation is skipped:
@@ -628,10 +621,21 @@ After executor returns:
# Snapshot files on main to detect resurrections
PRE_MERGE_FILES=$(git ls-files .planning/)
git merge "$WT_BRANCH" --no-edit -m "chore: merge quick task worktree ($WT_BRANCH)" 2>&1 || {
echo "⚠ Merge conflict — resolve manually"
# Pre-merge deletion guard: block merges that delete tracked .planning/ files
DELETIONS=$(git diff --diff-filter=D --name-only HEAD..."$WT_BRANCH" 2>/dev/null || true)
if [ -n "$DELETIONS" ]; then
echo "BLOCKED: Worktree branch $WT_BRANCH contains file deletions: $DELETIONS"
echo "Review these deletions before merging. If intentional, remove this guard and re-run."
rm -f "$STATE_BACKUP" "$ROADMAP_BACKUP"
continue
fi
git merge "$WT_BRANCH" --no-ff --no-edit -m "chore: merge quick task worktree ($WT_BRANCH)" 2>&1 || {
echo "⚠ Merge conflict from worktree $WT_BRANCH — resolve manually"
echo " STATE.md backup: $STATE_BACKUP"
echo " ROADMAP.md backup: $ROADMAP_BACKUP"
echo " Restore with: cp \$STATE_BACKUP .planning/STATE.md && cp \$ROADMAP_BACKUP .planning/ROADMAP.md"
break
}
# Restore orchestrator-owned files
@@ -639,7 +643,7 @@ After executor returns:
if [ -s "$ROADMAP_BACKUP" ]; then cp "$ROADMAP_BACKUP" .planning/ROADMAP.md; fi
rm -f "$STATE_BACKUP" "$ROADMAP_BACKUP"
# Remove files deleted on main but re-added by worktree
# Remove files deleted on main but re-added by worktree (--no-ff guarantees a merge commit so HEAD~1 is reliable)
DELETED_FILES=$(git diff --diff-filter=A --name-only HEAD~1 -- .planning/ 2>/dev/null || true)
for RESURRECTED in $DELETED_FILES; do
if ! echo "$PRE_MERGE_FILES" | grep -qxF "$RESURRECTED"; then
@@ -649,7 +653,7 @@ After executor returns:
if ! git diff --quiet .planning/STATE.md .planning/ROADMAP.md 2>/dev/null || \
[ -n "$DELETED_FILES" ]; then
COMMIT_DOCS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get commit_docs 2>/dev/null || echo "true")
COMMIT_DOCS=$(gsd-sdk query config-get commit_docs 2>/dev/null || echo "true")
if [ "$COMMIT_DOCS" != "false" ]; then
git add .planning/STATE.md .planning/ROADMAP.md 2>/dev/null || true
git commit --amend --no-edit 2>/dev/null || true
@@ -680,7 +684,7 @@ Skip this step entirely if `$FULL_MODE` is false.
**Config gate:**
```bash
CODE_REVIEW_ENABLED=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.code_review 2>/dev/null || echo "true")
CODE_REVIEW_ENABLED=$(gsd-sdk query config-get workflow.code_review 2>/dev/null || echo "true")
```
If `"false"`, skip with message "Code review skipped (workflow.code_review=false)".
@@ -827,7 +831,7 @@ Use Edit tool to make these changes atomically
**Step 8: Final commit and completion**
Stage and commit quick task artifacts. This step MUST always run — even if the executor already committed some files (e.g. when running without worktree isolation). The `gsd-tools commit` command handles already-committed files gracefully.
Stage and commit quick task artifacts. This step MUST always run — even if the executor already committed some files (e.g. when running without worktree isolation). The `gsd-sdk query commit` command (or legacy `gsd-tools.cjs` commit) handles already-committed files gracefully.
Build file list:
- `${QUICK_DIR}/${quick_id}-PLAN.md`
@@ -841,14 +845,14 @@ Build file list:
# Explicitly stage all artifacts before commit — PLAN.md may be untracked
# if the executor ran without worktree isolation and committed docs early
# Filter .planning/ files from staging if commit_docs is disabled (#1783)
COMMIT_DOCS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get commit_docs 2>/dev/null || echo "true")
COMMIT_DOCS=$(gsd-sdk query config-get commit_docs 2>/dev/null || echo "true")
if [ "$COMMIT_DOCS" = "false" ]; then
file_list_filtered=$(echo "${file_list}" | tr ' ' '\n' | grep -v '^\.planning/' | tr '\n' ' ')
git add ${file_list_filtered} 2>/dev/null
else
git add ${file_list} 2>/dev/null
fi
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(quick-${quick_id}): ${DESCRIPTION}" --files ${file_list}
gsd-sdk query commit "docs(quick-${quick_id}): ${DESCRIPTION}" ${file_list}
```
Get final commit hash:

Some files were not shown because too many files have changed in this diff Show More