@mutmutco/claude-plugin 4.5.157 → 4.5.159

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.157",
4
+ "version": "4.5.159",
5
5
  "mmiCompat": "4.x",
6
6
  "description": "MMI workflow skills and org gates delivery.",
7
7
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -7068,6 +7068,8 @@ var import_node_crypto5 = require("node:crypto");
7068
7068
  var APP_ACTOR_ENV = "MMI_ACTOR";
7069
7069
  var APP_VAULT_REPO = "mutmutco/MMI-Hub";
7070
7070
  var APP_VAULT_KEYS = ["GITHUB_APP_ID", "GITHUB_APP_INSTALLATION_ID", "GITHUB_APP_PRIVATE_KEY"];
7071
+ var APP2_VAULT_KEYS = ["GITHUB_APP2_ID", "GITHUB_APP2_INSTALLATION_ID", "GITHUB_APP2_PRIVATE_KEY"];
7072
+ var APP_POOL_MEMBERS = [APP_VAULT_KEYS, APP2_VAULT_KEYS];
7071
7073
  var APP_ELIGIBLE_COMMANDS = /* @__PURE__ */ new Set([
7072
7074
  "pr checks-wait",
7073
7075
  // #8042: App-native required-only read (`pr checks-required`) — REST check/status rows scoped by
@@ -7184,10 +7186,52 @@ async function fleetStatusWriteEnv(args) {
7184
7186
  }
7185
7187
  }
7186
7188
  async function mintScopedInstallationToken(deps, permissions) {
7187
- const [appId, installationId, privateKey] = await Promise.all(APP_VAULT_KEYS.map((k) => deps.fetchSecret(k)));
7189
+ const start = Math.floor((deps.random ?? Math.random)() * APP_POOL_MEMBERS.length) % APP_POOL_MEMBERS.length;
7190
+ const order = APP_POOL_MEMBERS.map((_, i) => APP_POOL_MEMBERS[(start + i) % APP_POOL_MEMBERS.length]);
7191
+ let firstError;
7192
+ let exhausted;
7193
+ let absent = 0;
7194
+ for (const [i, keys] of order.entries()) {
7195
+ try {
7196
+ const minted = await mintFromMember(deps, permissions, keys);
7197
+ if (i === order.length - 1 || !await allowanceSpent(deps, minted.token)) return minted;
7198
+ exhausted ??= minted;
7199
+ } catch (e) {
7200
+ if (e instanceof AppActorError && e.code === "vault-denied") {
7201
+ absent += 1;
7202
+ continue;
7203
+ }
7204
+ firstError ??= e;
7205
+ }
7206
+ }
7207
+ if (exhausted) return exhausted;
7208
+ if (firstError) throw firstError;
7209
+ if (absent === order.length) {
7210
+ throw new AppActorError(
7211
+ `app actor: vault denied all App credentials (${APP_VAULT_REPO} tier) \u2014 not an automation host, or no vault access`,
7212
+ "vault-denied"
7213
+ );
7214
+ }
7215
+ throw new AppActorError("app actor: no App pool member minted \u2014 automation fails closed");
7216
+ }
7217
+ async function allowanceSpent(deps, token) {
7218
+ try {
7219
+ const res = await deps.fetch("https://api.github.com/rate_limit", {
7220
+ method: "GET",
7221
+ headers: { authorization: `Bearer ${token}`, accept: "application/vnd.github+json", "user-agent": "mmi-cli-app-actor" }
7222
+ });
7223
+ if (!res.ok) return false;
7224
+ const body = await res.json();
7225
+ return body.resources?.core?.remaining === 0 || body.resources?.graphql?.remaining === 0;
7226
+ } catch {
7227
+ return false;
7228
+ }
7229
+ }
7230
+ async function mintFromMember(deps, permissions, keys) {
7231
+ const [appId, installationId, privateKey] = await Promise.all(keys.map((k) => deps.fetchSecret(k)));
7188
7232
  if (!appId || !installationId || !privateKey) {
7189
- const missing = APP_VAULT_KEYS.filter((_, i) => ![appId, installationId, privateKey][i]);
7190
- if (missing.length === APP_VAULT_KEYS.length) {
7233
+ const missing = keys.filter((_, i) => ![appId, installationId, privateKey][i]);
7234
+ if (missing.length === keys.length) {
7191
7235
  throw new AppActorError(
7192
7236
  `app actor: vault denied all App credentials (${APP_VAULT_REPO} tier) \u2014 not an automation host, or no vault access`,
7193
7237
  "vault-denied"
@@ -16372,6 +16416,38 @@ function checkRunbookCoverage(docs, base, git3) {
16372
16416
  }
16373
16417
  return findings;
16374
16418
  }
16419
+ function checkSeedRunbookReview(root, base, readFile10, git3) {
16420
+ const manifestJson = readFile10((0, import_node_path15.join)(root, "skills/bootstrap/seeds/manifest.json"));
16421
+ if (!manifestJson) return [];
16422
+ const changed = new Set(git3(["diff", "--name-only", `${base}...HEAD`]).split(/\r?\n/).filter(Boolean));
16423
+ const touched = loadBootstrapSeeds(manifestJson).seeds.filter((seed) => isPropagatableSeed(seed) && changed.has(seedSourcePath(seed)));
16424
+ if (!touched.length) return [];
16425
+ let declarations = null;
16426
+ try {
16427
+ declarations = JSON.parse(readFile10((0, import_node_path15.join)(root, RUNBOOK_UNAFFECTED_PATH)) ?? "null");
16428
+ } catch {
16429
+ declarations = null;
16430
+ }
16431
+ const findings = [];
16432
+ for (const seed of touched) {
16433
+ const source = seedSourcePath(seed);
16434
+ let blob;
16435
+ try {
16436
+ blob = git3(["rev-parse", `HEAD:${source}`]).trim();
16437
+ } catch {
16438
+ continue;
16439
+ }
16440
+ if (!runbookUnaffectedReason(declarations, seed.target, blob)) {
16441
+ findings.push({
16442
+ kind: "seed-runbook-unreviewed",
16443
+ doc: source,
16444
+ line: 0,
16445
+ detail: `${seed.target} (source blob ${blob}): propagatable seed changed without a runbook impact decision; add "${seed.target}": { "blob": "${blob}", "reason": "<why>" } to ${RUNBOOK_UNAFFECTED_PATH} or declare Seed-Runbook-Affected: <reason> in a commit message`
16446
+ });
16447
+ }
16448
+ }
16449
+ return findings;
16450
+ }
16375
16451
  function readFileOrNull(path2) {
16376
16452
  return (0, import_node_fs17.existsSync)(path2) ? (0, import_node_fs17.readFileSync)(path2, "utf8") : null;
16377
16453
  }
@@ -16505,11 +16581,14 @@ function runDocRefs(root, deps = {}) {
16505
16581
  if (deps.base) {
16506
16582
  const git3 = deps.git ?? ((args) => (0, import_node_child_process6.execFileSync)("git", args, { cwd: root, encoding: "utf8", maxBuffer: CHECK_IGNORE_MAX_BUFFER, windowsHide: true }));
16507
16583
  const stale = checkRunbookCoverage(runbooks, deps.base, git3);
16584
+ const seedStale = checkSeedRunbookReview(root, deps.base, readFile10, git3);
16508
16585
  const messages = git3(["log", "--format=%B", `${deps.base}..HEAD`]);
16509
- const sourceMessages = stale.length ? mergeGroupRunbookMessages(root, deps, readFile10, warnings) : "";
16510
- const override = /^Runbook-Unaffected:[ \t]*\S.*$/m.test(`${messages}
16511
- ${sourceMessages}`);
16586
+ const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps, readFile10, warnings) : "";
16587
+ const allMessages = `${messages}
16588
+ ${sourceMessages}`;
16589
+ const override = /^Runbook-Unaffected:[ \t]*\S.*$/m.test(allMessages);
16512
16590
  (override ? warnings : findings).push(...stale);
16591
+ if (!/^Seed-Runbook-Affected:[ \t]*\S.*$/m.test(allMessages)) findings.push(...seedStale);
16513
16592
  }
16514
16593
  return {
16515
16594
  ok: findings.length === 0,
@@ -18741,10 +18820,10 @@ var rollout_plan_default = {
18741
18820
  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)."
18742
18821
  },
18743
18822
  baseline: {
18744
- version: "4.5.157",
18745
- tag: "v4.5.157",
18746
- commit: "a6662d29e5ff",
18747
- npm: "@mutmutco/cli@4.5.157"
18823
+ version: "4.5.159",
18824
+ tag: "v4.5.159",
18825
+ commit: "daaf02084d87",
18826
+ npm: "@mutmutco/cli@4.5.159"
18748
18827
  },
18749
18828
  exitCriterion: "fleet-n-of-n",
18750
18829
  hubOnlyShortcut: "forbidden",
@@ -18761,14 +18840,14 @@ var rollout_plan_default = {
18761
18840
  repo: "mutmutco/mmi-hub",
18762
18841
  role: "canary",
18763
18842
  schedule: "train",
18764
- v3Target: "v4.5.157"
18843
+ v3Target: "v4.5.159"
18765
18844
  }
18766
18845
  ],
18767
18846
  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.",
18768
18847
  rollback: {
18769
18848
  independent: true,
18770
- mechanism: "npm dist-tag latest -> 4.5.157 and redeploy the Hub Lambda from tag v4.5.157 (a6662d29e5ff); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18771
- v3Target: "v4.5.157 (@mutmutco/cli@4.5.157, tag commit a6662d29e5ff \u2014 last known-good release carrying the repo-index v4-only contract)"
18849
+ mechanism: "npm dist-tag latest -> 4.5.159 and redeploy the Hub Lambda from tag v4.5.159 (daaf02084d87); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18850
+ v3Target: "v4.5.159 (@mutmutco/cli@4.5.159, tag commit daaf02084d87 \u2014 last known-good release carrying the repo-index v4-only contract)"
18772
18851
  }
18773
18852
  },
18774
18853
  {
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.157",
3
+ "version": "4.5.159",
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.157",
3
+ "version": "4.5.159",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",