* feat(sdk): golden parity harness and query handler CJS alignment (#2302 Track A) Golden/read-only parity tests and registry alignment, query handler fixes (check-completion, state-mutation, commit, validate, summary, etc.), and WAITING.json dual-write for .gsd/.planning readers. Refs gsd-build/get-shit-done#2341 * fix(sdk): getMilestoneInfo matches GSD ROADMAP (🟡, last bold, STATE fallback) - Recognize in-flight 🟡 milestone bullets like 🚧. - Derive from last **vX.Y Title** before ## Phases when emoji absent. - Fall back to STATE.md milestone when ROADMAP is missing; use last bare vX.Y in cleaned text instead of first (avoids v1.0 from shipped list). - Fixes init.execute-phase milestone_version and buildStateFrontmatter after state.begin-phase (syncStateFrontmatter). * feat(sdk): phase list, plan task structure, requirements extract handlers - Register phase.list-plans, phase.list-artifacts, plan.task-structure, requirements.extract-from-plans (SDK-only; golden-policy exceptions). - Add unit tests; document in QUERY-HANDLERS.md. - writeProfile: honor --output, render dimensions, return profile_path and dimensions_scored. * feat(sdk): centralize getGsdAgentsDir in query helpers Extract agent directory resolution to helpers (GSD_AGENTS_DIR, primary ~/.claude/agents, legacy path). Use from init and docs-init init bundles. docs(15): add 15-CONTEXT for autonomous phase-15 run. * feat(sdk): query CLI CJS fallback and session correlation - createRegistry(eventStream, sessionId) threads correlation into mutation events - gsd-sdk query falls back to gsd-tools.cjs when no native handler matches (disable with GSD_QUERY_FALLBACK=off); stderr bridge warnings - Export createRegistry from @gsd-build/sdk; add sdk/README.md - Update QUERY-HANDLERS.md and registry module docs for fallback + sessionId - Agents: prefer node dist/cli.js query over cat/grep for STATE and plans * fix(sdk): init phase_found parity, docs-init agents path, state field extract - Normalize findPhase not-found to null before roadmap fallback (matches findPhaseInternal) - docs-init: use detectRuntime + resolveAgentsDir for checkAgentsInstalled - state.cjs stateExtractField: horizontal whitespace only after colon (YAML progress guard) - Tests: commit_docs default true; config-get golden uses temp config; golden integration green Refs: #2302 * refactor(sdk): share SessionJsonlRecord in profile-extract-messages CodeRabbit nit: dedupe JSONL record shape for isGenuineUserMessage and streamExtractMessages. * fix(sdk): address CodeRabbit major threads (paths, gates, audit, verify) - Resolve @file: and CLI JSON indirection relative to projectDir; guard empty normalized query command - plan.task-structure + intel extract/patch-meta: resolvePathUnderProject containment - check.config-gates: safe string booleans; plan_checker alias precedence over plan_check default - state.validate/sync: phaseTokenMatches + comparePhaseNum ordering - verify.schema-drift: token match phase dirs; files_modified from parsed frontmatter - audit-open: has_scan_errors, unreadable rows, human report when scans fail - requirements PLANNED key PLAN for root PLAN.md; gsd-tools timeout note - ingest-docs: repo-root path containment; classifier output slug-hash Golden parity test strips has_scan_errors until CJS adds field. * fix: Resolve CodeRabbit security and quality findings - Secure intel.ts and cli.ts against path traversal - Catch and validate git add status in commit.ts - Expand roadmap milestone marker extraction - Fix parsing array-of-objects in frontmatter YAML - Fix unhandled config evaluations - Improve coverage test parity mapping * test: raise planner character extraction limit to 48K * fix(sdk): resolve TS build error in docs-init passing config
15 KiB
Handover: SDK query layer (registry, CLI, parity docs)
Paste this document (or @sdk/HANDOVER-QUERY-LAYER.md) at the start of a new session so work continues without re-deriving scope.
Parent tracking
- Issue: gsd-build/get-shit-done#2302 — Phase 3 SDK query parity, registry, docs (umbrella #2007).
- Workspace:
D:\Repos\get-shit-done(PBR backport). Upstream:gsd-build/get-shit-done. Confirm branch withgit branch(typical:feat/sdk-phase3-query-layer).
Scope anchors (do not confuse issues)
| Role | GitHub | Notes |
|---|---|---|
| Product / requirements anchor | #2007 | Problem statement, user stories, and target architecture for the SDK-first migration. Do not treat its original acceptance-checklist boxes as proof of what is merged upstream; work was split into phased PRs after maintainer review. |
| Phase 3 execution scope | #2302 + this handover | What this branch is actually doing now: registry/CLI parity, docs, harness gaps, runner alignment follow-ups as listed below. |
| Patch mine (if local tree is short) | PR #2008 and matching branches | Large pre-phasing PR; cherry-pick or compare when something looks missing vs that line of work. |
What was delivered (this line of work)
1. Parity documentation (QUERY-HANDLERS.md)
- ”Golden parity: coverage and exceptions” — How
golden.integration.test.tscompares SDK vsgsd-tools.cjs(fulltoEqual, subset, normalizeddocs-init,intel.updateCJS parity, time-dependent fields, etc.). - ”CJS command surface vs SDK registry” — Naming aliases, CLI-only rows, SDK-only rows, and a top-level
gsd-toolscommand → SDK matrix. docs/CLI-TOOLS.md— Short “Parity & registry” pointer into those sections.HANDOVER-GOLDEN-PARITY.md— One paragraph linking to the same sections.
2. gsd-sdk query tokenization (normalizeQueryCommand)
- Problem:
gsd-sdk queryused only argv[0] as the registry key, soquery state jsondispatchedstate(unregistered) instead ofstate.json. - Fix:
sdk/src/query/normalize-query-command.tsmerges the same command + subcommand patterns asgsd-toolsrunCommand()(e.g.state json→state.json,init execute-phase 9→init.execute-phase,scaffold …→phase.scaffold,progress bar→progress.bar). Wired insdk/src/cli.tsbeforeregistry.dispatch(). - Tests:
sdk/src/query/normalize-query-command.test.ts.
3. phase add-batch in the registry
- Implementation:
phaseAddBatchinsdk/src/query/phase-lifecycle.ts— port ofcmdPhaseAddBatchfromget-shit-done/bin/lib/phase.cjs(batch append under one roadmap lock; sequential orphase_naming: custom). - Registration:
phase.add-batchandphase add-batchinsdk/src/query/index.ts; listed inQUERY_MUTATION_COMMANDS(dotted + space forms). - Tests:
describe('phaseAddBatch')insdk/src/query/phase-lifecycle.test.ts. - Docs:
QUERY-HANDLERS.mdupdated —phase add-batchis registered; CLI-only table no longer lists it.
4. state load fully in the registry (split from state json)
Previously state.json and state.load were easy to confuse: CJS has two different commands — cmdStateJson (state json, rebuilt frontmatter) vs cmdStateLoad (state load, loadConfig + state_raw + existence flags).
stateJson—sdk/src/query/state.ts; registry keystate.json.stateProjectLoad—sdk/src/query/state-project-load.ts; registry keystate.load. UsescreateRequireto callcore.cjsloadConfig(projectDir)from the same resolution paths as a normal install (bundled monorepo path,projectDir/.claude/get-shit-done/...,~/.claude/get-shit-done/...).GSDTools.stateLoad()andformatRegistryRawStdoutfor--rawno longer force a subprocess solely for this command.- Risk: If
core.cjsis absent (e.g. some@gsd-build/sdk-only layouts),state.loadthrowsGSDError— document; future option is a TSloadConfigport or bundling. - Goldens:
read-only-parity.integration.test.ts— one block comparesstate.jsontostate json(striplast_updated); another comparesstate.loadtostate load(fulltoEqual).read-only-golden-rows.tsreadOnlyGoldenCanonicals()includes bothstate.jsonandstate.load.
Query surface completeness (snapshot)
| Status | Surface |
|---|---|
| Registered | Essentially all gsd-tools.cjs runCommand surfaces, including phase.add-batch. |
| CLI-only (by design) | graphify, from-gsd2 — not in createRegistry(); documented in QUERY-HANDLERS.md. |
| SDK-only extra | phases.archive — no gsd-tools phases archive subcommand (CJS has list / clear only). |
Programmatic API: createRegistry() / registry.dispatch('dotted.name', args, projectDir).
CLI: gsd-sdk query … — apply normalizeQueryCommand semantics (or pass dotted names explicitly).
Still not unified: GSDTools (sdk/src/gsd-tools.ts) shells out to gsd-tools.cjs for plan/session flows; migrating callers to the registry is separate #2302 / runner work. state load is not among the subprocess-only exceptions anymore (it uses the registry like other native query handlers when native query is active).
Canonical files
| Path | Role |
|---|---|
sdk/src/query/index.ts |
createRegistry(), QUERY_MUTATION_COMMANDS, handler wiring. |
sdk/src/query/state-project-load.ts |
state.load — CJS cmdStateLoad parity (loadConfig + state_raw + flags). |
sdk/src/query/normalize-query-command.ts |
CLI argv → registry command string. |
sdk/src/cli.ts |
gsd-sdk query path (uses normalizeQueryCommand). |
sdk/src/query/QUERY-HANDLERS.md |
Registry contracts, parity tiers, CJS matrix, mutation notes. |
sdk/src/golden/golden.integration.test.ts |
Golden parity vs captureGsdToolsOutput(). |
docs/CLI-TOOLS.md |
User-facing CLI; links to parity sections. |
Related handovers: HANDOVER-GOLDEN-PARITY.md, HANDOVER-PARITY-DOCS.md (older parity-doc brief; content largely folded into QUERY-HANDLERS.md).
Roadmap: parity vs decision offloading
Work that moves deterministic orchestration out of AI/bash and into SDK queries (historically gsd-tools.cjs) has two layers. Do not confuse them:
| Layer | Goal | What “done” looks like |
|---|---|---|
| Parity / migration | Existing CLI behavior is stable and testable in the registry so callers can use gsd-sdk query instead of node …/gsd-tools.cjs without silent drift. |
Goldens + QUERY-HANDLERS.md; same JSON/--raw contracts as CJS. |
| Offloading decisions | New or consolidated queries replace repeated grep, ls piped to wc -l, many config-gets, and inline node -e in workflows — so the model does less parsing and branching. |
Fewer inline shell blocks; measurable token/step reduction on representative workflows. |
Phase 3–style registry work mainly advances parity. The decision-routing-audit.md proposals are mostly offloading — they assume parity exists for commands workflows already call.
Decision-routing audit (proposed gsd-tools / SDK queries)
Source: .planning/research/decision-routing-audit.md §3. Tier = priority from §5 (implementation order). Do not implement = explicitly rejected in the audit.
| # | Proposed command | Tier | Notes |
|---|---|---|---|
| 3.1 | route next-action |
1 | Next slash-command from /gsd-next-style routing. |
| 3.2 | check gates <workflow> |
3 | Safety gates (continue-here, error state, verification debt). |
| 3.3 | check config-gates <workflow> |
1 | Batch workflow.* config for orchestration (replaces many config-gets). |
| 3.4 | check phase-ready <phase> |
1 | Phase directory readiness + next_step hint. |
| 3.5 | check auto-mode |
2 | auto_advance + _auto_chain_active → single boolean. |
| 3.6 | detect phase-type <phase> |
2 | Structured UI/schema detection (replaces fragile grep). |
| 3.7 | check completion <scope> |
2 | Phase or milestone completion rollup. |
| 3.8 | check verification-status <phase> |
3 | VERIFICATION.md parsing for routing. |
| 3.9 | check ship-ready <phase> |
3 | Ship preflight (ship.md). |
| 3.10 | route workflow-steps <workflow> |
❌ Do not implement | Pre-computed step lists are unsound when mid-workflow writes change state. See review-and-risks.md §3.6. |
Not in audit: phase-artifact-counts was only an example in an older handover line; there is no §3.11 for it — add via a new research doc if needed.
SDK registry (Tier 1): Done — check.config-gates, check.phase-ready, route.next-action in createRegistry() (sdk/src/query/index.ts). Documented in sdk/src/query/QUERY-HANDLERS.md § Decision routing (SDK-only until/unless mirrored in gsd-tools.cjs).
Simple roadmap (execute in order):
- Harden parity for surfaces workflows already depend on (registry dispatch, goldens, docs) so swaps from CJS to
gsd-sdk querystay safe. - Ship 1–2 high-leverage consolidation handlers from the audit (pick based on impact and risk; examples:
check auto-mode,phase-artifact-counts,route next-action— with display/routing fields required byreview-and-risks.mdif applicable). Each needs handlers, tests, andQUERY-HANDLERS.mdnotes. Progress:check.auto-modeshipped (sdk/src/query/check-auto-mode.ts); Tier 1route.next-actionalready registered. - Rewrite one heavy workflow (e.g.
next.mdor a focused slice ofautonomous.md) to consume those queries and measure before/after (steps, tokens, or both). Progress:execute-phase.md,discuss-phase.md,discuss-phase-assumptions.md, andplan-phase.md(UI gate) now usecheck auto-modeinstead of pairedconfig-gets where applicable. - Maintain a living boundary between SDK (data, deterministic checks) and workflows (judgment, sequencing, user-facing messages). Extend
decision-routing-audit.md§6 (decisions that stay with the AI) andreview-and-risks.md“Do not implement” (e.g. no pre-computedroute workflow-steps) as you add primitives. Progress: audit §3.5 / Tier 2 #4 updated to reference SDK implementation.
Gaps to keep in mind when designing new queries: call-time vs stale data after file writes (re-query volatile fields); workflows own gates/UX; behavioral contracts (e.g. UI keyword lists) must match existing greps; stderr/stdout and JSON shapes stable for bash/jq; hybrid require(core.cjs) paths called out for minimal installs.
Research references (repo root): .planning/research/decision-routing-audit.md, .planning/research/review-and-risks.md, .planning/research/inline-computation-audit.md, .planning/research/questions.md (Q1 boundary). For parity mechanics, prefer sdk/src/query/QUERY-HANDLERS.md and HANDOVER-GOLDEN-PARITY.md.
Suggested next session
(Strategic ordering of parity vs decision offloading is in Roadmap above.)
Golden test for— Done:phase.add-batchsdk/src/golden/mutation-subprocess.integration.test.ts(phase.add-batchJSON parity vs CJS).Re-export— Done: exported fromnormalizeQueryCommandsdk/src/query/index.tsandsdk/src/index.ts(@gsd-build/sdk).- Issue #2302 follow-ups — Runner alignment (
GSDTools→ registry where appropriate).configGetnow usesdispatchNativeJsonwith canonicalconfig-get(fixes subprocess argv vs realgsd-tools.cjs, which has noconfig+gettop-level). Keepgraphify/from-gsd2out of scope unless product reopens. - Drift check — When adding CJS commands, update
QUERY-HANDLERS.mdmatrix and golden docs in the same PR.
Verification commands
cd sdk
npm run build
npx vitest run src/query/normalize-query-command.test.ts src/query/phase-lifecycle.test.ts src/query/registry.test.ts --project unit
npx vitest run src/golden/golden.integration.test.ts --project integration
(Adjust --project to match sdk/vitest.config.ts.)
Success criteria (query-layer slice)
- Parity expectations and CJS↔SDK matrix documented in one place (
QUERY-HANDLERS.md). gsd-sdk queryunderstands two-token command patterns likegsd-tools.phase add-batchimplemented and registered; only intentional CLI-only gaps remain (graphify, from-gsd2).
Created/updated for query-layer handoff. Revise when registry surface, golden coverage, or the parity/offloading roadmap changes materially.