@mutmutco/cli 4.5.130 → 4.5.132

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 +47 -21
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -8162,6 +8162,11 @@ var DECLARED_ENTRIES = [
8162
8162
  // archived stage (including a stage whose containers are down) into scratch Postgres and compare
8163
8163
  // row counts, and read-verify every storage archive against its listing; per-stage PASS/FAIL.
8164
8164
  { name: "mmi-backup-restore-check (mm-central, mm-work)", cadence: "0 3 1 * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-backup-restore-check \u2192 /opt/mmi-control/nightly-backup-restore-check.sh; monthly restore proof for every archived stage (#7148; source scripts/nightly-backup-restore-check.sh); owner-approved mmi-oguz rebuild as CI-only mmi-runner2 with full erasure and no backups (#7859); zuber (46.225.58.31) is gone: deleted 2026-09-18 by the owner-approved ZuberShade decommission (MMC-ZuberShade#1838, snapshot kept); Hetzner has since reassigned that IP to another machine (#7351)" },
8165
+ // #8176: continuous WAL archiving of the mm-work dev Postgres (owner targets RPO <= 5 min, RTO <= 1 h). Postgres copies each
8166
+ // finished WAL file into a host spool (MM-Work#4170); this timer ships it encrypted to the Storage Box with WAL-G.
8167
+ { name: "mmi-walg-ship@mm-work-dev (mm-work)", cadence: "every 30s (systemd OnUnitInactiveSec=30s)", executor: "box systemd", llm: "no", resolved: "declared", source: "/etc/systemd/system/mmi-walg-ship@.timer \u2192 /opt/mmi-control/walg-ship.sh mm-work-dev; spool /srv/mm-work/walspool/mm-work-dev \u2192 Storage Box backups/walg/mmi-tools/mm-work-dev, libsodium-encrypted (#8176; source scripts/walg/; status /var/lib/mmi-backup-status/mm-work-dev.ship.json)" },
8168
+ { name: "mmi-walg-base (mm-work)", cadence: "30 3 * * 0", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-walg-base \u2192 /opt/mmi-control/walg-base.sh mm-work-dev; weekly WAL-G base backup + age-based retention (keep the base at or before now-7d and everything after, #8193) (#8176; source scripts/walg/; log /var/log/mmi-walg.log; status /var/lib/mmi-backup-status/mm-work-dev.base.json)" },
8169
+ { name: "mmi-walg-drill (mm-work)", cadence: "0 4 2 * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-walg-drill \u2192 /opt/mmi-control/walg-drill.sh mm-work-dev; monthly restore drill measuring RPO/RTO against the owner targets (300s/3600s) into a throwaway --network none container (#8177; source scripts/walg/; status /var/lib/mmi-backup-status/mm-work-dev.drill.json; alarm: backup-health.yml)" },
8165
8170
  // #7662 (MM-Work#1520): Vercel Cron's 15-minute central mail call, moved to the box with MM-Work. The app
8166
8171
  // calls its own endpoint with its own CRON_SECRET via docker exec, so the secret stays in the container.
8167
8172
  { name: "mm-work-mail-tick (mm-work)", cadence: "*/15 * * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mm-work-mail-tick \u2192 /opt/mmi-control/mm-work-mail-tick.sh; GET /api/internal/mail per stage listed in MM_WORK_MAIL_STAGES (source scripts/mm-work-mail-tick.sh; log /var/log/mm-work-mail-tick.log)" },
@@ -16681,6 +16686,7 @@ function gateExtraStepsYaml(steps) {
16681
16686
  return steps.map((step) => [
16682
16687
  `
16683
16688
  - name: ${yamlScalar(step.name)}`,
16689
+ "\n if: ${{ steps.development-gate.outputs.reuse != 'true' }}",
16684
16690
  step.env && Object.keys(step.env).length ? `
16685
16691
  env:${envYaml(step.env, " ")}` : "",
16686
16692
  "\n uses: mutmutco/MMI-Hub/.github/actions/run-with-budget@{{GATE_BUDGET_SHA}}",
@@ -17240,23 +17246,33 @@ async function installAppFoldDeps(deps) {
17240
17246
  }
17241
17247
  var SHARED_INSTALLER_PACKAGES = ["@mutmutco/installer-face", "@mutmutco/installer-launcher", "@mutmutco/installer-gate"];
17242
17248
  async function refreshSharedInstallerDeps(deps) {
17243
- let declared;
17249
+ let lockPaths;
17244
17250
  try {
17245
- const lock = JSON.parse(await deps.run("git", ["show", "HEAD:package-lock.json"]));
17246
- const present = Object.keys(lock.packages ?? {});
17247
- declared = SHARED_INSTALLER_PACKAGES.filter((name) => present.some((key) => key === `node_modules/${name}` || key.endsWith(`/node_modules/${name}`)));
17248
- } catch {
17249
- return null;
17250
- }
17251
- if (declared.length === 0) return null;
17252
- try {
17253
- await deps.run("npm", ["update", ...declared, "--package-lock-only", "--no-audit", "--no-fund"]);
17251
+ lockPaths = (await deps.run("git", ["ls-tree", "-r", "--name-only", "HEAD"])).split("\n").filter((path2) => path2 === "package-lock.json" || path2.endsWith("/package-lock.json"));
17254
17252
  } catch (e) {
17255
- const why = e instanceof Error ? e.message.split("\n")[0] : String(e);
17256
- deps.warn?.(`shared installer refresh skipped (${why}) \u2014 shipping the locked versions`);
17257
- return `shared installer refresh skipped (${why}); the locked ${declared.join(", ")} still satisfy their ranges`;
17253
+ throw trainReadFailure(
17254
+ "shared installer refresh: `git ls-tree -r --name-only HEAD`",
17255
+ e,
17256
+ "rerun in a readable checkout \u2014 lockfile roots must be discovered, never guessed"
17257
+ );
17258
+ }
17259
+ const notes = [];
17260
+ for (const lockPath of lockPaths) {
17261
+ const lock = JSON.parse(await deps.run("git", ["show", `HEAD:${lockPath}`]));
17262
+ const present = Object.keys(lock.packages ?? {});
17263
+ const declared = SHARED_INSTALLER_PACKAGES.filter((name) => present.some((key) => key === `node_modules/${name}` || key.endsWith(`/node_modules/${name}`)));
17264
+ if (declared.length === 0) continue;
17265
+ const prefix = lockPath.includes("/") ? lockPath.slice(0, lockPath.lastIndexOf("/")) : null;
17266
+ try {
17267
+ await deps.run("npm", [...prefix ? ["--prefix", prefix] : [], "update", ...declared, "--package-lock-only", "--no-audit", "--no-fund"]);
17268
+ notes.push(`shared installer deps refreshed in ${prefix ?? "."} (${declared.join(", ")})`);
17269
+ } catch (e) {
17270
+ const why = e instanceof Error ? e.message.split("\n")[0] : String(e);
17271
+ deps.warn?.(`shared installer refresh skipped for ${prefix ?? "."} (${why}) \u2014 shipping the locked versions`);
17272
+ notes.push(`shared installer refresh skipped for ${prefix ?? "."} (${why}); the locked ${declared.join(", ")} still satisfy their ranges`);
17273
+ }
17258
17274
  }
17259
- return `shared installer deps refreshed to the newest their ranges allow (${declared.join(", ")})`;
17275
+ return notes.length > 0 ? notes.join("; ") : null;
17260
17276
  }
17261
17277
  async function restoreMainNpmPackIdentities(deps, version) {
17262
17278
  const bomPath = "distribution-bom.json";
@@ -18258,10 +18274,10 @@ var rollout_plan_default = {
18258
18274
  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)."
18259
18275
  },
18260
18276
  baseline: {
18261
- version: "4.5.130",
18262
- tag: "v4.5.130",
18263
- commit: "6564bc03d8ee",
18264
- npm: "@mutmutco/cli@4.5.130"
18277
+ version: "4.5.132",
18278
+ tag: "v4.5.132",
18279
+ commit: "80a4c6f78d39",
18280
+ npm: "@mutmutco/cli@4.5.132"
18265
18281
  },
18266
18282
  exitCriterion: "fleet-n-of-n",
18267
18283
  hubOnlyShortcut: "forbidden",
@@ -18278,14 +18294,14 @@ var rollout_plan_default = {
18278
18294
  repo: "mutmutco/mmi-hub",
18279
18295
  role: "canary",
18280
18296
  schedule: "train",
18281
- v3Target: "v4.5.130"
18297
+ v3Target: "v4.5.132"
18282
18298
  }
18283
18299
  ],
18284
18300
  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.",
18285
18301
  rollback: {
18286
18302
  independent: true,
18287
- mechanism: "npm dist-tag latest -> 4.5.130 and redeploy the Hub Lambda from tag v4.5.130 (6564bc03d8ee); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18288
- v3Target: "v4.5.130 (@mutmutco/cli@4.5.130, tag commit 6564bc03d8ee \u2014 last known-good release carrying the repo-index v4-only contract)"
18303
+ mechanism: "npm dist-tag latest -> 4.5.132 and redeploy the Hub Lambda from tag v4.5.132 (80a4c6f78d39); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18304
+ v3Target: "v4.5.132 (@mutmutco/cli@4.5.132, tag commit 80a4c6f78d39 \u2014 last known-good release carrying the repo-index v4-only contract)"
18289
18305
  }
18290
18306
  },
18291
18307
  {
@@ -29517,10 +29533,17 @@ ${r.repo} (${r.class}, policy=${r.mergePolicy}) ${verdict}`);
29517
29533
  }
29518
29534
  return lines2.join("\n");
29519
29535
  }
29536
+ function unauditedReconcileError(reason) {
29537
+ return `cannot audit \u2014 ${reason}; no reconcile change made (unaudited, not canonical)`;
29538
+ }
29520
29539
  async function applyCiReconcileMergeSettingsFromReport(repo, deps, report) {
29521
29540
  const applied = [];
29522
29541
  const skipped = [];
29523
29542
  const errors = [];
29543
+ if (report.unauditedReason) {
29544
+ errors.push(unauditedReconcileError(report.unauditedReason));
29545
+ return { repo, applied, skipped, errors };
29546
+ }
29524
29547
  const mergeChecks = report.checks.filter((c) => c.label.startsWith("allow_") || c.label.startsWith("delete_branch") || c.label.startsWith("has_wiki"));
29525
29548
  const needsPatch = mergeChecks.some((c) => !c.ok);
29526
29549
  if (!needsPatch) {
@@ -29824,6 +29847,9 @@ async function applyCiReconcileRepo(repo, deps, options = {}) {
29824
29847
  return { repo, applied: [], skipped: [], errors: ["product-ruleset requires registry META requiredChecks"] };
29825
29848
  }
29826
29849
  const report = await auditRepoCi(repo, deps);
29850
+ if (report.unauditedReason) {
29851
+ return { repo, applied: [], skipped: [], errors: [unauditedReconcileError(report.unauditedReason)] };
29852
+ }
29827
29853
  const finish = (result2, pendingReason) => options.productRulesetOnly ? Promise.resolve(result2) : finalizeCiReconcile(repo, deps, result2, report, pendingReason);
29828
29854
  const baseBranch = "development";
29829
29855
  let raw = report.class === "deployable" && !report.explicitNoCi ? await fetchRulesetSeedBody(deps, repo) : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.130",
3
+ "version": "4.5.132",
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",