Files
get-shit-done/sdk/HANDOVER-GOLDEN-PARITY.md
Rezolv c5b1445529 feat(sdk): golden parity harness and query handler CJS alignment (#2302 Track A) (#2341)
* 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
2026-04-20 18:09:02 -04:00

19 KiB
Raw Permalink Blame History

Handover: Query layer + golden parity

Use this document at the start of a new session so work continues in context without re-deriving history.

Related: HANDOVER-PARITY-DOCS.md (#2302 scope); sdk/src/query/QUERY-HANDLERS.md (golden matrix, CJS↔SDK routing).


Goal for the next session (primary)

Track A (Golden/parity) is complete. 127/128 canonicals covered — the single exception (phases.archive) is permanent (SDK-only, no CJS analogue). Focus shifts to the remaining #2302 acceptance criteria.

Ongoing: pick next gap from GOLDEN_PARITY_EXCEPTIONS / registry orphans (run golden-policy.test.ts) or expand READ_ONLY_JSON_PARITY_ROWS for read-only handlers still on generic exceptions. The read-only batch in § Next batch below is done.

Follow-up: confirm GOLDEN_PARITY_EXCEPTIONS for any remaining read-only registry gaps (learnings.query, progress.bar, profile-questionnaire — still exception-only until strict rows); extend read-only-golden-rows.ts when aligned.

Remaining work — ordered by priority

  1. Track C — Runner alignment (not started)

    • PhaseRunner and InitRunner both take GSDTools (subprocess bridge) as a tools dependency (phase-runner.ts:55, init-runner.ts:70).
    • Issue #2302 says: "Align programmatic paths with the same contracts as query handlers (shared helpers or registry dispatch), without removing GSDTools."
    • Concretely: where runners currently shell out via GSDTools.run('state update …'), they could call the typed handler (stateUpdate()) directly or dispatch through createRegistry(). This eliminates subprocess overhead on the hot path while keeping GSDTools exported for backward compatibility.
    • Files to touch: sdk/src/phase-runner.ts, sdk/src/init-runner.ts, sdk/src/index.ts (re-exports). Tests: phase-runner.integration.test.ts, init-e2e.integration.test.ts, lifecycle-e2e.integration.test.ts.
    • Risk: Runner integration tests are slow and sensitive to state. Approach: swap one tools.run() call at a time, verify the integration test still passes, then proceed to the next.
  2. Track B — CHANGELOG.md [Unreleased] entries (not started)

    • CHANGELOG.md has an [Unreleased] section but no Phase 3 entries yet.
    • Add entries covering: golden parity policy gate, mutation subprocess infrastructure, handler alignment, profile-output port, CJS deprecation header.
    • docs/CLI-TOOLS.md already references QUERY-HANDLERS.md and SDK query layer — may need minor polish but is substantively done.
    • QUERY-HANDLERS.md is maintained and current.
  3. Track D — CJS deprecation headers (done)

    • gsd-tools.cjs already has @deprecated JSDoc header (lines 3-6) pointing to gsd-sdk query and @gsd-build/sdk.
    • No additional CJS file deletion in scope per #2302.
  4. CI verification (should run before any PR)

    • Run full integration suite: npx vitest run --project integration (mutation subprocess + read-only parity + golden composition).
    • Verify against CI matrix expectations: Ubuntu + macOS, Node 22 + 24.

Acceptance criteria from #2302 — status

Criterion Status Notes
Policy gate Done verifyGoldenPolicyComplete() green; 0 orphan canonicals
Parity Done 127/128 covered; strict rows, mutation subprocess, composition goldens
Registry Done CJS-only matrix in QUERY-HANDLERS.md; docs/CLI-TOOLS.md updated
Runners (Track C) Not started PhaseRunner/InitRunner still use GSDTools subprocess bridge
Deprecation (Track D) Done @deprecated header on gsd-tools.cjs
Docs Partial QUERY-HANDLERS.md current; CHANGELOG.md [Unreleased] needs Phase 3 entries
CI Not verified Unit tests green (1261/1261); integration suite not run this session

Repo / branch

  • Workspace: D:\Repos\get-shit-done (GSD PBR backport initiative).
  • Feature branch: feat/sdk-phase3-query-layer (62 commits ahead of main; confirm against origin before merging).
  • Upstream PRs: gsd-build/get-shit-done issue #2302.

Golden parity architecture (current)

Piece Role
sdk/src/golden/registry-canonical-commands.ts One canonical dispatch string per unique handler (pickCanonicalCommandName).
sdk/src/golden/golden-integration-covered.ts Canonicals exercised by golden.integration.test.ts (subset/full/shape tests).
sdk/src/golden/read-only-golden-rows.ts Strict JsonParityRow[] for read-only-parity.integration.test.ts (toEqual on parsed CJS JSON vs sdkResult.data).
sdk/src/golden/read-only-parity.integration.test.ts Rows from READ_ONLY_JSON_PARITY_ROWS + config-path (plain stdout vs { path }, path.normalize) + verify.commits.
sdk/src/golden/capture.ts captureGsdToolsOutput (JSON stdout); captureGsdToolsStdout (raw stdout, e.g. config-path).
sdk/src/golden/golden-policy.ts GOLDEN_PARITY_INTEGRATION_COVERED = integration readOnlyGoldenCanonicals() GOLDEN_MUTATION_SUBPROCESS_COVERED; GOLDEN_PARITY_EXCEPTIONS includes NO_CJS_SUBPROCESS_REASON, then MUTATION_DEFERRED_REASON for remaining mutations, else read-only.
sdk/src/golden/golden-mutation-covered.ts Canonicals exercised by mutation-subprocess.integration.test.ts (must match non-skipped tests).
sdk/src/golden/mutation-subprocess.integration.test.ts Tmp fixture + captureGsdToolsOutput vs registry.dispatch; dual sandbox per comparison.
sdk/src/golden/mutation-sandbox.ts createMutationSandbox({ git?: boolean }) — copy fixture, optional git init + commit.
sdk/src/golden/golden-policy.test.ts Calls verifyGoldenPolicyComplete() so every canonical is covered or excepted.

Invariant: Every canonical from getCanonicalRegistryCommands() is either in GOLDEN_PARITY_INTEGRATION_COVERED or has an exception string—never leave orphans by removing tests.


Reference pattern: porting like scan-sessions and workstream.status

These were fixed by aligning the TypeScript handler with the CJS implementation, then adding a row to READ_ONLY_JSON_PARITY_ROWS.

  1. Find the CJS source of truth

    • scan-sessions: get-shit-done/bin/lib/profile-pipeline.cjscmdScanSessions
    • workstream status: get-shit-done/bin/lib/workstream.cjscmdWorkstreamStatus
    • gsd-tools.cjs runCommand switch shows the top-level command and argv.
  2. Implement or adjust the SDK module

    • Example: sdk/src/query/profile-scan-sessions.ts mirrors the project-array build from cmdScanSessions; scanSessions in profile.ts parses --path / --verbose, throws when no sessions root (same error text as CJS), returns { data: projects } where projects matches CJS JSON array.
  3. Add a parity row in read-only-golden-rows.ts with canonical, sdkArgs, cjs, cjsArgs (must match what execFile(node, [gsdToolsPath, command, ...args]) expects).

  4. Run
    cd sdk && npm run build && npx vitest run src/golden/read-only-parity.integration.test.ts src/golden/golden-policy.test.ts --project integration --project unit

  5. Policy
    readOnlyGoldenCanonicals() picks up new canonicals automatically; no manual duplicate if the canonical is already in the JSON row list.

When not to copy line-for-line: subprocess-only concerns (e.g. agents_installed / missing_agents differing from in-process ~ resolution). Then normalize in the test (see golden.integration.test.ts docs-init: sort existing_docs, omit install fields)—document in QUERY-HANDLERS.md, do not delete the assertion.


Completed — Track A (golden parity)

All 127 portable canonicals have subprocess or in-process parity coverage. Summary of completed work by batch:

Profile-output + milestone subprocess batch (latest)

write-profile, generate-claude-profile, generate-dev-preferences, generate-claude-md — implemented in sdk/src/query/profile-output.ts (templates from get-shit-done/templates/, same JSON as profile-output.cjs); re-exported from profile.ts. milestone.complete — full port of cmdMilestoneComplete in phase-lifecycle.ts; readModifyWriteStateMdFull in state-mutation.ts for STATE writes matching CJS.

Mutation subprocess infrastructure

mutation-subprocess.integration.test.ts — tmp fixture sdk/src/golden/fixtures/mutation-project/ + createMutationSandbox() (mutation-sandbox.ts). assertJsonParity runs CJS and SDK on two fresh sandboxes (factory fn) so neither run sees the other's filesystem mutations. GOLDEN_MUTATION_SUBPROCESS_COVERED lists canonicals with non-skipped subprocess assertions. Handlers covered: config-ensure-section, commit, commitToSubrepo, configSetModelProfile, state.patch, frontmatter.set/merge, workstream.progress, workstream.set, nine state.* subprocess tests, write-profile, generate-claude-profile, generate-dev-preferences, generate-claude-md, milestone.complete, init.remove-workspace.

CJS mutation handler alignment

commit.ts--files argv boundary, commitToSubrepo config check, checkCommit allowed field. state-mutation.tsreadModifyWriteStateMdFull, statePlannedPhase=cmdStatePlannedPhase, record-session/add-decision/add-blocker/resolve-blocker/record-metric/update-progress JSON shapes. phase-lifecycle.tsmilestone.complete. workstream.tsworkstream.progress (cmdWorkstreamProgress), workstream.set. roadmap.ts — extracted roadmapUpdatePlanProgress to own module. frontmatter-mutation.ts--field/--value, --data parsing. config-mutation.tsconfigSetModelProfile CJS-shaped { updated, profile, previousProfile, agentToModelMap }. config-query.tsgetAgentToModelMapForProfile().

Read-only parity rows (earlier batches)

progress.table / stats.table, progress.bar, learnings.query, profile-questionnaire, verify.references, init.* composition goldens (9 handlers), profile-sample, extract-messages, uat.render-checkpoint, validate.agents + state.get, skill-manifest, audit-open + audit-uat, intel.extract-exports, summary-extract + history-digest, stats.json, todo.match-phase, verify.key-links, verify.schema-drift, state-snapshot, state.json/state.load, scan-sessions, workstream.status.


Next batch — summary / audit / skill / validate / UAT / intel / profile / init

Same workflow as above: read gsd-tools.cjs runCommand for argv → implement/adjust sdk/src/query/*.ts → add READ_ONLY_JSON_PARITY_ROWS and/or a named describe block with documented omissions → npm run buildread-only-parity.integration.test.ts + golden-policy.test.ts.

Priority Command (CLI) gsd-tools.cjs case / args CJS implementation SDK module Notes
1 summary-extract <path> [--fields a,b] summary-extract commands.cjs cmdSummaryExtract (~L425) summary.ts summaryExtract Done: strict READ_ONLY_JSON_PARITY_ROWS; summary.ts aligned with commands.cjs; extractFrontmatterLeading in frontmatter.ts for first-----block parity with frontmatter.cjs.
2 history-digest history-digest commands.cjs cmdHistoryDigest (~L133) summary.ts historyDigest Done: same row / handler alignment as above.
3 audit-open audit-open [--json] audit.cjs auditOpenArtifacts + optional formatAuditReport audit-open.ts Done: --json parity test + scanned_at normalization; sanitizeForDisplay = security.cjs.
4 audit-uat audit-uat uat.cjs cmdAuditUat uat.ts auditUat Done: auditUat ports cmdAuditUat (parseUatItems, milestone filter, summary.by_*); strict READ_ONLY_JSON_PARITY_ROWS row.
5 skill-manifest skill-manifest + args init.cjs cmdSkillManifest (~L1829) skill-manifest.ts Done: strict row; extractFrontmatterLeading for CJS parity (see QUERY-HANDLERS.md).
6 validate agents validate + agents verify.cjs cmdValidateAgents (~L997) validate.ts validateAgents Done: strict row; getAgentsDir parity with core.cjs; MODEL_PROFILES includes gsd-pattern-mapper (sync with model-profiles.cjs).
7 uat render-checkpoint --file <path> uat subcommand uat.cjs cmdRenderCheckpoint uat.ts uatRenderCheckpoint Done: strict row; fixture sdk/src/golden/fixtures/uat-render-checkpoint-sample.md; see QUERY-HANDLERS.md.
8 intel extract-exports <file> intel extract-exports intel.cjs intelExtractExports (~L502) intel.ts intelExtractExports Done: strict row + handler parity with intel.cjs (fixed file e.g. sdk/src/query/utils.ts).
9 extract-messages extract-messages + project/session flags profile-pipeline.cjs profile.ts extractMessages Done: profile-extract-messages.ts + golden output_file strip + JSONL compare; fixture extract-messages-sessions/.
10 profile-sample profile-sample profile-pipeline.cjs profile.ts profileSample Done: profile-sample.ts + golden output_file strip + JSONL compare; fixture profile-sample-sessions/.
11 init.* read-only JSON various init.cjs / init-complex init.ts, init-complex.ts Done: golden.integration.test.ts + nine init composition tests; withProjectRoot / subagent_timeout / GOLDEN_INTEGRATION_MAIN_FILE_CANONICALS; see QUERY-HANDLERS.md.

Suggested order: Audit/read-only batch above is complete — follow-ups via GOLDEN_PARITY_EXCEPTIONS / new strict rows as needed (learnings.query, progress.bar, profile-questionnaire, etc.).

Done (this line of work): summary-extract + history-digest — strict READ_ONLY_JSON_PARITY_ROWS; summary.ts aligned with commands.cjs; extractFrontmatterLeading in frontmatter.ts for first-----block parity with frontmatter.cjs.

Done (profile-output + milestone mutation batch): write-profile, generate-claude-profile, generate-dev-preferences, generate-claude-md (profile-output.ts); milestone.complete (phase-lifecycle.ts + readModifyWriteStateMdFull); GOLDEN_MUTATION_SUBPROCESS_COVERED updated; MUTATION_SUBPROCESS_GAP_REASON removed from golden-policy.ts.

Mutations (QUERY_MUTATION_COMMANDS): subprocess coverage is mutation-subprocess.integration.test.ts + GOLDEN_MUTATION_SUBPROCESS_COVERED. Remaining mutation canonicals without a subprocess row use MUTATION_DEFERRED_REASON (see golden-policy.ts). For known gaps before parity, prefer it.skip with an explicit rationale in code comments or restore a dedicated gap map — do not rely on silent deferral alone.


Backlog: other read-only handlers (lower priority or follow-ups)

Confirm against GOLDEN_PARITY_EXCEPTIONS in golden-policy.ts for the live list.

Mutations: Prefer tmp fixture + dual sandbox (see mutation-sandbox.ts). Do not green the suite by deleting subprocess tests; skip with it.skip and document the gap (policy entry or comment) until parity is restored.


Not in the SDK registry (product decision)

  • graphify, from-gsd2 / gsd2-import — CLI-only; no registry handler.

Files to know (updated)

Path Role
sdk/src/query/index.ts createRegistry(), QUERY_MUTATION_COMMANDS.
sdk/src/golden/golden-policy.ts Coverage set + exceptions; verifyGoldenPolicyComplete().
sdk/src/golden/read-only-golden-rows.ts Strict read-only JSON matrix.
sdk/src/golden/read-only-parity.integration.test.ts Subprocess + dispatch parity tests.
sdk/src/golden/capture.ts captureGsdToolsOutput, captureGsdToolsStdout.
sdk/src/golden/fixtures/mutation-project/ Ephemeral copy for mutation subprocess tests.
sdk/src/golden/mutation-subprocess.integration.test.ts Mutation handler subprocess parity.
sdk/src/golden/mutation-sandbox.ts createMutationSandbox({ git?: boolean }).
sdk/src/query/profile-output.ts CJS-parity profile output handlers.
sdk/src/phase-runner.ts Track C target — currently uses GSDTools.
sdk/src/init-runner.ts Track C target — currently uses GSDTools.
sdk/src/gsd-tools.ts Subprocess bridge; not deleted in Phase 3 scope.
get-shit-done/bin/gsd-tools.cjs runCommand — argv routing. Has @deprecated header.
get-shit-done/bin/lib/*.cjs Per-command implementations (CJS source of truth).

Commands (verification)

cd sdk
npm run build
npm run test:unit
npm run test:integration

Focused:

npx vitest run src/golden/read-only-parity.integration.test.ts src/golden/golden.integration.test.ts --project integration
npx vitest run src/golden/mutation-subprocess.integration.test.ts --project integration
npx vitest run src/golden/golden-policy.test.ts --project unit

Success criteria (extend, not replace)

  • No regression: golden-policy.test.ts / verifyGoldenPolicyComplete() stays green.
  • Track A complete: 127/128 covered; read-only rows, mutation subprocess, composition goldens all in place.
  • Track C: Runner alignment — PhaseRunner and InitRunner use typed handlers where possible; GSDTools remains exported.
  • CHANGELOG.md [Unreleased] updated with Phase 3 entries.
  • QUERY-HANDLERS.md updated when assertion style changes (full toEqual vs normalized subset).

Do not "green the suite" by deleting or shrinking golden tests. If a handler cannot match CJS byte-for-byte without product decisions, use documented normalization in the test or fix the TypeScript handler — do not silently remove assertions.


Commit history (this branch)

62 commits ahead of main on feat/sdk-phase3-query-layer. Recent batch (5 commits):

95db59c docs(sdk): update handover for profile-output and mutation subprocess batch
05e8238 sdk(golden): mutation subprocess test infrastructure and golden policy
593d9be sdk(query): port profile output handlers from profile-output.cjs
a2d0eb6 sdk(query): CJS parity for state, phase-lifecycle, workstream, roadmap, frontmatter, config, and intel
8bd9f1d sdk(query): align commit handler with CJS --files argv and allowed field

Cherry-pick notes: Commits 1 (8bd9f1d) and 3 (593d9be) are independently cherry-pickable. Commit 2 (a2d0eb6) is a bulk handler alignment (13 files). Commit 4 (05e8238) depends on handlers from 2+3 at test-runtime but compiles independently. Commit 5 is docs-only.


Update this file when registry or golden milestones change.