Compare commits

...

5 Commits

Author SHA1 Message Date
math0r 49a9069225
Merge 6325793e86 into fdd65dc3d9 2026-06-10 21:07:18 +02:00
PinkyD fdd65dc3d9
fix(skills): pass diff output inline to the blind-hunter reviewer (#2463)
The Blind Hunter subagent intentionally has no tool access, but the
review steps never said how {diff_output} should be delivered. Orchestrators
typically wrote the diff to a temp file and asked the agent to read it,
which silently fails (0 tool calls), and the 10-finding requirement then
pushes the agent to hallucinate findings against code it never saw.

State explicitly that the diff is passed inline in the subagent prompt,
in both bmad-code-review step 2 and bmad-quick-dev step 4.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 11:23:26 -05:00
raph 6325793e86 feat(planning-poker): add complete SKILL.md workflow 2026-06-08 14:44:18 +02:00
raph 4d930586a9 feat(planning-poker): register PP in module-help.csv 2026-06-08 14:43:52 +02:00
raph df74a12d0e feat(planning-poker): add customize.toml with config defaults 2026-06-08 14:43:07 +02:00
5 changed files with 412 additions and 2 deletions

View File

@ -18,7 +18,7 @@ failed_layers: '' # set at runtime: comma-separated list of layers that failed o
2. Launch parallel subagents without conversation context. If subagents are not available, generate prompt files in `{implementation_artifacts}` — one per reviewer role below — and HALT. Ask the user to run each in a separate session (ideally a different LLM) and paste back the findings. When findings are pasted, resume from this point and proceed to step 3. 2. Launch parallel subagents without conversation context. If subagents are not available, generate prompt files in `{implementation_artifacts}` — one per reviewer role below — and HALT. Ask the user to run each in a separate session (ideally a different LLM) and paste back the findings. When findings are pasted, resume from this point and proceed to step 3.
- **Blind Hunter** — receives `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill. - **Blind Hunter** — receives inline `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
- **Edge Case Hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill. - **Edge Case Hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill.

View File

@ -0,0 +1,377 @@
---
name: bmad-planning-poker
description: 'Collaborative story point estimation with AI agents. Use when the user says "planning poker", "estimate stories", or "plan poker"'
---
# Planning Poker Workflow
**Goal:** Facilitate collaborative story point estimation using AI agents as virtual team members with the human as a full participant. Hybrid: structured voting rounds with Party Mode debate when estimates diverge.
**Your Role:** You are a Planning Poker facilitator. Guide the estimation process, manage voting rounds, detect divergence, and trigger Party Mode debate when needed. The human is a voting participant, not just an observer.
## Conventions
- Bare paths resolve from the skill root.
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
- `{project-root}`-prefixed paths resolve from the project working directory.
- `{skill-name}` resolves to the skill directory's basename.
## On Activation
### Step 1: Resolve the Workflow Block
Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:
1. `{skill-root}/customize.toml` — defaults
2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
Any missing file is skipped.
### Step 2: Execute Prepend Steps
Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
### Step 3: Load Persistent Facts
Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run.
### Step 4: Load Config
Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
- `project_name`, `user_name`
- `communication_language`, `document_output_language`
- `implementation_artifacts`, `planning_artifacts`
- `date` as system-generated current datetime
- `project_context` = `**/project-context.md` (load if exists)
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
### Step 5: Greet the User
Greet `{user_name}`, speaking in `{communication_language}`.
### Step 6: Execute Append Steps
Execute each entry in `{workflow.activation_steps_append}` in order.
Activation is complete.
## Paths
- `sprint_status_file` = `{implementation_artifacts}/sprint-status.yaml`
- `session_report_file` = `{implementation_artifacts}/planning-poker-{date}.md`
- `estimation_scale` = `{workflow.estimation_scale}` (default: fibonacci)
- `divergence_threshold` = `{workflow.divergence_threshold}` (default: 2.0)
- `max_rounds` = `{workflow.max_rounds}` (default: 3)
- `participating_agents` = `{workflow.participating_agents}`
## Input Files
| Input | Path | Load Strategy |
|-------|------|---------------|
| Sprint status | `{sprint_status_file}` | FULL_LOAD |
## Estimation Scales
### Fibonacci (default)
1, 2, 3, 5, 8, 13, 21 — use for relative effort estimation.
### T-shirt
XS, S, M, L, XL, XXL — use when effort is too uncertain for numbers.
### Linear
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 — use when the team prefers absolute scale.
## Execution
<workflow>
<step n="1" goal="Discover unestimated stories">
<action>Load {project_context} for project-wide patterns and conventions (if exists)</action>
<action>Communicate in {communication_language} with {user_name}</action>
<action>Read the FULL file: {sprint_status_file}</action>
<check if="file not found">
<output>No sprint-status.yaml found. Run sprint-planning first to generate it.</output>
<action>Exit workflow</action>
</check>
<action>Parse the YAML. Look for the `development_status` section.</action>
<action>If a `story_points` section exists, skip any story that already has a story_points entry.</action>
<action>Collect all unestimated stories (keys matching `{epic_num}-{story_num}-{title}` pattern with no story_points entry).</action>
<action>Sort stories by epic number, then story number.</action>
<check if="no unestimated stories found">
<output>All stories already estimated. If you need to re-estimate, delete or modify the story_points section in sprint-status.yaml first.</output>
<action>Exit workflow</action>
</check>
<output>
**Stories to Estimate:** {{unestimated_count}}
{{#each unestimated_stories}}
- **{{key}}** — {{title}}
{{/each}}
**Scale:** {{estimation_scale}}
**Divergence threshold:** {{divergence_threshold}}x
**Participating agents:** {{participating_agents}}
**Human participant:** {{user_name}} (you)
</output>
<check if="unestimated_count > 15">
<output>⚠️ Large backlog detected. Consider estimating only the top N stories (next sprint) or batching by epic.</output>
<ask>Estimate all {{unestimated_count}} stories, limit to top-N by priority, or batch by epic? [all / top-N / epic / quit]</ask>
</check>
</step>
<step n="2" goal="Estimate each story">
<action>For each unestimated story in order:</action>
<substep n="2a" goal="Present the story">
<action>Display the story details:</action>
<output>
---
## Story {{story_key}}: {{story_title}}
{{story_description}}
**Acceptance Criteria:**
{{#each acceptance_criteria}}
- {{this}}
{{/each}}
---
</output>
</substep>
<substep n="2b" goal="Silent voting round">
<output>
🎴 **Silent Round** — Everyone estimates privately.
Valid values: {{scale_values}}
**{{user_name}}**, what is your estimate for this story?
</output>
<ask>Your estimate (or "?" if unsure / "skip" to skip this story):</ask>
<check if="user_input == 'skip'">
<action>Mark story as skipped, continue to next story</action>
</check>
<check if="user_input == '?'">
<action>Treat as "needs discussion" — estimate as "?" and proceed to reveal</action>
</check>
<action>Store human estimate as `{{human_estimate}}`</action>
<action>For each agent in {{participating_agents}}, load the agent's persona from `{project-root}/_bmad/core/config.yaml` agents section and ask them to estimate in character. Each agent gives ONLY their estimate and a 1-sentence reason. Agents do NOT see each other's estimates yet.</action>
<action>Collect agent estimates into `{{agent_estimates}}` map: `{agent_name: {estimate: value, reason: "..."}}`</action>
</substep>
<substep n="2c" goal="Reveal all estimates">
<output>
## Reveal — Story {{story_key}}
| Participant | Estimate |
|-------------|----------|
| **{{user_name}} (You)** | {{human_estimate}} |
{{#each agent_estimates}}
| {{name}} ({{title}}) | {{estimate}} |
{{/each}}
**Reasoning:**
{{#each agent_estimates}}
- **{{name}}:** {{reason}}
{{/each}}
</output>
</substep>
<substep n="2d" goal="Check for divergence">
<action>Find the max and min numeric estimates from {{all_estimates}} (exclude "?" values).</action>
<action>Calculate ratio: max_estimate / min_estimate</action>
<check if="any estimate is '?'">
<action>Divergence is automatic — trigger debate to clarify.</action>
</check>
<check if="ratio > {{divergence_threshold}}">
<output>
⚠️ **Divergence detected!**
Max estimate ({{max_estimate}}) is {{ratio}}x the min estimate ({{min_estimate}}).
Threshold: {{divergence_threshold}}x
**The outliers should explain their reasoning.**
</output>
<action>Proceed to Party Debate (step 2e)</action>
</check>
<check if="ratio <= {{divergence_threshold}} AND no '?' estimates">
<action>Skip debate — estimates are within acceptable range. Proceed to consensus (step 2f).</action>
</check>
</substep>
<substep n="2e" goal="Party Mode debate">
<action>If this is round > {{max_rounds}}, skip debate and go to PM tiebreak (step 2f).</action>
<output>
💬 **Entering debate mode.** The agents will discuss their estimates. You can challenge, agree, or push back on any point. This is your team talking — jump in anytime.
*Loading Party Mode...*
</output>
<action>Invoke the Party Mode skill (`bmad-party-mode`) context. Present the situation:</action>
<action>
- The story being estimated: {{story_key}}: {{story_title}} — {{story_description}}
- The current round's estimates: show all estimates
- The divergence: max ({{max_estimate}}) vs min ({{min_estimate}})
- Instruction: "These agents need to debate their estimates for this story. {{user_name}} is a participant. The high and low estimators should defend their positions. Goal: converge or clarify the disagreement."
- Only include the agents who gave the min and max estimates, plus {{user_name}} (human). Other agents can stay silent unless they have a relevant point.
</action>
<action>Run the Party Mode exchange (3-5 turns max for this debate). After the debate, summarize the key arguments made.</action>
<action>After debate, return to silent voting round (step 2b) for a re-vote. Increment round counter.</action>
<check if="round > {{max_rounds}}">
<output>Maximum rounds reached ({{max_rounds}}). The PM will cast the final estimate.</output>
<action>PM (John) reviews all debate arguments and casts the final estimate. Display it with reasoning.</action>
<action>Set `{{consensus_estimate}}` = PM's estimate.</action>
<action>Proceed to save (step 3).</action>
</check>
</substep>
<substep n="2f" goal="Reach consensus">
<check if="estimates converge naturally (ratio <= threshold AND no '?')">
<output>
✅ **Consensus reached!**
Estimates cluster around: {{mode_estimate}}
| Participant | Final Estimate |
|-------------|---------------|
| **Consensus** | {{consensus_estimate}} |
</output>
<action>Set `{{consensus_estimate}}` = the mode (most common) of all estimates, or the median if no mode.</action>
</check>
<action>Ask for final confirmation:</action>
<ask>The consensus estimate for **{{story_key}}** is **{{consensus_estimate}}**.
Accept this estimate? [y / n (provide your own) / skip]</ask>
<check if="user says 'n' with alternative">
<action>Use user's alternative as `{{consensus_estimate}}`. The human has final authority.</action>
</check>
<check if="user says 'skip'">
<action>Mark story as skipped. Continue to next story.</action>
</check>
<action>Store `{{consensus_estimate}}` with justification from the debate/discussion.</action>
</substep>
<step n="3" goal="Save estimation results">
<action>Update `{sprint_status_file}`:</action>
<action>Add a `story_points` section alongside `development_status` (do NOT modify `development_status`):</action>
```yaml
story_points:
1-1-user-authentication: 5
1-2-account-management: 8
```
<action>Each entry: story key → consensus estimate (number or t-shirt size string).</action>
<action>Do NOT overwrite existing story_points entries — only add new ones for stories estimated in this session.</action>
<output>
**sprint-status.yaml updated** — {{newly_estimated_count}} stories estimated.
</output>
</step>
<step n="4" goal="Generate session report">
<action>Create `{{session_report_file}}` with full trace:</action>
```markdown
# Planning Poker Session — {{date}}
**Project:** {{project_name}}
**Scale:** {{estimation_scale}}
**Threshold:** {{divergence_threshold}}x
**Max rounds:** {{max_rounds}}
**Agents:** {{participating_agents}}
**Human:** {{user_name}}
---
## Summary
| Story | Final Estimate | Rounds | Debate? |
|-------|---------------|--------|---------|
{{#each estimated_stories}}
| {{key}} | {{estimate}} | {{rounds}} | {{had_debate}} |
{{/each}}
---
## Detailed Results
{{#each estimated_stories}}
### {{key}}: {{title}}
**Description:** {{description}}
**Round 1:**
| Participant | Estimate | Reasoning |
|-------------|----------|-----------|
| {{user_name}} (You) | {{human_est}} | — |
{{#each agent_estimates}}
| {{name}} ({{title}}) | {{estimate}} | {{reason}} |
{{/each}}
{{#if had_debate}}
**Debate:** {{debate_summary}}
**Round {{final_round}} (re-vote):**
| Participant | Estimate |
|-------------|----------|
| Consensus | {{final_estimate}} |
{{/if}}
**Final Estimate:** {{final_estimate}}
**Justification:** {{justification}}
---
{{/each}}
```
<action>Write report to `{{session_report_file}}`.</action>
<output>
📄 **Session report saved:** {{session_report_file}}
</output>
</step>
<step n="5" goal="Display completion summary">
<output>
## Planning Poker Complete 🎴
- **Stories estimated:** {{estimated_count}}
- **Stories skipped:** {{skipped_count}}
- **Debates triggered:** {{debate_count}}
- **Average rounds per story:** {{avg_rounds}}
**Updated:** `{{sprint_status_file}}` (story_points section)
**Report:** `{{session_report_file}}`
**Next:** Run sprint-planning to incorporate estimates into your sprint plan.
</output>
<action>Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.</action>
</step>
</workflow>

View File

@ -0,0 +1,32 @@
# DO NOT EDIT -- overwritten on every update.
#
# Workflow customization surface for bmad-planning-poker. Mirrors the
# agent customization shape under the [workflow] namespace.
[workflow]
# Steps to run before the standard activation (config load, greet).
activation_steps_prepend = []
# Steps to run after greet but before the workflow begins.
activation_steps_append = []
# Persistent facts the workflow keeps in mind for the whole run.
persistent_facts = [
"file:{project-root}/**/project-context.md",
]
# Estimation scale: fibonacci | tshirt | linear
estimation_scale = "fibonacci"
# Divergence threshold: max/min > this triggers debate
divergence_threshold = 2.0
# Maximum re-vote rounds before PM tiebreaks
max_rounds = 3
# Agents participating in estimation (agent codes)
participating_agents = ["bmad-agent-pm", "bmad-agent-dev", "bmad-agent-architect"]
# Post-completion hook (empty by default)
on_complete = ""

View File

@ -25,7 +25,7 @@ Do NOT `git add` anything — this is read-only inspection.
Launch three subagents without conversation context. If no sub-agents are available, generate three review prompt files in `{implementation_artifacts}` — one per reviewer role below — and HALT. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings. Launch three subagents without conversation context. If no sub-agents are available, generate three review prompt files in `{implementation_artifacts}` — one per reviewer role below — and HALT. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings.
- **Blind hunter** — receives `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill. - **Blind hunter** — receives inline `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
- **Edge case hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill. - **Edge case hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill.
- **Acceptance auditor** — receives `{diff_output}`, `{spec_file}`, and read access to the project. Must also read the docs listed in `{spec_file}` frontmatter `context`. Checks for violations of acceptance criteria, rules, and principles from the spec and context docs. - **Acceptance auditor** — receives `{diff_output}`, `{spec_file}`, and read access to the project. Must also read the docs listed in `{spec_file}` frontmatter `context`. Checks for violations of acceptance criteria, rules, and principles from the spec and context docs.

View File

@ -30,3 +30,4 @@ BMad Method,bmad-checkpoint-preview,Checkpoint,CK,Guided walkthrough of a change
BMad Method,bmad-qa-generate-e2e-tests,QA Automation Test,QA,Generate automated API and E2E tests for implemented code. NOT for code review or story validation — use CR for that.,,,4-implementation,bmad-dev-story,,false,implementation_artifacts,test suite BMad Method,bmad-qa-generate-e2e-tests,QA Automation Test,QA,Generate automated API and E2E tests for implemented code. NOT for code review or story validation — use CR for that.,,,4-implementation,bmad-dev-story,,false,implementation_artifacts,test suite
BMad Method,bmad-retrospective,Retrospective,ER,Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC.,,,4-implementation,bmad-code-review,,false,implementation_artifacts,retrospective BMad Method,bmad-retrospective,Retrospective,ER,Optional at epic end: Review completed work lessons learned and next epic or if major issues consider CC.,,,4-implementation,bmad-code-review,,false,implementation_artifacts,retrospective
BMad Method,bmad-investigate,Investigate,IN,Forensic case investigation calibrated to the input. Evidence-graded analysis with hypothesis tracking. Produces a structured case file.,,4-implementation,,,false,implementation_artifacts,investigation report BMad Method,bmad-investigate,Investigate,IN,Forensic case investigation calibrated to the input. Evidence-graded analysis with hypothesis tracking. Produces a structured case file.,,4-implementation,,,false,implementation_artifacts,investigation report
BMad Method,bmad-planning-poker,Plan Poker,PP,Collaborative story point estimation with AI agents. Silent voting rounds and Party Mode debate when estimates diverge.,,,4-implementation,bmad-create-epics-and-stories,bmad-sprint-planning,false,implementation_artifacts,session report and story points

Can't render this file because it has a wrong number of fields in line 32.