fix: requirements tracking chain — strip brackets, add requirements field to plans and summaries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -68,9 +68,10 @@ Same methodology (goal-backward), different timing, different subject matter.
|
||||
|
||||
**Process:**
|
||||
1. Extract phase goal from ROADMAP.md
|
||||
2. Decompose goal into requirements (what must be true)
|
||||
3. For each requirement, find covering task(s)
|
||||
4. Flag requirements with no coverage
|
||||
2. Extract requirement IDs from ROADMAP.md `**Requirements:**` line for this phase (strip brackets if present)
|
||||
3. Verify each requirement ID appears in at least one plan's `requirements` frontmatter field
|
||||
4. For each requirement, find covering task(s) in the plan that claims it
|
||||
5. Flag requirements with no coverage or missing from all plans' `requirements` fields
|
||||
|
||||
**Red flags:**
|
||||
- Requirement has zero tasks addressing it
|
||||
|
||||
@@ -345,6 +345,7 @@ wave: N # Execution wave (1, 2, 3...)
|
||||
depends_on: [] # Plan IDs this plan requires
|
||||
files_modified: [] # Files this plan touches
|
||||
autonomous: true # false if plan has checkpoints
|
||||
requirements: [] # Requirement IDs this plan addresses (from ROADMAP)
|
||||
user_setup: [] # Human-required setup (omit if empty)
|
||||
|
||||
must_haves:
|
||||
@@ -410,6 +411,7 @@ After completion, create `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md`
|
||||
| `depends_on` | Yes | Plan IDs this plan requires |
|
||||
| `files_modified` | Yes | Files this plan touches |
|
||||
| `autonomous` | Yes | `true` if no checkpoints |
|
||||
| `requirements` | Yes | Requirement IDs this plan addresses (from ROADMAP) |
|
||||
| `user_setup` | No | Human-required setup items |
|
||||
| `must_haves` | Yes | Goal-backward verification criteria |
|
||||
|
||||
@@ -450,6 +452,9 @@ Only include what Claude literally cannot do.
|
||||
|
||||
## The Process
|
||||
|
||||
**Step 0: Extract Requirement IDs**
|
||||
Read ROADMAP.md `**Requirements:**` line for this phase. Strip brackets if present (e.g., `[AUTH-01, AUTH-02]` → `AUTH-01, AUTH-02`). Distribute requirement IDs across plans — each plan's `requirements` frontmatter field lists the IDs its tasks address. Every requirement ID must appear in at least one plan.
|
||||
|
||||
**Step 1: State the Goal**
|
||||
Take phase goal from ROADMAP.md. Must be outcome-shaped, not task-shaped.
|
||||
- Good: "Working chat interface" (outcome)
|
||||
|
||||
@@ -3196,7 +3196,7 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
|
||||
);
|
||||
|
||||
if (reqMatch) {
|
||||
const reqIds = reqMatch[1].split(/[,\s]+/).map(r => r.trim()).filter(Boolean);
|
||||
const reqIds = reqMatch[1].replace(/[\[\]]/g, '').split(/[,\s]+/).map(r => r.trim()).filter(Boolean);
|
||||
let reqContent = fs.readFileSync(reqPath, 'utf-8');
|
||||
|
||||
for (const reqId of reqIds) {
|
||||
|
||||
@@ -1825,6 +1825,79 @@ describe('phase complete command', () => {
|
||||
assert.ok(req.includes('| API-01 | Phase 2 | Pending |'), 'API-01 should remain Pending');
|
||||
});
|
||||
|
||||
test('handles requirements with bracket format [REQ-01, REQ-02]', () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'ROADMAP.md'),
|
||||
`# Roadmap
|
||||
|
||||
- [ ] Phase 1: Auth
|
||||
|
||||
### Phase 1: Auth
|
||||
**Goal:** User authentication
|
||||
**Requirements:** [AUTH-01, AUTH-02]
|
||||
**Plans:** 1 plans
|
||||
|
||||
### Phase 2: API
|
||||
**Goal:** Build API
|
||||
**Requirements:** [API-01]
|
||||
`
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'REQUIREMENTS.md'),
|
||||
`# Requirements
|
||||
|
||||
## v1 Requirements
|
||||
|
||||
### Authentication
|
||||
|
||||
- [ ] **AUTH-01**: User can sign up with email
|
||||
- [ ] **AUTH-02**: User can log in
|
||||
- [ ] **AUTH-03**: User can reset password
|
||||
|
||||
### API
|
||||
|
||||
- [ ] **API-01**: REST endpoints
|
||||
|
||||
## Traceability
|
||||
|
||||
| Requirement | Phase | Status |
|
||||
|-------------|-------|--------|
|
||||
| AUTH-01 | Phase 1 | Pending |
|
||||
| AUTH-02 | Phase 1 | Pending |
|
||||
| AUTH-03 | Phase 2 | Pending |
|
||||
| API-01 | Phase 2 | Pending |
|
||||
`
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'STATE.md'),
|
||||
`# State\n\n**Current Phase:** 01\n**Current Phase Name:** Auth\n**Status:** In progress\n**Current Plan:** 01-01\n**Last Activity:** 2025-01-01\n**Last Activity Description:** Working\n`
|
||||
);
|
||||
|
||||
const p1 = path.join(tmpDir, '.planning', 'phases', '01-auth');
|
||||
fs.mkdirSync(p1, { recursive: true });
|
||||
fs.writeFileSync(path.join(p1, '01-01-PLAN.md'), '# Plan');
|
||||
fs.writeFileSync(path.join(p1, '01-01-SUMMARY.md'), '# Summary');
|
||||
fs.mkdirSync(path.join(tmpDir, '.planning', 'phases', '02-api'), { recursive: true });
|
||||
|
||||
const result = runGsdTools('phase complete 1', tmpDir);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const req = fs.readFileSync(path.join(tmpDir, '.planning', 'REQUIREMENTS.md'), 'utf-8');
|
||||
|
||||
// Checkboxes updated for phase 1 requirements (brackets stripped)
|
||||
assert.ok(req.includes('- [x] **AUTH-01**'), 'AUTH-01 checkbox should be checked');
|
||||
assert.ok(req.includes('- [x] **AUTH-02**'), 'AUTH-02 checkbox should be checked');
|
||||
// Other requirements unchanged
|
||||
assert.ok(req.includes('- [ ] **AUTH-03**'), 'AUTH-03 should remain unchecked');
|
||||
assert.ok(req.includes('- [ ] **API-01**'), 'API-01 should remain unchecked');
|
||||
|
||||
// Traceability table updated
|
||||
assert.ok(req.includes('| AUTH-01 | Phase 1 | Complete |'), 'AUTH-01 status should be Complete');
|
||||
assert.ok(req.includes('| AUTH-02 | Phase 1 | Complete |'), 'AUTH-02 status should be Complete');
|
||||
assert.ok(req.includes('| AUTH-03 | Phase 2 | Pending |'), 'AUTH-03 should remain Pending');
|
||||
assert.ok(req.includes('| API-01 | Phase 2 | Pending |'), 'API-01 should remain Pending');
|
||||
});
|
||||
|
||||
test('handles phase with no requirements mapping', () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'ROADMAP.md'),
|
||||
|
||||
@@ -20,6 +20,7 @@ wave: N # Execution wave (1, 2, 3...). Pre-computed at plan
|
||||
depends_on: [] # Plan IDs this plan requires (e.g., ["01-01"]).
|
||||
files_modified: [] # Files this plan modifies.
|
||||
autonomous: true # false if plan has checkpoints requiring user interaction
|
||||
requirements: [] # Requirement IDs this plan addresses (from ROADMAP)
|
||||
user_setup: [] # Human-required setup Claude cannot automate (see below)
|
||||
|
||||
# Goal-backward verification (derived during planning, verified after execution)
|
||||
@@ -129,6 +130,7 @@ After completion, create `.planning/phases/XX-name/{phase}-{plan}-SUMMARY.md`
|
||||
| `depends_on` | Yes | Array of plan IDs this plan requires. |
|
||||
| `files_modified` | Yes | Files this plan touches. |
|
||||
| `autonomous` | Yes | `true` if no checkpoints, `false` if has checkpoints |
|
||||
| `requirements` | Yes | Requirement IDs this plan addresses (from ROADMAP) |
|
||||
| `user_setup` | No | Array of human-required setup items (external services) |
|
||||
| `must_haves` | Yes | Goal-backward verification criteria (see below) |
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Decimal phases appear between their surrounding integers in numeric order.
|
||||
### Phase 1: [Name]
|
||||
**Goal**: [What this phase delivers]
|
||||
**Depends on**: Nothing (first phase)
|
||||
**Requirements**: [REQ-01, REQ-02, REQ-03]
|
||||
**Requirements**: [REQ-01, REQ-02, REQ-03] <!-- brackets optional, parser handles both formats -->
|
||||
**Success Criteria** (what must be TRUE):
|
||||
1. [Observable behavior from user perspective]
|
||||
2. [Observable behavior from user perspective]
|
||||
|
||||
@@ -38,6 +38,8 @@ patterns-established:
|
||||
- "Pattern 1: description"
|
||||
- "Pattern 2: description"
|
||||
|
||||
requirements-completed: [] # Requirement IDs addressed by this plan (from PLAN frontmatter)
|
||||
|
||||
# Metrics
|
||||
duration: Xmin
|
||||
completed: YYYY-MM-DD
|
||||
|
||||
@@ -322,7 +322,7 @@ If user_setup exists: create `{phase}-USER-SETUP.md` using template `~/.claude/g
|
||||
<step name="create_summary">
|
||||
Create `{phase}-{plan}-SUMMARY.md` at `.planning/phases/XX-name/`. Use `~/.claude/get-shit-done/templates/summary.md`.
|
||||
|
||||
**Frontmatter:** phase, plan, subsystem, tags | requires/provides/affects | tech-stack.added/patterns | key-files.created/modified | key-decisions | duration ($DURATION), completed ($PLAN_END_TIME date).
|
||||
**Frontmatter:** phase, plan, subsystem, tags | requires/provides/affects | tech-stack.added/patterns | key-files.created/modified | key-decisions | requirements-completed (from PLAN.md requirements field) | duration ($DURATION), completed ($PLAN_END_TIME date).
|
||||
|
||||
Title: `# Phase [X] Plan [Y]: [Name] Summary`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user