# Open Epic Feedback - Collect Stakeholder Input on Story Breakdown
The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml
You MUST have already loaded and processed: {installed_path}/workflow.yaml
Call: mcp__github__get_me()
current_user = response.login
HALT
Call: mcp__github__search_issues({
query: "repo:{{github_owner}}/{{github_repo}} label:type:epic-review label:review-status:draft is:open"
})
HALT
draft_epics = response.items.map(issue => {
const labels = issue.labels.map(l => l.name)
return {
key: labels.find(l => l.startsWith('epic:'))?.replace('epic:', ''),
title: issue.title.replace(/^Epic Review:\s*/, ''),
source_prd: labels.find(l => l.startsWith('source-prd:'))?.replace('source-prd:', ''),
issue_number: issue.number
}
}).filter(e => e.key)
Select epic (1-{{draft_epics.length}}):
epic_key = draft_epics[parseInt(response) - 1].key
review_issue_number = draft_epics[parseInt(response) - 1].issue_number
epic_path = `${docs_dir}/epics/epic-${epic_key}.md`
Read epic_path
HALT
epic_content = file_content
title = extract_title(epic_content)
version = extract_version(epic_content)
stakeholders = extract_stakeholders(epic_content)
source_prd = extract_source_prd(epic_content)
stories = extract_epic_stories(epic_content)
Call: mcp__github__search_issues({
query: "repo:{{github_owner}}/{{github_repo}} label:type:epic-review label:epic:{{epic_key}} is:open"
})
HALT
review_issue = response.items[0]
review_issue_number = review_issue.number
Call: mcp__github__issue_read({
method: 'get',
owner: github_owner,
repo: github_repo,
issue_number: review_issue_number
})
review_issue = response
Days until feedback deadline (default: {{feedback_days}}):
feedback_days = parseInt(response) || feedback_days
deadline = new Date()
deadline.setDate(deadline.getDate() + feedback_days)
deadline_str = deadline.toISOString().split('T')[0]
Add additional stakeholders? (comma-separated or 'none'):
if (response.toLowerCase() !== 'none' && response.trim()) {
additional = response.split(',').map(s => s.trim().replace('@', ''))
stakeholders = [...new Set([...stakeholders, ...additional])]
}
updated_content = epic_content
.replace(/\*\*Status:\*\* .+/, '**Status:** Feedback')
.replace(/\| Feedback Deadline \| .+ \|/, `| Feedback Deadline | ${deadline_str} |`)
Write updated_content to epic_path
// Get current labels
current_labels = review_issue.labels.map(l => l.name)
// Update status label
new_labels = current_labels
.filter(l => !l.startsWith('review-status:'))
.concat(['review-status:open'])
Call: mcp__github__issue_write({
method: 'update',
owner: "{{github_owner}}",
repo: "{{github_repo}}",
issue_number: review_issue_number,
labels: new_labels,
assignees: stakeholders
})
feedback_comment = `## 💬 Feedback Round Open
${stakeholders.map(s => '@' + s).join(' ')}
**Epic:** epic:${epic_key}
**Version:** v${version}
**Deadline:** ${deadline_str}
**Source PRD:** prd:${source_prd}
---
## 📦 Story Breakdown
${stories.map((s, i) => `${i + 1}. **${s.title}** (${s.complexity || 'TBD'})\n ${s.description || ''}`).join('\n\n')}
---
## Feedback Types for Epics
Please provide feedback on:
- 🔍 **Scope**: Is this epic the right size? Should it be split or merged with another?
- 📝 **Story Breakdown**: Are stories well-defined, independent, and testable?
- 🔗 **Dependencies**: Are technical dependencies correctly identified?
- ⚡ **Priority**: Is the story order optimal for delivery?
- ⚠️ **Technical Risk**: Are there architectural or technical concerns?
- ➕ **Missing Stories**: Should additional stories be added?
---
### How to Submit Feedback
Reply with structured feedback or use the feedback workflow:
\`\`\`
/feedback epic:${epic_key}
Section: [Story Breakdown / Dependencies / Technical Risk / etc.]
Type: [scope / dependency / priority / technical_risk / story_split / missing_story]
Feedback: [Your detailed feedback]
\`\`\`
Or simply comment with your thoughts.
---
_Feedback requested by @${current_user} on ${new Date().toISOString().split('T')[0]}_
_Please respond by ${deadline_str}_`
Call: mcp__github__add_issue_comment({
owner: "{{github_owner}}",
repo: "{{github_repo}}",
issue_number: review_issue_number,
body: feedback_comment
})
## Helper Functions
```javascript
function extract_title(content) {
const match = content.match(/^#\s+(PRD|Epic):\s*(.+)$/m);
return match ? match[2].trim() : 'Untitled';
}
function extract_version(content) {
const match = content.match(/\*\*Version:\*\*\s*(\d+)/);
return match ? match[1] : '1';
}
function extract_source_prd(content) {
const match = content.match(/\*\*Source PRD:\*\*\s*`?prd:([^`\s]+)`?/);
return match ? match[1] : null;
}
function extract_stakeholders(content) {
const field = content.match(/\|\s*Stakeholders\s*\|\s*(.+?)\s*\|/);
if (!field) return [];
return field[1]
.split(/[,\s]+/)
.filter(s => s.startsWith('@'))
.map(s => s.replace('@', ''));
}
function extract_epic_stories(content) {
const stories = [];
// Match story sections in various formats
const storyRegex = /###\s+Story\s+\d+:\s*(.+)\n+([\s\S]*?)(?=###|---|\n##|$)/gi;
let match;
while ((match = storyRegex.exec(content)) !== null) {
const title = match[1].trim();
const body = match[2];
// Extract complexity
const complexityMatch = body.match(/\*\*Estimated Complexity:\*\*\s*(\w+)/i);
// Extract description
const descMatch = body.match(/\*\*Description:\*\*\s*(.+)/);
stories.push({
title: title,
description: descMatch ? descMatch[1].trim() : '',
complexity: complexityMatch ? complexityMatch[1] : null
});
}
return stories;
}
```
## Epic-Specific Feedback Types
```yaml
feedback_types:
scope_concern:
label: "Scope"
description: "Epic is too large/small, should be split/merged"
emoji: "🔍"
story_split:
label: "Story Breakdown"
description: "Story needs to be split, combined, or redefined"
emoji: "📝"
dependency:
label: "Dependency"
description: "Missing or incorrect dependency identification"
emoji: "🔗"
priority_question:
label: "Priority"
description: "Story order or priority should change"
emoji: "⚡"
technical_risk:
label: "Technical Risk"
description: "Architecture or technical feasibility concern"
emoji: "⚠️"
missing_story:
label: "Missing Story"
description: "An additional story should be added"
emoji: "➕"
```
## Natural Language Triggers
This workflow responds to:
- "Open feedback for epic"
- "Start epic feedback round"
- "Get feedback on epic"
- Menu trigger: `OE`