feat(gsd-tools): frontmatter CRUD, verification suite, template fill, state progression (#485)

* feat(gsd-tools): add frontmatter CRUD, verification suite, template fill, and state progression

Four new command groups that delegate deterministic operations from AI agents to code:

- frontmatter get/set/merge/validate: Safe YAML frontmatter manipulation with schema validation
- verify plan-structure/phase-completeness/references/commits/artifacts/key-links: Structural checks agents previously burned context on
- template fill summary/plan/verification: Pre-filled document skeletons so agents only fill creative content
- state advance-plan/record-metric/update-progress/add-decision/add-blocker/resolve-blocker/record-session: Automate arithmetic and formatting in STATE.md

Adds reconstructFrontmatter() + spliceFrontmatter() helpers for safe frontmatter roundtripping,
and parseMustHavesBlock() for 3-level YAML parsing of must_haves structures.

20 new functions, ~1037 new lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: wire gsd-tools commands into agents and workflows

- gsd-verifier: use `verify artifacts` and `verify key-links` instead of
  manual grep patterns for stub detection and wiring verification
- gsd-executor: use `state advance-plan`, `state update-progress`,
  `state record-metric`, `state add-decision`, `state record-session`
  instead of manual STATE.md manipulation
- gsd-plan-checker: use `verify plan-structure` and `frontmatter get`
  for structural validation and must_haves extraction
- gsd-planner: add validation step using `frontmatter validate` and
  `verify plan-structure` after writing PLAN.md
- execute-plan.md: use gsd-tools state commands for position/progress updates
- verify-phase.md: use gsd-tools for must_haves extraction and artifact/link verification

This makes the gsd-tools commands from PR #485 actually used by the system.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
TÂCHES
2026-02-08 09:28:50 -06:00
committed by GitHub
parent 4072fd2baf
commit 6a2d1f1bfb
7 changed files with 1255 additions and 82 deletions

View File

@@ -323,22 +323,44 @@ Do NOT skip. Do NOT proceed to state updates if self-check fails.
</self_check>
<state_updates>
After SUMMARY.md, update STATE.md:
After SUMMARY.md, update STATE.md using gsd-tools:
**Current Position:**
```markdown
Phase: [current] of [total] ([phase name])
Plan: [just completed] of [total in phase]
Status: [In progress / Phase complete]
Last activity: [today] - Completed {phase}-{plan}-PLAN.md
Progress: [progress bar]
```bash
# Advance plan counter (handles edge cases automatically)
node ~/.claude/get-shit-done/bin/gsd-tools.js state advance-plan
# Recalculate progress bar from disk state
node ~/.claude/get-shit-done/bin/gsd-tools.js state update-progress
# Record execution metrics
node ~/.claude/get-shit-done/bin/gsd-tools.js state record-metric \
--phase "${PHASE}" --plan "${PLAN}" --duration "${DURATION}" \
--tasks "${TASK_COUNT}" --files "${FILE_COUNT}"
# Add decisions (extract from SUMMARY.md key-decisions)
for decision in "${DECISIONS[@]}"; do
node ~/.claude/get-shit-done/bin/gsd-tools.js state add-decision \
--phase "${PHASE}" --summary "${decision}"
done
# Update session info
node ~/.claude/get-shit-done/bin/gsd-tools.js state record-session \
--stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md"
```
**Progress bar:** Count total plans, count completed (SUMMARY.md files), render █ for complete, ░ for incomplete.
**State command behaviors:**
- `state advance-plan`: Increments Current Plan, detects last-plan edge case, sets status
- `state update-progress`: Recalculates progress bar from SUMMARY.md counts on disk
- `state record-metric`: Appends to Performance Metrics table
- `state add-decision`: Adds to Decisions section, removes placeholders
- `state record-session`: Updates Last session timestamp and Stopped At fields
**Extract from SUMMARY.md:** Decisions → add to STATE.md Decisions table. Next Phase Readiness blockers → add to STATE.md.
**Extract decisions from SUMMARY.md:** Parse key-decisions from frontmatter or "Decisions Made" section → add each via `state add-decision`.
**Session Continuity:** Last session date, stopped at, resume file path.
**For blockers found during execution:**
```bash
node ~/.claude/get-shit-done/bin/gsd-tools.js state add-blocker "Blocker description"
```
</state_updates>
<final_commit>

View File

@@ -316,18 +316,35 @@ ls "$phase_dir"/*-BRIEF.md 2>/dev/null
## Step 2: Load All Plans
Use gsd-tools to validate plan structure:
```bash
for plan in "$PHASE_DIR"/*-PLAN.md; do
echo "=== $plan ==="
cat "$plan"
PLAN_STRUCTURE=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify plan-structure "$plan")
echo "$PLAN_STRUCTURE"
done
```
**Parse:** Frontmatter (phase, plan, wave, depends_on, files_modified, autonomous, must_haves), objective, tasks (type, name, files, action, verify, done), verification/success criteria.
Parse JSON result: `{ valid, errors, warnings, task_count, tasks: [{name, hasFiles, hasAction, hasVerify, hasDone}], frontmatter_fields }`
Map errors/warnings to verification dimensions:
- Missing frontmatter field → `task_completeness` or `must_haves_derivation`
- Task missing elements → `task_completeness`
- Wave/depends_on inconsistency → `dependency_correctness`
- Checkpoint/autonomous mismatch → `task_completeness`
## Step 3: Parse must_haves
Extract from each plan frontmatter:
Extract must_haves from each plan using gsd-tools:
```bash
MUST_HAVES=$(node ~/.claude/get-shit-done/bin/gsd-tools.js frontmatter get "$PLAN_PATH" --field must_haves)
```
Returns JSON: `{ truths: [...], artifacts: [...], key_links: [...] }`
**Expected structure:**
```yaml
must_haves:
@@ -362,12 +379,24 @@ For each requirement: find covering task(s), verify action is specific, flag gap
## Step 5: Validate Task Structure
Use gsd-tools plan-structure verification (already run in Step 2):
```bash
grep -c "<task" "$PHASE_DIR"/*-PLAN.md
grep -B5 "</task>" "$PHASE_DIR"/*-PLAN.md | grep -v "<verify>"
PLAN_STRUCTURE=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify plan-structure "$PLAN_PATH")
```
Check: valid task type (auto, checkpoint:*, tdd), auto tasks have files/action/verify/done, action is specific, verify is runnable, done is measurable.
The `tasks` array in the result shows each task's completeness:
- `hasFiles` — files element present
- `hasAction` — action element present
- `hasVerify` — verify element present
- `hasDone` — done element present
**Check:** valid task type (auto, checkpoint:*, tdd), auto tasks have files/action/verify/done, action is specific, verify is runnable, done is measurable.
**For manual validation of specificity** (gsd-tools checks structure, not content quality):
```bash
grep -B5 "</task>" "$PHASE_DIR"/*-PLAN.md | grep -v "<verify>"
```
## Step 6: Verify Dependency Graph

View File

@@ -1001,6 +1001,34 @@ Write to `.planning/phases/XX-name/{phase}-{NN}-PLAN.md`
Include all frontmatter fields.
</step>
<step name="validate_plan">
Validate each created PLAN.md using gsd-tools:
```bash
VALID=$(node ~/.claude/get-shit-done/bin/gsd-tools.js frontmatter validate "$PLAN_PATH" --schema plan)
```
Returns JSON: `{ valid, missing, present, schema }`
**If `valid=false`:** Fix missing required fields before proceeding.
Required plan frontmatter fields:
- `phase`, `plan`, `type`, `wave`, `depends_on`, `files_modified`, `autonomous`, `must_haves`
Also validate plan structure:
```bash
STRUCTURE=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify plan-structure "$PLAN_PATH")
```
Returns JSON: `{ valid, errors, warnings, task_count, tasks }`
**If errors exist:** Fix before committing:
- Missing `<name>` in task → add name element
- Missing `<action>` → add action element
- Checkpoint/autonomous mismatch → update `autonomous: false`
</step>
<step name="update_roadmap">
Update ROADMAP.md to finalize phase placeholders:

View File

@@ -115,58 +115,38 @@ For each truth:
## Step 4: Verify Artifacts (Three Levels)
### Level 1: Existence
Use gsd-tools for artifact verification against must_haves in PLAN frontmatter:
```bash
[ -f "$path" ] && echo "EXISTS" || echo "MISSING"
ARTIFACT_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify artifacts "$PLAN_PATH")
```
If MISSING → artifact fails, record and continue.
Parse JSON result: `{ all_passed, passed, total, artifacts: [{path, exists, issues, passed}] }`
### Level 2: Substantive
For each artifact in result:
- `exists=false` → MISSING
- `issues` contains "Only N lines" or "Missing pattern" → STUB
- `passed=true` → VERIFIED
**Line count check** — minimums by type:
- Component: 15+ lines | API route: 10+ | Hook/util: 10+ | Schema: 5+
**Artifact status mapping:**
**Stub pattern check:**
```bash
check_stubs() {
local path="$1"
local stubs=$(grep -c -E "TODO|FIXME|placeholder|not implemented|coming soon" "$path" 2>/dev/null || echo 0)
local empty=$(grep -c -E "return null|return undefined|return \{\}|return \[\]" "$path" 2>/dev/null || echo 0)
local placeholder=$(grep -c -E "will be here|placeholder|lorem ipsum" "$path" 2>/dev/null || echo 0)
local total=$((stubs + empty + placeholder))
[ "$total" -gt 0 ] && echo "STUB_PATTERNS ($total found)" || echo "NO_STUBS"
}
```
**Export check:**
```bash
grep -E "^export (default )?(function|const|class)" "$path" && echo "HAS_EXPORTS" || echo "NO_EXPORTS"
```
**Combine Level 2:**
- SUBSTANTIVE: Adequate length + no stubs + has exports
- STUB: Too short OR has stub patterns OR no exports
- PARTIAL: Mixed signals
### Level 3: Wired
**Import check:**
| exists | issues empty | Status |
| ------ | ------------ | ----------- |
| true | true | ✓ VERIFIED |
| true | false | ✗ STUB |
| false | - | ✗ MISSING |
**For wiring verification (Level 3)**, check imports/usage manually for artifacts that pass Levels 1-2:
```bash
# Import check
grep -r "import.*$artifact_name" "${search_path:-src/}" --include="*.ts" --include="*.tsx" 2>/dev/null | wc -l
```
**Usage check:**
```bash
# Usage check (beyond imports)
grep -r "$artifact_name" "${search_path:-src/}" --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v "import" | wc -l
```
**Combine Level 3:**
**Wiring status:**
- WIRED: Imported AND used
- ORPHANED: Exists but not imported/used
- PARTIAL: Imported but not used (or vice versa)
@@ -184,14 +164,25 @@ grep -r "$artifact_name" "${search_path:-src/}" --include="*.ts" --include="*.ts
Key links are critical connections. If broken, the goal fails even with all artifacts present.
**For each link pattern, verify: (1) call exists, (2) response/result is used.**
Use gsd-tools for key link verification against must_haves in PLAN frontmatter:
```bash
LINKS_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify key-links "$PLAN_PATH")
```
Parse JSON result: `{ all_verified, verified, total, links: [{from, to, via, verified, detail}] }`
For each link:
- `verified=true` → WIRED
- `verified=false` with "not found" in detail → NOT_WIRED
- `verified=false` with "Pattern not found" → PARTIAL
**Fallback patterns** (if must_haves.key_links not defined in PLAN):
### Pattern: Component → API
```bash
# Check for fetch/axios call to the API
grep -E "fetch\(['\"].*$api_path|axios\.(get|post).*$api_path" "$component" 2>/dev/null
# Check response handling
grep -A 5 "fetch\|axios" "$component" | grep -E "await|\.then|setData|setState" 2>/dev/null
```
@@ -200,9 +191,7 @@ Status: WIRED (call + response handling) | PARTIAL (call, no response use) | NOT
### Pattern: API → Database
```bash
# Check for DB query
grep -E "prisma\.$model|db\.$model|$model\.(find|create|update|delete)" "$route" 2>/dev/null
# Check result returned
grep -E "return.*json.*\w+|res\.json\(\w+" "$route" 2>/dev/null
```
@@ -211,7 +200,6 @@ Status: WIRED (query + result returned) | PARTIAL (query, static return) | NOT_W
### Pattern: Form → Handler
```bash
# Check onSubmit handler exists and has real implementation
grep -E "onSubmit=\{|handleSubmit" "$component" 2>/dev/null
grep -A 10 "onSubmit.*=" "$component" | grep -E "fetch|axios|mutate|dispatch" 2>/dev/null
```
@@ -221,7 +209,6 @@ Status: WIRED (handler + API call) | STUB (only logs/preventDefault) | NOT_WIRED
### Pattern: State → Render
```bash
# Check state exists and is rendered in JSX
grep -E "useState.*$state_var|\[$state_var," "$component" 2>/dev/null
grep -E "\{.*$state_var.*\}|\{$state_var\." "$component" 2>/dev/null
```
@@ -244,9 +231,19 @@ For each requirement: parse description → identify supporting truths/artifacts
## Step 7: Scan for Anti-Patterns
Identify files modified in this phase:
Identify files modified in this phase from SUMMARY.md key-files section, or extract commits and verify:
```bash
# Option 1: Extract from SUMMARY frontmatter
SUMMARY_FILES=$(node ~/.claude/get-shit-done/bin/gsd-tools.js summary-extract "$PHASE_DIR"/*-SUMMARY.md --fields key-files)
# Option 2: Verify commits exist (if commit hashes documented)
COMMIT_HASHES=$(grep -oE "[a-f0-9]{7,40}" "$PHASE_DIR"/*-SUMMARY.md | head -10)
if [ -n "$COMMIT_HASHES" ]; then
COMMITS_VALID=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify commits $COMMIT_HASHES)
fi
# Fallback: grep for files
grep -E "^\- \`" "$PHASE_DIR"/*-SUMMARY.md | sed 's/.*`\([^`]*\)`.*/\1/' | sort -u
```

File diff suppressed because it is too large Load Diff

View File

@@ -333,15 +333,45 @@ Next: more plans → "Ready for {next-plan}" | last → "Phase complete, ready f
</step>
<step name="update_current_position">
Update STATE.md: Phase [current]/[total] ([name]) | Plan [completed]/[total] | Status | Last activity: [today] - Completed {phase}-{plan} | Progress bar (█/░). Calculate: (total SUMMARYs / total PLANs) × 100%.
Update STATE.md using gsd-tools:
```bash
# Advance plan counter (handles last-plan edge case)
node ~/.claude/get-shit-done/bin/gsd-tools.js state advance-plan
# Recalculate progress bar from disk state
node ~/.claude/get-shit-done/bin/gsd-tools.js state update-progress
# Record execution metrics
node ~/.claude/get-shit-done/bin/gsd-tools.js state record-metric \
--phase "${PHASE}" --plan "${PLAN}" --duration "${DURATION}" \
--tasks "${TASK_COUNT}" --files "${FILE_COUNT}"
```
</step>
<step name="extract_decisions_and_issues">
From SUMMARY: "Decisions Made" (if not "None") → STATE.md Decisions: `| [phase] | [summary] | [rationale] |`. "Next Phase Readiness" blockers → STATE.md "Blockers/Concerns Carried Forward".
From SUMMARY: Extract decisions and add to STATE.md:
```bash
# Add each decision from SUMMARY key-decisions
node ~/.claude/get-shit-done/bin/gsd-tools.js state add-decision \
--phase "${PHASE}" --summary "${DECISION_TEXT}" --rationale "${RATIONALE}"
# Add blockers if any found
node ~/.claude/get-shit-done/bin/gsd-tools.js state add-blocker "Blocker description"
```
</step>
<step name="update_session_continuity">
STATE.md Session: Last session [date/time] | Stopped at: Completed {phase}-{plan} | Resume file: [path or "None"]. Keep STATE.md under 150 lines.
Update session info using gsd-tools:
```bash
node ~/.claude/get-shit-done/bin/gsd-tools.js state record-session \
--stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md" \
--resume-file "None"
```
Keep STATE.md under 150 lines.
</step>
<step name="issues_review_gate">

View File

@@ -46,15 +46,22 @@ Extract **phase goal** from ROADMAP.md (the outcome to verify, not tasks) and **
<step name="establish_must_haves">
**Option A: Must-haves in PLAN frontmatter**
Use gsd-tools to extract must_haves from each PLAN:
```bash
grep -l "must_haves:" "$PHASE_DIR"/*-PLAN.md 2>/dev/null
for plan in "$PHASE_DIR"/*-PLAN.md; do
MUST_HAVES=$(node ~/.claude/get-shit-done/bin/gsd-tools.js frontmatter get "$plan" --field must_haves)
echo "=== $plan ===" && echo "$MUST_HAVES"
done
```
If found, extract truths, artifacts (with paths), and key_links (from/to/via).
Returns JSON: `{ truths: [...], artifacts: [...], key_links: [...] }`
Aggregate all must_haves across plans for phase-level verification.
**Option B: Derive from phase goal**
If no must_haves in frontmatter:
If no must_haves in frontmatter (MUST_HAVES returns error or empty):
1. State the goal from ROADMAP.md
2. Derive **truths** (3-7 observable behaviors, each testable)
3. Derive **artifacts** (concrete file paths for each truth)
@@ -73,20 +80,28 @@ For each truth: identify supporting artifacts → check artifact status → chec
</step>
<step name="verify_artifacts">
For each required artifact, verify three levels:
Use gsd-tools for artifact verification against must_haves in each PLAN:
**Level 1 — Existence:** File/directory exists. If MISSING → record and continue.
```bash
for plan in "$PHASE_DIR"/*-PLAN.md; do
ARTIFACT_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify artifacts "$plan")
echo "=== $plan ===" && echo "$ARTIFACT_RESULT"
done
```
**Level 2 — Substantive:** Real implementation, not a stub.
- Line minimums: Component 15+, API route 10+, Hook/util 10+, Schema 5+
- Stub detection: `TODO|FIXME|placeholder|not implemented|coming soon`, empty returns (`return null|return {}|return []`), placeholder content
- Export check: `export (default )?(function|const|class)` exists
- SUBSTANTIVE = adequate length + no stubs + has exports. STUB = too short OR stub patterns OR no exports. PARTIAL = mixed.
Parse JSON result: `{ all_passed, passed, total, artifacts: [{path, exists, issues, passed}] }`
**Level 3 — Wired:** Connected to the system.
- Import: `grep -r "import.*$artifact_name" src/ --include="*.ts" --include="*.tsx"` → IMPORTED
- Usage: same grep excluding import lines → USED
- WIRED = imported AND used. ORPHANED = exists but not imported/used. PARTIAL = imported but unused.
**Artifact status from result:**
- `exists=false` → MISSING
- `issues` not empty → STUB (check issues for "Only N lines" or "Missing pattern")
- `passed=true` → VERIFIED (Levels 1-2 pass)
**Level 3 — Wired (manual check for artifacts that pass Levels 1-2):**
```bash
grep -r "import.*$artifact_name" src/ --include="*.ts" --include="*.tsx" # IMPORTED
grep -r "$artifact_name" src/ --include="*.ts" --include="*.tsx" | grep -v "import" # USED
```
WIRED = imported AND used. ORPHANED = exists but not imported/used.
| Exists | Substantive | Wired | Status |
|--------|-------------|-------|--------|
@@ -97,7 +112,23 @@ For each required artifact, verify three levels:
</step>
<step name="verify_wiring">
Key links are critical connections — if broken, goal fails even with all artifacts present.
Use gsd-tools for key link verification against must_haves in each PLAN:
```bash
for plan in "$PHASE_DIR"/*-PLAN.md; do
LINKS_RESULT=$(node ~/.claude/get-shit-done/bin/gsd-tools.js verify key-links "$plan")
echo "=== $plan ===" && echo "$LINKS_RESULT"
done
```
Parse JSON result: `{ all_verified, verified, total, links: [{from, to, via, verified, detail}] }`
**Link status from result:**
- `verified=true` → WIRED
- `verified=false` with "not found" → NOT_WIRED
- `verified=false` with "Pattern not found" → PARTIAL
**Fallback patterns (if key_links not in must_haves):**
| Pattern | Check | Status |
|---------|-------|--------|