@mutmutco/claude-plugin 4.5.192 → 4.5.194

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.192",
4
+ "version": "4.5.194",
5
5
  "mmiCompat": "4.x",
6
6
  "description": "MMI workflow skills and org gates delivery.",
7
7
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -365,7 +365,35 @@ var init_error_codes = __esm({
365
365
  function isAppFilingWrite(args) {
366
366
  if (args.some((a) => VIEWER.test(a))) return false;
367
367
  const [group, verb] = args;
368
- return (group === "issue" || group === "label") && verb === "create";
368
+ if ((group === "issue" || group === "label" || group === "pr") && verb === "create") return true;
369
+ if (group === "pr" && verb === "merge") return true;
370
+ if (group === "api") return isFilingWriteApi(args.slice(1));
371
+ return false;
372
+ }
373
+ function isFilingWriteApi(rest) {
374
+ let method = "GET";
375
+ let path2;
376
+ for (let i = 0; i < rest.length; i++) {
377
+ const a = rest[i];
378
+ if (a === "-X" || a === "--method") {
379
+ method = (rest[i + 1] ?? "").toUpperCase();
380
+ i++;
381
+ } else if (/^--method=/.test(a)) {
382
+ method = a.slice(9).toUpperCase();
383
+ } else if (a === "-f" || a === "-F" || a === "--field" || a === "--raw-field" || a === "--input" || a === "-H" || a === "--header" || a === "-q" || a === "--jq" || a === "-t" || a === "--template" || a === "--hostname") {
384
+ if (a === "-f" || a === "-F" || a === "--field" || a === "--raw-field" || a === "--input") {
385
+ if (method === "GET") method = "POST";
386
+ }
387
+ i++;
388
+ } else if (a.startsWith("--input=")) {
389
+ if (method === "GET") method = "POST";
390
+ } else if (!a.startsWith("-") && path2 === void 0) {
391
+ path2 = a.replace(/^\//, "");
392
+ }
393
+ }
394
+ if (method === "POST" && path2 && /^repos\/[^/]+\/[^/]+\/(issues|pulls)$/.test(path2)) return true;
395
+ if (method === "PUT" && path2 && /^repos\/[^/]+\/[^/]+\/pulls\/\d+\/merge$/.test(path2)) return true;
396
+ return false;
369
397
  }
370
398
  function isViewerFreeGhRead(args) {
371
399
  if (args.some((a) => VIEWER.test(a))) return false;
@@ -1254,8 +1282,13 @@ __export(cli_shared_exports, {
1254
1282
  repoProject: () => repoProject,
1255
1283
  setGhReadTokenProvider: () => setGhReadTokenProvider,
1256
1284
  setGhWriteTokenProvider: () => setGhWriteTokenProvider,
1257
- setInjectedStdin: () => setInjectedStdin
1285
+ setInjectedStdin: () => setInjectedStdin,
1286
+ shouldRetryIntegrationRefusalOnAmbient: () => shouldRetryIntegrationRefusalOnAmbient
1258
1287
  });
1288
+ function shouldRetryIntegrationRefusalOnAmbient(err, env = process.env) {
1289
+ if (env.MMI_ACTOR?.trim() === "app") return false;
1290
+ return /Resource not accessible by integration/i.test(String(err?.stderr ?? ""));
1291
+ }
1259
1292
  function setGhReadTokenProvider(provider) {
1260
1293
  ghReadTokenProvider = provider;
1261
1294
  }
@@ -1265,8 +1298,18 @@ function setGhWriteTokenProvider(provider) {
1265
1298
  async function ghFilingAppEnv(file, args) {
1266
1299
  if (!ghWriteTokenProvider || !/(^|[\\/])gh(\.exe)?$/i.test(file) || process.env.MMI_ACTOR?.trim() === "personal") return void 0;
1267
1300
  if (!isAppFilingWrite(args)) return void 0;
1268
- const token = await ghWriteTokenProvider().catch(() => void 0);
1269
- return token ? { ...process.env, GH_TOKEN: token } : void 0;
1301
+ const explicitApp = process.env.MMI_ACTOR?.trim() === "app";
1302
+ let token;
1303
+ try {
1304
+ token = await ghWriteTokenProvider();
1305
+ } catch (e) {
1306
+ if (explicitApp) throw e;
1307
+ return void 0;
1308
+ }
1309
+ if (!token && explicitApp) {
1310
+ throw new Error("app actor: filing write token unavailable \u2014 refusing personal-token fallback under MMI_ACTOR=app");
1311
+ }
1312
+ return token ? { ...process.env, GH_TOKEN: token, MMI_GH_POOL: "app" } : void 0;
1270
1313
  }
1271
1314
  async function ghReadAppEnv(file, args) {
1272
1315
  if (!ghReadTokenProvider || !/(^|[\\/])gh(\.exe)?$/i.test(file) || process.env.MMI_ACTOR?.trim() === "personal") return void 0;
@@ -1477,7 +1520,7 @@ var init_cli_shared = __esm({
1477
1520
  try {
1478
1521
  return await run(appEnv);
1479
1522
  } catch (e) {
1480
- if (/Resource not accessible by integration/i.test(String(e.stderr ?? ""))) return run();
1523
+ if (shouldRetryIntegrationRefusalOnAmbient(e)) return run();
1481
1524
  throw e;
1482
1525
  }
1483
1526
  };
@@ -7385,7 +7428,11 @@ async function mintCommandWriteToken(deps, commandPath4) {
7385
7428
  }
7386
7429
  async function mintFilingWriteToken(deps) {
7387
7430
  try {
7388
- return await mintFromMember(deps, { metadata: "read", issues: "write" }, APP_VAULT_KEYS);
7431
+ return await mintFromMember(
7432
+ deps,
7433
+ { metadata: "read", contents: "write", issues: "write", pull_requests: "write" },
7434
+ APP_VAULT_KEYS
7435
+ );
7389
7436
  } catch (e) {
7390
7437
  if (e instanceof AppActorError) throw e;
7391
7438
  throw new AppActorError(`app actor: filing token mint failed (${e?.constructor?.name ?? "Error"})`);
@@ -7512,6 +7559,11 @@ async function pollTokenOrUndefined(deps, env = process.env) {
7512
7559
  }
7513
7560
  var notedIneligibleCommand = false;
7514
7561
  var notedVaultDenied = false;
7562
+ var APP_SUBPROCESS_ROUTED_COMMANDS = /* @__PURE__ */ new Set([
7563
+ "issue create",
7564
+ "pr create",
7565
+ "pr merge"
7566
+ ]);
7515
7567
  async function activateAppActor(commandPath4, env, mint, note = (line) => process.stderr.write(`${line}
7516
7568
  `)) {
7517
7569
  activeQuotaScope = void 0;
@@ -7522,7 +7574,7 @@ async function activateAppActor(commandPath4, env, mint, note = (line) => proces
7522
7574
  throw new AppActorError(`app actor: unknown ${APP_ACTOR_ENV} value \u2014 only 'app' and 'personal' are supported; refusing to guess an identity`);
7523
7575
  }
7524
7576
  if (!APP_ELIGIBLE_COMMANDS.has(commandPath4) && !APP_WRITE_COMMANDS.has(commandPath4)) {
7525
- if (requested === "app" && !notedIneligibleCommand) {
7577
+ if (requested === "app" && !notedIneligibleCommand && !APP_SUBPROCESS_ROUTED_COMMANDS.has(commandPath4)) {
7526
7578
  notedIneligibleCommand = true;
7527
7579
  note(`app actor: '${commandPath4}' is personal-only (viewer/@me/authorship) \u2014 running on the personal token despite ${APP_ACTOR_ENV}=app`);
7528
7580
  }
@@ -14003,6 +14055,11 @@ mutation($projectId: ID!, $itemId: ID!) {
14003
14055
  }
14004
14056
  }`;
14005
14057
  async function updateItemSingleSelect(client, projectId, itemId, fieldId, optionId) {
14058
+ if (process.env.MMI_ACTOR?.trim() === "app") {
14059
+ const { writeHubBoardField: writeHubBoardField2 } = await Promise.resolve().then(() => (init_board_write(), board_write_exports));
14060
+ await writeHubBoardField2({ projectId, itemId, fieldId, optionId });
14061
+ return { credential: "app_installation" };
14062
+ }
14006
14063
  try {
14007
14064
  await client.graphql(UPDATE_ITEM_FIELD_MUTATION, { projectId, itemId, fieldId, optionId });
14008
14065
  return { credential: "user" };
@@ -19193,10 +19250,10 @@ var rollout_plan_default = {
19193
19250
  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)."
19194
19251
  },
19195
19252
  baseline: {
19196
- version: "4.5.192",
19197
- tag: "v4.5.192",
19198
- commit: "f1f8ae295dcd",
19199
- npm: "@mutmutco/cli@4.5.192"
19253
+ version: "4.5.194",
19254
+ tag: "v4.5.194",
19255
+ commit: "e53e981582fc",
19256
+ npm: "@mutmutco/cli@4.5.194"
19200
19257
  },
19201
19258
  exitCriterion: "fleet-n-of-n",
19202
19259
  hubOnlyShortcut: "forbidden",
@@ -19213,14 +19270,14 @@ var rollout_plan_default = {
19213
19270
  repo: "mutmutco/mmi-hub",
19214
19271
  role: "canary",
19215
19272
  schedule: "train",
19216
- v3Target: "v4.5.192"
19273
+ v3Target: "v4.5.194"
19217
19274
  }
19218
19275
  ],
19219
19276
  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.",
19220
19277
  rollback: {
19221
19278
  independent: true,
19222
- mechanism: "npm dist-tag latest -> 4.5.192 and redeploy the Hub Lambda from tag v4.5.192 (f1f8ae295dcd); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19223
- v3Target: "v4.5.192 (@mutmutco/cli@4.5.192, tag commit f1f8ae295dcd \u2014 last known-good release carrying the repo-index v4-only contract)"
19279
+ mechanism: "npm dist-tag latest -> 4.5.194 and redeploy the Hub Lambda from tag v4.5.194 (e53e981582fc); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
19280
+ v3Target: "v4.5.194 (@mutmutco/cli@4.5.194, tag commit e53e981582fc \u2014 last known-good release carrying the repo-index v4-only contract)"
19224
19281
  }
19225
19282
  },
19226
19283
  {
@@ -33368,11 +33425,33 @@ function planRemoteScript(dests) {
33368
33425
  `;
33369
33426
  }
33370
33427
  var ALERT_DIR = "/var/lib/mmi-control/alerts";
33428
+ var SUPPRESSED_RUNNER_PRIVATE_KEY_GLOB = "*/.local/share/docker/containerd/daemon/io.containerd.snapshotter.v1.overlayfs/snapshots/*/fs/etc/ssl/private/ssl-cert-snakeoil.key";
33429
+ var SUPPRESSED_RUNNER_PRIVATE_KEY_RE = new RegExp(
33430
+ `^${SUPPRESSED_RUNNER_PRIVATE_KEY_GLOB.split("*").map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*")}$`
33431
+ );
33432
+ function isSuppressedRunnerPrivateKeyPath(p) {
33433
+ return SUPPRESSED_RUNNER_PRIVATE_KEY_RE.test(p.trim());
33434
+ }
33371
33435
  function parseAlerts(output) {
33372
33436
  const out = [];
33373
33437
  for (const line of output.split("\n")) {
33374
33438
  const m = /^ALERT ([A-Za-z0-9._-]+) ?(.*)$/.exec(line.trim());
33375
- if (m) out.push({ name: m[1], message: m[2].trim() });
33439
+ if (!m) continue;
33440
+ const name = m[1];
33441
+ let message2 = m[2].trim();
33442
+ if (name === "runner-private-key") {
33443
+ const pm = /^(\d+)( private key file\(s\) readable by every CI job on this box \(#7535\): )(.+)$/.exec(message2);
33444
+ if (pm) {
33445
+ const advertisedCount = Number(pm[1]);
33446
+ const paths = pm[3].trim().split(/\s+/).filter(Boolean);
33447
+ if (paths.length === advertisedCount) {
33448
+ const kept = paths.filter((p) => !isSuppressedRunnerPrivateKeyPath(p));
33449
+ if (kept.length === 0) continue;
33450
+ message2 = `${kept.length}${pm[2]}${kept.join(" ")}`;
33451
+ }
33452
+ }
33453
+ }
33454
+ out.push({ name, message: message2 });
33376
33455
  }
33377
33456
  return out;
33378
33457
  }
@@ -47553,6 +47632,19 @@ async function attachToProject(issueNumber, repo, priority) {
47553
47632
  defaultGitHubClient()
47554
47633
  );
47555
47634
  if (!contentId) throw new Error("could not resolve issue node id");
47635
+ if (process.env.MMI_ACTOR?.trim() === "app") {
47636
+ const projectItemId2 = await attachViaHubApp(cfg, contentId);
47637
+ if (projectItemId2 && priority) {
47638
+ try {
47639
+ await setBoardItemPriority(defaultGitHubClient(), cfg, projectItemId2, priority);
47640
+ } catch (e) {
47641
+ const err = e;
47642
+ process.stderr.write(`warning: issue #${issueNumber} board Priority not set: ${(err.stderr || err.message || String(e)).trim()}
47643
+ `);
47644
+ }
47645
+ }
47646
+ return { projectItemId: projectItemId2, onBoard: true, credential: "app_installation" };
47647
+ }
47556
47648
  const { stdout } = await execFileP("gh", buildAddToProjectArgs(cfg.projectId, contentId), { timeout: GH_MUTATION_TIMEOUT_MS });
47557
47649
  const projectItemId = parseAddedItemId(stdout);
47558
47650
  if (projectItemId && priority) {
@@ -58008,7 +58100,12 @@ setPollTokenProvider(async () => activeAppToken() ?? pollTokenOrUndefined(appAct
58008
58100
  setGhReadTokenProvider(pollToken);
58009
58101
  setGitHubReadTokenProvider(pollToken);
58010
58102
  var filingToken;
58011
- setGhWriteTokenProvider(() => filingToken ??= mintFilingWriteToken(appActorDeps()).then((t) => t.token, () => void 0));
58103
+ setGhWriteTokenProvider(() => {
58104
+ if (process.env.MMI_ACTOR?.trim() === "app") {
58105
+ return mintFilingWriteToken(appActorDeps()).then((t) => t.token);
58106
+ }
58107
+ return filingToken ??= mintFilingWriteToken(appActorDeps()).then((t) => t.token, () => void 0);
58108
+ });
58012
58109
  setStatusWriteTokenProvider(() => mintStatusWriteToken(appActorDeps()));
58013
58110
  var registerPreAction = Reflect.get(program2, ["h", "ook"].join(""));
58014
58111
  registerPreAction.call(program2, "preAction", async (_thisCommand, actionCommand) => {
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.192",
3
+ "version": "4.5.194",
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.192",
3
+ "version": "4.5.194",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",