2062 Commits

Author SHA1 Message Date
Tom Boucher
990c3e648d fix(tests): update 5 source-text tests to read config-schema.cjs (#2480)
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>
2026-04-20 09:54:35 -04:00
Tom Boucher
62eaa8dd7b docs: close doc drift vectors — bidirectional parity, manifest, schema-driven config (#2479)
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>
2026-04-20 09:39:05 -04:00
Logan
fbf30792f3 docs: authoritative shipped-surface inventory with filesystem-backed parity tests (#2390)
* 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>
2026-04-20 09:31:34 -04:00
alanshurafa
3d6c2bea4b docs: clarify capture_thought is an optional convention (#1873) (#2379)
* 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>
2026-04-20 09:04:21 -04:00
Tom Boucher
ebbe74de72 feat(release): publish @gsd-build/sdk alongside get-shit-done-cc in release pipeline (#2468)
* 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>
2026-04-19 23:13:14 -04:00
Tom Boucher
2bb1f1ebaf fix(debug): read tdd_mode via workflow.tdd_mode key (closes #2398) (#2454)
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>
2026-04-19 23:12:23 -04:00
Rezolv
39623fd5b8 docs(cli): deprecate gsd-tools.cjs header in favor of gsd-sdk (#2343) (#2343)
Single-file change: JSDoc @deprecated notice pointing to SDK query registry.
No .planning or unrelated merges.
2026-04-19 23:10:32 -04:00
Tom Boucher
e3f40201dd fix(sdk): bump engines.node from >=20 to >=22.0.0 (#2465)
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>
2026-04-19 23:02:57 -04:00
Jeremy McSpadden
2bb274930b Merge pull request #2452 from gsd-build/codex/merge-hotfix-1.38.1-qwen-path
fix(install): template bare .claude hook paths for non-Claude runtimes
2026-04-19 19:00:18 -05:00
Jeremy McSpadden
f874313807 fix(install): template bare .claude hook paths for non-Claude runtimes 2026-04-19 18:47:59 -05:00
Jeremy McSpadden
30433368a0 fix(install): template bare .claude hook paths for non-Claude runtimes v1.38.1 2026-04-19 18:42:30 -05:00
Jeremy McSpadden
04fab926b5 test: add --no-sdk to hook-deployment installer tests
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.
2026-04-19 18:39:32 -05:00
Jeremy McSpadden
f98ef1e460 fix(install): fatal SDK install failures + CI smoke gate (#2439)
## 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>
2026-04-19 18:39:32 -05:00
Jeremy McSpadden
d0565e95c1 fix(set-profile): use hyphenated /gsd-set-profile in pre-flight message
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.
2026-04-19 18:39:32 -05:00
Jeremy McSpadden
4ef6275e86 fix(set-profile): guard gsd-sdk invocation with command -v pre-flight (#2439)
/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
2026-04-19 18:39:32 -05:00
Jeremy McSpadden
6c50490766 fix(sdk): register init.ingest-docs handler and add registry drift guard (#2442)
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>
2026-04-19 18:39:20 -05:00
Jeremy McSpadden
4cbebfe78c docs(readme): add /gsd-ingest-docs to Brownfield commands
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>
2026-04-19 18:39:20 -05:00
Jeremy McSpadden
9e87d43831 fix(build): include gsd-read-injection-scanner in hooks/dist (#2406)
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>
2026-04-19 18:39:20 -05:00
github-actions[bot]
29ea90bc83 chore: bump version to 1.38.1 for hotfix 2026-04-19 23:37:15 +00:00
Jeremy McSpadden
278082a51d Merge pull request #2440 from gsd-build/fix/2439-command-not-found-gsd-sdk
fix(set-profile): guard gsd-sdk invocation with command -v pre-flight (#2439)
2026-04-19 18:26:22 -05:00
Jeremy McSpadden
de59b14dde Merge pull request #2449 from gsd-build/fix/2439-installer-sdk-hardening
fix(install): fatal SDK install failures + CI smoke gate (#2439)
2026-04-19 18:24:21 -05:00
Jeremy McSpadden
e213ce0292 test: add --no-sdk to hook-deployment installer tests
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.
2026-04-19 16:35:32 -05:00
Jeremy McSpadden
af66cd89ca fix(install): fatal SDK install failures + CI smoke gate (#2439)
## 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>
2026-04-19 16:31:15 -05:00
Jeremy McSpadden
48a354663e Merge pull request #2443 from gsd-build/fix/2442-gsd-sdk-query-registry-integration
fix(sdk): register init.ingest-docs handler and add registry drift guard
2026-04-19 15:58:17 -05:00
Jeremy McSpadden
0a62e5223e fix(sdk): register init.ingest-docs handler and add registry drift guard (#2442)
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>
2026-04-19 15:55:37 -05:00
Jeremy McSpadden
708f60874e fix(set-profile): use hyphenated /gsd-set-profile in pre-flight message
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.
2026-04-19 15:40:50 -05:00
Jeremy McSpadden
a20aa81a0e Merge pull request #2437 from gsd-build/docs/readme-ingest-docs
docs(readme): add /gsd-ingest-docs to Brownfield commands
2026-04-19 15:39:30 -05:00
Jeremy McSpadden
d8aaeb6717 fix(set-profile): guard gsd-sdk invocation with command -v pre-flight (#2439)
/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
2026-04-19 15:34:44 -05:00
Jeremy McSpadden
6727a0c929 docs(readme): add /gsd-ingest-docs to Brownfield commands
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>
2026-04-19 15:06:16 -05:00
Jeremy McSpadden
f330ab5c9f Merge pull request #2407 from gsd-build/fix/2406-ship-read-injection-scanner
fix(build): ship gsd-read-injection-scanner hook to users
2026-04-19 14:58:44 -05:00
Jeremy McSpadden
3856b53098 Merge remote-tracking branch 'origin/main' into fix/2406-ship-read-injection-scanner
# Conflicts:
#	CHANGELOG.md
2026-04-18 11:37:47 -05:00
Rezolv
0171f70553 feat(sdk): GSDTools native dispatch and CJS fallback routing (#2302 Track C) (#2342) 2026-04-18 12:35:23 -04:00
Tom Boucher
381c138534 feat(sdk): make checkAgentsInstalled runtime-aware (#2402) (#2413) 2026-04-18 12:22:36 -04:00
Jeremy McSpadden
8ac02084be fix(sdk): point checkAgentsInstalled at ~/.claude/agents (#2401) 2026-04-18 12:11:07 -04:00
Tom Boucher
e208e9757c refactor(agents): consolidate emphasis-marker density in top 4 agents (#2368) (#2412) 2026-04-18 12:10:22 -04:00
Jeremy McSpadden
13a96ee994 fix(build): include gsd-read-injection-scanner in hooks/dist (#2406)
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>
2026-04-18 08:42:36 -05:00
github-actions[bot]
0c6172bfad chore: finalize v1.38.0 v1.38.0 2026-04-18 03:45:59 +00:00
Jeremy McSpadden
e3bd06c9fd fix(release): make merge-back PR step non-fatal
Repos that disable "Allow GitHub Actions to create and approve pull
requests" (org-level policy or repo-level setting) cause the "Create PR
to merge release back to main" step to fail with a GraphQL 403. That
failure cascades: Tag and push, npm publish, GitHub Release creation
are all skipped, and the entire release aborts.

The merge-back PR is a convenience — it's re-openable manually after
the release. Making it non-fatal with continue-on-error lets the rest
of the release complete. The step now emits ::warning:: annotations
pointing at the manual-recovery command when it fails.

Shell pipelines also fall through with `|| echo "::warning::..."` so
transient gh CLI failures don't mask the underlying policy issue.

Covers the failure mode seen on run 24596079637 where dry-run publish
validation passed but the release halted at the PR-creation step.
2026-04-17 22:45:22 -05:00
github-actions[bot]
c69ecd975a chore: bump to 1.38.0-rc.1 v1.38.0-rc.1 2026-04-18 03:05:35 +00:00
Jeremy McSpadden
06c4ded4ec docs(changelog): promote Unreleased to [1.38.0] + add ultraplan entry 2026-04-17 22:03:26 -05:00
github-actions[bot]
341bb941c6 chore: bump version to 1.38.0 for release 2026-04-18 03:02:41 +00:00
Jeremy McSpadden
28d6649f0b Merge pull request #2389 from gsd-build/feat/2387-ingest-docs-clean
feat(ingest-docs): /gsd-ingest-docs — bootstrap or merge .planning/ from repo docs
2026-04-17 21:49:57 -05:00
Jeremy McSpadden
d5f849955b Merge remote-tracking branch 'origin/main' into feat/2387-ingest-docs-clean
# Conflicts:
#	CHANGELOG.md
2026-04-17 21:46:39 -05:00
Jeremy McSpadden
0f7bcabd78 Merge pull request #2386 from gsd-build/fix/2385-sdk-install-flag
fix(install): auto-install @gsd-build/sdk so gsd-sdk is on PATH
2026-04-17 21:45:17 -05:00
Jeremy McSpadden
fc1fa9172b fix(install): build gsd-sdk from in-repo sdk/ source, not stale npm package
PR #2386 v1 installed the published @gsd-build/sdk from npm, which ships an
older version that lacks query handlers needed by current workflows. Every
GSD release would drift further from what the installer put on PATH.

This commit rewires installSdkIfNeeded() to build from the in-repo sdk/
source tree instead:

  1. cd sdk && npm install     (build-time deps incl. tsc)
  2. npm run build             (tsc → sdk/dist/)
  3. npm install -g .          (global install; gsd-sdk on PATH)

Each step is a hard gate — failures warn loudly and point users at the
manual equivalent command. No more silent drift between installed SDK and
the rest of the GSD system.

Root package.json `files` now ships sdk/src, sdk/prompts, sdk/package.json,
sdk/package-lock.json, and sdk/tsconfig.json so npm-registry installs also
carry the source tree needed to build gsd-sdk locally.

Also fixes a blocking tsc error in sdk/src/event-stream.ts:313 — the cast
to `Array<{ type: string; [key: string]: unknown }>` needed a double-cast
via `unknown` because BetaContentBlock's variants don't carry an index
signature. Runtime-neutral type-widening; sdk vitest suite unchanged
(1256 passing; the lone failure is a pre-existing integration test that
requires external API access).

Updates the #1657/#2385 regression test to assert the new build-from-source
path (path.resolve(__dirname, '..', 'sdk') + `npm run build` + `npm install
-g .`) plus a new assertion that root package.json files array ships sdk
source.

Refs #2385

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 19:53:16 -05:00
Jeremy McSpadden
b96255cf0c test(ingest-docs): add structural tests and CHANGELOG entry
- tests/ingest-docs.test.cjs — 40 structural assertions guarding the
  contract: command/workflow/agent/reference files exist; frontmatter
  shape; --mode/--manifest/--resolve/path parsing; path traversal
  guard; 50-doc cap; auto mode-detect via planning_exists; directory
  conventions for ADR/PRD/SPEC; parallel classifier + synthesizer
  spawns; BLOCKER/WARNING/INFO severity and the no-write safety gate;
  gsd-roadmapper routing; --resolve interactive reserved-for-future;
  INGEST-CONFLICTS.md writing. Classifier covers 5 types, JSON schema,
  Accepted-only locking. Synthesizer covers precedence ordering,
  LOCKED-vs-LOCKED block in both modes, three-bucket report, cycle
  detection, variant preservation, SYNTHESIS.md entry point. Plus a
  regression guard that /gsd-import still consumes the shared
  doc-conflict-engine reference (refactor drift check).

- CHANGELOG.md — Unreleased "Added" entry for /gsd-ingest-docs (#2387).

Full suite: 4151/4151 passing.

Refs #2387

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:12:34 -05:00
Jeremy McSpadden
bfdf3c3065 feat(ingest-docs): add /gsd-ingest-docs workflow and command
Orchestrator for the ingest pipeline (#2387):

- commands/gsd/ingest-docs.md — /gsd-ingest-docs command with
  [path] [--mode] [--manifest] [--resolve] args; @-references the
  shared doc-conflict-engine so the BLOCKER gate semantics are
  inherited from the same contract /gsd-import consumes.

- get-shit-done/workflows/ingest-docs.md — end-to-end flow:
    1. parse + validate args (traversal guard on path + manifest)
    2. init query + runtime detect + auto mode-detect (.planning/ presence)
    3. discover docs via directory convention OR manifest YAML
    4. 50-doc cap — forces --manifest for larger sets in v1
    5. discovery approval gate
    6. parallel spawn of gsd-doc-classifier per doc (fallback to
       sequential on non-Claude runtimes)
    7. single gsd-doc-synthesizer spawn
    8. conflict gate honoring doc-conflict-engine safety rule —
       BLOCKER count > 0 aborts without writing PROJECT/REQUIREMENTS/
       ROADMAP/STATE
    9. route to gsd-roadmapper (new) or append-to-milestone (merge),
       audits roadmapper's required PROJECT.md fields and only prompts
       for gaps
   10. commit via gsd-sdk

Updates ARCHITECTURE.md counts (commands 80→81, workflows 77→78,
agents tree-count 31→33).

--resolve interactive is reserved (explicit future-release reject).

Refs #2387

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:12:02 -05:00
Jeremy McSpadden
523a13f1e8 feat(agents): add gsd-doc-classifier and gsd-doc-synthesizer
Two new specialist agents for /gsd-ingest-docs (#2387):

- gsd-doc-classifier: reads one doc, writes JSON classification
  ({ADR|PRD|SPEC|DOC|UNKNOWN} + title + scope + cross-refs + locked).
  Heuristic-first, LLM on ambiguous. Designed for parallel fan-out per doc.

- gsd-doc-synthesizer: consumes all classifications + sources, applies
  precedence rules (ADR>SPEC>PRD>DOC, manifest-overridable), runs cycle
  detection on cross-ref graph, enforces LOCKED-vs-LOCKED hard-blocks
  in both modes, writes INGEST-CONFLICTS.md with three buckets
  (auto-resolved, competing-variants, unresolved-blockers) and
  per-type intel staging files for gsd-roadmapper.

Also updates docs/ARCHITECTURE.md total-agents count (31 → 33) and the
copilot-install expected agent list.

Refs #2387

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:12:02 -05:00
Jeremy McSpadden
0b90150ebf refactor(conflict-engine): extract shared doc-conflict-engine reference
Move the BLOCKER/WARNING/INFO conflict report format, severity semantics,
and safety-gate behavior from workflows/import.md into a new shared
reference file. /gsd-import consumes the reference; behavior is unchanged
(all 13 import-command tests + full 4091-test suite pass).

Prepares for /gsd-ingest-docs (#2387) which will consume the same contract
with its own domain-specific check list. Prevents drift between the two
implementations.

Refs #2387

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:12:02 -05:00
Jeremy McSpadden
819af761a0 fix(install): verify gsd-sdk resolves on PATH after npm install
`npm install -g` can succeed while the binary lands in a prefix that
isn't on the current shell's PATH (common with Homebrew, nvm, or an
unconfigured npm prefix). Re-probe via `which gsd-sdk` (or `where` on
Windows) after install; if it doesn't resolve, downgrade the success
message to a warning with a shell-restart hint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 16:09:19 -05:00