mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
0a049149e1e9a25d522a6f583fbb69bfc6dc5d2b
612 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0a049149e1 |
fix(sdk): decouple from build-from-source install, close #2441 #2453 (#2457)
* fix(sdk): decouple SDK from build-from-source install path, close #2441 and #2453
Ship sdk/dist prebuilt in the tarball and replace the npm-install-g
sub-install with a parent-package bin shim (bin/gsd-sdk.js). npm chmods
bin entries from a packed tarball correctly, eliminating the mode-644
failure (#2453) and the full class of NPM_CONFIG_PREFIX/ignore-scripts/
corepack/air-gapped failure modes that caused #2439 and #2441.
Changes:
- sdk/package.json: prepublishOnly runs `rm -rf dist && tsc && chmod +x
dist/cli.js` (stale-build guard + execute-bit fix at publish time)
- package.json: add "gsd-sdk": "bin/gsd-sdk.js" bin entry; add sdk/dist
to files so the prebuilt CLI ships in the tarball
- bin/gsd-sdk.js: new back-compat shim — resolves sdk/dist/cli.js relative
to the package root and delegates via `node`, so all existing PATH call
sites (slash commands, agents, hooks) continue to work unchanged (S1 shim)
- bin/install.js: replace installSdkIfNeeded() build-from-source + global-
install dance with a dist-verify + chmod-in-place guard; delete
resolveGsdSdk(), detectShellRc(), emitSdkFatal() helpers now unused
- .github/workflows/install-smoke.yml: add smoke-unpacked job that strips
execute bit from sdk/dist/cli.js before install to reproduce the exact
#2453 failure mode
- tests/bug-2441-sdk-decouple.test.cjs: new regression tests asserting all
invariants (no npm install -g from sdk/, shim exists, sdk/dist in files,
prepublishOnly has rm -rf + chmod)
- tests/bugs-1656-1657.test.cjs: update stale assertions that required
build-from-source behavior (now asserts new prebuilt-dist invariants)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(release): bump to 1.38.2, wire release.yml to build SDK dist
- Bump version 1.38.1 -> 1.38.2 for the #2441/#2453 fix shipped in
|
||
|
|
f30da8326a |
feat: add gates ensuring discuss-phase decisions are translated to plans and verified (closes #2492) (#2611)
* feat(#2492): add gates ensuring discuss-phase decisions are translated and verified Two gates close the loop between CONTEXT.md `<decisions>` and downstream work, fixing #2492: - Plan-phase **translation gate** (BLOCKING). After requirements coverage, refuses to mark a phase planned when a trackable decision is not cited (by id `D-NN` or by 6+-word phrase) in any plan's `must_haves`, `truths`, or body. Failure message names each missed decision with id, category, text, and remediation paths. - Verify-phase **validation gate** (NON-BLOCKING). Searches plans, SUMMARY.md, files modified, and recent commit subjects for each trackable decision. Misses are written to VERIFICATION.md as a warning section but do not change verification status. Asymmetry is deliberate — fuzzy-match miss should not fail an otherwise green phase. Shared helper `parseDecisions()` lives in `sdk/src/query/decisions.ts` so #2493 can consume the same parser. Decisions opt out of both gates via `### Claude's Discretion` heading or `[informational]` / `[folded]` / `[deferred]` tags. Both gates skip silently when `workflow.context_coverage_gate=false` (default `true`). Closes #2492 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(#2492): make plan-phase decision gate actually block (review F1, F8, F9, F10, F15) - F1: replace `${context_path}` with `${CONTEXT_PATH}` in the plan-phase gate snippet so the BLOCKING gate receives a non-empty path. The variable was defined in Step 4 (`CONTEXT_PATH=$(_gsd_field "$INIT" ...)`) and the gate snippet referenced the lowercase form, leaving the gate to run with an empty path argument and silently skip. - F15: wrap the SDK call with `jq -e '.data.passed == true' || exit 1` so failure halts the workflow instead of being printed and ignored. The verify-phase counterpart deliberately keeps no exit-1 (non-blocking by design) and now carries an inline note documenting the asymmetry. - F10: tag the JSON example fence as `json` and the options-list fence as `text` (MD040). - F8/F9: anchor the heading-presence test regexes to `^## 13[a-z]?\\.` so prose substrings like "Requirements Coverage Gate" mentioned in body text cannot satisfy the assertion. Added two new regression tests (variable-name match, exit-1 guard) so a future revert is caught. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(#2492): tighten decision-coverage gates against false positives and config drift (review F3,F4,F5,F6,F7,F16,F18,F19) - F3: forward `workstream` arg through both gate handlers so workstream-scoped `workflow.context_coverage_gate=false` actually skips. Added negative test that creates a workstream config disabling the gate while the root config has it enabled and asserts the workstream call is skipped. - F4: restrict the plan-phase haystack to designated sections — front-matter `must_haves` / `truths` / `objective` plus body sections under headings matching `must_haves|truths|tasks|objective`. HTML comments and fenced code blocks are stripped before extraction so a commented-out citation or a literal example never counts as coverage. Verify-phase keeps the broader artifact-wide haystack by design (non-blocking). - F5: reject decisions with fewer than 6 normalized words from soft-matching (previously only rejected when the resulting phrase was under 12 chars AFTER slicing — too lenient). Short decisions now require an explicit `D-NN` citation, with regression tests for the boundary. - F6: walk every `*-SUMMARY.md` independently and use `matchAll` with the `/g` flag so multiple `files_modified:` blocks across multiple summaries are all aggregated. Previously only the first block in the concatenated string was parsed, silently dropping later plans' files. - F7: validate every `files_modified` path stays inside `projectDir` after resolution (rejects absolute paths, `../` traversal). Cap each file read at 256 KB. Skipped paths emit a stderr warning naming the entry. - F16: validate `workflow.context_coverage_gate` is boolean in `loadGateConfig`; warn loudly on numeric or other-shaped values and default to ON. Mirrors the schema-vs-loadConfig validation gap from #2609. - F18: bump verify-phase `git log -n` cap from 50 to 200 so longer-running phases are not undercounted. Documented as a precision-vs-recall tradeoff appropriate for a non-blocking gate. - F19: tighten `QueryResult` / `QueryHandler` to be parameterized (`<T = unknown>`). Drops the `as unknown as Record<string, unknown>` casts in the gate handlers and surfaces shape mismatches at compile time for callers that pass a typed `data` value. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(#2492): harden decisions parser and verify-phase glob (review F11,F12,F13,F14,F17,F20) - F11: strip fenced code blocks from CONTEXT.md before searching for `<decisions>` so an example block inside ``` ``` is not mis-parsed. - F12: accept tab-indented continuation lines (previously required a leading space) so decisions split with `\t` continue cleanly. - F13: parse EVERY `<decisions>` block in the file via `matchAll`, not just the first. CONTEXT.md may legitimately carry more than one block. - F14: `decisions.parse` handler now resolves a relative path against `projectDir` — symmetric with the gate handlers — and still accepts absolute paths. - F17: replace `ls "${PHASE_DIR}"/*-CONTEXT.md | head -1` in verify-phase.md with a glob loop (ShellCheck SC2012 fix). Also avoids spawning an extra subprocess and survives filenames with whitespace. - F20: extend the unicode quote-stripping in the discretion-heading match to cover U+2018/2019/201A/201B and the U+201C-F double-quote variants plus backtick, so any rendering of "Claude's Discretion" collapses to the same key. Each fix has a regression test in `decisions.test.ts`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1a3d953767 |
feat: add unified post-planning gap checker (closes #2493) (#2610)
* feat: add unified post-planning gap checker (closes #2493) Adds a unified post-planning gap checker as Step 13e of plan-phase.md. After all plans are generated and committed, scans REQUIREMENTS.md and CONTEXT.md <decisions> against every PLAN.md in the phase directory and emits a single Source | Item | Status table. Why - The existing Requirements Coverage Gate (§13) blocks/re-plans on REQ gaps but emits two separate per-source signals. Issue #2493 asks for one unified report after planning so that requirements AND discuss-phase decisions slipping through are surfaced in one place before execution starts. What - New workflow.post_planning_gaps boolean config key, default true, added to VALID_CONFIG_KEYS, CONFIG_DEFAULTS, hardcoded.workflow, and cmdConfigSet (boolean validation). - New get-shit-done/bin/lib/decisions.cjs — shared parser for CONTEXT.md <decisions> blocks (D-NN entries). Designed for reuse by the related #2492 plan/verify decision gates. - New get-shit-done/bin/lib/gap-checker.cjs — parses REQUIREMENTS.md (checkbox + traceability table forms), reads CONTEXT.md decisions, walks PHASE_DIR/*-PLAN.md, runs word-boundary coverage detection (REQ-1 must not match REQ-10), formats a sorted report. - New gsd-tools gap-analysis CLI command wired through gsd-tools.cjs. - workflows/plan-phase.md gains §13e between §13d (commit plans) and §14 (Present Final Status). Existing §13 gate preserved — §13e is additive and non-blocking. - sdk/prompts/workflows/plan-phase.md gets an equivalent post_planning_gaps step for headless mode. - Docs: CONFIGURATION.md, references/planning-config.md, INVENTORY.md, INVENTORY-MANIFEST.json all updated. Tests - tests/post-planning-gaps-2493.test.cjs: 30 test cases covering step insertion position, decisions parser, gap detector behavior (covered/not-covered, false-positive guard, missing-file resilience, malformed-input resilience, gate on/off, deterministic natural sort), and full config integration. - Full suite: 5234 / 5234 pass. Design decisions - Numbered §13e (sub-step), not §14 — §14 already exists (Present Final Status); inserting before it preserves downstream auto-advance step numbers. - Existing §13 gate kept, not replaced — §13 blocks/re-plans on REQ gaps; §13e is the unified post-hoc report. Per spec: "default behavior MUST be backward compatible." - Word-boundary ID matching avoids REQ-1 matching REQ-10 and avoids brittle semantic/substring matching. - Shared decisions.cjs parser so #2492 can reuse the same regex. - Natural-sort keys (REQ-02 before REQ-10) for deterministic output. - Boolean validation in cmdConfigSet rejects non-boolean values matches the precedent set by drift_threshold/drift_action. Closes #2493 * fix(#2493): expose post_planning_gaps in loadConfig() + sync schema example Address CodeRabbit review on PR #2610: - core.cjs loadConfig(): return post_planning_gaps from both the config.json branch and the global ~/.gsd/defaults.json fallback so callers can rely on config.post_planning_gaps regardless of whether the key is present (comment 3127977404, Major). - docs/CONFIGURATION.md: add workflow.post_planning_gaps to the Full Schema JSON example so copy/paste users see the new toggle alongside security_block_on (comment 3127977392, Minor). - tests/post-planning-gaps-2493.test.cjs: regression coverage for loadConfig() — default true when key absent, honors explicit true/false from workflow.post_planning_gaps. |
||
|
|
cc17886c51 |
feat: make model profiles runtime-aware for Codex/non-Claude runtimes (closes #2517) (#2609)
* feat: make model profiles runtime-aware for Codex/non-Claude runtimes (closes #2517) Adds an optional top-level `runtime` config key plus a `model_profile_overrides[runtime][tier]` map. When `runtime` is set, profile tiers (opus/sonnet/haiku) resolve to runtime-native model IDs (and reasoning_effort where supported) instead of bare Claude aliases. Codex defaults from the spec: opus -> gpt-5.4 reasoning_effort: xhigh sonnet -> gpt-5.3-codex reasoning_effort: medium haiku -> gpt-5.4-mini reasoning_effort: medium Claude defaults mirror MODEL_ALIAS_MAP. Unknown runtimes fall back to the Claude-alias safe default rather than emit IDs the runtime cannot accept. reasoning_effort is only emitted into Codex install paths; never returned from resolveModelInternal and never written to Claude agent frontmatter. Backwards compatible: any user without `runtime` set sees identical behavior — the new branch is gated on `config.runtime != null`. Precedence (highest to lowest): 1. per-agent model_overrides 2. runtime-aware tier resolution (when `runtime` is set) 3. resolve_model_ids: "omit" 4. Claude-native default 5. inherit (literal passthrough) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(#2517): address adversarial review of #2609 (findings 1-16) Addresses all 16 findings from the adversarial review of PR #2609. Each finding is enumerated below with its resolution. CRITICAL - F1: readGsdRuntimeProfileResolver(targetDir) now probes per-project .planning/config.json AND ~/.gsd/defaults.json with per-project winning, so the PR's headline claim ("set runtime in project config and Codex TOML emit picks it up") actually holds end-to-end. - F2: resolveTierEntry field-merges user overrides with built-in defaults. The CONFIGURATION.md string-shorthand example `{ codex: { opus: "gpt-5-pro" } }` now keeps reasoning_effort from the built-in entry. Partial-object overrides like `{ opus: { reasoning_effort: 'low' } }` keep the built-in model. Both paths regression-tested. MAJOR - F3: resolveReasoningEffortInternal gates strictly on the RUNTIMES_WITH_REASONING_EFFORT allowlist regardless of override presence. Override + unknown-runtime no longer leaks reasoning_effort. - F4: runtime:"claude" is now a no-op for resolution (it is the implicit default). It no longer hijacks resolve_model_ids:"omit". Existing tests for `runtime:"claude"` returning Claude IDs were rewritten to reflect the no-op semantics; new test asserts the omit case returns "". - F5: _readGsdConfigFile in install.js writes a stderr warning on JSON parse failure instead of silently returning null. Read failure and parse failure are warned separately. Library require is hoisted to top of install.js so it is not co-mingled with config-read failure modes. - F6: install.js requires for core.cjs / model-profiles.cjs are hoisted to the top of the file with __dirname-based absolute paths so global npm install works regardless of cwd. Test asserts both lib paths exist relative to install.js __dirname. - F7: docs/CONFIGURATION.md `runtime` row no longer lists `opencode` as a valid runtime — install-path emission for non-Codex runtimes is explicitly out of scope per #2517 / #2612, and the doc now points at #2612 for the follow-on work. resolveModelInternal still accepts any runtime string (back-compat) and falls back safely for unknown values. - F8: Tests now isolate HOME (and GSD_HOME) to a per-test tmpdir so the developer's real ~/.gsd/defaults.json cannot bleed into assertions. Same pattern CodeRabbit caught on PRs #2603 / #2604. - F9: `runtime` and `model_profile_overrides` documented as flat-only in core.cjs comments — not routed through `get()` because they are top-level keys per docs/CONFIGURATION.md and introducing nested resolution for two new keys was not worth the edge-case surface. - F10/F13: loadConfig now invokes _warnUnknownProfileOverrides on the raw parsed config so direct .planning/config.json edits surface unknown runtime values (e.g. typo `runtime: "codx"`) and unknown tier values (e.g. `model_profile_overrides.codex.banana`) at read time. Warnings only — preserves back-compat for runtimes added later. Per-process warning cache prevents log spam across repeated loadConfig calls. MINOR / NIT - F11: Removed dead `tier || 'sonnet'` defensive shortcut. The local is now `const alias = tier;` with a comment explaining why `tier` is guaranteed truthy at that point (every MODEL_PROFILES entry defines `balanced`, the fallback profile). - F12: Extracted resolveTierEntry() in core.cjs as the single source of truth for runtime-aware tier resolution. core.cjs and bin/install.js both consume it — no duplicated lookup logic between the two files. - F14: Added regression tests for findings #1, #2, #3, #4, #6, #10, #13 in tests/issue-2517-runtime-aware-profiles.test.cjs. Each must-fix path has a corresponding test that fails against the pre-fix code and passes against the post-fix code. - F15: docs/CONFIGURATION.md `model_profile` row cross-references #1713 / #1806 next to the `adaptive` enum value. - F16: RUNTIME_PROFILE_MAP remains in core.cjs as the single source of truth; install.js imports it through the exported resolveTierEntry helper rather than carrying its own copy. Doc files (CONFIGURATION.md, USER-GUIDE.md, settings.md) intentionally still embed the IDs as text — code comment in core.cjs flags that those doc files must be updated whenever the constant changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
41dc475c46 |
refactor(workflows): extract discuss-phase modes/templates/advisor for progressive disclosure (closes #2551) (#2607)
* refactor(workflows): extract discuss-phase modes/templates/advisor for progressive disclosure (closes #2551) Splits 1,347-line workflows/discuss-phase.md into a 495-line dispatcher plus per-mode files in workflows/discuss-phase/modes/ and templates in workflows/discuss-phase/templates/. Mirrors the progressive-disclosure pattern that #2361 enforced for agents. - Per-mode files: power, all, auto, chain, text, batch, analyze, default, advisor - Templates lazy-loaded at the step that produces the artifact (CONTEXT.md template at write_context, DISCUSSION-LOG.md template at git_commit, checkpoint.json schema when checkpointing) - Advisor mode gated behind `[ -f $HOME/.claude/get-shit-done/USER-PROFILE.md ]` — inverse of #2174's --advisor flag (don't pay the cost when unused) - scout_codebase phase-type→map selection table extracted to references/scout-codebase.md - New tests/workflow-size-budget.test.cjs enforces tiered budgets across all workflows/*.md (XL=1700 / LARGE=1500 / DEFAULT=1000) plus the explicit <500 ceiling for discuss-phase.md per #2551 - Existing tests updated to read from the new file locations after the split (functional equivalence preserved — content moved, not removed) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(#2607): align modes/auto.md check_existing with parent (Update it, not Skip) CodeRabbit flagged drift between the parent step (which auto-selects "Update it") and modes/auto.md (which documented "Skip"). The pre-refactor file had both — line 182 said "Skip" in the overview, line 250 said "Update it" in the actual step. The step is authoritative. Fix the new mode file to match. Refs: PR #2607 review comment 3127783430 * test(#2607): harden discuss-phase regression tests after #2551 split CodeRabbit identified four test smells where the split weakened coverage: - workflow-size-budget: assertion was unreachable (entered if-block on match, then asserted occurrences === 0 — always failed). Now unconditional. - bug-2549-2550-2552: bounded-read assertion checked concatenated source, so src.includes('3') was satisfied by unrelated content in scout-codebase.md (e.g., "3-5 most relevant files"). Now reads parent only with a stricter regex. Also asserts SCOUT_REF exists. - chain-flag-plan-phase: filter(existsSync) silently skipped a missing modes/chain.md. Now fails loudly via explicit asserts. - discuss-checkpoint: same silent-filter pattern across three sources. Now asserts each required path before reading. Refs: PR #2607 review comments 3127783457, 3127783452, plus nitpicks for chain-flag-plan-phase.test.cjs:21-24 and discuss-checkpoint.test.cjs:22-27 * docs(#2607): fix INVENTORY count, context.md placeholders, scout grep portability - INVENTORY.md: subdirectory note said "50 top-level references" but the section header now says 51. Updated to 51. - templates/context.md: footer hardcoded XX-name instead of declared placeholders [X]/[Name], which would leak sample text into generated CONTEXT.md files. Now uses the declared placeholders. - references/scout-codebase.md: no-maps fallback used grep -rl with "\\|" alternation (GNU grep only — silent on BSD/macOS grep). Switched to grep -rlE with extended regex for portability. Refs: PR #2607 review comments 3127783404, 3127783448, plus nitpick for scout-codebase.md:32-40 * docs(#2607): label fenced examples + clarify overlay/advisor precedence - analyze.md / text.md / default.md: add language tags (markdown/text) to fenced example blocks to silence markdownlint MD040 warnings flagged by CodeRabbit (one fence in analyze.md, two in text.md, five in default.md). - discuss-phase.md: document overlay stacking rules in discuss_areas — fixed outer→inner order --analyze → --batch → --text, with a pointer to each overlay file for mode-specific precedence. - advisor.md: add tie-breaker rules for NON_TECHNICAL_OWNER signals — explicit technical_background overrides inferred signals; otherwise OR-aggregate; contradictory explanation_depth values resolve by most-recent-wins. Refs: PR #2607 review comments 3127783415, 3127783437, plus nitpicks for default.md:24, discuss-phase.md:345-365, and advisor.md:51-56 * fix(#2607): extract codebase_drift_gate body to keep execute-phase under XL budget PR #2605 added 80 lines to execute-phase.md (1622 -> 1702), pushing it over the XL_BUDGET=1700 line cap enforced by tests/workflow-size-budget.test.cjs (introduced by this PR). Per the test's own remediation hint and #2551's progressive-disclosure pattern, extract the codebase_drift_gate step body to get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md and leave a brief pointer in the workflow. execute-phase.md is now 1633 lines. Budget is NOT relaxed; the offending workflow is tightened. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
220da8e487 |
feat: /gsd-settings-integrations — configure third-party search and review integrations (closes #2529) (#2604)
* feat(#2529): /gsd-settings-integrations — third-party integrations command Adds /gsd-settings-integrations for configuring API keys, code-review CLI routing, and agent-skill injection. Distinct from /gsd-settings (workflow toggles) because these are connectivity, not pipeline shape. Three sections: - Search Integrations: brave_search / firecrawl / exa_search API keys, plus search_gitignored toggle. - Code Review CLI Routing: review.models.{claude,codex,gemini,opencode} shell-command strings. - Agent Skills Injection: agent_skills.<agent-type> free-text input, validated against [a-zA-Z0-9_-]+. Security: - New secrets.cjs module with ****<last-4> masking convention. - cmdConfigSet now masks value/previousValue in CLI output for secret keys. - Plaintext is written only to .planning/config.json; never echoed to stdout/stderr, never written to audit/log files by this flow. - Slug validators reject path separators, whitespace, shell metacharacters. Tests (tests/settings-integrations.test.cjs — 25 cases): - Artifact presence / frontmatter. - Field round-trips via gsd-tools config-set for all four search keys, review.models.<cli>, agent_skills.<agent-type>. - Config-merge safety: unrelated keys preserved across writes. - Masking: config-set output never contains plaintext sentinel. - Logging containment: plaintext secret sentinel appears only in config.json under .planning/, nowhere else on disk. - Negative: path-traversal, shell-metachar, and empty-slug rejected. - /gsd:settings workflow mentions /gsd:settings-integrations. Docs: - docs/COMMANDS.md: new command entry with security note. - docs/CONFIGURATION.md: integration settings section (keys, routing, skills injection) with masking documentation. - docs/CLI-TOOLS.md: reviewer CLI routing and secret-handling sections. - docs/INVENTORY.md + INVENTORY-MANIFEST.json regenerated. Closes #2529 * fix(#2529): mask secrets in config-get; address CodeRabbit review cmdConfigGet was emitting plaintext for brave_search/firecrawl/exa_search. Apply the same isSecretKey/maskSecret treatment used by config-set so the CLI surface never echoes raw API keys; plaintext still lives only in config.json on disk. Also addresses CodeRabbit review items in the same PR area: - #3127146188: config-get plaintext leak (root fix above) - #3127146211: rename test sentinels to concat-built markers so secret scanners stop flagging the test file. Behavior preserved. - #3127146207: add explicit 'text' language to fenced code blocks (MD040). - nitpick: unify masked-value wording in read_current legend ('****<last-4>' instead of '**** already set'). - nitpick: extend round-trip test to cover search_gitignored toggle. New regression test 'config-get masks secrets and never echoes plaintext' verifies the fix for all three secret keys. * docs(#2529): bump INVENTORY counts post-rebase (commands 84→85, workflows 82→83) * fix(test): bump CLI Modules count 27→28 after rebase onto main (CI #24811455435) PR #2604 was rebased onto main before #2605 (drift.cjs) merged. The pull_request CI runs against the merge ref (refs/pull/2604/merge), which now contains 28 .cjs files in get-shit-done/bin/lib/, but docs/INVENTORY.md headline still said "(27 shipped)". inventory-counts.test.cjs failed with: AssertionError: docs/INVENTORY.md "CLI Modules (27 shipped)" disagrees with get-shit-done/bin/lib/ file count (28) Rebased branch onto current origin/main (picks up drift.cjs row, which was already added by #2605) and bumped the headline to 28. Full suite: 5200/5200 pass. |
||
|
|
c90081176d |
fix(#2598): pass shell: true to npm spawnSync on Windows (#2600)
* fix(#2598): pass shell: true to npm spawnSync on Windows Since Node's CVE-2024-27980 fix (>= 18.20.2 / >= 20.12.2 / >= 21.7.3), spawnSync refuses to launch .cmd/.bat files on Windows without `shell: true`. installSdkIfNeeded picks npmCmd='npm.cmd' on win32 and then calls spawnSync five times — every one returns { status: null, error: EINVAL } before npm ever runs. The installer checks `status !== 0`, trips the failure path, and emits a bare "Failed to `npm install` in sdk/." with zero diagnostic output because `stdio: 'inherit'` never had a child to stream. Every fresh install on Windows has failed at the SDK build step on any supported Node version for the life of the post-CVE bin/install.js. Introduce a local `spawnNpm(args, opts)` helper inside installSdkIfNeeded that injects `shell: process.platform === 'win32'` when the caller doesn't override it. Route all five npm invocations through it: `npm install`, `npm run build`, `npm install -g .`, and both `npm config get prefix` calls. Adds a static regression test that parses installSdkIfNeeded and asserts no bare `spawnSync(npmCmd, ...)` remains, a shell-aware wrapper exists, and at least five invocations go through it. Closes #2598 * fix(#2598): surface spawnSync diagnostics in SDK install fatal paths Thread result.error / result.signal / result.status into emitSdkFatal for the three npm failure branches (install, run build, install -g .) via a formatSpawnFailure helper. The root cause of #2598 went silent precisely because `{ status: null, error: EINVAL }` was reduced to a generic "Failed to `npm install` in sdk/." with no diagnostic — stdio: 'inherit' had no child process to stream and result.error was swallowed. Any future regression in the same area (EINVAL, ENOENT, signal termination) now prints its real cause in the red fatal banner. Also strengthen the regression test so it cannot pass with only four real npm call sites: the previous `spawnSync(npmCmd, ..., shell)` regex double-counted the spawnNpm helper's own body when a helper existed. Separate arrow-form vs function-form helper detection and exclude the wrapper body from explicitShellNpm so the `>= 5` assertion reflects real invocations only. Add a new test that asserts all three fatal branches now reference formatSpawnFailure / result.error / signal / status. Addresses CodeRabbit review comments on PR #2600: - r3126987409 (bin/install.js): surface underlying spawnSync failure - r3126987419 (test): explicitShellNpm overcounts by one via helper def |
||
|
|
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> |
||
|
|
9c0a153a5f |
feat: /gsd-settings-advanced — power-user config tuning command (closes #2528) (#2603)
* feat: /gsd-settings-advanced — power-user config tuning command (closes #2528) Adds a second-tier interactive configuration command covering the power-user knobs that don't belong in the common-case /gsd-settings prompt. Six sectioned AskUserQuestion batches cover planning, execution, discussion, cross-AI, git, and runtime settings (19 config keys total). Current values are pre-selected; numeric fields reject non-numeric input; writes route through gsd-sdk query config-set so unrelated keys are preserved. - commands/gsd/settings-advanced.md — command entry - get-shit-done/workflows/settings-advanced.md — six-section workflow - get-shit-done/workflows/settings.md — advertise advanced command - get-shit-done/bin/lib/config-schema.cjs — add context_window to VALID_CONFIG_KEYS - docs/COMMANDS.md, docs/CONFIGURATION.md, docs/INVENTORY.md — docs + inventory - tests/gsd-settings-advanced.test.cjs — 81 tests (files, frontmatter, field coverage, pre-selection, merge-preserves-siblings, VALID_CONFIG_KEYS membership, confirmation table, /gsd-settings cross-link, negative scenarios) All 5073 tests pass; coverage 88.66% (>= 70% threshold). * docs(settings-advanced): clarify per-field numeric bounds and label fenced blocks Addresses CodeRabbit review on PR #2603: - Numeric-input rule now states min is field-specific: plan_bounce_passes and max_discuss_passes require >= 1; other numeric fields accept >= 0. Resolves the inconsistency between the global rule and the field-level prompts (CodeRabbit comment 3127136557). - Adds 'text' fence language to seven previously unlabeled code blocks in the workflow (six AskUserQuestion sections plus the confirmation banner) to satisfy markdownlint MD040 (CodeRabbit comment 3127136561). * test(settings-advanced): tighten section assertion, fix misleading test name, add executable numeric-input coverage Addresses CodeRabbit review on PR #2603: - Required section list now asserts the full 'Runtime / Output' heading rather than the looser 'Runtime' substring (comment 3127136564). - Renames the subagent_timeout coercion test to match the actual key under test (was titled 'context_window' but exercised workflow.subagent_timeout — comment 3127136573). - Adds two executable behavioral tests at the config-set boundary (comment 3127136579): * Non-numeric input on a numeric key currently lands as a string — locks in that the workflow's AskUserQuestion re-prompt loop is the layer responsible for type rejection. If a future change adds CLI-side numeric validation, the assertion flips and the test surfaces it. * Numeric string on workflow.max_discuss_passes is coerced to Number — locks in the parser invariant for a second numeric key. |
||
|
|
86c5863afb |
feat: add settings layers to /gsd-settings (Group A toggles) (closes #2527) (#2602)
* feat(#2527): add settings layers to /gsd:settings (Group A toggles) Expand /gsd:settings from 14 to 22 settings, grouped into six visual sections: Planning, Execution, Docs & Output, Features, Model & Pipeline, Misc. Adds 8 new toggles: workflow.pattern_mapper, workflow.tdd_mode, workflow.code_review, workflow.code_review_depth (conditional on code_review=on), workflow.ui_review, commit_docs, intel.enabled, graphify.enabled All 8 keys already existed in VALID_CONFIG_KEYS and docs/CONFIGURATION.md; this wires them into the interactive flow, update_config write step, ~/.gsd/defaults.json persistence, and confirmation table. Closes #2527 * test(#2527): tighten leaf-collision and rename mismatched negative test Addresses CodeRabbit findings on PR #2602: - comment 3127100796: leaf-only matching collapsed `intel.enabled` and `graphify.enabled` to a single `enabled` token, so one occurrence could satisfy both assertions. Replace with hasPathLike(), which requires each dotted segment to appear in order within a bounded window. Applied to both update_config and save_as_defaults blocks. - comment 3127100798: the negative-test description claimed to verify invalid `code_review_depth` value rejection but actually exercised an unknown key path. Split into two suites with accurate names: one asserts settings.md constrains the depth options, the other asserts config-set rejects an unknown key path. * docs(#2527): clarify resolved config path for /gsd-settings Addresses CodeRabbit comment 3127100790 on PR #2602: the original line implied a single `.planning/config.json` target, but settings updates route to `.planning/workstreams/<active>/config.json` when a workstream is active. Document both resolved paths so the merge target is unambiguous. |
||
|
|
b35fdd51f3 |
Revert "feat(#2473): ship refuses to open PR when HANDOFF.json declares in-pr…" (#2596)
This reverts commit
|
||
|
|
7212cfd4de |
feat(#2473): ship refuses to open PR when HANDOFF.json declares in-progress work (#2553)
* feat(#2473): ship refuses to open PR when HANDOFF.json declares in-progress work Add a preflight step to /gsd-ship that parses .planning/HANDOFF.json and refuses to run git push + gh pr create when any remaining_tasks[].status is not in the terminal set {done, cancelled, deferred_to_backend, wont_fix}. Refusal names each blocking task and lists four resolutions (finish, mark terminal, delete stale file, --force). Missing HANDOFF.json is a no-op so projects that do not use /gsd-pause-work see no behavior change. Also documents the terminal-statuses contract in references/artifact-types.md and adds tests/ship-handoff-preflight.test.cjs to lock in the contract. Closes #2473 * fix(#2473): capture node exit from $() so malformed HANDOFF.json hard-stops Command substitution BLOCKING=$(node -e "...") discards the inner process exit code, so a corrupted HANDOFF.json that fails JSON.parse would yield empty BLOCKING and fall through silently to push_branch — the opposite of what preflight is supposed to do. Capture node's exit into HANDOFF_EXIT via $? immediately after the assignment and branch on it. A non-zero exit is now a hard refusal with the parser error printed on the preceding stderr line. --force does not bypass this branch: if the file exists and can't be parsed, something is wrong and the user should fix it (option 3 in the refusal message — "Delete HANDOFF.json if it's stale" — still applies). Verified with a tmp-dir simulation: captured exit 2, hard-stop fires correctly on malformed JSON. Added a test case asserting the capture ($?) + branch (-ne 0) + parser exit (process.exit(2)) are all present, so a future refactor can't silently reintroduce the bug. Reported by @coderabbitai on PR #2553. |
||
|
|
2b5c35cdb1 |
test(#2519): add regression test for sdk tarball dist inclusion (#2586)
* test(#2519): add regression test verifying sdk/package.json has files + prepublishOnly Guards the sdk/package.json fix for #2519 (tarball shipped without dist/) so future edits can't silently drop either the `files` whitelist or the `prepublishOnly` build hook. Asserts: - `files` is a non-empty array - `files` includes "dist" (so compiled CLI ships in tarball) - `scripts.prepublishOnly` runs a build (npm run build / tsc) - `bin` target lives under dist/ (sanity tie-in) Closes #2519 * test(#2519): accept valid npm glob variants for dist in files matcher Addresses CodeRabbit nitpick: the previous equality check on 'dist' / 'dist/' / 'dist/**' would false-fail on other valid npm packaging forms like './dist', 'dist/**/*', or backslash-separated paths. Normalize each entry and use a regex that accepts all common dist path variants. |
||
|
|
73c1af5168 |
fix(#2543): replace legacy /gsd-<cmd> syntax with /gsd:<cmd> across all source files (#2595)
Commands are now installed as commands/gsd/<name>.md and invoked as /gsd:<name> in Claude Code. The old hyphen form /gsd-<name> was still hardcoded in hundreds of places across workflows, references, templates, lib modules, and command files — causing "Unknown command" errors whenever GSD suggested a command to the user. Replace all /gsd-<cmd> occurrences where <cmd> is a known command name (derived at runtime from commands/gsd/*.md) using a targeted Node.js script. Agent names, tool names (gsd-sdk, gsd-tools), directory names, and path fragments are not touched. Adds regression test tests/bug-2543-gsd-slash-namespace.test.cjs that enforces zero legacy occurrences going forward. Removes inverted tests/stale-colon-refs.test.cjs (bug #1748) which enforced the now-obsolete hyphen form; the new bug-2543 test supersedes it. Updates 5 assertion tests that hardcoded the old hyphen form to accept the new colon form. Closes #2543 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
533973700c |
feat(#2538): add last: /cmd suffix to statusline (opt-in) (#2594)
Adds a `statusline.show_last_command` config toggle (default: false) that appends ` │ last: /<cmd>` to the statusline, showing the most recently invoked slash command in the current session. The suffix is derived by tailing the active Claude Code transcript (provided as transcript_path in the hook input) and extracting the last <command-name> tag. Reads only the final 256 KiB to stay cheap per render. Graceful degradation: missing transcript, no recorded command, unreadable config, or parse errors all silently omit the suffix without breaking the statusline. Closes #2538 |
||
|
|
349daf7e6a |
fix(#2545): use word boundary in path replacement to catch ~/.claude without trailing slash (#2592)
The Copilot content converter only replaced `~/.claude/` and `$HOME/.claude/` when followed by a literal `/`. Bare references (e.g. `configDir = ~/.claude` at end of line) slipped through and triggered the post-install "Found N unreplaced .claude path reference(s)" warning, since the leak scanner uses `(?:~|$HOME)/\.claude\b`. Switched both replacements to a `(\/|\b)` capture group so trailing-slash and bare forms are handled in a single pass — matching the pattern already used by Antigravity, OpenCode, Kilo, and Codex converters. Closes #2545 |
||
|
|
6b7b5c15a5 |
fix(#2559): remove stale year injection from research agent web search instructions (#2591)
The gsd-phase-researcher and gsd-project-researcher agents instructed WebSearch queries to always include 'current year' (e.g., 2024). As time passes, a hardcoded year biases search results toward stale dated content — users saw 2024-tagged queries producing stale blog references in 2026. Remove the year-injection guidance. Instead, rely on checking publication dates on the returned sources. Query templates and success criteria updated accordingly. Closes #2559 |
||
|
|
67a9550720 |
fix(#2549,#2550,#2552): bound discuss-phase context reads, add phase-type map selection, prohibit split reads (#2590)
#2549: load_prior_context was reading every prior *-CONTEXT.md file, growing linearly with project phase count. Cap to the 3 most recent phases. If .planning/DECISIONS-INDEX.md exists, read that instead. #2550: scout_codebase claimed to select maps "based on phase type" but had no classifier — agents read all 7 maps. Replace with an explicit phase-type-to-maps table (2–3 maps per phase type) with a Mixed fallback. #2552: Add explicit instruction not to split-read the same file at two different offsets. Split reads break prompt cache reuse and cost more than a single full read. Closes #2549 Closes #2550 Closes #2552 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
fba040c72c |
fix(#2557): Gemini/Antigravity local hook commands use relative paths, not \$CLAUDE_PROJECT_DIR (#2589)
\$CLAUDE_PROJECT_DIR is Claude Code-specific. Gemini CLI doesn't set it, and on Windows its path-join logic doubled the value producing unresolvable paths like D:\Projects\GSD\'D:\Projects\GSD'. Gemini runs project hooks with project root as cwd, so bare relative paths (e.g. node .gemini/hooks/gsd-check-update.js) are cross-platform and correct. Claude Code and others still use the env var. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
0d6349a6c1 |
fix(#2554): preserve leading zero in getMilestonePhaseFilter (#2585)
The normalization `replace(/^0+/, '')` over-stripped decimal phase IDs: `"00.1"` collapsed to `".1"`, while the disk-side extractor yielded `"0.1"` from `"00.1-<slug>"`. Set membership failed and inserted decimal phases were silently excluded from every disk scan inside `buildStateFrontmatter`, causing `state update` to rewind progress counters. Strip leading zeros only when followed by a digit (`replace(/^0+(?=\d)/, '')`), preserving the zero before the decimal point while keeping existing behavior for zero-padded integer IDs. Closes #2554 |
||
|
|
c47a6a2164 |
fix: correct VALID_CONFIG_KEYS — remove internal state key, add missing public keys, migration hints (#2561)
* fix(#2530-2535): correct VALID_CONFIG_KEYS set — remove internal state key, add missing public keys, add migration hints - Remove workflow._auto_chain_active from VALID_CONFIG_KEYS (internal runtime state, not user-settable) (#2530) - Add hooks.workflow_guard to VALID_CONFIG_KEYS (read by gsd-workflow-guard.js hook, already documented) (#2531) - Add workflow.ui_review to VALID_CONFIG_KEYS (read in autonomous.md via config-get) (#2532) - Add workflow.max_discuss_passes to VALID_CONFIG_KEYS (read in discuss-phase.md via config-get) (#2533) - Add CONFIG_KEY_SUGGESTIONS entries for sub_repos → planning.sub_repos and plan_checker → workflow.plan_check (#2535) - Document workflow.ui_review and workflow.max_discuss_passes in docs/CONFIGURATION.md - Clear INTERNAL_KEYS exemption in parity test (workflow._auto_chain_active removed from schema entirely) - Add regression test file tests/bug-2530-valid-config-keys.test.cjs covering all 6 bugs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: align SDK VALID_CONFIG_KEYS with CJS — remove internal key, add missing public keys - Remove workflow._auto_chain_active from SDK (internal runtime state, not user-settable) - Add workflow.ui_review, workflow.max_discuss_passes, hooks.workflow_guard to SDK - Add ui_review and max_discuss_passes to Full Schema example in CONFIGURATION.md Resolves CodeRabbit review on #2561. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
af2dba2328 |
fix(hooks): detect Claude Code via stdin session_id (closes #2520) (#2521)
* fix(hooks): detect Claude Code via stdin session_id, not filtered env (#2520) The #2344 fix assumed `CLAUDECODE` would propagate to hook subprocesses. On Claude Code v2.1.116 it doesn't — Claude Code applies a separate env filter to PreToolUse hook commands that drops bare CLAUDECODE and CLAUDE_SESSION_ID, keeping only CLAUDE_CODE_*-prefixed vars plus CLAUDE_PROJECT_DIR. As a result every Edit/Write on an existing file produced a redundant READ-BEFORE-EDIT advisory inside Claude Code. Use `data.session_id` from the hook's stdin JSON as the primary Claude Code signal (it's part of Claude Code's documented PreToolUse hook-input schema). Keep CLAUDE_CODE_ENTRYPOINT / CLAUDE_CODE_SSE_PORT env checks as propagation-verified fallbacks, and keep the legacy CLAUDE_SESSION_ID / CLAUDECODE checks for back-compat and future-proofing. Add tests/bug-2520-read-guard-hook-subprocess-env.test.cjs, which spawns the hook with an env mirroring the actual Claude Code hook-subprocess filter. Extend the legacy test harnesses to also strip the propagation-verified CLAUDE_CODE_* vars so positive-path tests keep passing when the suite itself runs inside a Claude Code session (same class of leak as #2370 / PR #2375, now covering the new detection signals). Non-Claude-host behavior (OpenCode / MiniMax) is unchanged: with no `session_id` on stdin and no CLAUDE_CODE_* env var, the advisory still fires. Closes #2520 * test(2520): isolate session_id signal from env fallbacks in regression test Per reviewer feedback (Copilot + CodeRabbit on #2521): the session_id isolation test used the helper's default CLAUDE_CODE_ENTRYPOINT / CLAUDE_CODE_SSE_PORT values, so the env fallback would rescue the skip even if the primary `data.session_id` check regressed. Pass an explicit env override that clears those fallbacks, so only the stdin `session_id` signal can trigger the skip. Other cases (env-only fallback, negative / non-Claude host) already override env appropriately. --------- Co-authored-by: forfrossen <forfrossensvart@gmail.com> |
||
|
|
7397f580a5 |
fix(#2516): resolve executor_model inherit literal passthrough; add regression test (#2537)
When model_profile is "inherit", execute-phase was passing the literal string "inherit" to Task(model=), causing fallback to the default model. The workflow now documents that executor_model=="inherit" requires omitting the model= parameter entirely so Claude Code inherits the orchestrator model automatically. Closes #2516 |
||
|
|
9a67e350b3 |
fix(#2504): auto-pass UAT for infrastructure/foundation phases with no user-facing elements (#2541)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
98d92d7570 |
fix(#2526): warn about REQ-IDs in body missing from Traceability table (#2539)
Scan REQUIREMENTS.md body for all **REQ-ID** patterns during phase complete and emit a warning for any IDs absent from the Traceability table, regardless of whether the roadmap has a Requirements: line. Closes #2526 |
||
|
|
8eeaa20791 |
fix(install): chmod dist/cli.js 0o755 after npm install -g; add regression test (closes #2525) (#2536)
Use process.platform !== 'win32' guard in catch instead of a comment, and add regression test for bug #2525 (gsd-sdk bin symlink points at non-executable file). Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
f32ffc9fb8 |
fix(quick): include deferred-items.md in final commit file list (closes #2523) (#2542)
Step 8 file list omitted deferred-items.md, leaving executor out-of-scope findings untracked after final commit even with commit_docs: true. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
5676e2e4ef |
fix(sdk): forward --ws workstream flag through query dispatch (#2546)
* fix(sdk): forward --ws workstream flag through query dispatch (closes #2524) - cli.ts: pass args.ws as workstream to registry.dispatch() - registry.ts: add workstream? param to dispatch(), thread to handler - utils.ts: add optional workstream? to QueryHandler type signature - helpers.ts: planningPaths() accepts workstream? and uses relPlanningPath() - All ~26 query handlers updated to receive and pass workstream to planningPaths() - Config/commit/intel handlers use _workstream (project-global, not scoped) - Add failing-then-passing test: tests/bug-2524-sdk-query-ws-flag.test.cjs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(sdk): forward workstream to all downstream query helpers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): rewrite #2524 test as static source assertions — no sdk/dist build in CI Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
8789211038 |
fix(insert-phase): update STATE.md next-phase recommendation after phase insertion (#2509)
* fix(insert-phase): update STATE.md next-phase recommendation after inserting a phase Closes #2502 * fix(insert-phase): update all STATE.md pointers; tighten test scope Two follow-up fixes from CodeRabbit review of #2509: 1. The update_project_state instruction only said to find "the line" for the next-phase recommendation. STATE.md can have multiple pointers (structured current_phase: field AND prose recommendation text). Updated wording to explicitly require updating all of them in the same edit. 2. The regression test for the next-phase pointer update scanned the entire file, so a match anywhere would pass even if update_project_state itself was missing the instruction. Scoped the assertion to only the content inside <step name="update_project_state"> to prevent false positives. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
57bbfe652b |
fix: exclude non-wiped dirs from custom-file scan; warn on non-Claude model profiles (#2511)
* fix(detect-custom-files): exclude skills and command dirs not wiped by installer (closes #2505) GSD_MANAGED_DIRS included 'skills' and 'command' directories, but the installer never wipes those paths. Users with third-party skills installed (40+ files, none in GSD's manifest) had every skill flagged as a "custom file" requiring backup, producing noisy false-positive reports on every /gsd-update run. Removes 'skills' and 'command' from both gsd-tools.cjs and the SDK's detect-custom-files.ts. Adds two regression tests confirming neither directory is scanned. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(settings): warn that model profiles are no-ops on non-Claude runtimes (closes #2506) settings.md presented Quality/Balanced/Budget model profiles without any indication that these tiers map to Claude models (Opus/Sonnet/Haiku) and have no effect on non-Claude runtimes (Codex, Gemini CLI, OpenRouter). Users on Codex saw the profile chooser as if it would meaningfully select models, but all agents silently used the runtime default regardless. Adds a non-Claude runtime note before the profile question (shown in TEXT_MODE, the path all non-Claude runtimes take) explaining the profiles are no-ops and directing users to either choose Inherit or configure model_overrides manually. Also updates the Inherit option description to explicitly name the runtimes where it is the correct choice. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
a4764c5611 |
fix(execute-phase): resurrection-detection must check git history before deleting new .planning/ files (#2510)
The guard at the worktree-merge resurrection block was inverting the intended logic: it deleted any .planning/ file absent from PRE_MERGE_FILES, which includes brand-new files (e.g. SUMMARY.md just created by the executor). A genuine resurrection is a file that was previously tracked on main, deliberately removed, and then re-introduced by the merge. Detecting that requires a git history check — not just tree membership. Fix: replace the PRE_MERGE_FILES grep guard with a `git log --follow --diff-filter=D` check that only removes the file if it has a deletion event in main's ancestry. Closes #2501 |
||
|
|
b2534e8a05 |
feat(plan-phase): chunked mode + filesystem fallback for Windows stdio hang (#2499)
* feat(plan-phase): chunked mode + filesystem fallback for Windows stdio hang (#2310) Addresses the 2026-04-16 Windows incident where gsd-planner wrote all 5 PLAN.md files to disk but Task() never returned, hanging the orchestrator for 30+ minutes. Two mitigations: 1. Filesystem fallback (steps 9a, 11a): when Task() returns with an empty/truncated response but PLAN.md files exist on disk, surface a recoverable prompt (Accept plans / Retry planner / Stop) instead of silently failing. Directly addresses the post-restart recovery path. 2. Chunked mode (--chunked flag / workflow.plan_chunked config): splits the single long-lived planner Task into a short outline Task (~2 min) followed by N short per-plan Tasks (~3-5 min each). Each plan is committed individually for crash resilience. A hang loses one plan, not all of them. Resume detection skips plans already on disk on re-run. RCA confirmed: task state mtime 14:29 vs PLAN.md writes 14:32-14:52 = subagent completed normally, IPC return was dropped by Windows stdio deadlock. Neither mitigation fixes the root cause (requires upstream Task() timeout support); both bound damage and enable recovery. New reference file planner-chunked.md keeps OUTLINE COMPLETE / PLAN COMPLETE return formats out of gsd-planner.md (which sits at 46K near its size limit). Closes #2310 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(plan-phase): address CodeRabbit review comments on #2499 - docs/CONFIGURATION.md: add workflow.plan_chunked to full JSON schema example - plan-phase.md step 8.5.1: validate PLAN-OUTLINE.md with grep for OUTLINE COMPLETE marker before reusing (not just file existence) - plan-phase.md step 8.5.2: validate per-plan PLAN.md has YAML frontmatter (head -1 grep for ---) before skipping in resume path - plan-phase.md: add language tags (text/javascript/bash) to bare fenced code blocks in steps 8.5, 9a, 11a (markdownlint MD040) - Rejected: commit_docs gate on per-plan commits (gsd-sdk query commit already respects commit_docs internally — comment was a false positive) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(plan-phase): route Accept-plans through step 9 PLANNING COMPLETE handling Honors --skip-verify / plan_checker_enabled=false in 9a fallback path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
d1b56febcb |
fix(execute-phase): post-merge deletion audit for bulk file deletions (closes #2384) (#2483)
* fix(execute-phase): post-merge deletion audit for bulk file deletions (closes #2384) Two data-loss incidents were caused by worktree merges bringing in bulk file deletions silently. The pre-merge check (HEAD...WT_BRANCH) catches deletions on the worktree branch, but files deleted during the merge itself (e.g., from merge conflict resolution or stale branch state) were not audited post-merge. Adds a post-merge audit immediately after git merge --no-ff succeeds: - Counts files deleted outside .planning/ in the merge commit - If count > 5 and ALLOW_BULK_DELETE!=1: reverts the merge with git reset --hard HEAD~1 and continues to the next worktree - Logs the full file list and an escape-hatch instruction Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): tighten post-merge deletion audit assertions (CodeRabbit #2483) Replace loose substring checks with exact regex assertions: - assert.match against 'git diff --diff-filter=D --name-only HEAD~1 HEAD' - assert.match against threshold gate + ALLOW_BULK_DELETE override condition - assert.match against git reset --hard HEAD~1 revert - assert.match against MERGE_DEL_COUNT grep -vc for non-.planning count Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(inventory): update workflow count to 81 (graduation.md added in #2490) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
1657321eb0 |
fix(install): remove bare ~/.claude reference in update.md (closes #2470) (#2482)
* fix(install): remove bare ~/.claude reference in update.md (closes #2470) The installer's copyWithPathReplacement() replaces ~/\.claude\/ (with trailing slash) but not ~/\.claude (bare, no trailing slash). A comment on line 398 of update.md used the bare form, which scanForLeakedPaths() correctly flagged for every non-Claude runtime install. Replaced the example in the comment with a non-Claude runtime path so the file passes the scanner for all runtimes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): align regex with installer's word-boundary semantics (CodeRabbit #2482) Replace negative lookahead (?!\/) with \b word boundary to match the installer's scanForLeakedPaths() pattern. The lookahead would incorrectly flag ~/.claude_suffix whereas \b correctly excludes it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): revert \b regex — (?!\/) was intentionally scoped to bare refs The installer's scanForLeakedPaths uses \b but the test is specifically checking for bare ~/.claude without trailing slash that the replacer misses. ~/.claude/ (with slash) at line 359 of update.md is expected and handled. \b would flag it as a false positive. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(inventory): update workflow count to 81 (graduation.md added in #2490) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
2b494407e5 |
feat(assembly): add link mode for CLAUDE.md @-reference sections (#2484)
* feat(assembly): add link mode for CLAUDE.md @-reference sections (#2415) Adds `claude_md_assembly.mode: "link"` config option that writes `@.planning/<source>` instead of inlining content between GSD markers, reducing typical CLAUDE.md size by ~65%. Per-block overrides available via `claude_md_assembly.blocks.<section>`. Falls back to embed for sections without a real source file (workflow, fallbacks). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(test): add positive assertion for embedded workflow content (CodeRabbit #2484) The negative assertion only confirmed @GSD defaults wasn't written. Add assert.ok(content.includes('GSD Workflow Enforcement')) to verify the workflow section is actually embedded inline when link mode falls back. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
d0f4340807 |
feat(workflows): link pending todos to roadmap phases in new-milestone (#2433) (#2485)
Adds step 10.5 to gsd-new-milestone that scans pending todos against the approved roadmap and tags matches with `resolves_phase: N` in their YAML frontmatter. Adds a `close_phase_todos` step to execute-phase that moves tagged todos to `completed/` when the phase completes — closing the loop automatically with no manual cleanup. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
280eed93bc |
feat(cli): add /gsd-sync-skills for cross-runtime managed skill sync (#2491)
* fix(tests): update 5 source-text tests to read config-schema.cjs VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the drift-prevention companion PR. Tests that read config.cjs source text and checked for key literal includes() now point to the correct file. Closes #2480 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add /gsd-sync-skills for cross-runtime managed skill sync (#2380) Adds /gsd-sync-skills command so multi-runtime users can keep gsd-* skill directories aligned across runtime roots after updating one runtime with gsd-update. Changes: - bin/install.js: add --skills-root <runtime> flag that prints the skills root path for any supported runtime, reusing the existing getGlobalDir() table. Banner is suppressed when --skills-root is used (machine-readable output). - commands/gsd/sync-skills.md: slash command definition - get-shit-done/workflows/sync-skills.md: full workflow spec covering argument parsing, path resolution via --skills-root, diff computation (CREATE/UPDATE/ REMOVE/SKIP), dry-run report (default), apply execution, idempotency guarantee, and safety rules (only gsd-* touched, dry-run performs no writes). Safety rules: only gsd-* directories are ever created/updated/removed; non-GSD skills in destination roots are never touched; --dry-run is the default. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
b432d4a726 |
feat(workflows): close LEARNINGS.md consumption-and-graduation loop (#2490)
* fix(tests): update 5 source-text tests to read config-schema.cjs VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the drift-prevention companion PR. Tests that read config.cjs source text and checked for key literal includes() now point to the correct file. Closes #2480 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(workflows): close LEARNINGS.md consumption-and-graduation loop (#2430) Part A — Consumption: extend plan-phase.md cross-phase context load to include LEARNINGS.md files from the 3 most recent prior phases (same recency gate as CONTEXT.md + SUMMARY.md: CONTEXT_WINDOW >= 500000 only). Also loads LEARNINGS.md from any phases in the Depends-on chain. Silent skip if absent; 15% context budget cap with oldest-first truncation; [from Phase N LEARNINGS] attribution. Part B — Graduation: add graduation_scan step to transition.md (after evolve_project) that delegates to new graduation.md helper workflow. The helper clusters recurring items across the last N phases (default window=5, threshold=3) using Jaccard lexical similarity, surfaces HITL Promote/Defer/Dismiss prompts, routes promotions to PROJECT.md or PATTERNS.md by category, annotates graduated items with `graduated:` field, and persists dismissed/deferred clusters in STATE.md graduation_backlog. Always non-blocking; silently no-ops on first phase or when data is insufficient. Also: adds optional `graduated:` annotation docs to extract_learnings.md schema. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(graduation): address CodeRabbit review findings on PR #2490 - graduation.md: unify insufficient-data guard to silent-skip (remove contradictory [no-op] print path) - graduation.md: add TEXT_MODE fallback for HITL cluster prompts - graduation.md: add A (defer-all) to accepted actions [P/D/X/A] - graduation.md: tag untyped code fences with text language (MD040) - transition.md: tag untyped graduation.md fence with text language Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(graduation): rephrase TEXT_MODE line to avoid prompt-injection scanner false positive Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
cfe4dc76fd |
feat(health): canonical artifact registry and W019 unrecognized-file lint (#2448) (#2488)
Adds artifacts.cjs with canonical .planning/ root file names, W019 warning in gsd-health that flags unrecognized .md files at the .planning/ root, and templates/README.md as the authoritative artifact index for agents and humans. Closes #2448 |
||
|
|
f19d0327b2 |
feat(agents): sycophancy hardening for 9 audit-class agents (#2489)
* fix(tests): update 5 source-text tests to read config-schema.cjs VALID_CONFIG_KEYS moved from config.cjs to config-schema.cjs in the drift-prevention companion PR. Tests that read config.cjs source text and checked for key literal includes() now point to the correct file. Closes #2480 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(agents): sycophancy hardening for 9 audit-class agents (#2427) Add adversarial reviewer posture to gsd-plan-checker, gsd-code-reviewer, gsd-security-auditor, gsd-verifier, gsd-eval-auditor, gsd-nyquist-auditor, gsd-ui-auditor, gsd-integration-checker, and gsd-doc-verifier. Four changes per agent: - Third-person framing: <role> opens with submission framing, not "You are a GSD X" - FORCE stance: explicit starting hypothesis that the submission is flawed - Failure modes: agent-specific list of how each reviewer type goes soft - BLOCKER/WARNING classification: every finding must carry an explicit severity Also applies to sdk/prompts/agents variants of gsd-plan-checker and gsd-verifier. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
bd27d4fabe |
feat(roadmap): surface wave dependencies and cross-cutting constraints (#2487)
* feat(roadmap): surface wave dependencies and cross-cutting constraints (#2447) Adds roadmap.annotate-dependencies command that post-processes a phase's ROADMAP plan list to insert wave dependency notes and surface must_haves.truths entries shared across 2+ plans as cross-cutting constraints. Operation is idempotent and purely derived from existing PLAN frontmatter. Closes #2447 * fix(roadmap): address CodeRabbit review findings on PR #2487 - roadmap.cjs: expand idempotency guard to also check for existing cross-cutting constraints header, preventing duplicate injection on re-runs; add content equality check before writing to preserve true idempotency for single-wave phases - plan-phase.md: move ROADMAP annotation (13d) before docs commit (13c) so annotated ROADMAP.md is included in the commit rather than left dirty; include .planning/ROADMAP.md in committed files list - sdk/src/query/index.ts: add annotate-dependencies aliases to QUERY_MUTATION_COMMANDS so the mutation is properly event-wired - sdk/src/query/roadmap.ts: add timeout (15s) and maxBuffer to spawnSync; check result.error before result.status to handle spawn/timeout failures Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
e8ec42082d |
feat(health): detect MILESTONES.md drift from archived snapshots (#2446) (#2486)
Adds W018 warning when .planning/milestones/vX.Y-ROADMAP.md snapshots exist without a corresponding entry in MILESTONES.md. Introduces --backfill flag to synthesize missing entries from snapshot titles. Closes #2446 |
||
|
|
86fb9c85c3 |
docs(sdk): registry docs and gsd-sdk query call sites (#2302 Track B) (#2340)
* feat(sdk): golden parity harness and query handler CJS alignment (#2302 Track A) Golden/read-only parity tests and registry alignment, query handler fixes (check-completion, state-mutation, commit, validate, summary, etc.), and WAITING.json dual-write for .gsd/.planning readers. Refs gsd-build/get-shit-done#2341 * fix(sdk): getMilestoneInfo matches GSD ROADMAP (🟡, last bold, STATE fallback) - Recognize in-flight 🟡 milestone bullets like 🚧. - Derive from last **vX.Y Title** before ## Phases when emoji absent. - Fall back to STATE.md milestone when ROADMAP is missing; use last bare vX.Y in cleaned text instead of first (avoids v1.0 from shipped list). - Fixes init.execute-phase milestone_version and buildStateFrontmatter after state.begin-phase (syncStateFrontmatter). * feat(sdk): phase list, plan task structure, requirements extract handlers - Register phase.list-plans, phase.list-artifacts, plan.task-structure, requirements.extract-from-plans (SDK-only; golden-policy exceptions). - Add unit tests; document in QUERY-HANDLERS.md. - writeProfile: honor --output, render dimensions, return profile_path and dimensions_scored. * feat(sdk): centralize getGsdAgentsDir in query helpers Extract agent directory resolution to helpers (GSD_AGENTS_DIR, primary ~/.claude/agents, legacy path). Use from init and docs-init init bundles. docs(15): add 15-CONTEXT for autonomous phase-15 run. * feat(sdk): query CLI CJS fallback and session correlation - createRegistry(eventStream, sessionId) threads correlation into mutation events - gsd-sdk query falls back to gsd-tools.cjs when no native handler matches (disable with GSD_QUERY_FALLBACK=off); stderr bridge warnings - Export createRegistry from @gsd-build/sdk; add sdk/README.md - Update QUERY-HANDLERS.md and registry module docs for fallback + sessionId - Agents: prefer node dist/cli.js query over cat/grep for STATE and plans * fix(sdk): init phase_found parity, docs-init agents path, state field extract - Normalize findPhase not-found to null before roadmap fallback (matches findPhaseInternal) - docs-init: use detectRuntime + resolveAgentsDir for checkAgentsInstalled - state.cjs stateExtractField: horizontal whitespace only after colon (YAML progress guard) - Tests: commit_docs default true; config-get golden uses temp config; golden integration green Refs: #2302 * refactor(sdk): share SessionJsonlRecord in profile-extract-messages CodeRabbit nit: dedupe JSONL record shape for isGenuineUserMessage and streamExtractMessages. * fix(sdk): address CodeRabbit major threads (paths, gates, audit, verify) - Resolve @file: and CLI JSON indirection relative to projectDir; guard empty normalized query command - plan.task-structure + intel extract/patch-meta: resolvePathUnderProject containment - check.config-gates: safe string booleans; plan_checker alias precedence over plan_check default - state.validate/sync: phaseTokenMatches + comparePhaseNum ordering - verify.schema-drift: token match phase dirs; files_modified from parsed frontmatter - audit-open: has_scan_errors, unreadable rows, human report when scans fail - requirements PLANNED key PLAN for root PLAN.md; gsd-tools timeout note - ingest-docs: repo-root path containment; classifier output slug-hash Golden parity test strips has_scan_errors until CJS adds field. * fix: Resolve CodeRabbit security and quality findings - Secure intel.ts and cli.ts against path traversal - Catch and validate git add status in commit.ts - Expand roadmap milestone marker extraction - Fix parsing array-of-objects in frontmatter YAML - Fix unhandled config evaluations - Improve coverage test parity mapping * docs(sdk): registry docs and gsd-sdk query call sites (#2302 Track B) Update CHANGELOG, architecture and user guides, workflow call sites, and read-guard tests for gsd-sdk query; sync ARCHITECTURE.md command/workflow counts and directory-tree totals with the repo (80 commands, 77 workflows). Address CodeRabbit: fix markdown tables and emphasis; align CLI-TOOLS GSDTools and state.read docs with implementation; correct roadmap handler name in universal-anti-patterns; resolve settings workflow config path without relying on config_path from state.load. Refs gsd-build/get-shit-done#2340 * test: raise planner character extraction limit to 48K * fix(sdk): resolve build TS error and doc conflict markers |
||
|
|
c5b1445529 |
feat(sdk): golden parity harness and query handler CJS alignment (#2302 Track A) (#2341)
* feat(sdk): golden parity harness and query handler CJS alignment (#2302 Track A) Golden/read-only parity tests and registry alignment, query handler fixes (check-completion, state-mutation, commit, validate, summary, etc.), and WAITING.json dual-write for .gsd/.planning readers. Refs gsd-build/get-shit-done#2341 * fix(sdk): getMilestoneInfo matches GSD ROADMAP (🟡, last bold, STATE fallback) - Recognize in-flight 🟡 milestone bullets like 🚧. - Derive from last **vX.Y Title** before ## Phases when emoji absent. - Fall back to STATE.md milestone when ROADMAP is missing; use last bare vX.Y in cleaned text instead of first (avoids v1.0 from shipped list). - Fixes init.execute-phase milestone_version and buildStateFrontmatter after state.begin-phase (syncStateFrontmatter). * feat(sdk): phase list, plan task structure, requirements extract handlers - Register phase.list-plans, phase.list-artifacts, plan.task-structure, requirements.extract-from-plans (SDK-only; golden-policy exceptions). - Add unit tests; document in QUERY-HANDLERS.md. - writeProfile: honor --output, render dimensions, return profile_path and dimensions_scored. * feat(sdk): centralize getGsdAgentsDir in query helpers Extract agent directory resolution to helpers (GSD_AGENTS_DIR, primary ~/.claude/agents, legacy path). Use from init and docs-init init bundles. docs(15): add 15-CONTEXT for autonomous phase-15 run. * feat(sdk): query CLI CJS fallback and session correlation - createRegistry(eventStream, sessionId) threads correlation into mutation events - gsd-sdk query falls back to gsd-tools.cjs when no native handler matches (disable with GSD_QUERY_FALLBACK=off); stderr bridge warnings - Export createRegistry from @gsd-build/sdk; add sdk/README.md - Update QUERY-HANDLERS.md and registry module docs for fallback + sessionId - Agents: prefer node dist/cli.js query over cat/grep for STATE and plans * fix(sdk): init phase_found parity, docs-init agents path, state field extract - Normalize findPhase not-found to null before roadmap fallback (matches findPhaseInternal) - docs-init: use detectRuntime + resolveAgentsDir for checkAgentsInstalled - state.cjs stateExtractField: horizontal whitespace only after colon (YAML progress guard) - Tests: commit_docs default true; config-get golden uses temp config; golden integration green Refs: #2302 * refactor(sdk): share SessionJsonlRecord in profile-extract-messages CodeRabbit nit: dedupe JSONL record shape for isGenuineUserMessage and streamExtractMessages. * fix(sdk): address CodeRabbit major threads (paths, gates, audit, verify) - Resolve @file: and CLI JSON indirection relative to projectDir; guard empty normalized query command - plan.task-structure + intel extract/patch-meta: resolvePathUnderProject containment - check.config-gates: safe string booleans; plan_checker alias precedence over plan_check default - state.validate/sync: phaseTokenMatches + comparePhaseNum ordering - verify.schema-drift: token match phase dirs; files_modified from parsed frontmatter - audit-open: has_scan_errors, unreadable rows, human report when scans fail - requirements PLANNED key PLAN for root PLAN.md; gsd-tools timeout note - ingest-docs: repo-root path containment; classifier output slug-hash Golden parity test strips has_scan_errors until CJS adds field. * fix: Resolve CodeRabbit security and quality findings - Secure intel.ts and cli.ts against path traversal - Catch and validate git add status in commit.ts - Expand roadmap milestone marker extraction - Fix parsing array-of-objects in frontmatter YAML - Fix unhandled config evaluations - Improve coverage test parity mapping * test: raise planner character extraction limit to 48K * fix(sdk): resolve TS build error in docs-init passing config |
||
|
|
9d55d531a4 |
fix(#2432,#2424): pre-dispatch PLAN.md commit + reapply-patches baseline detection; docs(#2397): config schema drift (#2469)
- quick.md Step 5.6: commit PLAN.md to base branch before worktree executor spawn when USE_WORKTREES is active, preventing CC #36182 path-resolution drift that caused silent writes to main repo instead of worktree - reapply-patches.md Option A: replace first-add commit heuristic with pristine_hashes SHA-256 matching from backup-meta.json so baseline detection works correctly on multi-cycle repos; first-add fallback kept for older installers without pristine_hashes - CONFIGURATION.md: move security_enforcement/security_asvs_level/security_block_on to workflow.* (matches templates/config.json and workflow readers); rename context_profile → context (matches VALID_CONFIG_KEYS in config.cjs); add planning.sub_repos to schema example - universal-anti-patterns.md + context-budget.md: fix context_window_tokens → context_window (the actual key name in config.cjs) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
5f419c0238 |
fix(bugs): resolve issues #2388, #2431, #2396, #2376 (#2467)
#2388 (plan-phase silently renames feature branch): add explicit Git Branch Invariant section to plan-phase.md prohibiting branch creation/rename/switch during planning; phase slug changes are plan-level only and must not affect the git branch. #2431 (worktree teardown silently swallows errors): replace `git worktree remove --force 2>/dev/null || true` with a lock-aware block in quick.md and execute-phase.md that detects locked worktrees, attempts unlock+retry, and surfaces a user-visible recovery message when removal still fails. #2396 (hardcoded test commands bypass Makefile): add a three-tier test command resolver (project config → Makefile/Justfile → language sniff) in execute-phase.md, verify-phase.md, and audit-fix.md. Makefile with a `test:` target now takes priority over npm/cargo/go. #2376 (OpenCode @$HOME not mapped on Windows): add platform guard in bin/install.js so OpenCode on win32 uses the absolute path instead of `$HOME/...`, which OpenCode does not expand in @file references on Windows. Tests: 29 new assertions across 4 regression test files (all passing). Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
dfa1ecce99 |
fix(#2418,#2399,#2419,#2421): four workflow and installer bug fixes (#2462)
- #2418: convertClaudeToAntigravityContent now replaces bare ~/.claude and $HOME/.claude (no trailing slash) for both global and local installs, eliminating the "unreplaced .claude path reference" warnings in gsd-debugger.md and update.md during Antigravity installs. - #2399: plan-phase workflow gains step 13c that commits PLAN.md files and STATE.md via gsd-sdk query commit when commit_docs is true. Previously commit_docs:true was read but never acted on in plan-phase. - #2419: new-project.md and new-milestone.md now parse agents_installed and missing_agents from the init JSON and warn users clearly when GSD agents are not installed, rather than silently failing with "agent type not found" when trying to spawn gsd-project-researcher subagents. - #2421: gsd-planner.md gains a "Grep gate hygiene" rule immediately after the Nyquist Rule explaining the self-invalidating grep gate anti-pattern and providing comment-stripping alternatives (grep -v, ast-grep). Tests: 4 new test files (30 tests) all passing. Closes #2418 Closes #2399 Closes #2419 Closes #2421 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
4cd890b252 |
fix(phase): guard backlog dirs and YYYY-MM dates in integer phase removal (#2466)
* fix(phase): guard backlog dirs and YYYY-MM dates in integer phase removal Closes #2435 Closes #2434 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(phase): extend date-collision guard to hyphen-adjacent context The lookbehind `(?<!\d)` in renameIntegerPhases only excluded digit-prefixed matches; a YYYY-MM-DD date like 2026-05-14 has a hyphen before the month digits, which passed the original guard and caused date corruption when renumbering a phase whose zero-padded number matched the month. Replace with `(?<![0-9-])` lookbehind and `(?![0-9-])` lookahead to exclude both digit- and hyphen-adjacent contexts. Adds a regression test for the hyphen-adjacent case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
d117c1045a |
test: add --no-sdk to copilot-install E2E runners + static guard (#2461) (#2463)
Four execFileSync installer calls in copilot-install.test.cjs deleted
GSD_TEST_MODE but omitted --no-sdk, triggering the fatal installSdkIfNeeded()
path in test.yml CI where npm global bin is not on PATH.
Partial fix in
|
||
|
|
0ea443cbcf |
fix(install): chmod sdk dist/cli.js executable; fix context monitor over-reporting (#2460)
Bug #2453: After tsc builds sdk/dist/cli.js, npm install -g from a local directory does not chmod the bin-script target (unlike tarball extraction). The file lands at mode 644, the gsd-sdk symlink points at a non-executable file, and command -v gsd-sdk fails on every first install. Fix: explicitly chmodSync(cliPath, 0o755) immediately after npm install -g completes, mirroring the pattern used for hook files throughout the installer. Bug #2451: gsd-context-monitor warning messages over-reported usage by ~13 percentage points vs CC native /context. Root cause: gsd-statusline.js wrote a buffer-normalized used_pct (accounting for the 16.5% autocompact reserve) to the bridge file, inflating values. The bridge used_pct is now raw (Math.round(100 - remaining_percentage)), consistent with what CC's native /context command reports. The statusline progress bar continues to display the normalized value; only the bridge value changes. Updated the existing #2219 tests to check the normalized display via hook stdout rather than bridge.used_pct, and added a new assertion that bridge.used_pct is raw. Closes #2453 Closes #2451 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |