3eec3345334dacbbb0a13d65591f31b30ba7041f
15 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3eec334533 |
fix(3816): handle milestone-scoped phase dirs in roadmap parser, phase.add, init queries (#80)
* fix(#3816): handle milestone-scoped phase dirs in roadmap parser, phase.add, findPhase - phase.ts: replace hardcoded /^v[\d.]+-phases$/ regex with sortedMilestoneArchiveDirs() helper that matches any *-phases suffix and sorts the current-milestone dir first - roadmap.ts: add fallback for plain-bullet phases (- [ ] Phase N:) in searchPhaseInContent and roadmapAnalyze; truncate content at ## Backlog boundary in roadmapAnalyze to prevent backlog phases from leaking into the active-milestone phase list - phase-lifecycle.ts: add resolveWritePhasesDir() and findPhaseInsertionPoint() helpers; wire both into phaseAdd and phaseAddBatch so new phase dirs land in the milestone-scoped path and roadmap entries are inserted before ## Backlog rather than after the last --- Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(3816): sort milestone archives by version, not lexically `sortedMilestoneArchiveDirs` was sorting in descending order (b before a), causing v1.10-phases to be searched before v1.2-phases. Flip to ascending so the earliest archive is searched first, matching the deterministic sort the test at milestone-archive.test.cjs:383 asserts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
15e9c86ead |
fix(sdk): extractCurrentMilestone preserves generic Phase Details heading (#3493)
When a roadmap places shared phase-detail bodies under a non-version-prefixed `## Phase Details` heading AFTER a `### 📋 vX.Y+ (Planned)` sibling in document order, the entire Phase Details section fell outside the slice returned by `extractCurrentMilestone`. `gsd-sdk query phase.insert N` then reported "Phase N not found in ROADMAP.md" even though `### Phase N:` was unambiguously present. PR #2455 (closing #2422) added a same-version `continue` branch that already handles the version-prefixed variant (e.g. `## v2.0 Phase Details`). This fix extends the same intent to the generic-label variant: after the initial boundary scan, look for a literal `^#{1,3}\s+Phase\s+Details\b` heading past `sectionEnd` and, if found, append the Phase Details block (up to the next real milestone boundary — version-bearing or milestone-emoji-bearing heading — or EOF) to the returned slice. The intervening planned-milestone content is skipped so it does not leak into the active-milestone view. Bounded to a single append so a malformed roadmap can't loop. Only matches the literal `Phase Details` label (canonical per GSD ROADMAP template); anything else continues to terminate the slice. Does not regress the v2.0/v2.1+ version-prefixed handling shipped by #2455 (existing `bug-2422` test still passes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
ca148036d2 | fix(roadmap): prevent milestone version substring matches | ||
|
|
13bf56477a |
fix(#2641): symmetric attribute tolerance in stripShippedMilestones + lockdown tests
Address CodeRabbit follow-up review on PR #3046. One real bug + two lockdown gaps + one defensive assertion. REAL BUG — sibling-asymmetry in <details> attribute tolerance: extractCurrentMilestone's <details>-aware fallback uses <details\b[^>]*> to tolerate attributes (#2641 hardening commit). stripShippedMilestones still used literal <details>, so shipped content wrapped in `<details open>` (or any attributed tag) leaked through the strip. This is the failure mode trek-e's review almost caught with the "<details open>" / extended-attribute test gap I deferred — CodeRabbit caught the deeper issue: it's not just a test gap, it's an actual asymmetry between the two functions that handle <details> blocks. Fix: align stripShippedMilestones's regex with extractCurrentMilestone's <details\b[^>]*> form. Comment explicitly notes the symmetry contract so a future change to either function flags the other. Tests added in stripShippedMilestones describe block: - removes <details open> blocks - removes <details class="..." data-..."> blocks LOCKDOWN — leading-# strip in synthesized heading: My existing inline-HTML test exercised tag-stripping but didn't directly exercise the leading-# strip path (`.replace(/^#+\s*/, '')`). Added a dedicated test with `<summary># v0.9 Hash-Prefixed</summary>` so a future refactor that drops the strip would fail loudly instead of producing `## # v0.9 …` (which downstream `#{2,4}` regex parses as a 4-hash header). DEFENSIVE — toBeDefined guard in roadmapAnalyze regression test: Added `expect(data.milestones).toBeDefined()` before casting and calling `.some()`. Failure now reports "expected undefined to be defined" instead of TypeError. META: my prior adversarial pass missed the sibling-asymmetry because the checklist's "sibling consistency" item only audited PARSERS for the same INPUT field (STATE.md's `milestone:`), not ADJACENT FUNCTIONS that process the same DATA SHAPE (<details> blocks). The latter is a wider audit — every adjacent function that touches the data shape my new code relies on. Will refine the learned rule. Verification: 51/51 roadmap.test.ts pass (was 48; +3 tests). FAMP smoke unchanged: roadmap.get-phase 3 returns active milestone phase. |
||
|
|
19041b8824 |
test(#2641): lockdown tests from self-adversarial pass
Self-run adversarial pass on PR #3046 before next reviewer round-trip. Three lockdown tests added — none uncovered new bugs, all lock current behavior so a future change doesn't silently flip a convention. 1. Single-quote YAML version (`milestone: 'v0.9'`) Parity with the existing double-quote test. The strip pattern `/^["']|["']$/g` handles both — locked here so a future change to either character class doesn't silently regress one form. 2. Heading-anchor wins over <details> fallback (precedence lock) When a ROADMAP has BOTH `### v0.9` heading AND `<details><summary>v0.9</summary>` block, the heading-level lookup matches first and the fallback never fires. Test asserts the heading slice is returned starting at offset 0 AND the synthesized `## v0.9 ... details-anchored` heading is NOT prepended (proves fallback didn't run). Also documented in-test that the heading-anchor slice naturally includes downstream <details> blocks verbatim — a property of the heading path, not of this PR's fallback. 3. Multiple <details> blocks for same version → first match wins `content.match(detailsPattern)` (non-`g`) returns first match in document order. Locked so a future change to the matcher (e.g. switching to `matchAll` and picking last) doesn't silently change which block is treated as active. Adversarial-checklist coverage on commit 781cc6f8: - Boundary cases: empty / whitespace / single-char / single-quote / double-quote / digit-suffix (`v0.91`) / dot-suffix (`v0.9.0`) / hyphen-suffix (`v0.9-rc.1`, intentional same-milestone match per existing currentVersionStr convention) — all covered. - Sibling consistency: parseMilestoneFromState, getMilestoneInfo, extractCurrentMilestone all strip quotes identically. - Comment-vs-behavior: walked nested-guard, empty-guard, lookahead, tag-strip by hand against the regex; all comments accurate. - Downstream consumers: roadmapAnalyze + roadmapGetPhase both verified end-to-end via tests + FAMP smoke. - Failure-mode locality: all fall-through paths produce loud failures (empty arrays, `{found:false}`); no silent confident-wrong outputs. 48/48 roadmap.test.ts tests pass. |
||
|
|
4b66ca5800 |
fix(#2641): harden <details> fallback per trek-e review
Address trek-e's adversarial review on PR #3046. Two critical merge-blockers plus four hardening items, all now covered with tests. CRITICAL #1 — substring-version trap: `[^<]*${escapedVersion}[^<]*` did substring containment, so `milestone: v0.1` matched <summary>v0.10 …</summary> and returned the v0.10 block's body as the active milestone — confidently-wrong content worse than the pre-PR fall-through. Add `(?![\d.])` non-version-character lookahead, mirroring the same boundary protection used by the existing `currentVersionStr` logic on the heading path. Test asserts v0.1 active with v0.10 sibling block returns v0.1's phases, not v0.10's. CRITICAL #2 — nested <details> silent truncation: The lazy `[\s\S]*?</details>` terminates on the FIRST </details>, which is the inner closer when nesting is present. Prior comment claimed "would mis-anchor (acceptable; falls through)" — factually wrong: the match succeeds with truncated body and is returned with a confident `## ${summary}` heading. Future maintainer investigating a "missing phase" report would be misled. Add `!detailsMatch[2].includes('<details')` guard so nesting falls through to stripShippedMilestones (loud failure) instead of returning truncated content (silent failure). Test locks the contract: no synthesized v0.9 heading anchored to truncated body. HARDENING: - Empty-body guard: `<details><summary>v0.9</summary></details>` would synthesize `## v0.9\n` (phantom milestone, zero phases, no error signal). Treat as no-match. - Inline-HTML in <summary>: rejected by `[^<]*` capture. Widen to `(?:(?!</summary>).)*?` (non-greedy until close tag) and strip tags + leading `#` from the captured summary before promoting to a `##` heading. Covers GitHub-rendered <em>(active)</em>, <code>v0.9</code>, <strong>...</strong> patterns. - JSDoc: rewrote to describe both anchoring strategies and the synthesized-heading contract; demoted stale "Port of core.cjs lines 1102-1170" to historical context with the divergence list. - Comment block: rewrote in contract style ("any consumer scanning /##\s*.*vX.Y/ sees the active milestone") instead of coupling to specific call sites (roadmapAnalyze, "later in this file"). Adds explicit regex anatomy + hardening-guards section so future readers can audit each guard. OUT OF SCOPE (per trek-e's "Recommended action" tier): - Debug logging on fall-through paths (Suggestion #10) — adds tracing surface to a function that doesn't currently use logger; appropriate for a follow-up if/when other extraction bugs surface. - Uppercase <DETAILS>/<SUMMARY> + extended attribute coverage (Test gap #7 last two rows) — already covered by the documented `i` flag and the existing <details open> test; adding redundant cases inflates the test set without locking new contracts. Verification: 45/45 roadmap.test.ts tests pass (was 41/41; added 4 hardening tests). FAMP end-to-end smoke unchanged: roadmap.get-phase 3 returns "Claude Code integration polish", roadmap.analyze surfaces v0.9 Local-First Bus in data.milestones with phase_count: 4. |
||
|
|
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. |
||
|
|
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. |
||
|
|
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`.
|
||
|
|
74da61fb4a |
fix(#2619): prevent extractCurrentMilestone from truncating on phase-vX.Y headings (#2624)
* fix(#2619): prevent extractCurrentMilestone from truncating on phase-vX.Y headings extractCurrentMilestone sliced ROADMAP.md to the current milestone by looking for the next milestone heading with a greedy regex: ^#{1,N}\s+(?:.*v\d+\.\d+|✅|📋|🚧) Any heading that mentioned a version literal matched — including phase headings like "### Phase 12: v1.0 Tech-Debt Closure". When the current milestone was at the same heading level as the phases (### 🚧 v1.1 …), the slice terminated at the first such phase, hiding every phase that followed from phase.insert, validate.health W007, and other SDK commands. Fix: add a `(?!Phase\s+\S)` negative lookahead so phase headings can never be treated as milestone boundaries. Phase headings always start with the literal `Phase `, so this is a clean exclusion. Applied to: - get-shit-done/bin/lib/core.cjs (extractCurrentMilestone) - sdk/src/query/roadmap.ts (extractCurrentMilestone + extractNextMilestoneSection) Regression tests: - tests/roadmap-phase-fallback.test.cjs: extractCurrentMilestone does not truncate on phase heading containing vX.Y (#2619) - sdk/src/query/roadmap.test.ts: extractCurrentMilestone bug-2619: does not truncate at a phase heading containing vX.Y Closes #2619 * fix(#2619): make milestone-boundary Phase lookahead case-insensitive CodeRabbit follow-up on #2619: the negative lookahead `(?!Phase\s+\S)` in the SDK milestone-boundary regex was case-sensitive, so headings like `### PHASE 12: v1.0 Tech-Debt` or `### phase 12: …` still truncated the milestone slice. Add the `i` flag (now `gmi`). The sibling CJS regex in get-shit-done/bin/lib/core.cjs already uses the `mi` flag, so it is already case-insensitive; added a regression test to lock that in. - sdk/src/query/roadmap.ts: change flags from `gm` → `gmi` - sdk/src/query/roadmap.test.ts: add PHASE/phase regression test - tests/roadmap-phase-fallback.test.cjs: add PHASE/phase regression test Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
9b5397a30f |
feat(sdk): add queued_phases to init.manager (closes #2497) (#2514)
* feat(sdk): add queued_phases to init.manager (closes #2497) Surfaces the milestone immediately AFTER the active one so the /gsd-manager dashboard can preview upcoming phases without mixing them into the active phases grid. Changes: - roadmap.ts: exports two new helpers - extractPhasesFromSection(section): parses phase number / name / goal / depends_on using the same pattern initManager uses for the active milestone, so queued phases have identical shape. - extractNextMilestoneSection(content, projectDir): resolves the current milestone via the STATE-first path (matching upstream PR #2508) then scans for the next ## milestone heading. Shipped milestones are stripped first so they can't shadow the real next. Returns null when the active milestone is the last one. - init-complex.ts: initManager now exposes - queued_phases: Array<{ number, name, display_name, goal, depends_on, dep_phases, deps_display }> - queued_milestone_version: string | null - queued_milestone_name: string | null Existing phases array is unchanged — callers that only care about the active milestone see no behavior difference. Scope note: PR #2508 (merged upstream 2026-04-21) superseded the #2495 + #2496 portions of this branch's original submission. This commit is the rebased remainder contributing only #2497 on top of upstream's new helpers. Test coverage (7 new tests, all passing): - roadmap.test.ts: +5 tests - extractPhasesFromSection parses multiple phases with goal + deps - extractPhasesFromSection returns [] when no phase headings - extractNextMilestoneSection returns the milestone after the STATE-resolved active one - extractNextMilestoneSection returns null when active is last - extractNextMilestoneSection returns null when no version found - init-complex.test.ts: +4 tests under `queued_phases (#2497)` - surfaces next milestone with version + name metadata - queued entries carry name / deps_display / display_name - queued phases are NOT mixed into active phases list - returns [] + nulls when active is the last milestone All 51 tests in roadmap.test.ts + init-complex.test.ts pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(workflows): render queued_phases section in /gsd-manager dashboard Surfaces the new `queued_phases` / `queued_milestone_version` / `queued_milestone_name` fields from init.manager (SDK #2497) in a compact preview section directly below the main active-milestone table. Changes to workflows/manager.md: - Initialize step: parse the optional trio (queued_milestone_version, queued_milestone_name, queued_phases) alongside the existing init.manager fields. Treat missing as empty for backward compatibility with older SDK versions. - Dashboard step: new "Queued section (next milestone preview)" rendered between the main active-milestone grid and the Recommendations section. Renders only when queued_phases is non-empty; skipped entirely when absent or empty (e.g. active milestone is the last one). - Queued rows render without D/P/E columns since the phases haven't been discussed yet — just number, display_name, deps_display, and a fixed "· Queued" status. - Success criterion added: queued section renders when non-empty and is skipped when absent. Queued phases are deliberately NOT eligible for the Continue action menu; they live in a future milestone. The preview exists for situational awareness only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
2980f0ec48 |
fix(sdk): stripShippedMilestones handles inline SHIPPED headings; getMilestoneInfo prefers STATE.md (#2508)
* fix(sdk): stripShippedMilestones handles inline SHIPPED headings; getMilestoneInfo prefers STATE.md Fixes two compounding bugs: - #2496: stripShippedMilestones only stripped <details> blocks, ignoring '## Heading — ✅ SHIPPED ...' inline markers. Shipped milestone sections were leaking into downstream parsers. - #2495: getMilestoneInfo checked STATE.md frontmatter only as a last-resort fallback, so it returned the first heading match (often a leaked shipped milestone) rather than the current milestone. Moved STATE.md check to priority 1, consistent with extractCurrentMilestone. Closes #2495 Closes #2496 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(roadmap): handle ### SHIPPED headings and STATE.md version-only case Two follow-up fixes from CodeRabbit review of #2508: 1. stripShippedMilestones only split on ## boundaries; ### headings marked ✅ SHIPPED were not stripped, leaking into fallback parsers. Expanded the split/filter regex to #{2,3} to align with extractCurrentMilestone. 2. getMilestoneInfo's early-return on parseMilestoneFromState discarded the real milestone name from ROADMAP.md when STATE.md had only `milestone:` (no `milestone_name:`), returning the placeholder name 'milestone'. Now only short-circuits when STATE.md provides a real name; otherwise falls through to ROADMAP for the name while using stateVersion to override the version in every ROADMAP-derived return path. Tests: +2 new cases (### SHIPPED heading, version-only STATE.md). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
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 |
||
|
|
59cfbbba6a |
fix(sdk): extractCurrentMilestone Backlog leak + state.begin-phase flag parsing (#2455)
* fix(sdk): extractCurrentMilestone Backlog leak + state.begin-phase flag parsing Closes #2422 Closes #2420 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: patch-version semver in milestone boundary regex + flag-parser validation Two follow-on correctness issues identified in code review: 1. roadmap.ts: currentVersionMatch and nextMilestoneRegex only captured major.minor (v(\d+\.\d+)), collapsing v2.0.1 to "2.0". A sub-heading "## v2.0.2 Phase Details" would match the same prefix and be incorrectly skipped. Both patterns updated to v(\d+(?:\.\d+)+) to capture full semver. 2. state-mutation.ts: pair-wise flag parsing loop advanced i by 2 unconditionally, so a missing flag value caused the next flag token to be assigned as the value (e.g. flags['phase'] = '--name'). Fix: iterate with i++ and validate that the candidate value exists and does not start with '--' before assigning; throw GSDError('missing value for --<key>') on invalid input. Added regression test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
002bcf2a8a |
fix(2137): skip worktree isolation when .gitmodules detected (#2144)
* feat(sdk): add typed query foundation and gsd-sdk query (Phase 1) Add sdk/src/query registry and handlers with tests, GSDQueryError, CLI query wiring, and supporting type/tool-scoping hooks. Update CHANGELOG. Vitest 4 constructor mock fixes in milestone-runner tests. Made-with: Cursor * fix(2137): skip worktree isolation when .gitmodules detected When a project contains git submodules, worktree isolation cannot correctly handle submodule commits — three separate gaps exist in worktree setup, executor commit protocol, and merge-back. Rather than patch each gap individually, detect .gitmodules at phase start and fall back to sequential execution, which handles submodules transparently (Option B). Affected workflows: execute-phase.md, quick.md --------- Co-authored-by: David Sienkowski <dave@sienkowski.com> |