Extends the canonical runtime-launcher snippet with a third resolution arm
that probes $HOME/.claude/get-shit-done/bin/${_GSD_SHIM_NAME} between the
PATH check and the hard-error exit. Global Claude-Code installs (--claude
without --local) with no PATH wiring and no RUNTIME_DIR no longer hit the
hard-error path.
Resolution order: local/RUNTIME_DIR -> PATH -> ~/.claude/... -> hard error.
Propagated to 76 workflow .md files via sync-runtime-launcher.cjs. Parity
test (G) and bug-211 regression test (4 assertions) added.
180 lines
6.6 KiB
Markdown
180 lines
6.6 KiB
Markdown
<purpose>
|
|
Audit Nyquist validation gaps for a completed phase. Generate missing tests. Update VALIDATION.md.
|
|
</purpose>
|
|
|
|
<required_reading>
|
|
@~/.claude/get-shit-done/references/ui-brand.md
|
|
</required_reading>
|
|
|
|
<available_agent_types>
|
|
Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
|
|
- gsd-nyquist-auditor — Validates verification coverage
|
|
</available_agent_types>
|
|
|
|
<process>
|
|
|
|
## 0. Initialize
|
|
|
|
```bash
|
|
_GSD_SHIM_NAME="gsd-tools.cjs"; GSD_TOOLS="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}/get-shit-done/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/get-shit-done/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/get-shit-done/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/get-shit-done-redux@latest --claude --local" >&2; exit 1; fi
|
|
INIT=$(gsd_run query init.phase-op "${PHASE_ARG}")
|
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
AGENT_SKILLS_AUDITOR=$(gsd_run query agent-skills gsd-nyquist-auditor)
|
|
```
|
|
|
|
Parse: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`.
|
|
|
|
```bash
|
|
AUDITOR_MODEL=$(gsd_run query resolve-model gsd-nyquist-auditor --raw)
|
|
NYQUIST_CFG=$(gsd_run query config-get workflow.nyquist_validation --raw --default true)
|
|
```
|
|
|
|
If `NYQUIST_CFG` is `false`: exit with "Nyquist validation is disabled. Enable via /gsd:settings."
|
|
|
|
Display banner: `GSD > VALIDATE PHASE {N}: {name}`
|
|
|
|
## 1. Detect Input State
|
|
|
|
```bash
|
|
VALIDATION_FILE=$(ls "${PHASE_DIR}"/*-VALIDATION.md 2>/dev/null | head -1)
|
|
SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
|
|
```
|
|
|
|
- **State A** (`VALIDATION_FILE` non-empty): Audit existing
|
|
- **State B** (`VALIDATION_FILE` empty, `SUMMARY_FILES` non-empty): Reconstruct from artifacts
|
|
- **State C** (`SUMMARY_FILES` empty): Exit — "Phase {N} not executed. Run /gsd:execute-phase {N} ${GSD_WS} first."
|
|
|
|
## 2. Discovery
|
|
|
|
### 2a. Read Phase Artifacts
|
|
|
|
Read all PLAN and SUMMARY files. Extract: task lists, requirement IDs, key-files changed, verify blocks.
|
|
|
|
### 2b. Build Requirement-to-Task Map
|
|
|
|
Per task: `{ task_id, plan_id, wave, requirement_ids, has_automated_command }`
|
|
|
|
### 2c. Detect Test Infrastructure
|
|
|
|
State A: Parse from existing VALIDATION.md Test Infrastructure table.
|
|
State B: Filesystem scan:
|
|
|
|
```bash
|
|
find . -name "pytest.ini" -o -name "jest.config.*" -o -name "vitest.config.*" -o -name "pyproject.toml" 2>/dev/null | head -10
|
|
find . \( -name "*.test.*" -o -name "*.spec.*" -o -name "test_*" \) -not -path "*/node_modules/*" 2>/dev/null | head -40
|
|
```
|
|
|
|
### 2d. Cross-Reference
|
|
|
|
Match each requirement to existing tests by filename, imports, test descriptions. Record: requirement → test_file → status.
|
|
|
|
## 3. Gap Analysis
|
|
|
|
Classify each requirement:
|
|
|
|
| Status | Criteria |
|
|
|--------|----------|
|
|
| COVERED | Test exists, targets behavior, runs green |
|
|
| PARTIAL | Test exists, failing or incomplete |
|
|
| MISSING | No test found |
|
|
|
|
Build: `{ task_id, requirement, gap_type, suggested_test_path, suggested_command }`
|
|
|
|
No gaps → skip to Step 6, set `nyquist_compliant: true`.
|
|
|
|
## 4. Present Gap Plan
|
|
|
|
|
|
**Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available.
|
|
Call AskUserQuestion with gap table and options:
|
|
1. "Fix all gaps" → Step 5
|
|
2. "Skip — mark manual-only" → add to Manual-Only, Step 6
|
|
3. "Cancel" → exit
|
|
|
|
## 5. Spawn gsd-nyquist-auditor
|
|
|
|
```
|
|
Agent(
|
|
prompt="Read ~/.claude/agents/gsd-nyquist-auditor.md for instructions.\n\n" +
|
|
"<files_to_read>{PLAN, SUMMARY, impl files, VALIDATION.md}</files_to_read>" +
|
|
"<gaps>{gap list}</gaps>" +
|
|
"<test_infrastructure>{framework, config, commands}</test_infrastructure>" +
|
|
"<constraints>Never modify impl files. Max 3 debug iterations. Escalate impl bugs.</constraints>" +
|
|
"${AGENT_SKILLS_AUDITOR}",
|
|
subagent_type="gsd-nyquist-auditor",
|
|
model="{AUDITOR_MODEL}",
|
|
description="Fill validation gaps for Phase {N}"
|
|
)
|
|
```
|
|
|
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
|
|
|
|
Handle return:
|
|
- `## GAPS FILLED` → record tests + map updates, Step 6
|
|
- `## PARTIAL` → record resolved, move escalated to manual-only, Step 6
|
|
- `## ESCALATE` → move all to manual-only, Step 6
|
|
|
|
## 6. Generate/Update VALIDATION.md
|
|
|
|
**State B (create):**
|
|
1. Read template from `~/.claude/get-shit-done/templates/VALIDATION.md`
|
|
2. Fill: frontmatter, Test Infrastructure, Per-Task Map, Manual-Only, Sign-Off
|
|
3. Write to `${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md`
|
|
|
|
**State A (update):**
|
|
1. Update Per-Task Map statuses, add escalated to Manual-Only, update frontmatter
|
|
2. Append audit trail:
|
|
|
|
```markdown
|
|
## Validation Audit {date}
|
|
| Metric | Count |
|
|
|--------|-------|
|
|
| Gaps found | {N} |
|
|
| Resolved | {M} |
|
|
| Escalated | {K} |
|
|
```
|
|
|
|
## 7. Commit
|
|
|
|
```bash
|
|
git add {test_files}
|
|
git commit -m "test(phase-${PHASE}): add Nyquist validation tests"
|
|
|
|
gsd_run query commit "docs(phase-${PHASE}): add/update validation strategy"
|
|
```
|
|
|
|
## 8. Results + Routing
|
|
|
|
**Compliant:**
|
|
```
|
|
GSD > PHASE {N} IS NYQUIST-COMPLIANT
|
|
All requirements have automated verification.
|
|
▶ Next: /gsd:audit-milestone ${GSD_WS}
|
|
```
|
|
|
|
**Partial:**
|
|
```
|
|
GSD > PHASE {N} VALIDATED (PARTIAL)
|
|
{M} automated, {K} manual-only.
|
|
▶ Retry: /gsd:validate-phase {N} ${GSD_WS}
|
|
```
|
|
|
|
Display `/clear` reminder.
|
|
|
|
</process>
|
|
|
|
<success_criteria>
|
|
- [ ] Nyquist config checked (exit if disabled)
|
|
- [ ] Input state detected (A/B/C)
|
|
- [ ] State C exits cleanly
|
|
- [ ] PLAN/SUMMARY files read, requirement map built
|
|
- [ ] Test infrastructure detected
|
|
- [ ] Gaps classified (COVERED/PARTIAL/MISSING)
|
|
- [ ] User gate with gap table
|
|
- [ ] Auditor spawned with complete context
|
|
- [ ] All three return formats handled
|
|
- [ ] VALIDATION.md created or updated
|
|
- [ ] Test files committed separately
|
|
- [ ] Results with routing presented
|
|
</success_criteria>
|