When model_profile is "inherit", execute-phase was passing the literal string
"inherit" to Task(model=), causing fallback to the default model. The workflow
now documents that executor_model=="inherit" requires omitting the model= parameter
entirely so Claude Code inherits the orchestrator model automatically.
Closes#2516
Scan REQUIREMENTS.md body for all **REQ-ID** patterns during phase
complete and emit a warning for any IDs absent from the Traceability
table, regardless of whether the roadmap has a Requirements: line.
Closes#2526
Use process.platform !== 'win32' guard in catch instead of a comment, and add
regression test for bug #2525 (gsd-sdk bin symlink points at non-executable file).
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Step 8 file list omitted deferred-items.md, leaving executor out-of-scope
findings untracked after final commit even with commit_docs: true.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sdk): forward --ws workstream flag through query dispatch (closes#2524)
- cli.ts: pass args.ws as workstream to registry.dispatch()
- registry.ts: add workstream? param to dispatch(), thread to handler
- utils.ts: add optional workstream? to QueryHandler type signature
- helpers.ts: planningPaths() accepts workstream? and uses relPlanningPath()
- All ~26 query handlers updated to receive and pass workstream to planningPaths()
- Config/commit/intel handlers use _workstream (project-global, not scoped)
- Add failing-then-passing test: tests/bug-2524-sdk-query-ws-flag.test.cjs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sdk): forward workstream to all downstream query helpers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): rewrite #2524 test as static source assertions — no sdk/dist build in CI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Flips the bias in step 8b: build a simple HTML page/web UI by default,
fall back to stdout only for pure fact-checking (binary yes/no, benchmarks).
Mirrors upstream spike-idea skill constraint #3 update.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Spike workflow:
- Add frontier mode (no-arg or "frontier" proposes integration + frontier spikes)
- Add depth-over-speed principle — follow surprising findings, test edge cases,
document investigation trail not just verdict
- Add CONVENTIONS.md awareness — follow established patterns, update after session
- Add Requirements section in MANIFEST — track design decisions as they emerge
- Add re-ground step before each spike to prevent drift in long sessions
- Add Investigation Trail section to README template
- Restructured prior context loading with priority ordering
- Research step now runs per-spike with briefing and approach comparison table
Sketch workflow:
- Add frontier mode (no-arg or "frontier" proposes consistency + frontier sketches)
- Add spike context loading — ground mockups in real data shapes, requirements,
and conventions from spike findings
Spike wrap-up workflow:
- Add CONVENTIONS.md generation step (recurring stack/structure/pattern choices)
- Reference files now use implementation blueprint format (Requirements, How to
Build It, What to Avoid, Constraints)
- SKILL.md now includes requirements section from MANIFEST
- Next-steps route to /gsd-spike frontier mode instead of inline analysis
Sketch wrap-up workflow:
- Next-steps route to /gsd-sketch frontier mode
Commands updated with frontier mode in descriptions and argument hints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Spike workflow:
- Add frontier mode (no-arg or "frontier" proposes integration + frontier spikes)
- Add depth-over-speed principle — follow surprising findings, test edge cases,
document investigation trail not just verdict
- Add CONVENTIONS.md awareness — follow established patterns, update after session
- Add Requirements section in MANIFEST — track design decisions as they emerge
- Add re-ground step before each spike to prevent drift in long sessions
- Add Investigation Trail section to README template
- Restructured prior context loading with priority ordering
- Research step now runs per-spike with briefing and approach comparison table
Sketch workflow:
- Add frontier mode (no-arg or "frontier" proposes consistency + frontier sketches)
- Add spike context loading — ground mockups in real data shapes, requirements,
and conventions from spike findings
Spike wrap-up workflow:
- Add CONVENTIONS.md generation step (recurring stack/structure/pattern choices)
- Reference files now use implementation blueprint format (Requirements, How to
Build It, What to Avoid, Constraints)
- SKILL.md now includes requirements section from MANIFEST
- Next-steps route to /gsd-spike frontier mode instead of inline analysis
Sketch wrap-up workflow:
- Next-steps route to /gsd-sketch frontier mode
Commands updated with frontier mode in descriptions and argument hints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(sdk): stripShippedMilestones handles inline SHIPPED headings; getMilestoneInfo prefers STATE.md
Fixes two compounding bugs:
- #2496: stripShippedMilestones only stripped <details> blocks, ignoring
'## Heading — ✅ SHIPPED ...' inline markers. Shipped milestone sections
were leaking into downstream parsers.
- #2495: getMilestoneInfo checked STATE.md frontmatter only as a last-resort
fallback, so it returned the first heading match (often a leaked shipped
milestone) rather than the current milestone. Moved STATE.md check to
priority 1, consistent with extractCurrentMilestone.
Closes#2495Closes#2496
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(roadmap): handle ### SHIPPED headings and STATE.md version-only case
Two follow-up fixes from CodeRabbit review of #2508:
1. stripShippedMilestones only split on ## boundaries; ### headings marked
✅ SHIPPED were not stripped, leaking into fallback parsers. Expanded
the split/filter regex to #{2,3} to align with extractCurrentMilestone.
2. getMilestoneInfo's early-return on parseMilestoneFromState discarded the
real milestone name from ROADMAP.md when STATE.md had only `milestone:`
(no `milestone_name:`), returning the placeholder name 'milestone'.
Now only short-circuits when STATE.md provides a real name; otherwise
falls through to ROADMAP for the name while using stateVersion to
override the version in every ROADMAP-derived return path.
Tests: +2 new cases (### SHIPPED heading, version-only STATE.md).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(insert-phase): update STATE.md next-phase recommendation after inserting a phase
Closes#2502
* fix(insert-phase): update all STATE.md pointers; tighten test scope
Two follow-up fixes from CodeRabbit review of #2509:
1. The update_project_state instruction only said to find "the line" for
the next-phase recommendation. STATE.md can have multiple pointers
(structured current_phase: field AND prose recommendation text).
Updated wording to explicitly require updating all of them in the same
edit.
2. The regression test for the next-phase pointer update scanned the
entire file, so a match anywhere would pass even if update_project_state
itself was missing the instruction. Scoped the assertion to only the
content inside <step name="update_project_state"> to prevent false
positives.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(detect-custom-files): exclude skills and command dirs not wiped by installer (closes#2505)
GSD_MANAGED_DIRS included 'skills' and 'command' directories, but the
installer never wipes those paths. Users with third-party skills installed
(40+ files, none in GSD's manifest) had every skill flagged as a "custom
file" requiring backup, producing noisy false-positive reports on every
/gsd-update run.
Removes 'skills' and 'command' from both gsd-tools.cjs and the SDK's
detect-custom-files.ts. Adds two regression tests confirming neither
directory is scanned.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(settings): warn that model profiles are no-ops on non-Claude runtimes (closes#2506)
settings.md presented Quality/Balanced/Budget model profiles without any
indication that these tiers map to Claude models (Opus/Sonnet/Haiku) and
have no effect on non-Claude runtimes (Codex, Gemini CLI, OpenRouter).
Users on Codex saw the profile chooser as if it would meaningfully select
models, but all agents silently used the runtime default regardless.
Adds a non-Claude runtime note before the profile question (shown in
TEXT_MODE, the path all non-Claude runtimes take) explaining the profiles
are no-ops and directing users to either choose Inherit or configure
model_overrides manually. Also updates the Inherit option description to
explicitly name the runtimes where it is the correct choice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The guard at the worktree-merge resurrection block was inverting the
intended logic: it deleted any .planning/ file absent from PRE_MERGE_FILES,
which includes brand-new files (e.g. SUMMARY.md just created by the
executor). A genuine resurrection is a file that was previously tracked on
main, deliberately removed, and then re-introduced by the merge. Detecting
that requires a git history check — not just tree membership.
Fix: replace the PRE_MERGE_FILES grep guard with a `git log --follow
--diff-filter=D` check that only removes the file if it has a deletion
event in main's ancestry.
Closes#2501
* feat(plan-phase): chunked mode + filesystem fallback for Windows stdio hang (#2310)
Addresses the 2026-04-16 Windows incident where gsd-planner wrote all 5
PLAN.md files to disk but Task() never returned, hanging the orchestrator
for 30+ minutes. Two mitigations:
1. Filesystem fallback (steps 9a, 11a): when Task() returns with an
empty/truncated response but PLAN.md files exist on disk, surface a
recoverable prompt (Accept plans / Retry planner / Stop) instead of
silently failing. Directly addresses the post-restart recovery path.
2. Chunked mode (--chunked flag / workflow.plan_chunked config): splits the
single long-lived planner Task into a short outline Task (~2 min) followed
by N short per-plan Tasks (~3-5 min each). Each plan is committed
individually for crash resilience. A hang loses one plan, not all of them.
Resume detection skips plans already on disk on re-run.
RCA confirmed: task state mtime 14:29 vs PLAN.md writes 14:32-14:52 =
subagent completed normally, IPC return was dropped by Windows stdio deadlock.
Neither mitigation fixes the root cause (requires upstream Task() timeout
support); both bound damage and enable recovery.
New reference file planner-chunked.md keeps OUTLINE COMPLETE / PLAN COMPLETE
return formats out of gsd-planner.md (which sits at 46K near its size limit).
Closes#2310
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(plan-phase): address CodeRabbit review comments on #2499
- docs/CONFIGURATION.md: add workflow.plan_chunked to full JSON schema example
- plan-phase.md step 8.5.1: validate PLAN-OUTLINE.md with grep for OUTLINE
COMPLETE marker before reusing (not just file existence)
- plan-phase.md step 8.5.2: validate per-plan PLAN.md has YAML frontmatter
(head -1 grep for ---) before skipping in resume path
- plan-phase.md: add language tags (text/javascript/bash) to bare fenced
code blocks in steps 8.5, 9a, 11a (markdownlint MD040)
- Rejected: commit_docs gate on per-plan commits (gsd-sdk query commit
already respects commit_docs internally — comment was a false positive)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(plan-phase): route Accept-plans through step 9 PLANNING COMPLETE handling
Honors --skip-verify / plan_checker_enabled=false in 9a fallback path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(execute-phase): post-merge deletion audit for bulk file deletions (closes#2384)
Two data-loss incidents were caused by worktree merges bringing in bulk
file deletions silently. The pre-merge check (HEAD...WT_BRANCH) catches
deletions on the worktree branch, but files deleted during the merge
itself (e.g., from merge conflict resolution or stale branch state) were
not audited post-merge.
Adds a post-merge audit immediately after git merge --no-ff succeeds:
- Counts files deleted outside .planning/ in the merge commit
- If count > 5 and ALLOW_BULK_DELETE!=1: reverts the merge with
git reset --hard HEAD~1 and continues to the next worktree
- Logs the full file list and an escape-hatch instruction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): tighten post-merge deletion audit assertions (CodeRabbit #2483)
Replace loose substring checks with exact regex assertions:
- assert.match against 'git diff --diff-filter=D --name-only HEAD~1 HEAD'
- assert.match against threshold gate + ALLOW_BULK_DELETE override condition
- assert.match against git reset --hard HEAD~1 revert
- assert.match against MERGE_DEL_COUNT grep -vc for non-.planning count
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(inventory): update workflow count to 81 (graduation.md added in #2490)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(install): remove bare ~/.claude reference in update.md (closes#2470)
The installer's copyWithPathReplacement() replaces ~/\.claude\/ (with
trailing slash) but not ~/\.claude (bare, no trailing slash). A comment
on line 398 of update.md used the bare form, which scanForLeakedPaths()
correctly flagged for every non-Claude runtime install.
Replaced the example in the comment with a non-Claude runtime path so
the file passes the scanner for all runtimes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): align regex with installer's word-boundary semantics (CodeRabbit #2482)
Replace negative lookahead (?!\/) with \b word boundary to match the
installer's scanForLeakedPaths() pattern. The lookahead would incorrectly
flag ~/.claude_suffix whereas \b correctly excludes it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): revert \b regex — (?!\/) was intentionally scoped to bare refs
The installer's scanForLeakedPaths uses \b but the test is specifically
checking for bare ~/.claude without trailing slash that the replacer misses.
~/.claude/ (with slash) at line 359 of update.md is expected and handled.
\b would flag it as a false positive.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(inventory): update workflow count to 81 (graduation.md added in #2490)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(assembly): add link mode for CLAUDE.md @-reference sections (#2415)
Adds `claude_md_assembly.mode: "link"` config option that writes
`@.planning/<source>` instead of inlining content between GSD markers,
reducing typical CLAUDE.md size by ~65%. Per-block overrides available
via `claude_md_assembly.blocks.<section>`. Falls back to embed for
sections without a real source file (workflow, fallbacks).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): add positive assertion for embedded workflow content (CodeRabbit #2484)
The negative assertion only confirmed @GSD defaults wasn't written.
Add assert.ok(content.includes('GSD Workflow Enforcement')) to verify
the workflow section is actually embedded inline when link mode falls back.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds step 10.5 to gsd-new-milestone that scans pending todos against the
approved roadmap and tags matches with `resolves_phase: N` in their YAML
frontmatter. Adds a `close_phase_todos` step to execute-phase that moves
tagged todos to `completed/` when the phase completes — closing the loop
automatically with no manual cleanup.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update 5 source-text tests to read config-schema.cjs
VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the
drift-prevention companion PR. Tests that read config.cjs source text
and checked for key literal includes() now point to the correct file.
Closes#2480
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(cli): add /gsd-sync-skills for cross-runtime managed skill sync (#2380)
Adds /gsd-sync-skills command so multi-runtime users can keep gsd-* skill
directories aligned across runtime roots after updating one runtime with gsd-update.
Changes:
- bin/install.js: add --skills-root <runtime> flag that prints the skills root
path for any supported runtime, reusing the existing getGlobalDir() table.
Banner is suppressed when --skills-root is used (machine-readable output).
- commands/gsd/sync-skills.md: slash command definition
- get-shit-done/workflows/sync-skills.md: full workflow spec covering argument
parsing, path resolution via --skills-root, diff computation (CREATE/UPDATE/
REMOVE/SKIP), dry-run report (default), apply execution, idempotency guarantee,
and safety rules (only gsd-* touched, dry-run performs no writes).
Safety rules: only gsd-* directories are ever created/updated/removed; non-GSD
skills in destination roots are never touched; --dry-run is the default.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update 5 source-text tests to read config-schema.cjs
VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the
drift-prevention companion PR. Tests that read config.cjs source text
and checked for key literal includes() now point to the correct file.
Closes#2480
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(workflows): close LEARNINGS.md consumption-and-graduation loop (#2430)
Part A — Consumption: extend plan-phase.md cross-phase context load to include
LEARNINGS.md files from the 3 most recent prior phases (same recency gate as
CONTEXT.md + SUMMARY.md: CONTEXT_WINDOW >= 500000 only). Also loads LEARNINGS.md
from any phases in the Depends-on chain. Silent skip if absent; 15% context
budget cap with oldest-first truncation; [from Phase N LEARNINGS] attribution.
Part B — Graduation: add graduation_scan step to transition.md (after
evolve_project) that delegates to new graduation.md helper workflow. The helper
clusters recurring items across the last N phases (default window=5, threshold=3)
using Jaccard lexical similarity, surfaces HITL Promote/Defer/Dismiss prompts,
routes promotions to PROJECT.md or PATTERNS.md by category, annotates graduated
items with `graduated:` field, and persists dismissed/deferred clusters in
STATE.md graduation_backlog. Always non-blocking; silently no-ops on first phase
or when data is insufficient.
Also: adds optional `graduated:` annotation docs to extract_learnings.md schema.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(graduation): address CodeRabbit review findings on PR #2490
- graduation.md: unify insufficient-data guard to silent-skip (remove
contradictory [no-op] print path)
- graduation.md: add TEXT_MODE fallback for HITL cluster prompts
- graduation.md: add A (defer-all) to accepted actions [P/D/X/A]
- graduation.md: tag untyped code fences with text language (MD040)
- transition.md: tag untyped graduation.md fence with text language
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(graduation): rephrase TEXT_MODE line to avoid prompt-injection scanner false positive
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds artifacts.cjs with canonical .planning/ root file names, W019 warning
in gsd-health that flags unrecognized .md files at the .planning/ root, and
templates/README.md as the authoritative artifact index for agents and humans.
Closes#2448
* fix(tests): update 5 source-text tests to read config-schema.cjs
VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the
drift-prevention companion PR. Tests that read config.cjs source text
and checked for key literal includes() now point to the correct file.
Closes#2480
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(agents): sycophancy hardening for 9 audit-class agents (#2427)
Add adversarial reviewer posture to gsd-plan-checker, gsd-code-reviewer,
gsd-security-auditor, gsd-verifier, gsd-eval-auditor, gsd-nyquist-auditor,
gsd-ui-auditor, gsd-integration-checker, and gsd-doc-verifier.
Four changes per agent:
- Third-person framing: <role> opens with submission framing, not "You are a GSD X"
- FORCE stance: explicit starting hypothesis that the submission is flawed
- Failure modes: agent-specific list of how each reviewer type goes soft
- BLOCKER/WARNING classification: every finding must carry an explicit severity
Also applies to sdk/prompts/agents variants of gsd-plan-checker and gsd-verifier.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(roadmap): surface wave dependencies and cross-cutting constraints (#2447)
Adds roadmap.annotate-dependencies command that post-processes a phase's
ROADMAP plan list to insert wave dependency notes and surface must_haves.truths
entries shared across 2+ plans as cross-cutting constraints. Operation is
idempotent and purely derived from existing PLAN frontmatter.
Closes#2447
* fix(roadmap): address CodeRabbit review findings on PR #2487
- roadmap.cjs: expand idempotency guard to also check for existing
cross-cutting constraints header, preventing duplicate injection on
re-runs; add content equality check before writing to preserve
true idempotency for single-wave phases
- plan-phase.md: move ROADMAP annotation (13d) before docs commit (13c)
so annotated ROADMAP.md is included in the commit rather than left dirty;
include .planning/ROADMAP.md in committed files list
- sdk/src/query/index.ts: add annotate-dependencies aliases to
QUERY_MUTATION_COMMANDS so the mutation is properly event-wired
- sdk/src/query/roadmap.ts: add timeout (15s) and maxBuffer to spawnSync;
check result.error before result.status to handle spawn/timeout failures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds W018 warning when .planning/milestones/vX.Y-ROADMAP.md snapshots
exist without a corresponding entry in MILESTONES.md. Introduces
--backfill flag to synthesize missing entries from snapshot titles.
Closes#2446
* fix(tests): clear CLAUDECODE env var in read-guard test runner
The hook skips its advisory on two env vars: CLAUDE_SESSION_ID and
CLAUDECODE. runHook() cleared CLAUDE_SESSION_ID but inherited CLAUDECODE
from process.env, so tests run inside a Claude Code session silently
no-oped and produced no stdout, causing JSON.parse to throw.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ci): update ARCHITECTURE.md counts and add TEXT_MODE fallback to sketch workflow
Four new spike/sketch files were added in 1.37.0 but two housekeeping
items were missed: ARCHITECTURE.md component counts (75→79 commands,
72→76 workflows) and the required TEXT_MODE fallback in sketch.md for
non-Claude runtimes (#2012).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ci): update directory-tree slash command count in ARCHITECTURE.md
Missed the second count in the directory tree (# 75 slash commands → 79).
The prose "Total commands" was updated but the tree annotation was not,
causing command-count-sync.test.cjs to fail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- quick.md Step 5.6: commit PLAN.md to base branch before worktree executor
spawn when USE_WORKTREES is active, preventing CC #36182 path-resolution
drift that caused silent writes to main repo instead of worktree
- reapply-patches.md Option A: replace first-add commit heuristic with
pristine_hashes SHA-256 matching from backup-meta.json so baseline detection
works correctly on multi-cycle repos; first-add fallback kept for older
installers without pristine_hashes
- CONFIGURATION.md: move security_enforcement/security_asvs_level/security_block_on
to workflow.* (matches templates/config.json and workflow readers); rename
context_profile → context (matches VALID_CONFIG_KEYS in config.cjs); add
planning.sub_repos to schema example
- universal-anti-patterns.md + context-budget.md: fix context_window_tokens →
context_window (the actual key name in config.cjs)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
#2388 (plan-phase silently renames feature branch): add explicit Git
Branch Invariant section to plan-phase.md prohibiting branch
creation/rename/switch during planning; phase slug changes are
plan-level only and must not affect the git branch.
#2431 (worktree teardown silently swallows errors): replace
`git worktree remove --force 2>/dev/null || true` with a lock-aware
block in quick.md and execute-phase.md that detects locked worktrees,
attempts unlock+retry, and surfaces a user-visible recovery message
when removal still fails.
#2396 (hardcoded test commands bypass Makefile): add a three-tier
test command resolver (project config → Makefile/Justfile → language
sniff) in execute-phase.md, verify-phase.md, and audit-fix.md.
Makefile with a `test:` target now takes priority over npm/cargo/go.
#2376 (OpenCode @$HOME not mapped on Windows): add platform guard in
bin/install.js so OpenCode on win32 uses the absolute path instead of
`$HOME/...`, which OpenCode does not expand in @file references on
Windows.
Tests: 29 new assertions across 4 regression test files (all passing).
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- #2418: convertClaudeToAntigravityContent now replaces bare ~/.claude and
$HOME/.claude (no trailing slash) for both global and local installs,
eliminating the "unreplaced .claude path reference" warnings in
gsd-debugger.md and update.md during Antigravity installs.
- #2399: plan-phase workflow gains step 13c that commits PLAN.md files
and STATE.md via gsd-sdk query commit when commit_docs is true.
Previously commit_docs:true was read but never acted on in plan-phase.
- #2419: new-project.md and new-milestone.md now parse agents_installed
and missing_agents from the init JSON and warn users clearly when GSD
agents are not installed, rather than silently failing with "agent type
not found" when trying to spawn gsd-project-researcher subagents.
- #2421: gsd-planner.md gains a "Grep gate hygiene" rule immediately after
the Nyquist Rule explaining the self-invalidating grep gate anti-pattern
and providing comment-stripping alternatives (grep -v, ast-grep).
Tests: 4 new test files (30 tests) all passing.
Closes#2418Closes#2399Closes#2419Closes#2421
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(phase): guard backlog dirs and YYYY-MM dates in integer phase removal
Closes#2435Closes#2434
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(phase): extend date-collision guard to hyphen-adjacent context
The lookbehind `(?<!\d)` in renameIntegerPhases only excluded
digit-prefixed matches; a YYYY-MM-DD date like 2026-05-14 has a hyphen
before the month digits, which passed the original guard and caused
date corruption when renumbering a phase whose zero-padded number
matched the month. Replace with `(?<![0-9-])` lookbehind and
`(?![0-9-])` lookahead to exclude both digit- and hyphen-adjacent
contexts. Adds a regression test for the hyphen-adjacent case.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Four execFileSync installer calls in copilot-install.test.cjs deleted
GSD_TEST_MODE but omitted --no-sdk, triggering the fatal installSdkIfNeeded()
path in test.yml CI where npm global bin is not on PATH.
Partial fix in e213ce0 patched three hook-deployment tests but missed
runCopilotInstall, runCopilotUninstall, runClaudeInstall, runClaudeUninstall.
Also adds tests/sdk-no-sdk-guard.test.cjs: a static analysis guard that
scans test files for subprocess installer calls missing --no-sdk, so this
class of regression is caught automatically in future.
Closes#2461
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug #2453: After tsc builds sdk/dist/cli.js, npm install -g from a local
directory does not chmod the bin-script target (unlike tarball extraction).
The file lands at mode 644, the gsd-sdk symlink points at a non-executable
file, and command -v gsd-sdk fails on every first install. Fix: explicitly
chmodSync(cliPath, 0o755) immediately after npm install -g completes,
mirroring the pattern used for hook files throughout the installer.
Bug #2451: gsd-context-monitor warning messages over-reported usage by ~13
percentage points vs CC native /context. Root cause: gsd-statusline.js
wrote a buffer-normalized used_pct (accounting for the 16.5% autocompact
reserve) to the bridge file, inflating values. The bridge used_pct is now
raw (Math.round(100 - remaining_percentage)), consistent with what CC's
native /context command reports. The statusline progress bar continues to
display the normalized value; only the bridge value changes. Updated the
existing #2219 tests to check the normalized display via hook stdout rather
than bridge.used_pct, and added a new assertion that bridge.used_pct is raw.
Closes#2453Closes#2451
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sdk): extractCurrentMilestone Backlog leak + state.begin-phase flag parsing
Closes#2422Closes#2420
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#2444,#2445): scope stopped_at extraction to Session section; filter stale phase dirs
- buildStateFrontmatter now extracts stopped_at only from the ## Session
section when one exists, preventing historical prose elsewhere in the
body (e.g. "Stopped at: Phase 5 complete" in old notes) from overwriting
the current value in frontmatter (bug #2444)
- buildStateFrontmatter de-duplicates phase dirs by normalized phase number
before computing plan/phase counts, so stale phase dirs from a prior
milestone with the same phase numbers as the new milestone don't inflate
totals (bug #2445)
- cmdInitNewMilestone now filters phase dirs through getMilestonePhaseFilter
so phase_dir_count excludes stale prior-milestone dirs (bug #2445)
- Tests: 4 tests in state.test.cjs covering both bugs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sdk): extractCurrentMilestone Backlog leak + state.begin-phase flag parsing
Closes#2422Closes#2420
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sdk): skip stateVersion early-return for shipped milestones
When STATE.md has a stale `milestone: v1.0` entry but v1.0 is already
shipped (heading contains ✅ in ROADMAP.md), the stateVersion early-return
path in getMilestoneInfo was returning v1.0 instead of detecting the new
active milestone.
Two-part fix:
1. In the stateVersion block: skip the early-return when the matched
heading line includes ✅ (shipped marker). Fall through to normal
detection instead.
2. In the heading-format fallback regex: add a negative lookahead
`(?!.*✅)` so the regex never matches a ✅ heading regardless of
whether stateVersion was present. This handles the no-STATE.md case
and ensures fallthrough from part 1 actually finds the next milestone.
Adds two regression tests covering both ✅-suffix (`## v1.0 ✅ Name`)
and ✅-prefix (`## ✅ v1.0 Name`) heading formats.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(core): allow padded-and-unpadded phase headings in getRoadmapPhaseInternal
The zero-strip normalization (01→1) fixed the archived-phase guard but
broke lookup against ROADMAP headings that still use zero-padded numbers
like "Phase 01:". Change the regex to use 0*<normalized> so both formats
match, making the fix robust regardless of ROADMAP heading style.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(security): neutralize spaced+closing injection markers; fix audit-uat resolved status
scanForInjection recognizes — adds <user> tags, whitespace-padded tags
(e.g. <user >), closing [/SYSTEM]/[/INST] markers, and closing <</SYS>>
markers. Five new regression tests confirm each gap is closed.
whose result column reads PASS or resolved, so items that were already
confirmed do not appear as outstanding in audit-uat --raw. Two new
regression tests cover item-level PASS and file-level status: passed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add closing-tag assertion for spaced <user > sanitization
The test for 'neutralizes spaced tags like <user >' only asserted that the
opening token '<user' was removed. A spaced closing tag '</user >' could
survive sanitization undetected. Added assert.ok(!result.includes('</user'))
to the same test block so both sides of the tag are verified.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(sdk): extractCurrentMilestone Backlog leak + state.begin-phase flag parsing
Closes#2422Closes#2420
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: patch-version semver in milestone boundary regex + flag-parser validation
Two follow-on correctness issues identified in code review:
1. roadmap.ts: currentVersionMatch and nextMilestoneRegex only captured
major.minor (v(\d+\.\d+)), collapsing v2.0.1 to "2.0". A sub-heading
"## v2.0.2 Phase Details" would match the same prefix and be incorrectly
skipped. Both patterns updated to v(\d+(?:\.\d+)+) to capture full semver.
2. state-mutation.ts: pair-wise flag parsing loop advanced i by 2 unconditionally,
so a missing flag value caused the next flag token to be assigned as the value
(e.g. flags['phase'] = '--name'). Fix: iterate with i++ and validate that the
candidate value exists and does not start with '--' before assigning; throw
GSDError('missing value for --<key>') on invalid input. Added regression test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the
drift-prevention companion PR. Tests that read config.cjs source text
and checked for key literal includes() now point to the correct file.
Closes#2480
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Option A — ghost-entry guard (INVENTORY ⊆ actual):
tests/inventory-source-parity.test.cjs parses every declared row in
INVENTORY.md and asserts the source file exists. Catches deletions and
renames that leave ghost entries behind.
Option B — auto-generated structural manifest:
scripts/gen-inventory-manifest.cjs walks all six family dirs and emits
docs/INVENTORY-MANIFEST.json. tests/inventory-manifest-sync.test.cjs
fails CI when a new surface ships without a manifest update, surfacing
exactly which entries are missing.
Option C — schema-driven config validation + docs parity:
get-shit-done/bin/lib/config-schema.cjs extracted from config.cjs as
the single source of truth for VALID_CONFIG_KEYS and dynamic patterns.
config.cjs now imports from it. tests/config-schema-docs-parity.test.cjs
asserts every exact-match key appears in docs/CONFIGURATION.md, surfacing
14 previously undocumented keys (planning.sub_repos, workflow.ai_integration_phase,
git.base_branch, learnings.max_inject, and 10 others) — all now documented
in their appropriate sections.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: finish trust-bug fixes in user guide and commands
Correct load-bearing defects in the v1.36.0 docs corpus so readers stop
acting on wrong defaults and stale exhaustiveness claims.
- README.md: drop "Complete feature"/"Every command"/"All 18 agents"
exhaustiveness claims; replace version-pinned "What's new in v1.32"
bullet with a CHANGELOG pointer.
- CONFIGURATION.md: fix `claude_md_path` default (null/none -> `./CLAUDE.md`)
in both Full Schema and core settings table; correct `workflow.tdd_mode`
provenance from "Added in v1.37" to "Added in v1.36".
- USER-GUIDE.md: fix `workflow.discuss_mode` default (`standard` ->
`discuss`) in the workflow-toggles table AND in the abbreviated Full
Schema JSON block above it; align the Options cell with the shipped
enum.
- COMMANDS.md: drop "Complete command syntax" subtitle overclaim to
match the README posture.
- AGENTS.md: weaken "All 21 specialized agents" header to reflect that
the `agents/` filesystem is authoritative (shipped roster is 31).
Part 1 of a stacked docs refresh series (PR 1/4).
* docs: refresh shipped surface coverage for v1.36
Close the v1.36.0 shipped-surface gaps in the docs corpus.
- COMMANDS.md: add /gsd-graphify section (build/query/status/diff) and
its config gate; expand /gsd-quick with --validate flag and list/
status/resume subcommands; expand /gsd-thread with list --open, list
--resolved, close <slug>, status <slug>.
- CLI-TOOLS.md: replace the hardcoded "15 domain modules" count with a
pointer to the Module Architecture table; add a graphify verb-family
section (build/query/status/diff/snapshot); add Graphify and Learnings
rows to the Module Architecture table.
- FEATURES.md: add TOC entries for #116 TDD Pipeline Mode and #117
Knowledge Graph Integration; add the #117 body with REQ-GRAPH-01..05.
- CONFIGURATION.md: move security_enforcement / security_asvs_level /
security_block_on from root into `workflow.*` in Full Schema to match
templates/config.json and the gsd-sdk runtime reads; update Security
Settings table to use the workflow.* prefix; add planning.sub_repos
to Full Schema and description table; add a Graphify Settings section
documenting graphify.enabled and graphify.build_timeout.
Note: VALID_CONFIG_KEYS in bin/lib/config.cjs does not yet include
workflow.security_* or planning.sub_repos, so config-set currently
rejects them. That is a pre-existing validator gap that this PR does
not attempt to fix; the docs now correctly describe where these keys
live per the shipped template and runtime reads.
Part 2 of a stacked docs refresh series (PR 2/5), based on PR 1.
* docs: make inventory authoritative and reconcile architecture
Upgrade docs/INVENTORY.md from "complete for agents, selective for others"
to authoritative across all six shipped-surface families, and reconcile
docs/ARCHITECTURE.md against the new inventory so the PR that introduces
INVENTORY does not also introduce an INVENTORY/ARCHITECTURE contradiction.
- docs/AGENTS.md: weaken "21 specialized agents" header to 21 primary +
10 advanced (31 shipped); add new "Advanced and Specialized Agents"
section with concise role cards for the 10 previously-omitted shipped
agents (pattern-mapper, debug-session-manager, code-reviewer,
code-fixer, ai-researcher, domain-researcher, eval-planner,
eval-auditor, framework-selector, intel-updater); footnote the Agent
Tool Permissions Summary as primary-agents-only so it no longer
misleads.
- docs/INVENTORY.md (rewritten to be authoritative):
* Full 31-agent roster with one-line role + spawner + primary-doc
status per agent (unchanged from prior partial work).
* Commands: full 75-row enumeration grouped by Core Workflow, Phase &
Milestone Management, Session & Navigation, Codebase Intelligence,
Review/Debug/Recovery, and Docs/Profile/Utilities — each row
carries a one-line role derived from the command's frontmatter and
a link to the source file.
* Workflows: full 72-row enumeration covering every
get-shit-done/workflows/*.md, with a one-line role per workflow and
a column naming the user-facing command (or internal orchestrator)
that invokes it.
* References: full 41-row enumeration grouped by Core, Workflow,
Thinking-Model clusters, and the Modular Planner decomposition,
matching the groupings docs/ARCHITECTURE.md already uses; notes
the few-shot-examples subdirectory separately.
* CLI Modules and Hooks: unchanged — already full rosters.
* Maintenance section rewritten to describe the drift-guard test
suite that will land in PR4 (inventory-counts, commands-doc-parity,
agents-doc-parity, cli-modules-doc-parity, hooks-doc-parity).
- docs/ARCHITECTURE.md reconciled against INVENTORY:
* References block: drop the stale "(35 total)" count; point at
INVENTORY.md#references-41-shipped for the authoritative count.
* CLI Tools block: drop the stale "19 domain modules" count; point
at INVENTORY.md#cli-modules-24-shipped for the authoritative roster.
* Agent Spawn Categories: relabel as "Primary Agent Spawn Categories"
and add a footer naming the 10 advanced agents and pointing at
INVENTORY.md#agents-31-shipped for the full 31-agent roster.
- docs/CONFIGURATION.md: preserve the six model-profile rows added in
the prior partial work, and tighten the fallback note so it names the
13 shipped agents without an explicit profile row, documents
model_overrides as the escape hatch, and points at INVENTORY.md for
the authoritative 31-agent roster.
Part 3 of a stacked docs refresh series (PR 3/4). Remaining consistency
work (USER-GUIDE config-section delete-and-link, FEATURES.md TOC
reorder, ARCHITECTURE.md Hook-table expansion + installation-layout
collapse, CLI-TOOLS.md module-row additions, workflow-discuss-mode
invocation normalization, and the five doc-parity tests) lands in PR4.
* test(docs): add consistency guards and remove duplicate refs
Consolidates USER-GUIDE.md's command/config duplicates into pointers to
COMMANDS.md and CONFIGURATION.md (kills a ghost `resolve_model_ids` key
and a stale `discuss_mode: standard` default); reorders FEATURES.md TOC
chronologically so v1.32 precedes v1.34/1.35/1.36; expands
ARCHITECTURE.md's Hook table to the 11 shipped hooks
(gsd-read-injection-scanner, gsd-check-update-worker) and collapses
the installation-layout hook enumeration to the *.js/*.sh pattern form;
adds audit/gsd2-import/intel rows and state signal-*, audit-open,
from-gsd2 verbs to CLI-TOOLS.md; normalizes workflow-discuss-mode.md
invocations to `node gsd-tools.cjs config-set`.
Adds five drift guards anchored on docs/INVENTORY.md as the
authoritative roster: inventory-counts (all six families),
commands/agents/cli-modules/hooks parity checks that every shipped
surface has a row somewhere.
* fix(convergence): thread --ws to review agent; add stall and max-cycles behavioral tests
- Thread GSD_WS through to review agent spawn in plan-review-convergence
workflow (step 5a) so --ws scoping is symmetric with planning step
- Add behavioral stall detection test: asserts workflow compares
HIGH_COUNT >= prev_high_count and emits a stall warning
- Add behavioral --max-cycles 1 test: asserts workflow reaches escalation
gate when cycle >= MAX_CYCLES with HIGH > 0 after a single cycle
- Include original PR files (commands, workflow, tests) as the branch
predated the PR commits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(docs,config): PR #2390 review — security_* config keys and REQ-GRAPH-02 scope
Addresses trek-e's review items that don't require rebase:
- config.cjs: add workflow.security_enforcement, workflow.security_asvs_level,
workflow.security_block_on to VALID_CONFIG_KEYS so gsd-sdk config-set accepts
them (closed the gap where docs/CONFIGURATION.md listed keys the validator
rejected).
- core.cjs: add matching CONFIG_DEFAULTS entries (true / 1 / 'high') so the
canonical defaults table matches the documented values.
- config.cjs: wire the three keys into the new-project workflow defaults so
fresh configs inherit them.
- planning-config.md: document the three keys in the Workflow Fields table,
keeping the CONFIG_DEFAULTS ↔ doc parity test happy.
- config-field-docs.test.cjs: extend NAMESPACE_MAP so the flat keys in
CONFIG_DEFAULTS resolve to their workflow.* doc rows.
- FEATURES.md REQ-GRAPH-02: split the slash-command surface (build|query|
status|diff) from the CLI surface which additionally exposes `snapshot`
(invoked automatically at the tail of `graphify build`). The prior text
overstated the slash-command surface.
* docs(inventory): refresh rosters and counts for post-rebase drift
origin/main accumulated surfaces since this PR was authored:
- Agents: 31 → 33 (+ gsd-doc-classifier, gsd-doc-synthesizer)
- Commands: 76 → 82 (+ ingest-docs, ultraplan-phase, spike, spike-wrap-up,
sketch, sketch-wrap-up)
- Workflows: 73 → 79 (same 6 names)
- References: 41 → 49 (+ debugger-philosophy, doc-conflict-engine,
mandatory-initial-read, project-skills-discovery, sketch-interactivity,
sketch-theme-system, sketch-tooling, sketch-variant-patterns)
Adds rows in the existing sub-groupings, introduces a Sketch References
subsection, and bumps all four headline counts. Roles are pulled from
source frontmatter / purpose blocks for each file. All 5 parity tests
(inventory-counts, agents-doc-parity, commands-doc-parity,
cli-modules-doc-parity, hooks-doc-parity) pass against this state —
156 assertions, 0 failures.
Also updates the 'Coverage note' advanced-agent count 10 → 12 and the
few-shot-examples footnote "41 top-level references" → "49" to keep the
file internally consistent.
* docs(agents): add advanced stubs for gsd-doc-classifier and gsd-doc-synthesizer
Both agents ship on main (spawned by /gsd-ingest-docs) but had no
coverage in docs/AGENTS.md. Adds the "advanced stub" entries (Role,
property table, Key behaviors) following the template used by the other
10 advanced/specialized agents in the same section.
Also updates the Agent Tool Permissions Summary scope note from
"10 advanced/specialized agents" to 12 to reflect the two new stubs.
* docs(commands): add entries for ingest-docs, ultraplan-phase, plan-review-convergence
These three commands ship on main (plan-review-convergence via trek-e's
4b452d29 commit on this branch) but had no user-facing section in
docs/COMMANDS.md — they lived only in INVENTORY.md. The commands-doc-parity
test already passes via INVENTORY, but the user-facing doc was missing
canonical explanations, argument tables, and examples.
- /gsd-plan-review-convergence → Core Workflow (after /gsd-plan-phase)
- /gsd-ultraplan-phase → Core Workflow (after plan-review-convergence)
- /gsd-ingest-docs → Brownfield (after /gsd-import, since both consume
the references/doc-conflict-engine.md contract)
Content pulled from each command's frontmatter and workflow purpose block.
* test: remove redundant ARCHITECTURE.md count tests
tests/architecture-counts.test.cjs and tests/command-count-sync.test.cjs
were added when docs/ARCHITECTURE.md carried hardcoded counts for commands/
workflows/agents. With the PR #2390 cleanup, ARCHITECTURE.md no longer
owns those numbers — docs/INVENTORY.md does, enforced by
tests/inventory-counts.test.cjs (scans the same filesystem directories
with the same readdirSync filter).
Keeping these ARCHITECTURE-specific tests would re-introduce the hardcoded
counts they guard, defeating trek-e's review point. The single-source-of-
truth parity tests already catch the same drift scenarios.
Related: #2257 (the regression this replaced).
---------
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: clarify capture_thought is an optional convention (#1873)
Issue #1873 merged /gsd:extract-learnings with an optional
capture_thought hook, but the docs never explained what the tool is
or where it comes from — readers couldn't tell whether it was a
bundled GSD tool, a required dependency, or something they had to
install. This surfaced in a user question on that issue's thread.
Clarify in docs/FEATURES.md §112 and the workflow file that
capture_thought is a convention — any MCP server exposing a tool
with that name will be used; if none is present, LEARNINGS.md
remains the primary output and the step is a silent no-op.
No behavioral change. All 23 extract-learnings tests still pass.
* fix(security): add human to detection message; test [/INST] closing form neutralization
- Detection message now lists <human> alongside <system>/<assistant>/<user>
- Sanitizer regex extended to cover [/INST] closing form (was only [INST])
- Detection pattern extended to cover [/INST] closing form
- New sanitizeForPrompt test asserts [/INST] is neutralized
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(config): add workflow.security_* keys to VALID_CONFIG_KEYS
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add language tag to fenced code block in FEATURES.md
Fixes MD040 lint finding in PR #2379 — the capture_thought tool
signature example was missing a javascript language identifier.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>