Commit Graph

76 Commits

Author SHA1 Message Date
Tom Boucher
9223f2f4c8 feat(#247): runtime-neutral phase uat-passed predicate from HUMAN-UAT results (#1063)
* feat(#247): runtime-neutral phase uat-passed predicate from HUMAN-UAT results

Wire the already-reserved `phase.uat-passed` alias (subcommand `uat-passed`,
mutation:false) into the phase command router with a new markdown-aware
predicate that evaluates HUMAN-UAT results and reports pass only when every
required check passes. Post-SDK-retirement (ADR-0174/#174) successor to the
SDK-framed #70, with no SDK-specific API surface.

New pure module src/uat-predicate.cts:
- stripFalsePositiveContexts: frontmatter -> HTML-comment -> CommonMark-style
  fenced-block state machine (tracks delimiter char+length) -> blockquote,
  each a small composable step, so a `result: passed` inside frontmatter, a
  fenced/~~~ block (incl. ~~~ nested in a ``` fence), a comment, or a
  blockquote is never counted.
- parseUatResultItems: heading-block parser, column-0-anchored same-line
  result; a heading with no result -> `missing` (fail-closed).
- analyzeMarkdown: unterminated fence/comment detection (malformed -> blocker).
- evaluateUatPassed: allowlist pass/verification semantics; passed = no
  blockers && >=1 check && all passing; no_uat_artifacts discriminator (no
  vacuous pass); optional requireVerification policy hook.

Thin cmdPhaseUatPassed handler in phase.cts; router closure rejects unknown
flags via makeInvalidArgs. Hardened across two Codex adversarial passes
(vacuous pass, dropped failing tests, permissive verification status,
nested-fence escape, cross-line result value, masked unterminated comment) —
all fixed fail-closed. New unit + CLI-integration suites incl. a fast-check
property test; docs, CONTEXT glossary, inventory, and changeset updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#247): backfill changeset PR number (#1063)

* fix(#247): indexOf paired-scan for unterminated-comment detection

CodeQL js/incomplete-multi-character-sanitization (high) flagged the
`raw.replace(/<!--[\s\S]*?-->/g,'')`-then-`.includes('<!--')` detection in
analyzeMarkdown as incomplete sanitization (a single regex pass can leave a
residual `<!--`). Replace it with a paired left-to-right indexOf scan that
contains no `.replace()` of the comment token — CodeQL-clean and strictly
more correct (a closed earlier comment can never mask a later unterminated
one). Behaviour unchanged; 98 predicate tests + scoped docker run green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:37:17 -04:00
Colin
cd5db1f8db test(suites): seed security/slow/integration suites via measured retags
Renames (git mv) with all references updated (ci-test-scope RULES,
windows-parity allowlist, test-file-count allowlist, docs in 6 locales):

- 5 scanner tests -> *.security.test.cjs — the 'Run security tests' CI step
  ran zero files since the suite taxonomy landed; it is now honest.
- graphify-auto-update -> *.slow.test.cjs (36s, slowest file in the suite;
  e2e gsd-tools spawns) — runs on full-matrix lanes and push to next.
- installer-migration-install-integration -> *.integration.test.cjs
  (13s; an integration test by its own name).

Coverage gate measured after retags: 88.55% lines (gate 70%).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-09 23:50:41 -04:00
Tom Boucher
3697e6768f fix(#853): gate manager/autonomous background dispatch by runtime (#863)
* fix(#853): gate manager/autonomous bg dispatch by runtime

/gsd-manager and /gsd-autonomous --interactive dispatched Plan/Execute
via Agent(run_in_background=true). On Claude Code a backgrounded agent
has no Agent/Task tool, so it cannot spawn the nested subagents those
pipelines need — per-plan worktree-isolated executors, the plan-checker,
and the verifier. The phases reported complete but isolation and
independent verification silently never ran, even with use_worktrees /
plan_check / verifier enabled.

Both workflows now resolve the runtime (config-get runtime, default
claude) before dispatching: run plan/execute INLINE on Claude Code so
the nested pipeline runs, and background-dispatch only on runtimes where
a backgrounded agent can still nest. Mirrors execute-phase.md's existing
Codex fail-closed precedent. Reconciles the stale unconditional
background/overlap/lean-context claims elsewhere in both workflows and
in the docs. Adds a content regression test pinning the gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(#853): add changeset for runtime-gated bg dispatch

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 10:42:05 -04:00
Tom Boucher
29c0a2f5a1 docs(#849): capture 1.4.0 release features across the docs base (#850)
Diataxis review of the 1.4.0 content (52 changesets, multi-runtime maturation
plus native packaging and new flags) against the existing docs base found most
per-feature docs already landed with their PRs. Fill the four remaining gaps,
each in its Diataxis quadrant:

- Reference: FEATURES.md Feature #36 (Multi-Runtime Support) updated in place
  with 1.4.0 additions — native skills emission (Cline/Kilo/OpenCode), new
  slash-command surfaces (CodeBuddy/Augment/Cursor), cross-runtime lifecycle
  hooks for context-headroom tracking, and the Gemini CLI extension package.
- Reference: CONFIGURATION.md gains a dedicated worktree.baseRef entry (values,
  .claude/settings.local.json location, auto-set-on-install behaviour).
- How-to: plan-a-phase.md gains an 'override planning granularity for one phase'
  section for the --granularity flag.
- Explanation: context-engineering.md gains a 'Lifecycle hooks and context
  headroom' section (the why of lifecycle hooks + forked context), cross-linked
  from multi-agent-orchestration.md.

Docs-only; documents already-shipped features, so no changeset required
(docs/ is not in the changeset-lint user-facing prefixes).

Closes #849

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 23:22:15 -04:00
Tom Boucher
40d48c0508 feat(#815): add /gsd-update --next to install the @next RC channel (#839)
Adds an opt-in --next (alias --rc) flag to /gsd-update targeting the @next RC dist-tag (ADR #660), with a {latest,next} allowlist enforced at three layers, channel-aware version check + banner, and byte-for-byte unchanged default @latest behavior.

Closes #815
2026-06-07 20:22:07 -04:00
Tom Boucher
cb284962bf feat(#789): elevate CodeBuddy — slash commands (#830)
* feat(#789): elevate CodeBuddy — emit slash commands (+ document subagent/MCP scope)

Emit a CodeBuddy slash-command surface so GSD workflows appear in the
'/' menu, reaching parity with other elevated runtimes.

- Add convertClaudeCommandToCodebuddyCommand and register a commands/
  artifact kind for the codebuddy runtime (commands/gsd-<name>.md),
  consistent with the Cursor (#785) and Augment (#790) commands surfaces.
- Mark emitted skills user-invocable:false so the commands surface is the
  sole '/' entry point (no duplicate /gsd-* entries); skills stay
  model-invocable. CodeBuddy's SKILL.md supports this field.
- Normalize $HOME/.codebuddy (bare + slash) path forms in runtime
  rewrites so --config-dir/local installs don't leak the default home.
- Report installed commands/ count on install; uninstall prunes gsd-*
  commands while preserving user-owned commands.

Scope: subagents (~/.codebuddy/agents/) are already emitted by the
generic agents block (unchanged); no mcp.json is written (gsd ships no
MCP server, and CodeBuddy's mcp.json registers only external servers).

Closes #789

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#789): set changeset pr number to 830

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 18:56:47 -04:00
Tom Boucher
74a818308e feat(#785): write .cursor/commands/ Cursor 1.6 slash-command surface (#805)
* feat(#785): write .cursor/commands/ as Cursor 1.6 slash-command surface

Cursor 1.6 (released 2025-09-12) introduced plain-markdown slash commands
in `.cursor/commands/<name>.md` — no frontmatter, invocable via `/` in the
Agent input. GSD previously emitted only `~/.cursor/skills/` for Cursor.

This PR wires a second artifact kind for `cursor` in
`runtime-artifact-layout.cts`: `convertedCommandsKind('commands', 'gsd-',
'convertClaudeCommandToCursorCommand', configDir)`. The new kind applies the
same `convertClaudeToCursorMarkdown` transforms (tool renames, brand
substitution, slash-command normalisation) and then strips YAML frontmatter
so the output is plain prose. Skills output is unchanged.

`stageCommandsForRuntimeFlat` in `install-profiles.cts` stages each source
`.md` as a flat `<stem>.md` in a temp dir; the existing `_copyStaged` commands
path then prefixes and copies to `<configDir>/commands/`.

`.cursor/mcp.json` is explicitly OUT OF SCOPE: GSD ships no MCP server; the
`mcpServers` schema cannot be usefully populated by the installer.

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

* refactor(#785): address review nit

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 15:07:14 -04:00
Tom Boucher
f66c4a082c feat(#766): distribute gsd-core as a native Claude Code plugin (#797)
* feat(#766): distribute gsd-core as a native Claude Code plugin

Add an additive .claude-plugin/plugin.json manifest plus hooks/hooks.json so gsd-core can be installed as a first-class Claude Code plugin (marketplace or zero-friction @skills-dir), with /gsd-core: namespaced commands and lifecycle management — alongside the unchanged npm/file-copy installer.

- .claude-plugin/plugin.json: validated with 'claude plugin validate --strict'
- hooks/hooks.json: mirrors the installer's always-on Claude hook wiring via ${CLAUDE_PLUGIN_ROOT}
- package.json: ship .claude-plugin in the npm tarball
- tests/issue-766-plugin-manifest.test.cjs: manifest + always-on-hook-contract drift guards
- docs: install-on-your-runtime.md + FEATURES.md

Closes #766

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(#766): add ADR-766 + glossary entry for Claude Code Plugin Manifest Module

Record the plugin manifest as the Seam projecting gsd-core's artifact surfaces onto the Claude Code plugin contract (sibling of the Runtime Artifact Layout Module, ADR-3660), with the defined kind->field mapping and the always-on hook projection rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 12:02:39 -04:00
Tom Boucher
7e76f1a736 feat(#703): add --granularity override flag to /gsd:plan-phase (#750)
* feat(#703): add --granularity override flag to /gsd:plan-phase

Add a `--granularity <coarse|standard|fine>` flag to /gsd:plan-phase that
overrides the configured planning granularity for a single invocation.

The override is a new highest-priority tier above the existing precedence
chain (granularities[phaseType] -> granularity -> planning.granularity ->
'standard') in resolveGranularityInternal; when the flag is absent, resolution
is byte-for-byte unchanged. cmdInitPlanPhase now resolves with phaseType
'planning' so granularities.planning participates, and emits the resolved
value in the init JSON, which the plan-phase workflow forwards to the planner
prompt. Invalid values are rejected at the CLI boundary via a shared
assertValidGranularityOverride helper.

Closes #703

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#703): set changeset pr to 750

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 23:56:53 -04:00
Tom Boucher
14d0238cf5 docs: roll up legacy release notes into a single archive (#658) (#659)
Consolidate all pre-rename release notes (the retired get-shit-done-cc /
get-shit-done-redux lineage, 1.0.0 -> 1.50.0-canary.1) into one condensed,
read-only archive so the legacy 1.x version numbers no longer collide with
the current @opengsd/gsd-core line.

- Add docs/RELEASE-NOTES-LEGACY.md: rename banner, master version-index
  table, condensed per-version sections (1.42.3 -> 1.0.0), and a separate
  pre-release & canary builds section. Stale install commands stripped.
- Trim CHANGELOG.md to the current @opengsd/gsd-core line only; replace the
  Legacy Release History block with a pointer to the archive and drop the
  orphaned numbered legacy reference-link definitions.
- Remove the 10 standalone docs/RELEASE-v*.md files.
- Repoint docs/CANARY.md and docs/FEATURES.md links to the new archive.

Closes #658

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 23:04:44 -04:00
Tom Boucher
463cffd894 chore(#604): rename get-shit-done/ runtime directory to gsd-core/ (#615)
* chore(#604): rename get-shit-done/ runtime directory to gsd-core/

Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the
on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary
(`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers
are unaffected.

Mechanical (bulk, ~90% of the diff):
- `git mv get-shit-done gsd-core`
- Swept path/identifier references across the repo via
  `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead
  preserves the five legitimate slug variants that are NOT the directory:
  get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names).
- Build/manifest wiring: package.json (bin, files, coverage globs),
  tsconfig.build.json (outDir), ~86 .gitignore build-output entries,
  stryker.config.mjs, scan-ignore files, install.js path strings.
- Frozen (not rewritten): CHANGELOG.md history; translated docs
  (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/).

New logic (review here):
- src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper
  ADR-0008 installer migration. On upgrade it walks the legacy
  `~/.claude/get-shit-done/` tree, classifies each file via the prior install
  manifest, and emits remove-managed / backup-and-remove for managed files
  while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked
  root and symlinked entries; bounds-checks every path under configDir). The
  framework rolls back on install failure. Emptied dirs may remain (framework
  has no recursive dir-removal primitive) — documented.
- scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare
  `get-shit-done` directory token (split token to avoid self-match; case-
  insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists
  CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines).
  Wired into the lint-tests CI job.
- Restored scripts/lint-package-identity-drift.cjs detection regexes (the
  mechanical sweep had wrongly rewritten the old-name patterns it exists to
  detect) and marked them as intentional legacy references.
- TDD tests for the migration and the guard; do.md slash-command guard regex
  tightened so a `/gsd-core/bin` path segment is not mistaken for a command;
  changeset + docs/installer-migrations.md row added.

Breaking: the installed runtime path moves `~/.claude/get-shit-done/` ->
`~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed
files (preserving user files) on upgrade. Users with custom hooks/configs
hardcoding the old path must update them.

Closes #604

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): unsweep pending changesets + allowlist injection-example docs

CI fixes for the rename PR:
- Do not sweep pending .changeset/*.md (ephemeral release-note fragments,
  like CHANGELOG); reverted those body edits so 5 pre-existing malformed
  fragments (missing type/pr) no longer enter the PR diff and trip docs-lint.
  Allowlisted .changeset/ in the legacy-name guard accordingly.
- Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in
  prompt-injection-scan.sh: they contain intentional injection examples /
  security-model prose; the path-reference rewrites are kept.

CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR;
none in the new migration/guard) and are out of scope for the rename.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): resolve CodeQL alerts surfaced on this PR

The rename diff touched files carrying pre-existing CodeQL findings; per the
no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving
them off. All behavior-preserving:

- scripts/ci-test-scope.cjs: build the config-path match from string
  .includes() instead of a RegExp over an arg-derived value (js/regex-injection).
- src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName
  so the table-cell escape is complete (js/incomplete-sanitization).
- tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment
  strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization).
- tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace,
  keep the meaningful POSIX-class conversion (js/identity-replacement).

Verified: build:lib green; the touched test files + ci-test-scope + profile-output
suites pass; lint:legacy-name clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization)

The prior commit's fixes for two alerts were ineffective:
- ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file`
  reaching static regex `.test(file)` calls (not the config rule). Removed ALL
  regex over file/t — startsWith/includes/=== string checks + an isWindowsHint
  helper — so there is no regex sink for the tainted value.
- js/incomplete-multi-character-sanitization (3 test files): a single
  `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint
  loop (replace until stable) plus a final bare-opener strip.

Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass;
lint:legacy-name clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL

CodeQL flags the regex PATTERNS syntactically (regex-injection on the
--files arg split; incomplete-multi-character-sanitization on the <!--...-->
replace), so loop fixes do not satisfy it. Made these paths regex-free:
- ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/).
- 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)).
Behavior preserved; ci-test-scope + the 3 suites pass; guard clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): unblock security base64 scan on the large rename diff

The security job hit its 10m timeout: base64-scan.sh choked on the binary
test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/
non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings),
and the ~800-file rename diff is slow to scan regardless.

- scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they
  can't carry base64-obfuscated *text* and feeding NUL bytes through the
  per-line scanner is pathologically slow. collect_files already filtered
  binary *extensions*; this catches binary *content* in text extensions.
- .github/workflows/security-scan.yml: raise the security job timeout 10m->30m
  to accommodate very large diffs (the scan itself is unchanged).

Verified locally: scan skips the fixture, 0 "ignored null byte" warnings,
0 findings, exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): sweep get-shit-done refs introduced by merging next

The branch was updated with next (#614/#384/#618 etc.), which reference the
get-shit-done/ dir (still named that on next). Swept the stale references in
the merged files to gsd-core so the rename stays consistent and lint:legacy-name
passes:
- commands/gsd/discuss-phase.md (runtime-launcher shim paths)
- src/core.cts (getAgentsDir layout comments)
- tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib)

Verified: guard 0 violations; build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant

The #614 runtime-launcher shim added to discuss-phase.md references
`${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y
refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it
mis-read the directory path as a dangling `/gsd-core` command ref (same class as
the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path
segments are not treated as slash-command references.

Verified locally on BOTH platforms before pushing:
- mac (node 26) full suite: 0 failures
- gsd-test-runner (linux, node22 image) full suite: 0 failures
- bug-3683 + bug-2954 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI)

CI intermittently failed state.test's gsd-tools subprocess with
"findProjectRoot is not a function" (flip-flopping across legs; not reproducible
on mac full suite, gsd-test linux full suite, test:unit, or state.test x8).
findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs);
binding it via destructure at module-load can be undefined under a load-ordering
edge. Resolve it lazily at call time via a small wrapper so the lookup happens
after core.cjs is fully initialized.

Verified green on BOTH platforms before pushing:
- mac (node 26) full suite: 0 failures
- gsd-test-runner (linux, node22) full suite: 0 failures
- state.test.cjs: 106/106; gsd-tools loads cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#604): allowlist verification-patterns.md placeholder examples in secret scan

The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling
it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var
examples (illustrative Stripe test-key / database-URL / API-key placeholders) —
not real credentials. Added it to .secretscanignore with the strict annotation,
mirroring the existing gsd-core/workflows/plan-phase.md exception.

Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next
exits 0 with 0 findings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:35:29 -04:00
Tom Boucher
3bb2f8f1c5 docs: rebrand to GSD Core and restructure docs with Diataxis (#605)
* chore: wire docs/agents config into AGENTS.md Agent skills section

Add the `## Agent skills` discovery block pointing the engineering
skills at the existing docs/agents/{issue-tracker,triage-labels,domain}.md
files (issue tracker, triage label mapping, single-context domain docs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: rebrand to GSD Core and restructure docs with Diataxis

Reorganise the root README and docs/ around the Diataxis framework
(tutorials, how-to guides, reference, explanation), add new how-to
guides and schema references (STATE.md / CONTEXT.md / PLAN.md /
planning artifacts), and cross-link the whole set. Update the lone
legacy gsd-build reference to open-gsd; keep internal get-shit-done/
filesystem paths unchanged (directory rename tracked separately in
open-gsd/gsd-core#604). Regenerate the ja-JP, ko-KR, pt-BR and zh-CN
localised trees to mirror the new structure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: backfill changeset PR number (#605)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 08:13:09 -04:00
Tom Boucher
a11ba2dfcb feat(#68): per-phase granularity overrides (granularities.<phaseType>) (#595)
Closes #68. Per-phase-type granularity overrides via granularities.<phaseType>, mirroring models.<phaseType>. Includes maintainer-authorized sdk-seam reference cleanup.
2026-06-01 20:53:46 -04:00
Tom Boucher
9ffe45a7c3 feat(#163): tighten gsd-roadmapper granularity defaults to reduce thin-phase fragmentation (#591)
* feat(#163): tighten gsd-roadmapper granularity defaults to reduce thin-phase fragmentation

Tighten the Granularity Calibration buckets in gsd-roadmapper (Coarse 3-5->2-4,
Standard 5-8->4-6, Fine 8-12->6-10) and append inline Key guidance naming the
thin-phase failure pattern (single requirement / internal-quality goal /
task-shaped success criteria) with instruction to fold into a neighbor rather
than create a standalone phase. Implements the maintainer-approved proposal
verbatim.

Update the canonical English docs that hardcoded the old phase-count numbers:
docs/CONFIGURATION.md and docs/FEATURES.md. Translated docs are
community-maintained and are not updated per-PR (CONTRIBUTING.md language
policy).

Prompt/doc text only; no code, format, or downstream-consumer changes. Agent
size-budget and skills-awareness tests pass; full suite green.

Closes #163

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#163): add Changed changeset for roadmapper granularity tightening

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(#163): lock tightened gsd-roadmapper granularity buckets

source-text-is-the-product test asserting the Granularity Calibration table
holds the tightened ranges (Coarse 2-4, Standard 4-6, Fine 6-10), that no row
maps to an old bucket, and that the Key paragraph carries the thin-phase
folding guidance. Would fail if the values regress.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:37:49 -04:00
Tom Boucher
de2f73d21a enhancement(#34): add Antigravity CLI (agy) as a peer reviewer in /gsd-review
Closes #34

Squash-merged via admin override — all CI green (28/28 checks), branch protection review gate bypassed with maintainer authorization.
2026-05-31 16:15:41 -04:00
Tom Boucher
79002a00cb chore(#518): rename npm package + bin to @opengsd/gsd-core (#519)
* chore: rename npm package + bin to @opengsd/gsd-core (functional)

- package.json: name @opengsd/get-shit-done-redux → @opengsd/gsd-core,
  bin key get-shit-done-redux → gsd-core, repository/homepage/bugs URLs
- package-lock.json: regenerated (npm install --package-lock-only)
- tests/**, scripts/**, bin/**, .github/**, agents/**, commands/**,
  get-shit-done/bin/**, get-shit-done/workflows/**:
  applied the 4-rule replacement (scoped npm ref, GitHub repo path,
  bin/clone invocations) per #505 single-source refactor

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: sweep live references to @opengsd/gsd-core

Update all live documentation (README.md + translations, docs/**,
CONTRIBUTING.md, VERSIONING.md, SECURITY.md, CONTEXT.md,
docs/CANARY.md) to reflect the renamed package and repository.

Rules applied:
- @opengsd/get-shit-done-redux → @opengsd/gsd-core (scoped npm name)
- open-gsd/get-shit-done-redux → open-gsd/gsd-core (GitHub repo)
- GSD-redux/get-shit-done-redux → open-gsd/gsd-core (stale badge org)
- bare bin/clone refs → gsd-core

CHANGELOG.md, docs/adr/**, docs/RELEASE-*.md, docs/research/**,
and .changeset/** are preserved byte-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: add negative lookbehind to slash-command regex in bug-2954 test

The extractSlashReferences regex matched /gsd-core inside npm package
URLs (@opengsd/gsd-core), producing a false /gsd:core command reference.
Adding a negative lookbehind (?<![a-z]) excludes matches preceded by a
letter, so only standalone /gsd-<cmd> and /gsd:<cmd> tokens are found.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#518): add changeset for package rename

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(#518): update package-identity expectations to the renamed coordinates

The rebase regenerated the seam to @opengsd/gsd-core (bin gsd-core, repo
open-gsd/gsd-core). The #498 seam tests assert deriveIdentity against the REAL
package.json, so their expected literals must follow the rename. The drift-lint
unit test is left as-is — its SEAM is a self-consistent fixture and its
stale-literal detection cases would shift if altered; the live-repo scan in it
already passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 17:25:02 -04:00
Tom Boucher
e8fc50034d docs(#194): remove sdk programmatic docs and bridge guidance 2026-05-25 11:57:24 -04:00
Tom Boucher
334a64168e chore(npm): rebrand packages to @opengsd scope (#127)
* chore(npm): rebrand packages to @opengsd scope

Rename:
- get-shit-done-redux → @opengsd/get-shit-done-redux
- @gsd-redux/sdk → @opengsd/gsd-sdk

Add publishConfig.access=public for first-time scoped publish.
CLI binary names (get-shit-done-redux, gsd-sdk, gsd-tools) unchanged.

Sweeps install commands, npx invocations, CI publish/version-check
workflows, tests, docs, READMEs (all translations), and the
PACKAGE_NAME constant in check-latest-version.

Bumps qs 6.15.1 → 6.15.2 to clear a moderate advisory surfaced by
the audit-clean test (GHSA-q8mj-m7cp-5q26).

Closes #126

* chore: pin 2.0.0 release + remove canary workflow

- Bump both packages 1.50.0-canary.0 → 2.0.0 for first @opengsd publish
- Remove .github/workflows/canary.yml and canary dist-tag handling in
  release.yml / release-sdk.yml
- Drop canary section from VERSIONING.md

Refs #126

* chore: address review findings + harden tarball-smoke timeout

- .changeset/opengsd-org-rename.md: match project's custom
  parse.cjs frontmatter (type: Changed / pr: 127); the scoped
  @changesets/cli keys were silently rejected.
- CONTEXT.md: drop two canary-stream policy lines and a dangling
  DEFECT.CANARY-VERSION-LEAK.cross-ref now that canary.yml is gone.
- tests/release-tarball-smoke.install.test.cjs: pass
  timeout: 600_000 for npm pack + global install; the 3-minute
  runNpm default was timing out on slower Docker hosts (cartographer).

Refs #126

* fix(sdk): add missing type/runtime devDependencies for build

prepublishOnly invokes tsc which couldn't resolve @types/node,
@types/ws, or synckit. They had been hoisted from root but were
not declared in sdk/'s own package.json — first publish from a
clean SDK tree failed.

Refs #126

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

* fix(ci): use npm pack stdout instead of glob to find tarball

`npm pack --silent` for a scoped package (@opengsd/get-shit-done-redux)
produces `opengsd-get-shit-done-redux-*.tgz`, not `get-shit-done-redux-*.tgz`.
Capture the filename from stdout instead of a hardcoded glob so the step
works regardless of package name format.

Fixes smoke (ubuntu-latest, 22, false) CI failure.

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

* ci: treat workflow-file changes as test-skip eligible

`.github/workflows/install-smoke.yml` (and other workflow files)
were in neither `test.yml` paths nor `test-skip.yml` paths-ignore,
so neither workflow ran on a workflow-only commit — leaving the
required test-skip check perpetually missing.

Refs #126

* chore: reset version to 1.0.0 for first @opengsd publish

Nothing has been published yet under the @opengsd scope, so the
inaugural release uses 1.0.0 rather than 2.0.0. The "major bump"
in the changeset reflects the breaking install-command change for
users migrating from the prior unscoped `get-shit-done-redux`, not
a numeric continuation from a 1.x line under the new identity.

Refs #126

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 16:22:41 -04:00
Tom Boucher
2a915c1b82 chore: migrate references from gsd-build to open-gsd/get-shit-done-redux (#120) (#121)
Security-motivated migration of all stale repository and npm-scope references.

Three categories of changes (58 files, 174 substitutions):

1. gsd-build → open-gsd (security-critical):
   - .github/workflows/release-sdk.yml — npm token comment, tarball filename pattern
   - .github/workflows/hotfix.yml — same
   - .changeset/fix-3406-detect-stale-sdk-shadow.md — @gsd-build/sdk → @open-gsd/sdk
   - .changeset/sharp-quails-leap.md — same
   - get-shit-done/workflows/update.md — CHANGELOG raw GitHub URL

2. GSD-redux org slug → open-gsd (canonical rename):
   - package.json + sdk/package.json — repository/homepage/bugs metadata
   - All README.*.md — live badge and link sections
   - CONTRIBUTING.md, CONTEXT.md, QUICK-WINS-CONFIRMED-BUGS.md
   - .coderabbit.yaml, .release-monitor.sh, scripts/sync-rulesets.sh
   - docs/** — all live agent/ADR/user-facing documentation
   - tests/** — repo slug assertions and test fixtures
   - scripts/changeset/cli.cjs + github-release-notes.cjs
   - .github/ISSUE_TEMPLATE/*, .github/pull_request_template.md
   - bin/install.js, get-shit-done/bin/lib/model-catalog.cjs
   - sdk/HANDOVER-*.md, sdk/src/*.test.ts

3. CLAUDE.md (gitignored local file — not in this commit):
   Updated separately outside git: --repo gsd-build/get-shit-done →
   --repo open-gsd/get-shit-done-redux with security warning.

Intentionally unchanged: CHANGELOG.md, docs/RELEASE-*.md,
.changeset/README.md, .changeset/build-hooks-atomic-write.md,
README.md migration table (historical fork record),
tests/changeset-serialize.test.cjs line 78 (serialization fixture).

The gsd-build/get-shit-done repo is compromised (rug-pull documented in
README.md). Do not push to or interact with that repo.

Closes #120
2026-05-22 12:28:16 -04:00
Tom Boucher
dff176bfd2 chore: rebrand to GSD-redux/get-shit-done-redux
Mirror of code, issues, and PRs from the upstream gsd-build/get-shit-done,
which appears compromised or abandoned (maintainer unreachable since
2026-04-01; $GSD token linked to rug-pull).

- Adds rebrand notice block at top of English README
- Removes $GSD token badge and @gsd_foundation X badge (keeps Discord)
- Renames npm packages: get-shit-done-cc -> get-shit-done-redux,
  @gsd-build/sdk -> @gsd-redux/sdk
- Updates all repo URLs across docs, workflows, package.json, bin/
- Updates ci@gsd-build -> ci@gsd-redux in workflow git identities
- Leaves CHANGELOG and .changeset/* alone (historical, time-stamped)
2026-05-22 08:27:07 -04:00
Tom Boucher
6a5fa59129 feat(3081): auto-trim review prompts for small-context model reviewers (#3708)
* feat(3081): auto-trim review prompts for small-context model reviewers

Adds review.max_prompt_tokens and review.max_prompt_tokens_per_reviewer
config keys. When configured, the /gsd-review workflow deterministically
trims the assembled prompt before sending to each reviewer (drop CONTEXT
→ RESEARCH → REQUIREMENTS; head-shrink PROJECT.md; tail-truncate PLANs
proportionally; reserve disclosure-note tokens upfront). Trim metadata
is recorded in REVIEWS.md frontmatter. Reviewer is skipped with a
warning if even the minimum review set exceeds the budget.

Closes #3081

* fix(3081): register prompt-budget in SDK query registry and update inventory manifest

review.md references `gsd-sdk query prompt-budget` at three call sites, but the
command had no handler in the SDK registry — failing the registry-integration
drift-guard test on all 6 CI matrix legs. Added a native TypeScript SDK handler
(sdk/src/query/prompt-budget.ts) that ports the applyBudget logic from the CJS
module, registered it in DOMAIN_STATIC_CATALOG, and regenerated
docs/INVENTORY-MANIFEST.json to include the new cli_modules/prompt-budget.cjs entry.

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

* fix(3081): bump ws to 8.20.1 and allowlist prompt-budget sibling pair

Two additional CI failures after the registry fix:

1. ws moderate CVE (GHSA-58qx-3vcg-4xpx, uninitialized memory disclosure):
   The advisory covers ws >=8.0.0 <8.20.1. Both root and sdk/package.json
   pinned ^8.20.0 which resolved to 8.20.0. Bumped both to 8.20.1 to clear
   the npm audit drift-guard test (bug-3588-npm-audit-clean.test.cjs).

2. lint-shared-module-handsync detected the new prompt-budget.ts / prompt-budget.cjs
   sibling pair without an allowlist entry. Added a cooperatingSiblings entry
   to scripts/shared-module-handsync-allowlist.json with classification and
   justification matching the established pattern.

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

* fix(3081): align prompt-budget skip semantics across CJS and SDK dispatch paths

Replace brittle `[ $EXIT -eq 2 ]` guards with `[ $EXIT -ne 0 ]` in all three
local-reviewer blocks (Ollama, LM Studio, llama.cpp) in workflows/review.md.
Any non-zero exit from prompt-budget now triggers a skip with a descriptive
warning — exit 2/11 prints "budget too small", any other non-zero prints
"unexpected exit code". This ensures the SDK bridge dispatch path (exit 11
via GSDError(Blocked)) triggers the same skip as the CJS path (exit 2).

The SDK handler (sdk/src/query/prompt-budget.ts) already writes both metadata
and prompt files before throwing, so no change needed there.

The Ollama block also gains the missing OLLAMA_SKIP guard so the reviewer
invocation is actually skipped (previously the block only suppressed the
OLLAMA_PROMPT_FILE update but still ran the curl invocation).

SDK integration path (hardFailed via GSDError(Blocked) → exit 11) is covered
by handler unit tests in tests/prompt-budget.test.cjs; no gsd-sdk-*.test.cjs
exercising the full bridge dispatch for this command exists yet — that gap
remains and is documented here.

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

* fix prompt-budget trim ordering and review guard follow-ups

* perf: optimize prompt-budget and dedup reviewer trim workflow

* fix(3708): drop source-grep theater tests to satisfy lint-no-source-grep

All four test files added in commit 2df566ed were pure source-grep theater:
they read .cjs / .ts / .md source files and asserted that specific string
literals were present or absent. None exercised runtime behaviour.

Deleted:
- tests/gsd-tools-memory-optimizer.test.cjs   — 7 includes() on gsd-tools.cjs
- tests/prompt-budget-hotpath-optimizer.test.cjs — includes() on prompt-budget.cjs + .ts
- tests/prompt-budget-io-optimizer.test.cjs   — includes() on prompt-budget.ts + gsd-tools.cjs
- tests/review-workflow-budget-dedup.test.cjs — includes() on review.md

Behavioural coverage for the prompt-budget feature already exists in
tests/prompt-budget.test.cjs and tests/prompt-budget-cli.test.cjs (also
added by this PR). No replacement tests needed.

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

* fix(3708): correct budget-pressure threshold and minSet accounting

Two bugs in applyBudget caused premature trimming and false hard-fails:

1. UNNEEDED_TRIM: budgetUnderPressure compared baseTokens against
   effectiveBudget - NOTE_RESERVE_TOKENS, triggering trim pressure 80
   tokens before the budget was actually exceeded. Fix: compare against
   effectiveBudget directly; NOTE_RESERVE_TOKENS are still reserved in
   contentBudget once real pressure is confirmed.

2. FALSE_HARDFAIL: minSet included NOTE_RESERVE_TOKENS unconditionally,
   treating the note as mandatory even when no trim would occur and no
   note would be injected. Fix: exclude NOTE_RESERVE_TOKENS from minSet;
   a prompt that fits untrimmed needs no note and must not hard-fail.

Both fixes applied in CJS and TypeScript implementations. Two regression
tests added (cycles 11 and 12) that reproduce each case behaviorally.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:13:09 -04:00
Tom Boucher
5c202372ed docs: update v1.42.1 release documentation 2026-05-14 20:42:35 -04:00
Tom Boucher
245d5f66a1 feat: add review.default_reviewers config for /gsd-review defaults (#3464)
* feat(review): add review.default_reviewers selection policy

* docs(review): explain default reviewer config and precedence

* chore(changeset): add feature entry for review.default_reviewers

* chore(changeset): set pr field for #3464

* test(review): cover unavailable default-reviewer failure path

* fix(review): sync sdk and inventory parity for default reviewers

* fix(review): use canonical /gsd:review namespace in source
2026-05-13 14:10:15 -04:00
Tom Boucher
e79c472d7b Feat(ship): add configurable PR body sections (#3391)
* feat: add configurable ship PR body sections

* chore: add changeset for ship PR sections

* docs: avoid prompt scanner trigger in PR body guide

* docs: escape pr body source separator
2026-05-11 15:27:40 -04:00
Tom Boucher
3aaed8f5d7 test: replace deny-list parity tests with polarity-inverted live-registry (#3049) (#3284)
* test: reproduce Windows SDK not found after fresh npx install (#3211)

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

* test: red — docs-parity live-registry tests fail against stub helper (#3049)

Adds:
- tests/helpers/live-command-registry.cjs (stub: returns empty Set)
- tests/docs-parity-live-registry.test.cjs (new polarity-inverted test)
- tests/fixtures/live-command-registry/ (fixture .md files)

All parity and helper-contract tests fail because the stub returns an
empty registry. This is the intentional RED state before GREEN
implementation.

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

* feat(test-helpers): live-command-registry derives canonical tokens from commands/gsd/*.md (#3049)

Implements GREEN phase:
- tests/helpers/live-command-registry.cjs: walks commands/gsd/*.md, parses
  YAML frontmatter name: field, emits /gsd-slug, /gsd:slug, $gsd-slug per
  command. Memoized per process. Fails loud on malformed frontmatter (k302).
- tests/docs-parity-live-registry.test.cjs: updated with INTERNAL_COMPONENT_SLUGS
  exemption for path-component and placeholder tokens (gsd-build from GitHub
  org URLs, gsd-workspaces from ~/gsd-workspaces/ paths, gsd-tools from
  bin/gsd-tools.cjs paths, etc.)

Docs drift caught and fixed:
- ns-* rename: /gsd-ns-workflow→/gsd-workflow etc. in COMMANDS, FEATURES,
  INVENTORY, USER-GUIDE (6 commands across 4 English files)
- /gsd-scan → /gsd-map-codebase --fast (FEATURES, INVENTORY, USER-GUIDE)
- /gsd-note → /gsd-capture (FEATURES, issue-driven-orchestration, ja-JP, ko-KR)
- /gsd-do → /gsd-fast (FEATURES, ja-JP, ko-KR)
- /gsd-from-gsd2 → /gsd-import --from-gsd2 (CLI-TOOLS, FEATURES, INVENTORY)
- /gsd-verify-phase → /gsd-validate-phase (STATE-MD-LIFECYCLE)
- /gsd-settings-integrations → /gsd-settings or /gsd-config --integrations (CLI-TOOLS)
- /gsd-dev-preferences removed from profile-user artifact lists (AGENTS, COMMANDS,
  FEATURES in English, ja-JP, ko-KR)
- /gsd-select-framework removed from gsd-framework-selector spawner list
  (AGENTS, INVENTORY)

All 28 new tests pass.

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

* refactor(test): replace deny-list parity tests with polarity-inverted live-registry approach (#3049)

- Delete bug-3010-reapply-patches-references.test.cjs (hardcoded deny-list)
- Delete bug-3029-3034-stale-command-routes.test.cjs (hardcoded deny-list)
- Delete bug-3042-3044-research-flag-and-stale-refs.test.cjs (deny-list + frontmatter checks)
- Add tests/skill-frontmatter-contract.test.cjs (frontmatter structural checks extracted from deleted file)
- Update tests/commands-doc-parity.test.cjs to derive slug from name: frontmatter field
  instead of filename, so ns-* commands resolve to their actual deployed tokens

Closes #3049

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

* test: annotate commands-doc-parity with source-text-is-the-product exemption (#3049 lint fix)

The readFileSync on commands/gsd/*.md reads product markdown whose deployed
text IS what the user sees — content.startsWith('---') detects YAML frontmatter
in those files, not source-code structure. Add the allow-test-rule exemption
matching the same rationale used in docs-parity-live-registry.test.cjs.

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

* test: walk docs/** recursively to cover nested locale trees (CR finding 7)

Replaced the non-recursive listMdFiles() with a hand-rolled DFS walker
compatible with Node 20+. Surfaces unreadable-directory errors as stderr
warnings (PRED.k302) rather than silently skipping.

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

* test: annotate live-command-registry helper and commands-doc-parity with source-text exemptions (CR findings 6, 8)

Adds allow-test-rule comments to suppress lint-no-source-grep false
positives on YAML frontmatter structure checks in both files.

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

* test: anchor --research-phase assertions to arg-parsing section and verify combined refresh (CR findings 9, 10)

Finding 9: scopes --research-phase check to within 1200 chars of the flag
description section header, preventing false positives from prose mentions.

Finding 10: tightens the force-refresh assertion to require BOTH --research
and force/refresh semantics within the --research-phase description section,
verifying the combined-mode contract rather than standalone --research presence.

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

* test: fix execSync mock to accept opts parameter, forward to saved implementation (CR finding 5)

The mock at line 212 dropped the options parameter when delegating to
savedExecSync. Updated to (cmd, opts) signature and pass opts through.

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

* docs: correct routing entrypoint, --fast default, /gsd-review collision, verifying-stage mapping (CR findings 1-4)

Finding 1: Change Freeform Routing command from /gsd-fast to /gsd-progress --do.
/gsd-fast is the inline trivial-task executor, not the routing entrypoint.

Finding 2: Clarify that /gsd-map-codebase --fast REQ-SCAN-02 default (tech+arch)
runs as a single combined-focus agent, resolving the contradiction with REQ-SCAN-01.

Finding 3: Rename the namespace router /gsd-review to /gsd-quality across all docs,
command file, and help.md to eliminate the naming collision with the concrete
cross-AI peer-review command (review.md, name: gsd:review).

Finding 4: Replace /gsd-validate-phase with /gsd-verify-work in the STATE-MD-LIFECYCLE.md
verifying-stage table. /gsd-validate-phase is the retroactive Nyquist-validation
flow, not the normal phase-verification step.

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

* docs+test: fix locale doc drift surfaced by recursive walker (CR finding 7 follow-up)

The recursive listMdFiles() walker newly covered docs/**/*.md subdirs.
Stale command references in locale docs are now caught and fixed:

- docs/zh-CN/references/model-profiles.md: remove /gsd-set-profile (deleted command);
  config.json is the current mechanism
- docs/zh-CN/references/ui-brand.md: remove /gsd-alternative-1/2 template placeholders
- docs/{ja-JP,ko-KR,pt-BR}/superpowers/specs/2026-03-20-*: replace
  /gsd-new-workspace, /gsd-list-workspaces, /gsd-remove-workspace with
  /gsd-workspace --new / --list / --remove (consolidated in #2790)

Also adds smoke- and alternative-{1,2} to INTERNAL_COMPONENT_SLUGS (filesystem
path and template placeholder patterns, not slash commands) and introduces
listEnglishMdFiles() to scope the English parity check to docs/ excluding
locale subdirectories (which have their own per-locale describe blocks).

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

* docs: add bash language tag to fenced code blocks in ja-JP and ko-KR workspace specs (CR round 2)

Satisfies MD040 fenced-code-language requirement. These blocks contain
shell commands and were missing the language specifier.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 02:49:19 -04:00
Tom Boucher
924c697097 docs: replace retired /gsd-intel with /gsd-map-codebase --query (#3258) (#3260)
* test: forbid stale /gsd-intel references in workflow/reference docs (#3258)

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

* docs: replace retired /gsd-intel with /gsd-map-codebase --query (#3258)

Fixes 5 stale references across the two primary source files called out in
the issue. PR #2790 folded /gsd-intel into /gsd-map-codebase --query; these
prose surfaces were not updated at that time.

Fixes #3258

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

* docs: fix additional stale /gsd-intel references found in adversarial sweep (#3258)

Sweep found 7 more occurrences in docs/INVENTORY.md (x2), docs/USER-GUIDE.md (x4),
docs/FEATURES.md (x2), and agents/gsd-intel-updater.md (x2). All replaced with
/gsd-map-codebase --query. The gsd-intel-updater agent name itself (without leading
slash) is intentionally preserved.

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

* changeset: pr=3260 for #3258

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

* test: fail loudly on unreadable files in bug-3258 regression scan (CR finding)

Replace silent early-return on readFileSync failure with an explicit
throw so unreadable files surface as test failures rather than skipped
coverage gaps.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 09:06:37 -04:00
Tom Boucher
e3b52c70bb fix(docs): replace deleted /gsd-new-workspace with /gsd-workspace --new in FEATURES.md (#3221)
Feature 129 (Issue-Driven Orchestration Guide) referenced the deleted command
/gsd-new-workspace. Replace with its v1.40.0 successor /gsd-workspace --new to
fix the stale-ref test introduced in tests/bug-3042-3044-research-flag-and-stale-refs.

Fixes #3220

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 00:26:24 -04:00
Tom Boucher
c0be29607a docs: v1.41.0 release documentation — CHANGELOG promotion, release notes, FEATURES update (#3219)
- Promote CHANGELOG [Unreleased] → [1.41.0] - 2026-05-07; add fresh [Unreleased] header
- Fix CONFIGURATION.md version labels: 'added in v1.40' → 'added in v1.41' for models and dynamic_routing
- Create docs/RELEASE-v1.41.0.md in compact v1.39.0 bullet format
- Rewrite docs/RELEASE-v1.40.0-rc.1.md to compact bullet format (removes wall-of-text entries)
- Add docs/FEATURES.md v1.41.0 section (features 126–131: per-phase models, dynamic routing, update banner, issue-driven orchestration, graphify staleness, MVP SDK verbs)
- Update docs/FEATURES.md TOC
- Trim README "Notable extras" table (highlight page, not a command menu)

Fixes #3218

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 00:19:26 -04:00
Tom Boucher
811410be61 fix: address all 13 CodeRabbit comments from second review pass
Duplicate /gsd-help rows (caused by join-discord → help replacement
landing in tables that already had /gsd-help):
- Remove Discord-purpose duplicate row from README.md, README.ja-JP.md,
  README.zh-CN.md, README.ko-KR.md, docs/zh-CN/README.md,
  docs/zh-CN/USER-GUIDE.md, docs/ja-JP/USER-GUIDE.md,
  docs/ko-KR/USER-GUIDE.md
- Remove orphaned Discord-only ### /gsd-help sections from
  docs/ja-JP/COMMANDS.md and docs/ko-KR/COMMANDS.md

Gap-fix command precision (plan-milestone-gaps → audit-milestone --fix):
- README.ja-JP.md, README.ko-KR.md, README.zh-CN.md gap-fix rows
  updated to /gsd-audit-milestone --fix

docs/COMMANDS.md: document --path <dir> for --from-gsd2 in table and
  example block

docs/FEATURES.md:
- Add adaptive to /gsd-config --profile value set
- Add blank line before spike Produces table (MD058)

Suite: 6971/6971 pass
2026-05-05 11:22:37 -04:00
Tom Boucher
858c821829 docs: sweep stale /gsd-* command references across all user-facing docs
Replace 30 absorbed/deleted standalone command forms with their
consolidated flag-based equivalents across 25 files (English + 4
locales + AGENTS/CLI-TOOLS/CONFIGURATION):

  /gsd-session-report        → /gsd-pause-work --report
  /gsd-list-phase-assumptions → /gsd-discuss-phase --assumptions
  /gsd-analyze-dependencies  → /gsd-manager --analyze-deps
  /gsd-research-phase        → /gsd-plan-phase --research-phase
  /gsd-plan-milestone-gaps   → /gsd-audit-milestone
  /gsd-code-review-fix       → /gsd-code-review --fix
  /gsd-spike-wrap-up         → /gsd-spike --wrap-up
  /gsd-sketch-wrap-up        → /gsd-sketch --wrap-up
  /gsd-set-profile           → /gsd-config --profile
  /gsd-check-todos           → /gsd-capture --list
  /gsd-add-todo              → /gsd-capture
  /gsd-add-backlog           → /gsd-capture --backlog
  /gsd-plant-seed            → /gsd-capture --seed
  /gsd-note                  → /gsd-capture --note
  /gsd-add-phase             → /gsd-phase
  /gsd-insert-phase          → /gsd-phase --insert
  /gsd-edit-phase            → /gsd-phase --edit
  /gsd-remove-phase          → /gsd-phase --remove
  /gsd-new-workspace         → /gsd-workspace --new
  /gsd-list-workspaces       → /gsd-workspace --list
  /gsd-remove-workspace      → /gsd-workspace --remove
  /gsd-sync-skills           → /gsd-update --sync
  /gsd-reapply-patches       → /gsd-update --reapply
  /gsd-scan                  → /gsd-map-codebase --fast
  /gsd-intel                 → /gsd-map-codebase --query
  /gsd-next                  → /gsd-progress --next
  /gsd-do                    → /gsd-progress --do
  /gsd-status                → /gsd-progress
  /gsd-join-discord          → /gsd-help

Skipped: CHANGELOG, RELEASE notes, superpowers/specs (historical)
Suite: 6971/6971 pass
2026-05-05 11:01:15 -04:00
Tom Boucher
d978ad6b2f merge: sync main into PR #3114 and keep canonical next/profile commands 2026-05-04 23:32:42 -04:00
Tom Boucher
4ee6ce4a01 fix(3054): align docs anchors and structured stale-command checks 2026-05-04 23:30:35 -04:00
Tom Boucher
72f4c3b362 fix(docs): replace stale /gsd-next references with /gsd-progress --next 2026-05-04 22:54:01 -04:00
Tom Boucher
eb365f7336 docs: audit and update docs/ for v1.40.0 release (#3048)
* docs(en): update FEATURES/USER-GUIDE/COMMANDS for v1.40.0 surface

- FEATURES.md: append v1.40.0 section (#122 skill consolidation, #123
  namespace meta-skills, #124 context-window guard, #125 phase-lifecycle
  status-line read-side); add to TOC.
- USER-GUIDE.md: add slash-command form (hyphen vs colon) primer and
  namespace routing primer; replace deleted slash forms in walkthroughs
  (`/gsd-add-backlog`, `/gsd-plant-seed`, `/gsd-add-phase`,
  `/gsd-set-profile`, `/gsd-list-workspaces`, etc.) with consolidated
  forms (`/gsd-capture --backlog`, `/gsd-phase --insert`,
  `/gsd-config --profile`, `/gsd-workspace --list`, etc.); fix
  `/gsd-spike-wrap-up` and `/gsd-sketch-wrap-up` to flag form.
- COMMANDS.md: clarify Command Syntax (Gemini = colon form, others =
  hyphen form); add Namespace Meta-Skills section with all six routers;
  add `--context` to /gsd-health flag table.

Refs #3047

* docs(en): refresh INVENTORY/CLI-TOOLS/STATE-MD-LIFECYCLE for v1.40.0

- INVENTORY.md: workflow-row "Invoked by" column updated to point at
  consolidated commands (`/gsd-phase` family, `/gsd-workspace --list`,
  `/gsd-config --advanced/--integrations/--profile`,
  `/gsd-sketch --wrap-up`, `/gsd-spike --wrap-up`); CLI-modules row for
  `secrets.cjs` updated to `/gsd-config --integrations`. Command count
  and namespace meta-skills section already reflect 65 shipped (= 59
  consolidated sub-skills + 6 ns-* routers).
- CLI-TOOLS.md: add `validate context` row under Validation Commands
  with the 60 %/70 % threshold envelope used by `/gsd-health --context`.
- STATE-MD-LIFECYCLE.md: flip status header from "proposed" to
  "shipped in v1.40.0" since `parseStateMd()` and `formatGsdState()`
  now read and render `active_phase`, `next_action`, `next_phases`,
  and `progress`.

`docs/AGENTS.md` audited and verified clean — `gsd-code-fixer` row
already lists the correct `/gsd-code-review --fix` spawner; no
deleted-skill references found. `docs/INVENTORY-MANIFEST.json`
audited and verified clean — already enumerates the 65 commands
(including six ns-* routers) and contains no deleted slash forms.

Refs #3047

* docs(en): cleanup ARCHITECTURE/CONFIGURATION for v1.40.0

- ARCHITECTURE.md: split Commands install-target list to call out the
  Gemini colon form (`/gsd:command-name`) vs hyphen form for every
  other runtime. Add a new subsection covering two-stage hierarchical
  routing via the six namespace meta-skills (#2792) and a paired note
  on the MCP token-budget interaction so readers see the two big
  per-turn cost levers in one place.
- CONFIGURATION.md: rewrite three references to the deleted
  `/gsd-settings-advanced` and `/gsd-settings-integrations` slash
  forms to use the consolidated `/gsd-config --advanced` /
  `/gsd-config --integrations` invocations. Add a new "STATE.md
  Frontmatter (Phase Lifecycle)" section documenting the four
  optional fields (`active_phase`, `next_action`, `next_phases`,
  `progress`) read by the v1.40 status-line, with a pointer to
  STATE-MD-LIFECYCLE.md for the full reference.

`docs/manual-update.md` audited and verified clean — already documents
`/gsd-update --reapply` (the consolidated form), no reference to the
deleted `/gsd-reapply-patches`.

Refs #3047

* docs(i18n): mirror v1.40.0 slash-command rename into ja-JP/ko-KR/zh-CN/pt-BR

Mechanical token-level renames only — every reference to a deleted
micro-skill slash form is rewritten to the consolidated form on the
matching parent skill. No prose was machine-translated; new prose
sections (slash-form primer, namespace routing primer, v1.40 feature
entries, STATE.md frontmatter) were left for human translator
follow-up.

Renames applied uniformly across all four trees:
  /gsd-add-todo, /gsd-add-note, /gsd-add-backlog,
  /gsd-plant-seed, /gsd-check-todos      → /gsd-capture[ --note|
                                            --backlog|--seed|--list]
  /gsd-add-phase, /gsd-insert-phase,
  /gsd-remove-phase, /gsd-edit-phase     → /gsd-phase[ --insert|
                                            --remove|--edit]
  /gsd-new-workspace, /gsd-list-workspaces,
  /gsd-remove-workspace                  → /gsd-workspace[ --new|
                                            --list|--remove]
  /gsd-settings-advanced,
  /gsd-settings-integrations,
  /gsd-set-profile                       → /gsd-config[ --advanced|
                                            --integrations|--profile]
  /gsd-sketch-wrap-up                    → /gsd-sketch --wrap-up
  /gsd-spike-wrap-up                     → /gsd-spike --wrap-up
  /gsd-reapply-patches                   → /gsd-update --reapply
  /gsd-code-review-fix                   → /gsd-code-review --fix
  /gsd-plan-milestone-gaps               → /gsd-audit-milestone

Refs #3047

* docs(changelog): regroup [Unreleased] under Feature/Enhancement/Fix

Replace the existing Keep-a-Changelog \`Added\` / \`Changed\` /
\`Performance\` / \`Removed\` / \`Fixed\` sub-headers in the [Unreleased]
block with the issue/PR template taxonomy:

  Added                 → Feature
  Changed / Performance → Enhancement
  Removed               → Enhancement
  Fixed                 → Fix

Order within the release: Feature → Enhancement → Fix. Every bullet
preserved verbatim — only headers and grouping changed; the awkward
inline-versioned headers (\`### Added — 1.40.0-rc.1\`,
\`### Changed — 1.40.0-rc.1\`, \`### Fixed — 1.40.0-rc.1\`) folded into
the same buckets with the \`— 1.40.0-rc.1\` suffix dropped, since the
[Unreleased] block IS 1.40.0-rc.1.

The [1.39.2] hotfix block called out in #3047's spec does not yet
exist in CHANGELOG.md (the previously released hotfix is [1.39.1]),
so this commit only regroups [Unreleased]. Older release blocks
([1.39.1] and earlier) are frozen and untouched.

Refs #3047

* docs(changeset): add fragment for v1.40.0 doc audit

Refs #3047

* docs(en): strip leading / from deleted slash-command tokens in FEATURES

REQ-CONSOLIDATE-03 and REQ-CONSOLIDATE-04 listed deleted commands by
their `/gsd-foo` form for the historical record. The docs-parity tests
in bug-3010, bug-3029-3034, and bug-3042-3044 use the regex
`/\/gsd-[a-z0-9][a-z0-9-]*/g` to scan user-facing surfaces for any
remaining mention of removed slash forms — they cannot tell prose
about a deleted command from a live recommendation.

Strip the leading slash from the bare-name references (preserve the
historical text otherwise). Tests now require a `/` prefix to match,
so `gsd-add-todo` reads identically to a human but no longer trips
the parser.

Verified locally: 65/65 tests pass across the three docs-parity
suites that were red on CI run 25270072600.

Refs #3047

* docs(en): fix CR feedback + drop literal /gsd:plan-phase from USER-GUIDE

CI: tests/bug-2543-gsd-slash-namespace.test.cjs flagged
docs/USER-GUIDE.md:35 for embedding the literal `/gsd:plan-phase`
token in the parenthetical Gemini-form example. The test scans every
.md under docs/ for `/gsd:<live-cmd>` because non-Gemini surfaces must
not advertise the colon form. Replaced the literal example with a
prose substitution rule.

CR: docs/ARCHITECTURE.md:125 — the namespace meta-skills were listed
by file-prefix (`gsd-ns-workflow`) but the invocable frontmatter `name:`
is the bare form (`gsd-workflow`). Verified against the six
`commands/gsd/ns-*.md` files. Replaced with the canonical names and
noted the file/name disagreement in-line.

CR: docs/COMMANDS.md:723 — `v1.40` aligned to canonical `v1.40.0`.

CR: docs/FEATURES.md:2679 — REQ-CTX-GUARD-02 advertised the wrong
invocation (`gsd-tools validate context`). The shipped handler is
exposed via `gsd-sdk query validate.context` and requires explicit
`--tokens-used <int>` + `--context-window <int>` flags (verified
against sdk/src/query/validate.ts:849-882 and
get-shit-done/bin/lib/validate-command-router.cjs:19-36).

CR: docs/zh-CN/README.md:533 — added `inherit` to the profile-options
parenthetical to match the canonical set (verified against
model-profiles.cjs:29 `VALID_PROFILES = […MODEL_PROFILES['gsd-planner'], 'inherit']`).

Verified locally: 74/74 tests pass across the four docs-parity suites
that were red on CI runs 25270072600 and 25270182903.

Refs #3047
2026-05-03 07:33:27 -04:00
Tom Boucher
1e6737cd8e feat(plan-phase): --research-phase flag + scrub stale slash-command refs (#3042, #3044) (#3045)
* feat(plan-phase): --research-phase flag absorbs deleted /gsd-research-phase + scrub stale refs (#3042, #3044)

#3042 (orphaned research-phase): /gsd-research-phase had a workflow file
but no slash-command stub. Rather than restore the orphan, the research-
only capability is now a flag on /gsd-plan-phase:

  /gsd-plan-phase --research-phase <N>

When set, the workflow scopes to phase N, runs the research step (Section
5 of the existing plan-phase workflow), then early-exits before the
planner/plan-checker/verifier chain.

Per RCA against the deleted standalone, the flag adds two modifiers to
fully cover the original surface (Option B from the RCA discussion):

- --view : print existing RESEARCH.md to stdout, no spawn. Cheapest mode
  for the correction-without-replanning loop the issue reporter
  explicitly called out. Errors with a clear hint if RESEARCH.md is
  missing.
- --research : reuse the existing "force re-research" semantics. In
  research-only mode this skips the existing-RESEARCH.md prompt and
  re-spawns unconditionally.
- Neither flag, RESEARCH.md exists : prompt update/view/skip. Mirrors
  the deleted standalone's existing-artifact menu (#3042 RCA).

#3044 (stale slash-command refs): scrubbed five deleted commands from
all user-facing surfaces, including English docs, 4 localized doc sets
(ja-JP, ko-KR, zh-CN, pt-BR), workflows, templates, and references.

  /gsd-check-todos          → /gsd-capture --list
  /gsd-new-workspace        → /gsd-workspace --new
  /gsd-status               → /gsd-progress
  /gsd-plan-milestone-gaps  → table rows / orphan sections removed
                              (PR #3038 only scrubbed workflows/agent;
                              missed the docs surfaces this PR covers)
  /gsd-research-phase       → /gsd-plan-phase --research-phase

Includes a fix to docs/issue-driven-orchestration.md (PR #3036)
which itself referenced /gsd-new-workspace 4 times — self-correction.

Removed:
- get-shit-done/workflows/research-phase.md (orphan, capability
  absorbed into --research-phase flag)

Tests:
- tests/bug-3042-3044-research-flag-and-stale-refs.test.cjs — 46
  structural-IR tests across both bugs:
  - argument-hint advertises --research-phase + --view
  - workflow parses --research-phase, sets RESEARCH_ONLY,
    early-exits before planner
  - --view prints RESEARCH.md without spawning
  - --research forces refresh in research-only mode
  - existing-RESEARCH.md prompt path with update/view/skip
  - workflows/research-phase.md is removed
  - 5 deleted slash-commands absent from 17 English user-facing
    surfaces + 16 localized doc surfaces (4 locales × 4 docs each)
  - replacement command tokens present where deleted ones lived

6950/6950 full suite pass. Lints clean.

Closes #3042
Closes #3044

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: address all 8 CR findings on PR #3045

Major (3):
- get-shit-done/workflows/plan-phase.md:344 — added explicit early-exit
  guard at Section 5.1: "Skip if RESEARCH_ONLY=true". Without it, an LLM
  could fall through "use existing, skip to step 6" → planner spawn,
  violating the research-only contract. The guard makes the early-exit
  unreachable from any non-research-only branch.
- get-shit-done/references/continuation-format.md (3 examples) +
  zh-CN/.../continuation-format.md (3 examples) — pointed to
  `/gsd-plan-phase --research-phase` but docs/COMMANDS.md didn't
  document the flag. Added a full --research-phase + --view + --research
  modifier section to the /gsd-plan-phase flag table in COMMANDS.md so
  the canonical reference matches the continuation examples.

Minor (5):
- docs/FEATURES.md:1632 — `/gsd-plan-phase --research-phase` →
  `/gsd-plan-phase --research-phase <N>` (include required arg).
- get-shit-done/templates/README.md:46 — NN-VALIDATION.md producer
  reverted from `/gsd-plan-phase --research-phase` (Nyquist) to plain
  `/gsd-plan-phase` (Nyquist). VALIDATION.md is created during normal
  Nyquist flow, not research-only mode — the bulk replacement was
  wrong for that line.
- get-shit-done/workflows/help.md:89 — signature line was missing
  `--research`; added it alongside `--research-phase` and `--view`.
- tests/bug-3042-3044-...:197 — promptHasView/promptHasSkip were
  tautological (matched anywhere in 1700-line workflow). Tightened
  to a proximity check anchored on "RESEARCH.md already exists" prompt
  header within a 600-char window. Updated workflow to emit that
  literal phrase.
- tests/feat-2840-...:95 — workspace assertion used `/gsd-workspace`
  but the documented replacement is `/gsd-workspace --new`. Tightened
  to require both tokens (in 3 places: requiredCommands list, regex
  in conceptPairs, error message).

6950/6950 full suite pass. Lint clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 23:12:50 -04:00
Tom Boucher
7714b5244b fix(workflows,docs): scrub stale /gsd-code-review-fix and /gsd-plan-milestone-gaps refs (#3029, #3034) (#3038)
* fix(workflows,docs): scrub stale /gsd-code-review-fix and /gsd-plan-milestone-gaps refs (#3029, #3034)

#2790 consolidated /gsd-code-review-fix into /gsd-code-review --fix and
deleted /gsd-plan-milestone-gaps in favor of inline gap planning as part
of /gsd-audit-milestone's output. The deletion was propagated through
some surfaces (#2950 covered help/do/settings/discuss-phase/etc.) but
several user-facing surfaces still emitted the old forms:

#3029 — /gsd-code-review-fix references in:
- agents/gsd-code-fixer.md (description, "Spawned by", recovery prose)
- get-shit-done/workflows/code-review.md (offer text)
- get-shit-done/workflows/execute-phase.md (offer text)
- get-shit-done/workflows/code-review-fix.md (internal retry hints)
- docs/INVENTORY.md (agent + workflow rows)
- docs/CONFIGURATION.md (workflow.code_review row)
- docs/USER-GUIDE.md (3 occurrences in walkthrough)
- docs/AGENTS.md (gsd-code-fixer agent stub)
- docs/FEATURES.md (commands list + REQ-REVIEW-04)

All replaced with /gsd-code-review --fix. Internal retry hints in the
workflow file itself updated to point at the new form. Release notes
(docs/RELEASE-*.md) and gsd-ns-review's "absorbed by" deletion note
left unchanged — historical/explanatory content.

#3034 — /gsd-plan-milestone-gaps references in:
- get-shit-done/workflows/audit-milestone.md (<offer_next> blocks for
  gaps_found and tech_debt: lines 281, 323)
- commands/gsd/complete-milestone.md (gaps_found pre-flight: lines 46, 57)

Replaced with inline closure path:
  /gsd-phase --insert <N> "Close gap: <REQ-ID> ..."
  /gsd-discuss-phase <N>
  /gsd-plan-phase <N>
  /gsd-execute-phase <N>

Plus a Nyquist-coverage hint pointing at /gsd-validate-phase /
/gsd-secure-phase for retroactive audit-chain hygiene gaps. The
gsd-ns-project SKILL.md "deleted by #2790" note is preserved
(it's the canonical pointer for future readers asking what
happened to the command).

Tests:
- tests/bug-3029-3034-stale-command-routes.test.cjs — parser-based
  assertions per fixed surface, plus a structural cross-check that
  gsd-ns-project keeps the deletion note. 15 tests, all green.
- 6905/6905 full suite passes.

Closes #3029
Closes #3034

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: address CR feedback on PR #3038 — argument order, structural tests, agent count

CR findings on PR #3038:

1. **docs/USER-GUIDE.md (Major)** — `--fix` examples used flag-first form
   (`/gsd-code-review --fix 3`), but the supported CLI grammar is
   phase-first (`/gsd-code-review 3 --fix`). The original sed-based
   replacement preserved the position of the `gsd-code-review-fix`
   token, producing the wrong order. Fixed in USER-GUIDE.md (3
   occurrences) and the same drift in the workflow surfaces:
   - get-shit-done/workflows/code-review-fix.md (2 retry hints)
   - get-shit-done/workflows/code-review.md (offer text)
   - get-shit-done/workflows/execute-phase.md (offer text)

2. **docs/AGENTS.md (Minor)** — internal count drift: line 483 said
   "Ten additional agents" but line 725 said "12 advanced/specialized".
   Filesystem reality: 33 agents total, 21 primary, 12 specialized
   (count of `### ` stubs in the Advanced and Specialized section).
   Updated lines 3, 13, 483 to use 12/33 and added the two missing
   names (doc-classifier, doc-synthesizer) to the inline list at
   line 13.

3. **tests:94 (Major refactor suggestion)** — `.includes()` token checks
   were source-grep style. Refactored to a typed-IR pattern: extract
   the SET of slash-command tokens via regex, assert membership on the
   parsed Set instead of substring scanning the raw file text. Added
   the `allow-test-rule` comment explaining the IR-build vs
   IR-assertion split per scripts/lint-no-source-grep.cjs convention.

4. **tests:130 (Major)** — replacement-path assertion was file-wide and
   could false-pass on generic mentions of "inline" elsewhere in the
   file. Refactored: `extractOfferBlocks(content)` returns the typed
   list of `<offer_next>` and "Pre-flight" blocks where the deleted
   command previously lived, and the assertion runs against those
   blocks specifically. Now requires `/gsd-phase --insert` or
   inline-audit prose to appear in the same offer block, not just
   somewhere in the file.

15/15 targeted tests pass. 6905/6905 full suite pass. Lints clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 17:23:44 -04:00
Tom Boucher
95d2bc20f8 feat(hooks): opt-in SessionStart update banner for non-statusline users (#2795) (#3035)
* feat(hooks): opt-in SessionStart update banner for non-statusline users (#2795)

When a user declines (or keeps a non-GSD) statusline at install time, the
installer now offers an opt-in SessionStart banner that surfaces GSD update
availability. The banner reads the existing
~/.cache/gsd/gsd-update-check.json cache (written by
gsd-check-update-worker.js) and emits a single systemMessage line only when
update_available is true:

    GSD update available: <installed> → <latest>. Run /gsd-update.

It is silent when up-to-date and rate-limits "check failed" diagnostics to
once per 24h via a sentinel file so a corrupt cache doesn't nag every
session. Removed cleanly by `npx get-shit-done-cc --uninstall` which strips
both the script and the SessionStart entry. The banner is never offered when
GSD's statusline is being installed (statusline already surfaces update
info, so re-prompting would be noise).

Implementation:
- hooks/gsd-update-banner.js — pure functions buildBannerOutput,
  shouldSuppressFailureWarning, readCache; thin main() wires them.
- bin/install.js — handleUpdateBanner() prompt, parseUpdateBannerInput(),
  buildUpdateBannerHookEntry(), buildUpdateBannerPromptText(); chained into
  installAllRuntimes() so finalize() receives both flags. updateBannerCommand
  computed alongside the other JS-hook commands; finishInstall() registers
  the SessionStart entry only when shouldInstallBanner === true and the
  hook file is present at the target.
- Hook ships in scripts/build-hooks.js HOOKS_TO_COPY, listed in
  MANAGED_HOOKS for stale-detection in gsd-check-update-worker.js, in the
  uninstall hook-removal lists in install.js, and in the
  rewriteLegacyManagedNodeHookCommands allowlist.

Tests:
- tests/feat-2795-update-banner.test.cjs — 22 tests, structural-IR
  assertions on parsed JSON envelopes (no raw-text matching). Covers
  pure-function branches (cache present/absent, parseError, rate-limit
  suppression, missing version fields), end-to-end hook invocation against
  fixture cache states, and install.js wiring (prompt text, input parsing,
  hook entry shape).
- tests/trae-install.test.cjs — updated install() return-shape assertion to
  include updateBannerCommand: null for the no-settings runtime.
- 6881/6881 tests pass.

Docs (bundled in same commit per the bundle-docs-with-code skill):
- docs/USER-GUIDE.md — new "Surface GSD Update Notifications Without GSD's
  Statusline" task section with opt-in/opt-out instructions.
- docs/FEATURES.md — REQ-HOOK-08 added; "Update Banner" subsection under
  the Hook System feature with cache flow + removal path.
- docs/INVENTORY.md — hook count 11 → 12, new row for gsd-update-banner.js.
- docs/INVENTORY-MANIFEST.json — regenerated.

Closes #2795

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(install): gate banner prompt on actual installability (CR #3035)

CodeRabbit findings on PR #3035:

- bin/install.js (Major): continueAfterStatusline gated banner prompt on
  the raw `shouldInstallStatusline` flag from handleStatusline. But
  finishInstall later silently skips the statusline write on local
  installs unless --force-statusline is set (#2248). Two consequences:
    1. Interactive local Claude/Gemini installs got neither a statusline
       nor a banner offer.
    2. Codex/Cursor/Copilot/Windsurf/Trae/Cline-only installs (where
       every result.updateBannerCommand is null) still got prompted even
       though the choice was silently ignored.
  Fix: derive willInstallStatusline = shouldInstallStatusline &&
  (isGlobal || forceStatusline), and gate the banner prompt on a
  canInstallBanner precondition computed from results[].updateBannerCommand.
  Pass the raw shouldInstallStatusline through to finalize unchanged so
  per-runtime statusline gating in finishInstall is unaffected.

- tests/feat-2795-update-banner.test.cjs (Minor): rate-limit suppression
  test parsed r1.stdout without first asserting r1.status === 0. Other
  e2e tests in this file (lines 210, 241) do this. A non-zero exit would
  surface as a cryptic SyntaxError instead of a status assertion failure.
  Fix applied verbatim.

6881/6881 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 16:33:16 -04:00
Tom Boucher
e1d661ece0 feat(#3024): dynamic routing with failure-tier escalation (#3031)
* feat(#3024): dynamic routing with failure-tier escalation

Adds a `dynamic_routing` block to .planning/config.json that lets
the resolver start agents on a cheap tier and escalate one tier up
when the orchestrator detects a soft failure (verification
inconclusive, plan-check FLAG, etc.). Solves the "pay Opus rates as
insurance" anti-pattern by making escalation observed-quality-driven.

Architecture:
- AGENT_DEFAULT_TIERS map (light/standard/heavy) — every agent in
  MODEL_PROFILES declares a default tier; tests assert coverage
  so adding a new agent without updating the map fails CI.
- nextTier(currentTier) helper — light → standard → heavy → heavy
  (heavy stays at heavy; can't go further).
- resolveModelForTier(cwd, agentType, attempt) — new resolver. The
  orchestrator tracks the attempt counter and passes 0 for the
  first spawn, 1+ on escalation. The resolver caps internally at
  max_escalations so the orchestrator can blindly bump the counter.
- Schema validation: dynamic_routing.enabled / escalate_on_failure /
  max_escalations / tier_models.<light|standard|heavy>. Unknown
  tiers and unknown sub-keys rejected at config-set time.
- SDK schema mirror updated to keep CJS/SDK in lockstep (#2653).

Resolution precedence (highest → lowest):
  1. model_overrides[<agent>]              (full IDs accepted)
  2. dynamic_routing.tier_models[<tier>]   (NEW; escalation-aware)
  3. models[<phase_type>]                  (#3023 phase-type map)
  4. model_profile                         (per-agent column)
  5. Runtime default

Backward compatibility: dynamic_routing is disabled by default
(enabled: false or block omitted). resolveModelForTier short-
circuits to resolveModelInternal in that case, so callers can
adopt unconditionally without breaking existing behavior.

This PR delivers the JS-layer infrastructure: schema + tier map +
resolver. Orchestrator adoption (workflow markdown updates that
detect soft failures and call resolveModelForTier with attempt+1)
is incremental follow-up — verifier / plan-checker / integration-
checker each adopt the protocol when ready.

Tests (23 cases, all structural-IR — no stdout grep):
- Schema invariants: AGENT_DEFAULT_TIERS coverage, VALID_AGENT_TIERS
  exact match, every assignment uses a valid tier
- nextTier helper: light→standard→heavy→heavy, null on invalid input
- Disabled mode: no block + enabled:false both no-op (back-compat)
- Enabled mode: attempt=0 returns default tier model, attempt=1
  escalates, beyond max_escalations caps, heavy agents stay heavy,
  default max_escalations=1 when omitted
- Precedence: per-agent override beats dynamic_routing,
  dynamic_routing beats phase-type models
- Validation: every settings key accepted, unknown tiers/sub-keys
  rejected, bare `dynamic_routing` rejected as config-set target

Documentation:
- get-shit-done/references/model-profiles.md — full reference section
- docs/CONFIGURATION.md — full settings table + escalation flow
- docs/USER-GUIDE.md — task-oriented "Cheap-by-default" section
- docs/FEATURES.md — config row cross-link

Verification:
- 23/23 pass on regression test
- 6843/6843 full suite (23 net new from 6820)
- lint-no-source-grep clean (376 test files)
- SDK schema mirror keeps CJS/SDK in sync per #2653 parity test

Closes #3024

* fix(#3024): honor escalate_on_failure:false + 3 CR follow-ups

CodeRabbit on PR #3031 (4 findings — 1 Major + 2 Minor + 1 Nitpick):

1. **Major (inline)** — get-shit-done/bin/lib/core.cjs:1668
   resolveModelForTier ignored dynamic_routing.escalate_on_failure.
   When the user set it to false, escalation should be disabled, but
   the resolver only checked attempt/max_escalations. An orchestrator
   that always passes attempt+1 on retry would silently escalate
   despite the user opting out.
   Fix: gate effectiveAttempt on `dr.escalate_on_failure !== false`
   so false short-circuits every attempt back to the default tier.

2. **Minor (inline)** — docs/CONFIGURATION.md:123-126
   The dynamic_routing rows in the Core Settings table had 4 cells
   instead of 5 (missing the Options column), breaking the table
   structure. Added explicit Options values for enabled / escalate_on_failure
   / max_escalations rows.

3. **Minor (outside-diff)** — references/model-profiles.md:179-195
   "Resolution Logic" sketch was pre-#3024 and didn't include
   dynamic_routing in the precedence ladder. Updated to a 6-step
   block with dynamic_routing at step 3 (between override and
   phase-type).

4. **Nitpick** — tests/feat-3024-dynamic-routing.test.cjs:189+
   Tests used `if (lightAgent) { ... }` guards that silent-pass
   when AGENT_DEFAULT_TIERS drifts. Replaced all 5 conditional
   skips with `assert.ok(lightAgent, '...')` preconditions so a
   tier-mapping change surfaces as a test failure.

Plus: 2 new regression tests for the Major fix:
- escalate_on_failure:false caps every attempt at default tier
- escalate_on_failure:true (explicit) still escalates normally

Verification:
- 25/25 pass on regression test (23 prior + 2 escalate_on_failure)
- 6845/6845 full suite (2 net new)
- lint-no-source-grep clean

* docs(#3024): align precedence + add fence language tags (CR follow-up)

CodeRabbit (3 minor):

1. docs/CONFIGURATION.md:691 — "Per-Phase-Type Models → Resolution
   precedence" was a 4-step block written pre-#3024; readers got
   contradictory rules between the per-phase-type section and the
   later dynamic_routing section. Updated to the same 5-step ladder
   with dynamic_routing at step 2, and noted that dynamic_routing
   is disabled by default so this section's behavior is unchanged
   when the kill-switch is off.

2. docs/CONFIGURATION.md:770 — escalation-flow code fence missing
   language tag (MD040). Added `text`.

3. references/model-profiles.md:184 — resolution-ladder code fence
   missing language tag (MD040). Added `text`.

No code changes; docs only. Verification: regression test still 25/25.

* docs(#3024): clarify precedence prose — five layers, not four (CR nitpick)

CodeRabbit nitpick: the "Per-Phase-Type Models → Resolution
precedence" prose said "The four layers compose..." but the ladder
above lists five (including Runtime default). Also "dynamic_routing
escalates per-attempt above all of them" misreads as suggesting
dynamic_routing wins over model_overrides — actually overrides still
win at step 1.

Reworded top-down so the precedence direction is unambiguous:
  - model_profile = base
  - models = phase-level override
  - dynamic_routing = per-attempt escalation
  - model_overrides = per-agent exception (top)
  - runtime default = fallback

No code changes; docs only.

* docs(#3024): note escalate_on_failure:false in escalation-flow diagram (CR)

CodeRabbit nitpick: the escalation-flow diagram in
docs/CONFIGURATION.md described the soft-failure → respawn →
tier_models[next_tier_up] path, but didn't surface the
`dynamic_routing.escalate_on_failure: false` kill-switch right next
to it. Users reading the flow diagram (which is the canonical place
to understand attempt behavior) wouldn't see that the kill-switch
overrides the soft-failure branch.

Added a one-paragraph note immediately after the flow listing,
before the tier-sequence example, so the kill-switch is visible
exactly where users decide whether escalation will happen.

No code changes; docs only.
2026-05-02 14:26:35 -04:00
Tom Boucher
d812c66020 feat(#3023): per-phase-type model map in .planning/config.json (#3030)
* feat(#3023): per-phase-type model map in .planning/config.json

Adds a new `models` block to .planning/config.json with six phase-type
slots (planning / discuss / research / execution / verification /
completion). Lets users express coarse tuning ("Opus for planning,
Sonnet for the rest") without learning the agent taxonomy.

Resolution precedence (highest → lowest):
  1. Per-agent `model_overrides[agent]`     (full IDs; targeted exception)
  2. Phase-type `models[phase_type]`         (NEW; tier alias)
  3. Profile table (`model_profile`)          (per-agent column)
  4. Runtime default

The three layers compose: `models` defaults a phase, `model_overrides`
carves an exception. Phase-type values are tier aliases (opus/sonnet/
haiku/inherit) so the runtime-resolution chain (#2517) stays correct
end-to-end without further branching.

Implementation:
- model-profiles.cjs: new AGENT_TO_PHASE_TYPE map + VALID_PHASE_TYPES
  set. Each agent in MODEL_PROFILES gets one phase-type assignment;
  tests assert coverage so adding a new agent without updating the
  table fails CI.
- core.cjs (resolveModelInternal): inserts phase-type tier lookup
  between per-agent override and profile-derived tier. Skips runtime
  resolution when the resolved tier is 'inherit' (was previously gated
  only on profile === 'inherit'; phase-type can now produce inherit
  independently).
- core.cjs (loadConfig): pass `parsed.models` through both code paths
  so resolveModelInternal can read it.
- config-schema.cjs + sdk/src/query/config-schema.ts: dynamic-pattern
  validator accepts only the six known phase-types; unknown slots
  rejected at config-set time.

Backward compat: configs without `models` behave exactly as today.

Tests (15 cases, all structural-IR — no stdout grep):
- Schema: AGENT_TO_PHASE_TYPE coverage, VALID_PHASE_TYPES exact match
- Resolver: phase-type alone; per-agent override beats phase-type;
  phase-type beats profile; issue's full example; "inherit"; empty
  block is no-op; no block is no-op
- Validation: each of the 6 slots accepted; unknown slot rejected;
  bare `models` (no slot) rejected

Verification:
- 15/15 pass on new regression test
- 6808/6808 full suite (5 net new), 0 fail
- lint-no-source-grep clean across 375 test files

Closes #3023

* docs(#3023): document `models` per-phase-type config in user-facing docs

Adds `models` block coverage to the three user-facing docs that ship
with each release:

1. docs/CONFIGURATION.md
   - New "Per-Phase-Type Models" section between "Per-Agent Overrides"
     and "Non-Claude Runtimes" with:
       * full example mixing models + model_overrides
       * phase-type → agent mapping table
       * resolution-precedence pseudocode
       * accepted values (tier alias only)
       * "When to use which" decision matrix
       * validation behavior + example error
   - Added `"models": {}` to the Full Schema snippet
   - Added a row for `models.<phase_type>` to the config keys table
     (next to model_profile_overrides for adjacency)

2. docs/FEATURES.md
   - Added a row for models.<phase_type> in the Configurable Settings
     table (right under model_profile)
   - Cross-link to CONFIGURATION.md for the full surface

3. docs/USER-GUIDE.md
   - New task-oriented "Tuning model cost by phase" section above
     "Using Non-Claude Runtimes" — leads with the concrete config
     and shows the override pattern (one-shot phase + targeted exception)
   - Cross-link to CONFIGURATION.md

Verification:
- 29/29 pass on config-schema-docs-parity + docs-update + new feature
  test (parity-check passes, so the config-schema entry I added in the
  feature commit is now matched by a docs row)
- 6808/6808 full suite pass
- lint-no-source-grep clean

Doc style follows the same pattern used by the existing model_profile,
model_overrides, and model_profile_overrides sections — example-led,
table-backed, cross-referenced. Each doc surfaces the feature at the
right depth (reference / settings table / task guide).

* fix(#3023): mirror phase-type tier in resolveReasoningEffortInternal (CR Major)

CodeRabbit caught a real Codex correctness bug + 3 minor docs/test issues:

1. **Major (outside-diff)** — resolveReasoningEffortInternal in core.cjs
   derived its tier exclusively from the profile table, ignoring the
   models.<phase_type> override added in #3023. Failure mode on Codex:

     Config: model_profile=balanced, models.execution=opus, agent=gsd-executor
     resolveModelInternal:           tier=opus    → gpt-5.4
     resolveReasoningEffortInternal: tier=sonnet  → reasoning_effort=medium
                                                     ↑
                                                  WRONG — should be xhigh
                                                  (opus tier on Codex)

   The runtime received a mismatched (model, effort) pair. Mirrored the
   phase-type lookup from resolveModelInternal so both functions derive
   from the same tier source. 'inherit' phase-type returns null effort
   (no runtime entry maps to 'inherit'; let runtime decide).

2. Minor — .changeset/per-phase-type-models.md `pr: TBD` → `pr: 3030`.

3. Minor (outside-diff) — model-profiles.md "Resolution Logic" section
   omitted the new phase-type tier. Updated the 4-step block to a 5-step
   block including `models[phase_type]` between override and profile,
   plus a paragraph noting that `model` and `reasoning_effort` derive
   from the same tier source.

4. Nitpick — added 2 typo-safety tests:
   - models.research = "haiku3" (typo) → falls through to profile
   - models.research = "openai/gpt-5" (full ID) → falls through to profile
   Plus 5 new reasoning_effort tests covering the Major fix:
   - exported correctly
   - phase-type override flips both model AND effort to same tier
   - inherit phase-type returns null effort
   - per-agent override still bypasses phase-type for effort
   - claude runtime ignores models.* (no effort propagation)

Verification:
- 24/24 pass on regression test (15 original + 2 typo-safety + 5 effort + 2 outside-diff related)
- 6815/6815 full suite (7 net new from 6808)
- lint-no-source-grep clean

The reasoning_effort tests are written semantically (phase-type override
must produce the SAME effort as a profile-only opus config) rather than
hard-coding tier-specific effort strings, so changes to the runtime tier
map don't break them.

* fix(#3023): phase-type override beats profile=inherit (CR Major round 2)

CodeRabbit caught another precedence inversion: when
  { model_profile: 'inherit', models: { execution: 'opus' } }
both resolvers short-circuited on `profile === 'inherit'` BEFORE the
phase-type override could be honored. Result: model returned 'inherit'
and reasoning_effort returned null — both contradicting the documented
precedence where models[phase_type] wins over model_profile.

Fix in resolveModelInternal:
- Compute tier from phase-type FIRST. If phase-type is a valid alias,
  it wins. Otherwise, fall back to profile-derived tier OR 'inherit'
  (when profile === 'inherit').
- Gate the runtime-resolution branch on `tier !== 'inherit'` (was
  `profile !== 'inherit'`) so phase-type=opus can flip runtime mapping
  on even when profile=inherit.
- Gate the inherit-return on `tier === 'inherit'` (was
  `profile === 'inherit'`).

Fix in resolveReasoningEffortInternal:
- Remove the `if (profile === 'inherit') return null;` early-return.
- Compute tier from phase-type first, fall back to profile. If
  phase-type is explicitly 'inherit' OR the resolved tier is 'inherit',
  return null (no runtime entry maps to inherit).

Tests added (5 new):
- model: phase-type wins over profile=inherit (with explicit opus, with
  haiku for one phase + planner-without-slot still inheriting)
- model: profile=inherit + no models block → all agents inherit (no
  regression on existing inherit semantics)
- model: profile=inherit + models block but agent has no slot → that
  agent inherits, agents with slots get phase-type tier
- effort: phase-type opus + profile=inherit → produces opus-tier
  effort, NOT null (the original bug)

Verification:
- 27/27 pass on regression test (24 prior + 3 model + 1 effort)
- 6820/6820 full suite (5 net new)
- lint-no-source-grep clean

The effort test reads the expected value by running a profile-only opus
config and comparing — semantic check, not hard-coded effort string. So
runtime tier map changes don't break the test.
2026-05-02 13:19:15 -04:00
Tom Boucher
f2decefede fix(#3010): post-install message and docs use /gsd-update --reapply (#3012)
* fix(#3010): post-install message and docs use /gsd-update --reapply

PR #2824 consolidated 86 skills into ~58, removing the standalone
/gsd-reapply-patches command and folding it into a flag on /gsd-update
(/gsd-update --reapply). The 1.39.1 hotfix (#2954) updated help.md
but missed three other surfaces that still recommended the dead form:

1. bin/install.js reportLocalPatches() — runtime emitter shown after
   every install with backed-up patches. All branches updated:
   - claude/opencode/kilo/copilot: /gsd-update --reapply
   - gemini: /gsd:update --reapply
   - codex: $gsd-update --reapply
   - cursor: gsd-update --reapply (mention the skill name)

2. get-shit-done/workflows/update.md — Step 4 prose and the
   check_local_patches block both referenced /gsd-reapply-patches.
   Replaced with /gsd-update --reapply (with backticks around the
   command per CR feedback for copy/paste UX).

3. Localized docs (en/ja-JP/ko-KR/zh-CN) — 14 files across
   ARCHITECTURE.md / COMMANDS.md / FEATURES.md / INVENTORY.md /
   USER-GUIDE.md / manual-update.md still listed the removed command.

Tests:
- bug-3010-reapply-patches-references.test.cjs (4 tests): scans
  bin/install.js's reportLocalPatches body, every workflow file, and
  every doc (excluding CHANGELOG history and help.md's deprecation
  notice) for the removed command form, and verifies each runtime
  branch emits the consolidated form via captured console output.
- tests/copilot-install.test.cjs:1081-1115 — stale assertions that
  hard-coded the removed string updated to assert /gsd-update --reapply.

Verification: 115/115 pass across both files.

Co-authored-by: Patrick Clery <patrick@patrickclery.com>
Closes #3010

* test(#3010): broaden dead-command scan + tighten runtime exact-match

CodeRabbit follow-up findings on #3012:

1. Workflow + docs scans only matched "/gsd-reapply-patches", missing
   the gemini ("/gsd:reapply-patches") and codex ("$gsd-reapply-patches")
   spellings. A regression that re-introduced either form in localized
   docs would have passed silently. Extracted a DEAD_COMMAND_PATTERNS
   array + findDeadCommands() helper used by both scans, so all three
   removed forms are checked uniformly. Match output also reports which
   spellings hit, for faster diagnosis.

2. reportLocalPatches runtime test asserted output.includes('update --reapply'),
   which is too loose — a malformed prefix like '/gsd:update --reapply' on
   the claude branch would have passed. Replaced with an exact
   {runtime → expected token} map covering all 7 branches:
     claude/opencode/kilo/copilot → /gsd-update --reapply
     gemini → /gsd:update --reapply
     codex → $gsd-update --reapply
     cursor → gsd-update --reapply
   Negative assertion also runs DEAD_COMMAND_PATTERNS against output for
   every runtime, so dead forms can't slip in regardless of branch.

Verification: 4/4 pass on bug-3010-reapply-patches-references.test.cjs.

* test(#3010): add prefix-absence guard for cursor runtime (CR follow-up)

CodeRabbit (Minor): the cursor expected token "gsd-update --reapply" is
a substring of every prefixed form ("/gsd-update --reapply" for claude/
opencode/kilo/copilot, "\$gsd-update --reapply" for codex). The positive
output.includes(expectedToken) check therefore can't distinguish correct
cursor output from a regression where the installer emits a prefixed
form for cursor — both pass the substring check.

Add an explicit prefix-absence assertion for cursor that fails if any
of /, \$, or : appears immediately before "gsd-update --reapply" in
output. The gemini form ("/gsd:update --reapply") doesn't share the
substring (gsd:update vs gsd-update) so it's already caught by the
positive includes failing on cursor's expected bare token.

Verification: 4/4 pass.

---------

Co-authored-by: Patrick Clery <patrick@patrickclery.com>
2026-05-02 09:38:34 -04:00
Jeremy McSpadden
4d394a249d fix(commands): normalize gsd slash namespace drift (#2858)
* fix(commands): normalize gsd slash namespace drift

* fix(#2855): address CodeRabbit findings on namespace drift PR

Three CR findings, all valid:

1. autonomous.md line 783 still had `gsd:discuss-phase` (the PR's own
   normalization missed this line). Switched to `gsd-discuss-phase` and
   updated the matching test in autonomous-interactive.test.cjs that was
   asserting the now-retired colon form.

2. tests/bug-2543-gsd-slash-namespace.test.cjs source-grepped the
   fix-slash-commands.cjs script with .includes() rather than driving
   its transform behaviour. Refactored fix-slash-commands.cjs to export
   a pure transformContent(src, cmdNames) function, kept the CLI behaviour
   unchanged via require.main, and replaced the source-grep block with
   five behavioural cases: rewrite, multi-occurrence, idempotence on
   canonical input, no-op on gsd-sdk/gsd-tools, and word-boundary safety.

3. tests/bug-2808-skill-hyphen-name.test.cjs matched `name:` anywhere
   in SKILL.md; a stray name: in the body could satisfy the assertion.
   Scoped the lookup to the YAML frontmatter block via the suggested
   diff (parse the leading --- ... --- region first, then find name:
   inside it).

Full suite: 5854/5854 passing.

* fix(#2855): address remaining CodeRabbit findings on PR #2858

Three structural concerns flagged on the namespace-drift fix PR:

1. scripts/fix-slash-commands.cjs:24 — `buildPattern([])` compiled
   `/gsd:()(?=[^a-zA-Z0-9_-]|$)/g`. The empty capture group still
   matches any `/gsd:` token followed by a non-word boundary
   (whitespace, EOL, punctuation), rewriting it to a stray `/gsd-`.
   Verified live: `transformContent("/gsd:", [])` → `"/gsd-"`. Added
   a guard returning null from `buildPattern` on empty input and
   updated `transformContent` and `processDir` to no-op when the
   pattern is null.

2. tests/autonomous-interactive.test.cjs:44-47 — assertion was
   `content.includes('gsd-discuss-phase') && content.includes('INTERACTIVE')`,
   which would false-pass on any unrelated co-occurrence (e.g.
   `INTERACTIVE=""` initialization plus a stray `gsd-discuss-phase`
   prose mention). Replaced with a structural extraction: locate the
   `**If \`INTERACTIVE\` is set:**` branch, bound it by the next
   `**If` / `<step>` boundary, and assert the
   `Skill(skill="gsd-discuss-phase", ...)` invocation lives inside
   that region. Tolerates whitespace around `(`, `skill`, and `=`.

3. tests/bug-2808-skill-hyphen-name.test.cjs:104 — colon-call regex
   was `Skill\(skill=...` and missed valid formatting like
   `Skill(skill = "gsd:cmd")` or `Skill( skill = ...)`. Loosened to
   `Skill\(\s*skill\s*=\s*...` so reformatting drift can't slip past
   the namespace guard.

Verification: 5854/5854 pass on `npm test` from the rebased branch.

* fix(#2855): drop pre-validation filter that hid namespace drift

CR finding on tests/bug-2808-skill-hyphen-name.test.cjs:128: the test
collected generated skill directories with
`.filter(entry => entry.isDirectory() && entry.name.startsWith('gsd-'))`,
then validated namespace invariants over that filtered list. Anything
that violated the prefix invariant — `gsd:extract-learnings` (colon
form), `extract_learnings` without prefix, `Gsd-foo` mis-cased — would
silently disappear from the iteration and the test would falsely pass.

Drop the `startsWith('gsd-')` filter so every generated directory shows
up. Add explicit assertions before the existing per-skill loop:
  - directory list is non-empty (catches a broken converter that
    produces nothing)
  - every directory begins with `gsd-`
  - every directory contains no `:`
  - every directory contains no `_`

Re-audited the full PR diff for the same anti-pattern: only this one
site filtered before validating the namespace; bug-2643 and
commands-doc-parity also use `readdirSync().filter()` but only by file
extension, which is correct.

5854/5854 on `npm test`.

* fix(#2855): address remaining CR findings (1 active + 2 nitpicks)

Three findings on PR #2858, all the same root cause: input narrowing
before validation lets drift slip past the guards.

1. tests/bug-2808-...:104 (active) — `colonCallRe` captured local names
   with `[a-z0-9-]+`, which excluded the underscore. A drift like
   `Skill(skill="gsd:extract_learnings")` (deprecated colon syntax with
   the old underscore filename) silently slid through. Broadened the
   capture to `[^'"\s)]+` so any malformed local name is surfaced; surrounding pattern (whitespace tolerance, escape support, flags)
   unchanged.

2. tests/bug-2643-...:43 (nitpick) — `extractSkillNamesHyphen` and
   `extractSkillNamesColon` had the same over-strict capture plus
   relied on a single regex over raw bytes, which the project test-
   rigor memory bans (`feedback_no_source_grep_tests.md`). Replaced
   with `extractSkillCalls(content)` — a small structural extractor
   that walks `Skill(` openers, locates each call's matching `)`,
   parses the body's `skill = "..."` keyword argument with permissive
   whitespace + quoting + escape handling, and returns
   `{ name, raw }` records. The two namespace-form helpers become
   thin filters over the structured output. Tightened the body class
   to `[^'"\\]+` so a trailing escape `\` before the closing quote
   (as in `Skill(skill=\"gsd-foo\", …)` written inside another string
   context) doesn't get included in the captured name.

3. tests/bug-2543-...:44 (nitpick) — `DOC_SEARCH_FILES` was a hand-
   curated 7-entry array. Every doc added in the future would silently
   weaken drift detection until someone remembered to extend the list.
   Replaced with `discoverDocSearchFiles(ROOT)`: globs every `.md`
   under `docs/` and adds `README.md` if present. New docs are picked
   up automatically.

Re-audited the diff surface for similar narrowings; no other sites
filter or constrain before validating namespace invariants.

5854/5854 on `npm test`.

* fix(#2855): recurse docs/ tree so localized translations are scanned too

CR finding: discoverDocSearchFiles() stopped at docs/*.md, leaving
localized translation trees (docs/ja-JP/, docs/zh-CN/, docs/ko-KR/,
docs/pt-BR/) and other nested doc collections (docs/skills/,
docs/superpowers/) invisible to the namespace-drift invariant.

Verified the gap: docs/ has 6 nested directories with ~30 .md files
that the previous top-level-only scan was skipping. None contain
/gsd: references today, but a future translation update or new
doc subdir could leak drift.

Switch to an iterative stack walk so every .md under docs/ is scanned
regardless of depth. Stack form (rather than recursion) avoids the
risk of running into the call-stack limit on deep doc trees.

5854/5854 on `npm test`.

---------

Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
2026-04-29 22:56:59 -04:00
Tom Boucher
e81592878e feat(#2789): trim skill description anti-patterns; enforce 100-char budget (#2823)
* feat(#2789): trim skill description anti-patterns; enforce 100-char budget

- Trim descriptions in all commands/gsd/*.md files over 100 chars
- Remove flag documentation from descriptions (belongs in argument-hint)
- Remove Triggers: keyword stuffing
- Add scripts/lint-descriptions.cjs — fails on descriptions > 100 chars
- Add npm script: lint:descriptions
- Add tests/enh-2789-description-budget.test.cjs

Closes #2789

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

* docs(#2789): add CHANGELOG entry for description budget lint

* docs(#2789): update COMMANDS.md descriptions; add skill description standards note

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:14:11 -04:00
Tom Boucher
1a694fcac3 feat: auto-remap codebase after significant phase execution (closes #2003) (#2605)
* feat: auto-remap codebase after significant phase execution (#2003)

Adds a post-phase structural drift detector that compares the committed tree
against `.planning/codebase/STRUCTURE.md` and either warns or auto-remaps
the affected subtrees when drift exceeds a configurable threshold.

## Summary
- New `bin/lib/drift.cjs` — pure detector covering four drift categories:
  new directories outside mapped paths, new barrel exports at
  `(packages|apps)/*/src/index.*`, new migration files, and new route
  modules. Prioritizes the most-specific category per file.
- New `verify codebase-drift` CLI subcommand + SDK handler, registered as
  `gsd-sdk query verify.codebase-drift`.
- New `codebase_drift_gate` step in `execute-phase` between
  `schema_drift_gate` and `verify_phase_goal`. Non-blocking by contract —
  any error logs and the phase continues.
- Two new config keys: `workflow.drift_threshold` (int, default 3) and
  `workflow.drift_action` (`warn` | `auto-remap`, default `warn`), with
  enum/integer validation in `config-set`.
- `gsd-codebase-mapper` learns an optional `--paths <p1,p2,...>` scope hint
  for incremental remapping; agent/workflow docs updated.
- `last_mapped_commit` lives in YAML frontmatter on each
  `.planning/codebase/*.md` file; `readMappedCommit`/`writeMappedCommit`
  round-trip helpers ship in `drift.cjs`.

## Tests
- 55 new tests in `tests/drift-detection.test.cjs` covering:
  classification, threshold gating at 2/3/4 elements, warn vs. auto-remap
  routing, affected-path scoping, `--paths` sanitization (traversal,
  absolute, shell metacharacter rejection), frontmatter round-trip,
  defensive paths (missing STRUCTURE.md, malformed input, non-git repos),
  CLI JSON output, and documentation parity.
- Full suite: 5044 pass / 0 fail.

## Documentation
- `docs/CONFIGURATION.md` — rows for both new keys.
- `docs/ARCHITECTURE.md` — section on the post-execute drift gate.
- `docs/AGENTS.md` — `--paths` flag on `gsd-codebase-mapper`.
- `docs/USER-GUIDE.md` — user-facing behavior note + toggle commands.
- `docs/FEATURES.md` — new 27a section with REQ-DRIFT-01..06.
- `docs/INVENTORY.md` + `docs/INVENTORY-MANIFEST.json` — drift.cjs listed.
- `get-shit-done/workflows/execute-phase.md` — `codebase_drift_gate` step.
- `get-shit-done/workflows/map-codebase.md` — `parse_paths_flag` step.
- `agents/gsd-codebase-mapper.md` — `--paths` directive under parse_focus.

## Design decisions
- **Frontmatter over sidecar JSON** for `last_mapped_commit`: keeps the
  baseline attached to the file, survives git moves, survives per-doc
  regeneration, no extra file lifecycle.
- **Substring match against STRUCTURE.md** for `isPathMapped`: the map is
  free-form markdown, not a structured manifest; any mention of a path
  prefix counts as "mapped territory". Cheap, no parser, zero false
  negatives on reasonable maps.
- **Category priority migration > route > barrel > new_dir** so a file
  matching multiple rules counts exactly once at the most specific level.
- **Empty-tree SHA fallback** (`4b825dc6…`) when `last_mapped_commit` is
  absent — semantically correct (no baseline means everything is drift)
  and deterministic across repos.
- **Four layers of non-blocking** — detector try/catch, CLI try/catch, SDK
  handler try/catch, and workflow `|| echo` shell fallback. Any single
  layer failing still returns a valid skipped result.
- **SDK handler delegates to `gsd-tools.cjs`** rather than re-porting the
  detector to TypeScript, keeping drift logic in one canonical place.

Closes #2003

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(mapper): tag --paths fenced block as text (CodeRabbit MD040)

Comment 3127255172.

* docs(config): use /gsd- dash command syntax in drift_action row (CodeRabbit)

Comment 3127255180. Matches the convention used by every other command
reference in docs/CONFIGURATION.md.

* fix(execute-phase): initialize AGENT_SKILLS_MAPPER + tag fenced blocks

Two CodeRabbit findings on the auto-remap branch of the drift gate:

- 3127255186 (must-fix): the mapper Task prompt referenced
  ${AGENT_SKILLS_MAPPER} but only AGENT_SKILLS (for gsd-executor) is
  loaded at init_context (line 72). Without this fix the literal
  placeholder string would leak into the spawned mapper's prompt.
  Add an explicit gsd-sdk query agent-skills gsd-codebase-mapper step
  right before the Task spawn.
- 3127255183: tag the warn-message and Task() fenced code blocks as
  text to satisfy markdownlint MD040.

* docs(map-codebase): wire PATH_SCOPE_HINT through every mapper prompt

CodeRabbit (review id 4158286952, comment 3127255190) flagged that the
parse_paths_flag step defined incremental-remap semantics but did not
inject a normalized variable into the spawn_agents and sequential_mapping
mapper prompts, so incremental remap could silently regress to a
whole-repo scan.

- Define SCOPED_PATHS / PATH_SCOPE_HINT in parse_paths_flag.
- Inject ${PATH_SCOPE_HINT} into all four spawn_agents Task prompts.
- Document the same scope contract for sequential_mapping mode.

* fix(drift): writeMappedCommit tolerates missing target file

CodeRabbit (review id 4158286952, drift.cjs:349-355 nitpick) noted that
readMappedCommit returns null on ENOENT but writeMappedCommit threw — an
asymmetry that breaks first-time stamping of a freshly produced doc that
the caller has not yet written.

- Catch ENOENT on the read; treat absent file as empty content.
- Add a regression test that calls writeMappedCommit on a non-existent
  path and asserts the file is created with correct frontmatter.
  Test was authored to fail before the fix (ENOENT) and passes after.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 21:21:44 -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
2e97dee0d0 docs: update release notes and command reference for v1.37.0 (#2382)
* 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>

* docs: update release notes and command reference for v1.37.0

Covers spike/sketch commands, agent size-budget enforcement, and shared
boilerplate extraction across README, COMMANDS, FEATURES, and USER-GUIDE.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 13:45:30 -04:00
Tom Boucher
990b87abd4 feat(discuss-phase): adapt gray area language for non-technical owners via USER-PROFILE.md (#2125) (#2173)
When USER-PROFILE.md signals a non-technical product owner (learning_style: guided,
jargon in frustration_triggers, or high-level explanation_depth), discuss-phase now
reframes gray area labels and advisor_research rationale paragraphs in product-outcome
language. Same technical decisions, translated framing so product owners can participate
meaningfully without needing implementation vocabulary.

Closes #2125

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 16:45:29 -04:00
Tom Boucher
e24cb18b72 feat(workflow): add opt-in TDD pipeline mode (#2119)
* feat(workflow): add opt-in TDD pipeline mode (workflow.tdd_mode)

Add workflow.tdd_mode config key (default: false) that enables
red-green-refactor as a first-class phase execution mode. When
enabled, the planner aggressively applies type: tdd to eligible
tasks and the executor enforces RED/GREEN/REFACTOR gate sequence
with fail-fast on unexpected GREEN before RED. An end-of-phase
collaborative review checkpoint verifies gate compliance.

Closes #1871

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

* fix(test): allowlist plan-phase.md in prompt injection scan

plan-phase.md exceeds 50K chars after TDD mode integration.
This is legitimate orchestration complexity, not prompt stuffing.

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

* ci: trigger CI run

* ci: trigger CI run

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 14:42:01 -04:00
Tom Boucher
4553d356d2 docs: add v1.36.0 feature documentation for PRs #2100-#2111
Document 8 new features (108-115) in FEATURES.md, add --bounce/--cross-ai
flags to COMMANDS.md, new /gsd-extract-learnings command, 8 new config keys
in CONFIGURATION.md, and skill-manifest + --ws flag in CLI-TOOLS.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 09:54:21 -04:00
Tom Boucher
6c2795598a docs: release notes and documentation updates for v1.35.0 (#2079)
Closes #2080
2026-04-10 22:29:06 -04:00