valent-pipeline 0.2.21 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/pipeline/docs/prd-completion-audit-design.md +132 -0
- package/pipeline/steps/orchestration/sprint-execute.md +22 -0
- package/pipeline/steps/orchestration/sprint-init.md +5 -2
- package/pipeline/steps/orchestration/sprint-plan.md +9 -3
- package/pipeline/steps/orchestration/sprint-review.md +4 -3
package/package.json
CHANGED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Design: Post-Implementation PRD Completion Audit
|
|
2
|
+
|
|
3
|
+
**Status:** Proposal
|
|
4
|
+
**Scope:** Both epic and project mode
|
|
5
|
+
**Where it runs:** After all stories ship (Step 5 in valent-run-epic and valent-run-project), before writing the epic/project report.
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
The epics-and-stories breakdown is done once, early, and may miss PRD requirements. Stories can also be cancelled or blocked during execution. There is currently no post-implementation check that verifies the full PRD was actually delivered. The existing pre-implementation readiness check (bmad-check-implementation-readiness) runs before any code is written and only validates that epics *claim* to cover FRs — it doesn't verify that shipped code actually delivers them.
|
|
10
|
+
|
|
11
|
+
## Proposed Solution
|
|
12
|
+
|
|
13
|
+
A new orchestration step (`sprint-prd-audit.md`) that runs at epic/project completion. It re-reads the PRD, extracts all functional requirements, and checks each against what was actually shipped — generating gap stories for anything missed.
|
|
14
|
+
|
|
15
|
+
### Trigger Point
|
|
16
|
+
|
|
17
|
+
Insert between the sprint loop exit and the report generation:
|
|
18
|
+
|
|
19
|
+
- **valent-run-epic SKILL.md:** After Step 4 loop exits, before Step 5a (Write Epic Report)
|
|
20
|
+
- **valent-run-project SKILL.md:** After Step 4 loop exits, before Step 5a (Write Project Report)
|
|
21
|
+
|
|
22
|
+
### Step-by-Step Flow
|
|
23
|
+
|
|
24
|
+
#### Step 1: Extract PRD Functional Requirements
|
|
25
|
+
|
|
26
|
+
Read the PRD from `{prd_path}` (already a pipeline config variable). Extract every functional requirement (FR), keyed by FR number or section heading. Build a checklist:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
FR1: [requirement text] → status: unchecked
|
|
30
|
+
FR2: [requirement text] → status: unchecked
|
|
31
|
+
...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Also extract non-functional requirements (NFRs) that have testable acceptance criteria.
|
|
35
|
+
|
|
36
|
+
#### Step 2: Map Shipped Stories to FRs
|
|
37
|
+
|
|
38
|
+
For each shipped story (from `{epic_progress_path}` or `{backlog_path}` where status = `shipped`):
|
|
39
|
+
|
|
40
|
+
1. Read the story's `reqs-brief.md` from its output directory
|
|
41
|
+
2. Extract which FRs the story claims to address (REQS agent already tags these during grooming)
|
|
42
|
+
3. Mark those FRs as `covered` in the checklist
|
|
43
|
+
|
|
44
|
+
For cancelled or blocked stories:
|
|
45
|
+
- Extract their claimed FRs
|
|
46
|
+
- Mark as `gap-cancelled` or `gap-blocked`
|
|
47
|
+
|
|
48
|
+
#### Step 3: Cross-Reference with Test Evidence
|
|
49
|
+
|
|
50
|
+
For each `covered` FR, verify that shipped test evidence exists:
|
|
51
|
+
|
|
52
|
+
1. Query the calibration table for the covering story's test results
|
|
53
|
+
2. Check that the story's QA-B test spec includes tests traceable to the FR
|
|
54
|
+
3. If a FR is "covered" by a story but that story had no tests touching the FR, downgrade to `weak-coverage`
|
|
55
|
+
|
|
56
|
+
#### Step 4: Generate Gap Report
|
|
57
|
+
|
|
58
|
+
Produce `prd-audit-report.md` in the epic/project output directory:
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
# PRD Completion Audit
|
|
62
|
+
|
|
63
|
+
## Coverage Summary
|
|
64
|
+
- Total FRs: {count}
|
|
65
|
+
- Covered (with tests): {count}
|
|
66
|
+
- Weak coverage (no direct tests): {count}
|
|
67
|
+
- Gaps (cancelled/blocked story): {count}
|
|
68
|
+
- Gaps (never mapped to a story): {count}
|
|
69
|
+
- Coverage: {percentage}%
|
|
70
|
+
|
|
71
|
+
## Gap Details
|
|
72
|
+
|
|
73
|
+
### Never Mapped to a Story
|
|
74
|
+
| FR | Requirement | Recommendation |
|
|
75
|
+
|----|------------|----------------|
|
|
76
|
+
| FR7 | [text] | Create story in epic {X} |
|
|
77
|
+
|
|
78
|
+
### Lost to Cancelled/Blocked Stories
|
|
79
|
+
| FR | Requirement | Original Story | Status | Recommendation |
|
|
80
|
+
|----|------------|---------------|--------|----------------|
|
|
81
|
+
| FR3 | [text] | KANBAN-005 | cancelled | Re-scope into new story |
|
|
82
|
+
|
|
83
|
+
### Weak Coverage (no direct test evidence)
|
|
84
|
+
| FR | Requirement | Covering Story | Recommendation |
|
|
85
|
+
|----|------------|---------------|----------------|
|
|
86
|
+
| FR9 | [text] | KANBAN-012 | Add targeted tests |
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Step 5: Generate Gap Stories (Optional, User-Confirmed)
|
|
90
|
+
|
|
91
|
+
If gaps exist:
|
|
92
|
+
|
|
93
|
+
1. Present the gap report to the user
|
|
94
|
+
2. Ask: "Generate backlog stories for {N} uncovered requirements?"
|
|
95
|
+
3. If confirmed:
|
|
96
|
+
- For each gap FR, create a new story in `{backlog_path}` with:
|
|
97
|
+
- `type: story`
|
|
98
|
+
- `status: pending`
|
|
99
|
+
- `epic: {epic_id}` (or assign to most relevant epic in project mode)
|
|
100
|
+
- `title: "Implement FR{N}: {short description}"`
|
|
101
|
+
- `priority: {next available}`
|
|
102
|
+
- `source: prd-audit`
|
|
103
|
+
- Report the new story IDs
|
|
104
|
+
- These stories are available for the next epic/project run
|
|
105
|
+
|
|
106
|
+
### Agent Usage
|
|
107
|
+
|
|
108
|
+
This step is executed by Lead directly — no new agents needed. Lead already has access to read the PRD, backlog, story output directories, and the calibration DB. The step is read-heavy and analytical, not generative.
|
|
109
|
+
|
|
110
|
+
If the PRD is large (sharded across multiple files), Lead reads all shards. Context pressure is manageable because this runs after all story agents are torn down.
|
|
111
|
+
|
|
112
|
+
### Configuration
|
|
113
|
+
|
|
114
|
+
Add to `pipeline-config.yaml` under `sprint:`:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
sprint:
|
|
118
|
+
prd_audit: true # enable post-implementation PRD audit (default: true)
|
|
119
|
+
prd_audit_auto_stories: false # auto-generate gap stories without user confirmation (default: false)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Dependencies
|
|
123
|
+
|
|
124
|
+
- REQS agent must tag FRs in `reqs-brief.md` during grooming (already does this)
|
|
125
|
+
- PRD must use numbered/identifiable FR format (standard PRD template already requires this)
|
|
126
|
+
- Calibration table must have test result data per story (already recorded during sprint review)
|
|
127
|
+
|
|
128
|
+
### Open Questions
|
|
129
|
+
|
|
130
|
+
1. Should the audit run per-sprint as well, or only at epic/project completion? Per-sprint would catch drift earlier but adds overhead.
|
|
131
|
+
2. For project mode with multiple PRDs (one per epic), should the audit cross-reference all PRDs or just the one matching each epic?
|
|
132
|
+
3. Should `weak-coverage` FRs block the epic/project completion report, or just be informational?
|
|
@@ -41,6 +41,27 @@ For each story in sprint order:
|
|
|
41
41
|
|
|
42
42
|
If a genuine design conflict arises during execution that requires grooming-level deliberation, Lead spawns the relevant grooming agent (REQS, UXA, or QA-A) fresh via Design Council protocol. The freshly spawned agent queries Knowledge/SQLite for grooming context. Kill the temporary agent after deliberation resolves.
|
|
43
43
|
|
|
44
|
+
### Mid-Sprint Pull from Groomed Buffer
|
|
45
|
+
|
|
46
|
+
When all planned sprint stories have been executed and the time budget has NOT been exceeded:
|
|
47
|
+
|
|
48
|
+
1. Read `{backlog_path}` for stories with status `groomed` that are not tagged with a sprint (the groomed buffer from sprint-plan.md Step 1b)
|
|
49
|
+
2. If buffer is empty, proceed to sprint review
|
|
50
|
+
3. If buffer has stories, pull them into the current sprint using the same packing logic as sprint-plan.md Step 1:
|
|
51
|
+
- `remaining_capacity = current_velocity - points_completed_this_sprint`
|
|
52
|
+
- Pack by priority with dependency auto-inclusion, skipping stories that don't fit (`continue`, not `break`)
|
|
53
|
+
4. For each pulled story:
|
|
54
|
+
- Add `sprint: {current_sprint_id}` tag in `{backlog_path}`
|
|
55
|
+
- Set status to `sprint-planned`
|
|
56
|
+
- Add to `sprint-{n}-plan.md` Planned Stories table (mark as "pulled mid-sprint")
|
|
57
|
+
- Add to `sprint-{n}-status.yaml`
|
|
58
|
+
- Update `pipeline-state.json`: append to `stories_planned`, increment `points_planned`
|
|
59
|
+
5. Execute pulled stories using the same per-story flow above (Story 2+ rules — all Phase 2 agents spawned fresh)
|
|
60
|
+
6. After each pulled story ships, repeat: check time budget, check buffer, pull more if both allow
|
|
61
|
+
7. When the time budget is exceeded OR the buffer is empty, proceed to sprint review
|
|
62
|
+
|
|
63
|
+
This avoids starting a new sprint (with its groom/size/plan overhead) when there's already groomed work ready to execute.
|
|
64
|
+
|
|
44
65
|
### Sprint Rollover
|
|
45
66
|
|
|
46
67
|
When the time budget is exceeded:
|
|
@@ -50,6 +71,7 @@ When the time budget is exceeded:
|
|
|
50
71
|
- Reset status to `pending`
|
|
51
72
|
- These stories will be picked up by the next sprint's planning phase
|
|
52
73
|
3. Record rolled-over story IDs in the sprint plan artifact
|
|
74
|
+
4. Groomed buffer stories that were NOT pulled retain their `groomed` status — they carry forward to the next sprint's planning phase without re-grooming
|
|
53
75
|
|
|
54
76
|
## Update Sprint State
|
|
55
77
|
|
|
@@ -33,15 +33,18 @@ When a candidate story depends on another `pending` story, auto-include the prer
|
|
|
33
33
|
|
|
34
34
|
## Step 4: Determine Groom Target Count
|
|
35
35
|
|
|
36
|
-
Calculate how many stories to groom
|
|
36
|
+
Calculate how many stories to groom. We groom **2x velocity** worth to maintain a buffer — stories that don't fit the current sprint are already groomed and sized for the next one, and can be pulled into the current sprint if it finishes early.
|
|
37
37
|
|
|
38
38
|
```
|
|
39
39
|
avg_points_per_story = AVG(story_points) from calibration table (last 5 sprints)
|
|
40
40
|
defaults to 5 when no history exists
|
|
41
|
-
|
|
41
|
+
already_groomed = count of stories in backlog with status 'groomed' or 'sizing' (not yet sprint-planned)
|
|
42
|
+
groom_target = ceil((current_velocity * 2) / avg_points_per_story) - already_groomed
|
|
42
43
|
groom_target = max(groom_target, 3) # floor of 3
|
|
43
44
|
```
|
|
44
45
|
|
|
46
|
+
The `already_groomed` offset prevents re-grooming stories that were groomed in a prior sprint but not planned (the buffer from last sprint carries forward).
|
|
47
|
+
|
|
45
48
|
## Step 5: Update Sprint State
|
|
46
49
|
|
|
47
50
|
Write to `pipeline-state.json`:
|
|
@@ -29,16 +29,22 @@ for story in groomed_stories_by_priority:
|
|
|
29
29
|
sprint_stories.append(story)
|
|
30
30
|
remaining_capacity -= story.story_points
|
|
31
31
|
else:
|
|
32
|
-
|
|
32
|
+
continue # skip this story, try smaller ones to fill capacity
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
## Step 1b: Identify Groomed Buffer
|
|
36
|
+
|
|
37
|
+
After packing, any groomed+sized stories that did NOT fit into the sprint remain in the **groomed buffer**. These are available for mid-sprint pull (see sprint-execute.md) without needing another groom/size cycle.
|
|
38
|
+
|
|
39
|
+
Record `buffer_story_ids` = groomed stories not in `sprint_stories` (keep their `groomed` status — do NOT reset them).
|
|
40
|
+
|
|
35
41
|
## Step 2: Check if Sprint Needs More Stories
|
|
36
42
|
|
|
37
|
-
If `remaining_capacity >= 1` AND there are ungroomed `pending` stories in the backlog:
|
|
43
|
+
If `remaining_capacity >= 1` AND there are ungroomed `pending` stories in the backlog AND the groomed buffer is empty:
|
|
38
44
|
- Return to sprint-groom.md to groom additional stories
|
|
39
45
|
- Then return here to re-pack
|
|
40
46
|
|
|
41
|
-
Guard: do NOT enter groom-more loop if `remaining_capacity < 1` point.
|
|
47
|
+
Guard: do NOT enter groom-more loop if `remaining_capacity < 1` point or if the groomed buffer already has stories (they'll be pulled mid-sprint if needed).
|
|
42
48
|
|
|
43
49
|
## Step 3: Write Sprint Plan Artifact
|
|
44
50
|
|
|
@@ -14,13 +14,14 @@ Read each story's `phase-timing.md` for `total_elapsed_minutes` and count reject
|
|
|
14
14
|
## Step 2: Fill Sprint Summary
|
|
15
15
|
|
|
16
16
|
Update `sprint-{n}-plan.md` Sprint Summary:
|
|
17
|
-
- Stories shipped: count and list
|
|
17
|
+
- Stories shipped: count and list (distinguish originally planned vs mid-sprint pulls)
|
|
18
18
|
- Stories rolled over: count and list (if any)
|
|
19
|
-
- Points shipped: sum of shipped story points
|
|
19
|
+
- Points shipped: sum of shipped story points (includes mid-sprint pulls)
|
|
20
20
|
- Points rolled over: sum of unexecuted story points
|
|
21
21
|
- Total elapsed minutes: sum of execution time (not grooming)
|
|
22
|
-
- Velocity this sprint: points_shipped
|
|
22
|
+
- Velocity this sprint: points_shipped (all shipped stories count toward velocity, including pulls)
|
|
23
23
|
- Updated velocity (SMA-5): compute new moving average
|
|
24
|
+
- Mid-sprint pulls: count and list (stories pulled from groomed buffer during execution)
|
|
24
25
|
|
|
25
26
|
## Step 3: Finalize Sprint Status YAML
|
|
26
27
|
|