@mutmutco/cli 3.113.0 → 3.114.0

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.
Files changed (2) hide show
  1. package/dist/main.cjs +232 -88
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -5001,7 +5001,7 @@ var program = new Command();
5001
5001
  // src/index.ts
5002
5002
  var import_promises11 = require("node:fs/promises");
5003
5003
  var import_node_fs46 = require("node:fs");
5004
- var import_node_child_process19 = require("node:child_process");
5004
+ var import_node_child_process20 = require("node:child_process");
5005
5005
 
5006
5006
  // src/cli-shared.ts
5007
5007
  var import_node_child_process3 = require("node:child_process");
@@ -8820,6 +8820,12 @@ var AUTO_UPDATE_TOGGLE_STEPS = "`/plugin` \u2192 Marketplaces tab \u2192 select
8820
8820
  var CATALOG_CONTENT_REF = "main";
8821
8821
  var CATALOG_REF_PIN_STEPS = `add \`"ref": "${CATALOG_CONTENT_REF}"\` to this marketplace's \`source\` in ~/.claude/plugins/known_marketplaces.json, then restart Claude`;
8822
8822
  var PIN_HEAL_COMMAND = "run `mmi-cli doctor`";
8823
+ var HOST_RUNNING_REMEDY = "quit Claude Code, then run `mmi-cli doctor`";
8824
+ function marketplaceRemedyText(remedy, action, manualSteps) {
8825
+ if (remedy === "manual") return manualSteps;
8826
+ if (remedy === "host-running") return `${HOST_RUNNING_REMEDY} to ${action}`;
8827
+ return `${PIN_HEAL_COMMAND} to ${action}`;
8828
+ }
8823
8829
  var ORG_MARKETPLACE_PINS = { autoUpdate: true, ref: CATALOG_CONTENT_REF };
8824
8830
  function resolveCatalogRef(probe) {
8825
8831
  const { name, registered, ref, autoUpdate } = probe;
@@ -8843,7 +8849,7 @@ function resolveCatalogRef(probe) {
8843
8849
  reason: `no ref pinned \u2014 the catalog is served from the repo's default branch while plugin content is pinned to ${CATALOG_CONTENT_REF}`
8844
8850
  };
8845
8851
  }
8846
- function checkMarketplaceAutoUpdate(probe, healable = false) {
8852
+ function checkMarketplaceAutoUpdate(probe, remedy = "manual") {
8847
8853
  if (!probe) return null;
8848
8854
  const evidence = [`${probe.name}: auto-update ${probe.effective ? "on" : "off"} \u2014 ${probe.reason}`];
8849
8855
  if (probe.effective) {
@@ -8854,11 +8860,11 @@ function checkMarketplaceAutoUpdate(probe, healable = false) {
8854
8860
  ok: true,
8855
8861
  warn: true,
8856
8862
  label: `marketplace auto-update (${probe.name})`,
8857
- detail: `off \u2014 this machine will not pick up a new plugin release on its own; ${healable ? `${PIN_HEAL_COMMAND} to turn it on` : `turn it on with ${AUTO_UPDATE_TOGGLE_STEPS}`}`,
8863
+ detail: `off \u2014 this machine will not pick up a new plugin release on its own; ${marketplaceRemedyText(remedy, "turn it on", `turn it on with ${AUTO_UPDATE_TOGGLE_STEPS}`)}`,
8858
8864
  verbose: evidence
8859
8865
  };
8860
8866
  }
8861
- function checkMarketplaceCatalogRef(probe, healable = false) {
8867
+ function checkMarketplaceCatalogRef(probe, remedy = "manual") {
8862
8868
  if (!probe) return null;
8863
8869
  const label = `marketplace catalog ref (${probe.name})`;
8864
8870
  const evidence = [`${probe.name}: ${probe.reason}`, `auto-update: ${probe.autoUpdate ? "on" : "off"}`];
@@ -8875,7 +8881,7 @@ function checkMarketplaceCatalogRef(probe, healable = false) {
8875
8881
  // ✗ branch carried it in `fix` only because `renderCheckLine` discarded `detail` on failure — one
8876
8882
  // row, two conventions, decided by which field would actually print.
8877
8883
  detail: `${drift} while auto-update is ON`,
8878
- fix: `this machine installs plugin releases advertised by a branch nobody released; ${healable ? `${PIN_HEAL_COMMAND} to pin it` : CATALOG_REF_PIN_STEPS}`,
8884
+ fix: `this machine installs plugin releases advertised by a branch nobody released; ${marketplaceRemedyText(remedy, "pin it", CATALOG_REF_PIN_STEPS)}`,
8879
8885
  verbose: evidence
8880
8886
  };
8881
8887
  }
@@ -8884,11 +8890,11 @@ function checkMarketplaceCatalogRef(probe, healable = false) {
8884
8890
  ok: true,
8885
8891
  warn: true,
8886
8892
  label,
8887
- detail: `${drift} \u2014 harmless while auto-update is off, and the thing to fix before turning it on; ${healable ? `${PIN_HEAL_COMMAND} to pin it` : CATALOG_REF_PIN_STEPS}`,
8893
+ detail: `${drift} \u2014 harmless while auto-update is off, and the thing to fix before turning it on; ${marketplaceRemedyText(remedy, "pin it", CATALOG_REF_PIN_STEPS)}`,
8888
8894
  verbose: evidence
8889
8895
  };
8890
8896
  }
8891
- function marketplaceRows(name, known, settings, healable = false) {
8897
+ function marketplaceRows(name, known, settings, remedy = "manual") {
8892
8898
  const { registered, declared, ref } = readKnownMarketplace(known, name);
8893
8899
  const autoUpdate = resolveAutoUpdate({
8894
8900
  name,
@@ -8896,9 +8902,9 @@ function marketplaceRows(name, known, settings, healable = false) {
8896
8902
  declared,
8897
8903
  settingsDeclared: readSettingsAutoUpdate(settings, name)
8898
8904
  });
8899
- const rows = [checkMarketplaceAutoUpdate(autoUpdate, healable), checkMarketplaceCatalogRef(
8905
+ const rows = [checkMarketplaceAutoUpdate(autoUpdate, remedy), checkMarketplaceCatalogRef(
8900
8906
  resolveCatalogRef({ name, registered, ref, autoUpdate: autoUpdate.effective }),
8901
- healable
8907
+ remedy
8902
8908
  )];
8903
8909
  return rows.filter((r) => r !== null);
8904
8910
  }
@@ -11210,11 +11216,114 @@ var import_node_path19 = require("node:path");
11210
11216
 
11211
11217
  // src/plugin-guard-io.ts
11212
11218
  var import_node_fs17 = require("node:fs");
11213
- var import_node_child_process6 = require("node:child_process");
11219
+ var import_node_child_process7 = require("node:child_process");
11214
11220
  var import_node_path16 = require("node:path");
11215
11221
  var import_node_os5 = require("node:os");
11216
11222
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
11217
11223
 
11224
+ // src/npm-self-update.ts
11225
+ var import_node_child_process6 = require("node:child_process");
11226
+ var import_node_readline = require("node:readline");
11227
+ function npmSelfUpdateArgs(spec) {
11228
+ return [
11229
+ "install",
11230
+ "-g",
11231
+ spec,
11232
+ "--no-audit",
11233
+ "--no-fund",
11234
+ "--progress=false",
11235
+ "--loglevel=http",
11236
+ "--prefer-offline"
11237
+ ];
11238
+ }
11239
+ function packageFromFetchLine(line) {
11240
+ const m = line.match(
11241
+ /GET\s+(?:\d+\s+)?https?:\/\/\S*?\/((?:@[^/\s]+(?:\/|%2[fF]))?[^/\s]+)\/-\/[^/\s]*?-(\d+\.\d+\.\d+[^/\s]*?)\.tgz/u
11242
+ );
11243
+ if (!m) return void 0;
11244
+ return `${m[1].replace(/%2[fF]/u, "/")}@${m[2]}`;
11245
+ }
11246
+ function narrateNpmLine(line) {
11247
+ const text = line.trim();
11248
+ if (!text) return void 0;
11249
+ if (/^npm\s+warn\s+deprecated\b/iu.test(text)) return void 0;
11250
+ if (/added \d+ packages?|removed \d+ packages?|changed \d+ packages?|up to date/iu.test(text)) return text;
11251
+ const fetched = /\bhttp fetch\b/iu.test(text) ? packageFromFetchLine(text) : void 0;
11252
+ if (fetched) return `downloading ${fetched}`;
11253
+ if (/^npm\s+(warn|error)\b/iu.test(text)) return text;
11254
+ if (/\b(idealTree|resolveWithNewModule|placeDep)\b/u.test(text)) return "resolving dependencies";
11255
+ if (/\bhttp fetch\b/iu.test(text)) return "resolving dependencies";
11256
+ if (/\b(reify|extract|ADDITION|CHANGE)\b/u.test(text)) return "installing packages";
11257
+ if (/\baudit\b/iu.test(text)) return "finishing";
11258
+ return void 0;
11259
+ }
11260
+ var NPM_LOG_POINTER = /^npm\s+(error|ERR!)\s+A complete log of this run can be found in/iu;
11261
+ function npmFailureTail(output, maxLines = 6, maxChars = 500) {
11262
+ const lines = output.split(/\r?\n/u).map((l) => l.trimEnd()).filter((l) => l.trim().length > 0).filter((l) => !NPM_LOG_POINTER.test(l.trim())).filter((l) => !/^npm\s+notice\b/iu.test(l.trim()));
11263
+ const tail = lines.slice(-maxLines).join(" \xB7 ");
11264
+ if (!tail) return output.trim().replace(/\s+/gu, " ").slice(-maxChars) || "npm produced no output";
11265
+ return tail.length > maxChars ? `\u2026${tail.slice(-maxChars)}` : tail;
11266
+ }
11267
+ async function runNpmStreaming(opts) {
11268
+ const spawnFn = opts.spawnFn ?? import_node_child_process6.spawn;
11269
+ return await new Promise((resolveRun) => {
11270
+ const chunks = [];
11271
+ let settled = false;
11272
+ let child2;
11273
+ const finish = (result) => {
11274
+ if (settled) return;
11275
+ settled = true;
11276
+ clearTimeout(timer);
11277
+ resolveRun(result);
11278
+ };
11279
+ const timer = setTimeout(() => {
11280
+ child2?.kill("SIGTERM");
11281
+ chunks.push(`npm install timed out after ${opts.timeoutMs}ms`);
11282
+ finish({ ok: false, code: null, output: chunks.join("\n") });
11283
+ }, opts.timeoutMs);
11284
+ try {
11285
+ child2 = spawnFn(opts.file, [...opts.args], {
11286
+ env: opts.env ?? process.env,
11287
+ stdio: ["ignore", "pipe", "pipe"],
11288
+ shell: false,
11289
+ windowsHide: true
11290
+ });
11291
+ } catch (e) {
11292
+ chunks.push(e instanceof Error ? e.message : String(e));
11293
+ finish({ ok: false, code: null, output: chunks.join("\n") });
11294
+ return;
11295
+ }
11296
+ const onLine = (line) => {
11297
+ chunks.push(line);
11298
+ opts.onLine?.(line);
11299
+ };
11300
+ if (child2.stdout) (0, import_node_readline.createInterface)({ input: child2.stdout }).on("line", onLine);
11301
+ if (child2.stderr) (0, import_node_readline.createInterface)({ input: child2.stderr }).on("line", onLine);
11302
+ child2.on("error", (e) => {
11303
+ chunks.push(e.message);
11304
+ finish({ ok: false, code: null, output: chunks.join("\n") });
11305
+ });
11306
+ child2.on("close", (code) => finish({ ok: code === 0, code, output: chunks.join("\n") }));
11307
+ });
11308
+ }
11309
+ async function verifyInstalledCli(probe, target) {
11310
+ let stdout;
11311
+ try {
11312
+ stdout = await probe();
11313
+ } catch (e) {
11314
+ const message = e instanceof Error ? e.message : String(e);
11315
+ return { ok: false, detail: `the installed mmi-cli does not run (${message.trim().split(/\r?\n/u)[0]})` };
11316
+ }
11317
+ const version = /(\d+\.\d+\.\d+[^\s]*)/u.exec(stdout.trim())?.[1];
11318
+ if (!version) {
11319
+ return { ok: false, detail: `the installed mmi-cli printed no version (${stdout.trim().slice(0, 80) || "no output"})` };
11320
+ }
11321
+ if (target && version !== target) {
11322
+ return { ok: false, detail: `the installed mmi-cli reports ${version}, not the ${target} that was just installed` };
11323
+ }
11324
+ return { ok: true, detail: `verified: the installed mmi-cli runs ${version}` };
11325
+ }
11326
+
11218
11327
  // src/plugin-guard.ts
11219
11328
  function buildPluginGuardDecision(i) {
11220
11329
  if (!i.isOrgRepo) return { state: "not-org" };
@@ -11448,12 +11557,12 @@ function marketplaceClonePresent(surface, home, exists = import_node_fs17.exists
11448
11557
  return marketplaceCloneCandidates(surface, home, env).some(exists);
11449
11558
  }
11450
11559
  function runHostBinSync(bin, args) {
11451
- return isWin ? (0, import_node_child_process6.execFileSync)("cmd.exe", ["/c", bin, ...args], {
11560
+ return isWin ? (0, import_node_child_process7.execFileSync)("cmd.exe", ["/c", bin, ...args], {
11452
11561
  encoding: "utf8",
11453
11562
  stdio: ["ignore", "pipe", "ignore"],
11454
11563
  timeout: 15e3,
11455
11564
  windowsHide: true
11456
- }) : (0, import_node_child_process6.execFileSync)(bin, args, {
11565
+ }) : (0, import_node_child_process7.execFileSync)(bin, args, {
11457
11566
  encoding: "utf8",
11458
11567
  stdio: ["ignore", "pipe", "ignore"],
11459
11568
  timeout: 15e3,
@@ -11521,15 +11630,28 @@ async function fetchNpmReleasedVersion() {
11521
11630
  }
11522
11631
  }
11523
11632
  var NPM_INSTALL_TIMEOUT_MS = 12e4;
11524
- async function npmSelfUpdateCli(target, onStep) {
11633
+ var CLI_VERSION_PROBE_TIMEOUT_MS = 3e4;
11634
+ async function npmSelfUpdateCli(target, onStep, deps = {}) {
11525
11635
  const command = cliUpdateCommand(target);
11526
- try {
11527
- onStep?.(command);
11528
- await runHostBin("npm", ["install", "-g", `@mutmutco/cli@${target ?? "latest"}`], { timeout: NPM_INSTALL_TIMEOUT_MS });
11529
- return { ok: true, detail: `${command} exited 0` };
11530
- } catch (e) {
11531
- return { ok: false, detail: e.message.trim().slice(0, 200).replace(/\s+/g, " ") };
11532
- }
11636
+ const args = npmSelfUpdateArgs(`@mutmutco/cli@${target ?? "latest"}`);
11637
+ onStep?.(command);
11638
+ let last = "";
11639
+ const result = await (deps.run ?? runNpmStreaming)({
11640
+ file: isWin ? "cmd.exe" : "npm",
11641
+ args: isWin ? ["/c", "npm", ...args] : args,
11642
+ timeoutMs: NPM_INSTALL_TIMEOUT_MS,
11643
+ onLine: (line) => {
11644
+ const message = narrateNpmLine(line);
11645
+ if (!message || message === last) return;
11646
+ last = message;
11647
+ onStep?.(message);
11648
+ }
11649
+ });
11650
+ if (!result.ok) return { ok: false, detail: npmFailureTail(result.output) };
11651
+ const probe = deps.probeVersion ?? (async () => (await runHostBin("mmi-cli", ["--version"], { timeout: CLI_VERSION_PROBE_TIMEOUT_MS })).stdout);
11652
+ const verified = await verifyInstalledCli(probe, target);
11653
+ onStep?.(verified.detail);
11654
+ return verified.ok ? { ok: true, detail: `${command} exited 0 \u2014 ${verified.detail}` } : { ok: false, detail: `${command} exited 0 but ${verified.detail}` };
11533
11655
  }
11534
11656
  function kiloConfigListsPlugin(configRoot, home = (0, import_node_os5.homedir)(), read = (p) => (0, import_node_fs17.readFileSync)(p, "utf8"), exists = import_node_fs17.existsSync) {
11535
11657
  const candidates = ["kilo.json", "kilo.jsonc", "opencode.json", "opencode.jsonc", "config.json"];
@@ -12016,8 +12138,11 @@ function readKnownMarketplacesFile(path2) {
12016
12138
  return void 0;
12017
12139
  }
12018
12140
  }
12141
+ function claudeCodeEnvMarkerPresent(env = process.env) {
12142
+ return Boolean(env.CLAUDE_CODE_SESSION_ID?.trim() || env.CLAUDECODE?.trim() || env.CLAUDE_PLUGIN_ROOT?.trim());
12143
+ }
12019
12144
  function claudeCodeIsRunning(env = process.env, listProcesses = defaultProcessList) {
12020
- if (env.CLAUDE_CODE_SESSION_ID?.trim() || env.CLAUDECODE?.trim() || env.CLAUDE_PLUGIN_ROOT?.trim()) return true;
12145
+ if (claudeCodeEnvMarkerPresent(env)) return true;
12021
12146
  let table;
12022
12147
  try {
12023
12148
  table = listProcesses();
@@ -12028,7 +12153,7 @@ function claudeCodeIsRunning(env = process.env, listProcesses = defaultProcessLi
12028
12153
  return table.split(/\r?\n/).some((line) => /(^|[/\\])claude(\.(exe|cmd|ps1))?\s/.test(`${line.trim()} `));
12029
12154
  }
12030
12155
  function defaultProcessList() {
12031
- return isWin ? (0, import_node_child_process6.execFileSync)("powershell.exe", ["-NoProfile", "-Command", "Get-CimInstance Win32_Process | ForEach-Object { $_.CommandLine }"], { encoding: "utf8", windowsHide: true, maxBuffer: 32 * 1024 * 1024, timeout: 15e3 }) : (0, import_node_child_process6.execFileSync)("ps", ["-eo", "args="], { encoding: "utf8", windowsHide: true, timeout: 15e3 });
12156
+ return isWin ? (0, import_node_child_process7.execFileSync)("powershell.exe", ["-NoProfile", "-Command", "Get-CimInstance Win32_Process | ForEach-Object { $_.CommandLine }"], { encoding: "utf8", windowsHide: true, maxBuffer: 32 * 1024 * 1024, timeout: 15e3 }) : (0, import_node_child_process7.execFileSync)("ps", ["-eo", "args="], { encoding: "utf8", windowsHide: true, timeout: 15e3 });
12032
12157
  }
12033
12158
  function writeMarketplacePinsOnDisk(path2, pins, succeeded, failedVerb, declineWhileHostLive) {
12034
12159
  if (pins.size === 0) return void 0;
@@ -12059,6 +12184,7 @@ function restoreMarketplacePinsOnDisk(path2, pins, hostIsRunning = claudeCodeIsR
12059
12184
  }
12060
12185
  function applyOrgMarketplacePins(path2, names, hostIsRunning = claudeCodeIsRunning) {
12061
12186
  let landed = false;
12187
+ let blockedByHost = false;
12062
12188
  const detail = writeMarketplacePinsOnDisk(
12063
12189
  path2,
12064
12190
  new Map(names.map((name) => [name, ORG_MARKETPLACE_PINS])),
@@ -12067,9 +12193,13 @@ function applyOrgMarketplacePins(path2, names, hostIsRunning = claudeCodeIsRunni
12067
12193
  return `pinned ${[...pins.keys()].join(", ")} to ${ORG_MARKETPLACE_PINS.ref} with auto-update on`;
12068
12194
  },
12069
12195
  "pin",
12070
- () => hostIsRunning() ? "not pinned \u2014 Claude Code is running and rewrites this registration from its own copy; quit it, then run `mmi-cli doctor`" : void 0
12196
+ () => {
12197
+ if (!hostIsRunning()) return void 0;
12198
+ blockedByHost = true;
12199
+ return "not pinned \u2014 Claude Code is running and rewrites this registration from its own copy; quit it, then run `mmi-cli doctor`";
12200
+ }
12071
12201
  );
12072
- return detail === void 0 ? void 0 : { detail, wrote: landed };
12202
+ return detail === void 0 ? void 0 : { detail, wrote: landed, blockedByHost };
12073
12203
  }
12074
12204
  function writeMarketplacePinPending(path2, names, now = Date.now()) {
12075
12205
  try {
@@ -12777,7 +12907,8 @@ function workflowEntry(repo, workflowPath, yamlText) {
12777
12907
  executor: "github-actions",
12778
12908
  llm: llmFromHeader(yamlText),
12779
12909
  resolved: "live",
12780
- source: `${ORG}/${repo}:${workflowPath}`
12910
+ source: `${ORG}/${repo}:${workflowPath}`,
12911
+ harbourUnmanaged: isHarbourUnmanaged(yamlText)
12781
12912
  };
12782
12913
  }
12783
12914
  function awsRuleEntries(payload) {
@@ -12980,12 +13111,13 @@ function cadenceStale(registryCadence, liveCadence) {
12980
13111
  return !liveCrons.every((cron) => registered.has(cron));
12981
13112
  }
12982
13113
  function reconcileGithubActions(liveGithub, registry2, readRepos, activeWorkflowNames = /* @__PURE__ */ new Set(), disabledWorkflowNames = /* @__PURE__ */ new Set()) {
13114
+ const managedLiveGithub = liveGithub.filter((e) => !e.harbourUnmanaged);
12983
13115
  const registryGithub = registry2.filter((r) => r.executor === "github-actions");
12984
- const liveByName = new Map(liveGithub.map((e) => [e.name, e]));
13116
+ const liveByName = new Map(managedLiveGithub.map((e) => [e.name, e]));
12985
13117
  const registryById = new Map(registryGithub.map((r) => [r.id, r]));
12986
13118
  const drifts = [];
12987
13119
  const parked = [];
12988
- for (const e of liveGithub) {
13120
+ for (const e of managedLiveGithub) {
12989
13121
  if (!registryById.has(e.name)) {
12990
13122
  drifts.push({
12991
13123
  class: "live-but-unregistered",
@@ -13063,9 +13195,11 @@ function strayCronDrift(name) {
13063
13195
  remedy: "strip on: schedule \u2192 workflow_dispatch and let the harbour dispatcher fire on the registry cadence (docs/schedules.md rule 1)"
13064
13196
  };
13065
13197
  }
13066
- var STRAY_CRON_EXEMPT = /* @__PURE__ */ new Set(["MMI-Hub/schedule-plane-deadman"]);
13198
+ function isHarbourUnmanaged(yamlText) {
13199
+ return /^#\s*harbour:\s*unmanaged\s*$/im.test(yamlText);
13200
+ }
13067
13201
  function strayCronDrifts(workflows) {
13068
- return workflows.filter((w) => !STRAY_CRON_EXEMPT.has(w.name)).filter((w) => workflowTriggersSchedule(w.yamlText)).map((w) => strayCronDrift(w.name)).sort((a, b) => a.name.localeCompare(b.name));
13202
+ return workflows.filter((w) => !isHarbourUnmanaged(w.yamlText)).filter((w) => workflowTriggersSchedule(w.yamlText)).map((w) => strayCronDrift(w.name)).sort((a, b) => a.name.localeCompare(b.name));
13069
13203
  }
13070
13204
  function unlauncheredLlmDrift(entry) {
13071
13205
  if (entry.llm !== "yes") return null;
@@ -13180,7 +13314,7 @@ function scheduleRecordFromWorkflow(repo, workflowPath, yamlText) {
13180
13314
  if (!crons.length && !header.schedule) return null;
13181
13315
  const basename6 = workflowPath.split("/").pop() ?? workflowPath;
13182
13316
  const expectedId = `${repo}/${basename6.replace(/\.ya?ml$/, "")}`;
13183
- if (STRAY_CRON_EXEMPT.has(expectedId)) return null;
13317
+ if (isHarbourUnmanaged(yamlText)) return null;
13184
13318
  const missing = SCHEDULE_HEADER_FIELDS.filter((f) => !header[f]);
13185
13319
  if (missing.length) {
13186
13320
  throw new Error(`schedules register: ${expectedId} (${workflowPath}) is a scheduled workflow but is missing the eight-field entry-template header field(s): ${missing.join(", ")} \u2014 see docs/schedules.md "The entry template".`);
@@ -13545,7 +13679,7 @@ ${lines.join("\n")}`;
13545
13679
  }
13546
13680
 
13547
13681
  // src/secrets.ts
13548
- var import_node_child_process7 = require("node:child_process");
13682
+ var import_node_child_process8 = require("node:child_process");
13549
13683
  var import_node_os7 = require("node:os");
13550
13684
 
13551
13685
  // src/gh-create.ts
@@ -14817,7 +14951,7 @@ function spawnExitCode(status, signal) {
14817
14951
  }
14818
14952
  function defaultSpawn(command, args, env) {
14819
14953
  const target = resolveSpawnTarget(command, args);
14820
- const r = (0, import_node_child_process7.spawnSync)(target.cmd, target.args, {
14954
+ const r = (0, import_node_child_process8.spawnSync)(target.cmd, target.args, {
14821
14955
  windowsHide: true,
14822
14956
  stdio: "inherit",
14823
14957
  env,
@@ -15635,10 +15769,10 @@ var rollout_plan_default = {
15635
15769
  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)."
15636
15770
  },
15637
15771
  baseline: {
15638
- version: "3.113.0",
15639
- tag: "v3.113.0",
15640
- commit: "1d1e521aa96f",
15641
- npm: "@mutmutco/cli@3.113.0"
15772
+ version: "3.114.0",
15773
+ tag: "v3.114.0",
15774
+ commit: "cbe675e9904f",
15775
+ npm: "@mutmutco/cli@3.114.0"
15642
15776
  },
15643
15777
  exitCriterion: "fleet-n-of-n",
15644
15778
  hubOnlyShortcut: "forbidden",
@@ -15655,14 +15789,14 @@ var rollout_plan_default = {
15655
15789
  repo: "mutmutco/mmi-hub",
15656
15790
  role: "canary",
15657
15791
  schedule: "train",
15658
- v3Target: "v3.113.0"
15792
+ v3Target: "v3.114.0"
15659
15793
  }
15660
15794
  ],
15661
15795
  rollbackTrigger: "Any red inside the post-cut soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a v3 client refused while the compat window must still admit it (SUPPORTED_MINOR_WINDOW=2, MIN_CLIENT_VERSION 0.0.0 \u2014 D6a), or npm consumer install/doctor failure on the v4 dist.",
15662
15796
  rollback: {
15663
15797
  independent: true,
15664
- mechanism: "npm dist-tag latest -> 3.113.0 and redeploy the Hub Lambda from tag v3.113.0 (1d1e521aa96f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15665
- v3Target: "v3.113.0 (@mutmutco/cli@3.113.0, tag commit 1d1e521aa96f \u2014 the preserved latest-v3 distribution, D6b)"
15798
+ mechanism: "npm dist-tag latest -> 3.114.0 and redeploy the Hub Lambda from tag v3.114.0 (cbe675e9904f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15799
+ v3Target: "v3.114.0 (@mutmutco/cli@3.114.0, tag commit cbe675e9904f \u2014 the preserved latest-v3 distribution, D6b)"
15666
15800
  }
15667
15801
  },
15668
15802
  {
@@ -21316,7 +21450,7 @@ async function runPrLand(prNumber, options, deps) {
21316
21450
  var import_node_fs22 = require("node:fs");
21317
21451
 
21318
21452
  // src/stage-runner.ts
21319
- var import_node_child_process8 = require("node:child_process");
21453
+ var import_node_child_process9 = require("node:child_process");
21320
21454
  var import_node_fs21 = require("node:fs");
21321
21455
  var import_node_path20 = require("node:path");
21322
21456
  var import_node_net = require("node:net");
@@ -21328,7 +21462,7 @@ function normalizeEol(s) {
21328
21462
  }
21329
21463
 
21330
21464
  // src/stage-runner.ts
21331
- var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process8.execFile);
21465
+ var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process9.execFile);
21332
21466
  var DOCKER_TIMEOUT_MS = 15e3;
21333
21467
  var EARLY_EXIT_GRACE_MS = 2e3;
21334
21468
  function earlyExitGraceMs() {
@@ -21850,7 +21984,7 @@ async function startStage(config = {}, opts = {}) {
21850
21984
  let up = sub(config.up.trim());
21851
21985
  if (opts.forceRecreate) up = appendForceRecreate(up);
21852
21986
  const identity = await resolveStageIdentity(cwd);
21853
- const child2 = (0, import_node_child_process8.spawn)(up, {
21987
+ const child2 = (0, import_node_child_process9.spawn)(up, {
21854
21988
  cwd,
21855
21989
  shell: true,
21856
21990
  // POSIX-only: the process group exists for the group-kill in stopStage. On win32 teardown is
@@ -22054,7 +22188,7 @@ async function executeWaveLand(plan, deps, opts = { preserveWorktree: true }) {
22054
22188
  var import_node_os19 = require("node:os");
22055
22189
 
22056
22190
  // src/board.ts
22057
- var import_node_child_process9 = require("node:child_process");
22191
+ var import_node_child_process10 = require("node:child_process");
22058
22192
  var import_node_fs23 = require("node:fs");
22059
22193
  var import_node_os8 = require("node:os");
22060
22194
  var import_node_path21 = require("node:path");
@@ -22399,7 +22533,7 @@ function findDuplicateLesson(source, openLessons) {
22399
22533
  var BOARD_STATUSES = ["Todo", "In Progress", "In Review", "Done"];
22400
22534
 
22401
22535
  // src/board.ts
22402
- var rawExecFileP3 = (0, import_node_util6.promisify)(import_node_child_process9.execFile);
22536
+ var rawExecFileP3 = (0, import_node_util6.promisify)(import_node_child_process10.execFile);
22403
22537
  var BOARD_GIT_TIMEOUT_MS = 1e4;
22404
22538
  var WRITE_PROBE_CONCURRENCY = 8;
22405
22539
  var CLAIM_CONCURRENCY = 5;
@@ -25452,10 +25586,10 @@ function healClaudeBinary(host = {}, onStep) {
25452
25586
  }
25453
25587
 
25454
25588
  // src/statusline-invalidate.ts
25455
- var import_node_child_process10 = require("node:child_process");
25589
+ var import_node_child_process11 = require("node:child_process");
25456
25590
  function invalidateStatuslineBoardCache() {
25457
25591
  try {
25458
- const child2 = (0, import_node_child_process10.spawn)("jerv-cli", ["lane", "ops", "invalidate-board"], {
25592
+ const child2 = (0, import_node_child_process11.spawn)("jerv-cli", ["lane", "ops", "invalidate-board"], {
25459
25593
  detached: true,
25460
25594
  stdio: "ignore",
25461
25595
  windowsHide: true
@@ -25674,12 +25808,12 @@ function renderVerifyBroker(input) {
25674
25808
  }
25675
25809
 
25676
25810
  // src/hotfix-coverage.ts
25677
- var import_node_child_process11 = require("node:child_process");
25811
+ var import_node_child_process12 = require("node:child_process");
25678
25812
  var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
25679
25813
  function checkHotfixCoverage(options = {}) {
25680
25814
  const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
25681
25815
  const ack = (options.ack ?? []).filter(Boolean);
25682
- const git2 = options.git ?? ((args, opts) => (0, import_node_child_process11.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
25816
+ const git2 = options.git ?? ((args, opts) => (0, import_node_child_process12.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
25683
25817
  const revList = (range) => {
25684
25818
  const out = git2(["rev-list", "--no-merges", range]).trim();
25685
25819
  return out ? out.split("\n") : [];
@@ -25747,7 +25881,7 @@ function checkHotfixCoverage(options = {}) {
25747
25881
  }
25748
25882
  function checkHotfixCarries(options) {
25749
25883
  const { cwd = process.cwd(), branch, baseRef, targets } = options;
25750
- const git2 = options.git ?? ((args, opts) => (0, import_node_child_process11.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
25884
+ const git2 = options.git ?? ((args, opts) => (0, import_node_child_process12.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
25751
25885
  const isAncestor = (sha, ref) => {
25752
25886
  try {
25753
25887
  git2(["merge-base", "--is-ancestor", sha, ref]);
@@ -26771,7 +26905,7 @@ async function announceRelease(deps, args) {
26771
26905
 
26772
26906
  // src/repo-index.ts
26773
26907
  var import_node_crypto4 = require("node:crypto");
26774
- var import_node_child_process12 = require("node:child_process");
26908
+ var import_node_child_process13 = require("node:child_process");
26775
26909
  var import_node_fs27 = require("node:fs");
26776
26910
  var import_node_path25 = require("node:path");
26777
26911
  var REPO_INDEX_SCHEMA = 1;
@@ -26917,7 +27051,7 @@ function loadReadmeHints(cwd, candidatePaths) {
26917
27051
  function toPosix(p) {
26918
27052
  return p.split(import_node_path25.sep).join("/");
26919
27053
  }
26920
- function listCandidatePaths(cwd, exec = import_node_child_process12.execFileSync) {
27054
+ function listCandidatePaths(cwd, exec = import_node_child_process13.execFileSync) {
26921
27055
  try {
26922
27056
  const out = exec("git", ["ls-files", "-z", "-c", "-o", "--exclude-standard"], {
26923
27057
  cwd,
@@ -27040,7 +27174,7 @@ function searchRepoIndex(idx, query, limit = 20) {
27040
27174
  }
27041
27175
  return out;
27042
27176
  }
27043
- function inferRepoSlug(cwd, exec = import_node_child_process12.execFileSync) {
27177
+ function inferRepoSlug(cwd, exec = import_node_child_process13.execFileSync) {
27044
27178
  try {
27045
27179
  const url = String(exec("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" })).trim();
27046
27180
  const m = /[:/]([^/]+\/[^/]+?)(?:\.git)?$/.exec(url);
@@ -27190,7 +27324,7 @@ async function gcRepoIndexCloud(deps) {
27190
27324
  var import_node_fs28 = require("node:fs");
27191
27325
  var import_node_os12 = require("node:os");
27192
27326
  var import_node_path26 = require("node:path");
27193
- var import_node_child_process13 = require("node:child_process");
27327
+ var import_node_child_process14 = require("node:child_process");
27194
27328
  var MAX_EMBED_BACKFILL_ROUNDS = 40;
27195
27329
  function normalizeRepo(raw) {
27196
27330
  const t = raw.trim().replace(/\.git$/, "");
@@ -27210,7 +27344,7 @@ function rosterRepos(projects) {
27210
27344
  }
27211
27345
  function shallowClone(repo, dest, token) {
27212
27346
  const basic = Buffer.from(`x-access-token:${token}`, "utf8").toString("base64");
27213
- (0, import_node_child_process13.execFileSync)(
27347
+ (0, import_node_child_process14.execFileSync)(
27214
27348
  "git",
27215
27349
  ["-c", `http.extraHeader=Authorization: Basic ${basic}`, "clone", "--depth", "1", "--single-branch", `https://github.com/${repo}.git`, dest],
27216
27350
  { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true }
@@ -27479,7 +27613,7 @@ async function runRepoIndexHealth(opts) {
27479
27613
  }
27480
27614
 
27481
27615
  // src/spawn-policy-core.ts
27482
- var import_node_child_process14 = require("node:child_process");
27616
+ var import_node_child_process15 = require("node:child_process");
27483
27617
  var import_node_fs30 = require("node:fs");
27484
27618
  var import_node_path27 = require("node:path");
27485
27619
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
@@ -27550,7 +27684,7 @@ function findViolationsInSource(raw) {
27550
27684
  return found;
27551
27685
  }
27552
27686
  function policedFiles(root) {
27553
- const r = (0, import_node_child_process14.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
27687
+ const r = (0, import_node_child_process15.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
27554
27688
  cwd: root,
27555
27689
  encoding: "utf8",
27556
27690
  windowsHide: true,
@@ -27584,7 +27718,7 @@ function runSpawnPolicy(root) {
27584
27718
  }
27585
27719
 
27586
27720
  // src/test-policy-core.ts
27587
- var import_node_child_process15 = require("node:child_process");
27721
+ var import_node_child_process16 = require("node:child_process");
27588
27722
  var import_node_fs31 = require("node:fs");
27589
27723
  var import_node_path28 = require("node:path");
27590
27724
  var POLICY_FILE = "test-policy.json";
@@ -27714,14 +27848,14 @@ function evaluate(changed, policy, present = () => false) {
27714
27848
  return findings;
27715
27849
  }
27716
27850
  function git(args, cwd) {
27717
- return (0, import_node_child_process15.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
27851
+ return (0, import_node_child_process16.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
27718
27852
  }
27719
27853
  var COAUTHOR_KEY = "Co-authored-by";
27720
27854
  var GH_MESSAGE_SEPARATOR = /^-{5,}$/;
27721
27855
  var LIFTED_KEYS = new RegExp(`^(?:${TRAILER_KEY}|${COAUTHOR_KEY}):`, "i");
27722
27856
  function parseTrailers(message, cwd) {
27723
27857
  try {
27724
- return (0, import_node_child_process15.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
27858
+ return (0, import_node_child_process16.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
27725
27859
  windowsHide: true,
27726
27860
  cwd,
27727
27861
  input: message,
@@ -29522,9 +29656,9 @@ ${SSH_RECIPE_AGENT_NOTE}`);
29522
29656
 
29523
29657
  // src/schedules-commands.ts
29524
29658
  var import_promises5 = require("node:fs/promises");
29525
- var import_node_child_process16 = require("node:child_process");
29659
+ var import_node_child_process17 = require("node:child_process");
29526
29660
  var import_node_util7 = require("node:util");
29527
- var execFileP5 = (0, import_node_util7.promisify)(import_node_child_process16.execFile);
29661
+ var execFileP5 = (0, import_node_util7.promisify)(import_node_child_process17.execFile);
29528
29662
  var AWS_REGION = "eu-central-1";
29529
29663
  var AWS_TIMEOUT_MS = 3e4;
29530
29664
  var AWS_RETRY_DELAY_MS = 1500;
@@ -32403,7 +32537,7 @@ var import_node_fs38 = require("node:fs");
32403
32537
  var import_promises8 = require("node:fs/promises");
32404
32538
  var import_node_path36 = require("node:path");
32405
32539
  var import_node_os15 = require("node:os");
32406
- var import_node_child_process17 = require("node:child_process");
32540
+ var import_node_child_process18 = require("node:child_process");
32407
32541
 
32408
32542
  // src/board-advance.ts
32409
32543
  function repoOf2(ref) {
@@ -33009,7 +33143,7 @@ async function remoteBranchExists2(branch, options = {}) {
33009
33143
  }
33010
33144
  var COMPOSE_TIMEOUT_MS = 12e4;
33011
33145
  function spawnDeferredGcSweep() {
33012
- spawnDetachedSelf(["worktree", "gc", "sweep-deferred", "--quiet"], { spawn: import_node_child_process17.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
33146
+ spawnDetachedSelf(["worktree", "gc", "sweep-deferred", "--quiet"], { spawn: import_node_child_process18.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
33013
33147
  }
33014
33148
  async function createDeferredWorktreeStore() {
33015
33149
  try {
@@ -36689,7 +36823,8 @@ var RESTART_LINE = "\u21BB Restart Claude to finish.";
36689
36823
  var VERBOSE_INDENT = " ";
36690
36824
  function checkGlyph(check) {
36691
36825
  if (!check.ok) return "\u2717";
36692
- return check.verified === false ? "?" : "\u2713";
36826
+ if (check.verified === false) return "?";
36827
+ return check.warn ? "\u26A0" : "\u2713";
36693
36828
  }
36694
36829
  function renderCheckLine(check) {
36695
36830
  const head = check.detail ? `${checkGlyph(check)} ${check.label} \u2014 ${check.detail}` : `${checkGlyph(check)} ${check.label}`;
@@ -36707,9 +36842,11 @@ function renderTally(checks) {
36707
36842
  const total = checks.length;
36708
36843
  const failed = checks.filter((c) => !c.ok).length;
36709
36844
  const unverified = checks.filter((c) => c.ok && c.verified === false).length;
36710
- const healthy = total - failed - unverified;
36711
- if (failed === 0 && unverified === 0) return `\u2713 all ${total} checks healthy`;
36845
+ const warned = checks.filter((c) => c.ok && c.verified !== false && c.warn).length;
36846
+ const healthy = total - failed - unverified - warned;
36847
+ if (failed === 0 && unverified === 0 && warned === 0) return `\u2713 all ${total} checks healthy`;
36712
36848
  const parts = [`\u2713 ${healthy} verified healthy`];
36849
+ if (warned > 0) parts.push(`\u26A0 ${warned} warn`);
36713
36850
  if (unverified > 0) parts.push(`? ${unverified} unverified`);
36714
36851
  if (failed > 0) parts.push(`\u2717 ${failed} failed`);
36715
36852
  return `${parts.join(" \xB7 ")} \u2014 ${total} checks`;
@@ -38359,18 +38496,19 @@ async function runDoctorClean(opts, io, deps) {
38359
38496
  if (payload) emitNow(payload);
38360
38497
  }
38361
38498
  async function runMarketplaceRows() {
38499
+ let healed;
38362
38500
  if (applyEnv) {
38363
- const healed = deps.healMarketplacePins();
38364
- if (healed) {
38501
+ healed = deps.healMarketplacePins();
38502
+ if (healed?.wrote) {
38365
38503
  healIntent(`marketplace pins \u2014 ${healed.detail}`);
38366
- if (healed.wrote) {
38367
- traceHeal("env-heals");
38368
- markHealChanged();
38369
- restartPending = true;
38370
- }
38504
+ traceHeal("env-heals");
38505
+ markHealChanged();
38506
+ restartPending = true;
38371
38507
  }
38372
38508
  }
38373
- for (const row of deps.marketplaceRows()) emitNow(row);
38509
+ for (const row of deps.marketplaceRows(healed?.blockedByHost)) {
38510
+ emitNow(healed && !healed.wrote ? { ...row, verbose: [...row.verbose ?? [], `heal: ${healed.detail}`] } : row);
38511
+ }
38374
38512
  }
38375
38513
  async function runTrainSyncRow() {
38376
38514
  try {
@@ -38903,9 +39041,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
38903
39041
  var import_node_fs45 = require("node:fs");
38904
39042
  var import_node_os18 = require("node:os");
38905
39043
  var import_node_path42 = require("node:path");
38906
- var import_node_child_process18 = require("node:child_process");
39044
+ var import_node_child_process19 = require("node:child_process");
38907
39045
  var import_node_util8 = require("node:util");
38908
- var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process18.execFile);
39046
+ var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process19.execFile);
38909
39047
  var MMI_PLUGIN_ID2 = "mmi@mutmutco";
38910
39048
  function installedClaudePluginVersion() {
38911
39049
  try {
@@ -38951,12 +39089,12 @@ function installedSurfacePluginVersion(surface) {
38951
39089
  if (token === "claude") return installedClaudePluginVersion();
38952
39090
  if (token !== "codex") return void 0;
38953
39091
  try {
38954
- const raw = process.platform === "win32" ? (0, import_node_child_process18.execFileSync)("cmd.exe", ["/c", "codex", "plugin", "list", "--json"], {
39092
+ const raw = process.platform === "win32" ? (0, import_node_child_process19.execFileSync)("cmd.exe", ["/c", "codex", "plugin", "list", "--json"], {
38955
39093
  encoding: "utf8",
38956
39094
  stdio: ["ignore", "pipe", "ignore"],
38957
39095
  timeout: 15e3,
38958
39096
  windowsHide: true
38959
- }) : (0, import_node_child_process18.execFileSync)("codex", ["plugin", "list", "--json"], {
39097
+ }) : (0, import_node_child_process19.execFileSync)("codex", ["plugin", "list", "--json"], {
38960
39098
  encoding: "utf8",
38961
39099
  stdio: ["ignore", "pipe", "ignore"],
38962
39100
  timeout: 15e3,
@@ -38974,7 +39112,7 @@ function installedActivePluginVersion(surface = detectSurface(process.env)) {
38974
39112
  }
38975
39113
  function worktreeRootSync() {
38976
39114
  try {
38977
- const out = (0, import_node_child_process18.execFileSync)("git", ["rev-parse", "--show-toplevel"], { windowsHide: true, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
39115
+ const out = (0, import_node_child_process19.execFileSync)("git", ["rev-parse", "--show-toplevel"], { windowsHide: true, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
38978
39116
  let root = out.endsWith("\n") ? out.slice(0, -1) : out;
38979
39117
  if (process.platform === "win32" && root.endsWith("\r")) root = root.slice(0, -1);
38980
39118
  return root || null;
@@ -39227,7 +39365,7 @@ function mmiDoctorDeps(opts = {}) {
39227
39365
  sessionPayload: () => readSessionPayload(process.cwd()),
39228
39366
  // #3485 items 9 and 8: why the MMI plugin has never printed an "updated ? please restart" notice, and
39229
39367
  // which branch it would pick one up from. Two local file reads, no network, fail-soft to no rows.
39230
- marketplaceRows: () => {
39368
+ marketplaceRows: (hostBlocked) => {
39231
39369
  try {
39232
39370
  if (detectSurface(process.env) === "codex") return [];
39233
39371
  const home = (0, import_node_os19.homedir)();
@@ -39236,8 +39374,14 @@ function mmiDoctorDeps(opts = {}) {
39236
39374
  readFileSyncSafe((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
39237
39375
  readFileSyncSafe((0, import_node_path43.join)(home, ".claude", "settings.json"), import_node_fs46.readFileSync),
39238
39376
  // #3974: this CLI heals these rows, so report mode names the doctor run rather than the hand
39239
- // edit. Unconditional ? it is a fact about mmi-cli, not about the lane this run is on.
39240
- true
39377
+ // edit. #4792 narrows WHICH run: `applyOrgMarketplacePins` declines outright while Claude Code
39378
+ // is up, because the host owns this file and rewrites it from its own copy (#4083). Naming the
39379
+ // doctor there is the circular-and-false remedy the issue was filed on — doctor ran twice and
39380
+ // healed neither row. So the live host, when there is one, is what the rows name first.
39381
+ // The heal lane pays for the full process probe and hands its answer down; every other lane
39382
+ // reads the free env markers, which are set precisely when doctor runs inside a Claude session
39383
+ // — the case the owner hit. A cheap lane never shells a process listing for this.
39384
+ hostBlocked ?? claudeCodeEnvMarkerPresent() ? "host-running" : "doctor"
39241
39385
  );
39242
39386
  const pending = readMarketplacePinPending(
39243
39387
  (0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
@@ -39251,7 +39395,7 @@ function mmiDoctorDeps(opts = {}) {
39251
39395
  ...rest,
39252
39396
  ok: true,
39253
39397
  warn: true,
39254
- detail: `pending restart ? doctor pinned main at ${pending.at}; restart Claude Code to load it`,
39398
+ detail: `pending restart \u2014 doctor pinned main at ${pending.at}; restart Claude Code to load it`,
39255
39399
  verbose: [...row.verbose ?? [], "known_marketplaces.json was rewritten by the running Claude host after the verified doctor write"]
39256
39400
  };
39257
39401
  });
@@ -39864,11 +40008,11 @@ function runWorktreeInstall(command, cwd, quiet, opts) {
39864
40008
  "pipe"
39865
40009
  ];
39866
40010
  return new Promise((resolve5, reject) => {
39867
- const child2 = opts?.shell ? (0, import_node_child_process19.spawn)(command, { cwd, stdio, windowsHide: true, shell: true }) : (() => {
40011
+ const child2 = opts?.shell ? (0, import_node_child_process20.spawn)(command, { cwd, stdio, windowsHide: true, shell: true }) : (() => {
39868
40012
  const [bin, ...args] = command.split(" ");
39869
40013
  const file = isWin2 ? "cmd.exe" : bin;
39870
40014
  const spawnArgs = isWin2 ? ["/c", bin, ...args] : args;
39871
- return (0, import_node_child_process19.spawn)(file, spawnArgs, { cwd, stdio, windowsHide: true });
40015
+ return (0, import_node_child_process20.spawn)(file, spawnArgs, { cwd, stdio, windowsHide: true });
39872
40016
  })();
39873
40017
  let stderrTail = "";
39874
40018
  child2.stderr?.on("data", (chunk) => {
@@ -40251,7 +40395,7 @@ function scheduleRelatedDiscovery(o) {
40251
40395
  try {
40252
40396
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
40253
40397
  if (o.repo) args.push("--repo", o.repo);
40254
- spawnDetachedSelf(args, { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
40398
+ spawnDetachedSelf(args, { spawn: import_node_child_process20.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
40255
40399
  } catch {
40256
40400
  }
40257
40401
  }
@@ -42849,11 +42993,11 @@ program2.command("session-start").description("run the SessionStart verbs (whoam
42849
42993
  for (const line of scratchGcLines(process.cwd())) bannerIo.log(line);
42850
42994
  const worktreeBanner = worktreeAutoProvisionBanner(process.cwd());
42851
42995
  if (worktreeBanner) {
42852
- spawnDetachedSelf(["worktree", "setup", "--quiet"], { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
42996
+ spawnDetachedSelf(["worktree", "setup", "--quiet"], { spawn: import_node_child_process20.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
42853
42997
  bannerIo.log(worktreeBanner);
42854
42998
  }
42855
42999
  if (shouldSpawnReleaseCatchup((0, import_node_os19.homedir)(), process.env, readReleaseCatchupState)) {
42856
- spawnDetachedSelf(["plugin", "release-catchup", "--quiet"], { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
43000
+ spawnDetachedSelf(["plugin", "release-catchup", "--quiet"], { spawn: import_node_child_process20.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
42857
43001
  }
42858
43002
  if (isLinkedWorktree(process.cwd())) {
42859
43003
  const primaryRoot = await primaryCheckoutRoot(process.cwd());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "3.113.0",
3
+ "version": "3.114.0",
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",