Files
msd-core/sdk
Ben Lamm 19041b8824 test(#2641): lockdown tests from self-adversarial pass
Self-run adversarial pass on PR #3046 before next reviewer round-trip.
Three lockdown tests added — none uncovered new bugs, all lock current
behavior so a future change doesn't silently flip a convention.

1. Single-quote YAML version (`milestone: 'v0.9'`)
   Parity with the existing double-quote test. The strip pattern
   `/^["']|["']$/g` handles both — locked here so a future change to
   either character class doesn't silently regress one form.

2. Heading-anchor wins over <details> fallback (precedence lock)
   When a ROADMAP has BOTH `### v0.9` heading AND
   `<details><summary>v0.9</summary>` block, the heading-level lookup
   matches first and the fallback never fires. Test asserts the heading
   slice is returned starting at offset 0 AND the synthesized
   `## v0.9 ... details-anchored` heading is NOT prepended (proves
   fallback didn't run). Also documented in-test that the heading-anchor
   slice naturally includes downstream <details> blocks verbatim — a
   property of the heading path, not of this PR's fallback.

3. Multiple <details> blocks for same version → first match wins
   `content.match(detailsPattern)` (non-`g`) returns first match in
   document order. Locked so a future change to the matcher (e.g.
   switching to `matchAll` and picking last) doesn't silently change
   which block is treated as active.

Adversarial-checklist coverage on commit 781cc6f8:
- Boundary cases: empty / whitespace / single-char / single-quote /
  double-quote / digit-suffix (`v0.91`) / dot-suffix (`v0.9.0`) /
  hyphen-suffix (`v0.9-rc.1`, intentional same-milestone match per
  existing currentVersionStr convention) — all covered.
- Sibling consistency: parseMilestoneFromState, getMilestoneInfo,
  extractCurrentMilestone all strip quotes identically.
- Comment-vs-behavior: walked nested-guard, empty-guard, lookahead,
  tag-strip by hand against the regex; all comments accurate.
- Downstream consumers: roadmapAnalyze + roadmapGetPhase both verified
  end-to-end via tests + FAMP smoke.
- Failure-mode locality: all fall-through paths produce loud failures
  (empty arrays, `{found:false}`); no silent confident-wrong outputs.

48/48 roadmap.test.ts tests pass.
2026-05-06 15:41:27 -04:00
..

@gsd-build/sdk

TypeScript SDK for Get Shit Done: deterministic query/mutation handlers, plan execution, and event-stream telemetry so agents focus on judgment, not shell plumbing.

Install

npm install @gsd-build/sdk

Quickstart — programmatic

import { GSD, createRegistry } from '@gsd-build/sdk';

const gsd = new GSD({ projectDir: process.cwd(), sessionId: 'my-run' });
const tools = gsd.createTools();

const registry = createRegistry(gsd.eventStream, 'my-run');
const { data } = await registry.dispatch('state.json', [], process.cwd());

Quickstart — CLI

From a project that depends on this package, invoke the CLI with Node (recommended in CI and local dev):

node ./node_modules/@gsd-build/sdk/dist/cli.js query state.json
node ./node_modules/@gsd-build/sdk/dist/cli.js query roadmap.analyze

If no native handler is registered for a command, the CLI can transparently shell out to get-shit-done/bin/gsd-tools.cjs (see stderr warning), unless GSD_QUERY_FALLBACK=off.

What ships

Area Entry
Query registry createRegistry() in src/query/index.ts — same handlers as gsd-sdk query
Tools bridge GSDTools — native dispatch with optional CJS subprocess fallback
Orchestrators PhaseRunner, InitRunner, GSD
CLI gsd-sdk — query, run, init, auto

Guides

  • Handler registry & contracts: src/query/QUERY-HANDLERS.md
  • Repository docs (when present): docs/ARCHITECTURE.md, docs/CLI-TOOLS.md at repo root

Environment

Variable Purpose
GSD_QUERY_FALLBACK off / never disables CLI fallback to gsd-tools.cjs for unknown commands
GSD_AGENTS_DIR Override directory scanned for installed GSD agents (~/.claude/agents by default)