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>
* fix(sdk): bump engines.node from >=20 to >=22.0.0
Node 20 reaches EOL April 30 2026. The root package already declares
>=22.0.0 and CI only runs Node 22 and 24. Align sdk/package.json so
`npm install` on Node 20 fails with a clear engines mismatch rather
than a silent install that breaks at runtime.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(release): publish @gsd-build/sdk alongside get-shit-done-cc in release pipeline
Closes#2309
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
debug.md was calling `config-get tdd_mode` (top-level key) while every
other consumer (execute-phase, verify-phase, audit-fix) uses
`config-get workflow.tdd_mode`. This caused /gsd-debug to silently
ignore the tdd_mode setting even when explicitly set in config.json.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Node 20 reaches EOL April 30 2026. The root package already declares
>=22.0.0 and CI only runs Node 22 and 24. Align sdk/package.json so
`npm install` on Node 20 fails with a clear engines mismatch rather
than a silent install that breaks at runtime.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests #1834, #1924, #2136 exercise hook/artifact deployment and don't
care about SDK install. Now that installSdkIfNeeded() failures are
fatal, these tests fail on any CI runner without gsd-sdk pre-built
because the sdk/ tsc build path runs and can fail in CI env.
Pass --no-sdk so each test focuses on its actual subject. SDK install
path has dedicated end-to-end coverage in install-smoke.yml.
## Why
#2386 added `installSdkIfNeeded()` to build @gsd-build/sdk from bundled
source and `npm install -g .`, because the npm-published @gsd-build/sdk
is intentionally frozen and version-mismatched with get-shit-done-cc.
But every failure path in that function was warning-only — including
the final `which gsd-sdk` verification. When npm's global bin is off a
user's PATH (common on macOS), the installer printed a yellow warning
then exited 0. Users saw "install complete" and then every `/gsd-*`
command crashed with `command not found: gsd-sdk` (the #2439 symptom).
No CI job executed the install path, so this class of regression could
ship undetected — existing "install" tests only read bin/install.js as
a string.
## What changed
**bin/install.js — installSdkIfNeeded() is now transactional**
- All build/install failures exit non-zero (not just warn).
- Post-install `which gsd-sdk` check is fatal: if the binary landed
globally but is off PATH, we exit 1 with a red banner showing the
resolved npm bin dir, the user's shell, the target rc file, and the
exact `export PATH=…` line to add.
- Escape hatch: `GSD_ALLOW_OFF_PATH=1` downgrades off-PATH to exit 2
for users with intentionally restricted PATH who will wire up the
binary manually.
- Resolver uses POSIX `command -v` via `sh -c` (replaces `which`) so
behavior is consistent across sh/bash/zsh/fish.
- Factored `resolveGsdSdk()`, `detectShellRc()`, `emitSdkFatal()`.
**.github/workflows/install-smoke.yml (new)**
- Executes the real install path: `npm pack` → `npm install -g <tgz>`
→ run installer non-interactively → `command -v gsd-sdk` → run
`gsd-sdk --version`.
- PRs: path-filtered to installer-adjacent files, ubuntu + Node 22 only.
- main/release branches: full matrix (ubuntu+macos × Node 22+24).
- Reusable via workflow_call with `ref` input for release gating.
**.github/workflows/release.yml — pre-publish gate**
- New `install-smoke-rc` and `install-smoke-finalize` jobs invoke the
reusable workflow against the release branch. `rc` and `finalize`
now `needs: [validate-version, install-smoke-*]`, so a broken SDK
install blocks `npm publish`.
## Test plan
- Local full suite: 4154/4154 pass
- install-smoke.yml will self-validate on this PR (ubuntu+Node22 only)
Addresses root cause of #2439 (the per-command pre-flight in #2440 is
the complementary defensive layer).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The ingest-docs workflow called `gsd-sdk query init.ingest-docs` with a
fallback to `init.default` — neither was registered in createRegistry(),
so the workflow proceeded with `{}` and tried to parse project_exists,
planning_exists, has_git, and project_path from empty.
- Add initIngestDocs handler; register dotted + space aliases
- Simplify workflow call; drop broken fallback
- Repo-wide drift guard scans commands/, agents/, get-shit-done/,
hooks/, bin/, scripts/, docs/ for `gsd-sdk query <cmd>` and fails
on any reference with no registered handler (file:line citations)
- Unit tests for the new handler
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Project convention (#1748) requires /gsd-<cmd> hyphen form everywhere
except designated test inputs. Fix the colon references in the
pre-flight error and its regression test to satisfy stale-colon-refs.
/gsd:set-profile crashed with `command not found: gsd-sdk` when gsd-sdk
was not on PATH. The command invoked `gsd-sdk query` directly in a `!`
backtick with no guard, so a missing binary produced an opaque shell
error with exit 127.
Add a `command -v gsd-sdk` pre-flight that prints the install/update
hint and exits 1 when absent, mirroring the #2334 fix on /gsd-quick.
The auto-install in #2386 still runs at install time; this guard is the
defensive layer for users whose npm global bin is off-PATH (install.js
warns but does not fail in that case).
Closes#2439
Surfaces the new ingest-docs command from the Unreleased changelog in
the README Commands section so users discover it without digging.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The scanner was added in #2201 but never added to the HOOKS_TO_COPY
allowlist in scripts/build-hooks.js, so it never landed in hooks/dist/.
install.js reads from hooks/dist/, so every install on 1.37.0/1.37.1
emitted "Skipped read injection scanner hook — not found at target"
and the read-time prompt-injection scanner was silently disabled.
- Add gsd-read-injection-scanner.js to HOOKS_TO_COPY
- Add it to EXPECTED_ALL_HOOKS regression test in install-hooks-copy
Fixes#2406
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>