ma-agents 3.12.1 → 3.12.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.
@@ -37,7 +37,7 @@
37
37
  "name": "ma-skills",
38
38
  "source": "./",
39
39
  "description": "ma-agents extension module providing enterprise SDLC personas and operational workflow skills.",
40
- "version": "3.12.1",
40
+ "version": "3.12.2",
41
41
  "author": {
42
42
  "name": "Alon Mayaffit"
43
43
  },
package/lib/bmad.js CHANGED
@@ -1552,6 +1552,66 @@ async function deployClineWorkflows(projectRoot, tools = []) {
1552
1552
  }
1553
1553
  }
1554
1554
 
1555
+ /**
1556
+ * Write bmad-method's `.bmad-channel.json` marker for an offline-cached
1557
+ * module if one is not already present.
1558
+ *
1559
+ * Why this exists: bmad-method's `cloneExternalModule()` (in
1560
+ * `node_modules/bmad-method/tools/installer/modules/external-manager.js`)
1561
+ * resolves the install ref by hitting GitHub's API for the latest stable
1562
+ * tag. On an air-gapped machine the API call throws and the function
1563
+ * falls back to reading the cached marker via `readChannelMarker()`. If
1564
+ * the marker is missing, it instead throws `Could not resolve stable tag
1565
+ * for '<module>'` and aborts the entire install.
1566
+ *
1567
+ * Pre-3.12.2 ma-agents copied each module's source tree (with `.git/`
1568
+ * restored from `_git_preserved/`) into `~/.bmad/cache/external-modules/`
1569
+ * but never wrote the marker. The result: any first-time offline install
1570
+ * that pre-populated more than `bmm` failed at the first external module.
1571
+ * Pre-3.12.1 the bug was masked because ma-agents only ever requested
1572
+ * `--modules bmm` (built into bmad-method itself, no cache-marker check).
1573
+ *
1574
+ * The marker schema is the same one bmad-method writes after a successful
1575
+ * online clone (line 419 of external-manager.js). Channel defaults to
1576
+ * `stable` because that's bmad-method's own default when a registry
1577
+ * entry has no `default_channel` field.
1578
+ *
1579
+ * Best-effort: failures are swallowed. The next install attempt (online or
1580
+ * offline-with-marker) will write a fresh one.
1581
+ *
1582
+ * @param {string} moduleDir - Cache dir for the module
1583
+ * (e.g. `~/.bmad/cache/external-modules/tea`)
1584
+ * @param {{ branch?: string, commitSha?: string }} [manifestEntry] - Entry
1585
+ * from `lib/bmad-cache/cache-manifest.json` for this module
1586
+ * @returns {Promise<boolean>} `true` if the marker was written, `false` if
1587
+ * it already existed or the manifest entry is missing required fields
1588
+ */
1589
+ async function ensureCacheMarker(moduleDir, manifestEntry) {
1590
+ const markerPath = path.join(moduleDir, '.bmad-channel.json');
1591
+ if (await fs.pathExists(markerPath)) return false;
1592
+ if (!manifestEntry || !manifestEntry.commitSha) return false;
1593
+ try {
1594
+ await fs.writeFile(
1595
+ markerPath,
1596
+ JSON.stringify(
1597
+ {
1598
+ channel: 'stable',
1599
+ version: manifestEntry.branch || 'main',
1600
+ sha: manifestEntry.commitSha,
1601
+ writtenAt: new Date().toISOString(),
1602
+ },
1603
+ null,
1604
+ 2,
1605
+ ),
1606
+ );
1607
+ return true;
1608
+ } catch {
1609
+ // Best-effort — marker is a fallback, not a correctness requirement.
1610
+ // If we can't write it, bmad-method will surface its own error.
1611
+ return false;
1612
+ }
1613
+ }
1614
+
1555
1615
  async function prePopulateBmadCache(force = false) {
1556
1616
  const cacheSource = path.join(__dirname, 'bmad-cache');
1557
1617
  if (!(await fs.pathExists(cacheSource))) {
@@ -1563,10 +1623,23 @@ async function prePopulateBmadCache(force = false) {
1563
1623
  const targetDir = path.join(os.homedir(), '.bmad', 'cache', 'external-modules');
1564
1624
  await fs.ensureDir(targetDir);
1565
1625
 
1626
+ // Load manifest once so each module copy can stamp a `.bmad-channel.json`
1627
+ // marker for bmad-method's offline fallback. Missing/malformed manifest
1628
+ // is non-fatal — copy still happens, marker is just skipped.
1629
+ let manifest = null;
1630
+ try {
1631
+ const manifestPath = path.join(cacheSource, 'cache-manifest.json');
1632
+ if (await fs.pathExists(manifestPath)) {
1633
+ manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
1634
+ }
1635
+ } catch {
1636
+ manifest = null;
1637
+ }
1638
+
1566
1639
  const entries = await fs.readdir(cacheSource);
1567
1640
  const modules = entries.filter(e => e !== 'cache-manifest.json');
1568
1641
 
1569
- let copied = 0, skipped = 0, replaced = 0;
1642
+ let copied = 0, skipped = 0, replaced = 0, markersWritten = 0;
1570
1643
 
1571
1644
  for (const mod of modules) {
1572
1645
  const src = path.join(cacheSource, mod);
@@ -1598,11 +1671,21 @@ async function prePopulateBmadCache(force = false) {
1598
1671
  console.log(chalk.cyan(` + Pre-populated cached module: ${mod}`));
1599
1672
  copied++;
1600
1673
  }
1674
+
1675
+ // Stamp the offline-fallback marker. Always attempt — even on the
1676
+ // skip path, since prior ma-agents versions copied the module
1677
+ // without the marker and left users wedged on offline installs.
1678
+ // ensureCacheMarker no-ops when the marker already exists.
1679
+ const wrote = await ensureCacheMarker(dst, manifest && manifest.modules ? manifest.modules[mod] : null);
1680
+ if (wrote) markersWritten++;
1601
1681
  }
1602
1682
 
1603
1683
  if (copied > 0 || replaced > 0) {
1604
1684
  console.log(chalk.gray(` Cache pre-population complete: ${copied} copied, ${skipped} skipped, ${replaced} replaced`));
1605
1685
  }
1686
+ if (markersWritten > 0) {
1687
+ console.log(chalk.gray(` Wrote ${markersWritten} offline-fallback marker(s) (.bmad-channel.json)`));
1688
+ }
1606
1689
  } catch (err) {
1607
1690
  console.error(chalk.red(` Cache pre-population failed: ${err.message}`));
1608
1691
  }
@@ -2724,4 +2807,6 @@ module.exports = {
2724
2807
  getInstallableBmadModules,
2725
2808
  getInstalledBmadModules,
2726
2809
  resolveBmadModules,
2810
+ // 3.12.2 — offline-fallback marker for bmad-method's cloneExternalModule
2811
+ ensureCacheMarker,
2727
2812
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ma-agents",
3
- "version": "3.12.1",
3
+ "version": "3.12.2",
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": {