bmad-method 6.8.1-next.2 → 6.8.1-next.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/.claude-plugin/marketplace.json +9 -3
  2. package/package.json +10 -4
  3. package/src/bmm-skills/1-analysis/bmad-prfaq/SKILL.md +2 -2
  4. package/src/bmm-skills/1-analysis/bmad-product-brief/SKILL.md +8 -8
  5. package/src/bmm-skills/2-plan-workflows/bmad-prd/SKILL.md +7 -7
  6. package/src/bmm-skills/2-plan-workflows/bmad-prd/assets/headless-schemas.md +2 -2
  7. package/src/bmm-skills/2-plan-workflows/bmad-prd/customize.toml +1 -1
  8. package/src/bmm-skills/2-plan-workflows/bmad-prd/references/headless.md +1 -1
  9. package/src/bmm-skills/2-plan-workflows/bmad-prd/references/validate.md +1 -1
  10. package/src/bmm-skills/2-plan-workflows/bmad-ux/SKILL.md +8 -8
  11. package/src/bmm-skills/2-plan-workflows/bmad-ux/assets/design-directions.md +1 -1
  12. package/src/bmm-skills/2-plan-workflows/bmad-ux/assets/headless-schemas.md +2 -2
  13. package/src/bmm-skills/2-plan-workflows/bmad-ux/assets/key-screens.md +4 -4
  14. package/src/bmm-skills/2-plan-workflows/bmad-ux/customize.toml +1 -1
  15. package/src/bmm-skills/2-plan-workflows/bmad-ux/references/creative-tools.md +1 -1
  16. package/src/bmm-skills/2-plan-workflows/bmad-ux/references/headless.md +1 -1
  17. package/src/bmm-skills/2-plan-workflows/bmad-ux/references/validate.md +2 -2
  18. package/src/bmm-skills/3-solutioning/bmad-agent-architect/customize.toml +2 -2
  19. package/src/bmm-skills/3-solutioning/bmad-architecture/SKILL.md +85 -0
  20. package/src/bmm-skills/3-solutioning/bmad-architecture/assets/spine-template.md +79 -0
  21. package/src/bmm-skills/3-solutioning/bmad-architecture/customize.toml +100 -0
  22. package/src/bmm-skills/3-solutioning/bmad-architecture/references/headless.md +26 -0
  23. package/src/bmm-skills/3-solutioning/bmad-architecture/references/reviewer-gate.md +13 -0
  24. package/src/bmm-skills/3-solutioning/bmad-architecture/scripts/lint_spine.py +257 -0
  25. package/src/bmm-skills/3-solutioning/bmad-architecture/scripts/tests/test_lint_spine.py +270 -0
  26. package/src/bmm-skills/3-solutioning/bmad-create-architecture/SKILL.md +16 -60
  27. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md +12 -4
  28. package/src/bmm-skills/4-implementation/bmad-code-review/steps/step-02-review.md +1 -1
  29. package/src/bmm-skills/4-implementation/bmad-quick-dev/step-04-review.md +1 -1
  30. package/src/bmm-skills/4-implementation/bmad-retrospective/SKILL.md +29 -14
  31. package/src/bmm-skills/4-implementation/bmad-retrospective/customize.toml +1 -1
  32. package/src/bmm-skills/4-implementation/bmad-sprint-planning/SKILL.md +20 -1
  33. package/src/bmm-skills/4-implementation/bmad-sprint-planning/checklist.md +2 -1
  34. package/src/bmm-skills/4-implementation/bmad-sprint-planning/sprint-status-template.yaml +13 -0
  35. package/src/bmm-skills/4-implementation/bmad-sprint-status/SKILL.md +13 -0
  36. package/src/bmm-skills/module-help.csv +2 -2
  37. package/src/core-skills/bmad-brainstorming/SKILL.md +8 -10
  38. package/src/core-skills/bmad-brainstorming/references/converge.md +1 -1
  39. package/src/core-skills/bmad-brainstorming/references/finalize.md +1 -1
  40. package/src/core-skills/bmad-brainstorming/references/headless.md +4 -4
  41. package/src/core-skills/bmad-brainstorming/references/in-chat-techniques.md +1 -1
  42. package/src/core-skills/bmad-brainstorming/references/mode-autonomous.md +1 -1
  43. package/src/core-skills/bmad-brainstorming/scripts/tests/test_brain.py +2 -2
  44. package/src/core-skills/bmad-customize/scripts/tests/test_list_customizable_skills.py +1 -1
  45. package/src/core-skills/bmad-forge-idea/SKILL.md +79 -0
  46. package/src/core-skills/bmad-forge-idea/customize.toml +42 -0
  47. package/src/core-skills/bmad-forge-idea/scripts/resolve_personas.py +270 -0
  48. package/src/core-skills/bmad-forge-idea/scripts/tests/test_resolve_personas.py +138 -0
  49. package/src/core-skills/bmad-party-mode/SKILL.md +39 -56
  50. package/src/core-skills/bmad-party-mode/customize.toml +175 -0
  51. package/src/core-skills/bmad-party-mode/references/create-party.md +70 -0
  52. package/src/core-skills/bmad-party-mode/references/mode-agent-team.md +11 -0
  53. package/src/core-skills/bmad-party-mode/references/mode-auto.md +13 -0
  54. package/src/core-skills/bmad-party-mode/references/mode-subagent.md +19 -0
  55. package/src/core-skills/bmad-party-mode/references/party-memory.md +51 -0
  56. package/src/core-skills/bmad-party-mode/scripts/resolve_party.py +272 -0
  57. package/src/core-skills/bmad-party-mode/scripts/tests/test-resolve_party.py +146 -0
  58. package/src/core-skills/bmad-spec/SKILL.md +25 -9
  59. package/src/core-skills/bmad-spec/assets/headless-schemas.md +3 -3
  60. package/src/core-skills/bmad-spec/assets/spec-template.md +4 -4
  61. package/src/core-skills/module-help.csv +1 -0
  62. package/src/{core-skills/bmad-brainstorming/scripts → scripts}/memlog.py +56 -34
  63. package/src/scripts/resolve_config.py +8 -6
  64. package/src/scripts/resolve_customization.py +8 -6
  65. package/src/{core-skills/bmad-brainstorming/scripts → scripts}/tests/test_memlog.py +68 -27
  66. package/tools/installer/commands/install.js +3 -0
  67. package/tools/installer/core/installer.js +35 -1
  68. package/tools/installer/core/uv-check.js +97 -0
  69. package/tools/installer/core/wsl-node-check.js +109 -0
  70. package/tools/installer/ide/platform-codes.yaml +14 -0
  71. package/tools/installer/install-messages.yaml +4 -0
  72. package/tools/installer/ui.js +11 -0
  73. package/evals/bmm-skills/bmad-product-brief/evals.json +0 -237
  74. package/evals/bmm-skills/bmad-product-brief/files/branfield-memo.md +0 -46
  75. package/evals/bmm-skills/bmad-product-brief/files/forkbird-brief/addendum.md +0 -40
  76. package/evals/bmm-skills/bmad-product-brief/files/forkbird-brief/brief.md +0 -56
  77. package/evals/bmm-skills/bmad-product-brief/files/forkbird-brief/decision-log.md +0 -27
  78. package/evals/bmm-skills/bmad-product-brief/files/meridian-mobility-report.md +0 -116
  79. package/evals/bmm-skills/bmad-product-brief/files/mossridge-brief/addendum.md +0 -41
  80. package/evals/bmm-skills/bmad-product-brief/files/mossridge-brief/brief.md +0 -57
  81. package/evals/bmm-skills/bmad-product-brief/files/mossridge-brief/decision-log.md +0 -29
  82. package/evals/bmm-skills/bmad-product-brief/files/pantry-bridge-interviews.md +0 -90
  83. package/evals/bmm-skills/bmad-product-brief/files/q2-brainstorm.md +0 -101
  84. package/evals/bmm-skills/bmad-product-brief/triggers.json +0 -18
  85. package/src/bmm-skills/3-solutioning/bmad-create-architecture/architecture-decision-template.md +0 -12
  86. package/src/bmm-skills/3-solutioning/bmad-create-architecture/data/domain-complexity.csv +0 -13
  87. package/src/bmm-skills/3-solutioning/bmad-create-architecture/data/project-types.csv +0 -7
  88. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-01-init.md +0 -153
  89. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-01b-continue.md +0 -173
  90. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-02-context.md +0 -224
  91. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-03-starter.md +0 -329
  92. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-04-decisions.md +0 -318
  93. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-05-patterns.md +0 -359
  94. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-06-structure.md +0 -379
  95. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-07-validation.md +0 -361
  96. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-08-complete.md +0 -82
@@ -0,0 +1,270 @@
1
+ # /// script
2
+ # requires-python = ">=3.10"
3
+ # dependencies = ["pytest>=8.0"]
4
+ # ///
5
+ """Tests for lint_spine.py. Run: uv run --with pytest pytest scripts/tests/test_lint_spine.py
6
+
7
+ The spine under test: a clean spine lints empty; the linter catches exactly the
8
+ mechanical defects a prompt is unreliable at — literal placeholders, AD-n id breakage,
9
+ AD-n blocks missing required fields, and unpinned Stack versions.
10
+ """
11
+ import importlib.util
12
+ import json
13
+ import re
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ import pytest
18
+
19
+ _SPEC = importlib.util.spec_from_file_location(
20
+ "lint_spine", Path(__file__).resolve().parent.parent / "lint_spine.py"
21
+ )
22
+ lint_spine = importlib.util.module_from_spec(_SPEC)
23
+ sys.modules["lint_spine"] = lint_spine
24
+ _SPEC.loader.exec_module(lint_spine)
25
+
26
+
27
+ CLEAN = """---
28
+ name: 'Demo'
29
+ ---
30
+
31
+ ## Invariants & Rules
32
+
33
+ ### AD-1 — single write path
34
+
35
+ - **Binds:** all
36
+ - **Prevents:** divergent mutation
37
+ - **Rule:** state changes only through the command bus
38
+
39
+ ### AD-2 — layered deps `[ADOPTED]`
40
+
41
+ - **Binds:** all
42
+ - **Prevents:** import cycles
43
+ - **Rule:** ui -> app -> domain, never backward
44
+
45
+ ```mermaid
46
+ flowchart LR
47
+ A --> B{decision}
48
+ ```
49
+
50
+ ## Stack
51
+
52
+ | Name | Version |
53
+ | --- | --- |
54
+ | fastapi | 0.115 |
55
+ | pydantic | 2.9 |
56
+ """
57
+
58
+
59
+ def cats(result):
60
+ return sorted(f["category"] for f in result["findings"])
61
+
62
+
63
+ def test_clean_spine_passes():
64
+ result = lint_spine.lint(CLEAN)
65
+ assert result["ok"] is True
66
+ assert result["total_findings"] == 0
67
+
68
+
69
+ def test_mermaid_braces_not_flagged():
70
+ # the {decision} node lives in a fenced block and must not read as a template token
71
+ result = lint_spine.lint(CLEAN)
72
+ assert "placeholder" not in cats(result)
73
+
74
+
75
+ def test_placeholder_markers_caught():
76
+ text = CLEAN.replace("the command bus", "TBD")
77
+ result = lint_spine.lint(text)
78
+ assert "placeholder" in cats(result)
79
+
80
+
81
+ def test_similar_to_caught():
82
+ text = CLEAN.replace("import cycles", "similar to AD-1")
83
+ result = lint_spine.lint(text)
84
+ assert any("cross-reference" in f["detail"] for f in result["findings"])
85
+
86
+
87
+ def test_unfilled_template_token_caught():
88
+ text = CLEAN.replace("single write path", "{decision}")
89
+ result = lint_spine.lint(text)
90
+ assert any(f["category"] == "placeholder" for f in result["findings"])
91
+
92
+
93
+ def test_duplicate_ad_id_caught():
94
+ text = CLEAN.replace("### AD-2 — layered deps `[ADOPTED]`", "### AD-1 — layered deps")
95
+ result = lint_spine.lint(text)
96
+ assert "ad_id" in cats(result)
97
+
98
+
99
+ def test_non_monotonic_ad_id_caught():
100
+ text = CLEAN.replace("### AD-2 — layered deps `[ADOPTED]`", "### AD-5 — layered deps").replace(
101
+ "### AD-1 — single write path", "### AD-9 — single write path"
102
+ )
103
+ result = lint_spine.lint(text)
104
+ assert any("non-monotonic" in f["detail"] for f in result["findings"])
105
+
106
+
107
+ def test_missing_field_caught():
108
+ text = CLEAN.replace("- **Rule:** state changes only through the command bus\n", "")
109
+ result = lint_spine.lint(text)
110
+ assert any(f["category"] == "ad_fields" and "rule" in f["detail"] for f in result["findings"])
111
+
112
+
113
+ def test_unpinned_dep_caught():
114
+ text = CLEAN.replace("| fastapi | 0.115 |", "| fastapi | |")
115
+ result = lint_spine.lint(text)
116
+ assert "version_pin" in cats(result)
117
+
118
+
119
+ def test_placeholder_version_caught():
120
+ text = CLEAN.replace("| fastapi | 0.115 |", "| fastapi | {pin} |")
121
+ result = lint_spine.lint(text)
122
+ assert any(f["category"] == "version_pin" and "fastapi" in f["detail"] for f in result["findings"])
123
+
124
+
125
+ def test_no_stack_section_ok():
126
+ text = CLEAN.split("## Stack")[0]
127
+ result = lint_spine.lint(text)
128
+ assert "version_pin" not in cats(result)
129
+
130
+
131
+ def test_stack_skeleton_row_not_version_pinned():
132
+ # a leftover {token} name is the placeholder pass's job, not a double-reported version_pin
133
+ text = CLEAN.replace("| fastapi | 0.115 |", "| {language / framework} | {pinned version} |")
134
+ result = lint_spine.lint(text)
135
+ assert "version_pin" not in cats(result)
136
+
137
+
138
+ def test_stack_html_comment_not_parsed_as_row():
139
+ text = CLEAN.replace("## Stack\n", "## Stack\n\n<!-- SEED — verified current 2026-06 -->\n")
140
+ result = lint_spine.lint(text)
141
+ assert "version_pin" not in cats(result)
142
+
143
+
144
+ def test_template_token_is_low_severity():
145
+ # a bare {token} can be legitimate brace prose; it is flagged, but low (not high) so the
146
+ # mechanical pass stays near-zero false-positive
147
+ text = CLEAN.replace("single write path", "{decision}")
148
+ result = lint_spine.lint(text)
149
+ toks = [f for f in result["findings"] if f["category"] == "placeholder" and "template token" in f["detail"]]
150
+ assert toks and all(f["severity"] == "low" for f in toks)
151
+
152
+
153
+ def test_no_frontmatter_body_still_scanned():
154
+ text = "## Invariants\n\n### AD-1 — x\n\n- **Binds:** all\n- **Prevents:** drift\n- **Rule:** TBD\n"
155
+ result = lint_spine.lint(text)
156
+ assert "placeholder" in cats(result) # TBD caught even with no frontmatter
157
+
158
+
159
+ def test_frontmatter_value_with_dashes_not_truncated():
160
+ # a value containing '---' must not be read as the closing fence (line-exact close)
161
+ text = ("---\nname: 'x'\nscope: 'phase 1 --- phase 2'\n---\n\n"
162
+ "## Stack\n\n| Name | Version |\n| --- | --- |\n| fastapi | |\n")
163
+ result = lint_spine.lint(text)
164
+ assert any(f["category"] == "version_pin" for f in result["findings"]) # read past the inline ---
165
+
166
+
167
+ def test_ad_heading_in_fence_not_counted():
168
+ text = (
169
+ "---\nname: 'x'\n---\n\n"
170
+ "### AD-1 — real\n\n- **Binds:** all\n- **Prevents:** drift\n- **Rule:** do x\n\n"
171
+ "## Docs\n\n```text\n### AD-2 — illustrative only, no fields\n```\n"
172
+ )
173
+ result = lint_spine.lint(text)
174
+ assert result["ok"] is True # the fenced AD-2 is not a live AD → no ad_fields/ad_id finding
175
+
176
+
177
+ def test_stack_table_flags_only_the_unpinned_row():
178
+ text = ("---\nname: 'x'\n---\n\n## Stack\n\n| Name | Version |\n| --- | --- |\n"
179
+ "| fastapi | 0.115 |\n| redis | |\n")
180
+ result = lint_spine.lint(text)
181
+ pins = [f for f in result["findings"] if f["category"] == "version_pin"]
182
+ assert len(pins) == 1 and "redis" in pins[0]["detail"]
183
+
184
+
185
+ def test_stack_table_all_pinned_ok():
186
+ text = ("---\nname: 'x'\n---\n\n## Stack\n\n| Name | Version |\n| --- | --- |\n"
187
+ "| fastapi | 0.115 |\n")
188
+ result = lint_spine.lint(text)
189
+ assert "version_pin" not in cats(result)
190
+
191
+
192
+ def test_fenced_stack_rows_not_parsed():
193
+ # an illustrative fenced table under ## Stack must not be read as live rows (fences are
194
+ # blanked first, like every other pass) — a blank-version row inside a fence is not a finding
195
+ text = ("---\nname: 'x'\n---\n\n## Stack\n\n| Name | Version |\n| --- | --- |\n"
196
+ "| fastapi | 0.115 |\n\n```text\n| example | |\n```\n")
197
+ result = lint_spine.lint(text)
198
+ assert "version_pin" not in cats(result)
199
+
200
+
201
+ def test_fenced_stack_heading_not_live():
202
+ # a `## Stack` heading shown inside a code fence is not the live Stack section
203
+ text = ("---\nname: 'x'\n---\n\n## Docs\n\n```md\n## Stack\n\n| foo | |\n```\n")
204
+ result = lint_spine.lint(text)
205
+ assert "version_pin" not in cats(result)
206
+
207
+
208
+ def test_renamed_stack_heading_still_scanned():
209
+ # the heading match is word-boundary, so a varied `## Stack` heading still counts
210
+ text = ("---\nname: 'x'\n---\n\n## Stack & Versions\n\n| Name | Version |\n| --- | --- |\n"
211
+ "| redis | |\n")
212
+ result = lint_spine.lint(text)
213
+ pins = [f for f in result["findings"] if f["category"] == "version_pin"]
214
+ assert len(pins) == 1 and "redis" in pins[0]["detail"]
215
+
216
+
217
+ def test_reordered_columns_pair_name_to_version():
218
+ # Version-then-Name header: the unpinned row must still be flagged by its real name
219
+ text = ("---\nname: 'x'\n---\n\n## Stack\n\n| Version | Name |\n| --- | --- |\n"
220
+ "| 0.115 | fastapi |\n| | redis |\n")
221
+ result = lint_spine.lint(text)
222
+ pins = [f for f in result["findings"] if f["category"] == "version_pin"]
223
+ assert len(pins) == 1 and "redis" in pins[0]["detail"]
224
+
225
+
226
+ def test_placeholder_line_number_is_absolute():
227
+ # a TBD after a multi-line fence reports its real file line (fence blanked, not collapsed)
228
+ text = (
229
+ "---\nname: 'x'\n---\n\n"
230
+ "## A\n\n"
231
+ "```text\nf1\nf2\nf3\n```\n\n"
232
+ "TBD here\n"
233
+ )
234
+ result = lint_spine.lint(text)
235
+ ph = next(f for f in result["findings"] if "TBD" in f["detail"])
236
+ n = int(re.search(r"line (\d+)", ph["location"]).group(1))
237
+ assert n == 13
238
+
239
+
240
+ def test_missing_spine_file_reports_error(tmp_path, capsys):
241
+ rc = lint_spine.main(["--workspace", str(tmp_path)])
242
+ out = json.loads(capsys.readouterr().out)
243
+ assert rc == 0 and out["ok"] is False and "not found" in out["error"]
244
+
245
+
246
+ def test_frontmatter_unfilled_token_caught():
247
+ # an unfilled {scope}/{paradigm}/{date} in frontmatter is part of the contract and must lint
248
+ text = "---\nname: 'x'\nscope: '{what this spine governs}'\n---\n\n## Invariants\n"
249
+ result = lint_spine.lint(text)
250
+ fm = [f for f in result["findings"] if f["category"] == "placeholder" and "frontmatter" in f["detail"]]
251
+ assert fm and any("template token" in f["detail"] for f in fm)
252
+
253
+
254
+ def test_frontmatter_tbd_caught():
255
+ text = "---\nname: 'x'\nstatus: TBD\n---\n\n## Invariants\n"
256
+ result = lint_spine.lint(text)
257
+ assert any(f["category"] == "placeholder" and "frontmatter" in f["detail"] and "TBD" in f["detail"]
258
+ for f in result["findings"])
259
+
260
+
261
+ def test_unreadable_spine_returns_error_not_crash(tmp_path, capsys):
262
+ # a spine that exists but can't be UTF-8 decoded must yield error JSON + exit 0, not a traceback
263
+ (tmp_path / lint_spine.SPINE).write_bytes(b"\xff\xfe bad bytes not utf-8")
264
+ rc = lint_spine.main(["--workspace", str(tmp_path)])
265
+ out = json.loads(capsys.readouterr().out)
266
+ assert rc == 0 and out["ok"] is False and "could not read" in out["error"]
267
+
268
+
269
+ if __name__ == "__main__":
270
+ sys.exit(pytest.main([__file__, "-q"]))
@@ -1,74 +1,30 @@
1
1
  ---
2
2
  name: bmad-create-architecture
3
- description: 'Create architecture solution design decisions for AI agent consistency. Use when the user says "lets create architecture" or "create technical architecture" or "create a solution design"'
3
+ description: 'DEPRECATED consolidated into bmad-architecture create intent - this skill will be removed in v7 in favor of `bmad-architecture`.'
4
4
  ---
5
5
 
6
- # Architecture Workflow
6
+ # DEPRECATED — forwards to bmad-architecture (create intent)
7
7
 
8
- **Goal:** Create comprehensive architecture decisions through collaborative step-by-step discovery that ensures AI agents implement consistently.
9
-
10
- **Your Role:** You are an architectural facilitator collaborating with a peer. This is a partnership, not a client-vendor relationship. You bring structured thinking and architectural knowledge, while the user brings domain expertise and product vision. Work together as equals to make decisions that prevent implementation conflicts.
11
-
12
- ## Conventions
13
-
14
- - Bare paths (e.g. `steps/step-01-init.md`) resolve from the skill root.
15
- - `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
16
- - `{project-root}`-prefixed paths resolve from the project working directory.
17
- - `{skill-name}` resolves to the skill directory's basename.
18
-
19
- ## WORKFLOW ARCHITECTURE
20
-
21
- This uses **micro-file architecture** for disciplined execution:
22
-
23
- - Each step is a self-contained file with embedded rules
24
- - Sequential progression with user control at each step
25
- - Document state tracked in frontmatter
26
- - Append-only document building through conversation
27
- - You NEVER proceed to a step file if the current step file indicates the user must approve and indicate continuation.
8
+ This skill was consolidated into `bmad-architecture`. It is retained as a thin compatibility shim so existing invocations by name and `_bmad/custom/bmad-create-architecture.toml` override files keep working. New work should invoke `bmad-architecture` directly — it detects create / update / validate intent from the conversation.
28
9
 
29
10
  ## On Activation
30
11
 
31
- ### Step 1: Resolve the Workflow Block
32
-
33
- Run: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`
34
-
35
- **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:
36
-
37
- 1. `{skill-root}/customize.toml` — defaults
38
- 2. `{project-root}/_bmad/custom/{skill-name}.toml` — team overrides
39
- 3. `{project-root}/_bmad/custom/{skill-name}.user.toml` — personal overrides
40
-
41
- Any missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.
42
-
43
- ### Step 2: Execute Prepend Steps
44
-
45
- Execute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.
46
-
47
- ### Step 3: Load Persistent Facts
48
-
49
- Treat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.
50
-
51
- ### Step 4: Load Config
52
-
53
- Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
54
- - Use `{user_name}` for greeting
55
- - Use `{communication_language}` for all communications
56
- - Use `{document_output_language}` for output documents
57
- - Use `{planning_artifacts}` for output location and artifact scanning
58
- - Use `{project_knowledge}` for additional context scanning
59
-
60
- ### Step 5: Greet the User
61
-
62
- Greet `{user_name}`, speaking in `{communication_language}`.
12
+ 1. Resolve customization: `python3 {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --key workflow`. This picks up any `{project-root}/_bmad/custom/bmad-create-architecture.toml` and `bmad-create-architecture.user.toml` overrides for the legacy fields (`activation_steps_prepend`, `activation_steps_append`, `persistent_facts`, `on_complete`).
63
13
 
64
- ### Step 6: Execute Append Steps
14
+ 2. Load `{project-root}/_bmad/bmm/config.yaml` (and `config.user.yaml` if present) to resolve `{user_name}` and `{communication_language}`.
65
15
 
66
- Execute each entry in `{workflow.activation_steps_append}` in order.
16
+ 3. Emit a deprecation notice to the user in `{communication_language}`:
67
17
 
68
- Activation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.
18
+ > Notice: `bmad-create-architecture` is deprecated and will be removed in a future release. It now forwards to `bmad-architecture` with create intent. To silence this notice and access the full new customization surface (`spine_template`, `spine_output_path`, `run_folder_pattern`, `doc_standards`, `external_sources`, `external_handoffs`, `finalize_reviewers`), migrate `_bmad/custom/bmad-create-architecture.toml` to `_bmad/custom/bmad-architecture.toml` and invoke `bmad-architecture` directly next time. Customization fields that were in this version still remain in the new version and will be respected if present in `_bmad/custom/bmad-architecture.toml`, but the new version also supports additional fields that you can take advantage of by migrating.
69
19
 
70
- ## Execution
20
+ 4. Invoke `bmad-architecture` with the following context. Pass these as the activating context so `bmad-architecture` honors them instead of resolving its own customization from scratch:
71
21
 
72
- Read fully and follow: `./steps/step-01-init.md` to begin the workflow.
22
+ - **Intent:** `create` skip `bmad-architecture`'s usual intent detection step.
23
+ - **Pre-resolved legacy customization** — use these in place of resolving from `bmad-architecture`'s own `customize.toml` for the four legacy fields. For everything else (`spine_template`, `spine_output_path`, `run_folder_pattern`, `doc_standards`, `external_sources`, `external_handoffs`, `finalize_reviewers`), use `bmad-architecture`'s own defaults and overrides as normal:
24
+ - `activation_steps_prepend` = the resolved value from step 1
25
+ - `activation_steps_append` = the resolved value from step 1
26
+ - `persistent_facts` = the resolved value from step 1
27
+ - `on_complete` = the resolved value from step 1
28
+ - **Original user input:** forward whatever the user said when invoking this skill verbatim.
73
29
 
74
- **Note:** Input document discovery and all initialization protocols are handled in step-01-init.md.
30
+ `bmad-architecture` takes the workflow from here. Do not execute any further steps in this shim.
@@ -48,7 +48,7 @@ Verify required documents exist and are complete:
48
48
 
49
49
  1. **PRD.md** - Contains requirements (FRs and NFRs) and product scope
50
50
  2. **Architecture.md** - Contains technical decisions, API contracts, data models
51
- 3. **UX Design.md** (if UI exists) - Contains interaction patterns, mockups, user flows
51
+ 3. **UX design contract** (if UI exists) - Contains visual identity, interaction patterns, mockups, and user flows
52
52
 
53
53
  ### 2. Document Discovery and Validation
54
54
 
@@ -66,8 +66,16 @@ Search for required documents using these patterns (sharded means a large docume
66
66
 
67
67
  **UX Design Document Search (Optional):**
68
68
 
69
- 1. `{planning_artifacts}/*ux*.md` (whole document)
70
- 2. `{planning_artifacts}/*ux*/index.md` (sharded version)
69
+ 1. `{planning_artifacts}/ux-designs/ux-*/DESIGN.md` and `{planning_artifacts}/ux-designs/ux-*/EXPERIENCE.md` (bmad-ux spine pair)
70
+ 2. `{planning_artifacts}/*ux*.md` (legacy whole document)
71
+ 3. `{planning_artifacts}/*ux*/index.md` (legacy sharded version)
72
+
73
+ For each matching bmad-ux run folder, treat `DESIGN.md` and `EXPERIENCE.md` as one UX design contract:
74
+
75
+ - Confirm and load both files together. `DESIGN.md` owns visual identity and design tokens; `EXPERIENCE.md` owns information architecture, behavior, states, interactions, accessibility, and journeys.
76
+ - Add both files to the `inputDocuments: []` frontmatter array.
77
+ - If only one spine exists, report the incomplete pair and ask whether the user wants to include the partial UX handoff.
78
+ - If multiple run folders match, show each run folder with the spine frontmatter `status` and `updated` values when available, then ask the user which UX design contract to include.
71
79
 
72
80
  Before proceeding, Ask the user if there are any other documents to include for analysis, and if anything found should be excluded. Wait for user confirmation. Once confirmed, create the {planning_artifacts}/epics.md from the ../templates/epics-template.md and in the front matter list the files in the array of `inputDocuments: []`.
73
81
 
@@ -136,7 +144,7 @@ Review the Architecture document for technical requirements that impact epic and
136
144
 
137
145
  **IMPORTANT**: The UX Design Specification is a first-class input document, not supplementary material. Requirements from the UX spec must be extracted with the same rigor as PRD functional requirements.
138
146
 
139
- Read the FULL UX Design document and extract ALL actionable work items:
147
+ Read the FULL UX design contract and extract ALL actionable work items. For a bmad-ux spine pair, read both `DESIGN.md` and `EXPERIENCE.md`:
140
148
 
141
149
  **Look for:**
142
150
 
@@ -18,7 +18,7 @@ failed_layers: '' # set at runtime: comma-separated list of layers that failed o
18
18
 
19
19
  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.
20
20
 
21
- - **Blind Hunter** — receives `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
21
+ - **Blind Hunter** — receives inline `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
22
22
 
23
23
  - **Edge Case Hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill.
24
24
 
@@ -25,7 +25,7 @@ Do NOT `git add` anything — this is read-only inspection.
25
25
 
26
26
  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.
27
27
 
28
- - **Blind hunter** — receives `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
28
+ - **Blind hunter** — receives inline `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `bmad-review-adversarial-general` skill.
29
29
  - **Edge case hunter** — receives `{diff_output}` and read access to the project. Invoke via the `bmad-review-edge-case-hunter` skill.
30
30
  - **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.
31
31
 
@@ -225,12 +225,12 @@ Amelia (Developer): "Perfect. Epic {{epic_number}} is complete and ready for ret
225
225
 
226
226
  </step>
227
227
 
228
- <step n="0.5" goal="Discover and load project documents">
228
+ <step n="2" goal="Discover and load project documents">
229
229
  <action>Load input files according to the Input Files table above. For SELECTIVE_LOAD inputs, load only the epic matching {{epic_number}}. For FULL_LOAD inputs, load the complete document. For INDEX_GUIDED inputs, check the index first and load relevant sections. After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content}</action>
230
230
  <note>After discovery, these content variables are available: {epics_content} (selective load for this epic), {architecture_content}, {prd_content}, {document_project_content}</note>
231
231
  </step>
232
232
 
233
- <step n="2" goal="Deep Story Analysis - Extract Lessons from Implementation">
233
+ <step n="3" goal="Deep Story Analysis - Extract Lessons from Implementation">
234
234
 
235
235
  <output>
236
236
  Amelia (Developer): "Before we start the team discussion, let me review all the story records to surface key themes. This'll help us have a richer conversation."
@@ -324,7 +324,7 @@ Amelia (Developer): "We'll get to all of it. But first, let me load the previous
324
324
 
325
325
  </step>
326
326
 
327
- <step n="3" goal="Load and Integrate Previous Epic Retrospective">
327
+ <step n="4" goal="Load and Integrate Previous Epic Retrospective">
328
328
 
329
329
  <action>Calculate previous epic number: {{prev_epic_num}} = {{epic_number}} - 1</action>
330
330
 
@@ -350,6 +350,7 @@ Amelia (Developer): "I found our retrospectives from Epic {{prev_epic_num}}. Let
350
350
 
351
351
  **Action Item Follow-Through:**
352
352
  - For each action item from Epic {{prev_epic_num}} retro, check if it was completed
353
+ - Cross-check the action_items section in {sprint_status_file} (if present) for Epic {{prev_epic_num}} entries and their current status
353
354
  - Look for evidence in current epic's story records
354
355
  - Mark each action item: ✅ Completed, ⏳ In Progress, ❌ Not Addressed
355
356
 
@@ -420,7 +421,7 @@ Charlie (Senior Dev): "First epic, first retro. Let's make it count."
420
421
 
421
422
  </step>
422
423
 
423
- <step n="4" goal="Preview Next Epic with Change Detection">
424
+ <step n="5" goal="Preview Next Epic with Change Detection">
424
425
 
425
426
  <action>Calculate next epic number: {{next_epic_num}} = {{epic_number}} + 1</action>
426
427
 
@@ -509,7 +510,7 @@ Amelia (Developer): "No problem. We'll still do a thorough retro on Epic {{epic_
509
510
 
510
511
  </step>
511
512
 
512
- <step n="5" goal="Initialize Retrospective with Rich Context">
513
+ <step n="6" goal="Initialize Retrospective with Rich Context">
513
514
 
514
515
  <action>Load agent roster from {agent_roster}</action>
515
516
  <action>Identify which agents participated in Epic {{epic_number}} based on story records</action>
@@ -599,7 +600,7 @@ Amelia (Developer): "Exactly. {user_name}, any questions before we dive in?"
599
600
 
600
601
  </step>
601
602
 
602
- <step n="6" goal="Epic Review Discussion - What Went Well, What Didn't">
603
+ <step n="7" goal="Epic Review Discussion - What Went Well, What Didn't">
603
604
 
604
605
  <output>
605
606
  Amelia (Developer): "Let's start with the good stuff. What went well in Epic {{epic_number}}?"
@@ -673,7 +674,7 @@ Alice (Product Owner): "I appreciate that. I could've been more proactive about
673
674
  Amelia (Developer): "This is good. We're identifying systemic improvements, not assigning blame."
674
675
  </output>
675
676
 
676
- <action>Continue the discussion, weaving in patterns discovered from the deep story analysis (Step 2)</action>
677
+ <action>Continue the discussion, weaving in patterns discovered from the deep story analysis (Step 3)</action>
677
678
 
678
679
  <output>
679
680
  Amelia (Developer): "Speaking of patterns, I noticed something when reviewing all the story records..."
@@ -744,13 +745,13 @@ Amelia (Developer): "Does that capture it? Anyone have something important we mi
744
745
 
745
746
  </step>
746
747
 
747
- <step n="7" goal="Next Epic Preparation Discussion - Interactive and Collaborative">
748
+ <step n="8" goal="Next Epic Preparation Discussion - Interactive and Collaborative">
748
749
 
749
750
  <check if="{{next_epic_exists}} == false">
750
751
  <output>
751
752
  Amelia (Developer): "Normally we'd discuss preparing for the next epic, but since Epic {{next_epic_num}} isn't defined yet, let's skip to action items."
752
753
  </output>
753
- <action>Skip to Step 8</action>
754
+ <action>Skip to Step 9</action>
754
755
  </check>
755
756
 
756
757
  <output>
@@ -868,7 +869,7 @@ Amelia (Developer): "{user_name}, does this preparation plan work for you?"
868
869
 
869
870
  </step>
870
871
 
871
- <step n="8" goal="Synthesize Action Items with Significant Change Detection">
872
+ <step n="9" goal="Synthesize Action Items with Significant Change Detection">
872
873
 
873
874
  <output>
874
875
  Amelia (Developer): "Let's capture concrete action items from everything we've discussed."
@@ -1109,7 +1110,7 @@ Amelia (Developer): "Everyone clear on what they own?"
1109
1110
 
1110
1111
  </step>
1111
1112
 
1112
- <step n="9" goal="Critical Readiness Exploration - Interactive Deep Dive">
1113
+ <step n="10" goal="Critical Readiness Exploration - Interactive Deep Dive">
1113
1114
 
1114
1115
  <output>
1115
1116
  Amelia (Developer): "Before we close, I want to do a final readiness check."
@@ -1292,7 +1293,7 @@ Charlie (Senior Dev): "Better to catch this now than three stories into the next
1292
1293
 
1293
1294
  </step>
1294
1295
 
1295
- <step n="10" goal="Retrospective Closure with Celebration and Commitment">
1296
+ <step n="11" goal="Retrospective Closure with Celebration and Commitment">
1296
1297
 
1297
1298
  <output>
1298
1299
  Amelia (Developer): "We've covered a lot of ground today. Let me bring this retrospective to a close."
@@ -1368,7 +1369,7 @@ Amelia (Developer): "See you all when prep work is done. Meeting adjourned!"
1368
1369
 
1369
1370
  </step>
1370
1371
 
1371
- <step n="11" goal="Save Retrospective and Update Sprint Status">
1372
+ <step n="12" goal="Save Retrospective and Update Sprint Status">
1372
1373
 
1373
1374
  <action>Ensure retrospectives folder exists: {implementation_artifacts}</action>
1374
1375
  <action>Create folder if it doesn't exist</action>
@@ -1403,6 +1404,19 @@ Amelia (Developer): "See you all when prep work is done. Meeting adjourned!"
1403
1404
  <action>Find development_status key "epic-{{epic_number}}-retrospective"</action>
1404
1405
  <action>Verify current status (typically "optional" or "pending")</action>
1405
1406
  <action>Update development_status["epic-{{epic_number}}-retrospective"] = "done"</action>
1407
+ <action>Append each Epic {{epic_number}} action item to the action_items section, creating the section after development_status if missing. One entry per item:</action>
1408
+
1409
+ ```yaml
1410
+ action_items:
1411
+ - epic: {{epic_number}}
1412
+ action: "{{action_description}}"
1413
+ owner: "{{owner}}"
1414
+ status: open
1415
+ ```
1416
+
1417
+ <action>Quote action and owner values so punctuation (e.g., "#") cannot break YAML parsing</action>
1418
+
1419
+ <action>Update Epic {{prev_epic_num}} action_items entries based on Step 4 follow-through: ✅ Completed → done, ⏳ In Progress → in-progress, ❌ Not Addressed → keep existing status (do not modify)</action>
1406
1420
  <action>Update last_updated field to current date</action>
1407
1421
  <action>Save file, preserving ALL comments and structure including STATUS DEFINITIONS</action>
1408
1422
 
@@ -1412,6 +1426,7 @@ Amelia (Developer): "See you all when prep work is done. Meeting adjourned!"
1412
1426
 
1413
1427
  Retrospective key: epic-{{epic_number}}-retrospective
1414
1428
  Status: {{previous_status}} → done
1429
+ Action items recorded: {{action_count}}
1415
1430
  </output>
1416
1431
  </check>
1417
1432
 
@@ -1425,7 +1440,7 @@ Retrospective document was saved successfully, but {sprint_status_file} may need
1425
1440
 
1426
1441
  </step>
1427
1442
 
1428
- <step n="12" goal="Final Summary and Handoff">
1443
+ <step n="13" goal="Final Summary and Handoff">
1429
1444
 
1430
1445
  <output>
1431
1446
  **✅ Retrospective Complete, {user_name}!**
@@ -34,7 +34,7 @@ persistent_facts = [
34
34
  "file:{project-root}/**/project-context.md",
35
35
  ]
36
36
 
37
- # Scalar: executed when the workflow reaches Step 12 (Final Summary and Handoff),
37
+ # Scalar: executed when the workflow reaches Step 13 (Final Summary and Handoff),
38
38
  # after the retrospective document is saved and sprint-status is updated. Override wins.
39
39
  # Leave empty for no custom post-completion behavior.
40
40
 
@@ -151,6 +151,7 @@ development_status:
151
151
 
152
152
  - If existing `{status_file}` exists and has more advanced status, preserve it
153
153
  - Never downgrade status (e.g., don't change `done` to `ready-for-dev`)
154
+ - If existing `{status_file}` has an `action_items` section, carry it over unchanged
154
155
 
155
156
  **Status Flow Reference:**
156
157
 
@@ -194,12 +195,18 @@ development_status:
194
195
  # - optional: Can be completed but not required
195
196
  # - done: Retrospective has been completed
196
197
  #
198
+ # Action Item Status:
199
+ # - open: Committed during a retrospective, not yet addressed
200
+ # - in-progress: Actively being worked on
201
+ # - done: Completed
202
+ #
197
203
  # WORKFLOW NOTES:
198
204
  # ===============
199
205
  # - Epic transitions to 'in-progress' automatically when first story is created
200
206
  # - Stories can be worked in parallel if team capacity allows
201
207
  # - Developer typically creates next story after previous one is 'done' to incorporate learnings
202
208
  # - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
209
+ # - Retrospective appends its action items to action_items; sprint-status surfaces open ones
203
210
 
204
211
  generated: { date }
205
212
  last_updated: { date }
@@ -215,6 +222,7 @@ development_status:
215
222
  <action>Write the complete sprint status YAML to {status_file}</action>
216
223
  <action>CRITICAL: Metadata appears TWICE - once as comments (#) for documentation, once as YAML key:value fields for parsing</action>
217
224
  <action>Ensure all items are ordered: epic, its stories, its retrospective, next epic...</action>
225
+ <action>If the existing file had an action_items section, write it back unchanged after development_status</action>
218
226
  </step>
219
227
 
220
228
  <step n="5" goal="Validate and report">
@@ -223,7 +231,8 @@ development_status:
223
231
  - [ ] Every epic in epic files appears in {status_file}
224
232
  - [ ] Every story in epic files appears in {status_file}
225
233
  - [ ] Every epic has a corresponding retrospective entry
226
- - [ ] No items in {status_file} that don't exist in epic files
234
+ - [ ] No development_status items in {status_file} that don't exist in epic files
235
+ - [ ] action_items section (if it existed) carried over unchanged
227
236
  - [ ] All status values are legal (match state machine definitions)
228
237
  - [ ] File is valid YAML syntax
229
238
 
@@ -291,6 +300,16 @@ optional ↔ done
291
300
  - **optional**: Ready to be conducted but not required
292
301
  - **done**: Finished
293
302
 
303
+ **Action Item Status:**
304
+
305
+ ```
306
+ open → in-progress → done
307
+ ```
308
+
309
+ - **open**: Committed during a retrospective, not yet addressed
310
+ - **in-progress**: Actively being worked on
311
+ - **done**: Completed
312
+
294
313
  ### Guidelines
295
314
 
296
315
  1. **Epic Activation**: Mark epic as `in-progress` when starting work on its first story
@@ -7,7 +7,8 @@
7
7
  - [ ] Every epic found in epic\*.md files appears in sprint-status.yaml
8
8
  - [ ] Every story found in epic\*.md files appears in sprint-status.yaml
9
9
  - [ ] Every epic has a corresponding retrospective entry
10
- - [ ] No items in sprint-status.yaml that don't exist in epic files
10
+ - [ ] No development_status items in sprint-status.yaml that don't exist in epic files
11
+ - [ ] action_items section (if it existed) carried over unchanged
11
12
 
12
13
  ### Parsing Verification
13
14