Commit Graph

268 Commits

Author SHA1 Message Date
Ben Lamm
c8239f67f8 fix(#2641): inject normalized ## heading from <details><summary> capture
Address CodeRabbit review on PR #3046: the prior commit returned only the
body inside <details>...</details>, which fixed the `roadmapGetPhase`
miss but left `roadmapAnalyze`'s downstream `data.milestones` scan
(`/##\s*(.*v(\d+(?:\.\d+)+)[^(\n]*)/gi` at the bottom of roadmap.ts)
without an active-milestone anchor in the returned slice.

Now capture the <summary> text and prepend it as a synthesized `##`
heading on the returned slice. This makes both `data.phases` (the
original bug) AND `data.milestones` (the downstream consumer) surface
the active milestone correctly for <details>-wrapped ROADMAPs.

Also widened the inner tag to `<summary\b[^>]*>` for symmetry with the
outer `<details\b[^>]*>` — both now tolerate attributes.

Verified end-to-end against FAMP's v0.9 ROADMAP:
- Before this commit (after PR #3046 base):
    milestones: [{heading: '# Phase 1: ... (v0.5.2 atomic bump)', version: 'v0.5.2'}]
- After this commit:
    milestones: [{heading: 'v0.9 Local-First Bus', version: 'v0.9'},
                 {heading: '# Phase 1: ... (v0.5.2 ...)', version: 'v0.5.2'}]

(The v0.5.2 entry is pre-existing noise from the loose `##\s*` regex
matching the `### Phase 1: famp-bus (v0.5.2 atomic bump)` body heading;
unrelated to this fix and out of scope for this PR.)

Tests:
- Updated the two `<details><summary>` tests to assert the synthesized
  `## v0.9 Local-First Bus` heading is present on the returned slice.
- Added a 4th regression test (`roadmapAnalyze`) confirming
  `data.milestones` now contains the active milestone for
  <details>-wrapped ROADMAPs.
- All 40 roadmap.test.ts tests pass.
2026-05-06 15:41:27 -04:00
Ben Lamm
ba6a3efc3e fix(#2641): strip YAML quotes from STATE.md milestone version
Address CodeRabbit review on PR #3046: extractCurrentMilestone read the
`milestone:` value from STATE.md frontmatter via `.trim()` only, while
parseMilestoneFromState() and getMilestoneInfo() both also strip
surrounding YAML quotes via `.replace(/^["']|["']$/g, '')`.

For projects whose STATE.md uses quoted YAML (`milestone: "v0.9"`),
`version` carried literal quotes, `escapedVersion` became `\"v0\.9\"`,
and neither the markdown-heading regex nor the new <details><summary>
fallback could match anything — falling through to
stripShippedMilestones() and reintroducing the same archived-milestone
misrouting this PR addresses.

Strip quotes for parity. Three-line addition + one new test.
All 41 roadmap.test.ts tests pass.
2026-05-06 15:41:27 -04:00
Ben Lamm
592b676414 fix(#2641): recognize <details><summary> as active-milestone anchor
`extractCurrentMilestone` only matched markdown headings (## v0.9, ### v0.9)
to find the active milestone slice. Projects that wrap their active
milestone's phase details inside `<details><summary>vX.Y …</summary>`
(a common GitHub-friendly collapse pattern, e.g. FAMP) fell through to
`stripShippedMilestones`, which strips ALL `<details>` blocks indiscriminately.

Net effect: `roadmapGetPhase` returned `{found:false}` for phases that ARE in
the active ROADMAP. The `init.phase-op` safety guard at `init.ts:133`
('drop archived disk match when phase is in current ROADMAP') depends on
`roadmapPhase.found`, so it didn't fire. `init.phase-op` then returned a
`phase_dir` pointing at an ARCHIVED milestone's same-numbered phase —
silently routing downstream workflows (e.g. /gsd-discuss-phase) into
completed phases.

Fix: when no markdown heading matches the active version, try matching
`<details\b[^>]*><summary>...vX.Y...</summary>`. Returns the inner content
of the matching block. Purely additive — `stripShippedMilestones` behavior
and its tests are unchanged.

The `\b[^>]*>` form tolerates attributes like `<details open>` or
`<details class="...">` (GitHub commonly emits `<details open>` for
default-expanded sections). Lazy `[\s\S]*?` matches up to the first
`</details>`; nested `<details>` inside the active milestone are not
expected and would mis-anchor (acceptable; falls through to the existing
`stripShippedMilestones` path with no regression vs. today's behavior).

Closes #2641. Distinct from the closed #2642 which bundled three orthogonal
changes (parser fix + checkbox-scan fix + STATE.md counting auth) into one
PR; this PR addresses only the parser anchoring bug, leaving
`stripShippedMilestones`, `roadmapAnalyze`, and `initMilestoneOp` untouched.

Tests added (3, all in `roadmap.test.ts`):
- `bug-2641: finds active milestone wrapped in <details><summary>vX.Y …</summary>`
- `bug-2641: finds active milestone in <details open><summary>vX.Y …</summary>`
- `bug-2641: returns found:true for phase inside <details>-wrapped active milestone` (end-to-end via `roadmapGetPhase`)

All existing `roadmap.test.ts` tests pass (39/39). Real-world repro
verified against an FAMP-style ROADMAP: before the fix,
`gsd-sdk query roadmap.get-phase 3` returned `{found:false}` despite the
phase being at line 113 of the active ROADMAP; after the fix, it returns
the correct phase metadata, and `init.phase-op 3` no longer returns the
v0.8 archived `phase_dir`.
2026-05-06 15:41:27 -04:00
Tom Boucher
a1a81eec90 fix(config): align SDK runtime-state key validation with CJS 2026-05-06 15:19:34 -04:00
Tom Boucher
96ce608ee6 fix(config): add resolve_model_ids to VALID_CONFIG_KEYS; accept workflow._auto_chain_active via RUNTIME_STATE_KEYS
Fixes #3162

`resolve_model_ids` is a documented top-level config key (CONFIGURATION.md)
read by core.cjs and session-runner.ts, but was missing from the CJS and SDK
VALID_CONFIG_KEYS allowlists — causing config-set to reject it with
"Unknown config key".

`workflow._auto_chain_active` is internal runtime state intentionally excluded
from VALID_CONFIG_KEYS by #2530, but plan-phase, execute-phase, discuss-phase,
transition, and new-project workflows all write it via `config-set`. Without
a valid write path these calls emit spurious errors (silenced with `|| true`
but noisy in logs). A new RUNTIME_STATE_KEYS set in config-schema.cjs holds
keys that isValidConfigKey() accepts without exposing them as user-settable
options — preserving the #2530 intent while fixing the runtime error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 14:56:34 -04:00
Tom Boucher
3785c09307 fix(sdk): include hotpath fallback reason in bridge observability 2026-05-05 20:29:43 -04:00
Tom Boucher
fe16143e29 fix(sdk): align hotpath observability with actual dispatch mode 2026-05-05 20:22:03 -04:00
Tom Boucher
8ad2e3877f fix(sdk): address CodeRabbit runtime bridge and docs findings 2026-05-05 19:59:56 -04:00
Tom Boucher
51b809e8e9 feat(sdk): expose runtime bridge controls via GSD options 2026-05-05 19:36:47 -04:00
Tom Boucher
00ba404b60 test(sdk): enforce runtime bridge seam and explicit no-fallback behavior 2026-05-05 19:31:03 -04:00
Tom Boucher
54b06e653e docs(sdk): document runtime bridge seam, strict mode, and fallback policy 2026-05-05 19:29:59 -04:00
Tom Boucher
1bd11ab699 feat(sdk): emit runtime bridge dispatch observability events 2026-05-05 19:26:01 -04:00
Tom Boucher
0026065c7a feat(sdk): add strict mode and explicit fallback policy to runtime bridge 2026-05-05 19:23:39 -04:00
Tom Boucher
98dd9e4afb refactor(sdk): add runtime bridge seam for query dispatch 2026-05-05 19:21:31 -04:00
Tom Boucher
9811782e6d fix(#3121): implement commands verb in SDK native registry (#3146)
- Add commandsList handler — returns sorted JSON array of all registered
  verb strings; satisfies workstream-flag.md + agent tooling discoverability
- Register ['commands', commandsList] in DECISION_ROUTING_STATIC_CATALOG
- Add golden-policy exemption (SDK-only, no CJS mirror needed)
- check.decision-coverage-plan/verify were already registered; commands was the remaining gap

Closes #3121
2026-05-05 15:02:34 -04:00
Nicholas Ferrer
85ef9553d2 fix(commit): scope every commit call to its staged pathspec
The commit handler ran `git add <paths>` followed by `git commit`
without a pathspec, so anything pre-staged externally before the
handler ran was swept into the commit. #2767 fixed every call site
to use --files but left the handler emitting a pathspec-less commit,
so the bug survived the well-formed form too.

Compute pathsToCommit once and pass `'--', ...pathsToCommit` to every
git commit invocation: regular, --amend, and commit-to-subrepo. The
staged-files check uses the same pathspec so "nothing staged" reflects
what would actually be committed, not unrelated index entries.

Two follow-up safeguards on the same surface:

* When `--files` is passed but every following token gets filtered out
  (e.g. `--files --no-verify`), reject with `--files requires at least
  one path` instead of silently falling back to .planning/.
* Both `git add` invocations now use the `--` separator so a path
  starting with `-` (e.g. a file literally named `-A.md`) is treated
  as a pathspec rather than a git option.

Adds five regression tests in `commit.test.ts`: three covering the
pathspec scope (`--files`, `.planning/` fallback, and `--amend` with
pre-staged unrelated changes), one covering the empty `--files`
rejection, and one covering the `-A.md` round-trip.

Closes #3061
2026-05-05 15:30:05 -03:00
Patrick Clery
f9c1f01971 fix: extend fix-slash-commands SEARCH_DIRS to agents/, sdk/src/, .clinerules
scripts/fix-slash-commands.cjs SEARCH_DIRS did not cover agents/, sdk/src/,
or top-level files, so 9 colon-form references survived in 6 files. The hit
at agents/gsd-codebase-mapper.md:105 propagated into ~/.claude/agents/ at
install time (the fixer is not wired into install) and produced unrunnable
/gsd:<cmd> suggestions in agent output on non-Gemini runtimes.

This commit includes Pass 1 (the 9 line edits) AND Pass 2 (extending the
fixer's SEARCH_DIRS so future regressions are auto-rewritten and caught by
the bug-2543 guard, which mirrors that list). The standalone bug-3100 test
added in the prior revision is removed in favor of the bug-2543 guard's
extended scan, per CONTRIBUTING.md test standards (no source-grep tests on
non-.md files).

Refs #3100
2026-05-05 13:19:10 -04:00
Tom Boucher
aa64638176 Merge pull request #3112 from gsd-build/fix/3101-plan-summary-matcher-in-core-cjs-reports
fix: canonicalize plan-summary matching for suffixless summaries
2026-05-04 23:35:34 -04:00
Tom Boucher
e7ecd46bbe Merge pull request #3115 from gsd-build/fix/3053-sdk-ignores-multi-plan-phase-layout-plan
fix: count nested plans/ layout in phase status indexing
2026-05-04 23:35:26 -04:00
Tom Boucher
083e813aea Merge pull request #3116 from gsd-build/fix/3055-bug-top-level-branching-strategy-in-plan
fix: normalize legacy top-level branching_strategy into git config
2026-05-04 23:33:28 -04:00
Tom Boucher
f01f6b76dd Merge pull request #3122 from gsd-build/fix/3088-gsd-complete-milestone-leaves-state-md-n
fix: normalize stale STATE narrative tails on milestone completion
2026-05-04 23:31:06 -04:00
Tom Boucher
67684626d8 fix(3088): append missing STATE narrative sections on milestone close 2026-05-04 23:29:45 -04:00
coderabbitai[bot]
2d25c97706 fix: apply CodeRabbit auto-fixes
Fixed 1 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
2026-05-05 03:17:22 +00:00
Tom Boucher
2dcf374da0 fix(milestone): normalize STATE narrative after milestone completion 2026-05-04 23:17:00 -04:00
Tom Boucher
58062a64a0 fix(sdk-config): honor legacy top-level branching_strategy in init 2026-05-04 23:06:54 -04:00
Tom Boucher
65024683fd fix(init): count plans/ summaries from nested plans/ layout 2026-05-04 23:03:10 -04:00
Tom Boucher
c7886415c3 fix(phase): canonicalize plan-summary matching for suffixless summaries 2026-05-04 22:51:15 -04:00
Tom Boucher
40acf1f02e fix: address CodeRabbit findings on query/transport error handling 2026-05-04 21:49:41 -04:00
Tom Boucher
38718e9d4b fix: avoid unsafe Promise cast in execRaw 2026-05-04 21:49:40 -04:00
Tom Boucher
0500bdf619 refactor: deepen query architecture seams with compatibility shims 2026-05-04 21:49:40 -04:00
Tom Boucher
c6a35d6398 refactor: deepen transport policy and output projection paths 2026-05-04 21:49:40 -04:00
Tom Boucher
969cfcf998 refactor: split native hotpath fallback and dispatch branches 2026-05-04 21:49:40 -04:00
Tom Boucher
e0c791a5d0 refactor: centralize native dispatch data projection 2026-05-04 21:49:40 -04:00
Tom Boucher
deb4477375 refactor: remove thin runtime and tools error wrappers 2026-05-04 21:49:40 -04:00
Tom Boucher
5aaf0dbea5 refactor: reduce query error factory public surface 2026-05-04 21:49:40 -04:00
Tom Boucher
ace241d0c2 refactor: fold query error seam types into factory module 2026-05-04 21:49:40 -04:00
Tom Boucher
0fffc7c055 refactor: centralize gsd-tools error wrapping path 2026-05-04 21:49:40 -04:00
Tom Boucher
6059a574f2 refactor: remove redundant native dispatch cast in runtime 2026-05-04 21:49:40 -04:00
Tom Boucher
b0e616288b refactor: isolate native dispatch error projection 2026-05-04 21:49:40 -04:00
Tom Boucher
ed9d67c91b refactor: deepen subprocess adapter with shared execution error path 2026-05-04 21:49:40 -04:00
Tom Boucher
97019d274e refactor: keep classification constructors internal to GSDToolsError 2026-05-04 21:49:40 -04:00
Tom Boucher
7311e0a9ab refactor: extract query error seam factory builders 2026-05-04 21:49:39 -04:00
Tom Boucher
c66ff96de8 test: use typed GSDToolsError constructors in cli output tests 2026-05-04 21:49:39 -04:00
Tom Boucher
a24de43f8b test: consolidate tools error mapping coverage in factory tests 2026-05-04 21:49:39 -04:00
Tom Boucher
70faa0ff0f refactor: remove query tools error mapper wrapper 2026-05-04 21:49:39 -04:00
Tom Boucher
b9e3979fc1 refactor: introduce explicit query error seam contracts 2026-05-04 21:49:39 -04:00
Tom Boucher
c7d3f83b8b refactor: reduce failure-classification API surface 2026-05-04 21:49:39 -04:00
Tom Boucher
bc289fad4a refactor: type native adapter error seam to GSDToolsError 2026-05-04 21:49:39 -04:00
Tom Boucher
9bee4dce4a test: adopt typed GSDToolsError constructors across failure tests 2026-05-04 21:49:39 -04:00
Tom Boucher
9a469fa05c refactor: centralize query tools error construction in factory 2026-05-04 21:49:39 -04:00