feat(bmm): Add bug-tracking workflows - built-in Jira-lite for AI agents

Adds three human-in-the-loop workflows for tracking bugs and features:

- bug-tracking (triage): Converts informal bugs.md → structured bugs.yaml
- implement: Executes fixes with user confirmation at each step
- verify: Closes items after human testing confirms resolution

Key features:
- Built-in Jira-lite: No external tools needed for issue tracking
- Human-in-the-loop: User confirms routing, approach, and verification
- Production API sync: Framework for fetching bug reports from app database
- Dual-file system: bugs.md (human input) + bugs.yaml (agent metadata)
- Severity/complexity routing matrix with auto-routing logic
- Documentation impact assessment (PRD/Architecture/UX triggers)

Workflow integrations:
- sprint-planning: Loads bugs.yaml, tracks feature-to-story mappings
- sprint-status: Shows bug/feature counts, recommends verify for pending items
- story-done: Syncs related bugs/features to [IMPLEMENTED] when story completes
- retrospective: Closes epic-linked bugs/features when epic is marked done

Reference implementation includes:
- Database schema for in-app bug reporting (Drizzle ORM example)
- API endpoints for sync workflow (GET pending, POST mark-synced)
- UI component examples (Svelte 5, React)
This commit is contained in:
Darren Podolak 2025-12-28 14:30:59 -05:00
parent d8b13bdb2e
commit 5247468d98
15 changed files with 2056 additions and 8 deletions

View File

@ -1300,7 +1300,67 @@ Bob (Scrum Master): "See you all when prep work is done. Meeting adjourned!"
</step>
<step n="11" goal="Save Retrospective and Update Sprint Status">
<step n="11" goal="Sync Epic-Linked Bugs/Features to Closed Status">
<critical>Check bugs.yaml for bugs/features linked to this epic and close them</critical>
<action>Load {bugs_yaml} if it exists</action>
<check if="bugs.yaml exists">
<action>Search for entries with related_epic matching {{epic_number}}</action>
<action>For bugs section - find bugs with related_epic == {{epic_number}} AND status in ["fixed", "triaged", "routed"]:</action>
<check if="matching bugs found">
<action>For each matching bug:</action>
<action>- Move entry from "bugs" section to "closed_bugs" section</action>
<action>- Update status: → "closed"</action>
<action>- Set verified_by: "retrospective-workflow"</action>
<action>- Set verified_date: {date}</action>
<action>- Append to notes: "Auto-closed via epic retrospective. Epic {{epic_number}} completed on {date}."</action>
</check>
<action>For feature_requests section - find features with related_epic == {{epic_number}} AND status in ["implemented", "backlog", "in-progress"]:</action>
<check if="matching features found">
<action>For each matching feature:</action>
<action>- Move entry from "feature_requests" section to "implemented_features" section</action>
<action>- Update status: → "complete"</action>
<action>- Set completed_by: "retrospective-workflow"</action>
<action>- Set completed_date: {date}</action>
<action>- Append to notes: "Auto-closed via epic retrospective. Epic {{epic_number}} completed on {date}."</action>
</check>
<action>Update statistics section with new counts</action>
<action>Save updated bugs.yaml</action>
<check if="bugs/features were moved">
<action>Also update bugs.md:</action>
<action>- Remove [IMPLEMENTED] tag from closed items</action>
<action>- Move bug entries to "# Fixed Bugs" section if not already there</action>
<action>- Move feature entries to "# Implemented Features" section if not already there</action>
<action>- Add [CLOSED] or [COMPLETE] tag to indicate final status</action>
<action>Save updated bugs.md</action>
</check>
<output>
Bug/Feature Closure:
{{#if bugs_closed}}
- Bugs closed for Epic {{epic_number}}: {{bugs_closed_list}}
{{/if}}
{{#if features_completed}}
- Features completed for Epic {{epic_number}}: {{features_completed_list}}
{{/if}}
{{#if no_matches}}
- No outstanding bugs/features linked to Epic {{epic_number}}
{{/if}}
</output>
</check>
<check if="bugs.yaml does not exist">
<action>Skip bug tracking sync - no bugs.yaml file present</action>
</check>
</step>
<step n="12" goal="Save Retrospective and Update Sprint Status">
<action>Ensure retrospectives folder exists: {retrospectives_folder}</action>
<action>Create folder if it doesn't exist</action>
@ -1356,7 +1416,7 @@ Retrospective document was saved successfully, but {sprint_status_file} may need
</step>
<step n="12" goal="Final Summary and Handoff">
<step n="13" goal="Final Summary and Handoff">
<output>
**✅ Retrospective Complete, {user_name}!**

View File

@ -54,5 +54,9 @@ sprint_status_file: "{implementation_artifacts}/sprint-status.yaml"
story_directory: "{implementation_artifacts}"
retrospectives_folder: "{implementation_artifacts}"
# Bug tracking integration (optional)
bugs_yaml: "{planning_artifacts}/bugs.yaml"
bugs_md: "{planning_artifacts}/bugs.md"
standalone: true
web_bundle: false

View File

@ -48,6 +48,26 @@
<note>After discovery, these content variables are available: {epics_content} (all epics loaded - uses FULL_LOAD strategy)</note>
</step>
<step n="1.5" goal="Load bugs.yaml for bug/feature tracking (optional)">
<action>Check if {bugs_yaml} exists in {planning_artifacts}</action>
<check if="bugs_yaml exists">
<action>Read bugs.yaml using grep to find all bug-NNN and feature-NNN entries</action>
<action>For each bug/feature, extract:
- ID (e.g., bug-001, feature-003)
- Title
- Status (triaged, routed, in-progress, fixed/implemented, verified, closed)
- Recommended workflow (direct-fix, tech-spec, correct-course, backlog)
- Related stories (sprint_stories field for features)
</action>
<action>Build bug/feature inventory for inclusion in sprint status</action>
<action>Track feature-to-story mappings (feature-001 → stories 7-1, 7-2, etc.)</action>
</check>
<check if="bugs_yaml does not exist">
<output>Note: No bugs.yaml found - bug tracking not enabled for this project.</output>
<action>Continue without bug integration</action>
</check>
</step>
<step n="2" goal="Build sprint status structure">
<action>For each epic found, create entries in this order:</action>
@ -65,6 +85,17 @@ development_status:
epic-1-retrospective: optional
```
<action>If bugs.yaml was loaded, add bug/feature sources header comment:</action>
```yaml
# STORY SOURCES:
# ==============
# - epics.md: Primary source ({story_count} stories)
# - bugs.yaml: Feature-driven stories ({feature_story_count} stories from sprint_stories)
# - feature-001: 7-1, 7-2, 7-3 (from sprint_stories field)
# - feature-002: 3-7
```
</step>
<step n="3" goal="Apply intelligent status detection">

View File

@ -33,6 +33,10 @@ variables:
epics_location: "{planning_artifacts}" # Directory containing epic*.md files
epics_pattern: "epic*.md" # Pattern to find epic files
# Bug tracking integration (optional)
bugs_yaml: "{planning_artifacts}/bugs.yaml" # Structured bug/feature metadata
bugs_md: "{planning_artifacts}/bugs.md" # Human-readable bug tracking
# Output configuration
status_file: "{implementation_artifacts}/sprint-status.yaml"

View File

@ -88,15 +88,31 @@ Enter corrections (e.g., "1=in-progress, 2=backlog") or "skip" to continue witho
- IF any epic has status in-progress but has no associated stories: warn "in-progress epic has no stories"
</step>
<step n="2.5" goal="Load bug/feature tracking status (optional)">
<action>Check if {bugs_yaml} exists</action>
<check if="bugs_yaml exists">
<action>Grep for bug-NNN and feature-NNN entries with status field</action>
<action>Count items by status: triaged, fixed/implemented (pending verify), verified, closed</action>
<action>Identify items needing action:
- Items with [IMPLEMENTED] tag → need verification
- Items with status "triaged" + workflow "direct-fix" → ready for implementation
</action>
<action>Store: bugs_pending_verify, bugs_triaged, features_pending_verify, features_triaged</action>
</check>
</step>
<step n="3" goal="Select next action recommendation">
<action>Pick the next recommended workflow using priority:</action>
<note>When selecting "first" story: sort by epic number, then story number (e.g., 1-1 before 1-2 before 2-1)</note>
1. If any story status == in-progress → recommend `dev-story` for the first in-progress story
2. Else if any story status == review → recommend `code-review` for the first review story
3. Else if any story status == ready-for-dev → recommend `dev-story`
4. Else if any story status == backlog → recommend `create-story`
5. Else if any retrospective status == optional → recommend `retrospective`
6. Else → All implementation items done; suggest `workflow-status` to plan next phase
<note>Bug verification takes priority over new story work to close the feedback loop</note>
1. If any bug/feature has [IMPLEMENTED] tag (pending verify) → recommend `verify` for first pending item
2. If any story status == in-progress → recommend `dev-story` for the first in-progress story
3. Else if any story status == review → recommend `code-review` for the first review story
4. Else if any story status == ready-for-dev → recommend `dev-story`
5. Else if any bug status == triaged with workflow == direct-fix → recommend `implement` for first triaged bug
6. Else if any story status == backlog → recommend `create-story`
7. Else if any retrospective status == optional → recommend `retrospective`
8. Else → All implementation items done; suggest `workflow-status` to plan next phase
<action>Store selected recommendation as: next_story_id, next_workflow_id, next_agent (SM/DEV as appropriate)</action>
</step>
@ -112,6 +128,11 @@ Enter corrections (e.g., "1=in-progress, 2=backlog") or "skip" to continue witho
**Epics:** backlog {{epic_backlog}}, in-progress {{epic_in_progress}}, done {{epic_done}}
{{#if bugs_yaml_exists}}
**Bugs:** triaged {{bugs_triaged}}, pending-verify {{bugs_pending_verify}}, closed {{bugs_closed}}
**Features:** triaged {{features_triaged}}, pending-verify {{features_pending_verify}}, complete {{features_complete}}
{{/if}}
**Next Recommendation:** /bmad:bmm:workflows:{{next_workflow_id}} ({{next_story_id}})
{{#if risks}}

View File

@ -21,6 +21,9 @@ instructions: "{installed_path}/instructions.md"
variables:
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
tracking_system: "file-system"
# Bug tracking integration (optional)
bugs_yaml: "{planning_artifacts}/bugs.yaml"
bugs_md: "{planning_artifacts}/bugs.md"
# Smart input file references
input_file_patterns:

View File

@ -0,0 +1,180 @@
# Story Approved Workflow Instructions (DEV Agent)
<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>
<critical>Communicate all responses in {communication_language}</critical>
<workflow>
<critical>This workflow is run by DEV agent AFTER user confirms a story is approved (Definition of Done is complete)</critical>
<critical>Workflow: Update story file status to Done</critical>
<step n="1" goal="Find reviewed story to mark done" tag="sprint-status">
<check if="{story_path} is provided">
<action>Use {story_path} directly</action>
<action>Read COMPLETE story file and parse sections</action>
<action>Extract story_key from filename or story metadata</action>
<action>Verify Status is "review" - if not, HALT with message: "Story status must be 'review' to mark as done"</action>
</check>
<check if="{story_path} is NOT provided">
<critical>MUST read COMPLETE sprint-status.yaml file from start to end to preserve order</critical>
<action>Load the FULL file: {output_folder}/sprint-status.yaml</action>
<action>Read ALL lines from beginning to end - do not skip any content</action>
<action>Parse the development_status section completely</action>
<action>Find FIRST story (reading in order from top to bottom) where: - Key matches pattern: number-number-name (e.g., "1-2-user-auth") - NOT an epic key (epic-X) or retrospective (epic-X-retrospective) - Status value equals "review"
</action>
<check if="no story with status 'review' found">
<output>No stories with status "review" found
All stories are either still in development or already done.
**Next Steps:**
1. Run `dev-story` to implement stories
2. Run `code-review` if stories need review first
3. Check sprint-status.yaml for current story states
</output>
<action>HALT</action>
</check>
<action>Use the first reviewed story found</action>
<action>Find matching story file in {story_dir} using story_key pattern</action>
<action>Read the COMPLETE story file</action>
</check>
<action>Extract story_id and story_title from the story file</action>
<action>Find the "Status:" line (usually at the top)</action>
<action>Update story file: Change Status to "done"</action>
<action>Add completion notes to Dev Agent Record section:</action>
<action>Find "## Dev Agent Record" section and add:
```
### Completion Notes
**Completed:** {date}
**Definition of Done:** All acceptance criteria met, code reviewed, tests passing
```
</action>
<action>Save the story file</action>
</step>
<step n="2" goal="Update sprint status to done" tag="sprint-status">
<action>Load the FULL file: {output_folder}/sprint-status.yaml</action>
<action>Find development_status key matching {story_key}</action>
<action>Verify current status is "review" (expected previous state)</action>
<action>Update development_status[{story_key}] = "done"</action>
<action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action>
<check if="story key not found in file">
<output>Story file updated, but could not update sprint-status: {story_key} not found
Story is marked Done in file, but sprint-status.yaml may be out of sync.
</output>
</check>
</step>
<step n="3" goal="Sync related bugs/features in bug tracking">
<critical>Check bugs.yaml for bugs/features linked to this story and update their status</critical>
<action>Load {output_folder}/bugs.yaml if it exists</action>
<check if="bugs.yaml exists">
<action>Search for entries matching this story using ALL THREE methods:</action>
<action>1. Check sprint-status.yaml comment for "# Source: bugs.yaml/feature-XXX" or "# Source: bugs.yaml/bug-XXX" on the story line - this is the MOST RELIABLE method</action>
<action>2. Check related_story field matching {story_id} or {story_key}</action>
<action>3. Check sprint_stories array containing entries starting with {story_key}</action>
<critical>PRIORITY: Use sprint-status comment source if present - it's explicit and unambiguous</critical>
<check if="matching bugs found in bugs section (via related_story)">
<action>For each matching bug:</action>
<action>- Update status: "triaged" or "routed" → "fixed"</action>
<action>- Set fixed_date: {date}</action>
<action>- Set assigned_to: "dev-agent"</action>
<action>- Append to notes: "Auto-closed via story-done workflow. Story {story_key} marked done on {date}."</action>
</check>
<check if="matching features found in feature_requests section">
<action>For each matching feature (via related_story OR sprint_stories):</action>
<critical>MULTI-STORY FEATURE CHECK: If feature has sprint_stories array with multiple entries:</critical>
<action>1. Extract all story keys from sprint_stories (format: "story-key: status")</action>
<action>2. Load sprint-status.yaml and check development_status for EACH story</action>
<action>3. Only proceed if ALL stories in sprint_stories have status "done" in sprint-status.yaml</action>
<action>4. If any story is NOT done, skip this feature and log: "Feature {feature_id} has incomplete stories: {incomplete_list}"</action>
<check if="ALL sprint_stories are done (or feature has single story that matches)">
<action>- Update status: "backlog" or "in-progress" → "implemented"</action>
<action>- Set implemented_date: {date}</action>
<action>- Update sprint_stories entries to reflect done status</action>
<action>- Append to notes: "Auto-closed via story-done workflow. Story {story_key} marked done on {date}."</action>
</check>
</check>
<action>Save updated bugs.yaml</action>
<check if="bugs/features were updated">
<action>Also update bugs.md:</action>
<action>- Move bug entries from "# Tracked Bugs" to "# Fixed Bugs" with [IMPLEMENTED] tag</action>
<action>- Move feature entries from "# Tracked Feature Requests" to "# Implemented Features" with [IMPLEMENTED] tag</action>
<action>Save updated bugs.md</action>
</check>
<output>
Bug/Feature Sync:
{{#if bugs_updated}}
- Bugs marked fixed: {{bugs_updated_list}}
{{/if}}
{{#if features_updated}}
- Features marked implemented: {{features_updated_list}}
{{/if}}
{{#if features_pending}}
- Features with incomplete stories (not yet implemented): {{features_pending_list}}
{{/if}}
{{#if no_matches}}
- No related bugs/features found for story {story_key}
{{/if}}
</output>
</check>
<check if="bugs.yaml does not exist">
<action>Skip bug tracking sync - no bugs.yaml file present</action>
</check>
</step>
<step n="4" goal="Confirm completion to user">
<output>**Story Approved and Marked Done, {user_name}!**
Story file updated - Status: done
Sprint status updated: review → done
**Completed Story:**
- **ID:** {story_id}
- **Key:** {story_key}
- **Title:** {story_title}
- **Completed:** {date}
**Next Steps:**
1. Continue with next story in your backlog
- Run `create-story` for next backlog story
- Or run `dev-story` if ready stories exist
2. Check epic completion status
- Run `retrospective` workflow to check if epic is complete
- Epic retrospective will verify all stories are done
</output>
</step>
</workflow>

View File

@ -0,0 +1,27 @@
# Story Done Workflow (DEV Agent)
name: story-done
description: 'Marks a story as done (DoD complete), updates sprint-status → DONE, and syncs related bugs/features in bugs.yaml/bugs.md to [IMPLEMENTED] status.'
author: 'BMad'
# Critical variables from config
config_source: '{project-root}/.bmad/bmm/config.yaml'
output_folder: '{config_source}:output_folder'
user_name: '{config_source}:user_name'
communication_language: '{config_source}:communication_language'
date: system-generated
sprint_status: '{output_folder}/sprint-status.yaml'
# Workflow components
installed_path: '{project-root}/.bmad/bmm/workflows/4-implementation/story-done'
instructions: '{installed_path}/instructions.md'
# Variables and inputs
variables:
story_dir: '{config_source}:dev_ephemeral_location/stories' # Directory where stories are stored
bugs_yaml: '{output_folder}/bugs.yaml' # Bug/feature tracking structured data
bugs_md: '{output_folder}/bugs.md' # Bug/feature tracking human-readable log
# Output configuration - no output file, just status updates
default_output_file: ''
standalone: true

View File

@ -0,0 +1,376 @@
# Bug Tracking Workflow - Triage and Route
```xml
<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>
<critical>Communicate in {communication_language} with {user_name}</critical>
<critical>This workflow transforms informal bug reports (bugs.md) into structured metadata (bugs.yaml) with routing recommendations</critical>
<workflow>
<step n="0" goal="Sync bug reports from PostgreSQL">
<action>**0a. Fetch pending bug reports from the application database:**</action>
<action>GET {project_url}/api/bug-reports/pending</action>
<action>This endpoint returns all bug reports with status 'new' (not yet synced)</action>
<action>Response format: { data: { reports: [...], count: number } }</action>
<action>Each report contains: id, title, description, reporterType, reporterName, platform, browser, pageUrl, screenshotUrl, createdAt</action>
<check if="count == 0">
<output>No new bug reports from app. Proceeding with manual input check...</output>
<action>Continue to Step 1</action>
</check>
<check if="count > 0">
<action>**0b. Format reports as markdown entries:**</action>
<action>For each report, create markdown entry:
```markdown
## Bug: {title}
{description}
Reported by: {reporterName} ({reporterType})
Date: {createdAt formatted as YYYY-MM-DD}
Platform: {platform} / {browser}
Page: {pageUrl}
{if screenshotUrl: Screenshot: {screenshotUrl}}
```
</action>
<action>**0c. Insert into bugs.md under "# manual input" section:**</action>
<action>- Read the "# manual input" section location from bugs.md</action>
<action>- Insert the new markdown entries after the "# manual input" header</action>
<action>- Preserve any existing manual input entries</action>
<action>- Write updated bugs.md</action>
<action>**0d. Mark reports as synced in database:**</action>
<action>POST {project_url}/api/bug-reports/mark-synced</action>
<action>Body: { ids: [array of synced report IDs] }</action>
<action>This updates status to 'synced' so reports won't be fetched again</action>
<output>**Synced {count} bug report(s) from app:**
{for each report:}
- {title} (from {reporterName})
{end for}
Proceeding with triage...
</output>
</check>
</step>
<step n="1" goal="Load input files and initialize">
<action>Resolve variables from config_source: bugs_input, bugs_output, sprint_status, epics_file</action>
<action>**1a. Read "# manual input" section from bugs.md (section-based reading):**</action>
<action>- Grep for "# manual input" to find starting line number</action>
<action>- Grep for next section header ("# Tracked Bugs", "# Tracked Feature Requests", "# Fixed Bugs") to find ending line</action>
<action>- Read just that range using offset/limit (do NOT read entire file)</action>
<action>- If no closing section found within initial window, expand read range and retry</action>
<action>**1b. Search bugs.yaml for existing IDs (do NOT read entire file):**</action>
<action>- Grep for "bug-[0-9]+" pattern to find all existing bug IDs</action>
<action>- Grep for "feature-[0-9]+" pattern to find all existing feature IDs</action>
<action>- This allows duplicate detection and next-ID generation without reading full file</action>
<action>- If bugs.yaml doesn't exist, create it with header/definitions from template</action>
<action>Load {sprint_status} to understand current sprint context (which stories are in progress)</action>
<action>Load {epics_file} to map bugs to related stories/epics</action>
</step>
<step n="2" goal="Parse bugs.md and identify new/updated bugs">
<action>Parse {bugs_input} (bugs.md) to extract bug reports</action>
<action>CRITICAL: Only triage items from the "# manual input" section</action>
<action>DO NOT triage:
- Items in "# Tracked Bugs" section (already triaged)
- Items in "# Tracked Feature Requests" section (already triaged)
- Items in "# Fixed Bugs" section (already closed)
</action>
<action>Expected format in "# manual input" section (informal, user-written):
- Markdown headers (## Bug: Title) OR bullet lists
- Freeform descriptions
- Optional fields: reported by, date, related story
- May be incomplete (missing severity, complexity, etc.)
</action>
<action>Extract from each bug report in "# manual input":
- Title (required)
- Description (required - may be multi-paragraph)
- Reported by (optional - extract if mentioned)
- Reported date (optional - extract if mentioned)
- Related story (optional - extract story ID if mentioned, e.g. "2-7" or "Story 2.7")
- Platform (optional - extract if mentioned: iOS, Android, all)
- Any reproduction steps
</action>
<action>Compare extracted bugs with existing bugs.yaml entries:</action>
<action>- New bugs: Not in bugs.yaml yet (need full triage)</action>
<action>- Updated bugs: Already in bugs.yaml but description changed (need re-triage)</action>
<action>- Unchanged bugs: Already triaged, skip</action>
<action>If NO new bugs found in "# manual input" section:</action>
<output>No new bugs found in bugs.md
All bugs have already been triaged and are tracked in bugs.yaml.
**Options:**
1. Add new bugs to docs/bugs.md (informal format)
2. View bugs.yaml to see structured bug tracking
3. Route existing triaged bugs to workflows
</output>
<action>HALT</action>
</step>
<step n="3" goal="Triage each new/updated bug" for-each="new_bug">
<action>For each new/updated bug, perform triage analysis:</action>
<action>**3a. Generate Bug ID**</action>
<action>- Use grep results from Step 1b to find highest existing bug-NNN</action>
<action>- Assign next sequential ID (e.g., bug-006)</action>
<action>- Format: "bug-" + zero-padded 3-digit number</action>
<action>**3b. Assess Severity** (critical, high, medium, low)</action>
<action>Analysis questions:</action>
<action>- Does it prevent core functionality? (critical)</action>
<action>- Does it cause crashes or data loss? (critical)</action>
<action>- Does it block major features? (high)</action>
<action>- Does it significantly degrade UX but have workaround? (high)</action>
<action>- Does it affect subset of users with minor impact? (medium)</action>
<action>- Is it cosmetic or edge case? (low)</action>
<action>Reference severity definitions in bugs.yaml header</action>
<check if="severity unclear from description">
<ask>**Clarification needed for bug: {bug_title}**
I need more information to assess severity:
1. Does this bug prevent users from completing core flows?
2. Does the bug cause crashes or data loss?
3. How many users are affected? (all users, specific platform, edge case)
4. Is there a workaround available?
Please provide additional context so I can properly triage this bug.
</ask>
</check>
<action>**3c. Assess Complexity** (trivial, small, medium, complex)</action>
<action>Analysis questions:</action>
<action>- Is it a one-line fix? (trivial)</action>
<action>- Single file/component, solution obvious? (small)</action>
<action>- Multiple files OR requires investigation? (medium)</action>
<action>- Architectural change OR affects many stories? (complex)</action>
<action>Reference complexity definitions in bugs.yaml header</action>
<check if="complexity unclear from description">
<ask>**Clarification needed for bug: {bug_title}**
To estimate complexity, I need:
1. Have you identified the root cause, or does it need investigation?
2. Which file(s) or component(s) are affected?
3. Is this an isolated issue or does it affect multiple parts of the app?
Please provide technical details if available (stack trace, repro steps, affected files).
</ask>
</check>
<action>**3d. Calculate Effort Estimate** (in hours)</action>
<action>Based on complexity:</action>
<action>- trivial: 0.25 - 0.5 hours</action>
<action>- small: 0.5 - 2 hours</action>
<action>- medium: 2 - 8 hours</action>
<action>- complex: 8 - 16+ hours</action>
<action>**3e. Determine Workflow Path**</action>
<action>Apply routing matrix from bugs.yaml header:</action>
<action>- critical + any complexity -> "correct-course" (need impact analysis)</action>
<action>- high + trivial -> "direct-fix" (urgent, obvious fix)</action>
<action>- high + small -> "tech-spec" (urgent, needs spec)</action>
<action>- high + medium/complex -> "correct-course" (need proper analysis)</action>
<action>- medium + trivial -> "direct-fix"</action>
<action>- medium + small -> "tech-spec"</action>
<action>- medium + medium/complex -> "correct-course"</action>
<action>- low + trivial -> "direct-fix" (defer)</action>
<action>- low + small/medium/complex -> "backlog" (defer)</action>
<action>**3f. Map to Related Story/Epic**</action>
<action>If bug mentions story ID (e.g., "2-7"), use that</action>
<action>Otherwise, infer from description using epic keywords</action>
<action>Reference epics.md for story matching</action>
<action>**3g. Determine Affected Platform**</action>
<action>From description, extract: all | ios | android | web</action>
<action>Default to "all" if not specified</action>
<action>**3h. Set Initial Status**</action>
<action>- New bug -> status: "triaged"</action>
<action>- All other fields: null or empty (to be filled when routed/fixed)</action>
<action>**3i. Add Triage Notes**</action>
<action>Document reasoning:</action>
<action>- Why this severity? (business impact, user impact)</action>
<action>- Why this complexity? (investigation needed, files affected)</action>
<action>- Why this workflow? (routing logic applied)</action>
<action>- Suggested next steps or investigation areas</action>
<action>**3j. Assess Documentation Impact**</action>
<action>Evaluate if fix/feature requires updates beyond code:</action>
<action>**PRD Impact** (doc_impact.prd: true/false)</action>
<action>Set TRUE if issue:</action>
<action>- Conflicts with stated product goals or objectives</action>
<action>- Requires changing MVP scope or feature definitions</action>
<action>- Adds/removes/modifies core user-facing functionality</action>
<action>- Changes success metrics or acceptance criteria at product level</action>
<action>- Affects multiple epics or cross-cutting concerns</action>
<action>**Architecture Impact** (doc_impact.architecture: true/false)</action>
<action>Set TRUE if issue:</action>
<action>- Requires new system components or services</action>
<action>- Changes data model (new tables, schema modifications)</action>
<action>- Affects API contracts or integration points</action>
<action>- Introduces new dependencies or technology choices</action>
<action>- Changes authentication, authorization, or security model</action>
<action>- Modifies deployment or infrastructure patterns</action>
<action>**UX Impact** (doc_impact.ux: true/false)</action>
<action>Set TRUE if issue:</action>
<action>- Adds new screens, modals, or navigation paths</action>
<action>- Changes existing user flows or interaction patterns</action>
<action>- Requires new UI components not in design system</action>
<action>- Affects accessibility or responsive behavior requirements</action>
<action>- Changes visual hierarchy or information architecture</action>
<action>- Impacts user onboarding or first-run experience</action>
<action>**Documentation Notes** (doc_impact.notes)</action>
<action>If any impact is TRUE, briefly describe:</action>
<action>- Which specific sections need updates</action>
<action>- Nature of the change (addition, modification, removal)</action>
<action>- Dependencies between document updates</action>
<check if="any doc_impact is TRUE AND recommended_workflow != 'correct-course'">
<action>**Override workflow to correct-course**</action>
<action>Documentation impact requires proper change analysis before implementation</action>
<action>Update recommended_workflow: "correct-course"</action>
<action>Add to notes: "Workflow elevated to correct-course due to documentation impact"</action>
</check>
</step>
<step n="4" goal="Update bugs.yaml and bugs.md with triaged metadata">
<action>**4a. Update bugs.yaml**</action>
<action>Load existing bugs.yaml structure (if exists)</action>
<action>For each triaged bug:</action>
<action>- If new bug: Add to "bugs:" section with all metadata</action>
<action>- If existing bug: Update metadata fields if changed</action>
<action>Preserve all existing bugs and closed_bugs sections</action>
<action>Update statistics section:</action>
<action>- Count bugs by severity, complexity, status, workflow</action>
<action>- Set last_updated to {date}</action>
<action>Write complete bugs.yaml file</action>
<action>Preserve ALL header comments and definitions</action>
<action>**4b. Update bugs.md - Move triaged bugs to # Tracked Bugs section**</action>
<action>Use section-based reading to locate relevant sections:</action>
<action>- Grep for "# manual input" and "# Tracked Bugs" line numbers</action>
<action>- Read just those sections with offset/limit (do NOT read entire file)</action>
<action>For each newly triaged bug:</action>
<action>- REMOVE the original entry from "# manual input" section</action>
<action>- ADD formatted entry to "# Tracked Bugs" section (create section if missing)</action>
<action>- Format: "{bug_id}: {title} - {brief_description}. [Severity: {severity}, Complexity: {complexity}, Platform: {affected_platform}, Workflow: {recommended_workflow}]"</action>
<action>- If doc_impact flagged, add: "Doc Impact: {prd|architecture|ux as applicable}"</action>
<action>- Include sub-items with notes if available</action>
<action>For feature requests, use "# Tracked Feature Requests" section instead</action>
<action>Write updated bugs.md</action>
</step>
<step n="5" goal="Present triage summary and next steps">
<output>**Bug Triage Complete, {user_name}!**
**Triaged {triaged_count} bug(s):**
{for each triaged bug:}
---
**{bug_id}: {bug_title}**
- **Severity:** {severity} | **Complexity:** {complexity} | **Platform:** {affected_platform}
- **Effort:** ~{effort_estimate} hours
- **Recommended Workflow:** {recommended_workflow}
- **Related:** {related_story} (Epic {related_epic})
{if doc_impact.prd OR doc_impact.architecture OR doc_impact.ux:}
- **Documentation Impact:** {prd: Y | architecture: Y | ux: Y as applicable}
- {doc_impact.notes}
{end if}
**Triage Reasoning:**
{triage_notes}
{end for}
---
**Updated Files:**
- docs/bugs.yaml - Structured metadata for all triaged bugs
- docs/bugs.md - Moved triaged bugs to "# Tracked Bugs" section
**Summary:**
- Total Active Bugs: {total_active_bugs}
- Critical: {critical_count} | High: {high_count} | Medium: {medium_count} | Low: {low_count}
{if any doc_impact flagged:}
**Documentation Updates Required:**
- PRD Impact: {prd_impact_count} item(s)
- Architecture Impact: {arch_impact_count} item(s)
- UX Impact: {ux_impact_count} item(s)
Items with documentation impact have been routed to `correct-course` workflow.
{end if}
**Workflow Recommendations:**
- Direct Fix ({direct_fix_count}): `/implement bug-NNN` - Quick fixes, no spec needed
- Tech-Spec ({tech_spec_count}): Create tech-spec first, then `/implement`
- Correct-Course ({correct_course_count}): Run correct-course workflow for impact analysis
---
**Next Steps:**
To implement a bug fix:
```
/implement bug-NNN
```
To verify and close after testing:
```
/verify bug-NNN
```
To verify all implemented bugs:
```
/verify
```
</output>
</step>
</workflow>
```
## Example bugs.md Format (User-Facing)
Users can write bugs in any freeform markdown format. The workflow parses common patterns:
**Option 1: Markdown Headers**
```markdown
## Bug: Join button doesn't work on Android
When I tap the "Join" button, nothing happens. Tested on Samsung Galaxy S21.
Reported by: Sarah
Date: Nov 19, 2025
Related: Story 2.7
```
**Option 2: Bullet Lists**
```markdown
- **Join button unresponsive (Android)**: Button doesn't respond to taps. Works on iOS. Probably a touch target issue.
- **App crashes offline**: If I turn off WiFi and try to create something, the app crashes. CRITICAL!
```
**Option 3: Numbered Lists**
```markdown
1. Typo in success message - says "sucessfully" instead of "successfully"
2. Times showing in UTC instead of local time - very confusing for users
```
The workflow is flexible and extracts whatever information is available, then prompts the user for missing details during triage.

View File

@ -0,0 +1,542 @@
# In-App Bug Reporting - Reference Implementation
This document provides a reference implementation for adding **in-app bug reporting** to your project. The BMAD bug-tracking workflow works without this feature (using manual `bugs.md` input), but in-app reporting provides a better user experience.
## Overview
The in-app bug reporting feature allows users to submit bug reports directly from your application. Reports are stored in your database and then synced to `bugs.md` by the triage workflow.
```
User -> UI Modal -> API -> Database -> Triage Workflow -> bugs.md/bugs.yaml
```
## Components Required
| Component | Purpose | Stack-Specific |
|-----------|---------|----------------|
| Database table | Store pending bug reports | Yes |
| API: Create report | Accept user submissions | Yes |
| API: Get pending | Fetch unsynced reports | Yes |
| API: Mark synced | Update status after sync | Yes |
| UI Modal | Bug report form | Yes |
| Validation schemas | Input validation | Partially |
## 1. Database Schema
### Drizzle ORM (PostgreSQL)
```typescript
// src/lib/server/db/schema.ts
import { pgTable, uuid, text, timestamp, index } from 'drizzle-orm/pg-core';
export const bugReports = pgTable(
'bug_reports',
{
id: uuid('id').primaryKey().defaultRandom(),
organizationId: uuid('organization_id').notNull(), // For multi-tenant apps
reporterType: text('reporter_type').notNull(), // 'staff' | 'member' | 'user'
reporterId: uuid('reporter_id').notNull(),
title: text('title').notNull(),
description: text('description').notNull(),
userAgent: text('user_agent'),
pageUrl: text('page_url'),
platform: text('platform'), // 'Windows', 'macOS', 'iOS', etc.
browser: text('browser'), // 'Chrome', 'Safari', 'Firefox'
screenshotUrl: text('screenshot_url'), // Optional: cloud storage URL
status: text('status').notNull().default('new'), // 'new' | 'synced' | 'dismissed'
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
syncedAt: timestamp('synced_at', { withTimezone: true })
},
(table) => [
index('bug_reports_organization_id_idx').on(table.organizationId),
index('bug_reports_status_idx').on(table.status),
index('bug_reports_created_at_idx').on(table.createdAt)
]
);
export const BUG_REPORT_STATUS = {
NEW: 'new',
SYNCED: 'synced',
DISMISSED: 'dismissed'
} as const;
export const REPORTER_TYPE = {
STAFF: 'staff',
MEMBER: 'member',
USER: 'user'
} as const;
```
### Prisma Schema
```prisma
model BugReport {
id String @id @default(uuid())
organizationId String @map("organization_id")
reporterType String @map("reporter_type")
reporterId String @map("reporter_id")
title String
description String
userAgent String? @map("user_agent")
pageUrl String? @map("page_url")
platform String?
browser String?
screenshotUrl String? @map("screenshot_url")
status String @default("new")
createdAt DateTime @default(now()) @map("created_at")
syncedAt DateTime? @map("synced_at")
@@index([organizationId])
@@index([status])
@@index([createdAt])
@@map("bug_reports")
}
```
## 2. Validation Schemas
### Zod (TypeScript)
```typescript
// src/lib/schemas/bug-report.ts
import { z } from 'zod';
export const createBugReportSchema = z.object({
title: z
.string()
.trim()
.min(5, 'Title must be at least 5 characters')
.max(200, 'Title must be 200 characters or less'),
description: z
.string()
.trim()
.min(10, 'Description must be at least 10 characters')
.max(5000, 'Description must be 5000 characters or less'),
pageUrl: z.string().url().optional(),
userAgent: z.string().max(1000).optional(),
platform: z.string().max(50).optional(),
browser: z.string().max(50).optional()
});
export const markSyncedSchema = z.object({
ids: z.array(z.string().uuid()).min(1, 'At least one ID is required')
});
export const SCREENSHOT_CONFIG = {
maxSizeBytes: 5 * 1024 * 1024, // 5MB
maxSizeMB: 5,
allowedTypes: ['image/jpeg', 'image/png', 'image/webp'] as const
} as const;
```
## 3. API Endpoints
### POST /api/bug-reports - Create Report
```typescript
// SvelteKit: src/routes/api/bug-reports/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { db } from '$lib/server/db';
import { bugReports } from '$lib/server/db/schema';
import { createBugReportSchema } from '$lib/schemas/bug-report';
export const POST: RequestHandler = async ({ request, locals }) => {
// Determine reporter from auth context
if (!locals.user) {
return json({ error: { code: 'UNAUTHORIZED' } }, { status: 401 });
}
const body = await request.json();
const result = createBugReportSchema.safeParse(body);
if (!result.success) {
return json({
error: { code: 'VALIDATION_ERROR', message: result.error.issues[0]?.message }
}, { status: 400 });
}
const { title, description, pageUrl, userAgent, platform, browser } = result.data;
const [newReport] = await db
.insert(bugReports)
.values({
organizationId: locals.user.organizationId,
reporterType: 'staff',
reporterId: locals.user.id,
title,
description,
pageUrl,
userAgent,
platform,
browser
})
.returning();
return json({
data: {
bugReport: {
id: newReport.id,
title: newReport.title,
createdAt: newReport.createdAt.toISOString()
}
}
}, { status: 201 });
};
```
### GET /api/bug-reports/pending - Fetch for Triage
```typescript
// SvelteKit: src/routes/api/bug-reports/pending/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { db } from '$lib/server/db';
import { bugReports, BUG_REPORT_STATUS } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
export const GET: RequestHandler = async () => {
const reports = await db
.select()
.from(bugReports)
.where(eq(bugReports.status, BUG_REPORT_STATUS.NEW))
.orderBy(bugReports.createdAt);
// Map to workflow-expected format
const formatted = reports.map((r) => ({
id: r.id,
title: r.title,
description: r.description,
reporterType: r.reporterType,
reporterName: 'Unknown', // Join with users table for real name
platform: r.platform,
browser: r.browser,
pageUrl: r.pageUrl,
screenshotUrl: r.screenshotUrl,
createdAt: r.createdAt.toISOString()
}));
return json({
data: {
reports: formatted,
count: formatted.length
}
});
};
```
### POST /api/bug-reports/mark-synced - Update After Sync
```typescript
// SvelteKit: src/routes/api/bug-reports/mark-synced/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { db } from '$lib/server/db';
import { bugReports, BUG_REPORT_STATUS } from '$lib/server/db/schema';
import { inArray } from 'drizzle-orm';
import { markSyncedSchema } from '$lib/schemas/bug-report';
export const POST: RequestHandler = async ({ request }) => {
const body = await request.json();
const result = markSyncedSchema.safeParse(body);
if (!result.success) {
return json({
error: { code: 'VALIDATION_ERROR', message: result.error.issues[0]?.message }
}, { status: 400 });
}
const updated = await db
.update(bugReports)
.set({
status: BUG_REPORT_STATUS.SYNCED,
syncedAt: new Date()
})
.where(inArray(bugReports.id, result.data.ids))
.returning({ id: bugReports.id });
return json({
data: {
updatedCount: updated.length,
updatedIds: updated.map((r) => r.id)
}
});
};
```
## 4. UI Component
### Svelte 5 (with shadcn-svelte)
```svelte
<!-- src/lib/components/BugReportModal.svelte -->
<script lang="ts">
import * as Dialog from '$lib/components/ui/dialog';
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { Textarea } from '$lib/components/ui/textarea';
import { toast } from 'svelte-sonner';
import { Bug } from 'lucide-svelte';
import { browser } from '$app/environment';
interface Props {
open: boolean;
onClose: () => void;
}
let { open = $bindable(), onClose }: Props = $props();
let title = $state('');
let description = $state('');
let loading = $state(false);
// Auto-detect environment
let platform = $derived(browser ? detectPlatform() : '');
let browserName = $derived(browser ? detectBrowser() : '');
let currentUrl = $derived(browser ? window.location.href : '');
function detectPlatform(): string {
const ua = navigator.userAgent.toLowerCase();
if (ua.includes('iphone') || ua.includes('ipad')) return 'iOS';
if (ua.includes('android')) return 'Android';
if (ua.includes('mac')) return 'macOS';
if (ua.includes('win')) return 'Windows';
return 'Unknown';
}
function detectBrowser(): string {
const ua = navigator.userAgent;
if (ua.includes('Chrome') && !ua.includes('Edg')) return 'Chrome';
if (ua.includes('Safari') && !ua.includes('Chrome')) return 'Safari';
if (ua.includes('Firefox')) return 'Firefox';
if (ua.includes('Edg')) return 'Edge';
return 'Unknown';
}
async function handleSubmit() {
loading = true;
try {
const response = await fetch('/api/bug-reports', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title,
description,
pageUrl: currentUrl,
userAgent: navigator.userAgent,
platform,
browser: browserName
})
});
if (!response.ok) {
const data = await response.json();
toast.error(data.error?.message || 'Failed to submit');
return;
}
toast.success('Bug report submitted');
onClose();
} finally {
loading = false;
}
}
</script>
<Dialog.Root bind:open onOpenChange={(o) => !o && onClose()}>
<Dialog.Content class="sm:max-w-[500px]">
<Dialog.Header>
<Dialog.Title class="flex items-center gap-2">
<Bug class="h-5 w-5" />
Report a Bug
</Dialog.Title>
</Dialog.Header>
<form onsubmit={(e) => { e.preventDefault(); handleSubmit(); }} class="space-y-4">
<div>
<Input bind:value={title} placeholder="Brief summary" maxlength={200} />
</div>
<div>
<Textarea bind:value={description} placeholder="What happened?" rows={4} />
</div>
<div class="rounded-md bg-muted p-3 text-sm text-muted-foreground">
{platform} / {browserName}
</div>
<Dialog.Footer>
<Button variant="outline" onclick={onClose} disabled={loading}>Cancel</Button>
<Button type="submit" disabled={loading}>Submit</Button>
</Dialog.Footer>
</form>
</Dialog.Content>
</Dialog.Root>
```
### React (with shadcn/ui)
```tsx
// src/components/BugReportModal.tsx
import { useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Bug } from 'lucide-react';
import { toast } from 'sonner';
interface Props {
open: boolean;
onClose: () => void;
}
export function BugReportModal({ open, onClose }: Props) {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [loading, setLoading] = useState(false);
const detectPlatform = () => {
const ua = navigator.userAgent.toLowerCase();
if (ua.includes('iphone') || ua.includes('ipad')) return 'iOS';
if (ua.includes('android')) return 'Android';
if (ua.includes('mac')) return 'macOS';
if (ua.includes('win')) return 'Windows';
return 'Unknown';
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
const response = await fetch('/api/bug-reports', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title,
description,
pageUrl: window.location.href,
userAgent: navigator.userAgent,
platform: detectPlatform()
})
});
if (!response.ok) throw new Error('Failed to submit');
toast.success('Bug report submitted');
onClose();
} catch {
toast.error('Failed to submit bug report');
} finally {
setLoading(false);
}
};
return (
<Dialog open={open} onOpenChange={(o) => !o && onClose()}>
<DialogContent>
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Bug className="h-5 w-5" />
Report a Bug
</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<Input value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Brief summary" />
<Textarea value={description} onChange={(e) => setDescription(e.target.value)} placeholder="What happened?" />
<DialogFooter>
<Button variant="outline" onClick={onClose} disabled={loading}>Cancel</Button>
<Button type="submit" disabled={loading}>Submit</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}
```
## 5. Workflow Configuration
Update your project's `.bmad/bmm/config.yaml` to set the `project_url`:
```yaml
# .bmad/bmm/config.yaml
project_url: "http://localhost:5173" # Dev
# project_url: "https://your-app.com" # Prod
```
The triage workflow will use this to call your API endpoints.
## 6. API Response Format
The workflow expects these response formats:
### GET /api/bug-reports/pending
```json
{
"data": {
"reports": [
{
"id": "uuid",
"title": "Bug title",
"description": "Bug description",
"reporterType": "staff",
"reporterName": "John Doe",
"platform": "macOS",
"browser": "Chrome",
"pageUrl": "https://...",
"screenshotUrl": "https://...",
"createdAt": "2025-01-01T00:00:00Z"
}
],
"count": 1
}
}
```
### POST /api/bug-reports/mark-synced
Request:
```json
{ "ids": ["uuid1", "uuid2"] }
```
Response:
```json
{
"data": {
"updatedCount": 2,
"updatedIds": ["uuid1", "uuid2"]
}
}
```
## 7. Optional: Screenshot Storage
For screenshot uploads, you'll need cloud storage (R2, S3, etc.):
1. Create an upload endpoint: `POST /api/bug-reports/[id]/upload-screenshot`
2. Upload to cloud storage
3. Update `screenshotUrl` on the bug report record
## 8. Security Considerations
- **Authentication**: Create endpoint should require auth
- **API Key**: Consider adding API key auth for pending/mark-synced endpoints in production
- **Rate Limiting**: Add rate limits to prevent spam
- **Input Sanitization**: Validate all user input (handled by Zod schemas)
## Without In-App Reporting
If you don't implement in-app reporting, the workflow still works:
1. Users manually add bugs to `docs/bugs.md` under `# manual input`
2. Run `/triage` to process them
3. Workflow skips Step 0 (API sync) when no API is available
The workflows are designed to be flexible and work with or without the in-app feature.

View File

@ -0,0 +1,32 @@
name: bug-tracking
description: "Triage user-reported bugs from bugs.md, generate structured metadata in bugs.yaml, and route to appropriate workflow"
author: "BMad"
# Critical variables from config
config_source: "{project-root}/.bmad/bmm/config.yaml"
output_folder: "{config_source}:output_folder"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
date: system-generated
# Workflow components
installed_path: "{project-root}/.bmad/bmm/workflows/bug-tracking"
instructions: "{installed_path}/instructions.md"
validation: "{installed_path}/checklist.md"
template: false # This is an action workflow, not a template workflow
# Input and output files
variables:
bugs_input: "{output_folder}/bugs.md" # User-facing bug reports (informal)
bugs_output: "{output_folder}/bugs.yaml" # Agent-facing structured metadata
sprint_status: "{config_source}:dev_ephemeral_location/sprint-status.yaml" # For routing context
epics_file: "{output_folder}/epics.md" # For related story lookup
project_url: "http://localhost:5173" # Base URL for API calls (update for production)
# Output configuration
default_output_file: "{bugs_output}"
# Documentation
reference_implementation: "{installed_path}/reference-implementation.md" # Optional in-app reporting setup
standalone: true

View File

@ -0,0 +1,505 @@
# Implement Workflow (Bug Fix or Feature)
```xml
<critical>This workflow loads bug/feature context, implements the code, and updates tracking in both bugs.yaml and bugs.md</critical>
<critical>Communicate in {communication_language} with {user_name}</critical>
<critical>Auto-detects type from ID format: bug-NNN = bug fix, feature-NNN = feature implementation</critical>
<workflow>
<step n="1" goal="Get item ID from user">
<check if="item_id not provided in user input">
<ask>Which bug or feature should I implement? (e.g., bug-026 or feature-021)</ask>
</check>
<action>Extract item ID from user input</action>
<action>Detect type from ID format:</action>
<action>- "bug-NNN" -> type = "bug", action_verb = "fix", past_verb = "Fixed"</action>
<action>- "feature-NNN" -> type = "feature", action_verb = "implement", past_verb = "Implemented"</action>
<check if="ID doesn't match either format">
<output>Invalid ID format. Use bug-NNN (e.g., bug-026) or feature-NNN (e.g., feature-021)</output>
<action>HALT</action>
</check>
</step>
<step n="2" goal="Load context from bugs.yaml">
<action>Search for {item_id} in {bugs_yaml} using grep with 50+ lines of context after the match (do NOT read entire file - it exceeds token limits)</action>
<check if="type == bug">
<action>Entry will be in bugs section, grep will capture all fields</action>
</check>
<check if="type == feature">
<action>Entry will be in feature_requests section, grep will capture all fields</action>
</check>
<check if="item not found in bugs.yaml">
<output>{item_id} not found in bugs.yaml. Please verify the ID or run bug-tracking workflow first.</output>
<action>HALT</action>
</check>
<action>Extract and store metadata:</action>
<action>- title: Title/summary</action>
<action>- description: Full description</action>
<action>- severity/priority: Importance level</action>
<action>- complexity: trivial | small | medium | complex</action>
<action>- effort_estimate: Estimated hours</action>
<action>- affected_platform: all | ios | android (bugs only)</action>
<action>- related_story/related_epic: Related items if applicable</action>
<action>- doc_impact: Documentation impact flags (prd, architecture, ux) and notes</action>
<action>- notes: Triage notes including planned approach, files to check, implementation strategy</action>
<check if="recommended_workflow == 'backlog'">
<output>**BACKLOG ITEM - NOT READY FOR IMPLEMENTATION**
**{item_id}: {title}**
This item has `recommended_workflow: backlog` which means it's deferred and not scheduled for implementation.
**To implement this item, first promote it to the sprint:**
1. Run `*sprint-planning` and select this item for promotion
2. Or manually update bugs.yaml: change `recommended_workflow` to `direct-fix`, `tech-spec`, or `correct-course`
**Current Status:** {status}
**Priority:** {priority}
**Complexity:** {complexity}
</output>
<action>HALT</action>
</check>
<check if="status == 'deferred'">
<output>**DEFERRED ITEM - NOT READY FOR IMPLEMENTATION**
**{item_id}: {title}**
This item is deferred (marked for future release, not current MVP).
**To implement this item:**
1. Update bugs.yaml: change `status` from `deferred` to `backlog`
2. Run `*sprint-planning` to promote to current sprint
**Notes:** {notes}
</output>
<action>HALT</action>
</check>
<check if="status == 'blocked'">
<output>**BLOCKED ITEM - CANNOT IMPLEMENT**
**{item_id}: {title}**
This item is blocked and requires clarification before implementation.
**Blocking reason:** {notes}
**To unblock:**
1. Resolve the blocking issue
2. Update bugs.yaml: change `status` from `blocked` to `backlog`
3. Run `/triage {item_id}` to re-evaluate
</output>
<action>HALT</action>
</check>
</step>
<step n="2.5" goal="Check for documentation impact and route to appropriate agents">
<action>Check doc_impact fields from bugs.yaml entry</action>
<check if="doc_impact.prd OR doc_impact.architecture OR doc_impact.ux is TRUE">
<output>**DOCUMENTATION IMPACT DETECTED**
**{item_id}: {title}**
This {type} requires documentation updates BEFORE implementation:
{if doc_impact.prd:}
- **PRD Impact:** Updates needed to product requirements
-> Route to PM Agent for PRD updates
{end if}
{if doc_impact.architecture:}
- **Architecture Impact:** Updates needed to architecture docs
-> Route to Architect Agent for architecture updates
{end if}
{if doc_impact.ux:}
- **UX Impact:** Updates needed to UX specifications
-> Route to UX Designer Agent for UX spec updates
{end if}
**Details:** {doc_impact.notes}
**Options:**
1. **update-docs-first** - Route to agents for documentation updates before implementation (recommended)
2. **proceed-anyway** - Skip documentation updates and implement directly (not recommended)
3. **cancel** - Return to review</output>
<ask>How should we proceed?</ask>
<check if="user chooses update-docs-first">
<output>Routing to documentation update workflow...
**Documentation Update Sequence:**</output>
<check if="doc_impact.prd">
<output>1. **PRD Update** - Invoking PM Agent...</output>
<action>Prepare PRD update context:</action>
<action>- Source item: {item_id}</action>
<action>- Change description: {description}</action>
<action>- Specific PRD sections: {doc_impact.notes PRD sections}</action>
<invoke-agent agent="pm">
<task>Review and update PRD for {item_id}: {title}
Change context: {description}
Documentation notes: {doc_impact.notes}
Please update the relevant PRD sections to reflect this change. After updates, summarize what was changed.</task>
</invoke-agent>
</check>
<check if="doc_impact.architecture">
<output>2. **Architecture Update** - Invoking Architect Agent...</output>
<action>Prepare architecture update context:</action>
<action>- Source item: {item_id}</action>
<action>- Change description: {description}</action>
<action>- Specific architecture sections: {doc_impact.notes architecture sections}</action>
<invoke-agent agent="architect">
<task>Review and update Architecture documentation for {item_id}: {title}
Change context: {description}
Documentation notes: {doc_impact.notes}
Please update the relevant architecture sections (data model, APIs, security, etc.) to reflect this change. After updates, summarize what was changed.</task>
</invoke-agent>
</check>
<check if="doc_impact.ux">
<output>3. **UX Spec Update** - Invoking UX Designer Agent...</output>
<action>Prepare UX update context:</action>
<action>- Source item: {item_id}</action>
<action>- Change description: {description}</action>
<action>- Specific UX sections: {doc_impact.notes UX sections}</action>
<invoke-agent agent="ux-designer">
<task>Review and update UX specification for {item_id}: {title}
Change context: {description}
Documentation notes: {doc_impact.notes}
Please update the relevant UX spec sections (screens, flows, components, etc.) to reflect this change. After updates, summarize what was changed.</task>
</invoke-agent>
</check>
<output>**Documentation updates complete.**
Proceeding with implementation...</output>
<action>Continue to step 3</action>
</check>
<check if="user chooses cancel">
<output>Cancelled. {item_id} remains in current state.</output>
<action>HALT</action>
</check>
<action if="user chooses proceed-anyway">
<output>Proceeding without documentation updates. Remember to update docs after implementation.</output>
<action>Continue to step 3</action>
</action>
</check>
</step>
<step n="3" goal="Evaluate routing and auto-route to correct-course if needed">
<action>Check recommended_workflow field from bugs.yaml</action>
<check if="recommended_workflow == 'correct-course'">
<output>**AUTO-ROUTING TO CORRECT-COURSE**
**{item_id}: {title}**
**Priority:** {severity_or_priority} | **Complexity:** {complexity}
This {type} has `recommended_workflow: correct-course` which requires impact analysis and story creation before implementation.
Invoking correct-course workflow via SM agent...</output>
<action>Invoke the correct-course workflow skill with item context</action>
<invoke-skill skill="bmad:bmm:workflows:correct-course">
<args>{item_id}: {title} - {description}
Priority: {severity_or_priority}
Complexity: {complexity}
Doc Impact: {doc_impact summary}
Notes: {notes}</args>
</invoke-skill>
<action>HALT - Correct Course workflow will handle story/epic creation</action>
</check>
<check if="recommended_workflow == 'tech-spec'">
<output>**AUTO-ROUTING TO TECH-SPEC**
**{item_id}: {title}**
This {type} has `recommended_workflow: tech-spec`. Invoking tech-spec workflow...</output>
<invoke-skill skill="bmad:bmm:workflows:tech-spec">
<args>{item_id}: {title} - {description}</args>
</invoke-skill>
<action>HALT - Tech-spec workflow will create implementation spec</action>
</check>
<check if="recommended_workflow == 'direct-fix'">
<output>**DIRECT IMPLEMENTATION**
This {type} is routed for direct implementation. Proceeding...</output>
<action>Continue to step 4</action>
</check>
<check if="recommended_workflow is not set OR recommended_workflow is ambiguous">
<action>Evaluate the workflow routing matrix based on severity and complexity:</action>
<action>**Routing Matrix:**</action>
<action>- critical + any -> correct-course</action>
<action>- high/medium + medium/complex -> correct-course</action>
<action>- high + trivial -> direct-fix</action>
<action>- high/medium + small -> tech-spec</action>
<action>- medium + trivial -> direct-fix</action>
<action>- low + trivial -> direct-fix</action>
<action>- low + small+ -> backlog</action>
<action>Apply matrix to determine routing and continue accordingly</action>
</check>
</step>
<step n="4" goal="Present context and confirm approach">
<output>**{item_id}: {title}**
**Type:** {type} | **Severity/Priority:** {severity_or_priority} | **Complexity:** {complexity} | **Effort:** ~{effort_estimate}h
**Description:**
{description}
**Planned Approach (from triage notes):**
{notes}
**Related:** {related_story} / {related_epic}
</output>
<ask>Ready to {action_verb} this {type}? (yes/no/clarify)</ask>
<check if="user says clarify">
<ask>What additional context do you need?</ask>
<action>Gather clarification, update mental model</action>
</check>
<check if="user says no">
<output>Cancelled. {item_id} remains in current state.</output>
<action>HALT</action>
</check>
</step>
<step n="5" goal="Implement the fix/feature">
<action>Based on the notes/planned approach, identify files to modify or create</action>
<action>Read each affected file to understand current implementation</action>
<action>Implement following the planned approach:</action>
<action>- Make minimal, targeted changes</action>
<action>- Follow existing code patterns and style</action>
<action>- Add comments only where logic is non-obvious</action>
<action>- Do not over-engineer or add unrelated improvements</action>
<action>- Do not add extra features or "nice to haves"</action>
<action>For each file modified/created, track:</action>
<action>- File path</action>
<action>- What was changed/added</action>
<action>- How it addresses the bug/feature</action>
<check if="requires new files">
<action>Create new files following project conventions</action>
<action>Add appropriate imports/exports</action>
</check>
<check if="planned approach is unclear or insufficient">
<ask>The triage notes don't provide a clear approach.
Based on my analysis, I suggest: {proposed_approach}
Should I proceed with this approach?</ask>
</check>
</step>
<step n="6" goal="Verify implementation compiles">
<action>Run TypeScript compilation check: npm run check</action>
<check if="compilation errors in modified files">
<action>Fix compilation errors</action>
<action>Re-run compilation check</action>
</check>
<output>Compilation check passed.</output>
</step>
<step n="6.5" goal="Pre-update sync check">
<action>Search for {item_id} in both bugs.yaml and bugs.md using grep to check current status</action>
<check if="status differs between files OR item missing from one file">
<output>SYNC WARNING: {item_id} status mismatch detected
- bugs.yaml: {yaml_status}
- bugs.md: {md_status}
Proceeding will update both files to "{new_status}".</output>
</check>
</step>
<step n="7" goal="Update bugs.yaml">
<action>Update entry in bugs.yaml:</action>
<check if="type == bug">
<action>- status: "fixed"</action>
<action>- fixed_date: {date} (YYYY-MM-DD format)</action>
</check>
<check if="type == feature">
<action>- status: "implemented"</action>
<action>- implemented_date: {date} (YYYY-MM-DD format)</action>
</check>
<action>- assigned_to: "dev-agent"</action>
<action>- files_modified: {list of files changed/created during implementation}</action>
<action>- Append to notes: "{past_verb} ({date}): {summary of changes made}"</action>
<action>Write updated bugs.yaml</action>
</step>
<step n="8" goal="Update bugs.md">
<action>Search for {item_id} in {bugs_md} using grep with surrounding context to locate the entry</action>
<action>**8a. Remove from tracked section (if present)**</action>
<check if="type == bug">
<action>Search for "{item_id}:" in "# Tracked Bugs" section</action>
</check>
<check if="type == feature">
<action>Search for "{item_id}:" in "# Tracked Feature Requests" section</action>
</check>
<action>If found, remove the entire entry (including any indented sub-items)</action>
<action>**8b. Add to completed section (INSERT AT TOP - newest first)**</action>
<check if="type == bug">
<action>Locate "# Fixed Bugs" section in bugs.md</action>
<action>If section not found, create it</action>
<action>INSERT AT TOP of section (immediately after "# Fixed Bugs" header):</action>
<action>[IMPLEMENTED] {item_id}: {title} - {brief_description}. [Severity: {severity}, Platform: {platform}, Fixed: {date}, Verified: pending]</action>
<action> - Fix: {description of what was fixed}</action>
<action> - File(s): {list of modified files}</action>
</check>
<check if="type == feature">
<action>Locate "# Implemented Features" section in bugs.md</action>
<action>If section not found, create it before "# Fixed Bugs"</action>
<action>INSERT AT TOP of section (immediately after "# Implemented Features" header):</action>
<action>[IMPLEMENTED] {item_id}: {title} - {brief_description}. [Implemented: {date}, Platform: {platform}, Verified: pending]</action>
<action> - Files: {list of modified/created files}</action>
<action> - Features: {bullet list of what was implemented}</action>
</check>
<action>Write updated bugs.md</action>
</step>
<step n="9" goal="Post-update validation">
<action>Search for {item_id} in both bugs.yaml and bugs.md using grep to validate updates</action>
<action>Confirm {item_id} shows status "fixed"/"implemented" in bugs.yaml</action>
<action>Confirm {item_id} has [IMPLEMENTED] tag in bugs.md</action>
<check if="validation fails">
<output>SYNC ERROR: Files may be out of sync. Please verify manually:
- bugs.yaml: Expected status "fixed"/"implemented"
- bugs.md: Expected [IMPLEMENTED] tag in appropriate section</output>
</check>
</step>
<step n="10" goal="Present completion summary">
<output>**{item_id} {past_verb.upper()}**
**Changes Made:**
{for each modified file:}
- {file_path}: {what was changed}
{end for}
**Updated Tracking:**
- bugs.yaml: status -> "{status}", {date_field} -> {date}, files_modified updated
- bugs.md: Moved to "{target_section}" with [IMPLEMENTED] tag
**Verification Status:** pending
**Next Steps:**
1. Test manually
2. Run `/verify {item_id}` after verification to close
</output>
</step>
</workflow>
```
## Usage
```
/implement bug-026
/implement feature-021
```
## Key Principles
1. **Auto-detect Type** - ID format determines bug vs feature handling
2. **Context First** - Always read and present details before implementing
3. **Confirm Approach** - Validate planned approach with user before coding
4. **Minimal Changes** - Only implement what's needed, no scope creep
5. **Dual Tracking** - ALWAYS update both bugs.yaml AND bugs.md
6. **[IMPLEMENTED] Tag** - Indicates complete but awaiting verification
---
## Reference: Bug Tracking Definitions
### Severity Levels
| Level | Description | Action |
|-------|-------------|--------|
| **critical** | Blocks core functionality, prevents app use, or causes data loss (crashes, auth broken, data corruption) | Fix immediately, may require hotfix |
| **high** | Major feature broken, significant UX degradation, workaround exists but painful (platform-specific failure, 5+ sec delays, accessibility blocker) | Fix in current/next sprint |
| **medium** | Feature partially broken, UX degraded but usable (minor feature broken, unclear errors, 1-3 sec delays) | Fix when capacity allows |
| **low** | Minor issue, cosmetic, edge case (typos, spacing, visual glitches) | Fix opportunistically or defer |
### Complexity Levels
| Level | Description | Effort |
|-------|-------------|--------|
| **trivial** | Obvious fix, single line change, no investigation needed (typo, missing semicolon, wrong color) | < 30 minutes |
| **small** | Single file/component, clear root cause, solution known (missing validation, incorrect prop, logic error) | 30 min - 2 hours |
| **medium** | Multiple files affected OR investigation required (spans 2-3 components, debugging needed, integration issue) | 2-8 hours |
| **complex** | Architectural issue, affects multiple stories, requires design changes (race conditions, refactoring, profiling) | 8+ hours (1-2 days) |
### Workflow Routing Matrix
| Severity | Complexity | Workflow | Rationale |
|----------|------------|----------|-----------|
| critical | any | correct-course -> urgent | Need impact analysis even if small fix |
| high | trivial | direct-fix (urgent) | Fast path for obvious important fix |
| high | small | tech-spec (urgent) | Fast path with minimal overhead |
| high | medium+ | correct-course -> story | Need proper analysis + testing |
| medium | trivial | direct-fix | Too small for workflow overhead |
| medium | small | tech-spec | Isolated fix needs spec |
| medium | medium+ | correct-course -> story | Multi-file change needs story |
| low | trivial | direct-fix (defer) | Fix opportunistically |
| low | small+ | backlog (defer) | Document but don't schedule yet |
### Status Flow
```
reported -> triaged -> routed -> in-progress -> fixed -> verified -> closed
```
| Status | Description |
|--------|-------------|
| **reported** | Bug logged in bugs.md, not yet analyzed |
| **triaged** | PM analyzed, assigned severity/complexity/workflow |
| **routed** | Workflow determined, story/tech-spec created |
| **in-progress** | Developer actively working on fix |
| **fixed** | Code changed, tests passing, ready for verification |
| **verified** | Bug confirmed fixed by reporter or QA |
| **closed** | Bug resolved and verified, no further action |
### Metadata Fields
| Field | Description |
|-------|-------------|
| id | Unique identifier (bug-NNN or feature-NNN) |
| title | Short description (< 80 chars) |
| description | Detailed explanation |
| severity | critical \| high \| medium \| low |
| complexity | trivial \| small \| medium \| complex |
| status | Current workflow state |
| recommended_workflow | direct-fix \| tech-spec \| correct-course \| backlog |
| effort_estimate | Hours (based on complexity) |
| reported_by / reported_date | Who found it and when |
| triaged_by / triaged_date | Who triaged and when |
| fixed_date / verified_date | Implementation and verification dates |
| related_story / related_epic | Context links |
| affected_platform | all \| ios \| android |
| doc_impact | Documentation impact: prd, architecture, ux flags + notes |
| notes | Investigation notes, decisions, implementation details |

View File

@ -0,0 +1,22 @@
name: implement
description: "Implement a bug fix or feature - loads context from bugs.yaml, implements the code, updates both bugs.yaml and bugs.md with [IMPLEMENTED] tag"
author: "BMad"
# Critical variables from config
config_source: "{project-root}/.bmad/bmm/config.yaml"
output_folder: "{config_source}:output_folder"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
date: system-generated
# Workflow components
installed_path: "{project-root}/.bmad/bmm/workflows/implement"
instructions: "{installed_path}/instructions.md"
template: false
# Input and output files
variables:
bugs_md: "{output_folder}/bugs.md"
bugs_yaml: "{output_folder}/bugs.yaml"
standalone: true

View File

@ -0,0 +1,219 @@
# Verify Workflow (Close Implemented Bugs/Features)
```xml
<critical>This workflow verifies implemented items and closes them in both bugs.yaml and bugs.md</critical>
<critical>Communicate in {communication_language} with {user_name}</critical>
<critical>Removes [IMPLEMENTED] tag and updates status to CLOSED (bugs) or COMPLETE (features)</critical>
<workflow>
<step n="1" goal="Get item ID or list pending items">
<check if="item_id provided in user input">
<action>Extract item ID from user input</action>
<action>Detect type from ID format:</action>
<action>- "bug-NNN" -> type = "bug", final_status = "CLOSED"</action>
<action>- "feature-NNN" -> type = "feature", final_status = "COMPLETE"</action>
<action>Proceed to Step 2</action>
</check>
<check if="no item_id provided OR user says 'list'">
<action>Search {bugs_yaml} for 'status: "fixed"' or 'status: "implemented"' using grep (do NOT read entire file)</action>
<action>Search {bugs_md} for '[IMPLEMENTED]' entries using grep</action>
<action>Find all items with:</action>
<action>- status == "fixed" or "implemented" in bugs.yaml</action>
<action>- [IMPLEMENTED] tag in bugs.md</action>
<output>**Pending Verification:**
{for each pending item:}
- **{item_id}**: {title} [{type}, {fixed_date or implemented_date}]
{end for}
**Total:** {count} item(s) awaiting verification
To verify an item: `/verify bug-026`
To verify all: Type "verify all"
</output>
<ask>Which item would you like to verify?</ask>
</check>
<check if="user says 'verify all' or 'all'">
<action>Set batch_mode = true</action>
<action>Collect all pending items</action>
<action>Proceed to Step 2 with batch processing</action>
</check>
</step>
<step n="2" goal="Load item context and check sync">
<action>Search for {item_id} in {bugs_yaml} using grep with 50+ lines of context after the match (do NOT read entire file - it exceeds token limits)</action>
<check if="type == bug">
<action>Entry will be in bugs section, verify status == "fixed"</action>
</check>
<check if="type == feature">
<action>Entry will be in feature_requests section, verify status == "implemented"</action>
</check>
<check if="item not found OR status not fixed/implemented">
<output>{item_id} is not in an implemented state. Current status: {status}
Only items with status "fixed" (bugs) or "implemented" (features) can be verified.</output>
<action>HALT</action>
</check>
<action>Extract metadata: title, description, fixed_date/implemented_date, notes</action>
<action>**Sync Check:** Also read {bugs_md} to verify sync status</action>
<check if="bugs.yaml says fixed/implemented but bugs.md missing [IMPLEMENTED] tag">
<output>SYNC WARNING: {item_id} status mismatch detected
- bugs.yaml: {yaml_status}
- bugs.md: Missing [IMPLEMENTED] tag (may have been implemented outside workflow)
Proceeding will update both files to CLOSED/COMPLETE.</output>
<ask>Continue with verification? (yes/no)</ask>
<check if="user says no">
<output>Cancelled. Please run /implement {item_id} first to sync files.</output>
<action>HALT</action>
</check>
</check>
</step>
<step n="3" goal="Confirm verification">
<output>**Verify {item_id}: {title}**
**Type:** {type}
**{past_verb}:** {fixed_date or implemented_date}
**Implementation Notes:**
{notes - show the FIXED/IMPLEMENTED section}
**Files Changed:**
{extract file list from notes}
</output>
<ask>Has this been tested and verified working? (yes/no/skip)</ask>
<check if="user says no">
<ask>What issue did you find? (I'll add it to the notes)</ask>
<action>Append verification failure note to bugs.yaml notes field</action>
<output>Noted. {item_id} remains in implemented state for rework.</output>
<action>HALT or continue to next item in batch</action>
</check>
<check if="user says skip">
<output>Skipped. {item_id} remains in implemented state.</output>
<action>Continue to next item in batch or HALT</action>
</check>
</step>
<step n="4" goal="Update bugs.yaml">
<action>Update entry in bugs.yaml:</action>
<action>- status: "closed"</action>
<action>- verified_by: {user_name}</action>
<action>- verified_date: {date} (YYYY-MM-DD format)</action>
<action>- Append to notes: "Verified ({date}) by {user_name}"</action>
<action>Write updated bugs.yaml</action>
</step>
<step n="5" goal="Update bugs.md">
<action>Search for {item_id} in {bugs_md} using grep with surrounding context to locate the entry</action>
<action>**5a. Find the entry**</action>
<check if="type == bug">
<action>Search for "[IMPLEMENTED] {item_id}:" in "# Fixed Bugs" section</action>
<check if="not found">
<action>Search for "{item_id}:" in "# Tracked Bugs" section (implemented outside workflow)</action>
</check>
</check>
<check if="type == feature">
<action>Search for "[IMPLEMENTED] {item_id}:" in "# Implemented Features" section</action>
<check if="not found">
<action>Search for "{item_id}:" in "# Tracked Feature Requests" section (implemented outside workflow)</action>
</check>
</check>
<action>**5b. Move entry if in wrong section**</action>
<check if="entry found in Tracked section (implemented outside workflow)">
<action>DELETE the entry from "# Tracked Bugs" or "# Tracked Feature Requests"</action>
<action>ADD entry to correct section:</action>
<check if="type == bug">
<action>Add to "# Fixed Bugs" section</action>
</check>
<check if="type == feature">
<action>Add to "# Implemented Features" section (at top, before other entries)</action>
</check>
</check>
<action>**5c. Update the entry format**</action>
<action>Remove "[IMPLEMENTED] " prefix if present</action>
<action>Update the status tag in brackets:</action>
<check if="type == bug">
<action>Change from "[Severity: X, Fixed: DATE, Verified: pending]" or "[Severity: X, Complexity: Y, Workflow: Z]"</action>
<action>To "[Severity: X, Platform: Y, Fixed: {date}, Verified: {date}, CLOSED]"</action>
</check>
<check if="type == feature">
<action>Change from "[Implemented: DATE, Verified: pending]" or "[Priority: X, Complexity: Y, Workflow: Z]"</action>
<action>To "[Implemented: {date}, Platform: Y, Verified: {date}, COMPLETE]"</action>
</check>
<action>Add implementation notes if available from bugs.yaml</action>
<action>Write updated bugs.md</action>
</step>
<step n="5.5" goal="Post-update validation">
<action>Search for {item_id} in both bugs.yaml and bugs.md using grep to validate updates</action>
<action>Confirm bugs.yaml: status="closed", verified_by set, verified_date set</action>
<action>Confirm bugs.md: No [IMPLEMENTED] tag, has CLOSED/COMPLETE in status tag</action>
<check if="validation fails">
<output>SYNC ERROR: Verification may be incomplete. Please check both files:
- bugs.yaml: Expected status "closed", verified_by/verified_date set
- bugs.md: Expected CLOSED/COMPLETE tag, no [IMPLEMENTED] prefix</output>
</check>
</step>
<step n="6" goal="Present completion summary">
<check if="batch_mode">
<output>**Verification Complete**
**Verified {verified_count} item(s):**
{for each verified item:}
- {item_id}: {title} -> {final_status}
{end for}
**Skipped:** {skipped_count}
**Failed verification:** {failed_count}
**Updated Files:**
- bugs.yaml: status -> "closed", verified_by/verified_date set
- bugs.md: [IMPLEMENTED] tag removed, status -> {final_status}
</output>
</check>
<check if="not batch_mode">
<output>**{item_id} VERIFIED and {final_status}**
**Updated:**
- bugs.yaml: status -> "closed", verified_by -> {user_name}, verified_date -> {date}
- bugs.md: Removed [IMPLEMENTED] tag, added "Verified: {date}, {final_status}"
This item is now fully closed.
</output>
</check>
</step>
</workflow>
```
## Usage
```
/verify # List all pending verification
/verify bug-026 # Verify specific bug
/verify feature-021 # Verify specific feature
/verify all # Verify all pending items
```
## Status Transitions
| Type | Before | After |
|------|--------|-------|
| Bug | status: "fixed", [IMPLEMENTED] | status: "closed", CLOSED |
| Feature | status: "implemented", [IMPLEMENTED] | status: "closed", COMPLETE |
## Key Principles
1. **Verification Gate** - User must confirm item was tested and works
2. **Failure Handling** - If verification fails, add note and keep in implemented state
3. **Batch Support** - Can verify multiple items at once
4. **Dual Tracking** - ALWAYS update both bugs.yaml AND bugs.md
5. **Proper Closure** - Removes [IMPLEMENTED] tag, adds final CLOSED/COMPLETE status

View File

@ -0,0 +1,22 @@
name: verify
description: "Verify and close implemented bugs/features - removes [IMPLEMENTED] tag, updates status to CLOSED/COMPLETE in both bugs.yaml and bugs.md"
author: "BMad"
# Critical variables from config
config_source: "{project-root}/.bmad/bmm/config.yaml"
output_folder: "{config_source}:output_folder"
user_name: "{config_source}:user_name"
communication_language: "{config_source}:communication_language"
date: system-generated
# Workflow components
installed_path: "{project-root}/.bmad/bmm/workflows/verify"
instructions: "{installed_path}/instructions.md"
template: false
# Input and output files
variables:
bugs_md: "{output_folder}/bugs.md"
bugs_yaml: "{output_folder}/bugs.yaml"
standalone: true