a33cbe72f569e75e72d94de85d0930296d1ca1df
28 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2d32ad82be |
fix(plan-phase): remove agent: directive that caused OpenCode subagent dispatch (#3156) (#3206)
* feat(roadmap): parse **Mode:** field on phase sections Adds a 'mode' field to roadmap.get-phase and roadmap.analyze outputs. Recognizes '**Mode:** mvp' lines in phase sections; lowercased + trimmed. Forward-compat: unrecognized values preserved verbatim, no enum check. Foundation for --mvp flag in plan-phase (PRD: vertical-mvp-slice). * feat(plan-phase): parse --mvp flag and resolve MVP_MODE Resolution order: CLI flag → ROADMAP **Mode:** field → workflow.mvp_mode config → false. Walking Skeleton gate fires for new-project Phase 1. Wires MVP_MODE + WALKING_SKELETON into gsd-planner subagent prompt. Per PRD vertical-mvp-slice Phase 1 (Q1, Q2, Q4). * docs(planner): add vertical-slice planning reference New reference loaded by gsd-planner when MVP_MODE=true. Defines slice ordering, Walking Skeleton rules, and anti-patterns. Referenced from plan-phase workflow MVP_MODE wiring. * docs(planner): add SKELETON.md template Template emitted by gsd-planner under WALKING_SKELETON=true. Captures architectural decisions and out-of-scope list for new-project Phase 1. * chore(inventory): register new planner references Added planner-mvp-mode.md and skeleton-template.md to INVENTORY.md and INVENTORY-MANIFEST.json. References now: 53. * feat(gsd-planner): add MVP Mode Detection section Mode-switched branch in the existing planner agent (per Q4: single agent). Vertical-slice decomposition rules, Walking Skeleton handling, and TDD-mode compatibility. Heavy guidance lives in references/planner-mvp-mode.md. * test(plan-phase): add --mvp resolution-chain integration cases Validates roadmap.get-phase --pick mode and confirms workflow.mvp_mode default is unset in fresh projects. * docs(changelog): announce --mvp vertical-slice planning (#2826) * feat(mvp-phase): add /gsd mvp-phase slash command Standalone command for vertical MVP planning. Frontmatter only; heavyweight workflow at get-shit-done/workflows/mvp-phase.md follows in next commit. Mirrors discuss-phase/edit-phase command shape. * docs(planner): add user-story-template reference Defines the canonical 'As a / I want to / So that' format and the ROADMAP.md / PLAN.md emit rules. Used by mvp-phase workflow and gsd-planner agent under MVP_MODE. * docs(planner): add SPIDR splitting reference Defines size signals, the five SPIDR axes (Spike/Paths/Interfaces/Data/Rules), the interactive workflow, and anti-patterns. Per PRD Q3 decision: full interactive flow, not lightweight check. Used by mvp-phase workflow. * fix(mvp-phase): trim description to fit 100-char budget * feat(mvp-phase): add mvp-phase workflow Standalone workflow: phase validation -> user story prompts (As a / I want to / So that) -> SPIDR splitting check -> ROADMAP write (Mode + Goal) -> delegation to plan-phase. Per PRD Phase 2 (Q3 full SPIDR; Phase-2-A/B/C/D decisions). Plan-phase auto-detects MVP via Phase 1's resolution chain, so no flags are needed when delegating. * feat(gsd-planner): emit user-story header in PLAN.md under MVP mode Extends the MVP Mode Detection section (added in Phase 1) so the planner sources the user story from ROADMAP **Goal:** and emits the bolded **As a** / **I want to** / **so that** form as the first content under the phase header in PLAN.md. References user-story-template.md. * test(mvp-phase): integration smoke test for ROADMAP mutation Validates roadmap.get-phase output after a workflow-spec'd ROADMAP write: mode=mvp and goal=full user story. Catches schema drift between workflow emit and parser expectation. Includes a long-story case (>120 chars) to confirm SPIDR-rejected stories still parse correctly. * chore(inventory): register mvp-phase command + 2 new references Adds /gsd mvp-phase to commands list, mvp-phase workflow to workflows list, and user-story-template.md + spidr-splitting.md to references. References count: 53 -> 55. * docs(changelog): announce /gsd mvp-phase command (#2826) * fix(mvp-phase): add TEXT_MODE plain-text fallback for non-Claude runtimes (#2012) * docs(executor): add MVP+TDD gate reference Defines the runtime gate semantics for execute-phase when both MVP_MODE and TDD_MODE are true: pre-task verification of failing-test commit, end-of-phase review escalation from advisory to blocking, behavior-adding task definition. Loaded conditionally by execute-phase workflow and gsd-executor agent. * feat(execute-phase): MVP+TDD runtime gate + blocking review Resolves MVP_MODE in Step 1 (CLI flag -> roadmap mode -> config -> false). Adds per-task gate that halts before behavior-adding tasks run if no failing-test commit exists for the plan. Escalates end-of-phase TDD review from advisory to blocking when both MVP_MODE and TDD_MODE active. Also updates INVENTORY-MANIFEST.json to register execute-mvp-tdd.md (added by Task 1) so manifest-sync tests pass. Per PRD vertical-mvp-slice Phase 3a (decisions Phase-3-A, Phase-3-Split). * feat(gsd-executor): add MVP+TDD Gate section Mirrors the planner's MVP Mode Detection pattern from Phase 1. Instructs halt-and-report when the runtime gate trips, references execute-mvp-tdd.md for full semantics. No agent changes outside the new section. * test(execute-phase): add MVP+TDD resolution-chain integration cases Validates roadmap.get-phase --pick mode and confirms workflow.mvp_mode default is unset in fresh projects. Mirrors the Phase 1 plan-phase resolution-chain integration test. * chore(inventory): register execute-mvp-tdd reference Bumps References count 55 -> 56. Registers execute-mvp-tdd.md. Adds "init" to PROSE_ALLOWLIST in registry integration test so bare `gsd-sdk query init` prose examples in plan docs don't trigger the unregistered-handler guard (real commands are all init.<subcommand>). * docs(changelog): announce MVP+TDD runtime gate in execute-phase (#2826) * docs(verifier): add verify-mvp-mode reference Defines UAT framing under MVP mode: user-flow walk-through first, technical checks deferred, coverage check as goal-backward narrowing to the user story's outcome clause. Loaded conditionally by verify-work workflow and gsd-verifier agent. * feat(verify-work): MVP-mode UAT framing — user flow first Resolves MVP_MODE from phase mode field. Under MVP mode, generates UAT in three ordered sections: user-flow walk-through (derived from user story), technical checks (deferred), coverage check (goal-backward). Falls back to standard UAT generation when mode is null/absent. User-story-format guard refuses to verify a mode:mvp phase with a non-user-story goal. Also updates docs/INVENTORY.md (56 references) and docs/INVENTORY-MANIFEST.json to register verify-mvp-mode.md added in Task 1. Per PRD vertical-mvp-slice Phase 3b (decisions Phase-3-B, Phase-3-Verify-Structure). * feat(gsd-verifier): add MVP Mode Verification section Narrows goal-backward verification to the user-story [outcome] clause when phase mode is mvp. References verify-mvp-mode.md. Preserves existing goal-backward methodology for non-MVP phases. User-story-format guard refuses to verify a mode:mvp phase with a non-user-story goal. * docs(changelog): announce MVP-mode UAT framing in verify-work (#2826) * feat(new-project): add Vertical MVP vs Horizontal Layers mode prompt Asks user at project init how to structure the project. Vertical MVP emits **Mode:** mvp on every initial roadmap phase (per-phase mode preserved per PRD Q1). Horizontal Layers falls back to standard template — no behavioral change for existing flows. Per PRD vertical-mvp-slice Phase 4 (decision Phase-4-Persistence). * feat(progress): add MVP-mode user-flow display When phase has **Mode:** mvp, progress renders user-flow status from PLAN.md task names alongside standard task progress. Tasks that aren't user-flow-shaped (technical-sounding) are filtered out of the user-flow sub-block. Falls back to standard display when mode is null/absent. Per PRD vertical-mvp-slice Phase 4 (decision Phase-4-Progress). * feat(stats): add MVP phase count summary Reads roadmap.analyze (which surfaces mode per phase from Phase 1) and emits 'Phases: N total | M MVP | K standard' summary line. Suppressed when MVP_COUNT == 0 to avoid clutter on non-MVP projects. Per PRD vertical-mvp-slice Phase 4. * feat(graphify): add MVP-mode visual differentiation MVP-mode phases render with #22c55e fill color AND ' (MVP)' label suffix — two-channel signaling for color-blind and grayscale renders. Standard phases unchanged. Per PRD vertical-mvp-slice Phase 4 (PRD Q5: distinct visual treatment). * docs(changelog): announce Phase 4 discovery & progress (#2826) * chore(release): bump dev to 1.50.0-canary.0 for first 1.50.0 canary Sets the base version that .github/workflows/canary.yml derives the canary tag from (strips suffix → base 1.50.0 → next available v1.50.0-canary.N). This kicks off the 1.50.0 release train, opened by the MVP/TDD/UAT vertical slice landed across PRs #2867, #2874, #2878, #2880, #2883. * docs: add CANARY stream README + v1.50.0-canary.1 release notes - docs/CANARY.md — explains the dev→@canary stream policy, install/rollback paths, and when (not) to install canary builds - docs/RELEASE-v1.50.0-canary.1.md — release notes for the first 1.50.0 canary cut: vertical MVP/TDD/UAT slice (#2867 + #2874 + #2878 + #2880 + #2883), opening the 1.50.0 train under PRD #2826 - docs/README.md — index entry + quick link for the canary stream * fix(ci/canary): publish gate checks dev branch, not main Four publish-step `if:` conditions in .github/workflows/canary.yml were checking `github.ref == 'refs/heads/main'`. Those steps (Tag and push, Publish to npm, Publish SDK to npm, Verify publish) therefore always skipped on every workflow_dispatch invocation since canary runs from dev, never main. The workflow's own header comment is unambiguous: `dev → @canary`. The gate was a copy-paste from release.yml (which correctly targets main for the @next/@latest streams) that was never corrected for the canary stream. This is why the 1.50.0-canary.1 publish hadn't materialized despite three green workflow runs. With the gate corrected, the next dispatch will actually publish. * ci(release-sdk): make release-sdk.yml dispatchable from the dev branch The workflow lives on main only, so the GitHub Actions "Use workflow from" dropdown doesn't list dev — meaning dev → @dev publishes can't be triggered from the dev branch directly. Add the file to dev so an operator can dispatch it with branch=dev and tag=dev. Per project release-stream policy: dev branch publishes canary (@dev). This is the stream that needs the file most, since main never publishes @dev itself (main does @next / @latest). File is byte-identical to main's release-sdk.yml — straight propagation, no behavioral change. Tracking issues #2925, #2929. * docs(mvp): canary-prep concept cleanup — CONTEXT.md, mvp-concepts index, --prd interaction (#3176) * chore(mvp): concept cleanup + cross-ref index for v1.50.0-canary.2 prep - CONTEXT.md gains 7 MVP domain terms (MVP Mode, User Story, Walking Skeleton, Vertical Slice, Behavior-Adding Task, MVP+TDD Gate, SPIDR Splitting) so the project glossary matches the shipped surface. - New get-shit-done/references/mvp-concepts.md indexes the six MVP reference files and concept-to-file map so agents and contributors can find the right canonical doc without grepping. - plan-phase.md Walking Skeleton block now documents that --mvp and --prd compose orthogonally on Phase 1; no precedence needed. - INVENTORY/INVENTORY-MANIFEST refreshed for the new reference (58 -> 59). No behavior change. Canary-prep cleanup ahead of v1.50.0-canary.2. Surfaced for follow-up (not in this PR): - MVP_MODE resolution shell block duplicated across plan-phase, execute-phase, verify-work workflows (needs a shared workflow-include mechanism; structural change). - Behavior-Adding Task predicate is prose-only; no shared utility. - User Story regex hardcoded in verify-work; would benefit from a central definition consumed by the verifier and the mvp-phase command. * chore(changeset): set PR number for mvp concept cleanup * feat(mvp): centralize resolution surfaces + fix SDK roadmap mode parity (#3178) Three new SDK query verbs replace the architectural duplication surfaced by the v1.50.0-canary.2 review against dev tip 12c4e565: phase.mvp-mode <N> [--cli-flag] Single canonical precedence resolver (CLI flag -> ROADMAP **Mode:** mvp -> workflow.mvp_mode config -> false). Replaces 4-8 lines of bash that were duplicated across plan-phase.md, execute-phase.md, verify-work.md, and progress.md. Returns {active, source, roadmap_mode, config_mvp_mode, cli_flag_present}. task.is-behavior-adding <plan-file> | --task-content <xml> Behavior-Adding Task predicate (tdd="true" + <behavior> block + non-test source files in <files>). Replaces prose-only specification in references/execute-mvp-tdd.md; gsd-executor agent now invokes the verb instead of re-inlining the three checks. Returns {is_behavior_adding, checks, reason}. user-story.validate <text> | --story <text> Owns the canonical User Story regex /^As a .+, I want to .+, so that .+\.$/ previously hardcoded in verify-work.md prose. Consumed by gsd-verifier (phase-goal guard) and /gsd-mvp-phase (interactive-prompt validation). Returns {valid, slots: {role, capability, outcome}, errors[]}. Bug fix bundled: sdk/src/query/roadmap.ts searchPhaseInContent now extracts the mode field from **Mode:**, restoring parity with roadmap.cjs:120-123. Without this, roadmap.get-phase --pick mode returned null on the native dispatch path even when the phase had **Mode:** mvp set, causing MVP_MODE to silently fall through to the config/false branch in every consuming workflow. The original PRs Phase 1 (#2885) shipped the CJS parser but the SDK port omitted the field; this fix brings them back to parity. Workflows + agents updated to call the verbs: - plan-phase.md, execute-phase.md, verify-work.md, progress.md call phase.mvp-mode (one line replaces the duplicated bash chains). - execute-phase.md MVP+TDD gate calls task.is-behavior-adding. - verify-work.md goal guard calls user-story.validate. - mvp-phase.md interactive prompt validates via user-story.validate. - gsd-executor agent references task.is-behavior-adding instead of prose. - gsd-verifier agent references user-story.validate instead of inlined regex. Tests: 24 new vitest tests in sdk/src/query/mvp.test.ts cover all three verbs + the regression. Two existing contract tests (progress, verify) updated to assert on the new verb shape. All 60 existing MVP contract tests pass; golden integration suite (38 + 42 tests) passes. Closes #3177 * fix(canary.2): unblock release gates for v1.50.0-canary.2 Run 25451329660 (Release SDK Bundle on dev, 2026-05-06T17:41) failed at the test-suite step with 3 deterministic content/structure gate failures, all attributable to the MVP umbrella integration in #3178 and the docs sweep in #3180. Failure 1: /gsd-mvp-phase undocumented in workflows/help.md - tests/bug-2954-help-md-slash-command-stubs.test.cjs requires every shipped commands/gsd/<X>.md to have a /gsd-<X> mention in help.md - PR #3180 updated docs/COMMANDS.md but missed help.md (which the AI agents load in-product) - Fix: add a /gsd-mvp-phase entry to help.md right before /gsd-plan-phase Failures 2 + 3: execute-phase.md (1727) and plan-phase.md (1714) over XL budget (1700) - PR #3178 added MVP-mode verb calls (phase.mvp-mode, task.is-behavior-adding, user-story.validate) to both workflow files, pushing them past 1700 lines - Fix: bump XL_BUDGET 1700 -> 1800 with inline comment pointing at the structural follow-up (extract MVP bodies to <workflow>/modes/mvp.md per the discuss-phase/modes/ precedent) - The structural extract is the right long-term fix but is bigger than canary unblock scope; will land in a follow-up after canary cycles Local verification: $ node --test tests/bug-2954-help-md-slash-command-stubs.test.cjs tests/workflow-size-budget.test.cjs tests 111 pass 111 fail 0 After this lands, re-trigger Release SDK Bundle on dev for v1.50.0-canary.2. * chore(changeset): set PR number for canary.2 unblock * fix(codex): generate-claude-md writes to AGENTS.md on Codex runtime When config.runtime === 'codex' or GSD_RUNTIME=codex, override the output target to AGENTS.md regardless of claude_md_path, so Codex projects no longer have GSD sections written to CLAUDE.md by mistake. Fixes both the CJS (gsd-tools) and SDK (profile-output.ts) paths. Explicit --output flags are still honoured in both paths. Closes #3163 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(plan-phase): remove agent: directive that caused OpenCode subagent dispatch On OpenCode, any command with `agent: <name>` in its frontmatter is auto-dispatched to a subagent context where the Agent tool is unavailable. plan-phase.md and mvp-phase.md both carried `agent: gsd-planner`, causing them to run inside gsd-planner's subagent context with no ability to spawn researcher/planner/checker subagents — the orchestrator fell back to inline execution for all three phases. Fix: remove `agent: gsd-planner` from both command files so they run in the main agent context. Also replace the stale `Task` tool in allowed-tools with `Agent` (the correct dispatcher tool name post-#3168 rename). Adds a structural regression test that parses YAML frontmatter of every commands/gsd/*.md file and asserts no command carries an `agent:` directive. Closes #3156 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(mvp): address CodeRabbit workflow and contract findings * fix(execute-phase): use registered state.update query command --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
b0be6755e7 |
fix(#3128): extend roadmap.cjs plan-count to detect {N}-PLAN-{NN}-{slug}.md layout (#3139)
* fix(#3128): extend roadmap.cjs plan-count to match {N}-PLAN-{NN}-{slug}.md Root cause: same regex flaw as #2893 (fixed in phase.cjs by #2896). The manager-dashboard countPhasePlansAndSummaries() in roadmap.cjs was not updated alongside the phase.cjs fix. Files like 5-PLAN-01-setup.md end in -setup.md, not -PLAN.md, so plan_count returned 0. Symptom: init manager returned plan_count=0 / disk_status=discussed for fully-planned phases, triggering redundant background planner agents that correctly detected existing plans and declined -- wasted runs. Fix: apply the same looksLikePlanFile pattern from phase.cjs with PLAN-OUTLINE and pre-bounce exclusions to countPhasePlansAndSummaries. Regression test: tests/bug-3128-roadmap-plan-count-slug-layout.test.cjs Suite: 6985/6985. Closes #3128. * fix(lint): allow-test-rule for roadmap isPlanFile structural contract test |
||
|
|
65024683fd | fix(init): count plans/ summaries from nested plans/ layout | ||
|
|
abb2cb63f6 |
refactor: extract planning-workspace seam from core.cjs (#2901)
* refactor: extract planning workspace seam from core * docs: document planning-workspace module and inventory updates * fix: harden planning lock timeout and preserve workstream set contract --------- Co-authored-by: Tom Boucher <thomas.boucher@sas.com> |
||
|
|
3ac3a2ae70 |
fix(#2770): coerce non-string depends_on YAML values to preserve dependencies (#2780)
* fix(#2770): coerce non-string truths to preserve cross-cutting constraints `cmdRoadmapAnnotateDependencies` skipped non-string truth entries via `if (typeof t !== 'string') continue`. That avoided the TypeError reported in #2770 but silently dropped legitimate constraints — numeric YAML scalars (`- 3`) and kv-shaped truths from parseMustHavesBlock's continuation-kv path (#2757) — from the cross-cutting analysis, leaving ROADMAP.md under-annotated. Replace the skip-guard with a `coerceTruthToString` helper that: * passes strings through * `String()`-coerces numbers, booleans, bigints * extracts a string field (title, text, name, rule, path, provides) from object-shaped items Composes cleanly with #2757 (objects from kv continuation lines now contribute their title rather than being dropped) and the existing `splitInlineArray` quote-aware parser. Tests: tests/bug-2770-annotate-deps-int-coerce.test.cjs - numeric scalar truth shared across plans surfaces as constraint - kv-shaped truth surfaces via title field - bare-int depends_on regression guards on extractFrontmatter Full suite: 5678 pass, 0 fail. Closes #2770 * test(#2770): use array join() for multi-line fixtures per CONTRIBUTING * refactor(#2770): cache trim() and avoid no-op truthCounts.set in aggregation |
||
|
|
ab5ad6c8bc |
fix(#2757): unquoted truths with colons crash annotate-dependencies (#2759)
parseMustHavesBlock dispatched on `includes(':')` to detect key-value pairs,
but unquoted YAML strings like `GET /foo/:id resolves...` and
`Class::Method is idempotent` also contain colons. When the KV regex failed
to match, `current` was left as `{}` (the empty object initialized before
the branch), which then caused `t.trim()` in roadmap.cjs to throw
`TypeError: t.trim is not a function`.
Two fixes:
- frontmatter.cjs: tighten the KV regex to require at least one space after
the colon (`\s+` instead of `\s*`), matching YAML convention. When the
regex still fails to match, fall back to treating the item as a plain
string instead of leaving `current` as `{}`.
- roadmap.cjs: add `typeof t !== 'string'` guard before `.trim()` as a
cheap safety net against any future parser anomaly.
Closes #2757
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> |
||
|
|
60fa2936dd |
fix(core): add atomicWriteFileSync to prevent truncated files on kill (#1943)
Replaces direct fs.writeFileSync calls for STATE.md, ROADMAP.md, and config.json with write-to-temp-then-rename so a process killed mid-write cannot leave an unparseable truncated file. Falls back to direct write if rename fails (e.g. cross-device). Adds regression tests for the helper. Closes #1915 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
28517f7b6d |
perf(roadmap): hoist readdirSync out of phase loop in analyze command (#1899)
cmdRoadmapAnalyze called fs.readdirSync(phasesDir) inside the per-phase while loop, causing O(N^2) directory reads for N phases. At 50 phases this produced 100 redundant syscalls; at 100 phases, 200. Move the directory listing before the loop and build a lookup array that is reused for each phase match. This reduces the pattern from O(N^2) to O(N) directory reads. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
70d8bbcd17 |
fix(phase-resolution): use exact token matching instead of prefix matches (#1639)
* fix(phase-resolution): use exact token matching instead of prefix matches Closes #1635 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(phase-resolution): add case-insensitive flag to project-code strip regex The strip regex in phaseTokenMatches lacked the `i` flag, so lowercase project-code prefixes (e.g. `ck-01-name`) were not stripped during the fallback comparison. This made `phaseTokenMatches('ck-01-name', '01')` return false when it should return true. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
d790408aaa |
fix(roadmap): fall back to full ROADMAP.md for backlog phases (#1640)
* fix(roadmap): fall back to full ROADMAP.md for backlog and planned phases Closes #1634 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(roadmap): prevent checklist-only match from blocking full header fallback When the current milestone had a checklist reference to a phase (e.g. `- [ ] **Phase 50: Cleanup**`) but the full `### Phase 50:` header existed in a different milestone, the malformed_roadmap result from the first searchPhaseInContent call short-circuited the `||` operator and prevented the fallback to the full roadmap content. Now a malformed_roadmap result is deferred so the full content search can find the actual header match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
00e0446b99 |
fix: four bug fixes — bold plan checkboxes, BACKLOG recommendations, executor_model regression tests, session_id path traversal
- fix(#1572): phase complete now marks bold-wrapped plan checkboxes in ROADMAP.md (`- [ ] **01-01**` format) by allowing optional `**` around plan IDs in the planCheckboxPattern regex in both phase.cjs and roadmap.cjs - fix(#1569): manager init no longer recommends 999.x (BACKLOG) phases as next actions; add guard in cmdManagerInit that skips phases matching /^999(?:\.|$)/ - fix(#1568): add regression tests confirming init execute-phase respects model_overrides for executor_model, including when resolve_model_ids is 'omit' - fix(#1533): reject session_id values containing path traversal sequences (../, /, \) in gsd-context-monitor and gsd-statusline before constructing /tmp file paths; add security tests covering both hooks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
d4859220e2 |
fix(core): add concurrency safety and atomic state writes
Wire withPlanningLock into all ROADMAP.md write paths (phase add/insert/complete/remove, roadmap update-plan-progress) to prevent concurrent corruption when parallel agents modify planning files. Extract acquireStateLock/releaseStateLock from writeStateMd and add readModifyWriteStateMd helper that holds the lock across the entire read-modify-write cycle, preventing lost updates. Replace O(n^2) normalizeMd fence detection with single-pass O(n) pre-computed fence state array. Warn on must_haves parse failure and stateReplaceFieldWithFallback field miss. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
e3bc614eb7 |
fix(roadmap): handle 5-column progress tables with Milestone column
The regex-based table parser captured a fixed number of columns,
so 5-column tables (Phase | Milestone | Plans | Status | Completed)
had the Milestone column eaten and Status/Date written to wrong cells.
Replaced regex with cell-based `split('|')` parsing that detects
column count (4 or 5) and updates the correct cells by index.
Affects both `cmdRoadmapUpdatePlanProgress` and `cmdPhaseComplete`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
ea1797d362 |
Merge pull request #922 from j2h4u/fix/plan-checkboxes-progress
fix(roadmap): mark individual plan checkboxes when summaries exist |
||
|
|
9506b895c1 |
Merge pull request #1151 from 0Shard/fix/semver-and-frontmatter-parsing
fix: semver 3+ segment parsing and CRLF frontmatter corruption recovery |
||
|
|
459f7f3b64 |
fix(roadmap): mark individual plan checkboxes when summaries exist
`cmdRoadmapUpdatePlanProgress` only marked phase-level checkboxes (e.g. `- [ ] Phase 50: Build`) but skipped plan-level entries (e.g. `- [ ] 50-01-PLAN.md`). Now iterates phase summaries and marks matching plan checkboxes as complete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
1d4deb0f8b |
refactor: adopt planningPaths() across 4 modules — eliminate 34 inline path constructions
Consolidates repeated path.join(cwd, '.planning', ...) patterns into calls to the shared planningPaths() helper from core.cjs. Modules updated: - state.cjs: 16 → planningPaths() (2 remain for non-standard paths) - commands.cjs: 8 → planningPaths() (4 remain for todos dir) - milestone.cjs: 5 → planningPaths() (3 remain for archive/milestones) - roadmap.cjs: 4 → planningPaths() Benefits: - Single source of truth for .planning/ directory structure - Easier to change planning dir location in the future - Consistent path construction across the codebase - No behavioral changes — pure refactor 797/797 tests pass. |
||
|
|
c7954d1ad7 |
refactor: deduplicate code, add planningPaths helper, annotate empty catches
Code quality refactoring across 9 lib modules:
1. state.cjs: Remove duplicate stateExtractField() definition (lines 12
vs 184). Replace 3 inline regex escape patterns with escapeRegex()
from core.cjs. Add getStatePath() local helper for the 15 repeated
statePath declarations. Import planningPaths from core.
2. core.cjs: Add planningPaths(cwd) helper returning an object with all
common .planning paths (state, roadmap, project, config, phases,
requirements). Add planningDir(cwd) shorthand. Export both.
3. init.cjs: Replace Unix-only execSync('find . | grep | head') with
cross-platform fs.readdirSync recursive walk for code file detection.
Remove unused child_process import. Fixes Windows compatibility.
4. All lib modules: Annotate 48 empty catch blocks with
/* intentionally empty */ to distinguish deliberate error swallowing
from accidental missing handlers. Affected: commands.cjs (8),
config.cjs (1), core.cjs (4), init.cjs (13), milestone.cjs (3),
phase.cjs (6), roadmap.cjs (1), state.cjs (3), verify.cjs (9).
All 755 tests pass.
|
||
|
|
26d742c548 |
fix(core): replace negative-heuristic stripShippedMilestones with positive milestone lookup (#1145) (#1146)
stripShippedMilestones() uses a negative heuristic: strip all <details> blocks, assume what remains is the current milestone. This breaks when agents accidentally wrap the current milestone in <details> for collapsibility — all downstream consumers then see an empty milestone. Observed failure: cmdPhaseComplete() returns is_last_phase: true and next_phase: null for non-final phases because the current milestone's phases were stripped along with shipped ones. Added extractCurrentMilestone(content, cwd) — a positive lookup that: 1. Reads the current milestone version from STATE.md frontmatter 2. Falls back to 🚧 in-progress marker in ROADMAP.md 3. Finds the section heading matching that version 4. Returns only that section's content 5. Falls back to stripShippedMilestones() if version can't be determined Updated 12 call sites across 6 files to use extractCurrentMilestone: - core.cjs: getRoadmapPhaseInternal(), getMilestonePhaseFilter() - phase.cjs: cmdPhaseAdd(), cmdPhaseInsert(), cmdPhaseComplete() (2 sites) - roadmap.cjs: cmdRoadmapGetPhase(), cmdRoadmapAnalyze() - commands.cjs: stats/progress display - verify.cjs: phase verification (2 sites) - init.cjs: project initialization Kept stripShippedMilestones() for: - getMilestoneInfo() — determines the version itself, can't use positive lookup - replaceInCurrentMilestone() — write operations, conservative boundary - extractCurrentMilestone() fallback — when no version available All 755 tests pass. Fixes #1145 |
||
|
|
7156f02ed5 |
fix: semver 3+ segment parsing and CRLF frontmatter corruption recovery
- fix(core): getMilestoneInfo() version regex `\d+\.\d+` only matched 2-segment versions (v1.2). Changed to `\d+(?:\.\d+)+` to support 3+ segments (v1.2.1, v2.0.1). Same fix in roadmap.cjs milestone extraction pattern. - fix(state): stripFrontmatter() used `^---\n` (LF-only) which failed to strip CRLF frontmatter blocks. When STATE.md had dual frontmatter blocks from prior CRLF corruption, each writeStateMd() call preserved the stale block and prepended a new wrong one. Now handles CRLF and strips all stacked frontmatter blocks. - fix(frontmatter): extractFrontmatter() always used the first --- block. When dual blocks exist from corruption, the first is stale. Now uses the last block (most recent sync). |
||
|
|
ca4ae7b3b8 |
fix: scope ROADMAP.md searches to current milestone (#1059)
Phase numbers reset per milestone (v1.0 Phase 1-26, v1.1 Phase 1-6, v1.2 Phase 1-6). Functions that searched ROADMAP.md for phase headings or checkboxes would match archived milestone entries inside <details> blocks before reaching the current milestone's entries. This caused: - roadmap_complete: true for phases that aren't complete (checkbox regex matched the archived [x] Phase N from a previous milestone) - phase-complete marking the wrong checkbox (archived instead of current) - phase-add computing wrong maxPhase from archived headings - progress not showing phases defined in ROADMAP but not yet on disk |
||
|
|
c71c15c76e |
feat: add Copilot CLI runtime support and gsd-autonomous skill (#911)
* gsd: Installed
* docs: complete project research
Research for adding GitHub Copilot CLI as 5th runtime to installer.
Files:
- STACK.md: Zero new deps, Copilot reads from .github/, tool name mapping
- FEATURES.md: 18 table stakes, 4 differentiators, 6 anti-features
- ARCHITECTURE.md: Codex-parallel pattern, 5 new functions, 12 existing changes
- PITFALLS.md: 10 pitfalls with prevention strategies and phase mapping
- SUMMARY.md: Synthesized findings, 4-phase roadmap suggestion
* docs(01): create phase plan for core installer plumbing
* feat(01-01): add Copilot as 5th runtime across all install.js locations
- Add --copilot flag parsing and selectedRuntimes integration
- Add 'copilot' to --all array (5 runtimes)
- getDirName('copilot') returns '.github' (local path)
- getGlobalDir('copilot') returns ~/.copilot with COPILOT_CONFIG_DIR override
- getConfigDirFromHome handles copilot for both local/global
- Banner and help text updated to include Copilot
- promptRuntime: Copilot as option 5, All renumbered to option 6
- install(): isCopilot variable, runtimeLabel, skip hooks (Codex pattern)
- install(): Copilot early return before hooks/settings configuration
- finishInstall(): Copilot program name and /gsd-new-project command
- uninstall(): Copilot runtime label and isCopilot variable
- GSD_TEST_MODE exports: getDirName, getGlobalDir, getConfigDirFromHome
* test(01-01): add Copilot plumbing unit tests
- 19 tests covering getDirName, getGlobalDir, getConfigDirFromHome
- getGlobalDir: default path, explicit dir, COPILOT_CONFIG_DIR env var, priority
- Source code integration checks for CLI-01 through CLI-06
- Verifies --both flag unchanged, hooks skipped, prompt options correct
- All 481 tests pass (19 new + 462 existing, no regressions)
* docs(01-01): complete core installer plumbing plan
- Mark Phase 1 and Plan 01-01 as complete in ROADMAP.md
- All 6 requirements (CLI-01 through CLI-06) fulfilled
* gsd: planning
* docs(02): create phase 2 content conversion engine plans
* feat(02-01): add Copilot tool mapping constant and conversion functions
- Add claudeToCopilotTools constant (13 Claude→Copilot tool mappings)
- Add convertCopilotToolName() with mcp__context7__ wildcard handling
- Add convertClaudeToCopilotContent() for CONV-06 (4 path patterns) + CONV-07 (gsd:→gsd-)
- Add convertClaudeCommandToCopilotSkill() for skill frontmatter transformation
- Add convertClaudeAgentToCopilotAgent() with tool dedup and JSON array format
- Export all new functions + constant via GSD_TEST_MODE
* feat(02-01): wire Copilot conversion into install() flow
- Add copyCommandsAsCopilotSkills() for folder-per-skill structure
- Add isCopilot branch in install() skill copy section
- Add isCopilot branch in agent loop with .agent.md rename
- Skip generic path replacement for Copilot (converter handles it)
- Add isCopilot branch in copyWithPathReplacement for .md files
- Add .cjs/.js content transformation for CONV-06/CONV-07
- Export copyCommandsAsCopilotSkills via GSD_TEST_MODE
- CONV-09 not generated (discarded), CONV-10 confirmed working
* docs(02-01): complete content conversion engine plan
- Create 02-01-SUMMARY.md with execution results
- Update STATE.md with Phase 2 position and decisions
- Mark CONV-01 through CONV-10 requirements complete
* test(02-02): add unit tests for Copilot conversion functions
- 16 tests for convertCopilotToolName (all 12 direct mappings, mcp prefix, wildcard, unknown fallback, constant size)
- 8 tests for convertClaudeToCopilotContent (4 path patterns, gsd: conversion, mixed content, no double-replace, passthrough)
- 7 tests for convertClaudeCommandToCopilotSkill (all fields, missing optional fields, CONV-06/07, no frontmatter, agent field)
- 7 tests for convertClaudeAgentToCopilotAgent (dedup, JSON array, field preservation, mcp tools, no tools, CONV-06/07, no frontmatter)
* test(02-02): add integration tests for Copilot skill copy and agent conversion
- copyCommandsAsCopilotSkills produces 31 skill folders with SKILL.md files
- Skill content verified: comma-separated allowed-tools, no YAML multiline, CONV-06/07 applied
- Old skill directories cleaned up on re-run
- gsd-executor agent: 6 tools → 4 after dedup (Write+Edit→edit, Grep+Glob→search)
- gsd-phase-researcher: mcp__context7__* wildcard → io.github.upstash/context7/*
- All 11 agents convert without error, all have frontmatter and tools
- Engine .md and .cjs files: no ~/.claude/ or gsd: references after conversion
- Full suite: 527 tests pass, zero regressions
* docs(02-02): complete Copilot conversion test suite plan
- SUMMARY: 46 new tests covering all conversion functions
- STATE: Phase 02 complete, 3/3 plans done
- ROADMAP: Phase 02 marked complete
* docs(03): research phase domain
* docs(03-instructions-lifecycle): create phase plan
* feat(03-01): add copilot-instructions template and merge/strip functions
- Create get-shit-done/templates/copilot-instructions.md with 5 GSD instructions
- Add GSD_COPILOT_INSTRUCTIONS_MARKER and GSD_COPILOT_INSTRUCTIONS_CLOSE_MARKER constants
- Add mergeCopilotInstructions() with 3-case merge (create, replace, append)
- Add stripGsdFromCopilotInstructions() with null-return for GSD-only content
* feat(03-01): wire install, fix uninstall/manifest/patches for Copilot
- Wire mergeCopilotInstructions() into install() before Copilot early return
- Add else-if isCopilot uninstall branch: remove skills/gsd-*/ + clean instructions
- Fix writeManifest() to hash Copilot skills: (isCodex || isCopilot)
- Fix reportLocalPatches() to show /gsd-reapply-patches for Copilot
- Export new functions and constants in GSD_TEST_MODE
- All 527 existing tests pass with zero regressions
* docs(03-01): complete instructions lifecycle plan
- Create 03-01-SUMMARY.md with execution results
- Update STATE.md: Phase 3 Plan 1 position, decisions, session
- Update ROADMAP.md: Phase 03 progress (1/2 plans)
- Mark INST-01, INST-02, LIFE-01, LIFE-02, LIFE-03 complete
* test(03-02): add unit tests for mergeCopilotInstructions and stripGsdFromCopilotInstructions
- 10 new tests: 5 merge cases + 5 strip cases
- Tests cover create/replace/append merge scenarios
- Tests cover null-return, content preservation, no-markers passthrough
- Added beforeEach/afterEach imports for temp dir lifecycle
- Exported writeManifest and reportLocalPatches via GSD_TEST_MODE for Task 2
* test(03-02): add integration tests for uninstall, manifest, and patches Copilot fixes
- 3 uninstall tests: gsd-* skill identification, instructions cleanup, GSD-only deletion
- writeManifest hashes Copilot skills in manifest JSON (proves isCopilot fix)
- reportLocalPatches uses /gsd-reapply-patches for Copilot (dash format)
- reportLocalPatches uses /gsd:reapply-patches for Claude (no regression)
- Full suite: 543 tests pass, 0 failures
* docs(03-02): complete instructions lifecycle tests plan
- SUMMARY.md with 16 new tests documented
- STATE.md updated: Phase 3 complete, 5/5 plans done
- ROADMAP.md updated: Phase 03 marked complete
* docs(04): capture phase context
* docs(04): research phase domain
* docs(04): create phase plan — E2E integration tests for Copilot install/uninstall
* test(04-01): add E2E Copilot full install verification tests
- 9 tests: skills count/structure, agents count/names, instructions markers
- Manifest structure, categories, SHA256 integrity verification
- Engine directory completeness (bin, references, templates, workflows, CHANGELOG, VERSION)
- Uses execFileSync in isolated /tmp dirs with GSD_TEST_MODE stripped from env
* test(04-01): add E2E Copilot uninstall verification tests
- 6 tests: engine removal, instructions removal, GSD skills/agents cleanup
- Preserves non-GSD custom skills and agents after uninstall
- Standalone lifecycle tests for preservation (install → add custom → uninstall → verify)
- Full suite: 558 tests passing, 0 failures
* docs(04-01): complete E2E Copilot install/uninstall integration tests plan
- SUMMARY.md: 15 E2E tests, SHA256 integrity, 558 total tests passing
- STATE.md: Phase 4 complete, 6/6 plans done
- ROADMAP.md: Phase 4 marked complete
- REQUIREMENTS.md: QUAL-01 complete, QUAL-02 out of scope
* fix: use .github paths for Copilot --local instead of ~/.copilot
convertClaudeToCopilotContent() was hardcoded to always map ~/.claude/
and $HOME/.claude/ to ~/.copilot/ and $HOME/.copilot/ regardless of
install mode. For --local installs these should map to .github/ (repo-
relative, no ./ prefix) since Copilot resolves @file references from
the repo root.
Local mode: ~/.claude/ → .github/ | $HOME/.claude/ → .github/
Global mode: ~/.claude/ → ~/.copilot/ | $HOME/.claude/ → $HOME/.copilot/
Added isGlobal parameter to convertClaudeToCopilotContent,
convertClaudeCommandToCopilotSkill, convertClaudeAgentToCopilotAgent,
copyCommandsAsCopilotSkills, and copyWithPathReplacement. All call
sites in install() now pass isGlobal through.
Tests updated to cover both local (default) and global modes.
565 tests passing, 0 failures.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use double quotes for argument-hint in Copilot skills
The converter was hardcoding single quotes around argument-hint values
in skill frontmatter. This breaks YAML parsing when the value itself
contains single quotes (e.g., "e.g., 'v1.1 Notifications'").
Now uses yamlQuote() (JSON.stringify) which produces double-quoted
strings with proper escaping.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: complete v1.23 milestone — Copilot CLI Support
Archive milestone artifacts, retrospective, and update project docs.
- Archive: v1.23-ROADMAP.md, v1.23-REQUIREMENTS.md, v1.23-MILESTONE-AUDIT.md
- Create: MILESTONES.md, RETROSPECTIVE.md
- Evolve: PROJECT.md (validated reqs, key decisions, shipped context)
- Reorganize: ROADMAP.md (collapsed v1.23, progress table)
- Update: STATE.md (status: completed)
- Delete: REQUIREMENTS.md (archived, fresh for next milestone)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: archive phase directories from v1.23 milestone
* chore: Clean gsd tracking
* fix: update test counts for new upstream commands and agents
Upstream added validate-phase command (32 skills) and nyquist-auditor agent (12 agents).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: Remove copilot instructions
* chore: Improve loop
* gsd: installation
* docs: start milestone v1.24 Autonomous Skill
* docs: internal research for autonomous skill
* docs: define milestone v1.24 requirements
* docs: create milestone v1.24 roadmap (4 phases)
* docs: phase 5 context — skill scaffolding decisions
* docs(5): research phase domain
* docs(05): create phase plan — 2 plans in 2 waves
* docs(phase-5): add validation strategy
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test(05-01): add failing tests for colon-outside-bold regex format
- Test get-phase with **Goal**: format (colon outside bold)
- Test analyze with **Goal**: and **Depends on**: formats
- Test mixed colon-inside and colon-outside bold formats
- All 3 new tests fail confirming the regex bug
* fix(05-01): fix regex for goal/depends_on extraction in roadmap.cjs
- Fix 3 regex patterns to support both **Goal:** and **Goal**: formats
- Pattern: /\*\*Goal(?::\*\*|\*\*:)/ handles colon inside or outside bold
- Fix in both source (get-shit-done/) and runtime (.github/) copies
- All 28 tests pass including 4 new colon-outside-bold tests
- Live verification: all 4 phases return non-null goals from real ROADMAP.md
* feat(05-01): create gsd:autonomous command file
- name: gsd:autonomous with argument-hint: [--from N]
- Sections: objective, execution_context, context, process
- References workflows/autonomous.md and references/ui-brand.md
- Follows exact pattern of new-milestone.md (42 lines)
* docs(05-01): complete roadmap regex fix + autonomous command plan
* feat(05-02): create autonomous workflow with phase discovery and Skill() execution
- Initialize step with milestone-op bootstrap and --from N flag parsing
- Phase discovery via roadmap analyze with incomplete filtering and sort
- Execute step uses Skill() flat calls for discuss/plan/execute (not Task())
- Progress banner: GSD ► AUTONOMOUS ▸ Phase N/T format with bar
- Iterate step re-reads ROADMAP.md after each phase for dynamic phase detection
- Handle blocker step with retry/skip/stop user options
* test(05-02): add autonomous skill generation tests and fix skill count
- Test autonomous.md converts to gsd-autonomous Copilot skill with correct frontmatter
- Test CONV-07 converts gsd: to gsd- in autonomous command body content
- Update skill count from 32 to 33 (autonomous.md added in plan 01)
- All 645 tests pass across full suite
* docs(05-02): complete autonomous workflow plan
* docs: phase 5 complete — update roadmap and state
* docs: phase 6 context — smart discuss decisions
* docs(06): research smart discuss phase domain
* docs(06): create phase plan
* feat(06-01): replace Skill(discuss-phase) with inline smart discuss
- Add <step name="smart_discuss"> with 5 sub-steps: load prior context, scout codebase, analyze phase with infrastructure detection, present proposals per area in tables, write CONTEXT.md
- Rewire execute_phase step 3a: check has_context before/after, reference smart_discuss inline
- Remove Skill(gsd:discuss-phase) call entirely
- Preserve Skill(gsd:plan-phase) and Skill(gsd:execute-phase) calls unchanged
- Update success criteria to mention smart discuss
- Grey area proposals use table format with recommended/alternative columns
- AskUserQuestion offers Accept all, Change QN, Discuss deeper per area
- Infrastructure phases auto-detected and skip to minimal CONTEXT.md
- CONTEXT.md output uses identical XML-wrapped sections as discuss-phase.md
* docs(06-01): complete smart discuss inline logic plan
* docs(07): phase execution chain context — flag strategy, validation routing, error recovery
* docs(07): research phase execution chain domain
* docs(07): create phase plan
* feat(07-01): wire phase execution chain with verification routing
- Add --no-transition flag to execute-phase Skill() call in step 3c
- Replace step 3d transition with VERIFICATION.md-based routing
- Route on passed/human_needed/gaps_found with appropriate user prompts
- Add gap closure cycle with 1-retry limit to prevent infinite loops
- Route execute-phase failures (no VERIFICATION.md) to handle_blocker
- Update success_criteria with all new verification behaviors
* docs(07-01): complete phase execution chain plan
* docs(08): multi-phase orchestration & lifecycle context
* docs(08): research phase domain
* docs(08): create phase plan
* feat(08-01): add lifecycle step, fix progress bar, document smart_discuss
- Add lifecycle step (audit→complete→cleanup) after all phases complete
- Fix progress bar N/T to use phase number/total milestone phases
- Add smart_discuss CTRL-03 compliance documentation note
- Rewire iterate step to route to lifecycle instead of manual banner
- Renumber handle_blocker from step 5 to step 6
- Add 10 lifecycle-related items to success criteria
- File grows from 630 to 743 lines, 6 to 7 named steps
* docs(08-01): complete multi-phase orchestration & lifecycle plan
* docs: v1.24 milestone audit — passed (18/18 requirements)
* chore: complete v1.24 milestone — Autonomous Skill
* chore: archive phase directories from v1.24 milestone
* gsd: clean
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
||
|
|
14f9637538 |
fix: use roadmap_complete checkbox to override disk_status (#978)
When ROADMAP.md marks a phase as [x] complete, trust that over the disk file structure. Phases completed before GSD tracking started (or via external tools) may lack PLAN/SUMMARY pairs but are still done — the roadmap checkbox is the higher-authority signal. Without this fix, completed phases show as "discussed" or "planned" in /gsd:progress, causing incorrect routing and progress percentages. Fixes #977 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
bc77456204 |
fix: handle multi-level decimal phases and escape regex in phase operations (#720)
Phase number parsing only matched single-decimal (e.g. 03.2) but crashed
on multi-level decimals (e.g. 03.2.1). Requirement IDs with regex
metacharacters (parentheses, dots) were interpolated raw into RegExp
constructors, causing SyntaxError crashes.
- Add escapeRegex() utility for safe regex interpolation
- Update normalizePhaseName/comparePhaseNum for multi-level decimals
- Replace all .replace('.', '\\.') with escapeRegex() across modules
- Escape reqId before regex interpolation in cmdPhaseComplete
- Update all phase dir matching regexes from (?:\.\d+)? to (?:\.\d+)*
- Add regression test for phase complete 03.2.1
Closes #621
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
3704829aa6 |
fix: clamp progress bar percent to prevent RangeError crash (#715)
When orphaned SUMMARY.md files cause totalSummaries > totalPlans, the progress percentage exceeds 100%, making String.repeat() throw RangeError on negative arguments. Clamp percent to Math.min(100, ...) at all three computation sites (state, commands, roadmap). Closes #633 Co-authored-by: vinicius-tersi <vinicius-tersi@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
ed11f41ff2 |
Merge branch 'main' into fix/universal-phase-number-support
Rebased PR #639 onto refactored modular structure (lib/core.cjs, lib/phase.cjs, etc.) Changes ported from monolithic gsd-tools.cjs to new modules: - Add comparePhaseNum() helper to lib/core.cjs for universal phase sorting - Update normalizePhaseName() regex to handle letter-suffix phases (12A, 12B) - Update all phase-matching regexes across lib/*.cjs with [A-Z]? pattern - Replace parseFloat-based sorting with comparePhaseNum throughout - Add 15 new tests for comparePhaseNum, normalizePhaseName, and letter-suffix sorting Sort order: 12 → 12.1 → 12.2 → 12A → 12A.1 → 12A.2 → 12B → 13 Co-Authored-By: vinicius-tersi <MDQ6VXNlcjUyNDk2NDYw> |
||
|
|
c67ab759a7 |
refactor: split gsd-tools.cjs into 11 domain modules under bin/lib/
Break the 5324-line monolith into focused modules: - core.cjs: shared utilities, constants, internal helpers - frontmatter.cjs: YAML frontmatter parsing/serialization/CRUD - state.cjs: STATE.md operations + progression engine - phase.cjs: phase CRUD, query, and lifecycle - roadmap.cjs: roadmap parsing and updates - verify.cjs: verification suite + consistency/health validation - config.cjs: config ensure/set/get - template.cjs: template selection and fill - milestone.cjs: milestone + requirements lifecycle - commands.cjs: standalone utility commands - init.cjs: compound init commands for workflow bootstrapping gsd-tools.cjs is now a thin CLI router (~550 lines including JSDoc) that imports from lib/ modules. All 81 tests pass. Also updates package.json test script to point to tests/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |