Skip to content

fix: read deferred-work.md in create-story, sprint-status, and retrospective#2202

Open
don-petry wants to merge 2 commits intobmad-code-org:mainfrom
don-petry:fix/deferred-work-read-back-2199
Open

fix: read deferred-work.md in create-story, sprint-status, and retrospective#2202
don-petry wants to merge 2 commits intobmad-code-org:mainfrom
don-petry:fix/deferred-work-read-back-2199

Conversation

@don-petry
Copy link
Copy Markdown

Summary

Closes #2199.

Code reviews write deferred findings to deferred-work.md via bmad-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.md into 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 items
  • bmad-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) items
  • bmad-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 document

Test plan

  • Run bmad-create-story on a project with an existing deferred-work.md containing items that reference files the target story will touch — verify the story file includes a "Deferred Items to Address" section and corresponding task subtasks
  • Run bmad-create-story on a project with no deferred-work.md — verify workflow proceeds normally with no errors
  • Run bmad-sprint-status with an existing deferred backlog — verify the "Deferred Work" line appears in the status summary and high-priority items trigger risk warnings
  • Run bmad-sprint-status without a deferred-work.md — verify no deferred section appears and no errors occur
  • Run bmad-retrospective after 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 section
  • Verify all existing tests pass (npm test)

🤖 Generated with Claude Code

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>
Copilot AI review requested due to automatic review settings April 4, 2026 04:13
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2026

📝 Walkthrough

Walkthrough

Three workflow files now read and process deferred work items from a deferred-work.md file. The bmad-create-story workflow matches deferred items to story files and adds them as subtasks. The bmad-retrospective workflow computes deferred work statistics and includes them in retro output. The bmad-sprint-status workflow parses deferred items and exports counts for risk detection.

Changes

Cohort / File(s) Summary
Deferred Work Processing in Create-Story
src/bmm-skills/4-implementation/bmad-create-story/workflow.md
Added deferred_work_file input path. Introduced deferred work analysis phase that loads the file, parses deferred items, matches them against story's file list using exact/directory/component overlap rules, and classifies matches by priority (HIGH/MEDIUM/LOW). Conditionally injects "Deferred Items to Address" subsection and creates HIGH-priority subtasks in story output.
Deferred Work Backlog Analysis in Retrospective
src/bmm-skills/4-implementation/bmad-retrospective/workflow.md
Added optional deferred-work-file input path. Introduced "Deferred Work Backlog Analysis" phase during deep story analysis that loads and parses deferred items, computes aggregate stats (created/resolved/carried-forward counts), classifies by severity, and flags outstanding items. Extended retrospective output to include deferred work section with counts and warnings.
Deferred Work Statistics in Sprint Status
src/bmm-skills/4-implementation/bmad-sprint-status/workflow.md
Added deferred_work_file input path. Extended workflow to conditionally parse deferred items and compute severity-grouped counts. Appends risk entries when thresholds exceeded. Updated sprint summary display and data-mode output to export deferred_total, deferred_high, deferred_medium, and deferred_low counts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #2055 — Adds automated writing of deferred findings to deferred-work.md file in code review workflow, which is read back by the workflows modified in this PR.

Suggested reviewers

  • pbean
  • bmadcode
  • cecil-the-coder
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: reading deferred-work.md in three workflows (create-story, sprint-status, retrospective), which is the core purpose of this PR.
Description check ✅ Passed The description is directly related to the changeset, explaining why deferred-work.md needs to be read, which workflows consume it, and what each workflow does with the data.
Linked Issues check ✅ Passed The PR addresses all primary coding requirements from #2199: bmad-create-story reads/matches deferred items and folds them into story files; bmad-sprint-status parses and displays deferred backlog with risk warnings; bmad-retrospective includes deferred work metrics.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the three workflows specified in #2199 (create-story, sprint-status, retrospective). No unrelated modifications to other skills or systems were introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between d51e215 and 0416f72.

📒 Files selected for processing (3)
  • src/bmm-skills/4-implementation/bmad-create-story/workflow.md
  • src/bmm-skills/4-implementation/bmad-retrospective/workflow.md
  • src/bmm-skills/4-implementation/bmad-sprint-status/workflow.md

Comment on lines +239 to +243
<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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Comment on lines +378 to +380
<action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items:
- [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review)
</action>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/parse deferred-work.md, match relevant items to story scope, and inject them into the generated story as Dev Notes + tasks.
  • bmad-sprint-status: optionally reads deferred-work.md to 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.

Comment on lines 35 to 39
- `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`

Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +258 to +266
<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>
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{{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).

Copilot uses AI. Check for mistakes.
Comment on lines +242 to +244
- Originating review (e.g., "Deferred from: code review of story-2.3")
- Description text
</action>
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
- 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>

Copilot uses AI. Check for mistakes.
Comment on lines +374 to +379
- **[{{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)
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
- **[{{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)

Copilot uses AI. Check for mistakes.
</template-output>

<action>In the Tasks/Subtasks section, add corresponding subtasks for HIGH-priority deferred items:
- [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review)
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
- [ ] [Deferred] {{item_title}} [{{file_ref}}] (from previous review)
- [ ] [Deferred] {{description}} [{{file_ref}}] (from previous review)

Copilot uses AI. Check for mistakes.
Comment on lines 228 to +232
<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>
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +259 to +260
- Items originating from this epic's stories (match by "Deferred from: code review of story-{{epic_number}}.*")
- Items originating from previous epics (carried forward)
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
- 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)

Copilot uses AI. Check for mistakes.
- 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>
@don-petry
Copy link
Copy Markdown
Author

All review feedback from CodeRabbit and Copilot has been addressed in the latest push (beeccbc):

  • {{item_title}} undefined — replaced with {{description}} throughout
  • {{matched_count}} never set — now computed and stored when building matched_deferred_items
  • deferred_work_file not in Input Files table — added as an optional FULL_LOAD input
  • Deferred parser expects structured Category field — parser now extracts category heuristically from description keywords with inferred_category flag
  • Sprint-status undefined deferred vars when file missing — defaults to 0 when file does not exist or is empty
  • Double-bracket wrapping of file_ref — adjusted to avoid double-bracketing
  • Deferred attribution pattern mismatch — aligned to match bmad-code-review heading format (## Deferred from:)

Reviews were posted against the initial commit (0416f72); fixes were pushed ~3 hours later in beeccbc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Deferred work items from code reviews are write-only , never read back by create-story or any other workflow

2 participants