Files
msd-core/sdk
Tom Boucher ac34ab2cec fix(3587): address codex-review findings on PR #3611
Codex review surfaced 2 MED + 2 LOW in-scope findings (3 LOW were
pre-existing or out-of-scope, see below); all in-scope items addressed:

1. (MED, test sensitivity) The gh probe test only checked the boolean
   return shape, so a future change that re-introduces shell-string
   execSync for the gh path would pass. Added an
   `architectural-invariant` structural test that reads the production
   source file and asserts:
     - no `execSync(` call appears anywhere in code,
     - no `spawnSync` with `shell: true`,
     - `execFileSync` is the only imported child_process primitive,
     - every options object explicitly pins `shell: false`.
   This is the canonical pattern from CONTRIBUTING.md for invariants
   that behavioral tests can't observe — the defect is the *presence*
   of the shell parsing primitive, not its output.

2. (MED, cross-platform) The execFileSync options didn't explicitly pin
   `shell: false`. Default is already false, but spelling it out (a)
   documents the architectural invariant at the call site, (b) prevents
   a future options-spread refactor from silently flipping it, and
   (c) hardens against a Windows `git.cmd` shim path that could
   otherwise route through cmd.exe.

3. (LOW, test visibility) The exploit-blocked test silently `return`ed
   when git rejected the payload branch name on a stricter platform,
   turning a coverage loss into a stealth pass. Replaced with vitest's
   `ctx.skip()` so a lane that loses coverage now shows up in the skip
   count.

Out of scope, intentionally not changed:
- The `try/finally` at sdk/src/query/check-ship-ready.test.ts:79 is
  pre-existing test code from before this PR. One-concern-per-PR rule
  says no drive-by cleanup.
- The "use createTempGitProject helper" suggestion: that helper lives
  in tests/helpers.cjs (root, node:test world). SDK tests use vitest
  with their own ad-hoc tmpdir pattern; matching the SDK convention.
- The afterEach cleanup uses `rm` directly, matching the surrounding
  SDK test convention; not changing without broader SDK-side refactor.

Validation:
- SDK unit suite via vitest: 1,870/1,870 pass (+1 invariant test).
- Full root suite via gsd-test-both: 10,676/10,676 Mac AND Linux Docker,
  zero cross-platform diff.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:51:05 -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)