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.
- package/_bmad-output/implementation-artifacts/21-1-install-time-profile-prompt.md +181 -0
- package/_bmad-output/implementation-artifacts/21-10-profile-reconfigure.md +137 -0
- package/_bmad-output/implementation-artifacts/21-11-profile-uninstall.md +149 -0
- package/_bmad-output/implementation-artifacts/21-2-universal-instruction-block-expansion.md +98 -0
- package/_bmad-output/implementation-artifacts/21-3-roomodes-template-bmad-modes.md +106 -0
- package/_bmad-output/implementation-artifacts/21-4-agents-md-template-opencode.md +86 -0
- package/_bmad-output/implementation-artifacts/21-5-clinerules-template-extension.md +82 -0
- package/_bmad-output/implementation-artifacts/21-6-onprem-layered-guardrails.md +112 -0
- package/_bmad-output/implementation-artifacts/21-7-bmad-persona-phase-prefix.md +126 -0
- package/_bmad-output/implementation-artifacts/21-8-vllm-reference-doc-readme.md +100 -0
- package/_bmad-output/implementation-artifacts/21-9-tests-validation.md +97 -0
- package/_bmad-output/implementation-artifacts/bug-experimentalwarning-about-commonjs-loading-es-module-during-install.md +57 -0
- package/_bmad-output/implementation-artifacts/sprint-status.yaml +43 -1
- package/_bmad-output/methodology/BMAD_AI_Development_Training.pptx +0 -0
- package/_bmad-output/methodology/version.json +1 -1
- package/_bmad-output/planning-artifacts/architecture.md +52 -0
- package/_bmad-output/planning-artifacts/epics.md +397 -0
- package/_bmad-output/planning-artifacts/prd.md +46 -1
- package/bin/cli.js +109 -1
- package/docs/BMAD_AI_Development_Training.pptx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/logs/HEAD +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/logs/refs/heads/main +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-554778ad4e7254827618ebd2497c3f4bce9054a4.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/{pack-4b395d030ca386fc5748f1b670dcf8c0ef41c94c.pack → pack-554778ad4e7254827618ebd2497c3f4bce9054a4.pack} +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-554778ad4e7254827618ebd2497c3f4bce9054a4.rev +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py +7 -0
- package/lib/bmad-cache/cache-manifest.json +5 -5
- package/lib/bmad-cache/tea/_git_preserved/index +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/{pack-c79805bb3fee27fa6d8c612a971af7fc86fc80e1.pack → pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.pack} +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-e75385cd52b693dbb8a3b2afb50058952543b3a2.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/tea/_git_preserved/refs/tags/v1.10.0 +1 -0
- package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/tea/docs/explanation/tea-overview.md +2 -2
- package/lib/bmad-cache/tea/docs/how-to/workflows/run-atdd.md +28 -30
- package/lib/bmad-cache/tea/docs/reference/commands.md +4 -4
- package/lib/bmad-cache/tea/docs/reference/configuration.md +1 -1
- package/lib/bmad-cache/tea/package-lock.json +2 -2
- package/lib/bmad-cache/tea/package.json +1 -1
- package/lib/bmad-cache/tea/src/module-help.csv +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/SKILL.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/atdd-checklist-template.md +50 -27
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/checklist.md +18 -17
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/instructions.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01-preflight-and-context.md +21 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01b-resume.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-02-generation-mode.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-03-test-strategy.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04-generate-tests.md +20 -19
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04a-subagent-api-failing.md +13 -13
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04b-subagent-e2e-failing.md +13 -13
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04c-aggregate.md +42 -18
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-05-validate-and-complete.md +12 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow-plan.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/workflow.yaml +2 -2
- package/lib/bmad.js +25 -4
- package/lib/installer.js +2 -1
- package/lib/methodology/BMAD_AI_Development_Training.pptx +0 -0
- package/lib/methodology/version.json +1 -1
- package/lib/profile.js +107 -0
- package/lib/warning-filter.js +245 -0
- package/package.json +2 -2
- package/test/experimental-warning.test.js +314 -0
- package/test/fixtures/README.md +74 -0
- package/test/fixtures/empty-project/README.md +5 -0
- package/test/fixtures/empty-project/package.json +5 -0
- package/test/fixtures/onprem-profile-baseline/.gitkeep +2 -0
- package/test/fixtures/standard-profile-baseline/.gitkeep +2 -0
- package/test/onprem-injection.test.js +48 -0
- package/test/profile.test.js +301 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-4b395d030ca386fc5748f1b670dcf8c0ef41c94c.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-4b395d030ca386fc5748f1b670dcf8c0ef41c94c.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-c79805bb3fee27fa6d8c612a971af7fc86fc80e1.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-c79805bb3fee27fa6d8c612a971af7fc86fc80e1.rev +0 -0
package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04c-aggregate.md
CHANGED
|
@@ -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-{
|
|
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
|
|
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
|
|
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
|
-
✅
|
|
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 (
|
|
199
|
+
## Next Steps (Task-by-Task Activation)
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
During implementation of each task:
|
|
202
202
|
|
|
203
|
-
1. Remove `test.skip()` from
|
|
203
|
+
1. Remove `test.skip()` from the current test file or scenario
|
|
204
204
|
2. Run tests: `npm test`
|
|
205
|
-
3. Verify
|
|
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-{
|
|
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:
|
|
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
|
-
-
|
|
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-{
|
|
312
|
+
- {test_artifacts}/atdd-checklist-{story_key}.md
|
|
301
313
|
|
|
302
314
|
📝 Next Steps:
|
|
303
|
-
1.
|
|
304
|
-
2.
|
|
305
|
-
3.
|
|
306
|
-
4.
|
|
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
|
|
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-{
|
|
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
|
|
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 (
|
|
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-{
|
|
19
|
+
- {test_artifacts}/atdd-checklist-{story_key}.md
|
|
20
20
|
|
|
21
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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-{
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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.
|
|
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,
|
|
Binary file
|
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 };
|