feat: add story/epic revalidation with gap filling
Implements user-requested revalidation capability to verify checkbox accuracy. Use Case: "I am uncertain about the real status of some stories and epics that I've worked on and would love a re-check" - User FEATURE: /revalidate-story ------------------------- Clears all checkboxes and re-verifies each item against codebase: 1. Clear Phase: - Uncheck all boxes in ACs, Tasks, DoD - Start from clean slate 2. Verification Phase: - For each item: search codebase with Glob/Grep - Read files to verify actual implementation (not stubs) - Check for tests and verify they pass - Re-check verified items: [x] verified, [~] partial, [ ] missing 3. Gap Reporting: - Report what exists vs what's documented - Calculate accuracy (before % vs after %) - Identify over-reported (checked but missing) and under-reported (exists but unchecked) 4. Gap Filling Mode (optional): - Implement missing items - Run tests to verify - Commit per gap or all at once - Re-verify after filling Token Cost Analysis: - Verify-only: ~30-45K tokens (just scan and report) - Verify-and-fill (10% gaps): ~35-55K tokens - Verify-and-fill (50% gaps): ~60-90K tokens - Compare to full re-implementation: ~80-120K tokens - Savings: 40-60% when gaps <30% FEATURE: /revalidate-epic ------------------------ Batch revalidation of all stories in an epic using semaphore pattern: - Maintain pool of N concurrent workers - As worker finishes → immediately start next story - Constant concurrency until all stories revalidated - Epic-wide summary with health score - Stories grouped by completion % Usage: ```bash # Verify only /revalidate-story story_file=path/to/story.md # Verify and fill gaps /revalidate-story story_file=path/to/story.md fill_gaps=true # Revalidate entire epic /revalidate-epic epic_number=2 # Revalidate epic and fill all gaps /revalidate-epic epic_number=2 fill_gaps=true max_concurrent=5 ``` Files Created: - revalidate-story/workflow.yaml: Story revalidation config - revalidate-story/instructions.md: 10-step revalidation process - revalidate-epic/workflow.yaml: Epic batch revalidation config - revalidate-epic/instructions.md: Semaphore pattern for parallel revalidation Files Modified: - dev.agent.yaml: Added RVS and RVE menu items - sm.agent.yaml: Added RVS and RVE menu items Next: Reverse gap analysis (detect orphaned code with no stories)
This commit is contained in:
parent
0d66a28cfe
commit
1031b1cd21
|
|
@ -55,3 +55,11 @@ agent:
|
|||
- trigger: CR or fuzzy match on code-review
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/code-review/workflow.yaml"
|
||||
description: "[CR] Perform a thorough clean context code review (Highly Recommended, use fresh context and different LLM)"
|
||||
|
||||
- trigger: RVS or fuzzy match on revalidate-story
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/revalidate-story/workflow.yaml"
|
||||
description: "[RVS] Revalidate Story - clear checkboxes and re-verify against codebase (detect ghost features and gaps)"
|
||||
|
||||
- trigger: RVE or fuzzy match on revalidate-epic
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/revalidate-epic/workflow.yaml"
|
||||
description: "[RVE] Revalidate Epic - batch revalidation of all stories in an epic with semaphore pattern"
|
||||
|
|
|
|||
|
|
@ -49,3 +49,11 @@ agent:
|
|||
- trigger: CC or fuzzy match on correct-course
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml"
|
||||
description: "[CC] Execute correct-course task (When implementation is off-track)"
|
||||
|
||||
- trigger: RVS or fuzzy match on revalidate-story
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/revalidate-story/workflow.yaml"
|
||||
description: "[RVS] Revalidate Story - clear checkboxes and verify against codebase reality (find gaps and ghost features)"
|
||||
|
||||
- trigger: RVE or fuzzy match on revalidate-epic
|
||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/revalidate-epic/workflow.yaml"
|
||||
description: "[RVE] Revalidate Epic - batch revalidation of all stories with semaphore pattern"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,273 @@
|
|||
# Revalidate Epic - Batch Story Revalidation with Semaphore Pattern
|
||||
|
||||
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
|
||||
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
|
||||
|
||||
<workflow>
|
||||
|
||||
<step n="1" goal="Load sprint status and find epic stories">
|
||||
<action>Verify epic_number parameter provided</action>
|
||||
|
||||
<check if="epic_number not provided">
|
||||
<output>❌ ERROR: epic_number parameter required
|
||||
|
||||
Usage:
|
||||
/revalidate-epic epic_number=2
|
||||
/revalidate-epic epic_number=2 fill_gaps=true
|
||||
/revalidate-epic epic_number=2 fill_gaps=true max_concurrent=5
|
||||
</output>
|
||||
<action>HALT</action>
|
||||
</check>
|
||||
|
||||
<action>Read {sprint_status} file</action>
|
||||
<action>Parse development_status map</action>
|
||||
|
||||
<action>Filter stories starting with "{{epic_number}}-" (e.g., "2-1-", "2-2-", etc.)</action>
|
||||
<action>Exclude epics (keys starting with "epic-") and retrospectives</action>
|
||||
|
||||
<action>Store as: epic_stories (list of story keys)</action>
|
||||
|
||||
<check if="epic_stories is empty">
|
||||
<output>❌ No stories found for Epic {{epic_number}}
|
||||
|
||||
Check sprint-status.yaml to verify epic number is correct.
|
||||
</output>
|
||||
<action>HALT</action>
|
||||
</check>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
🔍 EPIC {{epic_number}} REVALIDATION
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
**Stories Found:** {{epic_stories.length}}
|
||||
**Mode:** {{#if fill_gaps}}Verify & Fill Gaps{{else}}Verify Only{{/if}}
|
||||
**Max Concurrent:** {{max_concurrent}} agents
|
||||
**Pattern:** Semaphore (continuous worker pool)
|
||||
|
||||
**Stories to Revalidate:**
|
||||
{{#each epic_stories}}
|
||||
{{@index + 1}}. {{this}}
|
||||
{{/each}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<ask>Proceed with revalidation? (yes/no):</ask>
|
||||
|
||||
<check if="response != 'yes'">
|
||||
<output>❌ Revalidation cancelled</output>
|
||||
<action>Exit workflow</action>
|
||||
</check>
|
||||
</step>
|
||||
|
||||
<step n="2" goal="Initialize semaphore pattern for parallel revalidation">
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
🚀 Starting Parallel Revalidation (Semaphore Pattern)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<action>Initialize worker pool state:</action>
|
||||
<action>
|
||||
- story_queue = epic_stories
|
||||
- active_workers = {}
|
||||
- completed_stories = []
|
||||
- failed_stories = []
|
||||
- verification_results = {}
|
||||
- next_story_index = 0
|
||||
- max_workers = {{max_concurrent}}
|
||||
</action>
|
||||
|
||||
<action>Fill initial worker slots:</action>
|
||||
|
||||
<iterate>While next_story_index < min(max_workers, story_queue.length):</iterate>
|
||||
|
||||
<action>
|
||||
story_key = story_queue[next_story_index]
|
||||
story_file = {sprint_artifacts}/{{story_key}}.md # Try multiple naming patterns if needed
|
||||
worker_id = next_story_index + 1
|
||||
|
||||
Spawn Task agent:
|
||||
- subagent_type: "general-purpose"
|
||||
- description: "Revalidate story {{story_key}}"
|
||||
- prompt: "Execute revalidate-story workflow for {{story_key}}.
|
||||
|
||||
CRITICAL INSTRUCTIONS:
|
||||
1. Load workflow: _bmad/bmm/workflows/4-implementation/revalidate-story/workflow.yaml
|
||||
2. Parameters: story_file={{story_file}}, fill_gaps={{fill_gaps}}
|
||||
3. Clear all checkboxes
|
||||
4. Verify each AC/Task/DoD against codebase
|
||||
5. Re-check verified items
|
||||
6. Report gaps
|
||||
{{#if fill_gaps}}7. Fill gaps and commit{{/if}}
|
||||
8. Return verification summary"
|
||||
- run_in_background: true
|
||||
|
||||
Store in active_workers[worker_id]:
|
||||
story_key: {{story_key}}
|
||||
task_id: {{returned_task_id}}
|
||||
started_at: {{timestamp}}
|
||||
</action>
|
||||
|
||||
<action>Increment next_story_index</action>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ {{active_workers.size}} workers active
|
||||
📋 {{story_queue.length - next_story_index}} stories queued
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="3" goal="Maintain worker pool until all stories revalidated">
|
||||
<critical>SEMAPHORE PATTERN: Keep {{max_workers}} agents running continuously</critical>
|
||||
|
||||
<iterate>While active_workers.size > 0 OR next_story_index < story_queue.length:</iterate>
|
||||
|
||||
<action>Poll for completed workers (non-blocking):</action>
|
||||
|
||||
<iterate>For each worker_id in active_workers:</iterate>
|
||||
|
||||
<action>Check worker status using TaskOutput(task_id, block=false)</action>
|
||||
|
||||
<check if="worker completed successfully">
|
||||
<action>Get verification results from worker output</action>
|
||||
<action>Parse: verified_pct, gaps_found, gaps_filled</action>
|
||||
|
||||
<action>Store in verification_results[story_key]</action>
|
||||
<action>Add to completed_stories</action>
|
||||
<action>Remove from active_workers</action>
|
||||
|
||||
<output>✅ Worker {{worker_id}}: {{story_key}} → {{verified_pct}}% verified{{#if gaps_filled > 0}}, {{gaps_filled}} gaps filled{{/if}}</output>
|
||||
|
||||
<check if="next_story_index < story_queue.length">
|
||||
<action>Refill slot with next story (same pattern as batch-super-dev)</action>
|
||||
<output>🔄 Worker {{worker_id}} refilled: {{next_story_key}}</output>
|
||||
</check>
|
||||
</check>
|
||||
|
||||
<check if="worker failed">
|
||||
<action>Add to failed_stories with error</action>
|
||||
<action>Remove from active_workers</action>
|
||||
<output>❌ Worker {{worker_id}}: {{story_key}} failed</output>
|
||||
|
||||
<check if="continue_on_failure AND next_story_index < story_queue.length">
|
||||
<action>Refill slot despite failure</action>
|
||||
</check>
|
||||
</check>
|
||||
|
||||
<action>Display live progress every 30 seconds:</action>
|
||||
<output>
|
||||
📊 Live Progress: {{completed_stories.length}} completed, {{active_workers.size}} active, {{story_queue.length - next_story_index}} queued
|
||||
</output>
|
||||
|
||||
<action>Sleep 5 seconds before next poll</action>
|
||||
</step>
|
||||
|
||||
<step n="4" goal="Generate epic-level summary">
|
||||
<action>Aggregate verification results across all stories:</action>
|
||||
<action>
|
||||
epic_total_items = sum of all items across stories
|
||||
epic_verified = sum of verified items
|
||||
epic_partial = sum of partial items
|
||||
epic_missing = sum of missing items
|
||||
epic_gaps_filled = sum of gaps filled
|
||||
|
||||
epic_verified_pct = (epic_verified / epic_total_items) × 100
|
||||
</action>
|
||||
|
||||
<action>Group stories by verification percentage:</action>
|
||||
<action>
|
||||
- complete_stories (≥95% verified)
|
||||
- mostly_complete_stories (80-94% verified)
|
||||
- partial_stories (50-79% verified)
|
||||
- incomplete_stories (<50% verified)
|
||||
</action>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
📊 EPIC {{epic_number}} REVALIDATION SUMMARY
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
**Total Stories:** {{epic_stories.length}}
|
||||
**Completed:** {{completed_stories.length}}
|
||||
**Failed:** {{failed_stories.length}}
|
||||
|
||||
**Epic-Wide Verification:**
|
||||
- ✅ Verified: {{epic_verified}}/{{epic_total_items}} ({{epic_verified_pct}}%)
|
||||
- 🔶 Partial: {{epic_partial}}/{{epic_total_items}}
|
||||
- ❌ Missing: {{epic_missing}}/{{epic_total_items}}
|
||||
{{#if fill_gaps}}- 🔧 Gaps Filled: {{epic_gaps_filled}}{{/if}}
|
||||
|
||||
**Story Health:**
|
||||
- ✅ Complete (≥95%): {{complete_stories.length}} stories
|
||||
- 🔶 Mostly Complete (80-94%): {{mostly_complete_stories.length}} stories
|
||||
- ⚠️ Partial (50-79%): {{partial_stories.length}} stories
|
||||
- ❌ Incomplete (<50%): {{incomplete_stories.length}} stories
|
||||
|
||||
---
|
||||
|
||||
**Complete Stories (≥95% verified):**
|
||||
{{#each complete_stories}}
|
||||
- {{story_key}}: {{verified_pct}}% verified
|
||||
{{/each}}
|
||||
|
||||
{{#if mostly_complete_stories.length > 0}}
|
||||
**Mostly Complete Stories (80-94%):**
|
||||
{{#each mostly_complete_stories}}
|
||||
- {{story_key}}: {{verified_pct}}% verified ({{gaps_count}} gaps{{#if gaps_filled > 0}}, {{gaps_filled}} filled{{/if}})
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
{{#if partial_stories.length > 0}}
|
||||
**⚠️ Partial Stories (50-79%):**
|
||||
{{#each partial_stories}}
|
||||
- {{story_key}}: {{verified_pct}}% verified ({{gaps_count}} gaps{{#if gaps_filled > 0}}, {{gaps_filled}} filled{{/if}})
|
||||
{{/each}}
|
||||
|
||||
Recommendation: Continue development on these stories
|
||||
{{/if}}
|
||||
|
||||
{{#if incomplete_stories.length > 0}}
|
||||
**❌ Incomplete Stories (<50%):**
|
||||
{{#each incomplete_stories}}
|
||||
- {{story_key}}: {{verified_pct}}% verified ({{gaps_count}} gaps{{#if gaps_filled > 0}}, {{gaps_filled}} filled{{/if}})
|
||||
{{/each}}
|
||||
|
||||
Recommendation: Re-implement these stories from scratch
|
||||
{{/if}}
|
||||
|
||||
{{#if failed_stories.length > 0}}
|
||||
**❌ Failed Revalidations:**
|
||||
{{#each failed_stories}}
|
||||
- {{story_key}}: {{error}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
---
|
||||
|
||||
**Epic Health Score:** {{epic_verified_pct}}/100
|
||||
|
||||
{{#if epic_verified_pct >= 95}}
|
||||
✅ Epic is COMPLETE and verified
|
||||
{{else if epic_verified_pct >= 80}}
|
||||
🔶 Epic is MOSTLY COMPLETE ({{epic_missing}} items need attention)
|
||||
{{else if epic_verified_pct >= 50}}
|
||||
⚠️ Epic is PARTIALLY COMPLETE (significant gaps remain)
|
||||
{{else}}
|
||||
❌ Epic is INCOMPLETE (major rework needed)
|
||||
{{/if}}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<check if="create_epic_report == true">
|
||||
<action>Write epic summary to: {sprint_artifacts}/revalidation-epic-{{epic_number}}-{{timestamp}}.md</action>
|
||||
<output>📄 Epic report: {{report_path}}</output>
|
||||
</check>
|
||||
|
||||
<check if="update_sprint_status == true">
|
||||
<action>Update sprint-status.yaml with revalidation timestamp and results</action>
|
||||
<action>Add comment to epic entry: # Revalidated: {{epic_verified_pct}}% verified ({{timestamp}})</action>
|
||||
</check>
|
||||
</step>
|
||||
|
||||
</workflow>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
name: revalidate-epic
|
||||
description: "Batch revalidation of all stories in an epic. Clears checkboxes and re-verifies against codebase with semaphore pattern."
|
||||
author: "BMad"
|
||||
version: "1.0.0"
|
||||
|
||||
# Critical variables from config
|
||||
config_source: "{project-root}/_bmad/bmm/config.yaml"
|
||||
output_folder: "{config_source}:output_folder"
|
||||
sprint_artifacts: "{output_folder}/sprint-artifacts"
|
||||
sprint_status: "{output_folder}/sprint-status.yaml"
|
||||
|
||||
# Input parameters
|
||||
epic_number: "{epic_number}" # Required: Epic number (e.g., "2" for Epic 2)
|
||||
fill_gaps: false # Optional: Fill missing items after verification
|
||||
max_concurrent: 3 # Optional: Max concurrent revalidation agents (default: 3)
|
||||
|
||||
# Verification settings (inherited by story revalidations)
|
||||
verification:
|
||||
verify_acceptance_criteria: true
|
||||
verify_tasks: true
|
||||
verify_definition_of_done: true
|
||||
check_for_stubs: true
|
||||
require_tests: true
|
||||
|
||||
# Gap filling settings
|
||||
gap_filling:
|
||||
max_gaps_per_story: 10 # Safety limit per story
|
||||
require_confirmation_first_story: true # Ask on first story, then auto for rest
|
||||
run_tests_after_each: true
|
||||
commit_strategy: "per_gap" # "per_gap" | "per_story" | "all_at_once"
|
||||
|
||||
# Execution settings
|
||||
execution:
|
||||
use_semaphore_pattern: true # Constant concurrency (not batch-and-wait)
|
||||
continue_on_failure: true # Keep processing if one story fails
|
||||
display_live_progress: true # Show progress updates every 30s
|
||||
|
||||
# Output settings
|
||||
output:
|
||||
create_epic_report: true # Generate epic-level summary
|
||||
create_story_reports: true # Generate per-story reports
|
||||
update_sprint_status: true # Update progress in sprint-status.yaml
|
||||
|
||||
standalone: true
|
||||
|
|
@ -0,0 +1,510 @@
|
|||
# Revalidate Story - Verify Checkboxes Against Codebase Reality
|
||||
|
||||
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
|
||||
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
|
||||
|
||||
<workflow>
|
||||
|
||||
<step n="1" goal="Load story and backup current state">
|
||||
<action>Verify story_file parameter provided</action>
|
||||
|
||||
<check if="story_file not provided">
|
||||
<output>❌ ERROR: story_file parameter required
|
||||
|
||||
Usage:
|
||||
/revalidate-story story_file=path/to/story.md
|
||||
/revalidate-story story_file=path/to/story.md fill_gaps=true
|
||||
</output>
|
||||
<action>HALT</action>
|
||||
</check>
|
||||
|
||||
<action>Read COMPLETE story file: {{story_file}}</action>
|
||||
<action>Parse sections: Acceptance Criteria, Tasks/Subtasks, Definition of Done, Dev Agent Record</action>
|
||||
|
||||
<action>Extract story_key from filename (e.g., "2-7-image-file-handling")</action>
|
||||
|
||||
<action>Create backup of current checkbox state:</action>
|
||||
<action>Count currently checked items:
|
||||
- ac_checked_before = count of [x] in Acceptance Criteria
|
||||
- tasks_checked_before = count of [x] in Tasks/Subtasks
|
||||
- dod_checked_before = count of [x] in Definition of Done
|
||||
- total_checked_before = sum of above
|
||||
</action>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
🔍 STORY REVALIDATION STARTED
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
**Story:** {{story_key}}
|
||||
**File:** {{story_file}}
|
||||
**Mode:** {{#if fill_gaps}}Verify & Fill Gaps{{else}}Verify Only{{/if}}
|
||||
|
||||
**Current State:**
|
||||
- Acceptance Criteria: {{ac_checked_before}}/{{ac_total}} checked
|
||||
- Tasks: {{tasks_checked_before}}/{{tasks_total}} checked
|
||||
- Definition of Done: {{dod_checked_before}}/{{dod_total}} checked
|
||||
- **Total:** {{total_checked_before}}/{{total_items}} ({{pct_before}}%)
|
||||
|
||||
**Action:** Clearing all checkboxes and re-verifying against codebase...
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="2" goal="Clear all checkboxes">
|
||||
<output>🧹 Clearing all checkboxes to start fresh verification...</output>
|
||||
|
||||
<action>Use Edit tool to replace all [x] with [ ] in Acceptance Criteria section</action>
|
||||
<action>Use Edit tool to replace all [x] with [ ] in Tasks/Subtasks section</action>
|
||||
<action>Use Edit tool to replace all [x] with [ ] in Definition of Done section</action>
|
||||
|
||||
<action>Save story file with all boxes unchecked</action>
|
||||
|
||||
<output>✅ All checkboxes cleared. Starting verification from clean slate...</output>
|
||||
</step>
|
||||
|
||||
<step n="3" goal="Verify Acceptance Criteria against codebase">
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
📋 VERIFYING ACCEPTANCE CRITERIA ({{ac_total}} items)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<action>Extract all AC items from Acceptance Criteria section</action>
|
||||
|
||||
<iterate>For each AC item:</iterate>
|
||||
|
||||
<substep n="3a" title="Parse AC and determine what should exist">
|
||||
<action>Extract AC description and identify artifacts:
|
||||
- File mentions (e.g., "UserProfile component")
|
||||
- Function names (e.g., "updateUser function")
|
||||
- Features (e.g., "dark mode toggle")
|
||||
- Test requirements (e.g., "unit tests covering edge cases")
|
||||
</action>
|
||||
|
||||
<output>Verifying AC{{@index}}: {{ac_description}}</output>
|
||||
</substep>
|
||||
|
||||
<substep n="3b" title="Search codebase for evidence">
|
||||
<action>Use Glob to find relevant files:
|
||||
- If AC mentions specific file: glob for that file
|
||||
- If AC mentions component: glob for **/*ComponentName*
|
||||
- If AC mentions feature: glob for files in related directories
|
||||
</action>
|
||||
|
||||
<action>Use Grep to search for symbols/functions/features</action>
|
||||
|
||||
<action>Read found files to verify:</action>
|
||||
<action>- NOT a stub (check for "TODO", "Not implemented", "throw new Error")</action>
|
||||
<action>- Has actual implementation (not just empty function)</action>
|
||||
<action>- Tests exist (search for *.test.* or *.spec.* files)</action>
|
||||
<action>- Tests pass (if --fill-gaps mode, run tests)</action>
|
||||
</substep>
|
||||
|
||||
<substep n="3c" title="Determine verification status">
|
||||
<check if="all evidence found AND no stubs AND tests exist">
|
||||
<action>verification_status = VERIFIED</action>
|
||||
<action>Check box [x] in story file for this AC</action>
|
||||
<action>Record evidence: "✅ VERIFIED: {{files_found}}, tests: {{test_files}}"</action>
|
||||
<output> ✅ AC{{@index}}: VERIFIED</output>
|
||||
</check>
|
||||
|
||||
<check if="partial evidence OR stubs found OR tests missing">
|
||||
<action>verification_status = PARTIAL</action>
|
||||
<action>Check box [~] in story file for this AC</action>
|
||||
<action>Record gap: "🔶 PARTIAL: {{what_exists}}, missing: {{what_is_missing}}"</action>
|
||||
<output> 🔶 AC{{@index}}: PARTIAL ({{what_is_missing}})</output>
|
||||
<action>Add to gaps_list with details</action>
|
||||
</check>
|
||||
|
||||
<check if="no evidence found">
|
||||
<action>verification_status = MISSING</action>
|
||||
<action>Leave box unchecked [ ] in story file</action>
|
||||
<action>Record gap: "❌ MISSING: No implementation found for {{ac_description}}"</action>
|
||||
<output> ❌ AC{{@index}}: MISSING</output>
|
||||
<action>Add to gaps_list with details</action>
|
||||
</check>
|
||||
</substep>
|
||||
|
||||
<action>Save story file after each AC verification</action>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Acceptance Criteria Verification Complete
|
||||
✅ Verified: {{ac_verified}}
|
||||
🔶 Partial: {{ac_partial}}
|
||||
❌ Missing: {{ac_missing}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="4" goal="Verify Tasks/Subtasks against codebase">
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
📋 VERIFYING TASKS ({{tasks_total}} items)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<action>Extract all Task items from Tasks/Subtasks section</action>
|
||||
|
||||
<iterate>For each Task item (same verification logic as ACs):</iterate>
|
||||
|
||||
<action>Parse task description for artifacts</action>
|
||||
<action>Search codebase with Glob/Grep</action>
|
||||
<action>Read and verify (check for stubs, tests)</action>
|
||||
<action>Determine status: VERIFIED | PARTIAL | MISSING</action>
|
||||
<action>Update checkbox: [x] | [~] | [ ]</action>
|
||||
<action>Record evidence or gap</action>
|
||||
<action>Save story file</action>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Tasks Verification Complete
|
||||
✅ Verified: {{tasks_verified}}
|
||||
🔶 Partial: {{tasks_partial}}
|
||||
❌ Missing: {{tasks_missing}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="5" goal="Verify Definition of Done against codebase">
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
📋 VERIFYING DEFINITION OF DONE ({{dod_total}} items)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<action>Extract all DoD items from Definition of Done section</action>
|
||||
|
||||
<iterate>For each DoD item:</iterate>
|
||||
|
||||
<action>Parse DoD requirement:
|
||||
- "Type check passes" → Run type checker
|
||||
- "Unit tests 90%+ coverage" → Run coverage report
|
||||
- "Linting clean" → Run linter
|
||||
- "Build succeeds" → Run build
|
||||
- "All tests pass" → Run test suite
|
||||
</action>
|
||||
|
||||
<action>Execute verification for this DoD item</action>
|
||||
|
||||
<check if="verification passes">
|
||||
<action>Check box [x]</action>
|
||||
<action>Record: "✅ VERIFIED: {{verification_result}}"</action>
|
||||
</check>
|
||||
|
||||
<check if="verification fails or N/A">
|
||||
<action>Leave unchecked [ ] or partial [~]</action>
|
||||
<action>Record gap if applicable</action>
|
||||
</check>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Definition of Done Verification Complete
|
||||
✅ Verified: {{dod_verified}}
|
||||
🔶 Partial: {{dod_partial}}
|
||||
❌ Missing: {{dod_missing}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="6" goal="Generate revalidation report">
|
||||
<action>Calculate overall completion:</action>
|
||||
<action>
|
||||
total_verified = ac_verified + tasks_verified + dod_verified
|
||||
total_partial = ac_partial + tasks_partial + dod_partial
|
||||
total_missing = ac_missing + tasks_missing + dod_missing
|
||||
total_items = ac_total + tasks_total + dod_total
|
||||
|
||||
verified_pct = (total_verified / total_items) × 100
|
||||
completion_pct = ((total_verified + total_partial) / total_items) × 100
|
||||
</action>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
📊 REVALIDATION SUMMARY
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
**Story:** {{story_key}}
|
||||
**File:** {{story_file}}
|
||||
|
||||
**Verification Results:**
|
||||
- ✅ Verified Complete: {{total_verified}}/{{total_items}} ({{verified_pct}}%)
|
||||
- 🔶 Partially Complete: {{total_partial}}/{{total_items}}
|
||||
- ❌ Missing/Incomplete: {{total_missing}}/{{total_items}}
|
||||
|
||||
**Breakdown:**
|
||||
- Acceptance Criteria: {{ac_verified}}✅ {{ac_partial}}🔶 {{ac_missing}}❌ / {{ac_total}} total
|
||||
- Tasks: {{tasks_verified}}✅ {{tasks_partial}}🔶 {{tasks_missing}}❌ / {{tasks_total}} total
|
||||
- Definition of Done: {{dod_verified}}✅ {{dod_partial}}🔶 {{dod_missing}}❌ / {{dod_total}} total
|
||||
|
||||
**Status Assessment:**
|
||||
{{#if verified_pct >= 95}}
|
||||
✅ Story is COMPLETE ({{verified_pct}}% verified)
|
||||
{{else if verified_pct >= 80}}
|
||||
🔶 Story is MOSTLY COMPLETE ({{verified_pct}}% verified, {{total_missing}} gaps)
|
||||
{{else if verified_pct >= 50}}
|
||||
⚠️ Story is PARTIALLY COMPLETE ({{verified_pct}}% verified, {{total_missing}} gaps)
|
||||
{{else}}
|
||||
❌ Story is INCOMPLETE ({{verified_pct}}% verified, significant work missing)
|
||||
{{/if}}
|
||||
|
||||
**Before Revalidation:** {{total_checked_before}}/{{total_items}} checked ({{pct_before}}%)
|
||||
**After Revalidation:** {{total_verified}}/{{total_items}} verified ({{verified_pct}}%)
|
||||
**Accuracy:** {{#if pct_before == verified_pct}}Perfect match{{else if pct_before > verified_pct}}{{pct_before - verified_pct}}% over-reported{{else}}{{verified_pct - pct_before}}% under-reported{{/if}}
|
||||
|
||||
{{#if total_missing > 0}}
|
||||
---
|
||||
**Gaps Found ({{total_missing}}):**
|
||||
{{#each gaps_list}}
|
||||
{{@index + 1}}. {{item_type}} - {{item_description}}
|
||||
Status: {{status}}
|
||||
Missing: {{what_is_missing}}
|
||||
{{#if evidence}}Evidence checked: {{evidence}}{{/if}}
|
||||
{{/each}}
|
||||
---
|
||||
{{/if}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<check if="create_report == true">
|
||||
<action>Write detailed report to: {sprint_artifacts}/revalidation-{{story_key}}-{{timestamp}}.md</action>
|
||||
<action>Include: verification results, gaps list, evidence for each item, recommendations</action>
|
||||
<output>📄 Detailed report: {{report_path}}</output>
|
||||
</check>
|
||||
</step>
|
||||
|
||||
<step n="7" goal="Decide on gap filling">
|
||||
<check if="fill_gaps == false">
|
||||
<output>
|
||||
✅ Verification complete (verify-only mode)
|
||||
|
||||
{{#if total_missing > 0}}
|
||||
**To fill the {{total_missing}} gaps, run:**
|
||||
/revalidate-story story_file={{story_file}} fill_gaps=true
|
||||
{{else}}
|
||||
No gaps found - story is complete!
|
||||
{{/if}}
|
||||
</output>
|
||||
<action>Exit workflow</action>
|
||||
</check>
|
||||
|
||||
<check if="fill_gaps == true AND total_missing == 0">
|
||||
<output>✅ No gaps to fill - story is already complete!</output>
|
||||
<action>Exit workflow</action>
|
||||
</check>
|
||||
|
||||
<check if="fill_gaps == true AND total_missing > 0">
|
||||
<check if="total_missing > max_gaps_to_fill">
|
||||
<output>
|
||||
⚠️ TOO MANY GAPS: {{total_missing}} gaps found (max: {{max_gaps_to_fill}})
|
||||
|
||||
This story has too many missing items for automatic gap filling.
|
||||
Consider:
|
||||
1. Re-implementing the story from scratch with /dev-story
|
||||
2. Manually implementing the gaps
|
||||
3. Increasing max_gaps_to_fill in workflow.yaml (use cautiously)
|
||||
|
||||
Gap filling HALTED for safety.
|
||||
</output>
|
||||
<action>HALT</action>
|
||||
</check>
|
||||
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
🔧 GAP FILLING MODE ({{total_missing}} gaps to fill)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
|
||||
<action>Continue to Step 8</action>
|
||||
</check>
|
||||
</step>
|
||||
|
||||
<step n="8" goal="Fill gaps (implement missing items)">
|
||||
<iterate>For each gap in gaps_list:</iterate>
|
||||
|
||||
<substep n="8a" title="Confirm gap filling">
|
||||
<check if="require_confirmation == true">
|
||||
<ask>
|
||||
Fill this gap?
|
||||
|
||||
**Item:** {{item_description}}
|
||||
**Type:** {{item_type}} ({{section}})
|
||||
**Missing:** {{what_is_missing}}
|
||||
|
||||
[Y] Yes - Implement this item
|
||||
[A] Auto-fill - Implement this and all remaining gaps without asking
|
||||
[S] Skip - Leave this gap unfilled
|
||||
[H] Halt - Stop gap filling
|
||||
|
||||
Your choice:
|
||||
</ask>
|
||||
|
||||
<check if="choice == 'A'">
|
||||
<action>Set require_confirmation = false (auto-fill remaining)</action>
|
||||
</check>
|
||||
|
||||
<check if="choice == 'S'">
|
||||
<action>Continue to next gap</action>
|
||||
</check>
|
||||
|
||||
<check if="choice == 'H'">
|
||||
<action>Exit gap filling loop</action>
|
||||
<action>Jump to Step 9 (Summary)</action>
|
||||
</check>
|
||||
</check>
|
||||
</substep>
|
||||
|
||||
<substep n="8b" title="Implement missing item">
|
||||
<output>🔧 Implementing: {{item_description}}</output>
|
||||
|
||||
<action>Load story context (Technical Requirements, Architecture Compliance, Dev Notes)</action>
|
||||
<action>Implement missing item following story specifications</action>
|
||||
<action>Write tests if required</action>
|
||||
<action>Run tests to verify implementation</action>
|
||||
<action>Verify linting/type checking passes</action>
|
||||
|
||||
<check if="implementation succeeds AND tests pass">
|
||||
<action>Check box [x] for this item in story file</action>
|
||||
<action>Update File List with new/modified files</action>
|
||||
<action>Add to Dev Agent Record: "Gap filled: {{item_description}}"</action>
|
||||
<output> ✅ Implemented and verified</output>
|
||||
|
||||
<check if="commit_strategy == 'per_gap'">
|
||||
<action>Stage files for this gap</action>
|
||||
<action>Commit: "fix({{story_key}}): fill gap - {{item_description}}"</action>
|
||||
<output> ✅ Committed</output>
|
||||
</check>
|
||||
</check>
|
||||
|
||||
<check if="implementation fails">
|
||||
<output> ❌ Failed to implement: {{error_message}}</output>
|
||||
<action>Leave box unchecked</action>
|
||||
<action>Record failure in gaps_list</action>
|
||||
<action>Add to failed_gaps</action>
|
||||
</check>
|
||||
</substep>
|
||||
|
||||
<action>After all gaps processed:</action>
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Gap Filling Complete
|
||||
✅ Filled: {{gaps_filled}}
|
||||
❌ Failed: {{gaps_failed}}
|
||||
⏭️ Skipped: {{gaps_skipped}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
<step n="9" goal="Re-verify filled gaps and finalize">
|
||||
<check if="gaps_filled > 0">
|
||||
<output>🔍 Re-verifying filled gaps...</output>
|
||||
|
||||
<iterate>For each filled gap:</iterate>
|
||||
<action>Re-run verification for that item</action>
|
||||
<action>Ensure still VERIFIED after all changes</action>
|
||||
|
||||
<output>✅ All filled gaps re-verified</output>
|
||||
</check>
|
||||
|
||||
<action>Calculate final completion:</action>
|
||||
<action>
|
||||
final_verified = count of [x] across all sections
|
||||
final_partial = count of [~] across all sections
|
||||
final_missing = count of [ ] across all sections
|
||||
final_pct = (final_verified / total_items) × 100
|
||||
</action>
|
||||
|
||||
<check if="commit_strategy == 'all_at_once' AND gaps_filled > 0">
|
||||
<action>Stage all changed files</action>
|
||||
<action>Commit: "fix({{story_key}}): fill {{gaps_filled}} gaps from revalidation"</action>
|
||||
<output>✅ All gaps committed</output>
|
||||
</check>
|
||||
|
||||
<check if="update_sprint_status == true">
|
||||
<action>Load {sprint_status} file</action>
|
||||
<action>Update entry with current progress:</action>
|
||||
<action>Format: {{story_key}}: {{current_status}} # Revalidated: {{final_verified}}/{{total_items}} ({{final_pct}}%) verified</action>
|
||||
<action>Save sprint-status.yaml</action>
|
||||
<output>✅ Sprint status updated with revalidation results</output>
|
||||
</check>
|
||||
|
||||
<check if="update_dev_agent_record == true">
|
||||
<action>Add to Dev Agent Record in story file:</action>
|
||||
<action>
|
||||
## Revalidation Record ({{timestamp}})
|
||||
|
||||
**Revalidation Mode:** {{#if fill_gaps}}Verify & Fill{{else}}Verify Only{{/if}}
|
||||
|
||||
**Results:**
|
||||
- Verified: {{final_verified}}/{{total_items}} ({{final_pct}}%)
|
||||
- Gaps Found: {{total_missing}}
|
||||
- Gaps Filled: {{gaps_filled}}
|
||||
|
||||
**Evidence:**
|
||||
{{#each verification_evidence}}
|
||||
- {{item}}: {{evidence}}
|
||||
{{/each}}
|
||||
|
||||
{{#if gaps_filled > 0}}
|
||||
**Gaps Filled:**
|
||||
{{#each filled_gaps}}
|
||||
- {{item}}: {{what_was_implemented}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
{{#if failed_gaps.length > 0}}
|
||||
**Failed to Fill:**
|
||||
{{#each failed_gaps}}
|
||||
- {{item}}: {{error}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</action>
|
||||
<action>Save story file</action>
|
||||
</check>
|
||||
</step>
|
||||
|
||||
<step n="10" goal="Final summary and recommendations">
|
||||
<output>
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ REVALIDATION COMPLETE
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
**Story:** {{story_key}}
|
||||
|
||||
**Final Status:**
|
||||
- ✅ Verified Complete: {{final_verified}}/{{total_items}} ({{final_pct}}%)
|
||||
- 🔶 Partially Complete: {{final_partial}}/{{total_items}}
|
||||
- ❌ Missing/Incomplete: {{final_missing}}/{{total_items}}
|
||||
|
||||
{{#if fill_gaps}}
|
||||
**Gap Filling Results:**
|
||||
- Filled: {{gaps_filled}}
|
||||
- Failed: {{gaps_failed}}
|
||||
- Skipped: {{gaps_skipped}}
|
||||
{{/if}}
|
||||
|
||||
**Accuracy Check:**
|
||||
- Before revalidation: {{pct_before}}% checked
|
||||
- After revalidation: {{final_pct}}% verified
|
||||
- Checkbox accuracy: {{#if pct_before == final_pct}}✅ Perfect (0% discrepancy){{else if pct_before > final_pct}}⚠️ {{pct_before - final_pct}}% over-reported (checkboxes were optimistic){{else}}🔶 {{final_pct - pct_before}}% under-reported (work done but not checked){{/if}}
|
||||
|
||||
{{#if final_pct >= 95}}
|
||||
**Recommendation:** Story is COMPLETE - mark as "done" or "review"
|
||||
{{else if final_pct >= 80}}
|
||||
**Recommendation:** Story is mostly complete - finish remaining {{final_missing}} items then mark "review"
|
||||
{{else if final_pct >= 50}}
|
||||
**Recommendation:** Story has significant gaps - continue development with /dev-story
|
||||
{{else}}
|
||||
**Recommendation:** Story is mostly incomplete - consider re-implementing with /dev-story or /super-dev-pipeline
|
||||
{{/if}}
|
||||
|
||||
{{#if failed_gaps.length > 0}}
|
||||
**⚠️ Manual attention needed for {{failed_gaps.length}} items that failed to fill automatically**
|
||||
{{/if}}
|
||||
|
||||
{{#if create_report}}
|
||||
**Detailed Report:** {sprint_artifacts}/revalidation-{{story_key}}-{{timestamp}}.md
|
||||
{{/if}}
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
</output>
|
||||
</step>
|
||||
|
||||
</workflow>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
name: revalidate-story
|
||||
description: "Clear checkboxes and re-verify story against actual codebase implementation. Identifies gaps and optionally fills them."
|
||||
author: "BMad"
|
||||
version: "1.0.0"
|
||||
|
||||
# Critical variables from config
|
||||
config_source: "{project-root}/_bmad/bmm/config.yaml"
|
||||
output_folder: "{config_source}:output_folder"
|
||||
sprint_artifacts: "{output_folder}/sprint-artifacts"
|
||||
|
||||
# Input parameters
|
||||
story_file: "{story_file}" # Required: Full path to story file
|
||||
fill_gaps: false # Optional: Fill missing items after verification (default: verify-only)
|
||||
auto_commit: false # Optional: Auto-commit filled gaps (default: prompt)
|
||||
|
||||
# Verification settings
|
||||
verification:
|
||||
verify_acceptance_criteria: true
|
||||
verify_tasks: true
|
||||
verify_definition_of_done: true
|
||||
check_for_stubs: true # Reject stub implementations (TODO, Not implemented, etc.)
|
||||
require_tests: true # Require tests for code items
|
||||
|
||||
# Gap filling settings (only used if fill_gaps=true)
|
||||
gap_filling:
|
||||
max_gaps_to_fill: 10 # Safety limit - HALT if more gaps than this
|
||||
require_confirmation: true # Ask before filling each gap (false = auto-fill all)
|
||||
run_tests_after_each: true # Verify each filled gap works
|
||||
commit_strategy: "per_gap" # "per_gap" | "all_at_once" | "none"
|
||||
|
||||
# Output settings
|
||||
output:
|
||||
create_report: true # Generate revalidation-report.md
|
||||
update_dev_agent_record: true # Add revalidation notes to story
|
||||
update_sprint_status: true # Update progress in sprint-status.yaml
|
||||
|
||||
standalone: false
|
||||
Loading…
Reference in New Issue