@mutmutco/cli 4.5.84 → 4.5.86
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/dist/main.cjs +111 -20
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -17268,10 +17268,10 @@ var rollout_plan_default = {
|
|
|
17268
17268
|
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)."
|
|
17269
17269
|
},
|
|
17270
17270
|
baseline: {
|
|
17271
|
-
version: "4.5.
|
|
17272
|
-
tag: "v4.5.
|
|
17273
|
-
commit: "
|
|
17274
|
-
npm: "@mutmutco/cli@4.5.
|
|
17271
|
+
version: "4.5.86",
|
|
17272
|
+
tag: "v4.5.86",
|
|
17273
|
+
commit: "6485afaf5af8",
|
|
17274
|
+
npm: "@mutmutco/cli@4.5.86"
|
|
17275
17275
|
},
|
|
17276
17276
|
exitCriterion: "fleet-n-of-n",
|
|
17277
17277
|
hubOnlyShortcut: "forbidden",
|
|
@@ -17288,14 +17288,14 @@ var rollout_plan_default = {
|
|
|
17288
17288
|
repo: "mutmutco/mmi-hub",
|
|
17289
17289
|
role: "canary",
|
|
17290
17290
|
schedule: "train",
|
|
17291
|
-
v3Target: "v4.5.
|
|
17291
|
+
v3Target: "v4.5.86"
|
|
17292
17292
|
}
|
|
17293
17293
|
],
|
|
17294
17294
|
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.",
|
|
17295
17295
|
rollback: {
|
|
17296
17296
|
independent: true,
|
|
17297
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
17298
|
-
v3Target: "v4.5.
|
|
17297
|
+
mechanism: "npm dist-tag latest -> 4.5.86 and redeploy the Hub Lambda from tag v4.5.86 (6485afaf5af8); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
17298
|
+
v3Target: "v4.5.86 (@mutmutco/cli@4.5.86, tag commit 6485afaf5af8 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
17299
17299
|
}
|
|
17300
17300
|
},
|
|
17301
17301
|
{
|
|
@@ -19607,6 +19607,7 @@ var TRAIN_COMMIT_STATUS_JQ = "[.statuses[]|{context:.context,state:.state,id:.id
|
|
|
19607
19607
|
var TRAIN_PROTECTION_CONTEXTS_JQ = "[.contexts[]]";
|
|
19608
19608
|
var TRAIN_RULES_CONTEXTS_JQ = '[.[]|select(.type=="required_status_checks")|.parameters.required_status_checks[].context]';
|
|
19609
19609
|
var TRAIN_CHECK_ATTEMPTS = 40;
|
|
19610
|
+
var TRAIN_QUEUED_CHECK_ATTEMPTS = 80;
|
|
19610
19611
|
var TRAIN_CHECK_DELAY_MS = 15e3;
|
|
19611
19612
|
var TRAIN_PR_ONLY_CONTEXTS = /* @__PURE__ */ new Set(["add-to-project", "mark-merged-pr-done", "guard", "verdict"]);
|
|
19612
19613
|
var TRAIN_PR_AUTOMATION_GRACE_ATTEMPTS = 3;
|
|
@@ -20011,10 +20012,14 @@ async function waitForRequiredTrainChecks(deps, ctx, sha, required, freshSince)
|
|
|
20011
20012
|
const sleep2 = resolveSleep(deps);
|
|
20012
20013
|
let lastStatus = "not checked";
|
|
20013
20014
|
let lastError;
|
|
20015
|
+
let workflowRunRead = "not-read";
|
|
20016
|
+
let workflowRunNote = "";
|
|
20017
|
+
let workflowRunEverSeen = false;
|
|
20018
|
+
let hadQueuedWorkflowRun = false;
|
|
20014
20019
|
const everObserved = /* @__PURE__ */ new Set();
|
|
20015
20020
|
const autoSatisfied = /* @__PURE__ */ new Set();
|
|
20016
20021
|
let fleetForeignStreak = 0;
|
|
20017
|
-
for (let attempt = 0; attempt < TRAIN_CHECK_ATTEMPTS; attempt++) {
|
|
20022
|
+
for (let attempt = 0; attempt < TRAIN_CHECK_ATTEMPTS || hadQueuedWorkflowRun && attempt < TRAIN_QUEUED_CHECK_ATTEMPTS; attempt++) {
|
|
20018
20023
|
if (attempt > 0) await sleep2(TRAIN_CHECK_DELAY_MS);
|
|
20019
20024
|
let checkRuns;
|
|
20020
20025
|
let statuses;
|
|
@@ -20032,6 +20037,40 @@ async function waitForRequiredTrainChecks(deps, ctx, sha, required, freshSince)
|
|
|
20032
20037
|
lastError = e.message || String(e);
|
|
20033
20038
|
continue;
|
|
20034
20039
|
}
|
|
20040
|
+
try {
|
|
20041
|
+
const workflowOut = await deps.run("gh", [
|
|
20042
|
+
"run",
|
|
20043
|
+
"list",
|
|
20044
|
+
"--repo",
|
|
20045
|
+
ctx.repo,
|
|
20046
|
+
"--commit",
|
|
20047
|
+
sha,
|
|
20048
|
+
"--limit",
|
|
20049
|
+
"100",
|
|
20050
|
+
"--json",
|
|
20051
|
+
"databaseId,status,conclusion,headSha"
|
|
20052
|
+
]);
|
|
20053
|
+
const parsedWorkflowRuns = JSON.parse(workflowOut);
|
|
20054
|
+
if (!Array.isArray(parsedWorkflowRuns)) throw new Error("workflow-runs response was not an array");
|
|
20055
|
+
const matchingRuns = parsedWorkflowRuns.filter((run) => !run.headSha || run.headSha === sha);
|
|
20056
|
+
if (matchingRuns.length) {
|
|
20057
|
+
workflowRunRead = "found";
|
|
20058
|
+
workflowRunEverSeen = true;
|
|
20059
|
+
const activeRun = matchingRuns.find((run) => run.status === "queued" || run.status === "in_progress");
|
|
20060
|
+
if (activeRun) {
|
|
20061
|
+
if (activeRun.status === "queued") hadQueuedWorkflowRun = true;
|
|
20062
|
+
workflowRunNote = activeRun.status === "queued" ? "Actions run is queued behind busy runners" : "Actions run is in progress";
|
|
20063
|
+
} else {
|
|
20064
|
+
workflowRunNote = "Actions run exists but has not produced the required check-run";
|
|
20065
|
+
}
|
|
20066
|
+
} else {
|
|
20067
|
+
workflowRunRead = "empty";
|
|
20068
|
+
workflowRunNote = "";
|
|
20069
|
+
}
|
|
20070
|
+
} catch (e) {
|
|
20071
|
+
workflowRunRead = "failed";
|
|
20072
|
+
workflowRunNote = `workflow-run lookup failed: ${e.message || String(e)}`;
|
|
20073
|
+
}
|
|
20035
20074
|
for (const c of required) {
|
|
20036
20075
|
if (checkRuns.some((r) => r.name === c) || statuses.some((s) => s.context === c)) everObserved.add(c);
|
|
20037
20076
|
}
|
|
@@ -20069,11 +20108,14 @@ async function waitForRequiredTrainChecks(deps, ctx, sha, required, freshSince)
|
|
|
20069
20108
|
return `required checks passed: ${pending.join(", ") || "(none pending)"}${satisfiedNote}${fleetNote}`;
|
|
20070
20109
|
}
|
|
20071
20110
|
}
|
|
20072
|
-
const
|
|
20111
|
+
const attempts = hadQueuedWorkflowRun ? TRAIN_QUEUED_CHECK_ATTEMPTS : TRAIN_CHECK_ATTEMPTS;
|
|
20112
|
+
const waitedMin = Math.round((attempts - 1) * TRAIN_CHECK_DELAY_MS / 6e4);
|
|
20073
20113
|
const neverMaterialized = required.filter((c) => !everObserved.has(c) && !autoSatisfied.has(c));
|
|
20074
|
-
const
|
|
20114
|
+
const noWorkflowRun = workflowRunRead === "empty" && !workflowRunEverSeen;
|
|
20115
|
+
const neverNote = neverMaterialized.length && noWorkflowRun ? ` No workflow run was found on ${sha} after a successful lookup, and no check-run or commit status appeared: ${neverMaterialized.join(", ")}.` : "";
|
|
20116
|
+
const runNote = workflowRunNote ? ` ${workflowRunNote}.` : "";
|
|
20075
20117
|
throw new Error(
|
|
20076
|
-
`timed out after ~${waitedMin}m (${
|
|
20118
|
+
`timed out after ~${waitedMin}m (${attempts} attempts) waiting for required train checks on ${sha}.${neverNote}${runNote}${lastError ? ` Last read error: ${lastError}` : ` Last observed: ${lastStatus}`}`
|
|
20077
20119
|
);
|
|
20078
20120
|
}
|
|
20079
20121
|
async function probeRemoteTag(deps, tag) {
|
|
@@ -20297,6 +20339,10 @@ function validSuiteCutContext(repo, context) {
|
|
|
20297
20339
|
function authorisedSuiteCut(repo, meta, context) {
|
|
20298
20340
|
return validSuiteCutContext(repo, context) && !!meta?.suite && context.lead.toLowerCase() === suiteLeadRepo(repo, meta.suite).toLowerCase();
|
|
20299
20341
|
}
|
|
20342
|
+
function acceptedSuiteContext(repo, meta, context) {
|
|
20343
|
+
if (authorisedSuiteCut(repo, meta, context)) return true;
|
|
20344
|
+
return !!context && context.token === SUITE_LEAD_TOKEN && !!meta?.suite && !isBundleOnlySuiteMember(repo, meta.suite) && context.repo.toLowerCase() === repo.toLowerCase();
|
|
20345
|
+
}
|
|
20300
20346
|
var BUNDLE_ONLY_RC_EXCEPTION = "suite member: rc is bundle-only (no rc runtime)";
|
|
20301
20347
|
function isBundleOnlySuiteMember(repo, suite) {
|
|
20302
20348
|
if (!suite) return false;
|
|
@@ -21747,7 +21793,7 @@ function partialTrainRecoveryError(cause, input) {
|
|
|
21747
21793
|
const causeMessage = cause instanceof Error ? cause.message : String(cause);
|
|
21748
21794
|
const branch = input.stage;
|
|
21749
21795
|
const releaseState = input.stage === "rc" ? "GitHub Release n/a" : "GitHub Release not created";
|
|
21750
|
-
const resumeCommand = input.stage === "rc" ? "mmi-cli devops rcand --resume" :
|
|
21796
|
+
const resumeCommand = input.stage === "rc" ? "mmi-cli devops rcand --resume" : `mmi-cli devops release --resume${input.suiteSolo ? " --suite-solo --owner-go" : ""}`;
|
|
21751
21797
|
const tenant2 = input.deployModel === "tenant-container";
|
|
21752
21798
|
const deployLine = tenant2 ? ` - deploy: dispatched by the train after the branch push; recover with \`mmi-cli devops runtime tenant redeploy ${input.repo} ${input.stage} --watch\` once the branch and release exist.` : ` - deploy: this repo is \`${input.deployModel ?? "not tenant-container"}\` \u2014 it has NO tenant runtime. Its own release/main-push workflows publish and deploy once the branch and Release exist. Do NOT run the tenant redeployer.`;
|
|
21753
21799
|
const stateBlock = `partial train state for ${input.tag}:
|
|
@@ -24767,7 +24813,7 @@ async function runTrainDoctor(input) {
|
|
|
24767
24813
|
const dev = input.dev === true && lane === "release";
|
|
24768
24814
|
const suiteRefusal = suiteMemberRefusal(repo, meta, lane, input.suiteSolo === true, input.suiteCut);
|
|
24769
24815
|
if (suiteRefusal) add({ code: "suite-member-solo", severity: "blocker", source: "origin", title: suiteRefusal, remedy: suiteRefusal });
|
|
24770
|
-
if (input.suiteCut && !
|
|
24816
|
+
if (input.suiteCut && !acceptedSuiteContext(repo, meta, input.suiteCut))
|
|
24771
24817
|
add({ code: "suite-cut-context-invalid", severity: "blocker", source: "origin", title: "suite cut context does not match this member and its registered lead", remedy: "run from the MM-Work suite command with the member registered in META" });
|
|
24772
24818
|
if (lane === "rcand" && track === "direct") {
|
|
24773
24819
|
add({ code: "lane-mismatch", severity: "blocker", source: "origin", title: `${repo} is direct-track (no rc) \u2014 rcand does not apply`, remedy: "run `mmi-cli devops release --apply` from development instead of rcand" });
|
|
@@ -25485,7 +25531,7 @@ function enforceGateBudget(deps, repo) {
|
|
|
25485
25531
|
async function preflight(deps, ctx, stage, meta, lane) {
|
|
25486
25532
|
assertGitBashOnWindowsForJervHubRelease(ctx.repo);
|
|
25487
25533
|
deps.warn?.("Release: Checking release prerequisites");
|
|
25488
|
-
if (deps.suiteCut && !
|
|
25534
|
+
if (deps.suiteCut && !acceptedSuiteContext(ctx.repo, meta, deps.suiteCut))
|
|
25489
25535
|
throw new Error(`${ctx.repo}: suite cut context does not match registry META; no deployment or tag was changed`);
|
|
25490
25536
|
const model = requireDeployModel(meta, ctx.repo);
|
|
25491
25537
|
if (model === "content") {
|
|
@@ -26154,7 +26200,7 @@ async function completeMainRelease(deps, ctx, meta, deployModel, watch, options,
|
|
|
26154
26200
|
}
|
|
26155
26201
|
let tagPush;
|
|
26156
26202
|
let tagLedgerStarted = false;
|
|
26157
|
-
const recoveryInput = { repo: ctx.repo, tag, stage: "main", deployModel, meta, branchHints };
|
|
26203
|
+
const recoveryInput = { repo: ctx.repo, tag, stage: "main", deployModel, suiteSolo: options.suiteSolo, meta, branchHints };
|
|
26158
26204
|
try {
|
|
26159
26205
|
await assertComputedReleaseTagStillNext(deps, tag, preOneZeroInForce(meta));
|
|
26160
26206
|
if (deployModel === "hub-serverless") {
|
|
@@ -26745,7 +26791,7 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
26745
26791
|
}
|
|
26746
26792
|
const steps = [];
|
|
26747
26793
|
let requiredChecks;
|
|
26748
|
-
const recoveryInput = { repo: ctx.repo, tag, stage: "main", deployModel, meta, branchHints };
|
|
26794
|
+
const recoveryInput = { repo: ctx.repo, tag, stage: "main", deployModel, suiteSolo: options.suiteSolo, meta, branchHints };
|
|
26749
26795
|
try {
|
|
26750
26796
|
requiredChecks = await discoverRequiredCheckContexts(deps, ctx, "main");
|
|
26751
26797
|
} catch (e) {
|
|
@@ -46729,6 +46775,17 @@ async function prepareLaneCheckout(git3, repo, branch, lane) {
|
|
|
46729
46775
|
const [head, origin] = (await git3(["rev-parse", "HEAD", `origin/${branch}`])).trim().split(/\s+/);
|
|
46730
46776
|
if (!head || head !== origin) throw new Error(`${repo}: local ${branch} ${head?.slice(0, 12)} is not origin/${branch} ${origin?.slice(0, 12)}; stop`);
|
|
46731
46777
|
}
|
|
46778
|
+
async function refreshSuiteCheckout(git3) {
|
|
46779
|
+
await git3(["fetch", "--prune", "origin"]);
|
|
46780
|
+
if ((await git3(["branch", "--remotes", "--list", "origin/rc"])).trim()) return;
|
|
46781
|
+
if (!(await git3(["branch", "--list", "rc"])).trim()) return;
|
|
46782
|
+
const upstream = (await git3(["for-each-ref", "--format=%(upstream:short)", "refs/heads/rc"])).trim();
|
|
46783
|
+
if (upstream !== "origin/rc") return;
|
|
46784
|
+
const sha = (await git3(["rev-parse", "--short=12", "refs/heads/rc"])).trim();
|
|
46785
|
+
let stale = `stale-rc-${sha}`;
|
|
46786
|
+
for (let suffix = 1; (await git3(["branch", "--list", stale])).trim(); suffix++) stale = `stale-rc-${sha}-${suffix}`;
|
|
46787
|
+
await git3(["branch", "--move", "rc", stale]);
|
|
46788
|
+
}
|
|
46732
46789
|
function rcRunCauseFromLog(log) {
|
|
46733
46790
|
const causes = [...new Set([...log.matchAll(/##\[error\](?!Process completed with exit code)([^\r\n]+)/g)].map((m) => m[1].trim()).filter(Boolean))];
|
|
46734
46791
|
return causes.length ? `: ${causes.join("; ")}` : "";
|
|
@@ -46750,6 +46807,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
|
46750
46807
|
const origin = await exec("git", ["remote", "get-url", "origin"], target);
|
|
46751
46808
|
if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
|
|
46752
46809
|
throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
|
|
46810
|
+
await refreshSuiteCheckout((args) => exec("git", args, target, WATCH_TIMEOUT));
|
|
46753
46811
|
return target;
|
|
46754
46812
|
};
|
|
46755
46813
|
const inTrain = async (repo, action, solo = false) => {
|
|
@@ -47766,6 +47824,16 @@ var surfaces_default = {
|
|
|
47766
47824
|
"mmi-cli.cmd"
|
|
47767
47825
|
]
|
|
47768
47826
|
},
|
|
47827
|
+
{
|
|
47828
|
+
mode: "files",
|
|
47829
|
+
sourcePath: "cli",
|
|
47830
|
+
targetPath: "packages/claude-plugin/cli",
|
|
47831
|
+
include: [
|
|
47832
|
+
"dist/index.cjs",
|
|
47833
|
+
"dist/main.cjs",
|
|
47834
|
+
"package.json"
|
|
47835
|
+
]
|
|
47836
|
+
},
|
|
47769
47837
|
{
|
|
47770
47838
|
mode: "files",
|
|
47771
47839
|
sourcePath: ".claude-plugin",
|
|
@@ -47841,6 +47909,16 @@ var surfaces_default = {
|
|
|
47841
47909
|
"mmi-cli.cmd"
|
|
47842
47910
|
]
|
|
47843
47911
|
},
|
|
47912
|
+
{
|
|
47913
|
+
mode: "files",
|
|
47914
|
+
sourcePath: "cli",
|
|
47915
|
+
targetPath: "packages/codex-plugin/cli",
|
|
47916
|
+
include: [
|
|
47917
|
+
"dist/index.cjs",
|
|
47918
|
+
"dist/main.cjs",
|
|
47919
|
+
"package.json"
|
|
47920
|
+
]
|
|
47921
|
+
},
|
|
47844
47922
|
{
|
|
47845
47923
|
mode: "files",
|
|
47846
47924
|
sourcePath: ".codex-plugin",
|
|
@@ -47916,6 +47994,16 @@ var surfaces_default = {
|
|
|
47916
47994
|
"mmi-cli.cmd"
|
|
47917
47995
|
]
|
|
47918
47996
|
},
|
|
47997
|
+
{
|
|
47998
|
+
mode: "files",
|
|
47999
|
+
sourcePath: "cli",
|
|
48000
|
+
targetPath: "packages/cursor-plugin/cli",
|
|
48001
|
+
include: [
|
|
48002
|
+
"dist/index.cjs",
|
|
48003
|
+
"dist/main.cjs",
|
|
48004
|
+
"package.json"
|
|
48005
|
+
]
|
|
48006
|
+
},
|
|
47919
48007
|
{
|
|
47920
48008
|
mode: "files",
|
|
47921
48009
|
sourcePath: ".cursor-plugin",
|
|
@@ -48132,7 +48220,7 @@ var surfaces_default = {
|
|
|
48132
48220
|
ownerPath: "packages/claude-plugin/package.json",
|
|
48133
48221
|
deliveryPath: "packages/claude-plugin/package.json",
|
|
48134
48222
|
delivery: "npm",
|
|
48135
|
-
applicability: "Claude Code plugin; npm package @mutmutco/claude-plugin carrying the plugin manifest, skills, hooks, gate scripts, and launchers. The thin git catalog stays in .claude-plugin/marketplace.json (#4945).",
|
|
48223
|
+
applicability: "Claude Code plugin; npm package @mutmutco/claude-plugin carrying the plugin manifest, skills, hooks, gate scripts, launchers, and the bundled mmi-cli engine the launchers run. The thin git catalog stays in .claude-plugin/marketplace.json (#4945).",
|
|
48136
48224
|
versionCoordinated: true,
|
|
48137
48225
|
surfaceToken: "claude",
|
|
48138
48226
|
versionPaths: [
|
|
@@ -48148,7 +48236,8 @@ var surfaces_default = {
|
|
|
48148
48236
|
additionalPaths: [
|
|
48149
48237
|
"packages/claude-plugin/.claude-plugin",
|
|
48150
48238
|
"packages/claude-plugin/skills",
|
|
48151
|
-
"packages/claude-plugin/bin"
|
|
48239
|
+
"packages/claude-plugin/bin",
|
|
48240
|
+
"packages/claude-plugin/cli"
|
|
48152
48241
|
],
|
|
48153
48242
|
artifactIdentity: {
|
|
48154
48243
|
kind: "npm-pack",
|
|
@@ -48183,7 +48272,8 @@ var surfaces_default = {
|
|
|
48183
48272
|
additionalPaths: [
|
|
48184
48273
|
"packages/codex-plugin/.codex-plugin",
|
|
48185
48274
|
"packages/codex-plugin/skills",
|
|
48186
|
-
"packages/codex-plugin/bin"
|
|
48275
|
+
"packages/codex-plugin/bin",
|
|
48276
|
+
"packages/codex-plugin/cli"
|
|
48187
48277
|
],
|
|
48188
48278
|
artifactIdentity: {
|
|
48189
48279
|
kind: "npm-pack",
|
|
@@ -48214,7 +48304,8 @@ var surfaces_default = {
|
|
|
48214
48304
|
additionalPaths: [
|
|
48215
48305
|
"packages/cursor-plugin/.cursor-plugin",
|
|
48216
48306
|
"packages/cursor-plugin/skills",
|
|
48217
|
-
"packages/cursor-plugin/bin"
|
|
48307
|
+
"packages/cursor-plugin/bin",
|
|
48308
|
+
"packages/cursor-plugin/cli"
|
|
48218
48309
|
],
|
|
48219
48310
|
artifactIdentity: {
|
|
48220
48311
|
kind: "npm-pack",
|
package/package.json
CHANGED