ma-agents 3.5.6 → 3.6.0

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 (53) hide show
  1. package/.ma-agents.json +10 -0
  2. package/AGENTS.md +97 -0
  3. package/MANIFEST.yaml +3 -0
  4. package/README.md +17 -0
  5. package/_bmad-output/implementation-artifacts/21-10-profile-reconfigure.md +30 -6
  6. package/_bmad-output/implementation-artifacts/21-11-profile-uninstall.md +2 -1
  7. package/_bmad-output/implementation-artifacts/21-2-universal-instruction-block-expansion.md +217 -62
  8. package/_bmad-output/implementation-artifacts/21-3-roomodes-template-bmad-modes.md +196 -73
  9. package/_bmad-output/implementation-artifacts/21-4-agents-md-template-opencode.md +242 -53
  10. package/_bmad-output/implementation-artifacts/21-5-clinerules-template-extension.md +180 -41
  11. package/_bmad-output/implementation-artifacts/21-6-onprem-layered-guardrails.md +250 -75
  12. package/_bmad-output/implementation-artifacts/21-7-bmad-persona-phase-prefix.md +221 -89
  13. package/_bmad-output/implementation-artifacts/21-8-vllm-reference-doc-readme.md +121 -63
  14. package/_bmad-output/implementation-artifacts/21-9-tests-validation.md +332 -61
  15. package/_bmad-output/implementation-artifacts/bug-bmad-recompile-fails-on-airgapped-network.md +112 -0
  16. package/_bmad-output/implementation-artifacts/sprint-status.yaml +3 -2
  17. package/bin/cli.js +59 -0
  18. package/docs/deployment/vllm-nemotron.md +130 -0
  19. package/lib/agents.js +17 -2
  20. package/lib/bmad-customize/bmm-analyst.customize.yaml +8 -0
  21. package/lib/bmad-customize/bmm-architect.customize.yaml +2 -0
  22. package/lib/bmad-customize/bmm-dev.customize.yaml +2 -0
  23. package/lib/bmad-customize/bmm-pm.customize.yaml +2 -0
  24. package/lib/bmad-customize/bmm-qa.customize.yaml +2 -0
  25. package/lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml +8 -0
  26. package/lib/bmad-customize/bmm-sm.customize.yaml +2 -0
  27. package/lib/bmad-customize/bmm-tech-writer.customize.yaml +2 -0
  28. package/lib/bmad-customize/bmm-ux-designer.customize.yaml +2 -0
  29. package/lib/bmad.js +293 -1
  30. package/lib/installer.js +617 -43
  31. package/lib/merge/roomodes.js +125 -0
  32. package/lib/profile.js +25 -2
  33. package/lib/reconfigure.js +334 -0
  34. package/lib/templates/agents-md.template.md +67 -0
  35. package/lib/templates/clinerules.template.md +13 -0
  36. package/lib/templates/instruction-block-onprem.template.md +86 -0
  37. package/lib/templates/instruction-block-universal.template.md +29 -0
  38. package/lib/templates/roomodes.template.yaml +96 -0
  39. package/lib/uninstall.js +314 -0
  40. package/package.json +4 -3
  41. package/test/agents-md.test.js +398 -0
  42. package/test/bmad-extension.test.js +2 -2
  43. package/test/bmad-persona-phase-prefix.test.js +271 -0
  44. package/test/clinerules.test.js +339 -0
  45. package/test/instruction-block.test.js +388 -0
  46. package/test/integration-verification.test.js +2 -2
  47. package/test/migration-validation.test.js +2 -2
  48. package/test/offline-recompile.test.js +237 -0
  49. package/test/onprem-injection.test.js +425 -32
  50. package/test/onprem-layer.test.js +419 -0
  51. package/test/reconfigure.test.js +436 -0
  52. package/test/roomodes.test.js +343 -0
  53. package/test/uninstall.test.js +402 -0
@@ -1,6 +1,6 @@
1
1
  # Story 21.7: BMAD Persona Phase-Aware Prompt Prefix (On-Prem Only)
2
2
 
3
- Status: backlog
3
+ Status: Ready
4
4
 
5
5
  ## Story
6
6
 
@@ -10,117 +10,249 @@ So that planning agents (PM, Architect, SM) stop overthinking and producing file
10
10
 
11
11
  ## Acceptance Criteria
12
12
 
13
- 1. Each `lib/bmad-customize/*.customize.yaml` file gains an optional `phase: planning|implementation` field. Initial classification:
14
- - **Planning** (reasoning-OFF prefix): `bmm-pm` (John), `bmm-architect` (Winston), `bmm-sm` (Bob), `bmm-analyst` (Mary), `bmm-tech-writer` (Paige), `bmm-ux-designer` (Sally), `bmm-qa` (Gad)
15
- - **Implementation** (reasoning-ON prefix): `bmm-dev` (Amelia), `bmm-quick-flow-solo-dev` (Barry)
16
- 2. Each `*.customize.yaml` file gains an optional `on_prem_phase_prefix:` field containing the prefix text. The values are populated for every agent listed in AC #1; the field is absent for any agent that does not need a prefix.
17
- 3. The BMAD customize-loader (location to be determined during Task 1 exploration — likely `lib/bmad.js` or a dedicated customize module) reads `getProfile(projectRoot)` from `lib/profile.js` and:
18
- - When profile=on-prem AND `on_prem_phase_prefix` is set, prepends the prefix to the persona's existing `critical_actions` / system-prompt content
19
- - When profile=standard OR `on_prem_phase_prefix` is absent, does NOT prepend anything (output identical to pre-Story-21.7 behavior)
20
- 4. NFR44 verification: with profile=standard, the rendered `.customize.yaml` consumption produces output byte-identical to the pre-Story-21.7 baseline for every agent. Captured by snapshot tests.
21
- 5. The phase prefix content for planning agents includes:
22
- - A `/no_think` directive at the top
23
- - "When the user asks a question or for an opinion, respond in TEXT in the chat. Do NOT create files."
24
- - "You are a planning-phase agent. Do NOT skip ahead to implementation."
25
- 6. The phase prefix content for implementation agents includes:
26
- - "Think carefully about the implementation before writing code."
27
- - "Reference the story or spec you are implementing before starting."
28
- - "When asked a question, respond in text. Do not start coding unless asked."
29
- 7. The customize-loader's prefix composition is idempotent — running the loader twice produces the same composed content (NFR46).
30
- 8. **Phase enum extended to `{planning | implementation | mixed}` with persona reassignment (supersedes AC #1).** The `phase` field in each `*.customize.yaml` now accepts the value `mixed` in addition to `planning` and `implementation`. Final per-persona assignment is:
31
- - **`phase: planning`** — `bmm-pm` (John), `bmm-architect` (Winston), `bmm-ux-designer` (Sally), `bmm-tech-writer` (Paige)
32
- - **`phase: implementation`** `bmm-dev` (Amelia), `bmm-quick-flow-solo-dev` (Barry)
33
- - **`phase: mixed`** — `bmm-sm` (Bob), `bmm-qa` (Gad), `bmm-analyst` (Mary)
34
- This supersedes AC #1's binary classification (which listed Bob, Gad, and Mary under `planning` and Paige under `planning`). The reason: Bob and Gad straddle planning conversations and story-file edits; Mary moves between research discussion and brief edits. A binary classification mislabels them and forces the wrong phase prefix. Each `*.customize.yaml` file must encode the `phase` value per this list.
35
- 9. **Composite prefix for `phase: mixed`.** Personas with `phase: mixed` receive the following composite preamble as their `on_prem_phase_prefix` value (in addition to any persona-specific content): `"This persona handles both discussion and editing. Default to text responses when asked questions; only create or edit files when explicitly asked (verbs: create, write, generate, update, edit). When editing code, reason carefully; when discussing, keep responses concise without deep reasoning chains."` The customize-loader composes this prefix when profile=on-prem AND `phase: mixed`, parallel to the planning/implementation branches in AC #5/#6.
36
- 10. **Customize-loader validator must accept `mixed`.** The Epic 15 customize-loader schema validation (wherever it lives see Dev Notes) must recognize `mixed` as a valid `phase` value. If the current loader validator only accepts `{planning, implementation}`, a prerequisite sub-task is to extend the validator enum. This AC is satisfied when: (a) the validator accepts all three values without error, and (b) a `*.customize.yaml` file with `phase: mixed` is loaded successfully in a unit test.
13
+ > ACs flagged **(gap-fill)** are refinements added by the story author to make the epic's AC operational and testable. They refine the "how" without contradicting the epic's "what". Where the epic is genuinely ambiguous, an **Open question** callout is raised for the implementing dev to resolve rather than silently guessed. Controlling invariants: **NFR44** (standard profile byte-identity), **NFR46** (idempotency), **NFR47** (Roo Code `fileRegex` not disturbed — consumed unchanged here), **NFR18** (additive JSON-merge not disturbed — this story does not touch `opencode.json`).
14
+
15
+ 1. **Planning-persona prefix content.** When `profile === 'on-prem'` is active at install time, each of the following planning personas has a phase-aware system-prompt prefix prepended to its composed `critical_actions` / system-prompt content:
16
+ - `bmm-pm` (John)
17
+ - `bmm-architect` (Winston)
18
+ - `bmm-sm` (Bob)
19
+ - `bmm-analyst` (Mary) see Open question below on source file presence
20
+ - `bmm-tech-writer` (Paige)
21
+ - `bmm-ux-designer` (Sally)
22
+ - `bmm-qa` (Gad)
23
+
24
+ The prefix text consists of a `/no_think` reasoning-OFF directive and a "respond in text for questions; create files only when explicitly asked" sentence, authored verbatim in each persona's `on_prem_phase_prefix` YAML field (AC #4).
25
+
26
+ 2. **Implementation-persona prefix content.** When `profile === 'on-prem'` is active, each of the following implementation personas receives a different phase-aware prefix:
27
+ - `bmm-dev` (Amelia)
28
+ - `bmm-quick-flow-solo-dev` (Barry) see Open question below on source file presence
29
+
30
+ The prefix is a "think carefully before writing code; reference the story you are implementing" directive reasoning ON retained, unlike planning personas.
31
+
32
+ 3. **Standard-profile isolation (NFR44).** When `profile === 'standard'` or `getProfile(projectRoot)` returns `undefined`, NO `on_prem_phase_prefix` content is prepended to any persona's composed system prompt. The customize output for every persona is byte-identical to the pre-Epic-21 baseline. Verified by comparing the on-disk content of `_bmad/_config/agents/*.customize.yaml` deployed by the installer in a standard-profile install against a snapshot captured before Epic 21 changes were staged.
33
+
34
+ 4. **(gap-fill) YAML schema additions.** Each `lib/bmad-customize/<persona>.customize.yaml` file gains two new optional top-level fields:
35
+ - `phase: planning | implementation` phase classification, stateless (keeps the consumer stateless per epic technical note, `epics.md` line 4102).
36
+ - `on_prem_phase_prefix: <string>` — the literal prefix text to prepend when `profile === 'on-prem'`.
37
+
38
+ Both fields are OPTIONAL. Files missing them behave as pre-Epic-21 (no prefix applied in any profile). The existing `critical_actions` array and any other fields are preserved byte-for-byte.
39
+
40
+ 5. **(gap-fill) `phase` field values enumerated.** The permissible values for `phase` are `planning` and `implementation`. Any other value is ignored with a console warning during deployment (non-fatal). See Open question below on whether a `mixed` value is in scope.
41
+
42
+ > **Open question (phase: mixed enumeration).** The epic cross-epic note at `_bmad-output/planning-artifacts/epics.md:4231` describes a "phase: mixed enum extension (added in corrective-plan step 3)". This story does NOT introduce `phase: mixed` in AC #5 because no epic AC enumerates it and no persona file has requested it. If the implementing dev finds a persona where both planning and implementation prefixes should co-apply (e.g., `bmm-bmad-master`), raise it as a follow-up story. Proposed resolution: scope strictly to `planning` and `implementation` for Story 21.7; `mixed` is a follow-up.
43
+
44
+ 6. **Loader integration contract — customize-loader lives upstream.** Per the Epic 21 cross-epic note at `_bmad-output/planning-artifacts/epics.md:4231`, the customize-loader that composes persona system prompts lives in **upstream BMAD**, not in ma-agents. `lib/bmad-customize/` (verified at `D:\Code\agents\lib\bmad-customize\`) contains only the 8 `*.customize.yaml` artifacts; there is no ma-agents loader JS to modify. Per the project's durable policy ("BMAD built-in override policy" — never upstream PRs; override via extension), this story's implementation MUST NOT submit changes to `bmad-method`. All on-prem prefix behavior is introduced via the ma-agents extension path.
45
+
46
+ > **Open question (two-branch decision — upstream loader behavior).** Per `epics.md:4231` the implementing dev MUST first probe upstream BMAD's customize-loader against a YAML file that contains the new `phase:` and `on_prem_phase_prefix:` keys. Two valid branches follow:
47
+ >
48
+ > - **Branch A — upstream accepts unknown keys (lenient schema).** The loader reads `critical_actions` and ignores the new keys. In this case, the prefix logic runs in a ma-agents-owned post-deploy step that rewrites the prepended content into the deployed `_bmad/_config/agents/<persona>.customize.yaml` (or equivalent compiled output) at install time, gated by `getProfile(projectRoot) === 'on-prem'`. The single source YAML in `lib/bmad-customize/` carries both keys and is consumed by BOTH profiles — the post-deploy step is the ONLY on-prem branch.
49
+ >
50
+ > - **Branch B — upstream rejects unknown keys (strict schema).** The epic mandates a dual-variant output: the extension emits two files per persona during install — `<persona>.customize.yaml` (standard, strips the new keys) and `<persona>.customize.on-prem.yaml` (on-prem, inlines the `on_prem_phase_prefix` into the prepended `critical_actions`). The installer chooses which variant to deploy to `_bmad/_config/agents/` based on `getProfile(projectRoot)`. `lib/bmad-customize/<persona>.customize.yaml` remains the single-source authoring file; the dual-variant expansion happens at deploy time in a ma-agents helper.
51
+ >
52
+ > Proposed resolution: Task 1 runs the probe with a throwaway YAML. Implementing dev picks the branch, records the decision in this file's Change Log, and implements exactly one branch. Both branches satisfy NFR44 (standard profile produces no on-prem content) — they differ only in WHERE the conditional lives.
53
+
54
+ 7. **(gap-fill) Prefix composition rule.** Whichever branch (A or B) is chosen, the on-prem prefix text is prepended to the EXISTING `critical_actions` list — it does not replace the existing items. Shape depends on branch:
55
+ - **Branch A shape:** post-deploy rewrite inserts the prefix as a new `critical_actions[0]` entry (quoted string) ahead of the existing entries.
56
+ - **Branch B shape:** the on-prem variant file is emitted with `critical_actions[0] = <prefix text>` already inlined; the standard variant omits it.
57
+
58
+ All pre-existing `critical_actions` entries are preserved in their original order in both shapes.
59
+
60
+ 8. **(gap-fill) Idempotency (NFR46).** Two consecutive on-prem installs produce byte-identical deployed `_bmad/_config/agents/*.customize.yaml` content for every persona touched by this story. Verified by hashing the deployed files after two back-to-back installs. The on-prem prefix strings contain no timestamps, random IDs, or environment-dependent content.
61
+
62
+ 9. **(gap-fill) Standard profile byte-identity to pre-Epic-21 baseline.** When `profile === 'standard'`, the deployed `_bmad/_config/agents/<persona>.customize.yaml` content is byte-identical to what the same installer would have produced before Epic 21 staged the schema additions from AC #4. If Branch A is chosen, this requires either (a) the post-deploy step being a no-op under standard profile, or (b) the post-deploy step explicitly stripping the new `phase` / `on_prem_phase_prefix` keys before writing. If Branch B is chosen, the standard-variant file emitted at deploy time strips the new keys. Either way, a standard-profile install MUST NOT leak the `phase:` or `on_prem_phase_prefix:` keys into the deployed artifact.
63
+
64
+ 10. **(gap-fill) Authoring file back-compat.** `lib/bmad-customize/<persona>.customize.yaml` files that are NOT touched by this story (or any persona whose `phase` field is unset) MUST continue to deploy identically to pre-Epic-21 behavior — this story only modifies the files for the 9 personas enumerated in AC #1 + AC #2. Other personas (e.g., `bmm-bmad-master`, `bmm-demerzel`, the IDE-agent customizations in `lib/bmad-customizations/*.customize.yaml`) are OUT OF SCOPE.
65
+
66
+ 11. **(gap-fill) NFR47 non-regression.** This story does not touch `.roomodes`, `fileRegex`, Roo Code modes, or any application-layer file restriction surface. Verified by asserting the generated `.roomodes` after a Story 21.7 install has the same `groups` / `fileRegex` patterns as a Story 21.6 install (content diff only in persona customize files under `_bmad/_config/agents/`).
67
+
68
+ 12. **(gap-fill) NFR18 non-regression.** This story does not touch `opencode.json` or any JSON-merge surface. Verified by asserting `opencode.json::instructions[]` length and content are identical between a Story 21.6 and Story 21.7 install (this story's deliverable is orthogonal to the OpenCode injection path).
69
+
70
+ > **Resolved (persona source files — `bmm-analyst` and `bmm-quick-flow-solo-dev`).** The epic lists `bmm-analyst` (Mary) in AC #1 and `bmm-quick-flow-solo-dev` (Barry) in AC #2, but `ls lib/bmad-customize/` (verified 2026-04-15) shows neither file. Existing files are: `bmm-architect`, `bmm-bmad-master`, `bmm-dev`, `bmm-pm`, `bmm-qa`, `bmm-sm`, `bmm-tech-writer`, `bmm-ux-designer`.
71
+ >
72
+ > **Decision:** Create both missing authoring files as part of this story (Tasks 2.8 and 2.9, unconditional). The authoring shape is trivial (~5 lines matching `bmm-pm.customize.yaml` / `bmm-dev.customize.yaml`) and the epic explicitly enumerates these personas in AC #1 and AC #2, so deferring to a follow-up would leave the epic's AC operationally incomplete. New files: `lib/bmad-customize/bmm-analyst.customize.yaml` (planning) and `lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml` (implementation), each carrying the standard `critical_actions` block plus `phase` + `on_prem_phase_prefix`.
37
73
 
38
74
  ## Tasks / Subtasks
39
75
 
40
- - [ ] Task 1: Locate the customize-loader code path (`lib/bmad.js`, `lib/bmad-customize/`, or a dedicated module). Document file:line in Dev Agent Record. Confirm where `critical_actions` are composed for each persona.
41
- - [ ] Task 2: Add `phase` and `on_prem_phase_prefix` fields to the 9 affected `*.customize.yaml` files (AC #1, #2, #5, #6)
42
- - Planning-phase content: shared text block defined once (e.g., in a comment-marked region) and pasted into each planning persona's YAML
43
- - Implementation-phase content: same approach, pasted into the 2 implementation personas
44
- - [ ] Task 3: Extend the customize-loader to compose the prefix when `getProfile(projectRoot) === 'on-prem'` and the YAML has `on_prem_phase_prefix` (AC #3, #7)
45
- - [ ] Task 4: Snapshot-test baseline parity (AC #4)
46
- - [ ] 4.1 Capture pre-Story-21.7 customize-loader output for all 11 BMAD agents (run before changes; commit snapshots to `test/snapshots/customize/`)
47
- - [ ] 4.2 With profile=standard after Story 21.7 changes, customize-loader output matches snapshots byte-for-byte
48
- - [ ] Task 5: Tests in `test/bmad-persona-phase-prefix.test.js`
49
- - [ ] 5.1 Profile=on-prem: planning agents get `/no_think` + text-response prefix prepended
50
- - [ ] 5.2 Profile=on-prem: implementation agents get careful-implementation prefix prepended
51
- - [ ] 5.3 Profile=standard: no prefix prepended for any agent (snapshot match — AC #4)
52
- - [ ] 5.4 Profile=on-prem with agent missing `on_prem_phase_prefix`: no prefix, no error
53
- - [ ] 5.5 Idempotency: two loader runs produce identical composed content (NFR46)
54
- - [ ] Task 6: Phase enum extension and persona reassignment (AC #8, #9, #10)
55
- - [ ] 6.1 Reassign `phase` values per AC #8: Bob, Gad, Mary `mixed`; Paige stays `planning`; others unchanged
56
- - [ ] 6.2 Populate `on_prem_phase_prefix` for the three `mixed` personas with the composite preamble in AC #9 (plus any persona-specific tail)
57
- - [ ] 6.3 PREREQUISITE: audit the Epic 15 customize-loader schema validator — if it enforces enum `{planning, implementation}`, extend it to `{planning, implementation, mixed}`. If the validator lives outside this story's scope, raise an Epic 15 issue/story and document the blocker in Dev Agent Record before proceeding
58
- - [ ] 6.4 Tests: (a) profile=on-prem + `phase: mixed` composite prefix prepended; (b) validator accepts all three enum values
76
+ - [ ] **Task 1: Upstream loader probe + branch decision** (AC #6)
77
+ - [ ] 1.1 Read the `bmad-method` upstream customize-loader source (node_modules path under `bmad-method/...`) locate the YAML-parse call and inspect whether unknown top-level keys throw or are silently dropped.
78
+ - [ ] 1.2 Author a throwaway YAML with `phase: planning` and `on_prem_phase_prefix: "test"` and run the recompile step (`lib/bmad.js` STAGE:CUSTOMIZE path) in a sandbox tmp project. Observe outcome.
79
+ - [ ] 1.3 Record decision (Branch A — lenient, or Branch B — strict) in this file's Change Log with a one-line justification. Do NOT check the probe into committed code.
80
+ - [ ] 1.4 If Branch B: design the dual-variant emission helper (see Task 3B). If Branch A: design the post-deploy rewrite helper (see Task 3A).
81
+
82
+ - [ ] **Task 2: Author persona customize.yaml updates** (AC #1, #2, #4, #10)
83
+ - [ ] 2.1 Modify `lib/bmad-customize/bmm-pm.customize.yaml` add `phase: planning` and `on_prem_phase_prefix: "<planning prefix text>"` top-level fields. Leave `critical_actions` untouched.
84
+ - [ ] 2.2 Modify `lib/bmad-customize/bmm-architect.customize.yaml` — same shape, planning.
85
+ - [ ] 2.3 Modify `lib/bmad-customize/bmm-sm.customize.yaml` same shape, planning.
86
+ - [ ] 2.4 Modify `lib/bmad-customize/bmm-tech-writer.customize.yaml` same shape, planning.
87
+ - [ ] 2.5 Modify `lib/bmad-customize/bmm-ux-designer.customize.yaml` same shape, planning.
88
+ - [ ] 2.6 Modify `lib/bmad-customize/bmm-qa.customize.yaml` same shape, planning.
89
+ - [ ] 2.7 Modify `lib/bmad-customize/bmm-dev.customize.yaml` add `phase: implementation` and `on_prem_phase_prefix: "<implementation prefix text>"`.
90
+ - [ ] 2.8 Create `lib/bmad-customize/bmm-analyst.customize.yaml` (new) with the standard `critical_actions` block mirroring `bmm-pm.customize.yaml`, plus `phase: planning` and `on_prem_phase_prefix: "<planning prefix text>"`.
91
+ - [ ] 2.9 Create `lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml` (new) with the standard `critical_actions` block mirroring `bmm-dev.customize.yaml`, plus `phase: implementation` and `on_prem_phase_prefix: "<implementation prefix text>"`.
92
+ - [ ] 2.10 Ensure every edited file ends with a single trailing newline and has no trailing whitespace (idempotency AC #8).
93
+
94
+ - [ ] **Task 3A: Branch A implementation post-deploy rewrite helper** (AC #6, #7, #9, #10)
95
+ - [ ] 3A.1 Add a helper function to `lib/bmad.js` (new function, name TBD by implementing dev, e.g., `applyOnPremPhasePrefix(configTargetDir, projectRoot)`), invoked AFTER the STAGE:CUSTOMIZE file copy (currently `lib/bmad.js` line ~414) and ONLY when `require('./profile').getProfile(projectRoot) === 'on-prem'`.
96
+ - [ ] 3A.2 The helper iterates `configTargetDir/*.customize.yaml`, parses each, and for files with a non-empty `on_prem_phase_prefix`, prepends the prefix as the first `critical_actions` entry. It then strips the `phase` and `on_prem_phase_prefix` top-level keys from the deployed file (keeping the authoring source unchanged).
97
+ - [ ] 3A.3 For standard-profile installs, the helper is not called — but the STAGE:CUSTOMIZE copy must still strip the `phase` and `on_prem_phase_prefix` keys from the deployed files to satisfy AC #9's byte-identity guarantee against the pre-Epic-21 baseline. Implement this as a profile-agnostic sibling step (strip-only) that runs before the on-prem helper.
98
+
99
+ - [ ] **Task 3B: Branch B implementation — dual-variant emission helper** (AC #6, #7, #9, #10)
100
+ - [ ] 3B.1 Add a helper function to `lib/bmad.js` (name TBD, e.g., `emitProfiledCustomizeVariants(customizeSource, configTargetDir, profile)`), invoked during STAGE:CUSTOMIZE (`lib/bmad.js` line ~410-418) REPLACING the current `fs.copy` loop for files that contain the new keys.
101
+ - [ ] 3B.2 For each `<persona>.customize.yaml` in `lib/bmad-customize/`: parse, and emit ONE file to `configTargetDir/<persona>.customize.yaml`. The emitted file content depends on the `profile` argument: on-prem variant has the prefix inlined into `critical_actions[0]`; standard variant omits it. Both variants strip the `phase` and `on_prem_phase_prefix` keys.
102
+ - [ ] 3B.3 Files that do NOT contain the new keys are copied unchanged by the existing loop (back-compat with AC #10).
103
+
104
+ - [ ] **Task 4: Deploy-path profile wiring** (AC #3, #6)
105
+ - [ ] 4.1 In `lib/bmad.js`, at the point just before STAGE:CUSTOMIZE, resolve `const profile = require('./profile').getProfile(projectRoot) ?? 'standard';` and pass it to the Task 3A or 3B helper.
106
+ - [ ] 4.2 Confirm the `projectRoot` value is the same one used elsewhere in `lib/bmad.js` (existing param, no new arg threading beyond the helper call).
107
+
108
+ - [ ] **Task 5: Tests** — see Testing section below.
109
+
110
+ - [ ] **Task 6: Documentation touch-up**
111
+ - [ ] 6.1 No new docs in this story (Story 21.8 owns the on-prem README section). If an existing `lib/bmad-customize/README.md` (none verified) or equivalent documents the customize.yaml schema, append a paragraph describing the two new optional fields.
59
112
 
60
113
  ## Dev Notes
61
114
 
62
- ### Architecture Compliance
115
+ ### Architecture compliance
63
116
 
64
- - **Decision P3-3** — BMAD persona phase prefix is the on-prem-only layer that complements per-tool guardrails. Inactive on standard profile.
65
- - **NFR44** — Standard profile customize output unchanged. Snapshot tests are the contract.
117
+ - **Decision P3-3 (Local-LLM / On-Prem Agent Tuning Profile)** — Story 21.7 delivers the persona-level system-prompt-prefix surface. This is a SEPARATE composition surface from the per-tool instruction injection (Stories 21.2–21.6, which flow through `composeInstructionBlock`). Per Story 21.6 Dev Notes Out-of-Scope list, persona prefixes ship here in 21.7 exclusively.
66
118
 
67
- ### Source Tree Components to Touch
119
+ - **NFR44 (profile isolation / standard-profile byte-identity)** — Epic cross-reference at `_bmad-output/planning-artifacts/epics.md:4095` reads: "profile=standard → NO phase prefix is prepended (NFR44 — standard profile is byte-identical to pre-Epic-21 baseline for customize output)". AC #3 and AC #9 are the contracts; Testing section 7.4 and 7.6 enforce.
68
120
 
69
- | File | Change |
70
- |------|--------|
71
- | `lib/bmad-customize/bmm-pm.customize.yaml` | MODIFY — add `phase: planning`, `on_prem_phase_prefix:` |
72
- | `lib/bmad-customize/bmm-architect.customize.yaml` | MODIFY — same |
73
- | `lib/bmad-customize/bmm-sm.customize.yaml` | MODIFY — same |
74
- | `lib/bmad-customize/bmm-analyst.customize.yaml` | MODIFY — same |
75
- | `lib/bmad-customize/bmm-tech-writer.customize.yaml` | MODIFY — same |
76
- | `lib/bmad-customize/bmm-ux-designer.customize.yaml` | MODIFY — same |
77
- | `lib/bmad-customize/bmm-qa.customize.yaml` | MODIFY — same (Gad — verify file name from Epic 20 SQA work) |
78
- | `lib/bmad-customize/bmm-dev.customize.yaml` | MODIFY — `phase: implementation`, prefix |
79
- | `lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml` | MODIFY — same |
80
- | `lib/bmad.js` (or customize-loader location) | MODIFY — profile-conditional prefix composition |
81
- | `test/bmad-persona-phase-prefix.test.js` | CREATE |
82
- | `test/snapshots/customize/*.snapshot` | CREATE — pre-change baselines for NFR44 verification |
121
+ - **NFR46 (idempotency)** `epics.md:263` and `epics.md:4144` item (c). AC #8 is the contract; Testing 7.8 enforces. Branch choice (A or B) does not affect idempotency: both branches are deterministic (no timestamps, no env-dependent content).
83
122
 
84
- ### Dependencies
123
+ - **NFR47 (Roo Code application-layer `fileRegex` enforcement)** — Not touched by this story. AC #11 is a non-regression guard. Story 21.9 owns the comprehensive cross-tool assertion; this story adds a minimal unit assertion via Testing 7.10.
85
124
 
86
- - Story 21.1 (`getProfile` API)
87
- - Epic 15 (BMAD 6.2.1 module restructure — customize-loader infrastructure may have changed)
125
+ - **NFR18 (additive JSON-merge for OpenCode)** — Not touched. AC #12 is a non-regression guard. Testing 7.11 is a thin guard; Story 21.9 owns cross-tool coverage.
88
126
 
89
- ### Out of Scope
127
+ ### BMAD built-in override policy — MANDATORY
90
128
 
91
- - Per-tool template content (Stories 21.2–21.6)
92
- - vLLM serving doc (Story 21.8)
93
- - Customize-loader refactoring beyond what's needed for prefix composition
129
+ Per user's durable memory (`BMAD built-in override policy — Override via extension, never upstream PRs to bmad-method`), this story's implementation MUST NOT submit changes to the `bmad-method` repository. The customize-loader is upstream. All on-prem-specific behavior introduced here lives in **ma-agents** code (`lib/bmad.js` helpers, `lib/bmad-customize/*.customize.yaml` artifacts). The Task 1 probe is READ-ONLY against upstream; do not touch upstream sources.
94
130
 
95
- ### Notes on Phase Enum Extension (Epic 15 Prerequisite)
131
+ Source locations to edit (per user's durable memory `Skill source locations — Never edit .claude/skills/; edit lib/bmad-extension/skills/ or skills/ instead`):
132
+ - YAML authoring: `lib/bmad-customize/<persona>.customize.yaml` (existing ma-agents-owned — edit here).
133
+ - Helper code: `lib/bmad.js` STAGE:CUSTOMIZE region (line ~406-418).
134
+ - DO NOT edit `.claude/skills/` (derived output).
135
+ - DO NOT edit anything under `bmad-method` / upstream.
96
136
 
97
- **2026-04-14 audit clarification:** `lib/bmad-customize/` in this repo contains only `*.customize.yaml` artifacts — no JS loader or validator code. The customize-loader lives upstream in BMAD (bmad-method). Per the project's durable policy of overriding BMAD built-ins via extension (not upstream PRs to bmad-method), the `phase: mixed` extension is implemented by either (a) relying on BMAD's loader accepting unknown YAML fields silently (outcome 1 below — trivially satisfied) or (b) the ma-agents extension intercepting the YAML at install time and producing profile-specific variants (`*.customize.yaml` for standard, `*.customize.on-prem.yaml` for on-prem) with the installer choosing based on the persisted profile (outcome 3 below). Outcome 2 is only relevant if BMAD's loader has an enum validator that accepts `mixed` — nice to discover, no action required.
137
+ ### Notes on Customize-Loader Discovery (Two-Branch Decision)
98
138
 
99
- AC #10 requires the Epic 15 customize-loader schema validator to accept `mixed` as a valid `phase` value. During Task 1's loader-discovery pass, verify whether a validator is in place and what enum it enforces. Three outcomes:
139
+ Per the Epic 21 cross-epic note at `_bmad-output/planning-artifacts/epics.md:4231`:
100
140
 
101
- 1. **No validator present** — `phase` is a free-form string today; AC #10 is trivially satisfied. Document this in Dev Agent Record.
102
- 2. **Validator present and accepts `mixed` already** — no change needed; satisfy AC #10 with a regression test.
103
- 3. **Validator present and rejects `mixed`** — extend the enum to `{planning, implementation, mixed}`. If the validator is owned by Epic 15 code outside this story's change scope, raise an Epic 15 issue/story as a prerequisite and block Task 6 until it lands. Document explicitly rather than letting the dev hit this at implementation time.
141
+ > **Customize-loader (Epic 15) prerequisite STATUS: clarified.** Story 21.7 was originally scoped as if ma-agents owned a customize-loader. On audit (2026-04-14), `lib/bmad-customize/` contains only `*.customize.yaml` artifacts the loader itself lives upstream in BMAD. Per the project's durable policy of overriding BMAD built-ins via extension rather than upstream PRs, Story 21.7's `phase: mixed` enum extension (added in corrective-plan step 3) will be implemented via the extension pattern: the `*.customize.yaml` files gain the `phase` field and, if BMAD's upstream loader rejects unknown values, the ma-agents extension intercepts the YAML at install time and produces two variants (`*.customize.yaml` and `*.customize.on-prem.yaml`) with the installer choosing based on the persisted profile. See Story 21.7 Dev Notes "Notes on Customize-Loader Discovery" for the decision branches the implementing dev will resolve during Task 1.
104
142
 
105
- ### Notes on Customize-Loader Discovery
143
+ **Decision branches (to be resolved in Task 1 by the implementing dev — DO NOT pre-commit to either branch):**
106
144
 
107
- If the loader is implicit (BMAD itself reads `*.customize.yaml` directly with no ma-agents intermediation), this story's design may need adjustment. In that case, the prefix must be embedded directly into the YAML's existing `critical_actions` block under a profile-aware key, OR ma-agents must intercept the file at install time and produce two variants (`*.customize.yaml` for standard, `*.customize.on-prem.yaml` for on-prem) with the installer choosing which to deploy. Decide during Task 1 and document the chosen approach.
145
+ - **Branch A upstream accepts unknown `phase:` / `on_prem_phase_prefix:` keys.** The extension path is a post-deploy rewrite step inside `lib/bmad.js` STAGE:CUSTOMIZE. `lib/bmad-customize/<persona>.customize.yaml` carries the new keys as-is; they travel into `_bmad/_config/agents/` via the existing copy; the post-deploy helper then rewrites on-prem-profile files in place to inline the prefix and strip the extra keys.
108
146
 
109
- ## Dev Agent Record
147
+ - **Branch B — upstream rejects unknown keys (strict schema, raises on load).** The extension path is a dual-variant expansion step that REPLACES the current `fs.copy` loop. `lib/bmad-customize/<persona>.customize.yaml` remains the single authoring file in ma-agents; at deploy time, the helper parses it, decides based on `getProfile(projectRoot)` whether to inline the on-prem prefix, and writes ONE `.customize.yaml` to `_bmad/_config/agents/` with the new keys STRIPPED. The "two variants" framing in epics.md:4231 refers to the two possible OUTPUTS of this helper, not two on-disk source files — there is still exactly one authoring file per persona.
110
148
 
111
- ### Agent Model Used
112
- _(to be filled by dev agent)_
149
+ The implementing dev MUST probe upstream (Task 1.1–1.2), pick a branch, record the decision in the Change Log, and implement ONE path. Both branches must produce byte-identical deployed output in standard-profile installs (AC #9). The choice affects WHERE the conditional lives, not WHAT ends up on disk.
113
150
 
114
- ### Debug Log References
115
- _(to be filled)_
151
+ ### Verified source-tree surface
116
152
 
117
- ### Completion Notes List
118
- _(to be filled)_
153
+ | File | Exists? | Role in this story |
154
+ |------|---------|--------------------|
155
+ | `lib/profile.js` | verified (Story 21.1 — `D:\Code\agents\lib\profile.js` lines 29-43) | Read-only — `getProfile(projectRoot)` consumed by the Task 3 helper |
156
+ | `lib/bmad.js` | verified (`D:\Code\agents\lib\bmad.js`) | MODIFY — add Task 3 helper; wire it in STAGE:CUSTOMIZE (line ~406-418) |
157
+ | `lib/bmad-customize/bmm-pm.customize.yaml` | verified | MODIFY — add `phase: planning` + `on_prem_phase_prefix` |
158
+ | `lib/bmad-customize/bmm-architect.customize.yaml` | verified | MODIFY — same |
159
+ | `lib/bmad-customize/bmm-sm.customize.yaml` | verified | MODIFY — same |
160
+ | `lib/bmad-customize/bmm-tech-writer.customize.yaml` | verified | MODIFY — same |
161
+ | `lib/bmad-customize/bmm-ux-designer.customize.yaml` | verified | MODIFY — same |
162
+ | `lib/bmad-customize/bmm-qa.customize.yaml` | verified | MODIFY — same |
163
+ | `lib/bmad-customize/bmm-dev.customize.yaml` | verified | MODIFY — `phase: implementation` |
164
+ | `lib/bmad-customize/bmm-analyst.customize.yaml` | (new) — does NOT exist today | CREATE (Task 2.8 / 2.9 — unconditional per Change Log 2026-04-15 resolution) |
165
+ | `lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml` | (new) — does NOT exist today | CREATE (Task 2.8 / 2.9 — unconditional per Change Log 2026-04-15 resolution) |
166
+ | `lib/bmad-customize/bmm-bmad-master.customize.yaml` | verified | UNCHANGED — out of scope (AC #10) |
167
+ | `lib/bmad-customizations/*.customize.yaml` | verified (IDE-agent customizations) | UNCHANGED — out of scope (AC #10) |
168
+ | `lib/installer.js` | verified | UNCHANGED — this story does not touch the per-tool injection path |
169
+ | `lib/agents.js` | verified | UNCHANGED — read-only reference for persona enumeration if needed |
170
+ | `test/bmad-persona-phase-prefix.test.js` | (new) | CREATE — unit + integration coverage per Testing section |
171
+ | `docs/` | (no doc change required in this story) | Story 21.8 owns the on-prem README/docs surface |
119
172
 
120
- ### File List
121
- _(to be filled)_
173
+ ### Library and pattern references
174
+
175
+ - **Profile resolution:** `require('./profile').getProfile(projectRoot)` — exact same call as Stories 21.2–21.6 use via `composeInstructionBlock`. See `D:\Code\agents\lib\profile.js:29-43`.
176
+ - **YAML parsing in `lib/bmad.js`:** `lib/bmad.js` at line ~885 already has `parseCustomizeYaml` referenced and a backup/restore flow in lines ~802-865 that parses customize.yaml files — the Task 3 helper should REUSE that existing parser rather than introduce a second YAML dependency.
177
+ - **STAGE:CUSTOMIZE invocation point:** `lib/bmad.js:406-418` is the canonical place to hook the Task 3 helper. Preserve the existing console.log output for unmodified personas.
178
+ - **Test framework:** node's built-in test runner + `os.tmpdir()` + `fs.mkdtempSync` per-test (mirror `test/profile.test.js` — Story 21.1 pattern).
179
+
180
+ ### NFR citations (explicit)
181
+
182
+ - **NFR44** — epics.md:261 ("On-prem profile guardrails must not regress standard profile — when profile=standard, no on-prem-specific instructions appear in any generated file"). Story 21.7 contract: AC #3, AC #9.
183
+ - **NFR46** — epics.md:263 ("Per-tool template stamping is idempotent — re-running install with the same profile produces byte-identical content within marker blocks"). Extended to customize output under AC #8.
184
+ - **NFR47** — epics.md:264 ("BMAD planning-mode file restrictions in `.roomodes` enforced at the application layer (Roo Code `FileRestrictionError`)"). Non-regression only: AC #11.
185
+ - **NFR18** — epics.md:223 ("OpenCode JSON instruction injection must not corrupt existing `opencode.json` configuration — additive-only"). Non-regression only: AC #12.
186
+
187
+ ### Persona prefix text — authoring guidance (not prescriptive)
188
+
189
+ The epic intentionally leaves the exact wording to the implementing dev. Seeds from the epic (AC #1 / AC #2 wording):
190
+
191
+ - Planning: `"/no_think You are in a planning phase — respond in text for questions; create files only when explicitly asked."` (adjust wording; `/no_think` token MUST appear verbatim per the on-prem-only signal used for NFR44 assertions in Story 21.6).
192
+ - Implementation: `"Think carefully before writing code. Always reference the story you are implementing before making edits."` (no `/no_think`; reasoning ON is the implementation default per epic AC #2 and the vLLM guidance in Story 21.8).
193
+
194
+ ## Dependencies
195
+
196
+ ### Upstream (blocking)
197
+
198
+ - **Story 21.1 (done)** — `lib/profile.js::getProfile(projectRoot)` is the input. Verified at `lib/profile.js:29-43`. No API change requested.
199
+
200
+ ### Upstream (recommended sequencing — not strictly blocking)
201
+
202
+ - **Story 21.6 (Ready)** — Persona prefix content references the same `/no_think` token that Story 21.6 stamps into the per-tool templates. Shipping 21.7 BEFORE 21.6 is safe; shipping them adjacent is preferred so on-prem installs get a consistent `/no_think` signal in both the per-tool rules and the persona system prompts. Per epic execution order (`sprint-status.yaml:113`: `21.1 → 21.2 → (21.3 + 21.4 + 21.5 in parallel) → 21.6 → 21.10 → 21.7 → 21.8 → 21.9 → 21.11`), Story 21.7 is scheduled AFTER 21.6 and 21.10.
203
+
204
+ ### Downstream (consumers of this story's surface)
205
+
206
+ - **Story 21.8** — vLLM deployment doc + README on-prem section. Documents the `/no_think` per-phase sampling guidance that maps 1:1 to this story's persona prefix dichotomy. Recommend a content-consistency test: the prefix text authored here should align with the per-phase sampling table in `docs/deployment/vllm-nemotron.md` (new, Story 21.8).
207
+ - **Story 21.9** — Integration tests covering (a) standard profile produces NO on-prem-specific strings across every surface INCLUDING `_bmad/_config/agents/*.customize.yaml`, (b) on-prem produces the prefix in every planning persona. Testing section 7.3–7.5 of this story are unit-level subsets; Story 21.9 adds cross-surface integration.
208
+ - **Story 21.10 (Profile Reconfigure)** — Re-stamps profile-dependent artifacts on profile flip. The Task 3 helper (Branch A or B) MUST be re-invokable cleanly on reconfigure. Idempotency AC #8 covers this implicitly.
209
+ - **Story 21.11 (Profile Uninstall)** — On `uninstall --profile-artifacts`, the on-prem prefix content in `_bmad/_config/agents/*.customize.yaml` must be removable. If Branch A is chosen, uninstall re-runs the STAGE:CUSTOMIZE copy (restoring the standard variant). If Branch B is chosen, same — uninstall emits the standard variant. Covered by Story 21.11's scope, not this story.
210
+
211
+ ## Testing
212
+
213
+ **Framework and isolation:** Match `test/profile.test.js` (Story 21.1) — node's built-in test runner, `os.tmpdir()` + `fs.mkdtempSync` per-test tmp project root, never mutate the repo's own `lib/bmad-customize/` files. Use `setProfile(tmpRoot, 'standard' | 'on-prem')` from the real `lib/profile.js`. Do NOT stub `lib/bmad.js`; exercise the real STAGE:CUSTOMIZE path against a tmp project.
214
+
215
+ New test file: `test/bmad-persona-phase-prefix.test.js` (new).
216
+
217
+ **Unit tests:**
218
+
219
+ - 7.1 `lib/bmad-customize/bmm-pm.customize.yaml` contains `phase: planning` and a non-empty `on_prem_phase_prefix` string. Repeat for each persona in AC #1 (7 tests) + AC #2 (2 tests, conditional on Open-question resolution).
220
+ - 7.2 Each planning persona's `on_prem_phase_prefix` contains the literal `/no_think` token (AC #1).
221
+ - 7.3 Each implementation persona's `on_prem_phase_prefix` does NOT contain `/no_think` (AC #2 — reasoning ON).
222
+ - 7.4 Task 3 helper (Branch A or B — whichever is chosen): given `profile === 'standard'`, the deployed file contains NO `/no_think`, NO `phase:` key, NO `on_prem_phase_prefix:` key (AC #3, AC #9).
223
+ - 7.5 Task 3 helper: given `profile === 'on-prem'`, the deployed file's `critical_actions[0]` contains the authored prefix text, `phase:` / `on_prem_phase_prefix:` keys are stripped, and all pre-existing `critical_actions` entries are preserved in order (AC #7).
224
+
225
+ **Integration tests (within this story — cross-surface lives in 21.9):**
226
+
227
+ - 7.6 End-to-end standard-profile install against a tmp project (via the public `lib/bmad.js` install entry point): deployed `_bmad/_config/agents/bmm-pm.customize.yaml` is byte-identical to the same file deployed without Epic 21 (use a snapshot golden file captured from pre-Epic-21 HEAD). Repeat for each persona in AC #1 (7 assertions).
228
+ - 7.7 End-to-end on-prem install: deployed `_bmad/_config/agents/bmm-pm.customize.yaml` has the on-prem prefix as the first entry in `critical_actions`. Repeat for each persona.
229
+ - 7.8 Idempotency (AC #8 / NFR46): two consecutive on-prem installs produce byte-identical deployed files for every persona.
230
+ - 7.9 Profile-switch is OUT OF SCOPE here — do not test standard→on-prem flip (Story 21.10).
231
+ - 7.10 NFR47 non-regression (AC #11): after an on-prem install, `.roomodes` byte-identity with a Story 21.6-only install (diff current install's `.roomodes` against a snapshot captured before Task 3 runs). Thin assertion — Story 21.9 owns the comprehensive version.
232
+ - 7.11 NFR18 non-regression (AC #12): `opencode.json::instructions[]` is untouched by an on-prem-with-21.7 install versus a baseline 21.6 install.
233
+
234
+ **Test data isolation:** Every test uses `fs.mkdtempSync(path.join(os.tmpdir(), 'ma-21-7-'))` for the project root. Use real `lib/bmad-customize/` on disk (do NOT stub YAML parsing). Clean up tmp dirs in a `t.after`. Capture pre-Epic-21 golden files via `git show <pre-Epic-21-sha>:lib/bmad-customize/<file>` into `test/fixtures/21-7/` (new fixtures dir).
235
+
236
+ **Coverage note:** Story 21.9 adds the cross-tool integration (standard-profile NFR44 absence of `/no_think` across EVERY generated surface including `_bmad/_config/agents/`). Do not duplicate that here. This story's tests are scoped to the persona-customize surface.
237
+
238
+ ## Out of Scope
239
+
240
+ - Universal per-tool instruction block (Story 21.2 — `composeInstructionBlock`).
241
+ - Per-tool on-prem layered guardrails (Story 21.6 — `instruction-block-onprem.template.md`, `.roomodes` / `AGENTS.md` / `.clinerules` injection).
242
+ - `.roomodes` authorship and `fileRegex` restrictions (Story 21.3 — not touched here).
243
+ - `AGENTS.md` authorship (Story 21.4 — not touched here).
244
+ - `.clinerules` authorship (Story 21.5 — not touched here).
245
+ - vLLM deployment documentation and README on-prem section (Story 21.8).
246
+ - Cross-tool NFR44/NFR46 integration tests (Story 21.9 — this story's tests scope to persona customize surface only).
247
+ - Profile-reconfigure flow (Story 21.10 — re-stamping on profile flip).
248
+ - Profile-uninstall flow (Story 21.11 — removing on-prem prefixes on uninstall).
249
+ - `phase: mixed` enum value (see Open question under AC #5 — follow-up story).
250
+ - Other persona files in `lib/bmad-customize/` not enumerated in AC #1 / AC #2 (e.g., `bmm-bmad-master`) and ALL IDE-agent customizations in `lib/bmad-customizations/*.customize.yaml` (AC #10).
251
+ - Any modification to upstream `bmad-method` source — prohibited by BMAD built-in override policy.
252
+ - `.claude/skills/` edits — prohibited per user's durable memory.
253
+ - Manifest version bump — already at 1.2.0 (Story 21.1).
122
254
 
123
255
  ## Change Log
124
- - 2026-04-14: Story created (Epic 21, Story 21.7)
125
- - 2026-04-14: Extended phase enum to `{planning, implementation, mixed}` via new ACs #8, #9, #10 (Finding #11, corrective plan step 3). Reassigned SM Bob, SQA Gad, Analyst Mary to `mixed`. AC #1's binary classification is SUPERSEDED by AC #8 but left in place to preserve the historical decision trail. Added Epic 15 validator-extension prerequisite note to Dev Notes.
126
- - 2026-04-14: Clarified Epic 15 prerequisite — customize-loader lives upstream in BMAD, not in ma-agents. Phase enum extension implemented via BMAD-built-in override policy (extension pattern, not upstream PR). Closes corrective-plan step 6 dependency-wiring audit.
256
+
257
+ - 2026-04-15: Story created (Epic 21, Story 21.7). ACs refined with explicit (gap-fill) flags where the epic required operationalization. Three Open questions raised inline rather than pre-resolved: (a) `phase: mixed` enum extension, (b) upstream loader two-branch decision (lenient Branch A vs strict Branch B per epics.md:4231 the implementing dev probes upstream in Task 1), (c) missing `bmm-analyst` and `bmm-quick-flow-solo-dev` authoring files. NFR44/NFR46/NFR47/NFR18 citations explicit in Dev Notes. Verified source-tree surface table distinguishes existing vs (new) paths. Dependencies split upstream/downstream. Testing section covers unit (7.1–7.5) and integration (7.6–7.11). Status set to Ready.
258
+ - 2026-04-15 (adversarial-review resolution): Closed P1 #6Tasks 2.8/2.9 conditional phrasing removed. Decision: create `lib/bmad-customize/bmm-analyst.customize.yaml` and `lib/bmad-customize/bmm-quick-flow-solo-dev.customize.yaml` unconditionally within this story (option a). Rationale: verified `ls lib/bmad-customize/` — neither file exists, but authoring shape is trivial (mirrors `bmm-pm` / `bmm-dev`) so creation is not blocked. Open question block for persona source files converted to a Resolved block referencing the decision. Epic 15 customize-loader two-branch Open Question (AC #6) retained as-is — genuine upstream probe per epics.md:4231. Canonical terminology (composer/merger/stamper) audited — no "injection function" / "marker-injection" occurrences present in this file, so no terminology replacements required. All Tasks now unconditional; Status remains Ready.