4471459ea13d8be89de0ea82d8906ae7bc62fa79
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8090456b66 |
feat(3555): QueryRuntimeBridge.executeForCjs synchronous primitive (Phase 5.0 of #3524)
Phase 5.0 of the CJS↔SDK hard-seam migration (parent #3524). Foundational PR. Ships ONLY the synchronous primitive on the SDK runtime bridge plus pinning tests. Per-family CJS router migrations (state.*, verify.*, init.*, phase.*, phases.*, validate.*, roadmap.*, frontmatter.*, config.*) become follow-up enhancements that each reuse this primitive. ## What landed - sdk/src/runtime-bridge-sync/index.ts (155 lines) — public API. Exports executeForCjs(input: RuntimeBridgeExecuteInput): RuntimeBridgeSyncResult. Synchronous; lazily creates the synckit sync function on first call. - sdk/src/runtime-bridge-sync/worker.ts (167 lines) — synckit worker. Constructs a native-only QueryRuntimeBridge (with allowFallbackToSubprocess: false), awaits its async execute, catches GSDToolsError / GSDError, maps classification to the six ADR-0001 canonical error kinds plus exit code. - sdk/src/runtime-bridge-sync/index.test.ts (197 lines, 8 vitest pinning fixtures) — success path; unknown_command; native_failure (shape); validation_error (shape); shape invariants; idempotency. - tests/runtime-bridge-sync-smoke.test.cjs (99 lines, 4 node:test cases) — proves the primitive works from CJS callers via require(). ## Decisions 1. Synchronous-bridging mechanism: synckit. Disqualified: - deasync: stagnant (68 open issues, single maintainer, last release Nov 2025), private Node API (process.binding('uv')), untested on Node 22, documented deadlocks with modern Promise chains. - Sync-native SDK refactor: technically infeasible — acquireStateLock in state-mutation.ts uses await setTimeout for retry backoff; making that fully sync requires either Atomics.wait (which IS synckit), busy-loop (degrades responsiveness), or breaking 100+ SDK consumers. Synckit (v0.11.12) is pure JS, actively maintained (last push today), stable public APIs (Atomics.wait + SharedArrayBuffer), Node 22 compatible, no native compile. 2. Native-only transport inside the worker. The sync bridge uses allowFallbackToSubprocess: false. Unknown commands surface as unknown_command instead of spawning gsd-sdk. Keeps the worker self-contained and predictable. 3. Worker path resolution. resolveWorkerPath() navigates ../.. from the loaded module URL to land at dist/runtime-bridge-sync/worker.js — works under both vitest (loads src) and CJS consumers (load dist). 4. GSDError.Blocked → validation_error. ADR-0001's 6-kind taxonomy has no `blocked` kind; Blocked classification is mapped onto validation_error since the operational shape matches (prerequisite missing). ## Numbers - 8 SDK vitest pinning tests pass. - 4 CJS smoke tests pass. - Full suite: 9286/9286 pass (baseline 9282; +4 from the new smoke test cases). - SDK vitest unit: 1860/1860 pass. - Performance: 80ms first-call cold latency (Worker startup + bridge construction); 0.1ms steady-state per-call latency (10-call average after warmup). Well within budget for CJS dispatcher overhead. ## Canonical error kind coverage - unknown_command: covered with pinning fixture - native_failure: shape coverage (handler that throws) - validation_error: shape coverage (GSDError.Validation + GSDError.Blocked) - internal_error: shape coverage only (eliciting TypeError reliably from a registered handler requires elaborate fixture) - native_timeout: NOT pinned (no registered handler genuinely times out; classification logic present in worker) - fallback_failure: NOT pinned (subprocess fallback disabled by design in sync bridge) The classification logic is in the worker regardless; per-family migration PRs will exercise the unpinned kinds incidentally. ## Wiring - sdk/package.json: synckit ^0.11.12 added as runtime dependency (not devDependency — it's required at runtime whenever a CJS caller invokes executeForCjs). - sdk/package-lock.json: regenerated. - CONTEXT.md: new "Sync Runtime Bridge Module" entry added after Dispatch Policy Module. Existing "CJS Command Router Adapter Module" entry amended with one sentence pointing at the primitive and the per-family migration roadmap. No generator/freshness check needed for this phase — the primitive IS the SDK (not a generated CJS mirror). Closes #3555. |
||
|
|
a3ca6ff6d6 |
feat(3553): Project-Root Resolution Module via generator (Phase 4 of #3524)
Phase 4 of the CJS↔SDK hard-seam migration (parent #3524). Eliminates the `findProjectRoot` duplication that lived at bin/lib/core.cjs:74-140 and sdk/src/query/helpers.ts:497-590, the drift carrier behind historical bugs #1362 and #2561. - sdk/src/project-root/index.ts — source of truth (120 lines, pure-with-sync-fs). Exports findProjectRoot(startDir: string) and FIND_PROJECT_ROOT_MAX_DEPTH constant. - sdk/src/project-root/index.test.ts — 13 vitest pinning fixtures covering all four heuristics, the #1362 guard, malformed config fallback, empty sub_repos, deep nesting, and depth-limit enforcement. - sdk/scripts/gen-project-root.mjs — generator. Captures function body via Function.prototype.toString() from compiled sdk/dist/. Emits CJS preamble for destructured node:fs / node:path / node:os imports. - sdk/scripts/check-project-root-fresh.mjs — freshness check. Imports the generator function directly (Phase 3's cleaner pattern). - get-shit-done/bin/lib/project-root.generated.cjs — generator- emitted CJS mirror. - tests/project-root-generator.test.cjs — 11 parity assertions comparing SDK source and generated CJS for every fixture. - sdk/src/query/helpers.ts: -127 lines. The 94-line inline findProjectRoot plus the FIND_PROJECT_ROOT_MAX_DEPTH constant (originally at line 471) replaced by a single re-export: `export { findProjectRoot } from '../project-root/index.js';` Removed unused `parse as parsePath` import. - get-shit-done/bin/lib/core.cjs: -83 lines net. The 67-line inline findProjectRoot replaced by a single `require('./project-root.generated.cjs')`. The detectSubRepos helper at lines 40-56 stays (used by loadConfig migration). - sdk/package.json: gen:project-root + check:project-root-fresh scripts. - package.json: proxy for the freshness check. - .githooks/pre-commit: drift block. - .github/workflows/test.yml: drift check step after the state-document drift step. - CONTEXT.md: Project-Root Resolution Module entry. - docs/INVENTORY.md, docs/INVENTORY-MANIFEST.json: +1 module count, +1 row. - Full suite: 9226/9226 pass (baseline 9215 + 11 new parity fixtures). - SDK vitest: 1804/1804 pass. - Reader shrink: -127 SDK + -83 CJS = 210 lines of duplication deleted across the two Readers. New shared Module is 120 lines. 1. Depth limit canonicalization. CJS findProjectRoot previously had no explicit walk-up bound (walked until dir === root or homedir). The new Module uses FIND_PROJECT_ROOT_MAX_DEPTH = 10, matching the SDK's pre-existing value. Only affects paths nested more than 10 levels deep from a .planning/ root — a pathological case in practice. None of the existing 22 CJS findProjectRoot tests covered this; the new parity test does. 2. platformReadSync → readFileSync. The old CJS findProjectRoot used the platformReadSync wrapper from shell-command-projection.cjs for reading .planning/config.json, which returns null on read failure. The Module uses raw readFileSync, which throws — caught by the surrounding try/catch that already swallowed errors. Functionally equivalent for the existing code path; no test exercises the null-return semantic. Closes #3553. |
||
|
|
ed8f4c9a31 |
feat(3544): Workstream Inventory Builder/Reader split (Phase 3 of #3524)
Phase 3 of the CJS↔SDK hard-seam migration (parent #3524). Introduces the Builder/Reader pattern for paired Modules with mixed pure-and-I/O concerns — the template for Phase 4 and follow-up enhancements that migrate other paired Modules. Phase 1 and Phase 2 migrated Modules where both sides used character-equivalent logic. Phase 3 introduces the case where the pure logic is shareable but the I/O is legitimately per-side. The Builder/Reader split resolves this: - The Builder is pure — accepts pre-collected data (BuilderInputs struct), returns the typed projection. One source of truth; one generator-emitted CJS mirror. Drift is structurally impossible. - The Readers are per-side hand-authored Adapters that do the fs reads in their native idiom (currently both sync; either side can go async later without touching the Builder), then delegate to the Builder. - sdk/src/workstream-inventory/builder.ts — Builder source. 170 lines. Pure. Exports buildWorkstreamInventory(inputs), isCompletedInventory(status), plus the three typed inventory interfaces (WorkstreamPhaseInventory, WorkstreamInventory, WorkstreamInventoryList). - sdk/src/workstream-inventory/builder.test.ts — 18 vitest pinning fixtures across all status branches, progress-percent clamping, active-marker projection, and isCompletedInventory classifier. - sdk/scripts/gen-workstream-inventory-builder.mjs — generator. Captures function bodies via Function.prototype.toString(); emits with the standard GENERATED FILE banner. Includes a small `const relative = path.relative;` preamble in the output to handle ESM destructured imports in the compiled source. - sdk/scripts/check-workstream-inventory-builder-fresh.mjs — freshness check. Imports the generator function directly (rather than duplicating logic) — a cleaner pattern than Phase 1/2's approach. - get-shit-done/bin/lib/workstream-inventory-builder.generated.cjs — generator-emitted CJS mirror. - tests/workstream-inventory-builder-generator.test.cjs — 16 parity assertions confirming CJS-generated output == SDK source output for every fixture. - bin/lib/workstream-inventory.cjs: 159 → 132 lines. Projection logic gone. `inspectWorkstream` and `listWorkstreamInventories` collect BuilderInputs via the existing sync fs functions and delegate to the Builder. `isCompletedInventory` re-exported from the Builder (its signature changed from object→string, but no external callers exist so the change is safe). - sdk/src/query/workstream-inventory.ts: 196 → 143 lines. Same shape, sync fs (the SDK was already sync — surprise from recon). Types re-exported from the Builder. - sdk/package.json: gen:workstream-inventory-builder and check:workstream-inventory-builder-fresh scripts. - package.json: proxy for the freshness check. - .githooks/pre-commit: drift block. - .github/workflows/test.yml: drift check step. - CONTEXT.md: amended "Workstream Inventory Module" entry to document the Builder/Reader split. - docs/INVENTORY.md, docs/INVENTORY-MANIFEST.json: +1 module count, +1 row for the generated builder. - Full suite: 9229/9229 pass (baseline 9215 + 14 net new from the parity assertions). - Vitest: 18 Builder fixtures pass. - Reader shrink: -27 lines on CJS, -53 lines on SDK. - Net diff (modified files only): +68 / -133 = 65-line reduction. New files (Builder, generator, freshness check, parity test) add ~600 lines of new structured code. 1. `isCompletedInventory` signature changed from isCompletedInventory(inventory: object) to isCompletedInventory(status: string). Original CJS exported the object form but no external caller passed an object — they all passed inventory.status. Verified by grep before committing. 2. Generator preamble. The compiled ESM uses `import { relative } from 'node:path'`, making `relative` a free variable in `buildWorkstreamInventory`. The generator emits `const relative = path.relative;` so the captured function body works in CJS. 3. Freshness check imports the generator. The freshness check imports the generator's buildWorkstreamInventoryBuilderCjs() function directly rather than duplicating generation logic. Cleaner than Phase 1/2; future generators should follow this. Shareable via the Builder/Reader pattern in future enhancements: - frontmatter (pure YAML/markdown parsing) - plan-scan (pure PLAN.md structure parsing) - decisions (pure decision-record parsing) - secrets (regex-based detection in text) - uat (UAT-criteria parsing) Structural divergence — different approach needed: - state — sync vs async file ops; mutation paths differ. - workstream — lifecycle ops; per-side API surface differs. - phase, roadmap, init, profile-output, template — large surfaces; each its own potential enhancement. None of these is in scope for Phase 3. Closes #3544. |
||
|
|
2de2d185fa |
feat(3536): Configuration Module via shared manifests + generator (Phase 2 of #3524)
Phase 2 of the CJS↔SDK hard-seam migration (parent #3524). Eliminates the structural drift surface that produced bug class After this phase, neither bin/lib/ nor sdk/src/ defines CONFIG_DEFAULTS, VALID_CONFIG_KEYS, DYNAMIC_KEY_PATTERNS, or the four legacy-key normalizations inline. All come from one canonical source: the Configuration Module (sdk/src/configuration/index.ts) + two JSON manifests (sdk/shared/config-{defaults,schema}.manifest.json). The CJS mirror is generator-emitted (get-shit-done/bin/lib/configuration.generated.cjs) with a CI freshness check (sdk/scripts/check-configuration-fresh.mjs). - sdk/shared/config-defaults.manifest.json — canonical nested defaults, union of CJS + SDK keys (includes security_*, post_planning_gaps, agent_skills, mode, every git/workflow/hooks sub-section). - sdk/shared/config-schema.manifest.json — VALID_CONFIG_KEYS array, RUNTIME_STATE_KEYS array, DYNAMIC_KEY_PATTERNS array with source strings (regex reconstructed at runtime). - sdk/src/configuration/index.ts — source of truth. Exports loadConfig (pure read), normalizeLegacyKeys (pure, idempotent, returns Normalization[]), mergeDefaults (deep-merge), migrateOnDisk (explicit opt-in disk writeback), plus CONFIG_DEFAULTS, VALID_CONFIG_KEYS, RUNTIME_STATE_KEYS, DYNAMIC_KEY_PATTERNS. - sdk/src/configuration/index.test.ts — 29 vitest pinning tests. - sdk/scripts/gen-configuration.mjs — generator (Function.prototype.toString() inspection of compiled SDK dist, plus brace-balanced text scan for internal helpers, matching the Phase 1 pattern). - sdk/scripts/check-configuration-fresh.mjs — CI freshness gate. - tests/configuration-generator.test.cjs — 27 parity assertions (CJS-generated == SDK source). - tests/configuration-migrate-config.test.cjs — 3 cases for the new gsd-tools migrate-config subcommand. - bin/lib/core.cjs: CONFIG_DEFAULTS literal now sources values from CANONICAL_CONFIG_DEFAULTS (the manifest), with a thin flat projection at the load boundary to preserve the existing flat-shape return contract for the ~21 CJS test files and 100+ consumers. All four legacy-key migration blocks (branching_strategy, sub_repos, multiRepo, depth — historically lines 351-358, 388-397, 401-408, 416-423) collapse to a single normalizeLegacyKeys call in each code path. The inline platformWriteSync writeback stays for now to preserve sync loadConfig semantics; the new async migrateOnDisk is reachable via gsd-tools migrate-config. - bin/lib/config-schema.cjs: 135 → 31 lines. Re-exports from the generated Module. - bin/lib/config.cjs: adds cmdMigrateConfig handler (calls migrateOnDisk on the explicit user-driven path). - bin/gsd-tools.cjs: wires migrate-config into command dispatch. - sdk/src/config.ts: re-exports CONFIG_DEFAULTS and mergeDefaults from the Module. loadConfig now calls normalizeLegacyKeys before mergeDefaults (replaces the inline branching_strategy graft). - sdk/src/query/config-schema.ts: 160 → 36 lines. Re-exports from the Module. - tests/config-schema-sdk-parity.test.cjs: refactored from "CJS Set equals SDK Set" (trivially true post-migration) to "both sides source from the manifest" — structural plus runtime invariant. - Four other tests that text-grepped source files for valid keys (plan-review-convergence, bug-3212, bug-2492, feat-3210) are updated to use runtime VALID_CONFIG_KEYS.has() or manifest JSON lookups. - CONTEXT.md: new Configuration Module entry with full Interface contract. - Root package.json: check:configuration-fresh proxy script. - sdk/package.json: gen:configuration + check:configuration-fresh. - .githooks/pre-commit: configuration drift block. - .github/workflows/test.yml: configuration drift step after the alias drift check. - 9201 CJS tests pass (baseline pre-cycle: 9195; +6 net new tests across migrate-config + parity refactor) - 1872 SDK vitest tests pass - 29 Configuration Module vitest fixtures - 27 CJS/SDK parity fixtures - Net diff: +388 / −519 = 131-line reduction across the seven cycles, despite adding the new Module, manifests, generator, freshness check, and two new test files. 1. SDK CONFIG_DEFAULTS now includes manifest-canonical keys (resolve_model_ids: false, context_window: 200000, phase_naming, claude_md_path, git.create_tag, workflow.security_*, workflow.code_review_*, planning.*, hooks.workflow_guard, ship.*). Consumers accessing via [key: string]: unknown index get the manifest default instead of undefined. 2. SDK mergeDefaults is now proper recursive deep-merge instead of spread-per-section. Overlay { workflow: { research: false } } now preserves sibling workflow keys; previously it replaced the entire workflow section with only research + the section's defaults. Semantically identical for the common case; strictly better for partial nested overrides. 3. New gsd-tools migrate-config CLI subcommand for the explicit, opt-in on-disk migration path. Closes #3536. |
||
|
|
bfd7ddbad3 |
feat(3530): STATE.md Document Module via generator (Phase 1 of #3524) (#3531)
* feat(3530): STATE.md Document Module via generator (Phase 1 of #3524) Phase 1 of the CJS↔SDK hard-seam migration (parent #3524). Converts the hand-synced state-document.cjs/state-document.ts pair into a generator-driven seam, modeled on the existing command-aliases.generated.* precedent. What landed: - sdk/src/query/state-document.ts is the source of truth. - sdk/scripts/gen-state-document.ts emits get-shit-done/bin/lib/state-document.generated.cjs from the compiled SDK dist via Function.prototype.toString() inspection for the 7 public exports and 3 internal helpers. - sdk/scripts/check-state-document-fresh.mjs is the CI freshness gate; pre-commit hook also runs it when relevant files change. - get-shit-done/bin/lib/state-document.cjs is reduced to a one-line re-export from state-document.generated.cjs so existing callers (state.cjs, workstream-inventory.cjs, init.cjs) need no changes. - New CI step in .github/workflows/test.yml after the existing alias drift check. - sdk/package.json: gen:state-document, check:state-document-fresh scripts. tsx added as devDep. - Root package.json: proxy script for the freshness check. - CONTEXT.md: one-sentence amendment on STATE.md Document Module recording the source-of-truth file path. Tests: - sdk/src/query/state-document.test.ts: 34 vitest fixtures across the 7 public exports (TDD pinning safety net). - tests/state-document-generator.test.cjs: 31 node:test parity assertions comparing SDK source vs generated CJS for every fixture. - Full suite: 9177/9177 pass (baseline was 9146; +31 new tests). One subtle behavior change worth flagging: the old hand-written state-document.cjs used String(str) coercion inside escapeRegex, which the SDK source does not. The generator faithfully matches the SDK (the source of truth per ADR-3524), so the new CJS no longer coerces non-string input to string before regex-escaping. No current caller passes non-string input, so no observable regression in the test suite. Flagged in the PR body for reviewers. Closes #3530. * fix(3530): address state-document review findings |
||
|
|
96806003c5 |
fix(#3229): shared model catalog source of truth for agent profiles + runtime tier defaults (#3230)
* docs(adr): add ADR-0003 model catalog module * fix(#3229): add shared model catalog as source of truth for agent profiles and runtime tier defaults Research / design (ADR-0003): - Existing drift came from 4 independent model truths: 1. CJS model-profiles.cjs 2. SDK config-query.ts stale copy (18 agents) 3. settings-advanced.md runtime tier table 4. session-runner Claude-only profile map - New design: one machine-readable Model Catalog Module in sdk/shared/ that both packages ship and consume. Implementation: - sdk/shared/model-catalog.json — canonical source of truth for: - full 33-agent registry - per-agent golden (quality) alias + balanced/budget aliases - adaptive derivation from routingTier - agent→phaseType map - agent→dynamic-routing default tier map - runtime tier defaults for all supported runtimes - get-shit-done/bin/lib/model-catalog.cjs — CJS adapter over the catalog - sdk/src/model-catalog.ts — SDK adapter over the same catalog - CJS model-profiles.cjs now re-exports derived data from model-catalog.cjs - SDK config-query.ts now re-exports MODEL_PROFILES/VALID_PROFILES from model-catalog.ts instead of maintaining its own list - sdk/src/query/helpers.ts runtime list now comes from the catalog (fixes hermes drift) - sdk/src/session-runner.ts Claude profile→model-id mapping now resolves via catalog - docs/CONFIGURATION.md + settings-advanced.md runtime tables updated to match catalog Behavior changes: - resolve-model now covers every shipped agent file on disk (33 agents) - unknown-agent fallback is profile-semantic, not hardcoded sonnet: quality→opus, budget→haiku, balanced/adaptive→sonnet, inherit→inherit - Group B runtimes remain known runtimes but do not get built-in tier defaults Tests (RED→GREEN): - root tests: shipped agent files must equal MODEL_PROFILES keys - sdk tests: shipped agent files must equal MODEL_PROFILES keys - direct fix assertion: gsd-code-reviewer resolves to opus under quality with no unknown_agent - runtime defaults parity test: settings-advanced.md + CONFIGURATION.md tables must match catalog - helper tests: hermes included in SUPPORTED_RUNTIMES and getRuntimeConfigDir() Closes #3229 * chore(changeset): update #3229 changeset pr field to 3230 * fix(ci): update inherit fallback expectations and inventory parity for model catalog |
||
|
|
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> |
||
|
|
006cdafe8f |
ci(drift): enforce alias freshness checks in CI and contributor flow (#2910)
Merging alias-drift guardrails and local hook hardening. |
||
|
|
f983c95ffc |
Release/1.39.0-rc.4 (#2797)
* chore: bump version to 1.39.0 for release * chore: bump to 1.39.0-rc.1 * chore: bump to 1.39.0-rc.2 * chore: bump to 1.39.0-rc.3 * chore: bump to 1.39.0-rc.4 * docs: add v1.39.0-rc.4 release notes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
0a049149e1 |
fix(sdk): decouple from build-from-source install, close #2441 #2453 (#2457)
* fix(sdk): decouple SDK from build-from-source install path, close #2441 and #2453 Ship sdk/dist prebuilt in the tarball and replace the npm-install-g sub-install with a parent-package bin shim (bin/gsd-sdk.js). npm chmods bin entries from a packed tarball correctly, eliminating the mode-644 failure (#2453) and the full class of NPM_CONFIG_PREFIX/ignore-scripts/ corepack/air-gapped failure modes that caused #2439 and #2441. Changes: - sdk/package.json: prepublishOnly runs `rm -rf dist && tsc && chmod +x dist/cli.js` (stale-build guard + execute-bit fix at publish time) - package.json: add "gsd-sdk": "bin/gsd-sdk.js" bin entry; add sdk/dist to files so the prebuilt CLI ships in the tarball - bin/gsd-sdk.js: new back-compat shim — resolves sdk/dist/cli.js relative to the package root and delegates via `node`, so all existing PATH call sites (slash commands, agents, hooks) continue to work unchanged (S1 shim) - bin/install.js: replace installSdkIfNeeded() build-from-source + global- install dance with a dist-verify + chmod-in-place guard; delete resolveGsdSdk(), detectShellRc(), emitSdkFatal() helpers now unused - .github/workflows/install-smoke.yml: add smoke-unpacked job that strips execute bit from sdk/dist/cli.js before install to reproduce the exact #2453 failure mode - tests/bug-2441-sdk-decouple.test.cjs: new regression tests asserting all invariants (no npm install -g from sdk/, shim exists, sdk/dist in files, prepublishOnly has rm -rf + chmod) - tests/bugs-1656-1657.test.cjs: update stale assertions that required build-from-source behavior (now asserts new prebuilt-dist invariants) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): bump to 1.38.2, wire release.yml to build SDK dist - Bump version 1.38.1 -> 1.38.2 for the #2441/#2453 fix shipped in 0f6903d. - Add `build:sdk` script (`cd sdk && npm ci && npm run build`). - `prepublishOnly` now runs hooks + SDK builds as a safety net. - release.yml (rc + finalize): build SDK dist before `npm publish` so the published tarball always ships fresh `sdk/dist/` (kept gitignored). - CHANGELOG: document 1.38.2 entry and `--sdk` flag semantics change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: build SDK dist before tests and smoke jobs sdk/dist/ is gitignored (built fresh at publish time via release.yml), but both the test suite and install-smoke jobs run `bin/install.js` or `npm pack` against the checked-out tree where dist doesn't exist yet. - test.yml: `npm run build:sdk` before `npm run test:coverage`, so tests that spawn `bin/install.js` don't hit `installSdkIfNeeded()`'s fatal missing-dist check. - install-smoke.yml (both smoke and smoke-unpacked): build SDK before pack/chmod so the published tarball contains dist and the unpacked install has a file to strip exec-bit from. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(sdk): lift SDK runtime deps to parent so tarball install can resolve them The SDK's runtime deps (ws, @anthropic-ai/claude-agent-sdk) live in sdk/package.json, but sdk/node_modules is NOT shipped in the parent tarball — only sdk/dist, sdk/src, sdk/prompts, and sdk/package.json are. When a user runs `npm install -g get-shit-done-cc`, npm installs the parent's node_modules but never runs `npm install` inside the nested sdk/ directory. Result: `node sdk/dist/cli.js` fails with ERR_MODULE_NOT_FOUND for 'ws'. The smoke tarball job caught this; the unpacked variant masked it because `npm install -g <dir>` copies the entire workspace including sdk/node_modules (left over from `npm run build:sdk`). Fix: declare the same deps in the parent package.json so they land in <pkg>/node_modules, which Node's resolution walks up to from <pkg>/sdk/dist/cli.js. Keep them declared in sdk/package.json too so the SDK remains a self-contained package for standalone dev. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(lockfile): regenerate package-lock.json cleanly The previous `npm install` run left the lockfile internally inconsistent (resolved esbuild@0.27.7 referenced but not fully written), causing `npm ci` to fail in CI with "Missing from lock file" errors. Clean regen via rm + npm install fixes all three failed jobs (test, smoke, smoke-unpacked), which were all hitting the same `npm ci` sync check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(deps): remove unused esbuild + vitest from root devDependencies Both were declared but never imported anywhere in the root package (confirmed via grep of bin/, scripts/, tests/). They lived in sdk/ already, which is the only place they're actually used. The transitive tree they pulled in (vitest → vite → esbuild 0.28 → @esbuild/openharmony-arm64) was the root of the CI npm ci failures: the openharmony platform package's `optional: true` flag was not being applied correctly by npm 10 on Linux runners, causing EBADPLATFORM. After removal: 800+ transitive packages → 155. Lockfile regenerated cleanly. All 4170 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(sdk): pretest:coverage builds sdk; tighten shim test assertions Add "pretest:coverage": "npm run build:sdk" so npm run test:coverage works in clean checkouts where sdk/dist/ hasn't been built yet. Tighten the two loose shim assertions in bug-2441-sdk-decouple.test.cjs: - forwards-to test now asserts path.resolve() is called with the 'sdk','dist','cli.js' path segments, not just substring presence - node-invocation test now asserts spawnSync(process.execPath, [...]) pattern, ruling out matches in comments or the shebang line Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address PR review — pretest:coverage + tighten shim tests Review feedback from trek-e on PR 2457: 1. pretest:coverage + pretest hooks now run `npm run build:sdk` so `npm run test[:coverage]` in a clean checkout produces the required sdk/dist/ artifacts before running the installer-dependent tests. CI already does this explicitly; local contributors benefit. 2. Shim tests in bug-2441-sdk-decouple.test.cjs tightened from loose substring matches (which would pass on comments/shebangs alone) to regex assertions on the actual path.resolve call, spawnSync with process.execPath, process.argv.slice(2), and process.exit pattern. These now provide real regression protection for #2453-class bugs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: correct CHANGELOG entry and add [1.38.2] reference link Two issues in the 1.38.2 CHANGELOG entry: - installSdkIfNeeded() was described as deleted but it still exists in bin/install.js (repurposed to verify sdk/dist/cli.js and fix execute bit). Corrected the description to say 'repurposes' rather than 'deletes'. - The reference-link block at the bottom of the file was missing a [1.38.2] compare URL and [Unreleased] still pointed to v1.37.1...HEAD. Added the [1.38.2] link and updated [Unreleased] to compare/v1.38.2...HEAD. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(sdk): double-cast WorkflowConfig to Record for strict tsc build TypeScript error on main (introduced in #2611) blocks `npm run build` in sdk/, which now runs as part of this PR's tarball build path. Apply the double-cast via `unknown` as the compiler suggests. Same fix as #2622; can be dropped if that lands first. * test: remove bug-2598 test obsoleted by SDK decoupling The bug-2598 test guards the Windows CVE-2024-27980 fix in the old build-from-source path (npm spawnSync with shell:true + formatSpawnFailure diagnostics). This PR removes that entire code path — installSdkIfNeeded no longer spawns npm, it just verifies the prebuilt sdk/dist/cli.js shipped in the tarball. The test asserts `installSdkIfNeeded.toString()` contains a formatSpawnFailure helper. After decoupling, no such helper exists (nothing to format — there's no spawn). Keeping the test would assert invariants of the rejected architecture. The original #2598 defect (silent failure of npm spawn on Windows) is structurally impossible in the shim path: bin/gsd-sdk.js invokes `node sdk/dist/cli.js` directly via child_process.spawn with an explicit argv array. No .cmd wrapper, no shell delegation. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Tom Boucher <trekkie@nomorestars.com> |
||
|
|
e3f40201dd |
fix(sdk): bump engines.node from >=20 to >=22.0.0 (#2465)
Node 20 reaches EOL April 30 2026. The root package already declares >=22.0.0 and CI only runs Node 22 and 24. Align sdk/package.json so `npm install` on Node 20 fails with a clear engines mismatch rather than a silent install that breaks at runtime. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
89f95c43ba |
feat: auto --init flag, headless prompts, and prompt sanitizer (#1417)
* fix: Created 10 headless prompt files (5 workflows + 5 agents) in sdk/p… - "sdk/prompts/workflows/execute-plan.md" - "sdk/prompts/workflows/research-phase.md" - "sdk/prompts/workflows/plan-phase.md" - "sdk/prompts/workflows/verify-phase.md" - "sdk/prompts/workflows/discuss-phase.md" - "sdk/prompts/agents/gsd-executor.md" - "sdk/prompts/agents/gsd-phase-researcher.md" - "sdk/prompts/agents/gsd-planner.md" GSD-Task: S01/T02 * feat: Created prompt-sanitizer.ts, wired headless prompt loading into P… - "sdk/src/prompt-sanitizer.ts" - "sdk/src/phase-prompt.ts" - "sdk/src/gsd-tools.ts" - "sdk/src/gsd-tools.test.ts" - "sdk/src/phase-runner-types.test.ts" GSD-Task: S01/T01 * test: Added 111 unit tests covering sanitizePrompt(), headless prompt l… - "sdk/src/prompt-sanitizer.test.ts" - "sdk/src/headless-prompts.test.ts" - "sdk/src/phase-prompt.test.ts" GSD-Task: S01/T03 * feat: Wired sdkPromptsDir preference and sanitizePrompt into InitRunner… - "sdk/src/init-runner.ts" - "sdk/package.json" GSD-Task: S02/T01 * feat: add --init flag to auto command for single-command PRD-to-execution gsd-sdk auto --init @path/to/prd.md now bootstraps the project (init) then immediately runs the autonomous phase execution loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: add remaining headless prompt files and templates Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: Extended init-runner.test.ts with 7 sdkPromptsDir preference and… - "sdk/src/init-runner.test.ts" GSD-Task: S02/T03 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
596ce2d252 |
feat: GSD SDK — headless CLI with init + auto commands (#1407)
* test: Bootstrapped sdk/ as TypeScript ESM package with full GSD-1 PLAN.… - "sdk/package.json" - "sdk/tsconfig.json" - "sdk/vitest.config.ts" - "sdk/src/types.ts" - "sdk/src/plan-parser.ts" - "sdk/src/plan-parser.test.ts" GSD-Task: S01/T01 * test: Implemented config reader and gsd-tools bridge with 25 unit tests… - "sdk/src/config.ts" - "sdk/src/config.test.ts" - "sdk/src/gsd-tools.ts" - "sdk/src/gsd-tools.test.ts" GSD-Task: S01/T02 * test: Built prompt-builder, session-runner, and GSD class — 85 total un… - "sdk/src/prompt-builder.ts" - "sdk/src/prompt-builder.test.ts" - "sdk/src/session-runner.ts" - "sdk/src/index.ts" - "sdk/src/types.ts" GSD-Task: S01/T03 * test: Created E2E integration test with fixtures proving full SDK pipel… - "sdk/src/e2e.integration.test.ts" - "sdk/test-fixtures/sample-plan.md" - "sdk/test-fixtures/.planning/config.json" - "sdk/test-fixtures/.planning/STATE.md" - "vitest.config.ts" - "tsconfig.json" GSD-Task: S01/T04 * test: Added PhaseType/GSDEventType enums, 16-variant GSDEvent union, GS… - "sdk/src/types.ts" - "sdk/src/event-stream.ts" - "sdk/src/logger.ts" - "sdk/src/event-stream.test.ts" - "sdk/src/logger.test.ts" GSD-Task: S02/T01 * test: Built ContextEngine for phase-aware context file resolution, getT… - "sdk/src/context-engine.ts" - "sdk/src/tool-scoping.ts" - "sdk/src/phase-prompt.ts" - "sdk/src/context-engine.test.ts" - "sdk/src/tool-scoping.test.ts" - "sdk/src/phase-prompt.test.ts" GSD-Task: S02/T02 * test: Wired event stream into session runner, added onEvent()/addTransp… - "sdk/src/session-runner.ts" - "sdk/src/index.ts" - "sdk/src/e2e.integration.test.ts" GSD-Task: S02/T03 * feat: Added PhaseStepType enum, PhaseOpInfo interface, phase lifecycle… - "sdk/src/types.ts" - "sdk/src/gsd-tools.ts" - "sdk/src/session-runner.ts" - "sdk/src/index.ts" - "sdk/src/phase-runner-types.test.ts" GSD-Task: S03/T01 * test: Implemented PhaseRunner state machine with 39 unit tests covering… - "sdk/src/phase-runner.ts" - "sdk/src/phase-runner.test.ts" GSD-Task: S03/T02 * test: Wired PhaseRunner into GSD.runPhase() public API with full re-exp… - "sdk/src/index.ts" - "sdk/src/phase-runner.integration.test.ts" - "sdk/src/phase-runner.ts" GSD-Task: S03/T03 * test: Expanded runVerifyStep with full gap closure cycle (plan → execut… - "sdk/src/types.ts" - "sdk/src/phase-runner.ts" - "sdk/src/phase-runner.test.ts" GSD-Task: S04/T02 * fix: Added 3 integration tests proving phasePlanIndex returns correct t… - "sdk/src/phase-runner.integration.test.ts" - "sdk/src/index.ts" GSD-Task: S04/T03 * test: Add milestone-level types, typed roadmapAnalyze(), GSD.run() orch… - "sdk/src/types.ts" - "sdk/src/gsd-tools.ts" - "sdk/src/index.ts" - "sdk/src/milestone-runner.test.ts" GSD-Task: S05/T01 * test: Added CLITransport (structured stdout log lines) and WSTransport… - "sdk/src/cli-transport.ts" - "sdk/src/cli-transport.test.ts" - "sdk/src/ws-transport.ts" - "sdk/src/ws-transport.test.ts" - "sdk/src/index.ts" - "sdk/package.json" GSD-Task: S05/T02 * test: Added gsd-sdk CLI entry point with argument parsing, bin field, p… - "sdk/src/cli.ts" - "sdk/src/cli.test.ts" - "sdk/package.json" GSD-Task: S05/T03 * feat: Add InitNewProjectInfo type, initNewProject()/configSet() GSDTool… - "sdk/src/types.ts" - "sdk/src/gsd-tools.ts" - "sdk/src/cli.ts" - "sdk/src/cli.test.ts" - "sdk/src/gsd-tools.test.ts" GSD-Task: S01/T01 * chore: Created InitRunner orchestrator with setup → config → PROJECT.md… - "sdk/src/init-runner.ts" - "sdk/src/types.ts" - "sdk/src/index.ts" GSD-Task: S01/T02 * test: Wired InitRunner into CLI main() for full gsd-sdk init dispatch a… - "sdk/src/cli.ts" - "sdk/src/init-runner.test.ts" - "sdk/src/cli.test.ts" GSD-Task: S01/T03 * test: Add PlanCheck step, AI self-discuss, and retryOnce wrapper to Pha… - "sdk/src/types.ts" - "sdk/src/phase-runner.ts" - "sdk/src/session-runner.ts" - "sdk/src/phase-runner.test.ts" - "sdk/src/phase-runner-types.test.ts" GSD-Task: S02/T01 * feat: Rewrite CLITransport with ANSI colors, phase banners, spawn indic… - "sdk/src/cli-transport.ts" - "sdk/src/cli-transport.test.ts" GSD-Task: S02/T02 * test: Add `gsd-sdk auto` command with autoMode config override, USAGE t… - "sdk/src/cli.ts" - "sdk/src/cli.test.ts" - "sdk/src/index.ts" - "sdk/src/types.ts" GSD-Task: S02/T03 * fix: CLI shebang + gsd-tools non-JSON output handling Three bugs found during first real gsd-sdk run: 1. cli.ts shebang was commented out — shell executed JS as bash, triggering ImageMagick's import command instead of Node 2. configSet() called exec() which JSON.parse()d the output, but gsd-tools config-set returns 'key=value' text, not JSON. Added execRaw() method for commands that return plain text. 3. Same JSON parse bug affected commit() (returns git SHA), stateLoad(), verifySummary(), initExecutePhase(), stateBeginPhase(), and phaseComplete(). All switched to execRaw(). Tests updated to match real gsd-tools output format (plain text instead of mocked JSON). 376/376 tests pass. |