@mutmutco/cli 4.6.42 → 4.6.44

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/dist/main.cjs +94 -20
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -25273,6 +25273,31 @@ function missingPlaceholders(rendered) {
25273
25273
  for (const m of rendered.matchAll(PLACEHOLDER_RE)) out.add(m[1]);
25274
25274
  return [...out];
25275
25275
  }
25276
+ function seedMatchesReleaseTrack(seed, releaseTrack) {
25277
+ if (!seed.releaseTracks?.length) return true;
25278
+ return releaseTrack != null && seed.releaseTracks.includes(releaseTrack);
25279
+ }
25280
+ var TRAIN_ONLY_BEGIN = "mmi-train-only:start";
25281
+ var TRAIN_ONLY_END = "mmi-train-only:end";
25282
+ function renderSelfSeedForTrack(content, releaseTrack) {
25283
+ if (releaseTrack !== "single") return content;
25284
+ const lines2 = content.split(/(?<=\n)/);
25285
+ const out = [];
25286
+ let skipping = false;
25287
+ for (const line of lines2) {
25288
+ if (!skipping && line.includes(TRAIN_ONLY_BEGIN)) {
25289
+ skipping = true;
25290
+ continue;
25291
+ }
25292
+ if (skipping) {
25293
+ if (line.includes(TRAIN_ONLY_END)) skipping = false;
25294
+ continue;
25295
+ }
25296
+ out.push(line);
25297
+ }
25298
+ if (skipping) throw new Error(`unterminated ${TRAIN_ONLY_BEGIN} region`);
25299
+ return out.join("");
25300
+ }
25276
25301
  function isPropagatableSeed(seed) {
25277
25302
  return seed.ownership === "org" && seed.source === "self" || seed.managedBlock != null;
25278
25303
  }
@@ -26639,6 +26664,7 @@ function withDerivedRepoVars(vars, parsed, cls, releaseTrack, requiredCheckBranc
26639
26664
  out.CLASS ??= cls;
26640
26665
  out.PROJECT_OWNER ??= parsed.owner;
26641
26666
  const track = releaseTrack ?? resolveBootstrapReleaseTrack(cls);
26667
+ out.RELEASE_TRACK ??= track;
26642
26668
  const runtime = out.GATE_RUNTIME === "python" ? "python" : "node";
26643
26669
  for (const [key, value] of Object.entries(gateSeedVars(cls, track, runtime, requiredCheckBranches, requiredChecks))) {
26644
26670
  out[key] ??= value;
@@ -26998,7 +27024,10 @@ function renderBootstrapAncillaryPlan(labels, environments, exceptions = []) {
26998
27024
  ].join("\n");
26999
27025
  }
27000
27026
  function resolveSeedContent(seed, vars, readFile11) {
27001
- if (seed.source === "self") return readFile11(seed.target);
27027
+ if (seed.source === "self") {
27028
+ const own = readFile11(seed.target);
27029
+ return own == null ? null : renderSelfSeedForTrack(own, vars.RELEASE_TRACK);
27030
+ }
27002
27031
  if (seed.source.startsWith("seed:")) {
27003
27032
  const tmpl = readFile11(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
27004
27033
  return tmpl == null ? null : renderSeed(tmpl, vars);
@@ -28527,10 +28556,10 @@ var rollout_plan_default = {
28527
28556
  note: "The v4.0.0 stamp happens at cut time (D6e #4463); until then the candidate is the origin/development head artifacts (built cli/dist + npm pack), identity proven by dist content hash (D6a)."
28528
28557
  },
28529
28558
  baseline: {
28530
- version: "4.6.42",
28531
- tag: "v4.6.42",
28532
- commit: "cb451037f47d",
28533
- npm: "@mutmutco/cli@4.6.42"
28559
+ version: "4.6.44",
28560
+ tag: "v4.6.44",
28561
+ commit: "2ce6b7e5afc3",
28562
+ npm: "@mutmutco/cli@4.6.44"
28534
28563
  },
28535
28564
  exitCriterion: "fleet-n-of-n",
28536
28565
  hubOnlyShortcut: "forbidden",
@@ -28547,14 +28576,14 @@ var rollout_plan_default = {
28547
28576
  repo: "mutmutco/mmi-hub",
28548
28577
  role: "canary",
28549
28578
  schedule: "train",
28550
- v3Target: "v4.6.42"
28579
+ v3Target: "v4.6.44"
28551
28580
  }
28552
28581
  ],
28553
28582
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
28554
28583
  rollback: {
28555
28584
  independent: true,
28556
- mechanism: "npm dist-tag latest -> 4.6.42 and redeploy the Hub Lambda from tag v4.6.42 (cb451037f47d); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28557
- v3Target: "v4.6.42 (@mutmutco/cli@4.6.42, tag commit cb451037f47d \u2014 last known-good release carrying the repo-index v4-only contract)"
28585
+ mechanism: "npm dist-tag latest -> 4.6.44 and redeploy the Hub Lambda from tag v4.6.44 (2ce6b7e5afc3); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28586
+ v3Target: "v4.6.44 (@mutmutco/cli@4.6.44, tag commit 2ce6b7e5afc3 \u2014 last known-good release carrying the repo-index v4-only contract)"
28558
28587
  }
28559
28588
  },
28560
28589
  {
@@ -31670,17 +31699,17 @@ function isBundleOnlySuiteMember(repo, suite) {
31670
31699
  if (!suite) return false;
31671
31700
  return repo.split("/")[1]?.toLowerCase() !== suite.toLowerCase();
31672
31701
  }
31702
+ var MM_GOES_LIVE = "MM-Work and its modules merge to development and it goes live; there is no release, rc or candidate stage.";
31673
31703
  function suiteMemberRefusal(repo, meta, lane, solo = false, cut) {
31674
31704
  const suite = meta?.suite;
31675
31705
  if (!suite) return null;
31676
31706
  if (!isBundleOnlySuiteMember(repo, suite)) {
31677
31707
  if (solo || cut?.token === SUITE_LEAD_TOKEN && cut.repo.toLowerCase() === repo.toLowerCase()) return null;
31678
- const route = lane === "hotfix" ? "hotfix the affected member from its own checkout, then run mmi-cli devops suite release --owner-go" : `run mmi-cli devops suite ${lane} --owner-go`;
31679
- return `${repo} is the ${suite} suite lead; a plain ${lane} would cut it without its members: ${route}. A lead-only ${lane} needs --suite-solo --owner-go.`;
31708
+ return `${repo} is the ${suite} suite lead; ${MM_GOES_LIVE} There is no ${lane} to run: land the change through a normal PR to development and state what landed.`;
31680
31709
  }
31681
31710
  if (authorisedSuiteCut(repo, meta, cut)) return null;
31682
31711
  if (lane !== "rcand" && solo) return null;
31683
- return `${repo} is part of the ${suite} suite; the cut comes from the suite lead ${suiteLeadRepo(repo, suite)}. A suite member never asks for, proposes or prompts an rc, release or hotfix: the suite orchestrator is the only voice that brings a cut to Jervaise, so state what landed and stop. --owner-go and --suite-solo are never self-authorized; only a backward-compatible solo backend release/hotfix with actual owner approval may pass --suite-solo --owner-go.`;
31712
+ return `${repo} is part of the ${suite} suite; ${MM_GOES_LIVE} A suite member never asks for, proposes or prompts an rc, release or hotfix: there is none, so state what landed and stop.`;
31684
31713
  }
31685
31714
 
31686
31715
  // src/tenant-control-parse.ts
@@ -42162,6 +42191,31 @@ function compactRouteManifest(manifest, onlyHouse) {
42162
42191
  }
42163
42192
  };
42164
42193
  }
42194
+ function filterCompactRouteManifest(output, match) {
42195
+ return { ...output, routes: output.routes.filter((route) => match.test(route.path)) };
42196
+ }
42197
+ function pruneManifestTree(node, match) {
42198
+ const subcommands = node.subcommands.map((child2) => pruneManifestTree(child2, match)).filter((child2) => child2 !== void 0);
42199
+ if (match.test(node.name) || match.test(node.path) || subcommands.length > 0) {
42200
+ return { ...node, subcommands };
42201
+ }
42202
+ return void 0;
42203
+ }
42204
+ function filterTreeAndIndex(tree, index, match) {
42205
+ return {
42206
+ tree: pruneManifestTree(tree, match) ?? { ...tree, subcommands: [] },
42207
+ index: index.filter((leaf) => match.test(leaf.name) || match.test(leaf.path))
42208
+ };
42209
+ }
42210
+ function filterCommandManifest(manifest, match) {
42211
+ const full = filterTreeAndIndex(manifest.tree, manifest.index, match);
42212
+ const primary = filterTreeAndIndex(manifest.primary_tree, manifest.primary_index, match);
42213
+ return { ...manifest, tree: full.tree, index: full.index, primary_tree: primary.tree, primary_index: primary.index };
42214
+ }
42215
+ function filterPrimaryCommandManifest(manifest, match) {
42216
+ const filtered = filterTreeAndIndex(manifest.tree, manifest.index, match);
42217
+ return { ...manifest, tree: filtered.tree, index: filtered.index };
42218
+ }
42165
42219
  var DOOR_DECLARATIONS = [
42166
42220
  { door: "board", question: "What is on my board \u2014 and what is next?", path: "board read", source: "the live GitHub Project v2 board, read through the Hub board API" },
42167
42221
  { door: "registry", question: "What repos and projects exist, with what META?", path: "org project list", source: "the Hub org registry (DDB)" },
@@ -51008,7 +51062,7 @@ async function verifyBootstrap(repo, repoClass, deps, releaseTrack) {
51008
51062
  detail: `expected: ${requiredProductRulesetRef} (apply as an active repo ruleset after bootstrap)`
51009
51063
  });
51010
51064
  }
51011
- if (repoClass === "deployable") {
51065
+ if (repoClass === "deployable" && effectiveTrack !== "single") {
51012
51066
  const trainScript = "scripts/next-version.mjs";
51013
51067
  checks.push({ ok: await contentExists2(deps, repo, baseBranch, trainScript), label: `train tooling script exists: ${trainScript}` });
51014
51068
  }
@@ -51734,7 +51788,9 @@ function registerBootstrapCommands(program3) {
51734
51788
  for (const repo of targets) {
51735
51789
  const cls = classOf(repo);
51736
51790
  const meta = metaOf(repo);
51737
- const seeds = byteComparableSeeds(manifest, cls);
51791
+ const track = resolveReleaseTrack(metaWithDeclaredClass(meta, cls), void 0, repo);
51792
+ const seeds = byteComparableSeeds(manifest, cls).filter((s) => seedMatchesReleaseTrack(s, track));
51793
+ const trackHubContents = new Map([...hubContents].map(([t, c]) => [t, c == null ? c : renderSelfSeedForTrack(c, track)]));
51738
51794
  seedsPerRepo = Math.max(seedsPerRepo, seeds.length);
51739
51795
  const baseBranch = cls === "content" ? "main" : "development";
51740
51796
  const reads = [];
@@ -51749,9 +51805,8 @@ function registerBootstrapCommands(program3) {
51749
51805
  }
51750
51806
  reads.push({ target: seed.target, content });
51751
51807
  }
51752
- findings.push(...auditRepoSeedDrift(repo, seeds, hubContents, reads));
51808
+ findings.push(...auditRepoSeedDrift(repo, seeds, trackHubContents, reads));
51753
51809
  findings.push(...declaredRenderWaivers(manifest, repo));
51754
- const track = resolveReleaseTrack(metaWithDeclaredClass(meta, cls), void 0, repo);
51755
51810
  const github = await readBootstrapGitHubFacts(repo, track, controlClient);
51756
51811
  const deployFacts = await fetchDeployFactsBySlug((repo.split("/").pop() ?? repo).toLowerCase(), registryClientDeps(await loadConfig()));
51757
51812
  const controlRows = planBootstrapControlPlane({
@@ -52176,6 +52231,7 @@ function registerBootstrapCommands(program3) {
52176
52231
  if (!seed.classes.includes(o.class)) continue;
52177
52232
  if (!seedMatchesDeployModel(seed, applyDeployModel)) continue;
52178
52233
  if (!seedMatchesProjectType(seed, applyProjectType)) continue;
52234
+ if (!seedMatchesReleaseTrack(seed, vars.RELEASE_TRACK)) continue;
52179
52235
  const waiver = seed.waivers?.[slug];
52180
52236
  if (waiver) {
52181
52237
  actions.push({ action: "skip", target: seed.target, ownership: seed.ownership, reason: `waived: ${waiver}` });
@@ -52670,7 +52726,12 @@ LIVE apply to ${repo}:
52670
52726
  const readSeedFile2 = (path2) => (0, import_node_fs40.existsSync)(path2) ? (0, import_node_fs40.readFileSync)(path2, "utf8") : null;
52671
52727
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
52672
52728
  const { projects, classOf, inClassRepos, canarySlug, sourcePilot } = await propagationScope(seed.classes, `target '${seed.target}'`);
52673
- const repos = inClassRepos.map((repo) => {
52729
+ const trackOf = (repo) => resolveReleaseTrack(
52730
+ projects.find((p) => (p.repos ?? []).some((r) => r.toLowerCase() === repo.toLowerCase())),
52731
+ void 0,
52732
+ repo
52733
+ );
52734
+ const repos = inClassRepos.filter((repo) => seedMatchesReleaseTrack(seed, trackOf(repo))).map((repo) => {
52674
52735
  const slug = repo.split("/").pop().toLowerCase();
52675
52736
  const waiver = seed.waivers?.[slug];
52676
52737
  return { repo, slug, waiver };
@@ -52718,7 +52779,7 @@ LIVE apply to ${repo}:
52718
52779
  }
52719
52780
  desired = resolved.content;
52720
52781
  } else {
52721
- desired = hubContent;
52782
+ desired = renderSelfSeedForTrack(hubContent, trackOf(r.repo));
52722
52783
  }
52723
52784
  desiredByRepo.set(r.repo, desired);
52724
52785
  const drift = compareSeedBytes(desired, content);
@@ -59669,7 +59730,7 @@ function branchRulesReadHint(path2) {
59669
59730
  const match = new RegExp(`^repos/(${NAME})/(${NAME})/(?:rules/branches/[^/?#]+|branches/[^/?#]+/protection(?:/|$)|rulesets(?:/|$))`).exec(path2.split("?")[0]);
59670
59731
  if (!match) return "";
59671
59732
  const slug = `${match[1]}/${match[2]}`;
59672
- return ` No raw rules, rulesets or branch-protection read is on the App allowlist, so retrying path or query variants cannot work \u2014 inspect a PR's required status contexts with \`MMI_ACTOR=app mmi-cli devops pr checks-required <pr> --repo ${slug} --json\`, or verify repository ruleset and branch-protection health with \`mmi-cli devops bootstrap verify --repo ${slug} --json\` and \`mmi-cli devops ci audit --repo ${slug} --json\`.`;
59733
+ return ` No raw rules, rulesets or branch-protection read is on the App allowlist, so retrying path or query variants cannot work \u2014 inspect a PR's required status contexts with \`MMI_ACTOR=app mmi-cli devops pr checks-required <pr> --repo ${slug} --json\`, or verify repository ruleset and branch-protection health with \`mmi-cli devops bootstrap verify --repo ${slug} --json\` and \`mmi-cli devops ci audit --repo ${slug} --json\`. Stepping around it with a raw \`gh api repos/${slug}/rulesets/<id> > file\` is not a substitute \u2014 when that read fails it leaves an EMPTY file, and a later require/JSON.parse throws 'Unexpected end of JSON input' that looks like corrupt data while the real refusal is only on stderr; check the exit code and file size, or ask a human token holder for the raw ruleset body.`;
59673
59734
  }
59674
59735
  function commitsReadHint(path2) {
59675
59736
  const clean4 = path2.split("?")[0];
@@ -73693,11 +73754,24 @@ function registerDeveloperCommands(program3) {
73693
73754
  console.log("mmi-cli devops org rules gitignore: up to date");
73694
73755
  }
73695
73756
  });
73696
- program3.command("commands").description("print the grouped agentic-coding map; JSON defaults to bounded routes").option("--all", "human: include operational depth; JSON: emit the exhaustive schema-2 manifest").option("--json", "machine-readable progressive discovery").option("--primary", "with --json, emit the compatibility schema-2 primary tree and index").addOption(new Option("--house <house>", "with --json, limit routes to one house").choices([...HOUSE_ROOTS, "core"])).action((o) => {
73757
+ program3.command("commands").description("print the grouped agentic-coding map; JSON defaults to bounded routes").option("--all", "human: include operational depth; JSON: emit the exhaustive schema-2 manifest").option("--json", "machine-readable progressive discovery; the compact default emits an OBJECT {schema_version, scope:'routes', routes[{path,house,summary,detail}], houses, doors, next{full:'mmi-cli commands --all --json'}} \u2014 never a top-level `commands` array; --all --json emits the exhaustive schema-2 manifest {scope:'all', tree, index, houses, doors, flat_alias_cut, primary_tree, primary_index, error_codes}").option("--primary", "with --json, emit the compatibility schema-2 primary tree and index").addOption(new Option("--house <house>", "with --json, limit routes to one house").choices([...HOUSE_ROOTS, "core"])).addOption(new Option("--match <regex>", "with --json, keep only routes/commands whose path or name matches this regular expression (case-insensitive)")).action((o) => {
73697
73758
  if (o.house && !o.json) {
73698
73759
  fail("commands: --house requires --json", { code: ERROR_CODES.ERR_CONFLICTING_FLAGS, offending_flag: "--house" });
73699
73760
  return;
73700
73761
  }
73762
+ if (o.match && !o.json) {
73763
+ fail("commands: --match requires --json", { code: ERROR_CODES.ERR_CONFLICTING_FLAGS, offending_flag: "--match" });
73764
+ return;
73765
+ }
73766
+ let match;
73767
+ if (o.match) {
73768
+ try {
73769
+ match = new RegExp(o.match, "i");
73770
+ } catch {
73771
+ fail(`commands: --match '${o.match}' is not a valid regular expression`, { code: ERROR_CODES.ERR_INVALID_INPUT, offending_flag: "--match" });
73772
+ return;
73773
+ }
73774
+ }
73701
73775
  const conflicting = [o.all ? "--all" : "", o.primary ? "--primary" : "", o.house ? "--house" : ""].filter(Boolean);
73702
73776
  if (o.json && conflicting.length > 1) {
73703
73777
  fail(`commands: ${conflicting.join(" and ")} are mutually exclusive`, { code: ERROR_CODES.ERR_CONFLICTING_FLAGS, offending_flag: conflicting.join(",") });
@@ -73705,7 +73779,7 @@ function registerDeveloperCommands(program3) {
73705
73779
  }
73706
73780
  const manifest = buildCommandManifest(program3);
73707
73781
  if (o.json) {
73708
- const output = o.all ? manifest : o.primary ? primaryCommandManifest(manifest) : compactRouteManifest(manifest, o.house);
73782
+ const output = o.all ? match ? filterCommandManifest(manifest, match) : manifest : o.primary ? match ? filterPrimaryCommandManifest(primaryCommandManifest(manifest), match) : primaryCommandManifest(manifest) : match ? filterCompactRouteManifest(compactRouteManifest(manifest, o.house), match) : compactRouteManifest(manifest, o.house);
73709
73783
  consoleIo.log(JSON.stringify(output, null, 2));
73710
73784
  return;
73711
73785
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.6.42",
3
+ "version": "4.6.44",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",