@mutmutco/claude-plugin 4.5.197 → 4.5.198

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mmi",
3
3
  "displayName": "MMI",
4
- "version": "4.5.197",
4
+ "version": "4.5.198",
5
5
  "mmiCompat": "4.x",
6
6
  "description": "MMI workflow skills and org gates delivery.",
7
7
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -7798,7 +7798,7 @@ function waitReadFailureMessage(e) {
7798
7798
  }
7799
7799
  var PR_CHECKS_POLL_MS = 6e4;
7800
7800
  function pollIntervalMs(elapsedMs) {
7801
- return Math.min(4 * PR_CHECKS_POLL_MS, PR_CHECKS_POLL_MS * 2 ** Math.floor(Math.max(0, elapsedMs) / 3e5));
7801
+ return Math.min(4 * PR_CHECKS_POLL_MS, PR_CHECKS_POLL_MS * 2 ** Math.floor(Math.max(0, elapsedMs) / 9e5));
7802
7802
  }
7803
7803
  var PR_CHECKS_TIMEOUT_MS = 30 * 6e4;
7804
7804
  var PR_CHECKS_SUCCESS_CONFIRMATIONS = 2;
@@ -19279,10 +19279,10 @@ var rollout_plan_default = {
19279
19279
  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)."
19280
19280
  },
19281
19281
  baseline: {
19282
- version: "4.5.197",
19283
- tag: "v4.5.197",
19284
- commit: "52a7574dc96e",
19285
- npm: "@mutmutco/cli@4.5.197"
19282
+ version: "4.5.198",
19283
+ tag: "v4.5.198",
19284
+ commit: "6d3c999e17f5",
19285
+ npm: "@mutmutco/cli@4.5.198"
19286
19286
  },
19287
19287
  exitCriterion: "fleet-n-of-n",
19288
19288
  hubOnlyShortcut: "forbidden",
@@ -19299,14 +19299,14 @@ var rollout_plan_default = {
19299
19299
  repo: "mutmutco/mmi-hub",
19300
19300
  role: "canary",
19301
19301
  schedule: "train",
19302
- v3Target: "v4.5.197"
19302
+ v3Target: "v4.5.198"
19303
19303
  }
19304
19304
  ],
19305
19305
  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.",
19306
19306
  rollback: {
19307
19307
  independent: true,
19308
- mechanism: "npm dist-tag latest -> 4.5.197 and redeploy the Hub Lambda from tag v4.5.197 (52a7574dc96e); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19309
- v3Target: "v4.5.197 (@mutmutco/cli@4.5.197, tag commit 52a7574dc96e \u2014 last known-good release carrying the repo-index v4-only contract)"
19308
+ mechanism: "npm dist-tag latest -> 4.5.198 and redeploy the Hub Lambda from tag v4.5.198 (6d3c999e17f5); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19309
+ v3Target: "v4.5.198 (@mutmutco/cli@4.5.198, tag commit 6d3c999e17f5 \u2014 last known-good release carrying the repo-index v4-only contract)"
19310
19310
  }
19311
19311
  },
19312
19312
  {
@@ -30269,6 +30269,69 @@ function auditRunnerFallbacks(repo, files) {
30269
30269
  }
30270
30270
  return checks;
30271
30271
  }
30272
+ var PENDING_LANDING_LABEL = "pending PRs landing (#8783)";
30273
+ var PENDING_LANDING_LIST_CAP = 50;
30274
+ var PENDING_LANDING_STALL_MS = 15 * 60 * 1e3;
30275
+ function summarizePendingLanding(nodes, base, capped, now) {
30276
+ const prs = nodes.filter((n) => !n.isDraft);
30277
+ const s = {
30278
+ base,
30279
+ considered: prs.length,
30280
+ capped,
30281
+ autoMergeRequested: 0,
30282
+ autoMergeNotRequested: 0,
30283
+ inMergeQueue: 0,
30284
+ blockers: { DIRTY: 0, BLOCKED: 0, BEHIND: 0, UNKNOWN: 0, CLEAN_NOT_QUEUED: 0 },
30285
+ stalled: []
30286
+ };
30287
+ for (const pr of prs) {
30288
+ const requested = Boolean(pr.autoMergeRequest);
30289
+ const queued = pr.isInMergeQueue === true;
30290
+ if (requested) s.autoMergeRequested++;
30291
+ else s.autoMergeNotRequested++;
30292
+ if (queued) s.inMergeQueue++;
30293
+ const state = pr.mergeStateStatus ?? "UNKNOWN";
30294
+ if (state === "DIRTY") s.blockers.DIRTY++;
30295
+ else if (state === "BLOCKED") s.blockers.BLOCKED++;
30296
+ else if (state === "BEHIND") s.blockers.BEHIND++;
30297
+ else if (state === "CLEAN") {
30298
+ if (!requested && !queued) {
30299
+ s.blockers.CLEAN_NOT_QUEUED++;
30300
+ const updated = Date.parse(pr.updatedAt ?? "");
30301
+ if (Number.isFinite(updated) && now - updated > PENDING_LANDING_STALL_MS) s.stalled.push(pr.number);
30302
+ }
30303
+ } else if (state !== "HAS_HOOKS" && state !== "UNSTABLE") s.blockers.UNKNOWN++;
30304
+ }
30305
+ return s;
30306
+ }
30307
+ function pendingLandingCheck(summary, base) {
30308
+ if (!summary) {
30309
+ return { ok: true, severity: "info", label: PENDING_LANDING_LABEL, detail: `UNAVAILABLE: open-PR read for ${base} failed \u2014 counts unknown, not zero` };
30310
+ }
30311
+ const b = summary.blockers;
30312
+ const detail = `${summary.considered} open non-draft PR(s) into ${base}${summary.capped ? ` (capped: first ${PENDING_LANDING_LIST_CAP} by most recent update; more exist)` : ""}; auto-merge REQUESTED on ${summary.autoMergeRequested}, not requested on ${summary.autoMergeNotRequested} (per-PR requests, not the repo allow_auto_merge permission); in merge queue ${summary.inMergeQueue}; blockers: DIRTY ${b.DIRTY}, BLOCKED ${b.BLOCKED}, BEHIND ${b.BEHIND}, UNKNOWN ${b.UNKNOWN}, CLEAN-not-queued ${b.CLEAN_NOT_QUEUED}` + (summary.stalled.length ? `; STALLED (CLEAN, no auto-merge request or queue entry, idle >15 min): ${summary.stalled.map((n) => `#${n}`).join(", ")}` : "");
30313
+ return {
30314
+ ok: true,
30315
+ severity: summary.stalled.length ? "warn" : "info",
30316
+ label: PENDING_LANDING_LABEL,
30317
+ detail,
30318
+ remediation: summary.stalled.length ? "mmi-cli pr land <n> --repo <repo> for each stalled PR" : void 0
30319
+ };
30320
+ }
30321
+ async function auditPendingLanding(repo, base, deps) {
30322
+ try {
30323
+ const [owner, name] = repo.split("/");
30324
+ const data = await deps.client.graphql(
30325
+ "query($owner:String!,$name:String!,$base:String!,$n:Int!){repository(owner:$owner,name:$name){pullRequests(states:OPEN,baseRefName:$base,first:$n,orderBy:{field:UPDATED_AT,direction:DESC}){totalCount nodes{number isDraft updatedAt mergeStateStatus isInMergeQueue autoMergeRequest{enabledAt}}}}}",
30326
+ { owner, name, base, n: PENDING_LANDING_LIST_CAP }
30327
+ );
30328
+ const prs = data?.repository?.pullRequests;
30329
+ if (!prs?.nodes) return pendingLandingCheck(void 0, base);
30330
+ return pendingLandingCheck(summarizePendingLanding(prs.nodes, base, (prs.totalCount ?? 0) > prs.nodes.length, (deps.now ?? Date.now)()), base);
30331
+ } catch {
30332
+ return pendingLandingCheck(void 0, base);
30333
+ }
30334
+ }
30272
30335
  function slugFromRepo(repo) {
30273
30336
  return (repo.includes("/") ? repo.split("/")[1] : repo).toLowerCase();
30274
30337
  }
@@ -30973,6 +31036,7 @@ async function auditRepoCi(repo, callerDeps) {
30973
31036
  const fresh = await auditDevStageFreshness(repo, deps);
30974
31037
  if (fresh) checks.push(fresh);
30975
31038
  }
31039
+ checks.push(await auditPendingLanding(repo, baseBranch, deps));
30976
31040
  const failure = unauditedReason();
30977
31041
  if (failure) {
30978
31042
  return { repo, class: repoClass, mergePolicy: policy, ok: false, checks: [], explicitNoCi, unauditedReason: failure };
@@ -31021,6 +31085,8 @@ function renderCiAuditMarkdown(report) {
31021
31085
  const gap = r.unauditedReason ? `CANNOT AUDIT \u2014 ${r.unauditedReason}` : r.checks.find((c) => !c.ok)?.label ?? "\u2014";
31022
31086
  lines2.push(`| ${r.repo} | ${r.class} | ${r.mergePolicy} | ${r.ok ? "yes" : "no"} | ${gap} |`);
31023
31087
  }
31088
+ const advisories = report.repos.flatMap((r) => r.checks.filter((c) => c.severity && c.label === PENDING_LANDING_LABEL).map((c) => `- ${c.severity === "warn" ? "WARN" : "INFO"} ${r.repo}: ${c.label} \u2014 ${c.detail ?? ""}`));
31089
+ if (advisories.length) lines2.push("", ...advisories);
31024
31090
  return lines2.join("\n");
31025
31091
  }
31026
31092
  function renderCiAuditText(report) {
@@ -31037,7 +31103,7 @@ ${r.repo} (${r.class}, policy=${r.mergePolicy}) ${verdict}`);
31037
31103
  continue;
31038
31104
  }
31039
31105
  for (const c of r.checks) {
31040
- lines2.push(` ${c.ok ? "OK" : "FAIL"} ${c.label}${c.detail ? ` \u2014 ${c.detail}` : ""}`);
31106
+ lines2.push(` ${!c.ok ? "FAIL" : c.severity === "warn" ? "WARN" : c.severity === "info" ? "INFO" : "OK"} ${c.label}${c.detail ? ` \u2014 ${c.detail}` : ""}`);
31041
31107
  }
31042
31108
  }
31043
31109
  return lines2.join("\n");
@@ -48815,7 +48881,11 @@ ${list}`);
48815
48881
  log: (message2) => console.warn(message2),
48816
48882
  // `pr land` inherits the same (raised) checks budget, so it needs the same liveness — otherwise the
48817
48883
  // 30m wait is SILENT and reads exactly like the hang #2940 was filed about, only three times longer.
48818
- progress: ({ state, elapsedMs, remainingMs }) => console.warn(`pr land: waiting on checks \u2014 ${state}, ${Math.round(elapsedMs / 1e3)}s elapsed, ${Math.round(remainingMs / 6e4)}m left`)
48884
+ progress: ({ state, elapsedMs, remainingMs }) => (
48885
+ // #8797: the wait counts only required checks; an aggregator like `gate` appears only after its
48886
+ // needs finish, so "no-checks-reported" there means CI is still running, not that nothing ran.
48887
+ console.warn(`pr land: waiting on checks \u2014 ${state === "no-checks-reported" ? "required check not created yet (CI running)" : state}, ${Math.round(elapsedMs / 1e3)}s elapsed, ${Math.round(remainingMs / 6e4)}m left`)
48888
+ )
48819
48889
  });
48820
48890
  },
48821
48891
  // #2425: re-probe used ONLY to decide whether a failed `gh pr merge --auto` is worth retrying — a
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.197",
3
+ "version": "4.5.198",
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/claude-plugin",
3
- "version": "4.5.197",
3
+ "version": "4.5.198",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",