ma-agents 3.5.3 → 3.5.5

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 (82) hide show
  1. package/_bmad-output/implementation-artifacts/21-1-install-time-profile-prompt.md +181 -0
  2. package/_bmad-output/implementation-artifacts/21-10-profile-reconfigure.md +137 -0
  3. package/_bmad-output/implementation-artifacts/21-11-profile-uninstall.md +149 -0
  4. package/_bmad-output/implementation-artifacts/21-2-universal-instruction-block-expansion.md +98 -0
  5. package/_bmad-output/implementation-artifacts/21-3-roomodes-template-bmad-modes.md +106 -0
  6. package/_bmad-output/implementation-artifacts/21-4-agents-md-template-opencode.md +86 -0
  7. package/_bmad-output/implementation-artifacts/21-5-clinerules-template-extension.md +82 -0
  8. package/_bmad-output/implementation-artifacts/21-6-onprem-layered-guardrails.md +112 -0
  9. package/_bmad-output/implementation-artifacts/21-7-bmad-persona-phase-prefix.md +126 -0
  10. package/_bmad-output/implementation-artifacts/21-8-vllm-reference-doc-readme.md +100 -0
  11. package/_bmad-output/implementation-artifacts/21-9-tests-validation.md +97 -0
  12. package/_bmad-output/implementation-artifacts/bug-experimentalwarning-about-commonjs-loading-es-module-during-install.md +57 -0
  13. package/_bmad-output/implementation-artifacts/sprint-status.yaml +43 -1
  14. package/_bmad-output/methodology/BMAD_AI_Development_Training.pptx +0 -0
  15. package/_bmad-output/methodology/version.json +1 -1
  16. package/_bmad-output/planning-artifacts/architecture.md +52 -0
  17. package/_bmad-output/planning-artifacts/epics.md +397 -0
  18. package/_bmad-output/planning-artifacts/prd.md +46 -1
  19. package/bin/cli.js +109 -1
  20. package/docs/BMAD_AI_Development_Training.pptx +0 -0
  21. package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
  22. package/lib/bmad-cache/bmb/_git_preserved/logs/HEAD +1 -1
  23. package/lib/bmad-cache/bmb/_git_preserved/logs/refs/heads/main +1 -1
  24. package/lib/bmad-cache/bmb/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
  25. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-554778ad4e7254827618ebd2497c3f4bce9054a4.idx +0 -0
  26. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/{pack-4b395d030ca386fc5748f1b670dcf8c0ef41c94c.pack → pack-554778ad4e7254827618ebd2497c3f4bce9054a4.pack} +0 -0
  27. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-554778ad4e7254827618ebd2497c3f4bce9054a4.rev +0 -0
  28. package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
  29. package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
  30. package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
  31. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py +7 -0
  32. package/lib/bmad-cache/cache-manifest.json +5 -5
  33. package/lib/bmad-cache/tea/_git_preserved/index +0 -0
  34. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.idx +0 -0
  35. package/lib/bmad-cache/tea/_git_preserved/objects/pack/{pack-c79805bb3fee27fa6d8c612a971af7fc86fc80e1.pack → pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.pack} +0 -0
  36. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.rev +0 -0
  37. package/lib/bmad-cache/tea/_git_preserved/packed-refs +1 -1
  38. package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
  39. package/lib/bmad-cache/tea/_git_preserved/refs/tags/v1.10.0 +1 -0
  40. package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
  41. package/lib/bmad-cache/tea/docs/explanation/tea-overview.md +2 -2
  42. package/lib/bmad-cache/tea/docs/how-to/workflows/run-atdd.md +28 -30
  43. package/lib/bmad-cache/tea/docs/reference/commands.md +4 -4
  44. package/lib/bmad-cache/tea/docs/reference/configuration.md +1 -1
  45. package/lib/bmad-cache/tea/package-lock.json +2 -2
  46. package/lib/bmad-cache/tea/package.json +1 -1
  47. package/lib/bmad-cache/tea/src/module-help.csv +1 -1
  48. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/SKILL.md +1 -1
  49. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/atdd-checklist-template.md +50 -27
  50. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/checklist.md +18 -17
  51. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/instructions.md +1 -1
  52. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01-preflight-and-context.md +21 -3
  53. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01b-resume.md +1 -1
  54. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-02-generation-mode.md +1 -1
  55. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-03-test-strategy.md +1 -1
  56. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04-generate-tests.md +20 -19
  57. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04a-subagent-api-failing.md +13 -13
  58. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04b-subagent-e2e-failing.md +13 -13
  59. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04c-aggregate.md +42 -18
  60. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-05-validate-and-complete.md +12 -3
  61. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow-plan.md +2 -2
  62. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow.md +2 -2
  63. package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow.yaml +2 -2
  64. package/lib/bmad.js +25 -4
  65. package/lib/installer.js +2 -1
  66. package/lib/methodology/BMAD_AI_Development_Training.pptx +0 -0
  67. package/lib/methodology/version.json +1 -1
  68. package/lib/profile.js +107 -0
  69. package/lib/warning-filter.js +245 -0
  70. package/package.json +2 -2
  71. package/test/experimental-warning.test.js +314 -0
  72. package/test/fixtures/README.md +74 -0
  73. package/test/fixtures/empty-project/README.md +5 -0
  74. package/test/fixtures/empty-project/package.json +5 -0
  75. package/test/fixtures/onprem-profile-baseline/.gitkeep +2 -0
  76. package/test/fixtures/standard-profile-baseline/.gitkeep +2 -0
  77. package/test/onprem-injection.test.js +48 -0
  78. package/test/profile.test.js +301 -0
  79. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-4b395d030ca386fc5748f1b670dcf8c0ef41c94c.idx +0 -0
  80. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-4b395d030ca386fc5748f1b670dcf8c0ef41c94c.rev +0 -0
  81. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-c79805bb3fee27fa6d8c612a971af7fc86fc80e1.idx +0 -0
  82. package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-c79805bb3fee27fa6d8c612a971af7fc86fc80e1.rev +0 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: 'step-04c-aggregate'
3
3
  description: 'Aggregate subagent outputs and complete ATDD test infrastructure'
4
- outputFile: '{test_artifacts}/atdd-checklist-{story_id}.md'
4
+ outputFile: '{test_artifacts}/atdd-checklist-{story_key}.md'
5
5
  nextStepFile: './step-05-validate-and-complete.md'
6
6
  ---
7
7
 
@@ -9,7 +9,7 @@ nextStepFile: './step-05-validate-and-complete.md'
9
9
 
10
10
  ## STEP GOAL
11
11
 
12
- Read outputs from parallel subagents (API + E2E failing test generation), aggregate results, verify TDD red phase compliance, and create supporting infrastructure.
12
+ Read outputs from parallel subagents (API + E2E red-phase test generation), aggregate results, verify TDD red phase compliance, and create supporting infrastructure.
13
13
 
14
14
  ---
15
15
 
@@ -22,7 +22,7 @@ Read outputs from parallel subagents (API + E2E failing test generation), aggreg
22
22
  - ✅ Generate shared fixtures based on fixture needs
23
23
  - ✅ Write all generated test files to disk
24
24
  - ❌ Do NOT remove test.skip() (that's done after feature implementation)
25
- - ❌ Do NOT run tests yet (that's step 5 - verify they fail)
25
+ - ❌ Do NOT run tests yet (that's step 5 - verify scaffolds and optional RED activation)
26
26
 
27
27
  ---
28
28
 
@@ -187,7 +187,7 @@ Note: More complete fixtures will be needed when moving to green phase.
187
187
 
188
188
  ## TDD Red Phase (Current)
189
189
 
190
- Failing tests generated
190
+ Red-phase test scaffolds generated
191
191
 
192
192
  - API Tests: {api_test_count} tests (all skipped)
193
193
  - E2E Tests: {e2e_test_count} tests (all skipped)
@@ -196,14 +196,14 @@ Note: More complete fixtures will be needed when moving to green phase.
196
196
 
197
197
  {list all acceptance criteria with test coverage}
198
198
 
199
- ## Next Steps (TDD Green Phase)
199
+ ## Next Steps (Task-by-Task Activation)
200
200
 
201
- After implementing the feature:
201
+ During implementation of each task:
202
202
 
203
- 1. Remove `test.skip()` from all test files
203
+ 1. Remove `test.skip()` from the current test file or scenario
204
204
  2. Run tests: `npm test`
205
- 3. Verify tests PASS (green phase)
206
- 4. If any tests fail:
205
+ 3. Verify the activated test fails first, then passes after implementation (green phase)
206
+ 4. If any activated tests still fail unexpectedly:
207
207
  - Either fix implementation (feature bug)
208
208
  - Or fix test (test bug)
209
209
  5. Commit passing tests
@@ -220,9 +220,21 @@ UI components to implement:
220
220
  **Save checklist:**
221
221
 
222
222
  ```javascript
223
- fs.writeFileSync(`{test_artifacts}/atdd-checklist-{story-id}.md`, checklistContent, 'utf8');
223
+ fs.writeFileSync(`{test_artifacts}/atdd-checklist-{story_key}.md`, checklistContent, 'utf8');
224
224
  ```
225
225
 
226
+ **If `{story_file}` exists and is writable, attempt to link artifacts back into the story:**
227
+
228
+ - Add or update a `### ATDD Artifacts` subsection under `## Dev Notes`
229
+ - Record:
230
+ - `Checklist: {test_artifacts}/atdd-checklist-{story_key}.md`
231
+ - `API tests: {api_test_file_path}` when present
232
+ - `E2E tests: {e2e_test_file_path}` when present
233
+ - `Component tests: {component_test_file_path}` when present
234
+ - Preserve all other story content verbatim
235
+ - The checklist template already contains the manual handoff instructions if story linking is not possible
236
+ - If the story file cannot be updated safely, continue without failing the workflow and keep the checklist's manual handoff instructions intact
237
+
226
238
  ---
227
239
 
228
240
  ### 7. Calculate Summary Statistics
@@ -279,14 +291,14 @@ Display to user:
279
291
  ```
280
292
  ✅ ATDD Test Generation Complete (TDD RED PHASE)
281
293
 
282
- 🔴 TDD Red Phase: Failing Tests Generated
294
+ 🔴 TDD Red Phase: Test Scaffolds Generated
283
295
 
284
296
  📊 Summary:
285
297
  - Total Tests: {total_tests} (all with test.skip())
286
298
  - API Tests: {api_tests} (RED)
287
299
  - E2E Tests: {e2e_tests} (RED)
288
300
  - Fixtures Created: {fixtures_created}
289
- - All tests will FAIL until feature implemented
301
+ - Activated tests will FAIL until feature is implemented
290
302
 
291
303
  ✅ Acceptance Criteria Coverage:
292
304
  {list all covered criteria}
@@ -297,15 +309,16 @@ Display to user:
297
309
  - tests/api/[feature].spec.ts (with test.skip())
298
310
  - tests/e2e/[feature].spec.ts (with test.skip())
299
311
  - tests/fixtures/test-data.ts
300
- - {test_artifacts}/atdd-checklist-{story-id}.md
312
+ - {test_artifacts}/atdd-checklist-{story_key}.md
301
313
 
302
314
  📝 Next Steps:
303
- 1. Implement the feature
304
- 2. Remove test.skip() from tests
305
- 3. Run tests verify PASS (green phase)
306
- 4. Commit passing tests
315
+ 1. Link ATDD artifacts into the story file if available
316
+ 2. Implement the feature
317
+ 3. Remove test.skip() from the tests for the current task
318
+ 4. Run activated tests → verify they FAIL before implementation, then PASS after implementation
319
+ 5. Commit passing tests
307
320
 
308
- ✅ Ready for validation (Step 5 - verify tests fail as expected)
321
+ ✅ Ready for validation (Step 5 - verify red-phase scaffolds and handoff metadata)
309
322
  ```
310
323
 
311
324
  ---
@@ -334,6 +347,11 @@ Proceed to Step 5 when:
334
347
  stepsCompleted: ['step-04c-aggregate']
335
348
  lastStep: 'step-04c-aggregate'
336
349
  lastSaved: '{date}'
350
+ storyId: '{story_id}'
351
+ storyKey: '{story_key}'
352
+ storyFile: '{story_file}'
353
+ atddChecklistPath: '{outputFile}'
354
+ generatedTestFiles: []
337
355
  ---
338
356
  ```
339
357
 
@@ -343,6 +361,11 @@ Proceed to Step 5 when:
343
361
  - Add `'step-04c-aggregate'` to `stepsCompleted` array (only if not already present)
344
362
  - Set `lastStep: 'step-04c-aggregate'`
345
363
  - Set `lastSaved: '{date}'`
364
+ - Set `storyId` to `{story_id}`
365
+ - Set `storyKey` to `{story_key}`
366
+ - Set `storyFile` to `{story_file}`
367
+ - Set `atddChecklistPath` to `{outputFile}`
368
+ - Set `generatedTestFiles` deterministically to the list of present test paths in this order: API, E2E, Component (omit blanks / N/A values)
346
369
  - Append this step's output to the appropriate section.
347
370
 
348
371
  Load next step: `{nextStepFile}`
@@ -358,6 +381,7 @@ Load next step: `{nextStepFile}`
358
381
  - All tests assert expected behavior (not placeholders)
359
382
  - All test files written to disk
360
383
  - ATDD checklist generated
384
+ - Story metadata and handoff paths captured in checklist frontmatter
361
385
 
362
386
  ### ❌ SYSTEM FAILURE:
363
387
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: 'step-05-validate-and-complete'
3
3
  description: 'Validate ATDD outputs and summarize'
4
- outputFile: '{test_artifacts}/atdd-checklist-{story_id}.md'
4
+ outputFile: '{test_artifacts}/atdd-checklist-{story_key}.md'
5
5
  ---
6
6
 
7
7
  # Step 5: Validate & Complete
@@ -42,7 +42,8 @@ Use `checklist.md` to validate:
42
42
  - Prerequisites satisfied
43
43
  - Test files created correctly
44
44
  - Checklist matches acceptance criteria
45
- - Tests are designed to fail before implementation
45
+ - Tests are generated as red-phase scaffolds and marked with `test.skip()`
46
+ - Story metadata and handoff paths are captured for downstream workflows
46
47
  - [ ] CLI sessions cleaned up (no orphaned browsers)
47
48
  - [ ] Temp artifacts stored in `{test_artifacts}/` not random locations
48
49
 
@@ -67,8 +68,9 @@ Report:
67
68
 
68
69
  - Test files created
69
70
  - Checklist output path
71
+ - Story key / story file handoff path
70
72
  - Key risks or assumptions
71
- - Next recommended workflow (e.g., implementation or `automate`)
73
+ - Next recommended workflow (usually `dev-story`; `automate` comes after implementation)
72
74
 
73
75
  ---
74
76
 
@@ -83,6 +85,11 @@ Report:
83
85
  stepsCompleted: ['step-05-validate-and-complete']
84
86
  lastStep: 'step-05-validate-and-complete'
85
87
  lastSaved: '{date}'
88
+ storyId: '{story_id}'
89
+ storyKey: '{story_key}'
90
+ storyFile: '{story_file}'
91
+ atddChecklistPath: '{outputFile}'
92
+ generatedTestFiles: []
86
93
  ---
87
94
  ```
88
95
 
@@ -92,6 +99,8 @@ Report:
92
99
  - Add `'step-05-validate-and-complete'` to `stepsCompleted` array (only if not already present)
93
100
  - Set `lastStep: 'step-05-validate-and-complete'`
94
101
  - Set `lastSaved: '{date}'`
102
+ - Ensure `storyId`, `storyKey`, `storyFile`, and `atddChecklistPath` are present and populated
103
+ - Ensure `generatedTestFiles` remains populated with the deterministic list of present generated test paths
95
104
  - Append this step's output to the appropriate section.
96
105
 
97
106
  ## 🚨 SYSTEM SUCCESS/FAILURE METRICS:
@@ -16,6 +16,6 @@
16
16
  - step-02-apply-edit.md
17
17
 
18
18
  ## Outputs
19
- - {test_artifacts}/atdd-checklist-{story_id}.md
19
+ - {test_artifacts}/atdd-checklist-{story_key}.md
20
20
 
21
- - Failing acceptance tests under {project-root}/tests
21
+ - Red-phase acceptance test scaffolds under {project-root}/tests
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: bmad-testarch-atdd
3
- description: Generate failing acceptance tests using TDD cycle. Use when user says 'lets write acceptance tests' or 'I want to do ATDD'
3
+ description: Generate red-phase acceptance test scaffolds using TDD cycle. Use when user says 'lets write acceptance tests' or 'I want to do ATDD'
4
4
  web_bundle: true
5
5
  ---
6
6
 
7
7
  # Acceptance Test-Driven Development (ATDD)
8
8
 
9
- **Goal:** Generate failing acceptance tests before implementation using TDD red-green-refactor cycle
9
+ **Goal:** Generate red-phase acceptance test scaffolds before implementation using TDD red-green-refactor cycle
10
10
 
11
11
  **Role:** You are the Master Test Architect.
12
12
 
@@ -1,7 +1,7 @@
1
1
  # Test Architect workflow: bmad-testarch-atdd
2
2
  name: bmad-testarch-atdd
3
3
  # prettier-ignore
4
- description: 'Generate failing acceptance tests using TDD cycle. Use when the user says "lets write acceptance tests" or "I want to do ATDD"'
4
+ description: 'Generate red-phase acceptance test scaffolds using TDD cycle. Use when the user says "lets write acceptance tests" or "I want to do ATDD"'
5
5
 
6
6
  # Critical variables from config
7
7
  config_source: "{project-root}/_bmad/tea/config.yaml"
@@ -23,7 +23,7 @@ variables:
23
23
  test_dir: "{project-root}/tests" # Root test directory
24
24
 
25
25
  # Output configuration
26
- default_output_file: "{test_artifacts}/atdd-checklist-{story_id}.md"
26
+ default_output_file: "{test_artifacts}/atdd-checklist-{story_key}.md"
27
27
 
28
28
  # Required tools
29
29
  required_tools:
package/lib/bmad.js CHANGED
@@ -4,6 +4,27 @@ const os = require('os');
4
4
  const { execSync } = require('child_process');
5
5
  const chalk = require('chalk');
6
6
  const yaml = require('yaml');
7
+ const { withExperimentalWarningSuppressed } = require('./warning-filter');
8
+
9
+ /**
10
+ * Build the env object passed to the bmad-method child spawn.
11
+ * Extends parent env with GIT_TERMINAL_PROMPT=0 and a NODE_OPTIONS
12
+ * value that silences the ExperimentalWarning about CJS require() of
13
+ * an ES Module (Bug A). Callers that need a different NODE_OPTIONS
14
+ * can merge after this call.
15
+ *
16
+ * @param {NodeJS.ProcessEnv} [parentEnv=process.env]
17
+ * @returns {NodeJS.ProcessEnv}
18
+ */
19
+ function buildChildSpawnEnv(parentEnv = process.env) {
20
+ return {
21
+ ...parentEnv,
22
+ GIT_TERMINAL_PROMPT: '0',
23
+ // Bug A — keep the bmad-method child as quiet about CJS-require-ESM
24
+ // as the parent. Preserves any NODE_OPTIONS the user already set.
25
+ NODE_OPTIONS: withExperimentalWarningSuppressed(parentEnv.NODE_OPTIONS),
26
+ };
27
+ }
7
28
 
8
29
  const BMAD_DIR = '_bmad';
9
30
  const CONFIG_DIR = path.join(BMAD_DIR, '_config', 'agents');
@@ -122,7 +143,7 @@ async function installBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = p
122
143
 
123
144
  console.log(chalk.gray(` Running: ${command}`));
124
145
  try {
125
- runCommand(command, { cwd: projectRoot, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
146
+ runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
126
147
  await deployMethodology(projectRoot, force);
127
148
  return true;
128
149
  } catch (error) {
@@ -157,7 +178,7 @@ async function runMigration(modules, tools, projectRoot, force, { userName, comm
157
178
 
158
179
  console.log(chalk.gray(` Running: ${command}`));
159
180
  try {
160
- runCommand(command, { cwd: projectRoot, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
181
+ runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
161
182
  } catch (error) {
162
183
  // Rollback on failure
163
184
  console.error(chalk.red(` BMAD update failed: ${error.message}`));
@@ -284,7 +305,7 @@ async function updateBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = pr
284
305
 
285
306
  console.log(chalk.gray(` Running: ${command}`));
286
307
  try {
287
- runCommand(command, { cwd: projectRoot, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
308
+ runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
288
309
  await deployMethodology(projectRoot, force);
289
310
  return true;
290
311
  } catch (error) {
@@ -361,7 +382,7 @@ async function applyCustomizations(projectRoot = process.cwd(), modules = ['bmm'
361
382
 
362
383
  console.log(chalk.gray(` Running: ${command}`));
363
384
  try {
364
- runCommand(command, { cwd: projectRoot, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
385
+ runCommand(command, { cwd: projectRoot, env: buildChildSpawnEnv() });
365
386
  } catch (error) {
366
387
  console.error(chalk.red(` BMAD recompile failed: ${error.message}`));
367
388
  }
package/lib/installer.js CHANGED
@@ -5,7 +5,7 @@ const prompts = require('prompts');
5
5
  const { getAgent, getAllAgents } = require('./agents');
6
6
 
7
7
  const MANIFEST_FILE = '.ma-agents.json';
8
- const MANIFEST_VERSION = '1.1.0';
8
+ const MANIFEST_VERSION = '1.2.0';
9
9
  const MA_AGENTS_SOURCE = 'ma-agents';
10
10
  const TEMPLATE_PATH = path.join(__dirname, 'templates', 'project-context.template.md');
11
11
 
@@ -1053,6 +1053,7 @@ module.exports = {
1053
1053
  uninstallSkill,
1054
1054
  getStatus,
1055
1055
  readManifest,
1056
+ ensureManifest,
1056
1057
  getInstalledSkillInfo,
1057
1058
  getManifestAgents,
1058
1059
  compareSemver,
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.0",
2
+ "version": "1.1.0",
3
3
  "description": "BMAD-METHOD AI Development Training Presentation",
4
4
  "files": [
5
5
  "BMAD_AI_Development_Training.pptx"
package/lib/profile.js ADDED
@@ -0,0 +1,107 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Story 21.1 — Install-time profile persistence and resolution.
5
+ *
6
+ * Public API (exactly three functions):
7
+ * getProfile(projectRoot) -> "on-prem" | "standard" | undefined
8
+ * setProfile(projectRoot, value) -> void (persists to .ma-agents.json)
9
+ * resolveProfile({ persisted, yesMode }) -> resolved value | null (pure, no I/O)
10
+ *
11
+ * NFR44: setProfile is the ONLY mutator of the "profile" field.
12
+ * Back-compat: manifests at 1.1.0 without "profile" are read without error;
13
+ * getProfile returns undefined for missing field.
14
+ * setProfile migrates 1.1.0 → 1.2.0 on write (profile field is
15
+ * 1.2.0-only; writing it onto a 1.1.0 manifest would be schema drift).
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ const MANIFEST_FILE = '.ma-agents.json';
22
+ const VALID_PROFILES = ['on-prem', 'standard'];
23
+
24
+ /**
25
+ * Reads the persisted profile from .ma-agents.json at the given project root.
26
+ * Returns undefined if the file does not exist, is malformed, or the "profile"
27
+ * field is absent. Does NOT throw on missing file.
28
+ */
29
+ function getProfile(projectRoot) {
30
+ const manifestPath = path.join(projectRoot, MANIFEST_FILE);
31
+ if (!fs.existsSync(manifestPath)) {
32
+ return undefined;
33
+ }
34
+ let manifest;
35
+ try {
36
+ manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
37
+ } catch {
38
+ return undefined;
39
+ }
40
+ if (!manifest || typeof manifest !== 'object') return undefined;
41
+ if (!Object.prototype.hasOwnProperty.call(manifest, 'profile')) return undefined;
42
+ return manifest.profile;
43
+ }
44
+
45
+ /**
46
+ * Persists the profile value into .ma-agents.json, preserving all other fields.
47
+ * Creates the file via the standard ensureManifest bootstrap path if absent.
48
+ * Throws an Error naming the bad value if `value` is not "on-prem" or "standard".
49
+ *
50
+ * Migration: If the loaded manifest is at manifestVersion 1.1.0 (or missing the
51
+ * version field entirely), setProfile bumps it to 1.2.0 before writing, because
52
+ * the "profile" field is 1.2.0-only. A one-time log line is emitted to stdout
53
+ * describing the migration. Manifests already at 1.2.0 or higher are left alone.
54
+ */
55
+ function setProfile(projectRoot, value) {
56
+ if (!VALID_PROFILES.includes(value)) {
57
+ throw new Error(
58
+ `Invalid profile value: ${JSON.stringify(value)}. Expected one of: ${VALID_PROFILES.join(', ')}`
59
+ );
60
+ }
61
+
62
+ const manifestPath = path.join(projectRoot, MANIFEST_FILE);
63
+
64
+ let manifest;
65
+ if (fs.existsSync(manifestPath)) {
66
+ try {
67
+ manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
68
+ } catch {
69
+ manifest = null;
70
+ }
71
+ }
72
+
73
+ if (!manifest || typeof manifest !== 'object') {
74
+ // Bootstrap via the standard schema (mirrors lib/installer.js ensureManifest shape).
75
+ // Require lazily to avoid potential circular-import pitfalls at module load.
76
+ const { ensureManifest } = require('./installer');
77
+ manifest = ensureManifest(projectRoot, null, 'project');
78
+ }
79
+
80
+ // Migrate 1.1.0 (or missing version) → 1.2.0, since the "profile" field is 1.2.0-only.
81
+ // Writing it onto a 1.1.0 manifest would be schema drift. Do not downgrade manifests
82
+ // that are already at 1.2.0 or higher.
83
+ const currentVersion = manifest.manifestVersion;
84
+ if (currentVersion === '1.1.0') {
85
+ manifest.manifestVersion = '1.2.0';
86
+ console.log('Migrated .ma-agents.json manifestVersion 1.1.0 → 1.2.0');
87
+ } else if (!currentVersion) {
88
+ manifest.manifestVersion = '1.2.0';
89
+ console.log('Migrated .ma-agents.json manifestVersion (none) → 1.2.0');
90
+ }
91
+
92
+ manifest.profile = value;
93
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
94
+ }
95
+
96
+ /**
97
+ * Pure resolver — performs NO I/O.
98
+ * Precedence: persisted > (yesMode ? 'standard' : null).
99
+ * Returns null when nothing is set and yesMode is false (caller must prompt).
100
+ */
101
+ function resolveProfile({ persisted, yesMode } = {}) {
102
+ if (persisted) return persisted;
103
+ if (yesMode === true) return 'standard';
104
+ return null;
105
+ }
106
+
107
+ module.exports = { getProfile, setProfile, resolveProfile };