ma-agents 3.4.5 → 3.4.7

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 (2) hide show
  1. package/lib/bmad.js +48 -30
  2. package/package.json +1 -1
package/lib/bmad.js CHANGED
@@ -207,37 +207,26 @@ async function updateBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = pr
207
207
  // the files-manifest, finds module "custom", and fails because it can't locate
208
208
  // the source for a module named "custom". Fix: strip stale "custom" module
209
209
  // entries from the manifest so the module gets cleanly reinstalled via --custom-content.
210
- const filesManifestPath = path.join(projectRoot, BMAD_DIR, '_config', 'files-manifest.csv');
211
- if (fs.existsSync(filesManifestPath)) {
212
- try {
213
- let csv = await fs.readFile(filesManifestPath, 'utf-8');
214
- const before = csv.split('\n').length;
215
- csv = csv.split('\n').filter(line => {
216
- const fields = line.split(',');
217
- return !(fields[2] && fields[2].replace(/"/g, '') === 'custom');
218
- }).join('\n');
219
- const after = csv.split('\n').length;
220
- if (after < before) {
221
- await fs.writeFile(filesManifestPath, csv, 'utf-8');
222
- console.log(chalk.gray(` Cleaned ${before - after} stale "custom" module entries from files-manifest.csv`));
223
- }
224
- } catch (err) {
225
- // Non-fatal — worst case the update fails and user retries
226
- }
227
- }
228
-
229
- // The real trigger: manifest.yaml lists "custom" and "bmb" as previously
230
- // installed modules. In --yes (non-interactive) mode, bmad-method preserves
231
- // all previously installed modules and tries to reinstall them. "custom" has
232
- // no source (it's actually "ma-skills"), and "bmb" has a broken directory
233
- // structure in 6.2.2. Fix: remove both from manifest.yaml before update.
210
+ // bmad-method 6.2.2 bug: on --action update --yes, the installer reads
211
+ // manifest.yaml to discover previously installed modules, then preserves them
212
+ // all (non-interactive default). It then tries to reinstall each one.
213
+ // "custom" fails because there's no source under that name (it's "ma-skills"),
214
+ // and "bmb" fails due to a broken directory structure in 6.2.2.
215
+ //
216
+ // Fix: before running bmad-method, clean all three persistence layers:
217
+ // 1. manifest.yaml — remove stale module entries
218
+ // 2. files-manifest.csv — remove stale file tracking entries
219
+ // 3. physical directories — remove _bmad/bmb/ and _bmad/_config/custom/
220
+
221
+ const staleModules = ['custom', 'bmb'];
222
+
223
+ // 1. Clean manifest.yaml (the primary trigger for the re-install loop)
234
224
  const yamlManifestPath = path.join(projectRoot, BMAD_DIR, '_config', 'manifest.yaml');
235
225
  if (fs.existsSync(yamlManifestPath)) {
236
226
  try {
237
227
  const yamlContent = await fs.readFile(yamlManifestPath, 'utf-8');
238
228
  const manifest = yaml.parse(yamlContent);
239
229
  if (manifest?.modules && Array.isArray(manifest.modules)) {
240
- const staleModules = ['custom', 'bmb'];
241
230
  const before = manifest.modules.length;
242
231
  manifest.modules = manifest.modules.filter(
243
232
  m => !staleModules.includes(typeof m === 'string' ? m : m.name)
@@ -253,17 +242,46 @@ async function updateBmad(modules = ['bmm', 'bmb'], tools = [], projectRoot = pr
253
242
  }
254
243
  }
255
244
 
256
- // Remove stale _config/custom/ cache directory that can confuse module scanning
257
- const customCacheDir = path.join(projectRoot, BMAD_DIR, '_config', 'custom');
258
- if (fs.existsSync(customCacheDir)) {
245
+ // 2. Clean files-manifest.csv (prevents stale file-tracking references)
246
+ const filesManifestPath = path.join(projectRoot, BMAD_DIR, '_config', 'files-manifest.csv');
247
+ if (fs.existsSync(filesManifestPath)) {
259
248
  try {
260
- await fs.remove(customCacheDir);
261
- console.log(chalk.gray(' Removed stale _config/custom/ cache directory'));
249
+ let csv = await fs.readFile(filesManifestPath, 'utf-8');
250
+ const before = csv.split('\n').length;
251
+ csv = csv.split('\n').filter(line => {
252
+ const fields = line.split(',');
253
+ const mod = fields[2] && fields[2].replace(/"/g, '');
254
+ return !staleModules.includes(mod);
255
+ }).join('\n');
256
+ const after = csv.split('\n').length;
257
+ if (after < before) {
258
+ await fs.writeFile(filesManifestPath, csv, 'utf-8');
259
+ console.log(chalk.gray(` Cleaned ${before - after} stale entries from files-manifest.csv`));
260
+ }
262
261
  } catch (err) {
263
262
  // Non-fatal
264
263
  }
265
264
  }
266
265
 
266
+ // 3. Remove physical directories so bmad-method's manifest-generator
267
+ // doesn't re-discover them via scanInstalledModules().
268
+ // _bmad/custom/ is safe to remove — applyCustomizations() recreates it after.
269
+ const staleDirs = [
270
+ path.join(projectRoot, BMAD_DIR, 'bmb'),
271
+ path.join(projectRoot, BMAD_DIR, 'custom'),
272
+ path.join(projectRoot, BMAD_DIR, '_config', 'custom'),
273
+ ];
274
+ for (const dir of staleDirs) {
275
+ if (fs.existsSync(dir)) {
276
+ try {
277
+ await fs.remove(dir);
278
+ console.log(chalk.gray(` Removed stale directory: ${path.relative(projectRoot, dir)}`));
279
+ } catch (err) {
280
+ // Non-fatal
281
+ }
282
+ }
283
+ }
284
+
267
285
  console.log(chalk.gray(` Running: ${command}`));
268
286
  try {
269
287
  runCommand(command, { cwd: projectRoot, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ma-agents",
3
- "version": "3.4.5",
3
+ "version": "3.4.7",
4
4
  "description": "NPX tool to install skills for AI coding agents (Claude Code, Gemini, Copilot, Kilocode, Cline, Cursor, Roo Code)",
5
5
  "main": "index.js",
6
6
  "bin": {