@mutmutco/cli 3.112.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 -87
  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,6 +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$/, "")}`;
13317
+ if (isHarbourUnmanaged(yamlText)) return null;
13183
13318
  const missing = SCHEDULE_HEADER_FIELDS.filter((f) => !header[f]);
13184
13319
  if (missing.length) {
13185
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".`);
@@ -13544,7 +13679,7 @@ ${lines.join("\n")}`;
13544
13679
  }
13545
13680
 
13546
13681
  // src/secrets.ts
13547
- var import_node_child_process7 = require("node:child_process");
13682
+ var import_node_child_process8 = require("node:child_process");
13548
13683
  var import_node_os7 = require("node:os");
13549
13684
 
13550
13685
  // src/gh-create.ts
@@ -14816,7 +14951,7 @@ function spawnExitCode(status, signal) {
14816
14951
  }
14817
14952
  function defaultSpawn(command, args, env) {
14818
14953
  const target = resolveSpawnTarget(command, args);
14819
- 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, {
14820
14955
  windowsHide: true,
14821
14956
  stdio: "inherit",
14822
14957
  env,
@@ -15634,10 +15769,10 @@ var rollout_plan_default = {
15634
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)."
15635
15770
  },
15636
15771
  baseline: {
15637
- version: "3.112.0",
15638
- tag: "v3.112.0",
15639
- commit: "e6eaa0103b25",
15640
- npm: "@mutmutco/cli@3.112.0"
15772
+ version: "3.114.0",
15773
+ tag: "v3.114.0",
15774
+ commit: "cbe675e9904f",
15775
+ npm: "@mutmutco/cli@3.114.0"
15641
15776
  },
15642
15777
  exitCriterion: "fleet-n-of-n",
15643
15778
  hubOnlyShortcut: "forbidden",
@@ -15654,14 +15789,14 @@ var rollout_plan_default = {
15654
15789
  repo: "mutmutco/mmi-hub",
15655
15790
  role: "canary",
15656
15791
  schedule: "train",
15657
- v3Target: "v3.112.0"
15792
+ v3Target: "v3.114.0"
15658
15793
  }
15659
15794
  ],
15660
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.",
15661
15796
  rollback: {
15662
15797
  independent: true,
15663
- mechanism: "npm dist-tag latest -> 3.112.0 and redeploy the Hub Lambda from tag v3.112.0 (e6eaa0103b25); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15664
- v3Target: "v3.112.0 (@mutmutco/cli@3.112.0, tag commit e6eaa0103b25 \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)"
15665
15800
  }
15666
15801
  },
15667
15802
  {
@@ -21315,7 +21450,7 @@ async function runPrLand(prNumber, options, deps) {
21315
21450
  var import_node_fs22 = require("node:fs");
21316
21451
 
21317
21452
  // src/stage-runner.ts
21318
- var import_node_child_process8 = require("node:child_process");
21453
+ var import_node_child_process9 = require("node:child_process");
21319
21454
  var import_node_fs21 = require("node:fs");
21320
21455
  var import_node_path20 = require("node:path");
21321
21456
  var import_node_net = require("node:net");
@@ -21327,7 +21462,7 @@ function normalizeEol(s) {
21327
21462
  }
21328
21463
 
21329
21464
  // src/stage-runner.ts
21330
- 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);
21331
21466
  var DOCKER_TIMEOUT_MS = 15e3;
21332
21467
  var EARLY_EXIT_GRACE_MS = 2e3;
21333
21468
  function earlyExitGraceMs() {
@@ -21849,7 +21984,7 @@ async function startStage(config = {}, opts = {}) {
21849
21984
  let up = sub(config.up.trim());
21850
21985
  if (opts.forceRecreate) up = appendForceRecreate(up);
21851
21986
  const identity = await resolveStageIdentity(cwd);
21852
- const child2 = (0, import_node_child_process8.spawn)(up, {
21987
+ const child2 = (0, import_node_child_process9.spawn)(up, {
21853
21988
  cwd,
21854
21989
  shell: true,
21855
21990
  // POSIX-only: the process group exists for the group-kill in stopStage. On win32 teardown is
@@ -22053,7 +22188,7 @@ async function executeWaveLand(plan, deps, opts = { preserveWorktree: true }) {
22053
22188
  var import_node_os19 = require("node:os");
22054
22189
 
22055
22190
  // src/board.ts
22056
- var import_node_child_process9 = require("node:child_process");
22191
+ var import_node_child_process10 = require("node:child_process");
22057
22192
  var import_node_fs23 = require("node:fs");
22058
22193
  var import_node_os8 = require("node:os");
22059
22194
  var import_node_path21 = require("node:path");
@@ -22398,7 +22533,7 @@ function findDuplicateLesson(source, openLessons) {
22398
22533
  var BOARD_STATUSES = ["Todo", "In Progress", "In Review", "Done"];
22399
22534
 
22400
22535
  // src/board.ts
22401
- 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);
22402
22537
  var BOARD_GIT_TIMEOUT_MS = 1e4;
22403
22538
  var WRITE_PROBE_CONCURRENCY = 8;
22404
22539
  var CLAIM_CONCURRENCY = 5;
@@ -25451,10 +25586,10 @@ function healClaudeBinary(host = {}, onStep) {
25451
25586
  }
25452
25587
 
25453
25588
  // src/statusline-invalidate.ts
25454
- var import_node_child_process10 = require("node:child_process");
25589
+ var import_node_child_process11 = require("node:child_process");
25455
25590
  function invalidateStatuslineBoardCache() {
25456
25591
  try {
25457
- 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"], {
25458
25593
  detached: true,
25459
25594
  stdio: "ignore",
25460
25595
  windowsHide: true
@@ -25673,12 +25808,12 @@ function renderVerifyBroker(input) {
25673
25808
  }
25674
25809
 
25675
25810
  // src/hotfix-coverage.ts
25676
- var import_node_child_process11 = require("node:child_process");
25811
+ var import_node_child_process12 = require("node:child_process");
25677
25812
  var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
25678
25813
  function checkHotfixCoverage(options = {}) {
25679
25814
  const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
25680
25815
  const ack = (options.ack ?? []).filter(Boolean);
25681
- 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"] }));
25682
25817
  const revList = (range) => {
25683
25818
  const out = git2(["rev-list", "--no-merges", range]).trim();
25684
25819
  return out ? out.split("\n") : [];
@@ -25746,7 +25881,7 @@ function checkHotfixCoverage(options = {}) {
25746
25881
  }
25747
25882
  function checkHotfixCarries(options) {
25748
25883
  const { cwd = process.cwd(), branch, baseRef, targets } = options;
25749
- 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"] }));
25750
25885
  const isAncestor = (sha, ref) => {
25751
25886
  try {
25752
25887
  git2(["merge-base", "--is-ancestor", sha, ref]);
@@ -26770,7 +26905,7 @@ async function announceRelease(deps, args) {
26770
26905
 
26771
26906
  // src/repo-index.ts
26772
26907
  var import_node_crypto4 = require("node:crypto");
26773
- var import_node_child_process12 = require("node:child_process");
26908
+ var import_node_child_process13 = require("node:child_process");
26774
26909
  var import_node_fs27 = require("node:fs");
26775
26910
  var import_node_path25 = require("node:path");
26776
26911
  var REPO_INDEX_SCHEMA = 1;
@@ -26916,7 +27051,7 @@ function loadReadmeHints(cwd, candidatePaths) {
26916
27051
  function toPosix(p) {
26917
27052
  return p.split(import_node_path25.sep).join("/");
26918
27053
  }
26919
- function listCandidatePaths(cwd, exec = import_node_child_process12.execFileSync) {
27054
+ function listCandidatePaths(cwd, exec = import_node_child_process13.execFileSync) {
26920
27055
  try {
26921
27056
  const out = exec("git", ["ls-files", "-z", "-c", "-o", "--exclude-standard"], {
26922
27057
  cwd,
@@ -27039,7 +27174,7 @@ function searchRepoIndex(idx, query, limit = 20) {
27039
27174
  }
27040
27175
  return out;
27041
27176
  }
27042
- function inferRepoSlug(cwd, exec = import_node_child_process12.execFileSync) {
27177
+ function inferRepoSlug(cwd, exec = import_node_child_process13.execFileSync) {
27043
27178
  try {
27044
27179
  const url = String(exec("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" })).trim();
27045
27180
  const m = /[:/]([^/]+\/[^/]+?)(?:\.git)?$/.exec(url);
@@ -27189,7 +27324,7 @@ async function gcRepoIndexCloud(deps) {
27189
27324
  var import_node_fs28 = require("node:fs");
27190
27325
  var import_node_os12 = require("node:os");
27191
27326
  var import_node_path26 = require("node:path");
27192
- var import_node_child_process13 = require("node:child_process");
27327
+ var import_node_child_process14 = require("node:child_process");
27193
27328
  var MAX_EMBED_BACKFILL_ROUNDS = 40;
27194
27329
  function normalizeRepo(raw) {
27195
27330
  const t = raw.trim().replace(/\.git$/, "");
@@ -27209,7 +27344,7 @@ function rosterRepos(projects) {
27209
27344
  }
27210
27345
  function shallowClone(repo, dest, token) {
27211
27346
  const basic = Buffer.from(`x-access-token:${token}`, "utf8").toString("base64");
27212
- (0, import_node_child_process13.execFileSync)(
27347
+ (0, import_node_child_process14.execFileSync)(
27213
27348
  "git",
27214
27349
  ["-c", `http.extraHeader=Authorization: Basic ${basic}`, "clone", "--depth", "1", "--single-branch", `https://github.com/${repo}.git`, dest],
27215
27350
  { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true }
@@ -27478,7 +27613,7 @@ async function runRepoIndexHealth(opts) {
27478
27613
  }
27479
27614
 
27480
27615
  // src/spawn-policy-core.ts
27481
- var import_node_child_process14 = require("node:child_process");
27616
+ var import_node_child_process15 = require("node:child_process");
27482
27617
  var import_node_fs30 = require("node:fs");
27483
27618
  var import_node_path27 = require("node:path");
27484
27619
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
@@ -27549,7 +27684,7 @@ function findViolationsInSource(raw) {
27549
27684
  return found;
27550
27685
  }
27551
27686
  function policedFiles(root) {
27552
- 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"], {
27553
27688
  cwd: root,
27554
27689
  encoding: "utf8",
27555
27690
  windowsHide: true,
@@ -27583,7 +27718,7 @@ function runSpawnPolicy(root) {
27583
27718
  }
27584
27719
 
27585
27720
  // src/test-policy-core.ts
27586
- var import_node_child_process15 = require("node:child_process");
27721
+ var import_node_child_process16 = require("node:child_process");
27587
27722
  var import_node_fs31 = require("node:fs");
27588
27723
  var import_node_path28 = require("node:path");
27589
27724
  var POLICY_FILE = "test-policy.json";
@@ -27713,14 +27848,14 @@ function evaluate(changed, policy, present = () => false) {
27713
27848
  return findings;
27714
27849
  }
27715
27850
  function git(args, cwd) {
27716
- 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 });
27717
27852
  }
27718
27853
  var COAUTHOR_KEY = "Co-authored-by";
27719
27854
  var GH_MESSAGE_SEPARATOR = /^-{5,}$/;
27720
27855
  var LIFTED_KEYS = new RegExp(`^(?:${TRAILER_KEY}|${COAUTHOR_KEY}):`, "i");
27721
27856
  function parseTrailers(message, cwd) {
27722
27857
  try {
27723
- 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"], {
27724
27859
  windowsHide: true,
27725
27860
  cwd,
27726
27861
  input: message,
@@ -29521,9 +29656,9 @@ ${SSH_RECIPE_AGENT_NOTE}`);
29521
29656
 
29522
29657
  // src/schedules-commands.ts
29523
29658
  var import_promises5 = require("node:fs/promises");
29524
- var import_node_child_process16 = require("node:child_process");
29659
+ var import_node_child_process17 = require("node:child_process");
29525
29660
  var import_node_util7 = require("node:util");
29526
- 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);
29527
29662
  var AWS_REGION = "eu-central-1";
29528
29663
  var AWS_TIMEOUT_MS = 3e4;
29529
29664
  var AWS_RETRY_DELAY_MS = 1500;
@@ -32402,7 +32537,7 @@ var import_node_fs38 = require("node:fs");
32402
32537
  var import_promises8 = require("node:fs/promises");
32403
32538
  var import_node_path36 = require("node:path");
32404
32539
  var import_node_os15 = require("node:os");
32405
- var import_node_child_process17 = require("node:child_process");
32540
+ var import_node_child_process18 = require("node:child_process");
32406
32541
 
32407
32542
  // src/board-advance.ts
32408
32543
  function repoOf2(ref) {
@@ -33008,7 +33143,7 @@ async function remoteBranchExists2(branch, options = {}) {
33008
33143
  }
33009
33144
  var COMPOSE_TIMEOUT_MS = 12e4;
33010
33145
  function spawnDeferredGcSweep() {
33011
- 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] });
33012
33147
  }
33013
33148
  async function createDeferredWorktreeStore() {
33014
33149
  try {
@@ -36688,7 +36823,8 @@ var RESTART_LINE = "\u21BB Restart Claude to finish.";
36688
36823
  var VERBOSE_INDENT = " ";
36689
36824
  function checkGlyph(check) {
36690
36825
  if (!check.ok) return "\u2717";
36691
- return check.verified === false ? "?" : "\u2713";
36826
+ if (check.verified === false) return "?";
36827
+ return check.warn ? "\u26A0" : "\u2713";
36692
36828
  }
36693
36829
  function renderCheckLine(check) {
36694
36830
  const head = check.detail ? `${checkGlyph(check)} ${check.label} \u2014 ${check.detail}` : `${checkGlyph(check)} ${check.label}`;
@@ -36706,9 +36842,11 @@ function renderTally(checks) {
36706
36842
  const total = checks.length;
36707
36843
  const failed = checks.filter((c) => !c.ok).length;
36708
36844
  const unverified = checks.filter((c) => c.ok && c.verified === false).length;
36709
- const healthy = total - failed - unverified;
36710
- 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`;
36711
36848
  const parts = [`\u2713 ${healthy} verified healthy`];
36849
+ if (warned > 0) parts.push(`\u26A0 ${warned} warn`);
36712
36850
  if (unverified > 0) parts.push(`? ${unverified} unverified`);
36713
36851
  if (failed > 0) parts.push(`\u2717 ${failed} failed`);
36714
36852
  return `${parts.join(" \xB7 ")} \u2014 ${total} checks`;
@@ -38358,18 +38496,19 @@ async function runDoctorClean(opts, io, deps) {
38358
38496
  if (payload) emitNow(payload);
38359
38497
  }
38360
38498
  async function runMarketplaceRows() {
38499
+ let healed;
38361
38500
  if (applyEnv) {
38362
- const healed = deps.healMarketplacePins();
38363
- if (healed) {
38501
+ healed = deps.healMarketplacePins();
38502
+ if (healed?.wrote) {
38364
38503
  healIntent(`marketplace pins \u2014 ${healed.detail}`);
38365
- if (healed.wrote) {
38366
- traceHeal("env-heals");
38367
- markHealChanged();
38368
- restartPending = true;
38369
- }
38504
+ traceHeal("env-heals");
38505
+ markHealChanged();
38506
+ restartPending = true;
38370
38507
  }
38371
38508
  }
38372
- 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
+ }
38373
38512
  }
38374
38513
  async function runTrainSyncRow() {
38375
38514
  try {
@@ -38902,9 +39041,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
38902
39041
  var import_node_fs45 = require("node:fs");
38903
39042
  var import_node_os18 = require("node:os");
38904
39043
  var import_node_path42 = require("node:path");
38905
- var import_node_child_process18 = require("node:child_process");
39044
+ var import_node_child_process19 = require("node:child_process");
38906
39045
  var import_node_util8 = require("node:util");
38907
- 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);
38908
39047
  var MMI_PLUGIN_ID2 = "mmi@mutmutco";
38909
39048
  function installedClaudePluginVersion() {
38910
39049
  try {
@@ -38950,12 +39089,12 @@ function installedSurfacePluginVersion(surface) {
38950
39089
  if (token === "claude") return installedClaudePluginVersion();
38951
39090
  if (token !== "codex") return void 0;
38952
39091
  try {
38953
- 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"], {
38954
39093
  encoding: "utf8",
38955
39094
  stdio: ["ignore", "pipe", "ignore"],
38956
39095
  timeout: 15e3,
38957
39096
  windowsHide: true
38958
- }) : (0, import_node_child_process18.execFileSync)("codex", ["plugin", "list", "--json"], {
39097
+ }) : (0, import_node_child_process19.execFileSync)("codex", ["plugin", "list", "--json"], {
38959
39098
  encoding: "utf8",
38960
39099
  stdio: ["ignore", "pipe", "ignore"],
38961
39100
  timeout: 15e3,
@@ -38973,7 +39112,7 @@ function installedActivePluginVersion(surface = detectSurface(process.env)) {
38973
39112
  }
38974
39113
  function worktreeRootSync() {
38975
39114
  try {
38976
- 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"] });
38977
39116
  let root = out.endsWith("\n") ? out.slice(0, -1) : out;
38978
39117
  if (process.platform === "win32" && root.endsWith("\r")) root = root.slice(0, -1);
38979
39118
  return root || null;
@@ -39226,7 +39365,7 @@ function mmiDoctorDeps(opts = {}) {
39226
39365
  sessionPayload: () => readSessionPayload(process.cwd()),
39227
39366
  // #3485 items 9 and 8: why the MMI plugin has never printed an "updated ? please restart" notice, and
39228
39367
  // which branch it would pick one up from. Two local file reads, no network, fail-soft to no rows.
39229
- marketplaceRows: () => {
39368
+ marketplaceRows: (hostBlocked) => {
39230
39369
  try {
39231
39370
  if (detectSurface(process.env) === "codex") return [];
39232
39371
  const home = (0, import_node_os19.homedir)();
@@ -39235,8 +39374,14 @@ function mmiDoctorDeps(opts = {}) {
39235
39374
  readFileSyncSafe((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
39236
39375
  readFileSyncSafe((0, import_node_path43.join)(home, ".claude", "settings.json"), import_node_fs46.readFileSync),
39237
39376
  // #3974: this CLI heals these rows, so report mode names the doctor run rather than the hand
39238
- // edit. Unconditional ? it is a fact about mmi-cli, not about the lane this run is on.
39239
- 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"
39240
39385
  );
39241
39386
  const pending = readMarketplacePinPending(
39242
39387
  (0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
@@ -39250,7 +39395,7 @@ function mmiDoctorDeps(opts = {}) {
39250
39395
  ...rest,
39251
39396
  ok: true,
39252
39397
  warn: true,
39253
- 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`,
39254
39399
  verbose: [...row.verbose ?? [], "known_marketplaces.json was rewritten by the running Claude host after the verified doctor write"]
39255
39400
  };
39256
39401
  });
@@ -39863,11 +40008,11 @@ function runWorktreeInstall(command, cwd, quiet, opts) {
39863
40008
  "pipe"
39864
40009
  ];
39865
40010
  return new Promise((resolve5, reject) => {
39866
- 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 }) : (() => {
39867
40012
  const [bin, ...args] = command.split(" ");
39868
40013
  const file = isWin2 ? "cmd.exe" : bin;
39869
40014
  const spawnArgs = isWin2 ? ["/c", bin, ...args] : args;
39870
- 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 });
39871
40016
  })();
39872
40017
  let stderrTail = "";
39873
40018
  child2.stderr?.on("data", (chunk) => {
@@ -40250,7 +40395,7 @@ function scheduleRelatedDiscovery(o) {
40250
40395
  try {
40251
40396
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
40252
40397
  if (o.repo) args.push("--repo", o.repo);
40253
- 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() });
40254
40399
  } catch {
40255
40400
  }
40256
40401
  }
@@ -42848,11 +42993,11 @@ program2.command("session-start").description("run the SessionStart verbs (whoam
42848
42993
  for (const line of scratchGcLines(process.cwd())) bannerIo.log(line);
42849
42994
  const worktreeBanner = worktreeAutoProvisionBanner(process.cwd());
42850
42995
  if (worktreeBanner) {
42851
- 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] });
42852
42997
  bannerIo.log(worktreeBanner);
42853
42998
  }
42854
42999
  if (shouldSpawnReleaseCatchup((0, import_node_os19.homedir)(), process.env, readReleaseCatchupState)) {
42855
- 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] });
42856
43001
  }
42857
43002
  if (isLinkedWorktree(process.cwd())) {
42858
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.112.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",