bmad-method 6.5.1-next.1 → 6.5.1-next.2
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/package.json
CHANGED
|
@@ -435,6 +435,9 @@ class ManifestGenerator {
|
|
|
435
435
|
// this means user-scoped keys (e.g. user_name) could mis-file into the
|
|
436
436
|
// team config, so the operator should notice.
|
|
437
437
|
const scopeByModuleKey = {};
|
|
438
|
+
// Maps installer moduleName (may be full display name) → module code field
|
|
439
|
+
// from module.yaml, so TOML sections use [modules.<code>] not [modules.<name>].
|
|
440
|
+
const codeByModuleName = {};
|
|
438
441
|
for (const moduleName of this.updatedModules) {
|
|
439
442
|
const moduleYamlPath = await resolveInstalledModuleYaml(moduleName);
|
|
440
443
|
if (!moduleYamlPath) {
|
|
@@ -447,6 +450,7 @@ class ManifestGenerator {
|
|
|
447
450
|
try {
|
|
448
451
|
const parsed = yaml.parse(await fs.readFile(moduleYamlPath, 'utf8'));
|
|
449
452
|
if (!parsed || typeof parsed !== 'object') continue;
|
|
453
|
+
if (parsed.code) codeByModuleName[moduleName] = parsed.code;
|
|
450
454
|
scopeByModuleKey[moduleName] = {};
|
|
451
455
|
for (const [key, value] of Object.entries(parsed)) {
|
|
452
456
|
if (value && typeof value === 'object' && 'prompt' in value) {
|
|
@@ -545,6 +549,9 @@ class ManifestGenerator {
|
|
|
545
549
|
if (moduleName === 'core') continue;
|
|
546
550
|
const cfg = moduleConfigs[moduleName];
|
|
547
551
|
if (!cfg || Object.keys(cfg).length === 0) continue;
|
|
552
|
+
// Use the module's code field from module.yaml as the TOML key so the
|
|
553
|
+
// section is [modules.mdo] not [modules.MDO: Maxio DevOps Operations].
|
|
554
|
+
const sectionKey = codeByModuleName[moduleName] || moduleName;
|
|
548
555
|
// Only filter out spread-from-core pollution when we actually know
|
|
549
556
|
// this module's prompt schema. For external/marketplace modules whose
|
|
550
557
|
// module.yaml isn't in the src tree, fall through as all-team so we
|
|
@@ -552,14 +559,14 @@ class ManifestGenerator {
|
|
|
552
559
|
const haveSchema = Object.keys(scopeByModuleKey[moduleName] || {}).length > 0;
|
|
553
560
|
const { team: modTeam, user: modUser } = partition(moduleName, cfg, haveSchema);
|
|
554
561
|
if (Object.keys(modTeam).length > 0) {
|
|
555
|
-
teamLines.push(`[modules.${
|
|
562
|
+
teamLines.push(`[modules.${sectionKey}]`);
|
|
556
563
|
for (const [key, value] of Object.entries(modTeam)) {
|
|
557
564
|
teamLines.push(`${key} = ${formatTomlValue(value)}`);
|
|
558
565
|
}
|
|
559
566
|
teamLines.push('');
|
|
560
567
|
}
|
|
561
568
|
if (Object.keys(modUser).length > 0) {
|
|
562
|
-
userLines.push(`[modules.${
|
|
569
|
+
userLines.push(`[modules.${sectionKey}]`);
|
|
563
570
|
for (const [key, value] of Object.entries(modUser)) {
|
|
564
571
|
userLines.push(`${key} = ${formatTomlValue(value)}`);
|
|
565
572
|
}
|
|
@@ -86,6 +86,8 @@ function getExternalModuleCachePath(moduleName, ...segments) {
|
|
|
86
86
|
* Built-in modules (core, bmm) live under <src>. External official modules are
|
|
87
87
|
* cloned into ~/.bmad/cache/external-modules/<name>/ with varying internal
|
|
88
88
|
* layouts (some at src/module.yaml, some at skills/module.yaml, some nested).
|
|
89
|
+
* Local custom-source modules are not cached; their path is read from the
|
|
90
|
+
* CustomModuleManager resolution cache set during the same install run.
|
|
89
91
|
* This mirrors the candidate-path search in
|
|
90
92
|
* ExternalModuleManager.findExternalModuleSource but performs no git/network
|
|
91
93
|
* work, which keeps it safe to call during manifest writing.
|
|
@@ -97,26 +99,56 @@ async function resolveInstalledModuleYaml(moduleName) {
|
|
|
97
99
|
const builtIn = path.join(getModulePath(moduleName), 'module.yaml');
|
|
98
100
|
if (await fs.pathExists(builtIn)) return builtIn;
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
102
|
+
// Search a resolved root directory using the same candidate-path pattern.
|
|
103
|
+
async function searchRoot(root) {
|
|
104
|
+
for (const dir of ['skills', 'src']) {
|
|
105
|
+
const direct = path.join(root, dir, 'module.yaml');
|
|
106
|
+
if (await fs.pathExists(direct)) return direct;
|
|
107
|
+
|
|
108
|
+
const dirPath = path.join(root, dir);
|
|
109
|
+
if (await fs.pathExists(dirPath)) {
|
|
110
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
111
|
+
for (const entry of entries) {
|
|
112
|
+
if (!entry.isDirectory()) continue;
|
|
113
|
+
const nested = path.join(dirPath, entry.name, 'module.yaml');
|
|
114
|
+
if (await fs.pathExists(nested)) return nested;
|
|
115
|
+
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
118
|
+
|
|
119
|
+
// BMB standard: {setup-skill}/assets/module.yaml (setup skill is any *-setup directory)
|
|
120
|
+
const rootEntries = await fs.readdir(root, { withFileTypes: true });
|
|
121
|
+
for (const entry of rootEntries) {
|
|
122
|
+
if (!entry.isDirectory() || !entry.name.endsWith('-setup')) continue;
|
|
123
|
+
const setupAssets = path.join(root, entry.name, 'assets', 'module.yaml');
|
|
124
|
+
if (await fs.pathExists(setupAssets)) return setupAssets;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const atRoot = path.join(root, 'module.yaml');
|
|
128
|
+
if (await fs.pathExists(atRoot)) return atRoot;
|
|
129
|
+
return null;
|
|
116
130
|
}
|
|
117
131
|
|
|
118
|
-
const
|
|
119
|
-
if (await fs.pathExists(
|
|
132
|
+
const cacheRoot = getExternalModuleCachePath(moduleName);
|
|
133
|
+
if (await fs.pathExists(cacheRoot)) {
|
|
134
|
+
const found = await searchRoot(cacheRoot);
|
|
135
|
+
if (found) return found;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Fallback: local custom-source modules store their source path in the
|
|
139
|
+
// CustomModuleManager resolution cache populated during the same install run.
|
|
140
|
+
// Match by code OR name since callers may use either form.
|
|
141
|
+
try {
|
|
142
|
+
const { CustomModuleManager } = require('./modules/custom-module-manager');
|
|
143
|
+
for (const [, mod] of CustomModuleManager._resolutionCache) {
|
|
144
|
+
if ((mod.code === moduleName || mod.name === moduleName) && mod.localPath) {
|
|
145
|
+
const found = await searchRoot(mod.localPath);
|
|
146
|
+
if (found) return found;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
// Resolution cache unavailable — continue
|
|
151
|
+
}
|
|
120
152
|
|
|
121
153
|
return null;
|
|
122
154
|
}
|