docs(sdk): registry docs and gsd-sdk query call sites (#2302 Track B) (#2340)

* 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

* docs(sdk): registry docs and gsd-sdk query call sites (#2302 Track B)

Update CHANGELOG, architecture and user guides, workflow call sites, and read-guard tests for gsd-sdk query; sync ARCHITECTURE.md command/workflow counts and directory-tree totals with the repo (80 commands, 77 workflows).

Address CodeRabbit: fix markdown tables and emphasis; align CLI-TOOLS GSDTools and state.read docs with implementation; correct roadmap handler name in universal-anti-patterns; resolve settings workflow config path without relying on config_path from state.load.

Refs gsd-build/get-shit-done#2340

* test: raise planner character extraction limit to 48K

* fix(sdk): resolve build TS error and doc conflict markers
This commit is contained in:
Rezolv
2026-04-20 18:09:21 -04:00
committed by GitHub
parent c5b1445529
commit 86fb9c85c3
27 changed files with 873 additions and 447 deletions

View File

@@ -40,10 +40,8 @@ When a milestone completes:
<step name="pre_close_artifact_audit">
Before proceeding with milestone close, run the comprehensive open artifact audit.
`audit-open` is not registered on `gsd-sdk query` yet; use the installed CJS CLI:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" audit-open 2>/dev/null
gsd-sdk query audit-open 2>/dev/null
```
If the output contains open items (any section with count > 0):
@@ -59,7 +57,7 @@ These items are open. Choose an action:
```
If user chooses [A] (Acknowledge):
1. Re-run `audit-open --json` to get structured data
1. Re-run `gsd-sdk query audit-open --json` to get structured data
2. Write acknowledged items to STATE.md under `## Deferred Items` section:
```markdown
## Deferred Items
@@ -78,7 +76,7 @@ If user chooses [A] (Acknowledge):
If output shows all clear (no open items): print `All artifact types clear.` and proceed.
SECURITY: Audit JSON output is structured data from `audit-open` (gsd-tools.cjs) — validated and sanitized at source. When writing to STATE.md, item slugs and descriptions are sanitized via `sanitizeForDisplay()` before inclusion. Never inject raw user-supplied content into STATE.md without sanitization.
SECURITY: Audit JSON output is structured data from the `audit-open` query handler (same JSON contract as legacy `gsd-tools.cjs audit-open`) — validated and sanitized at source. When writing to STATE.md, item slugs and descriptions are sanitized via `sanitizeForDisplay()` before inclusion. Never inject raw user-supplied content into STATE.md without sanitization.
</step>
<step name="verify_readiness">

View File

@@ -622,21 +622,20 @@ Check for auto-advance trigger:
gsd-sdk query config-set workflow._auto_chain_active false 2>/dev/null
fi
```
3. Read chain flag and user preference:
3. Read consolidated auto-mode (`active` = chain flag OR user preference):
```bash
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_MODE=$(gsd-sdk query check auto-mode --pick active 2>/dev/null || echo "false")
```
**If `--auto` flag present AND `AUTO_CHAIN` is not true:**
**If `--auto` flag present AND `AUTO_MODE` is not true:**
```bash
gsd-sdk query config-set workflow._auto_chain_active true
```
**If `--auto` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**
**If `--auto` flag present OR `AUTO_MODE` is true:**
Display banner:
```
```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GSD ► AUTO-ADVANCING TO PLAN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

View File

@@ -1223,18 +1223,17 @@ Check for auto-advance trigger:
gsd-sdk query config-set workflow._auto_chain_active false 2>/dev/null
fi
```
3. Read both the chain flag and user preference:
3. Read consolidated auto-mode (`active` = chain flag OR user preference):
```bash
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_MODE=$(gsd-sdk query check auto-mode --pick active 2>/dev/null || echo "false")
```
**If `--auto` or `--chain` flag present AND `AUTO_CHAIN` is not true:** Persist chain flag to config (handles direct usage without new-project):
**If `--auto` or `--chain` flag present AND `AUTO_MODE` is not true:** Persist chain flag to config (handles direct usage without new-project):
```bash
gsd-sdk query config-set workflow._auto_chain_active true
```
**If `--auto` flag present OR `--chain` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**
**If `--auto` flag present OR `--chain` flag present OR `AUTO_MODE` is true:**
Display banner:
```

View File

@@ -865,13 +865,12 @@ Plans with `autonomous: false` require user interaction.
**Auto-mode checkpoint handling:**
Read auto-advance config (chain flag + user preference):
Read auto-advance config (chain flag OR user preference — same boolean as `check.auto-mode`):
```bash
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_MODE=$(gsd-sdk query check auto-mode --pick active 2>/dev/null || echo "false")
```
When executor returns a checkpoint AND (`AUTO_CHAIN` is `"true"` OR `AUTO_CFG` is `"true"`):
When executor returns a checkpoint AND `AUTO_MODE` is `true`:
- **human-verify** → Auto-spawn continuation agent with `{user_response}` = `"approved"`. Log `⚡ Auto-approved checkpoint`.
- **decision** → Auto-spawn continuation agent with `{user_response}` = first option from checkpoint details. Log `⚡ Auto-selected: [option]`.
- **human-action** → Present to user (existing behavior below). Auth gates cannot be automated.
@@ -1484,13 +1483,12 @@ STOP. Do not proceed to auto-advance or transition.
**Auto-advance detection:**
1. Parse `--auto` flag from $ARGUMENTS
2. Read both the chain flag and user preference (chain flag already synced in init step):
2. Read consolidated auto-mode (`active` = chain flag OR user preference; chain flag already synced in init step):
```bash
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CFG=$(gsd-sdk query config-get workflow.auto_advance 2>/dev/null || echo "false")
AUTO_MODE=$(gsd-sdk query check auto-mode --pick active 2>/dev/null || echo "false")
```
**If `--auto` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true (AND verification passed with no gaps):**
**If `--auto` flag present OR `AUTO_MODE` is true (AND verification passed with no gaps):**
```
╔══════════════════════════════════════════╗
@@ -1503,7 +1501,7 @@ Execute the transition workflow inline (do NOT use Task — orchestrator context
Read and follow `~/.claude/get-shit-done/workflows/transition.md`, passing through the `--auto` flag so it propagates to the next phase invocation.
**If none of `--auto`, `AUTO_CHAIN`, or `AUTO_CFG` is true:**
**If neither `--auto` nor `AUTO_MODE` is true:**
**STOP. Do not auto-advance. Do not execute transition. Do not plan next phase. Present options to the user and wait.**

View File

@@ -475,9 +475,9 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
**If UI-SPEC.md missing AND `UI_GATE_CFG` is `true`:**
Read auto-chain state:
Read ephemeral chain flag (same field as `check.auto-mode` → `auto_chain_active`):
```bash
AUTO_CHAIN=$(gsd-sdk query config-get workflow._auto_chain_active 2>/dev/null || echo "false")
AUTO_CHAIN=$(gsd-sdk query check auto-mode --pick auto_chain_active 2>/dev/null || echo "false")
```
**If `AUTO_CHAIN` is `true` (running inside a `--chain` or `--auto` pipeline):**

View File

@@ -13,13 +13,21 @@ Ensure config exists and load current state:
```bash
gsd-sdk query config-ensure-section
GSD_CONFIG_PATH=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-path)
INIT=$(gsd-sdk query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# `state.load` returns STATE frontmatter JSON from the SDK — it does not include `config_path`. Orchestrators may set `GSD_CONFIG_PATH` from init phase-op JSON; otherwise resolve the same path gsd-tools uses for flat vs active workstream (#2282).
if [[ -z "${GSD_CONFIG_PATH:-}" ]]; then
if [[ -f .planning/active-workstream ]]; then
WS=$(tr -d '\n\r' < .planning/active-workstream)
GSD_CONFIG_PATH=".planning/workstreams/${WS}/config.json"
else
GSD_CONFIG_PATH=".planning/config.json"
fi
fi
```
Creates config.json (at the workstream-aware path) with defaults if missing and loads current config values.
Store `$GSD_CONFIG_PATH` — all subsequent reads and writes use this path, not the hardcoded `.planning/config.json`, so active-workstream installs write to the correct location (#2282).
Creates `config.json` (at the resolved path) with defaults if missing. `INIT` still holds `state.load` output for any step that needs STATE fields.
Store `$GSD_CONFIG_PATH` — all subsequent reads and writes use this path, not a hardcoded `.planning/config.json`, so active-workstream installs target the correct file (#2282).
</step>
<step name="read_current">

View File

@@ -53,9 +53,7 @@ COMMIT_DOCS=$(gsd-sdk query config-get commit_docs 2>/dev/null || echo "true")
**Otherwise:**
**Text mode:** If TEXT_MODE is enabled (set in the banner step), replace AskUserQuestion calls with plain-text numbered lists — emit the options and ask the user to type the number of their choice.
Before sketching anything, explore the design intent through conversation. Ask one question at a time — using AskUserQuestion in normal mode, or a plain-text numbered list if TEXT_MODE is active — with a paragraph of context and reasoning for each.
Before sketching anything, explore the design intent through conversation. Ask one question at a time using AskUserQuestion, with a paragraph of context and reasoning for each.
**Questions to cover (adapt to what the user has already shared):**

View File

@@ -388,8 +388,9 @@ installer does not know about and will delete during the wipe.
**Do not use bash path-stripping (`${filepath#$RUNTIME_DIR/}`) or `node -e require()`
inline** — those patterns fail when `$RUNTIME_DIR` is unset and the stripped
relative path may not match manifest key format, which causes CUSTOM_COUNT=0
even when custom files exist (bug #1997). Use `gsd-tools detect-custom-files`
instead, which resolves paths reliably with Node.js `path.relative()`.
even when custom files exist (bug #1997). Use `gsd-sdk query detect-custom-files`
when `gsd-sdk` is on `PATH`, or the bundled `gsd-tools.cjs detect-custom-files`
otherwise — both resolve paths reliably with Node.js `path.relative()`.
First, resolve the config directory (`RUNTIME_DIR`) from the install scope
detected in `get_installed_version`:
@@ -410,17 +411,20 @@ fi
If `RUNTIME_DIR` is empty or does not exist, skip this step (no config dir to
inspect).
Otherwise, resolve the path to `gsd-tools.cjs` and run:
Otherwise run `detect-custom-files` (prefer SDK when available):
```bash
GSD_TOOLS="$RUNTIME_DIR/get-shit-done/bin/gsd-tools.cjs"
if [ -f "$GSD_TOOLS" ] && [ -n "$RUNTIME_DIR" ]; then
CUSTOM_JSON=''
if [ -n "$RUNTIME_DIR" ] && command -v gsd-sdk >/dev/null 2>&1; then
CUSTOM_JSON=$(gsd-sdk query detect-custom-files --config-dir "$RUNTIME_DIR" 2>/dev/null)
elif [ -f "$GSD_TOOLS" ] && [ -n "$RUNTIME_DIR" ]; then
CUSTOM_JSON=$(node "$GSD_TOOLS" detect-custom-files --config-dir "$RUNTIME_DIR" 2>/dev/null)
CUSTOM_COUNT=$(echo "$CUSTOM_JSON" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{console.log(JSON.parse(d).custom_count);}catch{console.log(0);}})" 2>/dev/null || echo "0")
else
CUSTOM_COUNT=0
fi
if [ -z "$CUSTOM_JSON" ]; then
CUSTOM_JSON='{"custom_files":[],"custom_count":0}'
fi
CUSTOM_COUNT=$(echo "$CUSTOM_JSON" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{console.log(JSON.parse(d).custom_count);}catch{console.log(0);}})" 2>/dev/null || echo "0")
```
**If `CUSTOM_COUNT` > 0:**

View File

@@ -464,7 +464,7 @@ Run phase artifact scan to surface any open items before marking phase verified:
`audit-open` is CJS-only until registered on `gsd-sdk query`:
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" audit-open --json 2>/dev/null
gsd-sdk query audit-open --json 2>/dev/null
```
Parse the JSON output. For the CURRENT PHASE ONLY, surface: