@mutmutco/cli 4.0.0 → 4.0.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.
Files changed (2) hide show
  1. package/dist/main.cjs +92 -26
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -8237,6 +8237,25 @@ function awsScheduleRefs(payload) {
8237
8237
  }
8238
8238
  return refs;
8239
8239
  }
8240
+ function decorateAwsModel(entries, registry2, verdicts) {
8241
+ if (!registry2 || registry2.length === 0) return [...entries];
8242
+ const rowById = new Map(registry2.map((r) => [r.id, r]));
8243
+ const literalById = /* @__PURE__ */ new Map();
8244
+ for (const v of verdicts ?? []) {
8245
+ if (typeof v.modelId === "string" && v.modelId.trim() && !literalById.has(v.id)) {
8246
+ literalById.set(v.id, v.modelId);
8247
+ }
8248
+ }
8249
+ return entries.map((e) => {
8250
+ if (!e.scheduleId) return e;
8251
+ const row = rowById.get(e.scheduleId);
8252
+ if (!row || row.executor !== "cursor-agent") return e;
8253
+ const literal = literalById.get(e.scheduleId);
8254
+ if (literal) return { ...e, model: literal };
8255
+ if (row.model) return { ...e, model: `role: ${row.model}` };
8256
+ return { ...e, model: "org-default" };
8257
+ });
8258
+ }
8240
8259
  var DECLARED_ENTRIES = [
8241
8260
  { name: "mmi-backup (mm-central, mmi-fofu, zuber, mmi-oguz)", cadence: "17 2 * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-backup \u2192 /opt/mmi-control/nightly-backup.sh (verify: mmi-cli devops runtime box get <box> --ssh)" },
8242
8261
  // #3370: the floor under runner-hygiene.yml. That workflow runs ON the runner and needs checkout +
@@ -8247,8 +8266,16 @@ var DECLARED_ENTRIES = [
8247
8266
  // #4118: Listening + systemd-active ≠ GitHub online after acquirejob 503. restart.conf cannot see
8248
8267
  // it; an Actions workflow on mmi-live cannot heal it when half the fleet is offline. Root cron.
8249
8268
  { name: "mmi-runner-online-reconcile (mmi-runner)", cadence: "*/5 * * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-runner-online \u2192 /opt/mmi-control/runner-online-reconcile.sh; API-offline + _diag acquirejob, max 2 restarts/tick (verify: mmi-cli devops runtime box get mmi-runner --ssh)" },
8250
- { name: "zuber-bake", cadence: "*:05/30 (every 30 min)", executor: "zuber systemd timer", llm: "no", resolved: "declared", source: "zuber-bake.timer \u2192 rolling overlay bake, metro tier, next ~6h window (verify over ssh)" },
8251
- { name: "zuber-bake-full", cadence: "00:30 UTC (03:30 TRT, daily)", executor: "zuber systemd timer", llm: "no", resolved: "declared", source: "zuber-bake-full.timer \u2192 full 24h overlay rebuild, all 81 il (verify over ssh)" }
8269
+ // #3852: the runner /tmp sweep daily inode hygiene (03:41 UTC), deliberately the one clutter path the
8270
+ // out-of-band disk-relief script must never touch. Verified installed 2026-08-18: the cron.d file and
8271
+ // flock line match scripts/runner-tmp-sweep.cron exactly.
8272
+ { name: "mmi-runner-tmp-sweep (mmi-runner)", cadence: "41 3 * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-runner-tmp-sweep \u2192 /opt/mmi-control/runner-tmp-sweep.sh; daily inode hygiene, flock -n (verify: mmi-cli devops runtime box get mmi-runner --ssh)" }
8273
+ // RETIRED 2026-08-18 (MMI-Hub#5234): `zuber-bake` (every 30 min) and `zuber-bake-full` (daily 00:30 UTC)
8274
+ // were declared as zuber systemd timers. The ZuberShade full park (#1774, 2026-08-06) stopped them: on
8275
+ // the box (46.225.58.31) zuber-bake.timer / zuber-bake-full.timer answer not-found and
8276
+ // zuber-bake-demand.timer is disabled — no bake/oven timer remains armed, and the notebook must not
8277
+ // claim a job the box does not run. Re-add when the hold lifts and the demand bake re-arms
8278
+ // (MMC-ZuberShade docs/aws-teardown-hold-2026-08-03.md).
8252
8279
  ];
8253
8280
  function sortEntries(entries) {
8254
8281
  return [...entries].sort(
@@ -8263,10 +8290,12 @@ function formatSchedulesTable(entries, now = /* @__PURE__ */ new Date()) {
8263
8290
  const cadW = w((e) => e.cadence, "CADENCE");
8264
8291
  const exeW = w((e) => e.executor, "EXECUTOR");
8265
8292
  const llmW = w((e) => e.llm, "LLM");
8293
+ const modelOf = (e) => e.model ?? "-";
8294
+ const modW = w((e) => modelOf(e), "MODEL");
8266
8295
  const resW = w((e) => resolvedOf.get(e) ?? e.resolved, "RESOLVED");
8267
- const row = (n, c, x, l, r, s) => `${n.padEnd(nameW)} ${c.padEnd(cadW)} ${x.padEnd(exeW)} ${l.padEnd(llmW)} ${r.padEnd(resW)} ${s}`;
8268
- const lines = [row("JOB", "CADENCE", "EXECUTOR", "LLM", "RESOLVED", "SOURCE")];
8269
- for (const e of entries) lines.push(row(e.name, e.cadence, e.executor, e.llm, resolvedOf.get(e) ?? e.resolved, e.source));
8296
+ const row = (n, c, x, l, m, r, s) => `${n.padEnd(nameW)} ${c.padEnd(cadW)} ${x.padEnd(exeW)} ${l.padEnd(llmW)} ${m.padEnd(modW)} ${r.padEnd(resW)} ${s}`;
8297
+ const lines = [row("JOB", "CADENCE", "EXECUTOR", "LLM", "MODEL", "RESOLVED", "SOURCE")];
8298
+ for (const e of entries) lines.push(row(e.name, e.cadence, e.executor, e.llm, modelOf(e), resolvedOf.get(e) ?? e.resolved, e.source));
8270
8299
  return lines.join("\n");
8271
8300
  }
8272
8301
  function withTickState(entry, now = /* @__PURE__ */ new Date()) {
@@ -8274,11 +8303,11 @@ function withTickState(entry, now = /* @__PURE__ */ new Date()) {
8274
8303
  }
8275
8304
  function renderDocSection(entries, generatedAtIso) {
8276
8305
  const lines = [
8277
- "| Job | Cadence | Executor | LLM | Resolved | Source |",
8278
- "|---|---|---|---|---|---|"
8306
+ "| Job | Cadence | Executor | LLM | Model | Resolved | Source |",
8307
+ "|---|---|---|---|---|---|---|"
8279
8308
  ];
8280
8309
  for (const e of entries) {
8281
- lines.push(`| ${e.name} | \`${e.cadence}\` | ${e.executor} | ${e.llm} | ${e.resolved} | ${e.source} |`);
8310
+ lines.push(`| ${e.name} | \`${e.cadence}\` | ${e.executor} | ${e.llm} | ${e.model ?? "-"} | ${e.resolved} | ${e.source} |`);
8282
8311
  }
8283
8312
  return [
8284
8313
  DOC_START_MARKER,
@@ -8694,6 +8723,22 @@ async function fetchSchedulesList(deps) {
8694
8723
  return null;
8695
8724
  }
8696
8725
  }
8726
+ async function fetchRunVerdicts(deps) {
8727
+ if (!deps.baseUrl) return null;
8728
+ const token = await deps.token();
8729
+ if (!token) return null;
8730
+ try {
8731
+ const res = await retriedFetch(deps, `${deps.baseUrl.replace(/\/$/, "")}/schedules/verdicts`, {
8732
+ method: "GET",
8733
+ headers: { Authorization: `Bearer ${token}` }
8734
+ });
8735
+ if (!res.ok) return null;
8736
+ const body = await res.json();
8737
+ return Array.isArray(body?.runVerdicts) ? body.runVerdicts : null;
8738
+ } catch {
8739
+ return null;
8740
+ }
8741
+ }
8697
8742
  async function fetchOrgConfig(deps) {
8698
8743
  if (!deps.baseUrl) return null;
8699
8744
  const token = await deps.token();
@@ -10774,10 +10819,10 @@ var rollout_plan_default = {
10774
10819
  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)."
10775
10820
  },
10776
10821
  baseline: {
10777
- version: "4.0.0",
10778
- tag: "v4.0.0",
10779
- commit: "71c720103455",
10780
- npm: "@mutmutco/cli@4.0.0"
10822
+ version: "4.0.2",
10823
+ tag: "v4.0.2",
10824
+ commit: "e703fd090be7",
10825
+ npm: "@mutmutco/cli@4.0.2"
10781
10826
  },
10782
10827
  exitCriterion: "fleet-n-of-n",
10783
10828
  hubOnlyShortcut: "forbidden",
@@ -10794,14 +10839,14 @@ var rollout_plan_default = {
10794
10839
  repo: "mutmutco/mmi-hub",
10795
10840
  role: "canary",
10796
10841
  schedule: "train",
10797
- v3Target: "v4.0.0"
10842
+ v3Target: "v4.0.2"
10798
10843
  }
10799
10844
  ],
10800
10845
  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.",
10801
10846
  rollback: {
10802
10847
  independent: true,
10803
- mechanism: "npm dist-tag latest -> 4.0.0 and redeploy the Hub Lambda from tag v4.0.0 (71c720103455); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
10804
- v3Target: "v4.0.0 (@mutmutco/cli@4.0.0, tag commit 71c720103455 \u2014 last known-good release carrying the repo-index v4-only contract)"
10848
+ mechanism: "npm dist-tag latest -> 4.0.2 and redeploy the Hub Lambda from tag v4.0.2 (e703fd090be7); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
10849
+ v3Target: "v4.0.2 (@mutmutco/cli@4.0.2, tag commit e703fd090be7 \u2014 last known-good release carrying the repo-index v4-only contract)"
10805
10850
  }
10806
10851
  },
10807
10852
  {
@@ -23516,16 +23561,23 @@ async function probeRepoIndexV4ReadinessCloud(queries, deps) {
23516
23561
  if (!token) return { ok: false, error: "no Hub session token (run `gh auth login`)" };
23517
23562
  const baseUrl = deps.baseUrl.replace(/\/$/, "");
23518
23563
  const headers = { ...clientVersionHeaders(), Authorization: ["Bearer", token].join(" "), "content-type": "application/json" };
23519
- try {
23564
+ const shadowPass = async () => {
23520
23565
  for (const query of queries) {
23521
- const res2 = await fetchWithRetry(deps.fetch ?? fetch, `${baseUrl}/repo-index/v4/shadow`, {
23566
+ const res = await fetchWithRetry(deps.fetch ?? fetch, `${baseUrl}/repo-index/v4/shadow`, {
23522
23567
  method: "POST",
23523
23568
  headers,
23524
23569
  body: JSON.stringify({ q: query.query, mode: query.mode, readinessProbe: true })
23525
23570
  }, { attempts: RETRY_ATTEMPTS2, timeoutMs: 12e4, sleep: deps.retrySleep });
23526
- const body2 = await res2.json().catch(() => ({}));
23527
- if (!res2.ok) return { ok: false, error: `${query.id}: ${body2.error ?? `v4 readiness probe HTTP ${res2.status}`}${body2.errorClass ? ` (${body2.errorClass})` : ""}`, status: res2.status };
23571
+ const body = await res.json().catch(() => ({}));
23572
+ if (!res.ok) return { ok: false, error: `${query.id}: ${body.error ?? `v4 readiness probe HTTP ${res.status}`}${body.errorClass ? ` (${body.errorClass})` : ""}`, status: res.status };
23528
23573
  }
23574
+ return { ok: true };
23575
+ };
23576
+ try {
23577
+ const warmup = await shadowPass();
23578
+ if (!warmup.ok) return warmup;
23579
+ const verdict = await shadowPass();
23580
+ if (!verdict.ok) return verdict;
23529
23581
  const res = await fetchWithRetry(deps.fetch ?? fetch, `${baseUrl}/repo-index/status`, {
23530
23582
  method: "GET",
23531
23583
  headers: { ...clientVersionHeaders(), Authorization: ["Bearer", token].join(" ") }
@@ -23534,8 +23586,8 @@ async function probeRepoIndexV4ReadinessCloud(queries, deps) {
23534
23586
  if (!res.ok) return { ok: false, error: body.error ?? `v4 readiness status HTTP ${res.status}`, status: res.status };
23535
23587
  const readiness = body.v4Readiness;
23536
23588
  const complete = !!readiness && ["ready", "not-ready"].includes(readiness.verdict) && Array.isArray(readiness.reasons) && Number.isFinite(readiness.goldenCount) && Number.isFinite(readiness.evidenceCount) && !!readiness.modes && ["lexical", "semantic", "hybrid"].every((mode) => {
23537
- const verdict = readiness.modes[mode]?.verdict;
23538
- return verdict === "ready" || verdict === "not-ready";
23589
+ const verdict2 = readiness.modes[mode]?.verdict;
23590
+ return verdict2 === "ready" || verdict2 === "not-ready";
23539
23591
  });
23540
23592
  if (!complete) return { ok: false, error: "Hub status omitted the explicit v4 readiness verdict/reasons/modes contract", status: res.status };
23541
23593
  return { ok: true, readiness };
@@ -26508,12 +26560,20 @@ async function readOrFail(read) {
26508
26560
  async function defaultRegistryRead() {
26509
26561
  return fetchSchedulesList(registryClientDeps(await loadConfig()));
26510
26562
  }
26511
- async function fetchNotebook(client = defaultGitHubClient(), readRegistry = defaultRegistryRead, readProjects = defaultProjectsRead) {
26512
- const [gh, aws, registryRead, projectsRead] = await Promise.all([
26563
+ async function defaultRunVerdictRead() {
26564
+ return fetchRunVerdicts(registryClientDeps(await loadConfig()));
26565
+ }
26566
+ function modelRoleKeyOf(row) {
26567
+ const model = row.model;
26568
+ return typeof model === "string" && model.trim() ? model : void 0;
26569
+ }
26570
+ async function fetchNotebook(client = defaultGitHubClient(), readRegistry = defaultRegistryRead, readProjects = defaultProjectsRead, readRunVerdicts = defaultRunVerdictRead) {
26571
+ const [gh, aws, registryRead, projectsRead, runVerdictRead] = await Promise.all([
26513
26572
  githubEntries(client),
26514
26573
  awsEntries(),
26515
26574
  readOrFail(readRegistry),
26516
- readOrFail(readProjects)
26575
+ readOrFail(readProjects),
26576
+ readOrFail(readRunVerdicts)
26517
26577
  ]);
26518
26578
  const readFailures = [];
26519
26579
  if (registryRead.state === "failed") {
@@ -26523,10 +26583,16 @@ async function fetchNotebook(client = defaultGitHubClient(), readRegistry = defa
26523
26583
  readFailures.push(`registry: could not read the projects list \u2014 schedulesMode opt-outs unresolved (nothing suppressed) \u2014 ${projectsRead.error}`);
26524
26584
  }
26525
26585
  const registry2 = registryRead.state === "ok" ? registryRead.value : null;
26586
+ const runVerdicts = runVerdictRead.state === "ok" ? runVerdictRead.value : null;
26526
26587
  const projects = projectsRead.state === "ok" ? projectsRead.value : null;
26588
+ const decoratedAws = decorateAwsModel(
26589
+ aws.entries,
26590
+ registry2?.map((r) => ({ id: r.id, executor: r.executor, model: modelRoleKeyOf(r) })) ?? null,
26591
+ runVerdicts
26592
+ );
26527
26593
  const recon = assembleReconciliation(gh.entries, new Set(gh.readRepos), registry2, new Set(gh.workflowNames), {
26528
26594
  // #3286: the harbour side joins registry rows against the live aws-scheduler clocks by scheduleId.
26529
- awsEntries: aws.entries,
26595
+ awsEntries: decoratedAws,
26530
26596
  schedulerRead: Boolean(aws.schedulerRead)
26531
26597
  }, new Set(gh.disabledWorkflowNames));
26532
26598
  const selfManaged = /* @__PURE__ */ new Set();
@@ -26540,7 +26606,7 @@ async function fetchNotebook(client = defaultGitHubClient(), readRegistry = defa
26540
26606
  );
26541
26607
  const driftLines = reconciliation.map(renderDrift);
26542
26608
  return {
26543
- entries: sortEntries([...gh.entries, ...aws.entries, ...DECLARED_ENTRIES]),
26609
+ entries: sortEntries([...gh.entries, ...decoratedAws, ...DECLARED_ENTRIES]),
26544
26610
  incomplete: [...gh.incomplete, ...aws.incomplete, ...recon.incomplete, ...readFailures],
26545
26611
  drift: driftLines,
26546
26612
  reconciliation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
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",