bmad-plus 0.13.0 → 0.14.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.
- package/CHANGELOG.md +22 -0
- package/README.md +96 -489
- package/package.json +7 -2
- package/readme-international/README.de.md +9 -5
- package/readme-international/README.es.md +9 -5
- package/readme-international/README.fr.md +9 -5
- package/src/bmad-plus/agents/agent-orchestrator/SKILL.md +3 -3
- package/src/bmad-plus/packs/pack-dev-studio/README.md +133 -141
- package/src/bmad-plus/packs/pack-dev-studio/SKILL.md +49 -0
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/analyst-agent.md +35 -60
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/document-project.md +59 -59
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/domain-research.md +55 -93
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/market-research.md +58 -93
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/prfaq.md +55 -132
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/product-brief.md +63 -78
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/tech-writer-agent.md +54 -69
- package/src/bmad-plus/packs/pack-dev-studio/categories/analysis/technical-research.md +54 -93
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/architect-agent.md +32 -60
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/create-architecture.md +67 -71
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/create-epics-stories.md +61 -90
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/generate-project-context.md +56 -78
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/implementation-readiness.md +55 -88
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-01-init.md +20 -153
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-01b-continue.md +20 -173
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-02-context.md +14 -220
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-03-starter.md +20 -329
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-04-decisions.md +15 -314
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-05-patterns.md +15 -355
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-06-structure.md +15 -375
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-07-validation.md +14 -357
- package/src/bmad-plus/packs/pack-dev-studio/categories/architecture/steps/step-08-complete.md +13 -78
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/checkpoint-preview.md +52 -65
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-01-gather-context.md +14 -81
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-02-review.md +14 -31
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-03-triage.md +14 -45
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review-steps/step-04-present.md +13 -128
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/code-review.md +61 -87
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/correct-course.md +55 -298
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/create-story.md +52 -426
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-agent.md +48 -69
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-story-checklist.md +22 -80
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/dev-story.md +60 -482
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/investigate.md +50 -184
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/qa-e2e-tests.md +57 -173
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/quick-dev.md +56 -108
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/retrospective.md +54 -1509
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/sprint-planning.md +54 -296
- package/src/bmad-plus/packs/pack-dev-studio/categories/implementation/sprint-status.md +41 -283
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/create-prd.md +58 -18
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/create-ux-design.md +103 -72
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/edit-prd.md +55 -27
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/pm-agent.md +34 -60
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/prd.md +46 -87
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/steps/step-01-init.md +10 -0
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/ux-designer-agent.md +30 -60
- package/src/bmad-plus/packs/pack-dev-studio/categories/planning/validate-prd.md +57 -27
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/advanced-elicitation.md +47 -138
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/adversarial-review.md +48 -34
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/bmad-help.md +51 -68
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/brainstorming.md +46 -3
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/customize.md +68 -109
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/distillator.md +53 -174
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/edge-case-hunter.md +39 -53
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/editorial-review-prose.md +45 -83
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/editorial-review-structure.md +45 -176
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/index-docs.md +45 -63
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/party-mode.md +53 -124
- package/src/bmad-plus/packs/pack-dev-studio/categories/utilities/shard-doc.md +44 -100
- package/src/bmad-plus/packs/pack-dev-studio/dev-studio-orchestrator.md +56 -116
- package/src/bmad-plus/packs/pack-dev-studio/shared/architecture-decision-template.md +49 -12
- package/src/bmad-plus/packs/pack-dev-studio/shared/bwml-spec.md +51 -328
- package/src/bmad-plus/packs/pack-dev-studio/shared/catalog.json +489 -0
- package/src/bmad-plus/packs/pack-dev-studio/shared/execution.md +69 -0
- package/src/bmad-plus/packs/pack-dev-studio/shared/module-help.csv +39 -32
- package/src/bmad-plus/packs/pack-dev-studio/upstream-sync.yaml +85 -14
- package/src/bmad-plus/packs/pack-memory/README.md +6 -0
- package/src/bmad-plus/packs/pack-memory/memory-orchestrator.md +12 -5
- package/src/bmad-plus/packs/pack-seo/SKILL.md +27 -1
- package/src/bmad-plus/packs/pack-seo/seo-chief.md +16 -1
- package/src/bmad-plus/packs/pack-seo/seo-judge.md +12 -0
- package/src/bmad-plus/packs/pack-seo/seo-scout.md +12 -0
- package/src/bmad-plus/skills/bmad-plus-autopilot/SKILL.md +3 -3
- package/src/bmad-plus/skills/bmad-plus-sync/SKILL.md +5 -3
- package/src/bmad-plus/skills/dev-studio/SKILL.md +19 -0
- package/tools/build/check-install-contract.js +165 -13
- package/tools/build/generate.js +213 -40
- package/tools/build/generated-adapters/.codex/AGENTS.md +1 -1
- package/tools/build/generated-adapters/.cursor/rules/bmad-plus.mdc +1 -1
- package/tools/build/generated-adapters/.opencode/AGENTS.md +1 -1
- package/tools/build/generated-adapters/AGENTS.md +1 -1
- package/tools/build/generated-adapters/CLAUDE.md +1 -1
- package/tools/build/generated-adapters/CONVENTIONS.md +1 -1
- package/tools/build/generated-adapters/GEMINI.md +1 -1
- package/tools/build/pack-delivery.js +78 -0
- package/tools/cli/bmad-plus-cli.js +1 -1
- package/tools/cli/commands/doctor.js +49 -189
- package/tools/cli/commands/install.js +1 -1
- package/tools/cli/commands/studio.js +68 -0
- package/tools/cli/lib/installation-health.js +360 -0
- package/tools/cli/lib/packs.js +118 -9
- package/tools/cli/lib/python-health.js +233 -0
- package/tools/cli/lib/python-provision.js +2 -2
- package/tools/cli/lib/studio.js +310 -0
- package/tools/release/publication-content.js +901 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/** Read-only by default; optional Python import probes never provision or repair. */
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const semver = require('semver');
|
|
5
|
+
const { DERIVED } = require('./packs');
|
|
6
|
+
const { readInstallManifest } = require('./install-manifest');
|
|
7
|
+
const { inventoryOf, collectManagedFiles, MANIFEST } = require('./update-transaction');
|
|
8
|
+
const { fileHash } = require('./pack-copy');
|
|
9
|
+
const { contentHash } = require('./installed-adapters');
|
|
10
|
+
const {
|
|
11
|
+
safeTarget,
|
|
12
|
+
GENERATED_MARKER,
|
|
13
|
+
USER_CONFIG_MARKER,
|
|
14
|
+
} = require('../../build/generate-adapters');
|
|
15
|
+
|
|
16
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '../../..');
|
|
17
|
+
|
|
18
|
+
function inspectFile(root, file) {
|
|
19
|
+
try {
|
|
20
|
+
return { state: 'present', bytes: fs.readFileSync(safeTarget(root, file)) };
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return { state: error.code === 'ENOENT' ? 'missing' : 'unreadable' };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function collectInstallationHealth({
|
|
27
|
+
projectDir = process.cwd(),
|
|
28
|
+
packageRoot = PACKAGE_ROOT,
|
|
29
|
+
cliVersion = require('../../../package.json').version,
|
|
30
|
+
nodeVersion = process.versions.node,
|
|
31
|
+
verifyPython = false,
|
|
32
|
+
pythonRunner,
|
|
33
|
+
} = {}) {
|
|
34
|
+
projectDir = path.resolve(projectDir);
|
|
35
|
+
const report = {
|
|
36
|
+
schemaVersion: 1,
|
|
37
|
+
projectDir,
|
|
38
|
+
status: 'ok',
|
|
39
|
+
versions: { installed: null, cli: cliVersion, published: null },
|
|
40
|
+
inventory: { status: 'unknown', trackedFiles: 0 },
|
|
41
|
+
packs: [],
|
|
42
|
+
integrations: [],
|
|
43
|
+
runtimes: [],
|
|
44
|
+
checks: [],
|
|
45
|
+
summary: { passed: 0, warnings: 0, errors: 0 },
|
|
46
|
+
};
|
|
47
|
+
function check(code, status, message, extra = {}) {
|
|
48
|
+
report.checks.push({ code, status, message, ...extra });
|
|
49
|
+
}
|
|
50
|
+
function finish() {
|
|
51
|
+
for (const entry of report.checks) {
|
|
52
|
+
report.summary[
|
|
53
|
+
entry.status === 'pass' ? 'passed' : entry.status === 'warning' ? 'warnings' : 'errors'
|
|
54
|
+
]++;
|
|
55
|
+
}
|
|
56
|
+
report.status = report.summary.errors ? 'error' : report.summary.warnings ? 'warning' : 'ok';
|
|
57
|
+
return report;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const manifestFile = inspectFile(projectDir, MANIFEST);
|
|
61
|
+
if (manifestFile.state !== 'present') {
|
|
62
|
+
check(
|
|
63
|
+
manifestFile.state === 'missing' ? 'installation.missing' : 'manifest.unreadable',
|
|
64
|
+
'error',
|
|
65
|
+
manifestFile.state === 'missing'
|
|
66
|
+
? 'BMAD+ is not installed in this directory.'
|
|
67
|
+
: 'Installation manifest cannot be read safely.',
|
|
68
|
+
{ path: MANIFEST }
|
|
69
|
+
);
|
|
70
|
+
return finish();
|
|
71
|
+
}
|
|
72
|
+
let manifest;
|
|
73
|
+
try {
|
|
74
|
+
manifest = readInstallManifest(safeTarget(projectDir, MANIFEST));
|
|
75
|
+
} catch (error) {
|
|
76
|
+
check('manifest.invalid', 'error', 'Invalid installation manifest: ' + error.message, {
|
|
77
|
+
path: MANIFEST,
|
|
78
|
+
});
|
|
79
|
+
return finish();
|
|
80
|
+
}
|
|
81
|
+
report.versions.installed = manifest.version;
|
|
82
|
+
check('manifest.valid', 'pass', 'Manifest found: v' + manifest.version);
|
|
83
|
+
check(
|
|
84
|
+
'version.cli',
|
|
85
|
+
manifest.version === cliVersion ? 'pass' : 'warning',
|
|
86
|
+
manifest.version === cliVersion
|
|
87
|
+
? 'Installed and executing CLI versions match.'
|
|
88
|
+
: 'Version mismatch: installed v' + manifest.version + ', executing CLI v' + cliVersion + '.'
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const selectedPacks = [...new Set(manifest.packs)];
|
|
92
|
+
const validPacks = selectedPacks.filter((id) => Object.hasOwn(DERIVED.packs, id));
|
|
93
|
+
for (const id of selectedPacks) {
|
|
94
|
+
if (!validPacks.includes(id))
|
|
95
|
+
check('pack.unknown', 'error', 'Unknown installed pack: ' + id, { pack: id });
|
|
96
|
+
}
|
|
97
|
+
if (!selectedPacks.includes('core'))
|
|
98
|
+
check('pack.core-missing', 'error', 'The required Core pack is not selected.');
|
|
99
|
+
|
|
100
|
+
if (selectedPacks.includes('dev-studio')) {
|
|
101
|
+
try {
|
|
102
|
+
const studio = require('./studio');
|
|
103
|
+
const resolved = studio.validatePack(studio.installedPack(projectDir));
|
|
104
|
+
studio.resolveConfig(projectDir);
|
|
105
|
+
check(
|
|
106
|
+
'studio.resources',
|
|
107
|
+
'pass',
|
|
108
|
+
`Dev Studio: ${resolved.catalog.workflows.length} routes and ${resolved.resources.length} resources resolved; host execution is not verified.`
|
|
109
|
+
);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
check(
|
|
112
|
+
'studio.resources',
|
|
113
|
+
'error',
|
|
114
|
+
'Dev Studio cannot prepare its workflows: ' + error.message,
|
|
115
|
+
{ path: '.agents/skills/pack-dev-studio' }
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const inventory = inventoryOf(manifest);
|
|
121
|
+
const validInventory =
|
|
122
|
+
inventory &&
|
|
123
|
+
Object.values(inventory).every((hash) => typeof hash === 'string') &&
|
|
124
|
+
typeof manifest.fileInventory.complete === 'boolean';
|
|
125
|
+
report.inventory.status =
|
|
126
|
+
manifest.fileInventory === undefined
|
|
127
|
+
? 'legacy'
|
|
128
|
+
: !validInventory
|
|
129
|
+
? 'invalid'
|
|
130
|
+
: manifest.fileInventory.complete
|
|
131
|
+
? 'complete'
|
|
132
|
+
: 'incomplete';
|
|
133
|
+
const owned = validInventory ? inventory : {};
|
|
134
|
+
report.inventory.trackedFiles = Object.keys(owned).length;
|
|
135
|
+
|
|
136
|
+
const expectedFiles = new Set(['_bmad/module.yaml', '_bmad/module-help.csv']);
|
|
137
|
+
for (const id of validPacks) {
|
|
138
|
+
const pack = DERIVED.packs[id];
|
|
139
|
+
report.packs.push({ id, runtimes: pack.runtimes, requiredResources: pack.requiredResources });
|
|
140
|
+
for (const file of pack.requiredResources) expectedFiles.add(file);
|
|
141
|
+
}
|
|
142
|
+
// Check delivery against the executing package, even if a manifest omits a file.
|
|
143
|
+
try {
|
|
144
|
+
for (const { file } of collectManagedFiles({ projectDir, packageRoot, packs: validPacks }))
|
|
145
|
+
expectedFiles.add(file);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
check('package.unreadable', 'error', 'Cannot inspect the executing package: ' + error.message);
|
|
148
|
+
}
|
|
149
|
+
const resources = new Set([...expectedFiles, ...Object.keys(owned)]);
|
|
150
|
+
for (const file of [...resources].sort()) {
|
|
151
|
+
if (!Object.hasOwn(owned, file) && report.inventory.status === 'complete')
|
|
152
|
+
report.inventory.status = 'incomplete';
|
|
153
|
+
const observed = inspectFile(projectDir, file);
|
|
154
|
+
if (observed.state !== 'present') {
|
|
155
|
+
check(
|
|
156
|
+
'file.' + observed.state,
|
|
157
|
+
'error',
|
|
158
|
+
observed.state === 'missing'
|
|
159
|
+
? 'Missing required file: ' + file
|
|
160
|
+
: 'File cannot be read safely: ' + file,
|
|
161
|
+
{ path: file }
|
|
162
|
+
);
|
|
163
|
+
} else if (Object.hasOwn(owned, file)) {
|
|
164
|
+
const unchanged = fileHash(observed.bytes) === owned[file];
|
|
165
|
+
check(
|
|
166
|
+
unchanged ? 'file.unchanged' : 'file.modified',
|
|
167
|
+
unchanged ? 'pass' : 'warning',
|
|
168
|
+
unchanged
|
|
169
|
+
? 'Managed file unchanged.'
|
|
170
|
+
: 'Managed file modified locally; review before updating.',
|
|
171
|
+
{ path: file }
|
|
172
|
+
);
|
|
173
|
+
} else {
|
|
174
|
+
check('file.unowned', 'warning', 'File present without a recorded ownership hash.', {
|
|
175
|
+
path: file,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (manifest.fileInventory?.complete && report.inventory.status === 'incomplete') {
|
|
180
|
+
check(
|
|
181
|
+
'inventory.omissions',
|
|
182
|
+
'warning',
|
|
183
|
+
'Inventory claims completeness but omits expected files.'
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
check(
|
|
187
|
+
'inventory.' + report.inventory.status,
|
|
188
|
+
report.inventory.status === 'complete'
|
|
189
|
+
? 'pass'
|
|
190
|
+
: report.inventory.status === 'invalid'
|
|
191
|
+
? 'error'
|
|
192
|
+
: 'warning',
|
|
193
|
+
'File ownership inventory: ' + report.inventory.status + '.'
|
|
194
|
+
);
|
|
195
|
+
const config = inspectFile(projectDir, '_bmad/config.yaml');
|
|
196
|
+
check(
|
|
197
|
+
'config.' + config.state,
|
|
198
|
+
config.state === 'present' ? 'pass' : 'error',
|
|
199
|
+
config.state === 'present'
|
|
200
|
+
? 'Project configuration present.'
|
|
201
|
+
: 'Project configuration missing or unreadable.',
|
|
202
|
+
{ path: '_bmad/config.yaml' }
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const contract = DERIVED.diagnostics;
|
|
206
|
+
const declaredTools = Object.keys(contract.integrations);
|
|
207
|
+
let selectedTools = [];
|
|
208
|
+
if (manifest.ides === undefined) {
|
|
209
|
+
selectedTools = declaredTools.filter(
|
|
210
|
+
(tool) =>
|
|
211
|
+
inspectFile(projectDir, contract.integrations[tool].instructionFile).state !== 'missing'
|
|
212
|
+
);
|
|
213
|
+
check(
|
|
214
|
+
'integrations.legacy',
|
|
215
|
+
'warning',
|
|
216
|
+
'IDE selection was not recorded; existing adapter paths were inspected.'
|
|
217
|
+
);
|
|
218
|
+
} else if (
|
|
219
|
+
!Array.isArray(manifest.ides) ||
|
|
220
|
+
manifest.ides.some((id) => typeof id !== 'string' || !declaredTools.includes(id))
|
|
221
|
+
) {
|
|
222
|
+
check(
|
|
223
|
+
'integrations.invalid',
|
|
224
|
+
'error',
|
|
225
|
+
'Manifest IDE selection contains invalid or unknown targets.'
|
|
226
|
+
);
|
|
227
|
+
} else selectedTools = [...new Set(manifest.ides)];
|
|
228
|
+
|
|
229
|
+
const adapterPaths =
|
|
230
|
+
selectedTools.length || manifest.ides === undefined
|
|
231
|
+
? [
|
|
232
|
+
...new Set([
|
|
233
|
+
DERIVED.targets.spine,
|
|
234
|
+
...selectedTools.map((tool) => contract.integrations[tool].instructionFile),
|
|
235
|
+
]),
|
|
236
|
+
]
|
|
237
|
+
: [];
|
|
238
|
+
const ownership = new Map();
|
|
239
|
+
const hashes = manifest.adapterHashes;
|
|
240
|
+
const validHashes =
|
|
241
|
+
hashes === undefined ||
|
|
242
|
+
(hashes &&
|
|
243
|
+
typeof hashes === 'object' &&
|
|
244
|
+
!Array.isArray(hashes) &&
|
|
245
|
+
Object.entries(hashes).every(
|
|
246
|
+
([file, hash]) =>
|
|
247
|
+
[DERIVED.targets.spine, ...DERIVED.targets.adapters.map((entry) => entry.file)].includes(
|
|
248
|
+
file
|
|
249
|
+
) &&
|
|
250
|
+
typeof hash === 'string' &&
|
|
251
|
+
/^[a-f0-9]{64}$/.test(hash)
|
|
252
|
+
));
|
|
253
|
+
if (!validHashes) check('adapters.invalid', 'error', 'Adapter ownership hashes are invalid.');
|
|
254
|
+
for (const file of adapterPaths) {
|
|
255
|
+
const observed = inspectFile(projectDir, file);
|
|
256
|
+
let state = observed.state;
|
|
257
|
+
if (state === 'present') {
|
|
258
|
+
const text = observed.bytes.toString('utf8');
|
|
259
|
+
const previous = validHashes && hashes && Object.hasOwn(hashes, file) ? hashes[file] : null;
|
|
260
|
+
state =
|
|
261
|
+
text.includes(GENERATED_MARKER) && !text.includes(USER_CONFIG_MARKER)
|
|
262
|
+
? 'adopted'
|
|
263
|
+
: !previous || !text.includes(USER_CONFIG_MARKER)
|
|
264
|
+
? 'unowned'
|
|
265
|
+
: contentHash(text) === previous
|
|
266
|
+
? 'unchanged'
|
|
267
|
+
: 'modified';
|
|
268
|
+
}
|
|
269
|
+
ownership.set(file, state);
|
|
270
|
+
check(
|
|
271
|
+
'adapter.' + state,
|
|
272
|
+
['missing', 'unreadable'].includes(state)
|
|
273
|
+
? 'error'
|
|
274
|
+
: state === 'unchanged'
|
|
275
|
+
? 'pass'
|
|
276
|
+
: 'warning',
|
|
277
|
+
'Instruction file: ' + state + '.',
|
|
278
|
+
{ path: file }
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
report.integrations = selectedTools.map((tool) => ({
|
|
282
|
+
tool,
|
|
283
|
+
...contract.integrations[tool],
|
|
284
|
+
ownership: ownership.get(contract.integrations[tool].instructionFile),
|
|
285
|
+
hostVerified: false,
|
|
286
|
+
}));
|
|
287
|
+
|
|
288
|
+
const nodeMinimum = contract.runtimeMinimums.node;
|
|
289
|
+
const nodeReady = Boolean(semver.valid(nodeVersion) && semver.gte(nodeVersion, nodeMinimum));
|
|
290
|
+
report.runtimes.push({
|
|
291
|
+
runtime: 'node',
|
|
292
|
+
minimum: nodeMinimum,
|
|
293
|
+
version: nodeVersion,
|
|
294
|
+
status: nodeReady ? 'verified' : 'unsupported',
|
|
295
|
+
});
|
|
296
|
+
check(
|
|
297
|
+
'runtime.node',
|
|
298
|
+
nodeReady ? 'pass' : 'error',
|
|
299
|
+
'Executing Node.js ' + nodeVersion + '; minimum ' + nodeMinimum + '.'
|
|
300
|
+
);
|
|
301
|
+
for (const id of validPacks.filter((pack) => DERIVED.packs[pack].runtimes.includes('python'))) {
|
|
302
|
+
const requirements = DERIVED.pythonPacks[id].requirements.join('/');
|
|
303
|
+
const delivery = inspectFile(packageRoot, requirements).state;
|
|
304
|
+
const environmentFile = '.bmad/venv/' + id + '/pyvenv.cfg';
|
|
305
|
+
const environment = inspectFile(projectDir, environmentFile).state;
|
|
306
|
+
const runtime = {
|
|
307
|
+
runtime: 'python',
|
|
308
|
+
pack: id,
|
|
309
|
+
minimum: contract.runtimeMinimums.python,
|
|
310
|
+
requirements,
|
|
311
|
+
packageRequirements: delivery,
|
|
312
|
+
environment,
|
|
313
|
+
imports: 'not-verified',
|
|
314
|
+
};
|
|
315
|
+
report.runtimes.push(runtime);
|
|
316
|
+
check(
|
|
317
|
+
'runtime.requirements',
|
|
318
|
+
delivery === 'present' ? 'pass' : 'error',
|
|
319
|
+
delivery === 'present'
|
|
320
|
+
? 'Python requirements are available in the executing package.'
|
|
321
|
+
: 'Python requirements are missing or unreadable in the executing package.',
|
|
322
|
+
{ pack: id, path: requirements, scope: 'package' }
|
|
323
|
+
);
|
|
324
|
+
if (verifyPython) {
|
|
325
|
+
const { probePythonRuntime } = require('./python-health');
|
|
326
|
+
const probe = probePythonRuntime({
|
|
327
|
+
projectDir,
|
|
328
|
+
packId: id,
|
|
329
|
+
minimum: contract.runtimeMinimums.python,
|
|
330
|
+
verifyModules: DERIVED.pythonPacks[id].verifyModules,
|
|
331
|
+
runner: pythonRunner,
|
|
332
|
+
});
|
|
333
|
+
Object.assign(runtime, probe);
|
|
334
|
+
check(
|
|
335
|
+
'runtime.python-probe',
|
|
336
|
+
probe.status === 'verified' ? 'pass' : 'warning',
|
|
337
|
+
probe.message +
|
|
338
|
+
(probe.status === 'verified'
|
|
339
|
+
? ''
|
|
340
|
+
: ' Use bmad-plus install --provision-python to provision selected Python packs.'),
|
|
341
|
+
{
|
|
342
|
+
pack: id,
|
|
343
|
+
path: environmentFile,
|
|
344
|
+
}
|
|
345
|
+
);
|
|
346
|
+
} else {
|
|
347
|
+
check(
|
|
348
|
+
'runtime.python-unverified',
|
|
349
|
+
'warning',
|
|
350
|
+
'Python environment ' +
|
|
351
|
+
environment +
|
|
352
|
+
'; interpreter version and imports have not been executed. Use doctor --verify-python to probe them.',
|
|
353
|
+
{ pack: id, path: environmentFile }
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return finish();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
module.exports = { collectInstallationHealth };
|
package/tools/cli/lib/packs.js
CHANGED
|
@@ -210,7 +210,7 @@ const DERIVED = {
|
|
|
210
210
|
"product": {
|
|
211
211
|
"code": "bmad-plus",
|
|
212
212
|
"displayName": "BMAD+",
|
|
213
|
-
"version": "0.
|
|
213
|
+
"version": "0.14.0",
|
|
214
214
|
"derivedFrom": "BMAD-METHOD v6.6.0"
|
|
215
215
|
},
|
|
216
216
|
"packOrder": [
|
|
@@ -256,6 +256,19 @@ const DERIVED = {
|
|
|
256
256
|
"skillCount": 3,
|
|
257
257
|
"referenceFiles": 0,
|
|
258
258
|
"categoryAgentCounts": [],
|
|
259
|
+
"runtimes": [
|
|
260
|
+
"node"
|
|
261
|
+
],
|
|
262
|
+
"requiredResources": [
|
|
263
|
+
".agents/skills/agent-strategist/SKILL.md",
|
|
264
|
+
".agents/skills/agent-architect-dev/SKILL.md",
|
|
265
|
+
".agents/skills/agent-quality/SKILL.md",
|
|
266
|
+
".agents/skills/agent-orchestrator/SKILL.md",
|
|
267
|
+
".agents/skills/bmad-plus-autopilot/SKILL.md",
|
|
268
|
+
".agents/skills/bmad-plus-parallel/SKILL.md",
|
|
269
|
+
".agents/skills/bmad-plus-sync/SKILL.md",
|
|
270
|
+
".agents/data/role-triggers.yaml"
|
|
271
|
+
],
|
|
259
272
|
"personas": [
|
|
260
273
|
{
|
|
261
274
|
"id": "agent-strategist",
|
|
@@ -302,6 +315,12 @@ const DERIVED = {
|
|
|
302
315
|
"skillCount": 0,
|
|
303
316
|
"referenceFiles": 0,
|
|
304
317
|
"categoryAgentCounts": [],
|
|
318
|
+
"runtimes": [
|
|
319
|
+
"node"
|
|
320
|
+
],
|
|
321
|
+
"requiredResources": [
|
|
322
|
+
".agents/skills/agent-shadow/SKILL.md"
|
|
323
|
+
],
|
|
305
324
|
"personas": [
|
|
306
325
|
{
|
|
307
326
|
"id": "agent-shadow",
|
|
@@ -330,6 +349,12 @@ const DERIVED = {
|
|
|
330
349
|
"skillCount": 0,
|
|
331
350
|
"referenceFiles": 0,
|
|
332
351
|
"categoryAgentCounts": [],
|
|
352
|
+
"runtimes": [
|
|
353
|
+
"node"
|
|
354
|
+
],
|
|
355
|
+
"requiredResources": [
|
|
356
|
+
".agents/skills/agent-maker/SKILL.md"
|
|
357
|
+
],
|
|
333
358
|
"personas": [
|
|
334
359
|
{
|
|
335
360
|
"id": "agent-maker",
|
|
@@ -365,6 +390,13 @@ const DERIVED = {
|
|
|
365
390
|
3,
|
|
366
391
|
3
|
|
367
392
|
],
|
|
393
|
+
"runtimes": [
|
|
394
|
+
"node"
|
|
395
|
+
],
|
|
396
|
+
"requiredResources": [
|
|
397
|
+
".agents/skills/pack-shield/shield-orchestrator.md",
|
|
398
|
+
".agents/skills/pack-shield/SKILL.md"
|
|
399
|
+
],
|
|
368
400
|
"personas": [
|
|
369
401
|
{
|
|
370
402
|
"id": "shield-orchestrator",
|
|
@@ -393,6 +425,17 @@ const DERIVED = {
|
|
|
393
425
|
"skillCount": 0,
|
|
394
426
|
"referenceFiles": 0,
|
|
395
427
|
"categoryAgentCounts": [],
|
|
428
|
+
"runtimes": [
|
|
429
|
+
"node",
|
|
430
|
+
"python"
|
|
431
|
+
],
|
|
432
|
+
"requiredResources": [
|
|
433
|
+
".agents/skills/pack-seo/seo-scout.md",
|
|
434
|
+
".agents/skills/pack-seo/seo-chief.md",
|
|
435
|
+
".agents/skills/pack-seo/seo-judge.md",
|
|
436
|
+
".agents/skills/pack-seo/SKILL.md",
|
|
437
|
+
".agents/skills/pack-seo/scripts/seo_fetch.py"
|
|
438
|
+
],
|
|
396
439
|
"personas": [
|
|
397
440
|
{
|
|
398
441
|
"id": "seo-scout",
|
|
@@ -433,6 +476,13 @@ const DERIVED = {
|
|
|
433
476
|
"skillCount": 0,
|
|
434
477
|
"referenceFiles": 0,
|
|
435
478
|
"categoryAgentCounts": [],
|
|
479
|
+
"runtimes": [
|
|
480
|
+
"node"
|
|
481
|
+
],
|
|
482
|
+
"requiredResources": [
|
|
483
|
+
".agents/skills/pack-memory/zecher-agent.md",
|
|
484
|
+
".agents/skills/pack-memory/memory-orchestrator.md"
|
|
485
|
+
],
|
|
436
486
|
"personas": [
|
|
437
487
|
{
|
|
438
488
|
"id": "zecher",
|
|
@@ -468,6 +518,18 @@ const DERIVED = {
|
|
|
468
518
|
0,
|
|
469
519
|
0
|
|
470
520
|
],
|
|
521
|
+
"runtimes": [
|
|
522
|
+
"node"
|
|
523
|
+
],
|
|
524
|
+
"requiredResources": [
|
|
525
|
+
".agents/skills/pack-dev-studio/dev-studio-orchestrator.md",
|
|
526
|
+
".agents/skills/dev-studio/SKILL.md",
|
|
527
|
+
".agents/skills/pack-dev-studio/SKILL.md",
|
|
528
|
+
".agents/skills/pack-dev-studio/shared/catalog.json",
|
|
529
|
+
".agents/skills/pack-dev-studio/shared/execution.md",
|
|
530
|
+
".agents/skills/pack-dev-studio/categories/planning/create-ux-design.md",
|
|
531
|
+
".agents/skills/pack-dev-studio/categories/planning/steps/step-01-init.md"
|
|
532
|
+
],
|
|
471
533
|
"personas": [
|
|
472
534
|
{
|
|
473
535
|
"id": "analyst-agent",
|
|
@@ -532,6 +594,12 @@ const DERIVED = {
|
|
|
532
594
|
"skillCount": 0,
|
|
533
595
|
"referenceFiles": 0,
|
|
534
596
|
"categoryAgentCounts": [],
|
|
597
|
+
"runtimes": [
|
|
598
|
+
"node"
|
|
599
|
+
],
|
|
600
|
+
"requiredResources": [
|
|
601
|
+
".agents/skills/pack-backup/backup-agent.md"
|
|
602
|
+
],
|
|
535
603
|
"personas": [
|
|
536
604
|
{
|
|
537
605
|
"id": "backup-agent",
|
|
@@ -560,6 +628,12 @@ const DERIVED = {
|
|
|
560
628
|
"skillCount": 0,
|
|
561
629
|
"referenceFiles": 0,
|
|
562
630
|
"categoryAgentCounts": [],
|
|
631
|
+
"runtimes": [
|
|
632
|
+
"node"
|
|
633
|
+
],
|
|
634
|
+
"requiredResources": [
|
|
635
|
+
".agents/skills/pack-animated/animated-website-agent.md"
|
|
636
|
+
],
|
|
563
637
|
"personas": [
|
|
564
638
|
{
|
|
565
639
|
"id": "animated-website-agent",
|
|
@@ -588,15 +662,50 @@ const DERIVED = {
|
|
|
588
662
|
"defusedxml",
|
|
589
663
|
"lxml"
|
|
590
664
|
]
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
"diagnostics": {
|
|
668
|
+
"schemaVersion": 1,
|
|
669
|
+
"runtimeMinimums": {
|
|
670
|
+
"node": "20.0.0",
|
|
671
|
+
"python": "3.11"
|
|
591
672
|
},
|
|
592
|
-
"
|
|
593
|
-
"
|
|
594
|
-
"
|
|
595
|
-
"
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
673
|
+
"integrations": {
|
|
674
|
+
"claude-code": {
|
|
675
|
+
"instructionFile": "CLAUDE.md",
|
|
676
|
+
"execution": "host-managed",
|
|
677
|
+
"lifecycleEvents": "not-integrated"
|
|
678
|
+
},
|
|
679
|
+
"gemini-cli": {
|
|
680
|
+
"instructionFile": "GEMINI.md",
|
|
681
|
+
"execution": "host-managed",
|
|
682
|
+
"lifecycleEvents": "not-integrated"
|
|
683
|
+
},
|
|
684
|
+
"antigravity": {
|
|
685
|
+
"instructionFile": "GEMINI.md",
|
|
686
|
+
"execution": "host-managed",
|
|
687
|
+
"lifecycleEvents": "not-integrated"
|
|
688
|
+
},
|
|
689
|
+
"cursor": {
|
|
690
|
+
"instructionFile": ".cursor/rules/bmad-plus.mdc",
|
|
691
|
+
"execution": "host-managed",
|
|
692
|
+
"lifecycleEvents": "not-integrated"
|
|
693
|
+
},
|
|
694
|
+
"codex-cli": {
|
|
695
|
+
"instructionFile": ".codex/AGENTS.md",
|
|
696
|
+
"execution": "host-managed",
|
|
697
|
+
"lifecycleEvents": "not-integrated"
|
|
698
|
+
},
|
|
699
|
+
"opencode": {
|
|
700
|
+
"instructionFile": ".opencode/AGENTS.md",
|
|
701
|
+
"execution": "host-managed",
|
|
702
|
+
"lifecycleEvents": "not-integrated"
|
|
703
|
+
},
|
|
704
|
+
"aider": {
|
|
705
|
+
"instructionFile": "CONVENTIONS.md",
|
|
706
|
+
"execution": "host-managed",
|
|
707
|
+
"lifecycleEvents": "not-integrated"
|
|
708
|
+
}
|
|
600
709
|
}
|
|
601
710
|
},
|
|
602
711
|
"targets": {
|