fix: read deferred-work.md in create-story, sprint-status, and retrospective#2202
fix: read deferred-work.md in create-story, sprint-status, and retrospective#2202don-petry wants to merge 2 commits intobmad-code-org:mainfrom
Conversation
Closes bmad-code-org#2199. Code reviews write deferred items to deferred-work.md but no downstream workflow ever reads them back, causing tech debt to accumulate silently. This change integrates deferred-work.md into the three key workflows that should consume it: - bmad-create-story: loads deferred-work.md in step 2, matches items by file path against the new story's scope, and folds overlapping items into the story as Dev Notes and Tasks subtasks - bmad-sprint-status: parses the deferred backlog, adds severity counts to the status display, and raises risks for large or high-priority backlogs - bmad-retrospective: analyzes deferred items created vs resolved during the epic, surfaces carried-forward stats in the metrics summary, and includes the deferred work summary in the saved retro document Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThree workflow files now read and process deferred work items from a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/bmm-skills/4-implementation/bmad-create-story/workflow.md`:
- Around line 378-380: The deferred-subtask template is using an undefined
template variable {{item_title}} which yields blank task text; update the
Tasks/Subtasks section so the line uses {{description}} instead of
{{item_title}} (or modify the deferred parsing step to extract and populate
item_title from the parsed item) for HIGH-priority deferred items (the template
line: "- [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review)").
Ensure the change is applied wherever deferred subtasks are generated so the
task text is populated.
- Around line 239-243: The deferred-item parser (the "Parse all deferred items"
action that feeds {{matched_deferred_items}}) currently expects a guaranteed
Category field which the producer does not provide; update the parser to stop
requiring a structured Category and instead always extract file paths,
description text, and originating review, then derive category/severity
heuristically (e.g., keyword-to-category mapping like "security", "bug",
"performance", "style", default to "uncategorized") and set a boolean flag
(e.g., inferred_category=true) when the category is inferred; ensure the output
schema used by {{matched_deferred_items}} includes the derived category,
severity, and the inferred flag so downstream priority mapping and matching
remain deterministic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 50abbe98-f0fa-4aa5-a432-1ab9e108d448
📒 Files selected for processing (3)
src/bmm-skills/4-implementation/bmad-create-story/workflow.mdsrc/bmm-skills/4-implementation/bmad-retrospective/workflow.mdsrc/bmm-skills/4-implementation/bmad-sprint-status/workflow.md
| <action>Parse all deferred items, extracting for each: | ||
| - File paths mentioned (e.g., [src/foo.ts:42]) | ||
| - Category (bug, security, tech-debt, style, etc.) | ||
| - Originating review (e.g., "Deferred from: code review of story-2.3") | ||
| - Description text |
There was a problem hiding this comment.
Deferred parser expects fields the producer does not guarantee.
Line 241 requires extracting a Category, but deferred entries are produced as free-text findings with file refs, not structured category fields. This can silently collapse priority mapping and matching quality for {{matched_deferred_items}}. Align parsing to the actual producer format and derive category/severity heuristically when absent.
Suggested adjustment
- <action>Parse all deferred items, extracting for each:
- - File paths mentioned (e.g., [src/foo.ts:42])
- - Category (bug, security, tech-debt, style, etc.)
- - Originating review (e.g., "Deferred from: code review of story-2.3")
- - Description text
- </action>
+ <action>Parse all deferred items, extracting for each:
+ - File paths mentioned (e.g., [src/foo.ts:42])
+ - Originating review heading
+ - Description text
+ - Optional category/severity only if explicitly present
+ </action>
+ <action>If category/severity is absent, infer priority conservatively from keywords
+ (security, vuln, auth, bug, regression, tech debt, style) and default to MEDIUM.
+ </action>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/bmm-skills/4-implementation/bmad-create-story/workflow.md` around lines
239 - 243, The deferred-item parser (the "Parse all deferred items" action that
feeds {{matched_deferred_items}}) currently expects a guaranteed Category field
which the producer does not provide; update the parser to stop requiring a
structured Category and instead always extract file paths, description text, and
originating review, then derive category/severity heuristically (e.g.,
keyword-to-category mapping like "security", "bug", "performance", "style",
default to "uncategorized") and set a boolean flag (e.g.,
inferred_category=true) when the category is inferred; ensure the output schema
used by {{matched_deferred_items}} includes the derived category, severity, and
the inferred flag so downstream priority mapping and matching remain
deterministic.
| <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items: | ||
| - [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review) | ||
| </action> |
There was a problem hiding this comment.
Undefined {{item_title}} will produce empty deferred subtasks.
Line 379 uses {{item_title}}, but this field is never extracted in the deferred parsing step. Use {{description}} (or explicitly extract item_title) to avoid blank task text.
Suggested fix
- <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items:
- - [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review)
- </action>
+ <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items:
+ - [ ] [Deferred] {{description}} [{{file_ref}}] (from {{origin_review}})
+ </action>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/bmm-skills/4-implementation/bmad-create-story/workflow.md` around lines
378 - 380, The deferred-subtask template is using an undefined template variable
{{item_title}} which yields blank task text; update the Tasks/Subtasks section
so the line uses {{description}} instead of {{item_title}} (or modify the
deferred parsing step to extract and populate item_title from the parsed item)
for HIGH-priority deferred items (the template line: "- [ ] [Deferred]
{{item_title}} [{{file_ref}}] (from previous review)"). Ensure the change is
applied wherever deferred subtasks are generated so the task text is populated.
There was a problem hiding this comment.
Pull request overview
This PR closes #2199 by wiring the deferred-work.md backlog (written by bmad-code-review) into downstream implementation workflows so deferred findings are surfaced and actionable instead of accumulating silently.
Changes:
bmad-create-story: attempts to load/parsedeferred-work.md, match relevant items to story scope, and inject them into the generated story as Dev Notes + tasks.bmad-sprint-status: optionally readsdeferred-work.mdto show severity-grouped counts and raise risk flags for large/high-priority backlogs.bmad-retrospective: optionally analyzes deferred work created/resolved/carried-forward and includes those metrics in the retro output.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
src/bmm-skills/4-implementation/bmad-create-story/workflow.md |
Adds deferred-work ingestion + story injection, but has a few variable/matching issues that will prevent reliable output. |
src/bmm-skills/4-implementation/bmad-sprint-status/workflow.md |
Adds optional deferred-work loading + summary counts and risk signals. |
src/bmm-skills/4-implementation/bmad-retrospective/workflow.md |
Adds optional deferred-work analysis and retro metrics/summary section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - `story_title` = "" (will be elicited if not derivable) | ||
| - `project_context` = `**/project-context.md` (load if exists) | ||
| - `deferred_work_file` = `{implementation_artifacts}/deferred-work.md` | ||
| - `default_output_file` = `{implementation_artifacts}/{{story_key}}.md` | ||
|
|
There was a problem hiding this comment.
deferred_work_file is introduced, but the create-story discover-inputs.md protocol only loads files declared in the workflow’s Input Files table. Without adding {deferred_work_file} as an (optional) input there, deferred-work may not be loaded into context consistently, and the later "Load {deferred_work_file}" step relies on ad-hoc behavior. Add an Input Files row for deferred work (optional) or explicitly document/ensure it’s loaded outside the discovery protocol.
| <check if="overlapping deferred items found"> | ||
| <action>Store {{matched_deferred_items}} for inclusion in the story file</action> | ||
| <action>Classify matches by priority: | ||
| - HIGH: security fixes, bugs in files this story will modify | ||
| - MEDIUM: tech-debt in the same module, performance issues in touched code | ||
| - LOW: style issues, minor refactors in adjacent files | ||
| </action> | ||
| <output>📋 Found {{matched_count}} deferred work items relevant to this story from previous code reviews</output> | ||
| </check> |
There was a problem hiding this comment.
{{matched_count}} is referenced in the output, but it’s never set anywhere in the workflow. This will render as blank/undefined. Compute and store a matched count when building matched_deferred_items (or derive it from the collection length).
| - Originating review (e.g., "Deferred from: code review of story-2.3") | ||
| - Description text | ||
| </action> |
There was a problem hiding this comment.
The example/pattern for the deferred-work heading/origin (e.g., "Deferred from: code review of story-2.3") doesn’t match the format currently written by bmad-code-review (it appends headings like ## Deferred from: code review (DATE) and, when a story file is known, includes that story file’s basename in the heading). Align the parsing/matching instructions here with the actual deferred-work.md format so items can be attributed to the right story/epic reliably.
| - Originating review (e.g., "Deferred from: code review of story-2.3") | |
| - Description text | |
| </action> | |
| - Originating deferred-work heading / review origin exactly as written in the section heading (e.g., `## Deferred from: code review (DATE)`) | |
| - Any reviewed story reference included in that heading, especially the story file basename when present | |
| - Description text | |
| </action> | |
| <action>When matching deferred items to this story, use the actual deferred-work.md heading patterns written by `bmad-code-review`: | |
| - Headings are written as `## Deferred from: code review (DATE)` | |
| - When a story file is known, the heading may also include that story file's basename | |
| - Do not rely on older examples such as "Deferred from: code review of story-2.3" | |
| - Prefer exact heading text and extracted story basename/story reference for attribution when available | |
| </action> |
| - **[{{priority}}]** {{description}} `[{{file_ref}}]` — _from {{origin_review}}_ | ||
| {{/each}} | ||
| </template-output> | ||
|
|
||
| <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items: | ||
| - [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review) |
There was a problem hiding this comment.
The deferred item render assumes file_ref should be wrapped like [{{file_ref}}], but deferred-work entries are likely already written with brackets (e.g., [src/foo.ts:42]). This can lead to double-bracketing in the story output. Normalize file_ref to a consistent representation (either store without brackets and add them here, or store with brackets and render without adding another pair).
| - **[{{priority}}]** {{description}} `[{{file_ref}}]` — _from {{origin_review}}_ | |
| {{/each}} | |
| </template-output> | |
| <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items: | |
| - [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review) | |
| - **[{{priority}}]** {{description}} `{{file_ref}}` — _from {{origin_review}}_ | |
| {{/each}} | |
| </template-output> | |
| <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items: | |
| - [ ] [Deferred] {{item_title}} {{file_ref}} (from previous review) |
| </template-output> | ||
|
|
||
| <action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items: | ||
| - [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review) |
There was a problem hiding this comment.
Task subtask generation references {{item_title}}, but that field is never defined in the earlier parsing/matching steps (only description is). This will produce empty/undefined task titles unless you either derive item_title from description or change the template to use description.
| - [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review) | |
| - [ ] [Deferred] {{description}} [{{file_ref}}] (from previous review) |
| <template-output>risks = {{risks}}</template-output> | ||
| <template-output>deferred_total = {{deferred_total}}</template-output> | ||
| <template-output>deferred_high = {{deferred_high}}</template-output> | ||
| <template-output>deferred_medium = {{deferred_medium}}</template-output> | ||
| <template-output>deferred_low = {{deferred_low}}</template-output> |
There was a problem hiding this comment.
Deferred-work variables are only set when {deferred_work_file} exists and has content, but in data mode the workflow always emits deferred_* template outputs. When the file is missing/empty this will output undefined values and may confuse downstream callers. Consider setting defaults (0) when deferred-work.md is absent/empty, or guard these template-output lines behind a check.
| - Items originating from this epic's stories (match by "Deferred from: code review of story-{{epic_number}}.*") | ||
| - Items originating from previous epics (carried forward) |
There was a problem hiding this comment.
The deferred-work attribution pattern here (match by "Deferred from: code review of story-{{epic_number}}.*") doesn’t match the format written by bmad-code-review (it appends headings like ## Deferred from: code review (DATE) and may include the story file basename, which is typically {{epic}}-{{story}}-..., not story-{{epic}}.*). Update the parsing/matching instructions to reflect the actual deferred-work.md heading format so epic scoping works reliably.
| - Items originating from this epic's stories (match by "Deferred from: code review of story-{{epic_number}}.*") | |
| - Items originating from previous epics (carried forward) | |
| - Items originating from this epic's stories (match deferred sections headed like "## Deferred from: code review (DATE)"; within each section, use any referenced story/source file basename and treat basenames starting with "{{epic_number}}-" — typically "{{epic_number}}-{{story_number}}-..." — as belonging to this epic) | |
| - Items originating from previous epics (carried forward; deferred sections without a current-epic story basename match should be counted here) |
- Align parsing to actual bmad-code-review output format (## headings with date)
- Make Category optional with heuristic keyword-based derivation
- Replace undefined {{item_title}} with {{description}} in subtask template
- Add {{matched_count}} computation before it is referenced
- Guard against missing/empty deferred-work.md (initialize counts to 0)
- Add deferred_work_file to create-story Input Files table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
All review feedback from CodeRabbit and Copilot has been addressed in the latest push (
Reviews were posted against the initial commit ( |
Summary
Closes #2199.
Code reviews write deferred findings to
deferred-work.mdviabmad-code-review/step-04-present.md, but no downstream workflow ever reads that file back. This creates a write-only data sink where tech debt accumulates silently.This PR integrates
deferred-work.mdinto the three workflows that should consume it:bmad-create-story— Loads deferred-work.md during step 2 (artifact analysis), matches items by file path against the new story's scope, and folds overlapping items into the story file as a "Deferred Items to Address" Dev Notes subsection plus Tasks subtasks for high-priority itemsbmad-sprint-status— Parses the deferred backlog, displays severity-grouped counts in the status summary, and raises risks when the backlog is large or contains high-priority (security/bug) itemsbmad-retrospective— Analyzes deferred items created vs. resolved during the epic, surfaces carried-forward stats in the metrics display, and includes a deferred work summary in the saved retrospective documentTest plan
bmad-create-storyon a project with an existingdeferred-work.mdcontaining items that reference files the target story will touch — verify the story file includes a "Deferred Items to Address" section and corresponding task subtasksbmad-create-storyon a project with nodeferred-work.md— verify workflow proceeds normally with no errorsbmad-sprint-statuswith an existing deferred backlog — verify the "Deferred Work" line appears in the status summary and high-priority items trigger risk warningsbmad-sprint-statuswithout a deferred-work.md — verify no deferred section appears and no errors occurbmad-retrospectiveafter completing an epic with deferred items — verify the metrics display includes "Deferred Work (from code reviews)" stats and the saved retro document includes a deferred work summary sectionnpm test)🤖 Generated with Claude Code