From 1764abc61593b660b526a75f92232c48a7ce62ed Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Tue, 17 Feb 2026 13:19:02 -0600 Subject: [PATCH] fix: executor updates ROADMAP.md and REQUIREMENTS.md per-plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gsd-executor had no instruction to update ROADMAP or REQUIREMENTS after completing a plan — both stayed unchecked throughout milestone execution. - Add `roadmap update-plan-progress` call to executor state_updates - Add `requirements mark-complete` CLI command to gsd-tools - Wire requirement marking into executor and execute-plan workflows - Include ROADMAP.md and REQUIREMENTS.md in executor final commit Co-Authored-By: Claude Opus 4.6 --- agents/gsd-executor.md | 18 ++++- get-shit-done/bin/gsd-tools.cjs | 83 ++++++++++++++++++++++++ get-shit-done/workflows/execute-phase.md | 3 +- get-shit-done/workflows/execute-plan.md | 12 +++- 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/agents/gsd-executor.md b/agents/gsd-executor.md index dcaf4c54e..df6a5d4bd 100644 --- a/agents/gsd-executor.md +++ b/agents/gsd-executor.md @@ -382,12 +382,25 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs state record-session \ --stopped-at "Completed ${PHASE}-${PLAN}-PLAN.md" ``` +```bash +# Update ROADMAP.md progress for this phase (plan counts, status) +node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap update-plan-progress "${PHASE_NUMBER}" + +# Mark completed requirements from PLAN.md frontmatter +# Extract the `requirements` array from the plan's frontmatter, then mark each complete +node ~/.claude/get-shit-done/bin/gsd-tools.cjs requirements mark-complete ${REQ_IDS} +``` + +**Requirement IDs:** Extract from the PLAN.md frontmatter `requirements:` field (e.g., `requirements: [AUTH-01, AUTH-02]`). Pass all IDs to `requirements mark-complete`. If the plan has no requirements field, skip this step. + **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 +- `roadmap update-plan-progress`: Updates ROADMAP.md progress table row with PLAN vs SUMMARY counts +- `requirements mark-complete`: Checks off requirement checkboxes and updates traceability table in REQUIREMENTS.md **Extract decisions from SUMMARY.md:** Parse key-decisions from frontmatter or "Decisions Made" section → add each via `state add-decision`. @@ -399,7 +412,7 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs state add-blocker "Blocker descri ```bash -node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md +node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md ``` Separate from per-task commits — captures execution results only. @@ -432,6 +445,7 @@ Plan execution complete when: - [ ] Authentication gates handled and documented - [ ] SUMMARY.md created with substantive content - [ ] STATE.md updated (position, decisions, issues, session) -- [ ] Final metadata commit made +- [ ] ROADMAP.md updated with plan progress (via `roadmap update-plan-progress`) +- [ ] Final metadata commit made (includes SUMMARY.md, STATE.md, ROADMAP.md) - [ ] Completion format returned to orchestrator diff --git a/get-shit-done/bin/gsd-tools.cjs b/get-shit-done/bin/gsd-tools.cjs index 6b9a997d8..2e6a2ff89 100755 --- a/get-shit-done/bin/gsd-tools.cjs +++ b/get-shit-done/bin/gsd-tools.cjs @@ -41,6 +41,10 @@ * roadmap analyze Full roadmap parse with disk status * roadmap update-plan-progress Update progress table row from disk (PLAN vs SUMMARY counts) * + * Requirements Operations: + * requirements mark-complete Mark requirement IDs as complete in REQUIREMENTS.md + * Accepts: REQ-01,REQ-02 or REQ-01 REQ-02 or [REQ-01, REQ-02] + * * Milestone Operations: * milestone complete Archive milestone, create MILESTONES.md * [--name ] @@ -3131,6 +3135,75 @@ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) { }, raw, `${summaryCount}/${planCount} ${status}`); } +// ─── Requirements Mark Complete ─────────────────────────────────────────────── + +function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) { + if (!reqIdsRaw || reqIdsRaw.length === 0) { + error('requirement IDs required. Usage: requirements mark-complete REQ-01,REQ-02 or REQ-01 REQ-02'); + } + + // Accept comma-separated, space-separated, or bracket-wrapped: [REQ-01, REQ-02] + const reqIds = reqIdsRaw + .join(' ') + .replace(/[\[\]]/g, '') + .split(/[,\s]+/) + .map(r => r.trim()) + .filter(Boolean); + + if (reqIds.length === 0) { + error('no valid requirement IDs found'); + } + + const reqPath = path.join(cwd, '.planning', 'REQUIREMENTS.md'); + if (!fs.existsSync(reqPath)) { + output({ updated: false, reason: 'REQUIREMENTS.md not found', ids: reqIds }, raw, 'no requirements file'); + return; + } + + let reqContent = fs.readFileSync(reqPath, 'utf-8'); + const updated = []; + const notFound = []; + + for (const reqId of reqIds) { + let found = false; + + // Update checkbox: - [ ] **REQ-ID** → - [x] **REQ-ID** + const checkboxPattern = new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${reqId}\\*\\*)`, 'gi'); + if (checkboxPattern.test(reqContent)) { + reqContent = reqContent.replace(checkboxPattern, '$1x$2'); + found = true; + } + + // Update traceability table: | REQ-ID | Phase N | Pending | → | REQ-ID | Phase N | Complete | + const tablePattern = new RegExp(`(\\|\\s*${reqId}\\s*\\|[^|]+\\|)\\s*Pending\\s*(\\|)`, 'gi'); + if (tablePattern.test(reqContent)) { + // Re-read since test() advances lastIndex for global regex + reqContent = reqContent.replace( + new RegExp(`(\\|\\s*${reqId}\\s*\\|[^|]+\\|)\\s*Pending\\s*(\\|)`, 'gi'), + '$1 Complete $2' + ); + found = true; + } + + if (found) { + updated.push(reqId); + } else { + notFound.push(reqId); + } + } + + if (updated.length > 0) { + fs.writeFileSync(reqPath, reqContent, 'utf-8'); + } + + output({ + updated: updated.length > 0, + marked_complete: updated, + not_found: notFound, + total: reqIds.length, + }, raw, `${updated.length}/${reqIds.length} requirements marked complete`); +} + // ─── Phase Complete (Transition) ────────────────────────────────────────────── function cmdPhaseComplete(cwd, phaseNum, raw) { @@ -5078,6 +5151,16 @@ async function main() { break; } + case 'requirements': { + const subcommand = args[1]; + if (subcommand === 'mark-complete') { + cmdRequirementsMarkComplete(cwd, args.slice(2), raw); + } else { + error('Unknown requirements subcommand. Available: mark-complete'); + } + break; + } + case 'phase': { const subcommand = args[1]; if (subcommand === 'next-decimal') { diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md index e9f6cae52..e902bebce 100644 --- a/get-shit-done/workflows/execute-phase.md +++ b/get-shit-done/workflows/execute-phase.md @@ -106,7 +106,7 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true` prompt=" Execute plan {plan_number} of phase {phase_number}-{phase_name}. - Commit each task atomically. Create SUMMARY.md. Update STATE.md. + Commit each task atomically. Create SUMMARY.md. Update STATE.md and ROADMAP.md. @@ -128,6 +128,7 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true` - [ ] Each task committed individually - [ ] SUMMARY.md created in plan directory - [ ] STATE.md updated with position and decisions + - [ ] ROADMAP.md updated with plan progress (via `roadmap update-plan-progress`) " ) diff --git a/get-shit-done/workflows/execute-plan.md b/get-shit-done/workflows/execute-plan.md index 16556b5fd..4b51d7c40 100644 --- a/get-shit-done/workflows/execute-plan.md +++ b/get-shit-done/workflows/execute-plan.md @@ -386,11 +386,21 @@ node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap update-plan-progress "${P Counts PLAN vs SUMMARY files on disk. Updates progress table row with correct count and status (`In Progress` or `Complete` with date). + +Mark completed requirements from the PLAN.md frontmatter `requirements:` field: + +```bash +node ~/.claude/get-shit-done/bin/gsd-tools.cjs requirements mark-complete ${REQ_IDS} +``` + +Extract requirement IDs from the plan's frontmatter (e.g., `requirements: [AUTH-01, AUTH-02]`). If no requirements field, skip. + + Task code already committed per-task. Commit plan metadata: ```bash -node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md +node ~/.claude/get-shit-done/bin/gsd-tools.cjs commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md ```