@mutmutco/claude-plugin 4.6.16 → 4.6.17

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.6.16",
4
+ "version": "4.6.17",
5
5
  "mmiCompat": "4.x",
6
6
  "description": "MMI workflow skills and org gates delivery.",
7
7
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -27805,10 +27805,10 @@ var rollout_plan_default = {
27805
27805
  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)."
27806
27806
  },
27807
27807
  baseline: {
27808
- version: "4.6.16",
27809
- tag: "v4.6.16",
27810
- commit: "4bd6f2423939",
27811
- npm: "@mutmutco/cli@4.6.16"
27808
+ version: "4.6.17",
27809
+ tag: "v4.6.17",
27810
+ commit: "efe71da889a6",
27811
+ npm: "@mutmutco/cli@4.6.17"
27812
27812
  },
27813
27813
  exitCriterion: "fleet-n-of-n",
27814
27814
  hubOnlyShortcut: "forbidden",
@@ -27825,14 +27825,14 @@ var rollout_plan_default = {
27825
27825
  repo: "mutmutco/mmi-hub",
27826
27826
  role: "canary",
27827
27827
  schedule: "train",
27828
- v3Target: "v4.6.16"
27828
+ v3Target: "v4.6.17"
27829
27829
  }
27830
27830
  ],
27831
27831
  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.",
27832
27832
  rollback: {
27833
27833
  independent: true,
27834
- mechanism: "npm dist-tag latest -> 4.6.16 and redeploy the Hub Lambda from tag v4.6.16 (4bd6f2423939); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
27835
- v3Target: "v4.6.16 (@mutmutco/cli@4.6.16, tag commit 4bd6f2423939 \u2014 last known-good release carrying the repo-index v4-only contract)"
27834
+ mechanism: "npm dist-tag latest -> 4.6.17 and redeploy the Hub Lambda from tag v4.6.17 (efe71da889a6); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
27835
+ v3Target: "v4.6.17 (@mutmutco/cli@4.6.17, tag commit efe71da889a6 \u2014 last known-good release carrying the repo-index v4-only contract)"
27836
27836
  }
27837
27837
  },
27838
27838
  {
@@ -47165,7 +47165,7 @@ function sshRemoteCommand(remoteCommand) {
47165
47165
  function shellSingleQuote(value) {
47166
47166
  return `'${value.replace(/'/g, `'\\''`)}'`;
47167
47167
  }
47168
- var SSH_RECIPE_AGENT_NOTE = "# agent callers: this is multi-line, so running it inline is denied (#1473/#2125).\n# Use `mmi-cli devops runtime box get <name> --ssh --script <path>` to write it to a file, then `bash <path>`.";
47168
+ var SSH_RECIPE_AGENT_NOTE = '# agent callers: this is multi-line, so running it inline is denied (#1473/#2125).\n# Use `mmi-cli devops runtime box get <name> --ssh --script <path>` to write it to a file, then `bash <path>`.\n# For a multi-line remote body add --stdin (or --body <file>): the recipe then runs `sh -s` on the box,\n# and you stream the body over stdin \u2014 `bash "<path>" < "<body-file>"` \u2014 with no remote re-quoting (#9750).';
47169
47169
  function sshRecipeScript(box, remoteCommand) {
47170
47170
  return `#!/usr/bin/env bash
47171
47171
  ${formatSshRecipe(box, remoteCommand)}
@@ -47249,8 +47249,16 @@ function registerBoxCommands(program3) {
47249
47249
  await failGraceful(e.message);
47250
47250
  }
47251
47251
  });
47252
- box.command("get <name> [command...]").description("one box by name \u2014 its address and ssh key path; --ssh prints a ready-to-run connect recipe").option("--json", "machine-readable output").option("--ssh", "print a copy-paste ssh recipe (runs under the keyless vault wrapper and loads the key into an ssh-agent; the key is never written to a file or echoed)").option("--script <path>", "with --ssh: write the recipe to <path> and print the one line to run \u2014 the runnable form for agent callers, whose transport denies a multi-line inline body (#3385)").action(async (name, command, o) => {
47252
+ box.command("get <name> [command...]").description("one box by name \u2014 its address and ssh key path; --ssh prints a ready-to-run connect recipe").option("--json", "machine-readable output").option("--ssh", "print a copy-paste ssh recipe (runs under the keyless vault wrapper and loads the key into an ssh-agent; the key is never written to a file or echoed)").option("--script <path>", "with --ssh: write the recipe to <path> and print the one line to run \u2014 the runnable form for agent callers, whose transport denies a multi-line inline body (#3385)").option("--stdin", "with --ssh --script: write the recipe with remote command sh -s so a multi-line script can be piped or redirected on stdin without remote shell re-quoting (#9750)").option("--body <file>", 'with --ssh --script: same as --stdin, and name <file> in the printed run line: bash "<script>" < "<file>" (#9750)').action(async (name, command, o) => {
47253
47253
  try {
47254
+ if ((o.stdin || o.body) && (!o.ssh || !o.script)) {
47255
+ await failGraceful("runtime box get: --stdin/--body requires --ssh --script <path> (it writes an sh -s recipe that reads the remote body from stdin)");
47256
+ return;
47257
+ }
47258
+ if ((o.stdin || o.body) && command && command.length) {
47259
+ await failGraceful("runtime box get: cannot combine --stdin/--body with trailing [command...] arguments \u2014 put the commands in the stdin body file instead");
47260
+ return;
47261
+ }
47254
47262
  const { boxes, incomplete } = await fetchInventory();
47255
47263
  const result = lookupBox(name, boxes, incomplete);
47256
47264
  if (result.kind === "unknown") {
@@ -47269,16 +47277,19 @@ function registerBoxCommands(program3) {
47269
47277
  await failGraceful("runtime box get: --script requires --ssh (it writes the ssh connect recipe)");
47270
47278
  return;
47271
47279
  }
47272
- const remote = command && command.length ? command.join(" ") : void 0;
47280
+ const useStdin = Boolean(o.stdin || o.body);
47281
+ const remote = useStdin ? "sh -s" : command && command.length ? command.join(" ") : void 0;
47282
+ const stdinSource = o.body ? `"${o.body}"` : "<body.sh>";
47273
47283
  const wroteScript = o.ssh && o.script ? o.script : null;
47284
+ const runLine = wroteScript ? useStdin ? `bash "${wroteScript}" < ${stdinSource}` : `bash "${wroteScript}"` : void 0;
47274
47285
  if (wroteScript) (0, import_node_fs37.writeFileSync)(wroteScript, sshRecipeScript(found, remote), "utf8");
47275
47286
  if (o.json) {
47276
47287
  console.log(JSON.stringify({
47277
47288
  box: found,
47278
47289
  incomplete,
47279
- ...wroteScript ? { script: { path: wroteScript, run: `bash "${wroteScript}"` } } : {}
47290
+ ...wroteScript ? { script: { path: wroteScript, run: runLine, ...useStdin ? { stdin: o.body ?? true } : {} } } : {}
47280
47291
  }, null, 2));
47281
- } else if (wroteScript) console.log(`wrote ${wroteScript} \u2014 run: bash "${wroteScript}"`);
47292
+ } else if (wroteScript) console.log(`wrote ${wroteScript} \u2014 run: ${runLine}`);
47282
47293
  else if (o.ssh) console.log(`${formatSshRecipe(found, remote)}
47283
47294
  ${SSH_RECIPE_AGENT_NOTE}`);
47284
47295
  else console.log(formatBoxTable([found]));
@@ -68400,6 +68411,22 @@ function stageAllowlistConfig(project2) {
68400
68411
  const stages = cfg.stages.filter((s) => ALLOWLIST_STAGES.includes(s));
68401
68412
  return stages.length > 0 ? { key: cfg.key, stages } : null;
68402
68413
  }
68414
+ function resolveStageAllowlistTarget(repo, projects) {
68415
+ if (!projects) return { kind: "registry-unreadable", exitCode: 1, message: "org access sync: could not read the org project registry \u2014 nothing written" };
68416
+ const project2 = projects.find((p) => (p.repos ?? []).some((r) => r.toLowerCase() === repo.toLowerCase())) ?? null;
68417
+ if (!project2) return { kind: "unregistered", exitCode: 1, message: `org access sync: ${repo} is not in the org project registry \u2014 nothing written` };
68418
+ if (project2.stageAllowlist == null) {
68419
+ return {
68420
+ kind: "no-opt-in",
68421
+ exitCode: 0,
68422
+ json: { repo, optIn: null, stages: [], skipped: "no-stageAllowlist" },
68423
+ message: `org access sync: ${repo} has no stageAllowlist opt-in \u2014 nothing to rebuild (set it with \`mmi-cli oracle org project set ${repo} --var 'stageAllowlist={"key":"<KEY>","stages":["dev"]}'\`)`
68424
+ };
68425
+ }
68426
+ const config = stageAllowlistConfig(project2);
68427
+ if (!config) return { kind: "malformed", exitCode: 1, message: `org access sync: ${repo} has a malformed stageAllowlist in the registry \u2014 set it with \`mmi-cli oracle org project set ${repo} --var 'stageAllowlist={"key":"<KEY>","stages":["dev"]}'\`` };
68428
+ return { kind: "sync", exitCode: 0, config };
68429
+ }
68403
68430
  function developerAdminLogins(collaborators) {
68404
68431
  const logins = /* @__PURE__ */ new Set();
68405
68432
  for (const c of collaborators) {
@@ -72215,11 +72242,13 @@ access.command("sync [repo]").description("rebuild the stage allowlist (e.g. MM-
72215
72242
  if (!repo) return fail("org access sync: pass <owner/repo> or run inside a repo checkout");
72216
72243
  const cfg = await loadConfig();
72217
72244
  if (!cfg.sagaApiUrl) return fail("org access sync: Hub API URL not configured");
72218
- const projects = await fetchProjectsList(registryClientDeps(cfg));
72219
- if (!projects) return failGraceful("org access sync: could not read the org project registry \u2014 nothing written");
72220
- const project2 = projects.find((p) => (p.repos ?? []).some((r) => r.toLowerCase() === repo.toLowerCase())) ?? null;
72221
- const config = stageAllowlistConfig(project2);
72222
- if (!config) return failGraceful(`org access sync: ${repo} has no stageAllowlist opt-in \u2014 set it with \`mmi-cli oracle org project set ${repo} --var 'stageAllowlist={"key":"<KEY>","stages":["dev"]}'\``);
72245
+ const target = resolveStageAllowlistTarget(repo, await fetchProjectsList(registryClientDeps(cfg)));
72246
+ if (target.kind === "no-opt-in") {
72247
+ console.log(o.json ? JSON.stringify(target.json, null, 2) : target.message);
72248
+ return;
72249
+ }
72250
+ if (target.kind !== "sync") return failGraceful(target.message);
72251
+ const config = target.config;
72223
72252
  const secretsDeps = makeSecretsDeps(cfg);
72224
72253
  const client = defaultGitHubClient();
72225
72254
  const result = await syncStageAllowlist({
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.6.16",
3
+ "version": "4.6.17",
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.6.16",
3
+ "version": "4.6.17",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",