@mutmutco/codex-plugin 4.5.95 → 4.5.96
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.
- package/.codex-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +26 -24
- package/cli/package.json +1 -1
- package/package.json +1 -1
package/cli/dist/main.cjs
CHANGED
|
@@ -7460,11 +7460,11 @@ function workflowEntry(repo, workflowPath, yamlText) {
|
|
|
7460
7460
|
};
|
|
7461
7461
|
}
|
|
7462
7462
|
var DECLARED_ENTRIES = [
|
|
7463
|
-
{ name: "mmi-backup (mm-central, mm-work
|
|
7463
|
+
{ name: "mmi-backup (mm-central, mm-work)", cadence: "17 2 * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-backup \u2192 /opt/mmi-control/nightly-backup.sh; every Docker volume is tarred and every running Postgres container is pg_dumpall'd beside it (#7147; source scripts/nightly-backup.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)" },
|
|
7464
7464
|
// #7148: a backup nobody restored is a hope. Monthly, restore the latest artifact of every
|
|
7465
7465
|
// archived stage (including a stage whose containers are down) into scratch Postgres and compare
|
|
7466
7466
|
// row counts, and read-verify every storage archive against its listing; per-stage PASS/FAIL.
|
|
7467
|
-
{ name: "mmi-backup-restore-check (mm-central, mm-work
|
|
7467
|
+
{ 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)" },
|
|
7468
7468
|
// #7662 (MM-Work#1520): Vercel Cron's 15-minute central mail call, moved to the box with MM-Work. The app
|
|
7469
7469
|
// calls its own endpoint with its own CRON_SECRET via docker exec, so the secret stays in the container.
|
|
7470
7470
|
{ 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)" },
|
|
@@ -7472,10 +7472,11 @@ var DECLARED_ENTRIES = [
|
|
|
7472
7472
|
// setup-node before it can prune, so at 100% it dies at checkout and never prunes — the cleanup is
|
|
7473
7473
|
// unavailable exactly when it is needed. This one is root cron on the box: no checkout, no node, and
|
|
7474
7474
|
// a no-op below 90% disk, which is why 15 minutes is affordable.
|
|
7475
|
-
{ name: "mmi-runner-hygiene-oob (mmi-runner)", cadence: "*/15 * * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-runner-hygiene \u2192 /opt/mmi-control/runner-hygiene-oob.sh; routine docker/cache prunes every
|
|
7475
|
+
{ name: "mmi-runner-hygiene-oob (mmi-runner, mmi-runner2)", cadence: "*/15 * * * * + 5-59/15,10-59/15 * * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-runner-hygiene \u2192 /opt/mmi-control/runner-hygiene-oob.sh; routine docker/cache prunes every 15 min, relief-only pressure checks between, _work relief at >=90% disk or <8 GiB free; second-host rollout #7859 (verify each box via mmi-cli devops runtime box get <box> --ssh)" },
|
|
7476
7476
|
// #4118: Listening + systemd-active ≠ GitHub online after acquirejob 503. restart.conf cannot see
|
|
7477
7477
|
// it; an Actions workflow on mmi-live cannot heal it when half the fleet is offline. Root cron.
|
|
7478
7478
|
{ 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)" },
|
|
7479
|
+
{ name: "mmi-runner-online-reconcile (mmi-runner2)", 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; scripts/runner2-online-reconcile.cron selects lanes 13-16, disables credential files, _diag acquirejob only, max 2 restarts/tick; rollout #7859 (verify: mmi-cli devops runtime box get mmi-runner2 --ssh)" },
|
|
7479
7480
|
// #5292: a lane that holds a dispatched JOB but produces zero output past the budget honestly
|
|
7480
7481
|
// reports "busy", so the online reconcile never fires and GitHub will not re-dispatch while the
|
|
7481
7482
|
// run holds the assignment. This tick cancels + re-triggers those runs (max 1/tick, debounced).
|
|
@@ -7483,7 +7484,7 @@ var DECLARED_ENTRIES = [
|
|
|
7483
7484
|
// #3852: the runner /tmp sweep — daily inode hygiene (03:41 UTC), deliberately the one clutter path the
|
|
7484
7485
|
// out-of-band disk-relief script must never touch. Verified installed 2026-08-18: the cron.d file and
|
|
7485
7486
|
// flock line match scripts/runner-tmp-sweep.cron exactly.
|
|
7486
|
-
{ name: "mmi-runner-tmp-sweep (mmi-runner)", cadence: "41 * * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-runner-tmp-sweep \u2192 /opt/mmi-control/runner-tmp-sweep.sh; hourly inode hygiene, 6h age (#6274), flock -n (verify
|
|
7487
|
+
{ name: "mmi-runner-tmp-sweep (mmi-runner, mmi-runner2)", cadence: "41 * * * *", executor: "box cron.d", llm: "no", resolved: "declared", source: "/etc/cron.d/mmi-runner-tmp-sweep \u2192 /opt/mmi-control/runner-tmp-sweep.sh; hourly inode hygiene, 6h age (#6274), flock -n; second-host rollout #7859 (verify each box via mmi-cli devops runtime box get <box> --ssh)" }
|
|
7487
7488
|
// RETIRED 2026-08-18 (MMI-Hub#5234): `zuber-bake` (every 30 min) and `zuber-bake-full` (daily 00:30 UTC)
|
|
7488
7489
|
// were declared as zuber systemd timers. The ZuberShade full park (#1774, 2026-08-06) stopped them: on
|
|
7489
7490
|
// the box (46.225.58.31) zuber-bake.timer / zuber-bake-full.timer answer not-found and
|
|
@@ -17255,10 +17256,10 @@ var rollout_plan_default = {
|
|
|
17255
17256
|
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)."
|
|
17256
17257
|
},
|
|
17257
17258
|
baseline: {
|
|
17258
|
-
version: "4.5.
|
|
17259
|
-
tag: "v4.5.
|
|
17260
|
-
commit: "
|
|
17261
|
-
npm: "@mutmutco/cli@4.5.
|
|
17259
|
+
version: "4.5.96",
|
|
17260
|
+
tag: "v4.5.96",
|
|
17261
|
+
commit: "191fc3cf3396",
|
|
17262
|
+
npm: "@mutmutco/cli@4.5.96"
|
|
17262
17263
|
},
|
|
17263
17264
|
exitCriterion: "fleet-n-of-n",
|
|
17264
17265
|
hubOnlyShortcut: "forbidden",
|
|
@@ -17275,14 +17276,14 @@ var rollout_plan_default = {
|
|
|
17275
17276
|
repo: "mutmutco/mmi-hub",
|
|
17276
17277
|
role: "canary",
|
|
17277
17278
|
schedule: "train",
|
|
17278
|
-
v3Target: "v4.5.
|
|
17279
|
+
v3Target: "v4.5.96"
|
|
17279
17280
|
}
|
|
17280
17281
|
],
|
|
17281
17282
|
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.",
|
|
17282
17283
|
rollback: {
|
|
17283
17284
|
independent: true,
|
|
17284
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
17285
|
-
v3Target: "v4.5.
|
|
17285
|
+
mechanism: "npm dist-tag latest -> 4.5.96 and redeploy the Hub Lambda from tag v4.5.96 (191fc3cf3396); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
17286
|
+
v3Target: "v4.5.96 (@mutmutco/cli@4.5.96, tag commit 191fc3cf3396 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
17286
17287
|
}
|
|
17287
17288
|
},
|
|
17288
17289
|
{
|
|
@@ -37015,8 +37016,8 @@ function bothSidesText(portFailures, portLaneShas) {
|
|
|
37015
37016
|
if (rows.length === 0) return "";
|
|
37016
37017
|
return `BEFORE that --ack: ${rows.map((r) => `${r.label} also conflicts on ${r.paths.join(", ")}`).join("; ")}, which exist on both branches \u2014 the port resolves them by hand for main, so land the SAME resolution on development first (the --ack covers the whole commit, and the next release would otherwise overwrite or clash with the main-only content). `;
|
|
37017
37018
|
}
|
|
37018
|
-
function formatHotfixBatchPreflightRefusal(failures, fromSpecs, portLaneShas = /* @__PURE__ */ new Map()) {
|
|
37019
|
-
const lines2 = failures.map((f) => ` - ${f.label}: ${f.blocking.join(", ")}`);
|
|
37019
|
+
function formatHotfixBatchPreflightRefusal(failures, fromSpecs, portLaneShas = /* @__PURE__ */ new Map(), context = { sources: failures, ackedShas: [] }) {
|
|
37020
|
+
const lines2 = failures.map((f) => ` - ${f.label}: ${f.blocking.join(", ")}` + (f.afterAbortedPicks?.length ? ` (observed after aborted pick(s): ${f.afterAbortedPicks.join(", ")}; may depend on those missing changes)` : ""));
|
|
37020
37021
|
const portFailures = failures.filter((f) => portLaneShas.has(f.sha));
|
|
37021
37022
|
const synthFailures = failures.filter((f) => !portLaneShas.has(f.sha));
|
|
37022
37023
|
const head = `hotfix start batch preflight refused: ${failures.length} pick(s) would hard-stop on origin/main:
|
|
@@ -37024,15 +37025,15 @@ ${lines2.join("\n")}
|
|
|
37024
37025
|
`;
|
|
37025
37026
|
const batchFrom = fromSpecs.join(",");
|
|
37026
37027
|
const guide = "https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#hotfix-pick-refused";
|
|
37027
|
-
|
|
37028
|
-
|
|
37029
|
-
|
|
37030
|
-
|
|
37031
|
-
|
|
37032
|
-
|
|
37033
|
-
|
|
37034
|
-
${
|
|
37035
|
-
|
|
37028
|
+
const replaceNow = failures.filter((f) => !f.afterAbortedPicks?.length);
|
|
37029
|
+
const replacements = new Map(replaceNow.map((f, i) => [f.sha, `<replacementSHA${i + 1}>`]));
|
|
37030
|
+
const picks = context.sources.map((s) => replacements.get(s.sha) ?? s.sha).join(",");
|
|
37031
|
+
const exclusions = [.../* @__PURE__ */ new Set([...context.ackedShas, ...replaceNow.map((f) => f.sha)])].join(",");
|
|
37032
|
+
const mapping = replaceNow.map((f) => `${replacements.get(f.sha)} replaces ${f.label} (${f.sha})`).join("; ");
|
|
37033
|
+
const dependencyNote = failures.some((f) => f.afterAbortedPicks?.length) ? "Later failures were observed after earlier picks were aborted. Keep those original SHAs in the retry. Re-preflight the complete repaired batch before treating a later path absent on static origin/main as an independent port requirement. If a later pick still fails, replacing it requires separate approval for its exact original SHA. " : "";
|
|
37034
|
+
const portText = portFailures.length > 0 ? `Pick(s) ${portFailures.map((f) => f.label).join(", ")} have path(s) ABSENT on origin/main but present on origin/development. If they still fail after prerequisite repairs, use the main-based PORT-COMMIT lane: cut a branch FROM origin/main, add the missing paths and fix, push it and keep it pushed until the release \u2014 never merge it into development. Record the port SHA in the hotfix PR body. The NEXT rc\u2192main release must pass \`--ack <the hotfix's main commit>\` (hotfix-coverage). ` + bothSidesText(portFailures, portLaneShas) : "";
|
|
37035
|
+
const repairText = synthFailures.length > 0 ? `Pick(s) ${synthFailures.map((f) => f.label).join(", ")} need a development repair PR: cut FROM origin/development and land the conflict correction through normal CI. Its picked commit must carry the required main-clean delta; merely citing the original fixes carries no content and grants no coverage exemption. If that delta cannot be produced on development, stop and ask the owner for a scoped port plan. ` : "";
|
|
37036
|
+
return `${head}${portFailures.length > 0 && synthFailures.length > 0 ? "Mixed batch. " : ""}${dependencyNote}${portText}${repairText}Original ordered --from: ${batchFrom}. Replacement mapping: ${mapping}. Keep every passing pick in its original position and retain existing approved exclusions. Additional owner approval required for replacing/excluding original development commit(s): ${replaceNow.map((f) => f.sha).join(",")}. No cite-only marker is implemented; mmi-hotfix-carries is release verification only. Only after that explicit approval, replace the placeholders and rerun \`mmi-cli devops hotfix start --from ${picks} --ack ${exclusions}\`. Re-preflight the whole batch. Never hand-resolve onto main or merge a main-parented branch into development; see ${guide}`;
|
|
37036
37037
|
}
|
|
37037
37038
|
var CHERRY_PICKED_FROM = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
|
|
37038
37039
|
async function scanHotfixPickGaps(deps, sources, tolerated, rcRef) {
|
|
@@ -37122,7 +37123,8 @@ async function preflightHotfixBatchPicks(deps, sources, pickTolerated) {
|
|
|
37122
37123
|
failures.push({
|
|
37123
37124
|
label: source.label,
|
|
37124
37125
|
sha: source.sha,
|
|
37125
|
-
blocking: blocking.length > 0 ? blocking : [message2.split("\n")[0] ?? message2]
|
|
37126
|
+
blocking: blocking.length > 0 ? blocking : [message2.split("\n")[0] ?? message2],
|
|
37127
|
+
...failures.length > 0 ? { afterAbortedPicks: failures.map((f) => f.label) } : {}
|
|
37126
37128
|
});
|
|
37127
37129
|
}
|
|
37128
37130
|
}
|
|
@@ -37337,7 +37339,7 @@ async function runHotfixStartLocked(deps, options, doctor) {
|
|
|
37337
37339
|
const preflight2 = await preflightHotfixBatchPicks(deps, sources, pickTolerated);
|
|
37338
37340
|
if (preflight2.failures.length > 0) {
|
|
37339
37341
|
const portLaneShas = await classifyHotfixPortLanePicks(deps, preflight2.failures);
|
|
37340
|
-
throw new Error(formatHotfixBatchPreflightRefusal(preflight2.failures, specs, portLaneShas));
|
|
37342
|
+
throw new Error(formatHotfixBatchPreflightRefusal(preflight2.failures, specs, portLaneShas, { sources, ackedShas }));
|
|
37341
37343
|
}
|
|
37342
37344
|
if (preflight2.skipped.length > 0) {
|
|
37343
37345
|
const skippedShas = new Set(preflight2.skipped.map((s) => s.sha));
|
package/cli/package.json
CHANGED