mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
Compare commits
29 Commits
fix/2240-i
...
feat/2318-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53078d3f85 | ||
|
|
712e381f13 | ||
|
|
09e471188d | ||
|
|
d3a79917fa | ||
|
|
762b8ed25b | ||
|
|
5f521e0867 | ||
|
|
55877d372f | ||
|
|
779bd1a383 | ||
|
|
509a431438 | ||
|
|
a13c4cee3e | ||
|
|
6ef3255f78 | ||
|
|
ef5b0c187f | ||
|
|
262b395879 | ||
|
|
d9a4e5bf40 | ||
|
|
7b0a8b6237 | ||
|
|
899419ebec | ||
|
|
1005f02db2 | ||
|
|
4f5ffccec7 | ||
|
|
62261a3166 | ||
|
|
8f1dd94495 | ||
|
|
875b257c18 | ||
|
|
7b85d9e689 | ||
|
|
fa02cd2279 | ||
|
|
2f28c99db4 | ||
|
|
e1fe12322c | ||
|
|
32ab8ac77e | ||
|
|
8b94f0370d | ||
|
|
4a34745950 | ||
|
|
c051e71851 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>"
|
||||
```
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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:**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
133
bin/install.js
133
bin/install.js
@@ -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
|
||||
|
||||
@@ -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:**
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
38
commands/gsd/inbox.md
Normal 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>
|
||||
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:**
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/`
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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.
|
||||
|
||||
22
docs/gsd-sdk-query-migration-blurb.md
Normal file
22
docs/gsd-sdk-query-migration-blurb.md
Normal 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.
|
||||
92
docs/skills/discovery-contract.md
Normal file
92
docs/skills/discovery-contract.md
Normal 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`
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -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;
|
||||
|
||||
277
get-shit-done/references/autonomous-smart-discuss.md
Normal file
277
get-shit-done/references/autonomous-smart-discuss.md
Normal 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
|
||||
```
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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>
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}`
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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:**
|
||||
|
||||
@@ -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:**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):**
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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"
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
```
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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**
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user