@mutmutco/cli 3.40.0 → 3.42.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 +369 -136
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -3410,8 +3410,8 @@ var program = new Command();
3410
3410
 
3411
3411
  // src/index.ts
3412
3412
  var import_promises7 = require("node:fs/promises");
3413
- var import_node_fs28 = require("node:fs");
3414
- var import_node_child_process12 = require("node:child_process");
3413
+ var import_node_fs29 = require("node:fs");
3414
+ var import_node_child_process13 = require("node:child_process");
3415
3415
 
3416
3416
  // src/cli-shared.ts
3417
3417
  var import_node_child_process3 = require("node:child_process");
@@ -8949,7 +8949,7 @@ function commandLadderHint() {
8949
8949
  }
8950
8950
 
8951
8951
  // src/index.ts
8952
- var import_node_path25 = require("node:path");
8952
+ var import_node_path26 = require("node:path");
8953
8953
 
8954
8954
  // src/merge-ci-policy.ts
8955
8955
  function resolveMergeCiPolicy(input) {
@@ -15375,6 +15375,213 @@ function createDocsIndexDeps(repoRoot2) {
15375
15375
  };
15376
15376
  }
15377
15377
 
15378
+ // src/doc-refs-core.ts
15379
+ var import_node_child_process9 = require("node:child_process");
15380
+ var import_node_fs18 = require("node:fs");
15381
+ var import_node_path16 = require("node:path");
15382
+ var PIN_RE = /<!--\s*pinned by\s+([^:]+?)\s*:\s*"([^"]+)"[^"]*-->/;
15383
+ var PIN_MENTION_RE = /<!--\s*pinned by\b/;
15384
+ var REF_RE = /`([A-Za-z0-9_./-]+\.[A-Za-z0-9]+)(?::\d+)?`/g;
15385
+ var LINK_RE = /\]\(([^)#\s]+?\.md)(?:#[^)]*)?\)/g;
15386
+ var CMD_RE = /`mmi-cli ((?:[a-z][a-z-]*)(?: [a-z][a-z-]*){0,3})/g;
15387
+ var RETIRED_RE = /\b(retired|historical|removed|deleted|gone|no longer|superseded|legacy)\b/i;
15388
+ var ROOT_DOCS = ["README.md", "architecture.md"];
15389
+ var SKIP_WALK = ["docs/Archive/", "docs/incidents/"];
15390
+ var PINNED_DOCS = ["docs/Reference/runtime-contracts.md"];
15391
+ function stripFences(markdown) {
15392
+ let inFence = false;
15393
+ return markdown.split(/\r?\n/).map((line) => {
15394
+ if (/^\s*```/.test(line)) {
15395
+ inFence = !inFence;
15396
+ return "";
15397
+ }
15398
+ return inFence ? "" : line;
15399
+ });
15400
+ }
15401
+ function isRetiredLine(text) {
15402
+ return RETIRED_RE.test(text);
15403
+ }
15404
+ function extractPins(markdown) {
15405
+ const pins = [];
15406
+ markdown.split(/\r?\n/).forEach((text, index) => {
15407
+ const match = PIN_RE.exec(text);
15408
+ if (match) {
15409
+ pins.push({ file: match[1].trim(), phrase: match[2], line: index + 1 });
15410
+ } else if (PIN_MENTION_RE.test(text.replace(/`[^`]*`/g, ""))) {
15411
+ pins.push({ malformed: true, line: index + 1, text: text.trim() });
15412
+ }
15413
+ });
15414
+ return pins;
15415
+ }
15416
+ function checkPins(root, readFile6) {
15417
+ const findings = [];
15418
+ for (const doc of PINNED_DOCS) {
15419
+ const markdown = readFile6((0, import_node_path16.join)(root, doc));
15420
+ if (markdown == null) {
15421
+ findings.push({ kind: "missing-doc", doc, line: 0, detail: doc });
15422
+ continue;
15423
+ }
15424
+ for (const pin of extractPins(markdown)) {
15425
+ if ("malformed" in pin) {
15426
+ findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
15427
+ continue;
15428
+ }
15429
+ const source = readFile6((0, import_node_path16.join)(root, pin.file));
15430
+ if (source == null) {
15431
+ findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
15432
+ continue;
15433
+ }
15434
+ if (!source.includes(pin.phrase)) {
15435
+ findings.push({ kind: "unasserted-phrase", doc, line: pin.line, detail: pin.phrase });
15436
+ }
15437
+ }
15438
+ }
15439
+ return { ok: findings.length === 0, findings };
15440
+ }
15441
+ function isDomainLike(ref) {
15442
+ const first = ref.split("/")[0];
15443
+ return first.includes(".") && !first.startsWith(".");
15444
+ }
15445
+ function extractRefs(markdown) {
15446
+ const lines = stripFences(markdown);
15447
+ const refs = [];
15448
+ lines.forEach((text, index) => {
15449
+ if (isRetiredLine(text)) return;
15450
+ for (const match of text.matchAll(REF_RE)) {
15451
+ const ref = match[1];
15452
+ if (!ref.includes("/")) continue;
15453
+ if (ref.startsWith("/") || ref.startsWith(".git/")) continue;
15454
+ if (isDomainLike(ref)) continue;
15455
+ refs.push({ ref, line: index + 1 });
15456
+ }
15457
+ });
15458
+ return refs;
15459
+ }
15460
+ function extractLinks(markdown) {
15461
+ const lines = stripFences(markdown);
15462
+ const links = [];
15463
+ lines.forEach((text, index) => {
15464
+ if (isRetiredLine(text)) return;
15465
+ for (const match of text.matchAll(LINK_RE)) {
15466
+ const target = match[1];
15467
+ if (/^[a-z]+:/i.test(target)) continue;
15468
+ links.push({ target, line: index + 1 });
15469
+ }
15470
+ });
15471
+ return links;
15472
+ }
15473
+ function extractCommands(markdown) {
15474
+ const lines = stripFences(markdown);
15475
+ const commands = [];
15476
+ lines.forEach((text, index) => {
15477
+ if (isRetiredLine(text)) return;
15478
+ for (const match of text.matchAll(CMD_RE)) {
15479
+ commands.push({ command: match[1], line: index + 1 });
15480
+ }
15481
+ });
15482
+ return commands;
15483
+ }
15484
+ function checkRefs(root, deps, docs2) {
15485
+ const { exists, isIgnored = () => /* @__PURE__ */ new Set() } = deps;
15486
+ const candidates = [];
15487
+ for (const [doc, markdown] of Object.entries(docs2)) {
15488
+ for (const { ref, line } of extractRefs(markdown)) {
15489
+ const first = ref.split("/")[0];
15490
+ if (!exists((0, import_node_path16.join)(root, first))) continue;
15491
+ if (!exists((0, import_node_path16.join)(root, ref))) candidates.push({ kind: "missing-path", doc, line, detail: ref });
15492
+ }
15493
+ const docDir = import_node_path16.posix.dirname(doc);
15494
+ for (const { target, line } of extractLinks(markdown)) {
15495
+ const resolved = import_node_path16.posix.normalize(import_node_path16.posix.join(docDir === "." ? "" : docDir, target));
15496
+ if (!exists((0, import_node_path16.join)(root, resolved))) {
15497
+ candidates.push({ kind: "missing-link", doc, line, detail: target, resolved });
15498
+ }
15499
+ }
15500
+ }
15501
+ const ignored = candidates.length ? isIgnored(candidates.map((c) => c.kind === "missing-link" ? c.resolved : c.detail)) : /* @__PURE__ */ new Set();
15502
+ const findings = candidates.filter((c) => !ignored.has(c.kind === "missing-link" ? c.resolved : c.detail)).map(({ resolved, ...finding }) => finding);
15503
+ return { ok: findings.length === 0, findings };
15504
+ }
15505
+ function checkCommands(docs2, commandPaths) {
15506
+ const findings = [];
15507
+ const prefixesSome = (prefix) => {
15508
+ for (const path2 of commandPaths) {
15509
+ if (path2 === prefix || path2.startsWith(`${prefix} `)) return true;
15510
+ }
15511
+ return false;
15512
+ };
15513
+ for (const [doc, markdown] of Object.entries(docs2)) {
15514
+ for (const { command, line } of extractCommands(markdown)) {
15515
+ const tokens2 = command.split(" ");
15516
+ for (let i = 1; i <= tokens2.length; i += 1) {
15517
+ const prefix = tokens2.slice(0, i).join(" ");
15518
+ if (prefixesSome(prefix)) continue;
15519
+ const parent = tokens2.slice(0, i - 1).join(" ");
15520
+ if (i > 1 && commandPaths.has(parent)) break;
15521
+ findings.push({ kind: "unknown-command", doc, line, detail: `mmi-cli ${prefix}` });
15522
+ break;
15523
+ }
15524
+ }
15525
+ }
15526
+ return { ok: findings.length === 0, findings };
15527
+ }
15528
+ function readFileOrNull(path2) {
15529
+ return (0, import_node_fs18.existsSync)(path2) ? (0, import_node_fs18.readFileSync)(path2, "utf8") : null;
15530
+ }
15531
+ function walk(dir, root, out) {
15532
+ for (const entry of (0, import_node_fs18.readdirSync)(dir)) {
15533
+ const full = (0, import_node_path16.join)(dir, entry);
15534
+ if ((0, import_node_fs18.statSync)(full).isDirectory()) walk(full, root, out);
15535
+ else if (entry.endsWith(".md")) out.push(full.slice(root.length + 1).replaceAll("\\", "/"));
15536
+ }
15537
+ return out;
15538
+ }
15539
+ function defaultListDocs(root) {
15540
+ const docsDir = (0, import_node_path16.join)(root, "docs");
15541
+ const docs2 = ((0, import_node_fs18.existsSync)(docsDir) ? walk(docsDir, root, []) : []).filter(
15542
+ (rel) => !SKIP_WALK.some((skip) => rel.startsWith(skip))
15543
+ );
15544
+ return [...ROOT_DOCS.filter((rel) => (0, import_node_fs18.existsSync)((0, import_node_path16.join)(root, rel))), ...docs2];
15545
+ }
15546
+ function defaultIsIgnored(root, relPaths, exec = import_node_child_process9.execFileSync) {
15547
+ try {
15548
+ const out = exec("git", ["check-ignore", "--stdin"], {
15549
+ cwd: root,
15550
+ input: relPaths.join("\n"),
15551
+ encoding: "utf8"
15552
+ });
15553
+ return new Set(out.split(/\r?\n/).filter(Boolean));
15554
+ } catch (error) {
15555
+ if (error?.status === 1) return /* @__PURE__ */ new Set();
15556
+ throw error;
15557
+ }
15558
+ }
15559
+ function runDocRefs(root, deps = {}) {
15560
+ const readFile6 = deps.readFile ?? readFileOrNull;
15561
+ const exists = deps.exists ?? import_node_fs18.existsSync;
15562
+ const listDocs = deps.listDocs ?? defaultListDocs;
15563
+ const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
15564
+ const commandPaths = deps.commandPaths ?? null;
15565
+ const docs2 = Object.fromEntries(
15566
+ listDocs(root).map((rel) => [rel, readFile6((0, import_node_path16.join)(root, rel))]).filter(([, body]) => body != null)
15567
+ );
15568
+ const findings = [
15569
+ ...checkPins(root, readFile6).findings,
15570
+ ...checkRefs(root, { exists, isIgnored }, docs2).findings
15571
+ ];
15572
+ if (commandPaths == null) {
15573
+ findings.push({
15574
+ kind: "command-manifest-unavailable",
15575
+ doc: "cli command manifest",
15576
+ line: 0,
15577
+ detail: "the CLI could not enumerate its own commands \u2014 command refs cannot be verified"
15578
+ });
15579
+ } else {
15580
+ findings.push(...checkCommands(docs2, commandPaths).findings);
15581
+ }
15582
+ return { ok: findings.length === 0, findings, docCount: Object.keys(docs2).length };
15583
+ }
15584
+
15378
15585
  // src/docs-audit-command.ts
15379
15586
  function serializeOutcome(outcome) {
15380
15587
  switch (outcome.kind) {
@@ -16298,8 +16505,8 @@ function writeError(res) {
16298
16505
  }
16299
16506
 
16300
16507
  // src/secrets-commands.ts
16301
- var import_node_fs18 = require("node:fs");
16302
- var import_node_path16 = require("node:path");
16508
+ var import_node_fs19 = require("node:fs");
16509
+ var import_node_path17 = require("node:path");
16303
16510
  var import_node_os5 = require("node:os");
16304
16511
 
16305
16512
  // src/project-runtime.ts
@@ -16423,18 +16630,18 @@ function collectMap(value, previous = []) {
16423
16630
  return [...previous, value];
16424
16631
  }
16425
16632
  async function decryptRailsCredentials(input) {
16426
- const appDir = (0, import_node_path16.resolve)(input.appDir ?? process.cwd());
16633
+ const appDir = (0, import_node_path17.resolve)(input.appDir ?? process.cwd());
16427
16634
  const credentialsFile = input.credentialsFile ?? DEFAULT_RAILS_CREDENTIALS_FILE;
16428
16635
  const masterKeyFile = input.masterKeyFile ?? DEFAULT_RAILS_MASTER_KEY_FILE;
16429
- const credentialsPath = (0, import_node_path16.resolve)(appDir, credentialsFile);
16430
- const masterKeyPath = (0, import_node_path16.resolve)(appDir, masterKeyFile);
16636
+ const credentialsPath = (0, import_node_path17.resolve)(appDir, credentialsFile);
16637
+ const masterKeyPath = (0, import_node_path17.resolve)(appDir, masterKeyFile);
16431
16638
  const env = {
16432
16639
  ...process.env,
16433
16640
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
16434
16641
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
16435
16642
  };
16436
- if ((0, import_node_fs18.existsSync)(masterKeyPath)) {
16437
- env.RAILS_MASTER_KEY = (0, import_node_fs18.readFileSync)(masterKeyPath, "utf8").trim();
16643
+ if ((0, import_node_fs19.existsSync)(masterKeyPath)) {
16644
+ env.RAILS_MASTER_KEY = (0, import_node_fs19.readFileSync)(masterKeyPath, "utf8").trim();
16438
16645
  }
16439
16646
  const script = [
16440
16647
  'require "json"',
@@ -16444,9 +16651,9 @@ async function decryptRailsCredentials(input) {
16444
16651
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
16445
16652
  "puts JSON.generate(config.config)"
16446
16653
  ].join("\n");
16447
- const scriptDir = (0, import_node_fs18.mkdtempSync)((0, import_node_path16.join)((0, import_node_os5.tmpdir)(), "mmi-rails-decrypt-"));
16448
- const scriptPath = (0, import_node_path16.join)(scriptDir, "decrypt.rb");
16449
- (0, import_node_fs18.writeFileSync)(scriptPath, script, "utf8");
16654
+ const scriptDir = (0, import_node_fs19.mkdtempSync)((0, import_node_path17.join)((0, import_node_os5.tmpdir)(), "mmi-rails-decrypt-"));
16655
+ const scriptPath = (0, import_node_path17.join)(scriptDir, "decrypt.rb");
16656
+ (0, import_node_fs19.writeFileSync)(scriptPath, script, "utf8");
16450
16657
  try {
16451
16658
  const args = ["exec", "ruby", scriptPath];
16452
16659
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -16458,7 +16665,7 @@ async function decryptRailsCredentials(input) {
16458
16665
  });
16459
16666
  return JSON.parse(stdout);
16460
16667
  } finally {
16461
- (0, import_node_fs18.rmSync)(scriptDir, { recursive: true, force: true });
16668
+ (0, import_node_fs19.rmSync)(scriptDir, { recursive: true, force: true });
16462
16669
  }
16463
16670
  }
16464
16671
  async function readSecretStdin() {
@@ -16548,7 +16755,7 @@ function registerSecretsCommands(program3) {
16548
16755
  let body;
16549
16756
  if (o.file) {
16550
16757
  try {
16551
- body = (0, import_node_fs18.readFileSync)((0, import_node_path16.resolve)(o.file), "utf8");
16758
+ body = (0, import_node_fs19.readFileSync)((0, import_node_path17.resolve)(o.file), "utf8");
16552
16759
  } catch (e) {
16553
16760
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
16554
16761
  }
@@ -16653,7 +16860,7 @@ function registerSecretsCommands(program3) {
16653
16860
  {
16654
16861
  ...d,
16655
16862
  decryptRailsCredentials,
16656
- removeFile: (path2) => (0, import_node_fs18.unlinkSync)((0, import_node_path16.resolve)(o.appDir ?? process.cwd(), path2))
16863
+ removeFile: (path2) => (0, import_node_fs19.unlinkSync)((0, import_node_path17.resolve)(o.appDir ?? process.cwd(), path2))
16657
16864
  },
16658
16865
  {
16659
16866
  repo: o.repo,
@@ -17028,7 +17235,7 @@ function registerBoxCommands(program3) {
17028
17235
 
17029
17236
  // src/schedules-commands.ts
17030
17237
  var import_promises2 = require("node:fs/promises");
17031
- var import_node_child_process9 = require("node:child_process");
17238
+ var import_node_child_process10 = require("node:child_process");
17032
17239
  var import_node_util7 = require("node:util");
17033
17240
 
17034
17241
  // src/schedules.ts
@@ -17334,7 +17541,7 @@ function assembleReconciliation(githubEntries2, readRepos, registry2, activeWork
17334
17541
  }
17335
17542
 
17336
17543
  // src/schedules-commands.ts
17337
- var execFileP5 = (0, import_node_util7.promisify)(import_node_child_process9.execFile);
17544
+ var execFileP5 = (0, import_node_util7.promisify)(import_node_child_process10.execFile);
17338
17545
  var AWS_REGION = "eu-central-1";
17339
17546
  var AWS_TIMEOUT_MS = 3e4;
17340
17547
  var AWS_RETRY_DELAY_MS = 1500;
@@ -17570,14 +17777,14 @@ function registerSchedulesCommands(program3) {
17570
17777
 
17571
17778
  // src/schedules-lift-command.ts
17572
17779
  var import_promises3 = require("node:fs/promises");
17573
- var import_node_path17 = require("node:path");
17780
+ var import_node_path18 = require("node:path");
17574
17781
 
17575
17782
  // src/schedules-lift.ts
17576
17783
  var SCHEDULE_HEADER_FIELDS = ["schedule", "what", "owner", "cadence", "executor", "llm", "output", "breaks", "kill"];
17577
17784
  function parseScheduleHeader(yamlText) {
17578
17785
  const out = {};
17579
17786
  for (const rawLine of yamlText.split("\n")) {
17580
- const m = /^#\s*(schedule|what|owner|cadence|executor|llm|output|breaks|kill|target):\s*(.+?)\s*$/.exec(rawLine);
17787
+ const m = /^#\s*(schedule|what|owner|cadence|executor|llm|output|breaks|kill|target|model):\s*(.+?)\s*$/.exec(rawLine);
17581
17788
  if (m && out[m[1]] === void 0) out[m[1]] = m[2].trim();
17582
17789
  }
17583
17790
  return out;
@@ -17614,6 +17821,10 @@ function scheduleRecordFromWorkflow(repo, workflowPath, yamlText) {
17614
17821
  if (target !== void 0 && !/^mmi-fleet-[A-Za-z0-9_-]{1,130}$/.test(target)) {
17615
17822
  throw new Error(`schedules lift: ${expectedId} header \`target: ${target}\` must be a bare lambda function name in the reserved fleet namespace \`mmi-fleet-*\` (allowed after the prefix: A-Z a-z 0-9 _ -; total max 140). The dispatcher can only invoke mmi-fleet-* functions.`);
17616
17823
  }
17824
+ const model = header.model;
17825
+ if (model !== void 0 && !/^[a-z][a-z0-9-]{0,30}$/.test(model)) {
17826
+ throw new Error(`schedules lift: ${expectedId} header \`model: ${model}\` must be a model ROLE KEY (lowercase kebab, max 31 chars \u2014 e.g. janitor, arbiter), never a model id \u2014 ids resolve from the vault at dispatch.`);
17827
+ }
17617
17828
  return {
17618
17829
  id: expectedId,
17619
17830
  what: h.what,
@@ -17626,7 +17837,8 @@ function scheduleRecordFromWorkflow(repo, workflowPath, yamlText) {
17626
17837
  kill: h.kill,
17627
17838
  repo,
17628
17839
  sourcePath: workflowPath,
17629
- ...target !== void 0 ? { target } : {}
17840
+ ...target !== void 0 ? { target } : {},
17841
+ ...model !== void 0 ? { model } : {}
17630
17842
  };
17631
17843
  }
17632
17844
  function scheduleRecordsFromWorkflows(repo, files) {
@@ -17671,7 +17883,7 @@ async function readWorkflowFiles(dir) {
17671
17883
  const files = [];
17672
17884
  for (const name of names.sort()) {
17673
17885
  if (!/\.ya?ml$/.test(name)) continue;
17674
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises3.readFile)((0, import_node_path17.join)(dir, name), "utf8") });
17886
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises3.readFile)((0, import_node_path18.join)(dir, name), "utf8") });
17675
17887
  }
17676
17888
  return files;
17677
17889
  }
@@ -18211,7 +18423,7 @@ function registerQueryCommands(program3) {
18211
18423
  }
18212
18424
 
18213
18425
  // src/bootstrap-commands.ts
18214
- var import_node_fs19 = require("node:fs");
18426
+ var import_node_fs20 = require("node:fs");
18215
18427
 
18216
18428
  // src/bootstrap-verify.ts
18217
18429
  var TRAIN_BRANCHES2 = ["development", "rc", "main"];
@@ -18759,7 +18971,7 @@ function registerBootstrapCommands(program3) {
18759
18971
  client: defaultGitHubClient(),
18760
18972
  projectMeta: meta,
18761
18973
  deployModel: typeof meta?.deployModel === "string" ? meta.deployModel : void 0,
18762
- readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs19.existsSync)(path2) ? (0, import_node_fs19.readFileSync)(path2, "utf8") : null,
18974
+ readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs20.existsSync)(path2) ? (0, import_node_fs20.readFileSync)(path2, "utf8") : null,
18763
18975
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
18764
18976
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
18765
18977
  requiredGcpApis: (() => {
@@ -18810,12 +19022,12 @@ function registerBootstrapCommands(program3) {
18810
19022
  return fail(`bootstrap apply: ${e.message}`);
18811
19023
  }
18812
19024
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
18813
- if (!(0, import_node_fs19.existsSync)(manifestPath)) return fail(`bootstrap apply: ${manifestPath} not found; bootstrap runs from the MMI-Hub repo root by design \u2014 it stamps org-level resources (Project, Ruleset, secrets, access) through the GitHub App, which is only authorized from the Hub checkout`);
18814
- const manifest = loadBootstrapSeeds((0, import_node_fs19.readFileSync)(manifestPath, "utf8"));
19025
+ if (!(0, import_node_fs20.existsSync)(manifestPath)) return fail(`bootstrap apply: ${manifestPath} not found; bootstrap runs from the MMI-Hub repo root by design \u2014 it stamps org-level resources (Project, Ruleset, secrets, access) through the GitHub App, which is only authorized from the Hub checkout`);
19026
+ const manifest = loadBootstrapSeeds((0, import_node_fs20.readFileSync)(manifestPath, "utf8"));
18815
19027
  const baseBranch = o.class === "content" ? "main" : "development";
18816
19028
  const slug = parsedRepo.slug;
18817
19029
  const gh = async (args) => execFileP2("gh", args, { timeout: 2e4 });
18818
- const readFile6 = (p) => (0, import_node_fs19.existsSync)(p) ? (0, import_node_fs19.readFileSync)(p, "utf8") : null;
19030
+ const readFile6 = (p) => (0, import_node_fs20.existsSync)(p) ? (0, import_node_fs20.readFileSync)(p, "utf8") : null;
18819
19031
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
18820
19032
  const rawVars = {};
18821
19033
  for (const value of cmdOpts.var ?? []) {
@@ -19011,12 +19223,12 @@ LIVE apply to ${repo}:
19011
19223
  }
19012
19224
 
19013
19225
  // src/stage-commands.ts
19014
- var import_node_fs21 = require("node:fs");
19015
- var import_node_path19 = require("node:path");
19226
+ var import_node_fs22 = require("node:fs");
19227
+ var import_node_path20 = require("node:path");
19016
19228
 
19017
19229
  // src/port-registry.ts
19018
- var import_node_fs20 = require("node:fs");
19019
- var import_node_path18 = require("node:path");
19230
+ var import_node_fs21 = require("node:fs");
19231
+ var import_node_path19 = require("node:path");
19020
19232
 
19021
19233
  // ../infra/port-geometry.mjs
19022
19234
  var PORT_BLOCK = 100;
@@ -19030,8 +19242,8 @@ function nextPortBlock(registry2) {
19030
19242
  return [base, base + PORT_SPAN];
19031
19243
  }
19032
19244
  function loadPortRegistry(path2) {
19033
- if (!(0, import_node_fs20.existsSync)(path2)) return {};
19034
- const raw = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
19245
+ if (!(0, import_node_fs21.existsSync)(path2)) return {};
19246
+ const raw = JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
19035
19247
  const out = {};
19036
19248
  for (const [key, value] of Object.entries(raw)) {
19037
19249
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -19045,9 +19257,9 @@ function ensurePortRange(repo, path2) {
19045
19257
  const existing = registry2[repo];
19046
19258
  if (existing) return existing;
19047
19259
  const range = nextPortBlock(registry2);
19048
- const raw = (0, import_node_fs20.existsSync)(path2) ? JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8")) : {};
19260
+ const raw = (0, import_node_fs21.existsSync)(path2) ? JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8")) : {};
19049
19261
  raw[repo] = range;
19050
- (0, import_node_fs20.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
19262
+ (0, import_node_fs21.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
19051
19263
  return range;
19052
19264
  }
19053
19265
  function portCursorSeed(registry2) {
@@ -19069,22 +19281,22 @@ function existingPortRange(repo, registry2) {
19069
19281
  return registry2[repo] ?? null;
19070
19282
  }
19071
19283
  function portRangeInfraAt(root, source) {
19072
- const registryPath = (0, import_node_path18.join)(root, "infra", "port-ranges.json");
19073
- const ddbScriptPath = (0, import_node_path18.join)(root, "infra", "port-ddb.mjs");
19074
- if (!(0, import_node_fs20.existsSync)(registryPath) || !(0, import_node_fs20.existsSync)(ddbScriptPath)) return null;
19284
+ const registryPath = (0, import_node_path19.join)(root, "infra", "port-ranges.json");
19285
+ const ddbScriptPath = (0, import_node_path19.join)(root, "infra", "port-ddb.mjs");
19286
+ if (!(0, import_node_fs21.existsSync)(registryPath) || !(0, import_node_fs21.existsSync)(ddbScriptPath)) return null;
19075
19287
  return { root, source, registryPath, ddbScriptPath };
19076
19288
  }
19077
19289
  function resolvePortRangeInfra(cwd, packageDir) {
19078
19290
  const direct = portRangeInfraAt(cwd, "cwd");
19079
19291
  if (direct) return direct;
19080
- for (let dir = cwd; ; dir = (0, import_node_path18.dirname)(dir)) {
19081
- const sibling = portRangeInfraAt((0, import_node_path18.join)(dir, "MMI-Hub"), "sibling-hub");
19292
+ for (let dir = cwd; ; dir = (0, import_node_path19.dirname)(dir)) {
19293
+ const sibling = portRangeInfraAt((0, import_node_path19.join)(dir, "MMI-Hub"), "sibling-hub");
19082
19294
  if (sibling) return sibling;
19083
- const parent = (0, import_node_path18.dirname)(dir);
19295
+ const parent = (0, import_node_path19.dirname)(dir);
19084
19296
  if (parent === dir) break;
19085
19297
  }
19086
19298
  if (packageDir) {
19087
- const pkgRoot = (0, import_node_path18.join)(packageDir, "..", "..");
19299
+ const pkgRoot = (0, import_node_path19.join)(packageDir, "..", "..");
19088
19300
  const pkgFrom = portRangeInfraAt(pkgRoot, "pkg-root");
19089
19301
  if (pkgFrom) return pkgFrom;
19090
19302
  }
@@ -19260,8 +19472,8 @@ function registerStageCommands(program3) {
19260
19472
  const portRange = portRangeMeta && typeof portRangeMeta.start === "number" && typeof portRangeMeta.end === "number" ? [portRangeMeta.start, portRangeMeta.end] : void 0;
19261
19473
  return decideStage({
19262
19474
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
19263
- hasCompose: (0, import_node_fs21.existsSync)((0, import_node_path19.join)(process.cwd(), "docker-compose.yml")),
19264
- hasEnvExample: (0, import_node_fs21.existsSync)((0, import_node_path19.join)(process.cwd(), ".env.example"))
19475
+ hasCompose: (0, import_node_fs22.existsSync)((0, import_node_path20.join)(process.cwd(), "docker-compose.yml")),
19476
+ hasEnvExample: (0, import_node_fs22.existsSync)((0, import_node_path20.join)(process.cwd(), ".env.example"))
19265
19477
  });
19266
19478
  }
19267
19479
  async function fetchStageVaultEnvMerge() {
@@ -19696,9 +19908,9 @@ function registerBoardCommands(program3) {
19696
19908
  }
19697
19909
 
19698
19910
  // src/merge-cleanup.ts
19699
- var import_node_fs22 = require("node:fs");
19911
+ var import_node_fs23 = require("node:fs");
19700
19912
  var import_promises5 = require("node:fs/promises");
19701
- var import_node_child_process10 = require("node:child_process");
19913
+ var import_node_child_process11 = require("node:child_process");
19702
19914
 
19703
19915
  // src/board-advance.ts
19704
19916
  function repoOf2(ref) {
@@ -19784,7 +19996,7 @@ function boardAdvanceFailureMessage(result) {
19784
19996
 
19785
19997
  // src/deferred-registry-store.ts
19786
19998
  var import_promises4 = require("node:fs/promises");
19787
- var import_node_path20 = require("node:path");
19999
+ var import_node_path21 = require("node:path");
19788
20000
  var sleep = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
19789
20001
  async function atomicWrite(target, contents) {
19790
20002
  const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
@@ -19888,12 +20100,12 @@ function makeDeferredWorktreeStore(registryPath, lockOpts = {}) {
19888
20100
  },
19889
20101
  // Standalone atomic write — THROWS on failure (no best-effort swallow, #2846).
19890
20102
  write: async (entries) => {
19891
- await (0, import_promises4.mkdir)((0, import_node_path20.dirname)(registryPath), { recursive: true });
20103
+ await (0, import_promises4.mkdir)((0, import_node_path21.dirname)(registryPath), { recursive: true });
19892
20104
  await atomicWrite(registryPath, serializeDeferredWorktrees(entries));
19893
20105
  },
19894
20106
  // Serialized read-modify-write under the repo-wide lock (#2846).
19895
20107
  update: async (mutate) => {
19896
- await (0, import_promises4.mkdir)((0, import_node_path20.dirname)(registryPath), { recursive: true });
20108
+ await (0, import_promises4.mkdir)((0, import_node_path21.dirname)(registryPath), { recursive: true });
19897
20109
  const deadline = Date.now() + opts.maxWaitMs;
19898
20110
  for (; ; ) {
19899
20111
  const guard = await acquireLock(lockPath, opts, deadline);
@@ -20020,7 +20232,7 @@ async function applyGcPlan(plan, remote) {
20020
20232
  return cleanupPrMergeLocalBranch(branch.branch, {
20021
20233
  beforeWorktrees,
20022
20234
  startingPath: branch.worktreePath,
20023
- pathExists: (p) => (0, import_node_fs22.existsSync)(p),
20235
+ pathExists: (p) => (0, import_node_fs23.existsSync)(p),
20024
20236
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
20025
20237
  teardownWorktreeStage,
20026
20238
  deferredStore,
@@ -20046,7 +20258,7 @@ async function applyGcPlan(plan, remote) {
20046
20258
  for (const wt of plan.worktreeDirs) {
20047
20259
  try {
20048
20260
  const cleanupTarget = resolveSafeSiblingWorktreeCleanupTarget(wt.path, siblingRoot, {
20049
- realpath: (path2) => (0, import_node_fs22.realpathSync)(path2)
20261
+ realpath: (path2) => (0, import_node_fs23.realpathSync)(path2)
20050
20262
  });
20051
20263
  if (!cleanupTarget.ok) {
20052
20264
  result.failed.push(`${wt.path}: ${cleanupTarget.reason}`);
@@ -20159,7 +20371,7 @@ async function remoteBranchExists2(branch, options = {}) {
20159
20371
  }
20160
20372
  var COMPOSE_TIMEOUT_MS = 12e4;
20161
20373
  function spawnDeferredGcSweep() {
20162
- spawnDetachedSelf(["worktree", "gc", "sweep-deferred", "--quiet"], { spawn: import_node_child_process10.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
20374
+ spawnDetachedSelf(["worktree", "gc", "sweep-deferred", "--quiet"], { spawn: import_node_child_process11.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
20163
20375
  }
20164
20376
  async function createDeferredWorktreeStore() {
20165
20377
  try {
@@ -20173,13 +20385,13 @@ var realWorktreeDirRemover = {
20173
20385
  probe: (p) => {
20174
20386
  let st;
20175
20387
  try {
20176
- st = (0, import_node_fs22.lstatSync)(p);
20388
+ st = (0, import_node_fs23.lstatSync)(p);
20177
20389
  } catch {
20178
20390
  return null;
20179
20391
  }
20180
20392
  if (st.isSymbolicLink()) return "link";
20181
20393
  try {
20182
- (0, import_node_fs22.readlinkSync)(p);
20394
+ (0, import_node_fs23.readlinkSync)(p);
20183
20395
  return "link";
20184
20396
  } catch {
20185
20397
  }
@@ -20187,7 +20399,7 @@ var realWorktreeDirRemover = {
20187
20399
  },
20188
20400
  readdir: (p) => {
20189
20401
  try {
20190
- return (0, import_node_fs22.readdirSync)(p);
20402
+ return (0, import_node_fs23.readdirSync)(p);
20191
20403
  } catch {
20192
20404
  return [];
20193
20405
  }
@@ -20196,9 +20408,9 @@ var realWorktreeDirRemover = {
20196
20408
  // leaving the target); a file symlink with unlink. rmdir first, fall back to unlink.
20197
20409
  detachLink: (p) => {
20198
20410
  try {
20199
- (0, import_node_fs22.rmdirSync)(p);
20411
+ (0, import_node_fs23.rmdirSync)(p);
20200
20412
  } catch {
20201
- (0, import_node_fs22.unlinkSync)(p);
20413
+ (0, import_node_fs23.unlinkSync)(p);
20202
20414
  }
20203
20415
  },
20204
20416
  removeTree: (p) => (0, import_promises5.rm)(p, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
@@ -20231,9 +20443,9 @@ async function worktreeHasStageState(worktreePath) {
20231
20443
  }
20232
20444
  }
20233
20445
  function stageStateFileBelongsToWorktree(statePath, worktreePath) {
20234
- if (!(0, import_node_fs22.existsSync)(statePath)) return false;
20446
+ if (!(0, import_node_fs23.existsSync)(statePath)) return false;
20235
20447
  try {
20236
- const state = JSON.parse((0, import_node_fs22.readFileSync)(statePath, "utf8"));
20448
+ const state = JSON.parse((0, import_node_fs23.readFileSync)(statePath, "utf8"));
20237
20449
  const recordedCwd = typeof state.identity?.cwd === "string" ? state.identity.cwd : typeof state.cwd === "string" ? state.cwd : "";
20238
20450
  return Boolean(recordedCwd && isPathUnderDirectory(recordedCwd, worktreePath));
20239
20451
  } catch {
@@ -20361,8 +20573,8 @@ async function fetchRestCorePool(gh = defaultGhApi) {
20361
20573
  }
20362
20574
 
20363
20575
  // src/worktree-lifecycle-commands.ts
20364
- var import_node_fs23 = require("node:fs");
20365
- var import_node_path21 = require("node:path");
20576
+ var import_node_fs24 = require("node:fs");
20577
+ var import_node_path22 = require("node:path");
20366
20578
  var GH_TIMEOUT_MS = 2e4;
20367
20579
  var DEFAULT_BASE = "origin/development";
20368
20580
  var DEFAULT_REMOTE = "origin";
@@ -20499,13 +20711,13 @@ function registerWorktreeCommands(program3) {
20499
20711
  if (PROTECTED_BRANCHES2.has(branch)) {
20500
20712
  return fail(`worktree land: refusing to land protected branch '${branch}'`, { code: ERROR_CODES.ERR_BAD_ENUM });
20501
20713
  }
20502
- const gitFile = (0, import_node_path21.join)(wtPath, ".git");
20503
- const isLinked = (0, import_node_fs23.existsSync)(gitFile) && (0, import_node_fs23.statSync)(gitFile).isFile();
20714
+ const gitFile = (0, import_node_path22.join)(wtPath, ".git");
20715
+ const isLinked = (0, import_node_fs24.existsSync)(gitFile) && (0, import_node_fs24.statSync)(gitFile).isFile();
20504
20716
  if (apply && !isLinked) {
20505
20717
  return fail("worktree land: run from inside the linked worktree you want to land (this is the primary checkout)");
20506
20718
  }
20507
20719
  const commonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
20508
- const primaryCheckout = commonDir ? (0, import_node_path21.dirname)(commonDir) : wtPath;
20720
+ const primaryCheckout = commonDir ? (0, import_node_path22.dirname)(commonDir) : wtPath;
20509
20721
  const stageSummary = readStageSummary(wtPath);
20510
20722
  const hasStage = stageSummary != null;
20511
20723
  const steps = landSteps(branch, true, hasStage);
@@ -20617,10 +20829,10 @@ async function gatherWorktreeContext() {
20617
20829
  }
20618
20830
  const orphanDirs = [];
20619
20831
  const wtRoot = siblingMmiWorktreesRoot(repoRoot2);
20620
- if ((0, import_node_fs23.existsSync)(wtRoot)) {
20832
+ if ((0, import_node_fs24.existsSync)(wtRoot)) {
20621
20833
  let entries = [];
20622
20834
  try {
20623
- entries = (0, import_node_fs23.readdirSync)(wtRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path21.join)(wtRoot, e.name));
20835
+ entries = (0, import_node_fs24.readdirSync)(wtRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path22.join)(wtRoot, e.name));
20624
20836
  } catch {
20625
20837
  }
20626
20838
  const known = new Set(worktrees.map((w) => w.path));
@@ -20645,7 +20857,7 @@ async function bestEffortGit(args, cwd, step, timeoutMs = GIT_TIMEOUT_MS) {
20645
20857
  }
20646
20858
 
20647
20859
  // src/issue-commands.ts
20648
- var import_node_fs24 = require("node:fs");
20860
+ var import_node_fs25 = require("node:fs");
20649
20861
  var import_node_crypto5 = require("node:crypto");
20650
20862
  var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
20651
20863
  async function editIssue(client, options, deps = {}) {
@@ -20659,7 +20871,7 @@ async function editIssue(client, options, deps = {}) {
20659
20871
  if (options.body !== void 0 || options.bodyFile !== void 0) {
20660
20872
  let body;
20661
20873
  if (options.bodyFile) {
20662
- const td = deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs24.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
20874
+ const td = deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs25.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
20663
20875
  body = await resolveIssueBody({ body: options.body, bodyFile: options.bodyFile }, td);
20664
20876
  } else {
20665
20877
  body = options.body ?? "";
@@ -21142,7 +21354,7 @@ function extendCreateCommand(issue2) {
21142
21354
  if (opts.batch) {
21143
21355
  let specs;
21144
21356
  try {
21145
- const raw = (0, import_node_fs24.readFileSync)(opts.batch, "utf8");
21357
+ const raw = (0, import_node_fs25.readFileSync)(opts.batch, "utf8");
21146
21358
  specs = JSON.parse(raw);
21147
21359
  if (!Array.isArray(specs)) throw new Error("batch file must contain a JSON array");
21148
21360
  } catch (e) {
@@ -21186,12 +21398,12 @@ ${lines}`);
21186
21398
  }
21187
21399
 
21188
21400
  // src/train-commands.ts
21189
- var import_node_fs26 = require("node:fs");
21190
- var import_node_path23 = require("node:path");
21401
+ var import_node_fs27 = require("node:fs");
21402
+ var import_node_path24 = require("node:path");
21191
21403
 
21192
21404
  // src/plugin-guard-io.ts
21193
- var import_node_fs25 = require("node:fs");
21194
- var import_node_path22 = require("node:path");
21405
+ var import_node_fs26 = require("node:fs");
21406
+ var import_node_path23 = require("node:path");
21195
21407
  var import_node_os6 = require("node:os");
21196
21408
 
21197
21409
  // src/plugin-guard.ts
@@ -21321,11 +21533,11 @@ function runHostBin(bin, args, opts) {
21321
21533
  }
21322
21534
  var installedPluginsPath2 = (surface = detectSurface(process.env)) => {
21323
21535
  const homeDir = surface === "codex" ? ".codex" : ".claude";
21324
- return (0, import_node_path22.join)((0, import_node_os6.homedir)(), homeDir, "plugins", "installed_plugins.json");
21536
+ return (0, import_node_path23.join)((0, import_node_os6.homedir)(), homeDir, "plugins", "installed_plugins.json");
21325
21537
  };
21326
21538
  function readInstalledPlugins(surface = detectSurface(process.env)) {
21327
21539
  try {
21328
- return JSON.parse((0, import_node_fs25.readFileSync)(installedPluginsPath2(surface), "utf8"));
21540
+ return JSON.parse((0, import_node_fs26.readFileSync)(installedPluginsPath2(surface), "utf8"));
21329
21541
  } catch {
21330
21542
  return null;
21331
21543
  }
@@ -21333,13 +21545,13 @@ function readInstalledPlugins(surface = detectSurface(process.env)) {
21333
21545
  function marketplaceCloneCandidates(surface, home) {
21334
21546
  if (surface === "codex") {
21335
21547
  return [
21336
- (0, import_node_path22.join)(home, ".codex", ".tmp", "marketplaces", "mutmutco"),
21337
- (0, import_node_path22.join)(home, ".codex", "plugins", "marketplaces", "mutmutco")
21548
+ (0, import_node_path23.join)(home, ".codex", ".tmp", "marketplaces", "mutmutco"),
21549
+ (0, import_node_path23.join)(home, ".codex", "plugins", "marketplaces", "mutmutco")
21338
21550
  ];
21339
21551
  }
21340
- return [(0, import_node_path22.join)(home, ".claude", "plugins", "marketplaces", "mutmutco")];
21552
+ return [(0, import_node_path23.join)(home, ".claude", "plugins", "marketplaces", "mutmutco")];
21341
21553
  }
21342
- function marketplaceClonePresent(surface, home, exists = import_node_fs25.existsSync) {
21554
+ function marketplaceClonePresent(surface, home, exists = import_node_fs26.existsSync) {
21343
21555
  return marketplaceCloneCandidates(surface, home).some(exists);
21344
21556
  }
21345
21557
  async function fetchNpmReleasedVersion() {
@@ -21366,7 +21578,7 @@ function snapshotPluginGuardInput(surface = detectSurface(process.env), isOrgRep
21366
21578
  isOrgRepo,
21367
21579
  installRecordPresent: hasUserInstallRecord(installed, MMI_PLUGIN_ID) || hasProjectInstallRecord(installed, MMI_PLUGIN_ID, process.cwd()),
21368
21580
  marketplaceClonePresent: marketplaceClonePresent(surface, (0, import_node_os6.homedir)()),
21369
- pluginCachePresent: (0, import_node_fs25.existsSync)((0, import_node_path22.join)((0, import_node_os6.homedir)(), homeDir, "plugins", "cache", "mutmutco", "mmi"))
21581
+ pluginCachePresent: (0, import_node_fs26.existsSync)((0, import_node_path23.join)((0, import_node_os6.homedir)(), homeDir, "plugins", "cache", "mutmutco", "mmi"))
21370
21582
  };
21371
21583
  }
21372
21584
  function claudePluginGuardState(isOrgRepo) {
@@ -21501,7 +21713,7 @@ function formatTrainStatus(r) {
21501
21713
  // src/train-commands.ts
21502
21714
  function readRepoVersion() {
21503
21715
  try {
21504
- return JSON.parse((0, import_node_fs26.readFileSync)((0, import_node_path23.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
21716
+ return JSON.parse((0, import_node_fs27.readFileSync)((0, import_node_path24.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
21505
21717
  } catch {
21506
21718
  return void 0;
21507
21719
  }
@@ -22953,17 +23165,17 @@ async function runDoctorClean(opts, io, deps) {
22953
23165
  }
22954
23166
 
22955
23167
  // src/doctor-io.ts
22956
- var import_node_fs27 = require("node:fs");
23168
+ var import_node_fs28 = require("node:fs");
22957
23169
  var import_node_os7 = require("node:os");
22958
- var import_node_path24 = require("node:path");
22959
- var import_node_child_process11 = require("node:child_process");
23170
+ var import_node_path25 = require("node:path");
23171
+ var import_node_child_process12 = require("node:child_process");
22960
23172
  var import_node_util8 = require("node:util");
22961
- var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process11.execFile);
23173
+ var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process12.execFile);
22962
23174
  var MMI_PLUGIN_ID2 = "mmi@mutmutco";
22963
23175
  function installedClaudePluginVersion() {
22964
23176
  try {
22965
23177
  const file = JSON.parse(
22966
- (0, import_node_fs27.readFileSync)((0, import_node_path24.join)((0, import_node_os7.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
23178
+ (0, import_node_fs28.readFileSync)((0, import_node_path25.join)((0, import_node_os7.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
22967
23179
  );
22968
23180
  const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
22969
23181
  if (versions.length === 0) return void 0;
@@ -22974,7 +23186,7 @@ function installedClaudePluginVersion() {
22974
23186
  }
22975
23187
  function worktreeRootSync() {
22976
23188
  try {
22977
- const out = (0, import_node_child_process11.execFileSync)("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
23189
+ const out = (0, import_node_child_process12.execFileSync)("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
22978
23190
  let root = out.endsWith("\n") ? out.slice(0, -1) : out;
22979
23191
  if (process.platform === "win32" && root.endsWith("\r")) root = root.slice(0, -1);
22980
23192
  return root || null;
@@ -22984,13 +23196,13 @@ function worktreeRootSync() {
22984
23196
  }
22985
23197
  var gitignorePath = () => {
22986
23198
  const root = worktreeRootSync();
22987
- return root === null ? null : (0, import_node_path24.join)(root, ".gitignore");
23199
+ return root === null ? null : (0, import_node_path25.join)(root, ".gitignore");
22988
23200
  };
22989
23201
  function readGitignore() {
22990
23202
  const path2 = gitignorePath();
22991
23203
  if (path2 === null) return null;
22992
23204
  try {
22993
- return (0, import_node_fs27.readFileSync)(path2, "utf8");
23205
+ return (0, import_node_fs28.readFileSync)(path2, "utf8");
22994
23206
  } catch {
22995
23207
  return null;
22996
23208
  }
@@ -22999,7 +23211,7 @@ function writeGitignore(content) {
22999
23211
  const path2 = gitignorePath();
23000
23212
  if (path2 === null) return false;
23001
23213
  try {
23002
- (0, import_node_fs27.writeFileSync)(path2, content, "utf8");
23214
+ (0, import_node_fs28.writeFileSync)(path2, content, "utf8");
23003
23215
  return true;
23004
23216
  } catch {
23005
23217
  return false;
@@ -23023,7 +23235,7 @@ async function repoRoot() {
23023
23235
  }
23024
23236
  function hasRepoLocalWorktrees() {
23025
23237
  const root = worktreeRootSync();
23026
- return root !== null && (0, import_node_fs27.existsSync)((0, import_node_path24.join)(root, ".worktrees"));
23238
+ return root !== null && (0, import_node_fs28.existsSync)((0, import_node_path25.join)(root, ".worktrees"));
23027
23239
  }
23028
23240
 
23029
23241
  // src/index.ts
@@ -23141,16 +23353,16 @@ var cachedLongFlags;
23141
23353
  function allLongFlags() {
23142
23354
  if (cachedLongFlags) return cachedLongFlags;
23143
23355
  const acc = /* @__PURE__ */ new Set();
23144
- const walk = (node) => {
23356
+ const walk2 = (node) => {
23145
23357
  if (!isCanonicalSuggestion(node)) return;
23146
23358
  for (const opt of node.options) {
23147
23359
  if (opt.discovery) continue;
23148
23360
  const m = /--[\w-]+/.exec(opt.flags);
23149
23361
  if (m) acc.add(m[0]);
23150
23362
  }
23151
- for (const child2 of node.subcommands) walk(child2);
23363
+ for (const child2 of node.subcommands) walk2(child2);
23152
23364
  };
23153
- walk(buildCommandManifest(program2).tree);
23365
+ walk2(buildCommandManifest(program2).tree);
23154
23366
  cachedLongFlags = [...acc];
23155
23367
  return cachedLongFlags;
23156
23368
  }
@@ -23250,19 +23462,19 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
23250
23462
  });
23251
23463
  var rules = program2.command("rules").description("org-managed .gitignore delivery");
23252
23464
  rules.command("gitignore").option("--write", "upsert the managed block into .gitignore (default: check only, non-zero exit on drift)").option("--json", "machine-readable output").description("verify (or --write) this repo's org-managed .gitignore block matches the SSOT").action((opts) => {
23253
- const path2 = (0, import_node_path25.join)(process.cwd(), ".gitignore");
23254
- const current = (0, import_node_fs28.existsSync)(path2) ? (0, import_node_fs28.readFileSync)(path2, "utf8") : null;
23465
+ const path2 = (0, import_node_path26.join)(process.cwd(), ".gitignore");
23466
+ const current = (0, import_node_fs29.existsSync)(path2) ? (0, import_node_fs29.readFileSync)(path2, "utf8") : null;
23255
23467
  const plan = planManagedGitignore(current);
23256
23468
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
23257
23469
  if (opts.json) {
23258
- if (opts.write && plan.changed) (0, import_node_fs28.writeFileSync)(path2, plan.content, "utf8");
23470
+ if (opts.write && plan.changed) (0, import_node_fs29.writeFileSync)(path2, plan.content, "utf8");
23259
23471
  console.log(JSON.stringify(plan, null, 2));
23260
23472
  if (!opts.write && plan.changed) process.exitCode = 1;
23261
23473
  return;
23262
23474
  }
23263
23475
  if (opts.write) {
23264
23476
  if (plan.changed) {
23265
- (0, import_node_fs28.writeFileSync)(path2, plan.content, "utf8");
23477
+ (0, import_node_fs29.writeFileSync)(path2, plan.content, "utf8");
23266
23478
  console.log(`mmi-cli org rules gitignore: updated .gitignore (${drift})`);
23267
23479
  } else {
23268
23480
  console.log("mmi-cli org rules gitignore: up to date");
@@ -23420,7 +23632,7 @@ function runWorktreeInstall(command, cwd, quiet) {
23420
23632
  const file = isWin2 ? "cmd.exe" : bin;
23421
23633
  const spawnArgs = isWin2 ? ["/c", bin, ...args] : args;
23422
23634
  return new Promise((resolve5, reject) => {
23423
- const child2 = (0, import_node_child_process12.spawn)(file, spawnArgs, { cwd, stdio: quiet ? "ignore" : "inherit", windowsHide: true });
23635
+ const child2 = (0, import_node_child_process13.spawn)(file, spawnArgs, { cwd, stdio: quiet ? "ignore" : "inherit", windowsHide: true });
23424
23636
  const timer = setTimeout(() => {
23425
23637
  try {
23426
23638
  child2.kill();
@@ -23452,26 +23664,26 @@ function makeProvisionDeps(worktreeRoot, quiet, log) {
23452
23664
  function acquireWorktreeSetupLock(worktreeRoot) {
23453
23665
  const lockPath = repoRuntimeStatePath(worktreeRoot, "worktree-setup.lock");
23454
23666
  const take = () => {
23455
- const fd = (0, import_node_fs28.openSync)(lockPath, "wx");
23667
+ const fd = (0, import_node_fs29.openSync)(lockPath, "wx");
23456
23668
  try {
23457
- (0, import_node_fs28.writeSync)(fd, String(Date.now()));
23669
+ (0, import_node_fs29.writeSync)(fd, String(Date.now()));
23458
23670
  } finally {
23459
- (0, import_node_fs28.closeSync)(fd);
23671
+ (0, import_node_fs29.closeSync)(fd);
23460
23672
  }
23461
23673
  return () => {
23462
23674
  try {
23463
- (0, import_node_fs28.rmSync)(lockPath, { force: true });
23675
+ (0, import_node_fs29.rmSync)(lockPath, { force: true });
23464
23676
  } catch {
23465
23677
  }
23466
23678
  };
23467
23679
  };
23468
23680
  try {
23469
- (0, import_node_fs28.mkdirSync)((0, import_node_path25.dirname)(lockPath), { recursive: true });
23681
+ (0, import_node_fs29.mkdirSync)((0, import_node_path26.dirname)(lockPath), { recursive: true });
23470
23682
  return take();
23471
23683
  } catch {
23472
23684
  try {
23473
- if (Date.now() - (0, import_node_fs28.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
23474
- (0, import_node_fs28.rmSync)(lockPath, { force: true });
23685
+ if (Date.now() - (0, import_node_fs29.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
23686
+ (0, import_node_fs29.rmSync)(lockPath, { force: true });
23475
23687
  return take();
23476
23688
  }
23477
23689
  } catch {
@@ -23651,7 +23863,7 @@ function scheduleRelatedDiscovery(o) {
23651
23863
  try {
23652
23864
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
23653
23865
  if (o.repo) args.push("--repo", o.repo);
23654
- spawnDetachedSelf(args, { spawn: import_node_child_process12.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
23866
+ spawnDetachedSelf(args, { spawn: import_node_child_process13.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
23655
23867
  } catch {
23656
23868
  }
23657
23869
  }
@@ -23677,6 +23889,27 @@ docs.command("index").description("regenerate docs/index.md from the docs/ tree
23677
23889
  await failGraceful(e.message);
23678
23890
  }
23679
23891
  });
23892
+ docs.command("refs").description("deterministic doc reference gate: every backticked repo path, relative .md link, `mmi-cli` command ref, and `<!-- pinned by \u2026 -->` comment across docs/** + README.md + architecture.md must resolve, or exit 1 (fleet-portable port of the Hub gate scripts/check-doc-refs.mjs, #3339)").option("--json", "machine-readable findings list: { ok, docCount, findings[] }").action(async (o) => {
23893
+ try {
23894
+ const root = await repoRoot();
23895
+ const commandPaths = new Set(buildCommandManifest(program2).index.map((entry) => entry.path));
23896
+ const result = runDocRefs(root, { commandPaths });
23897
+ if (o.json) {
23898
+ consoleIo.log(JSON.stringify({ ok: result.ok, docCount: result.docCount, findings: result.findings }, null, 2));
23899
+ if (!result.ok) process.exitCode = 1;
23900
+ return;
23901
+ }
23902
+ if (result.ok) {
23903
+ console.log(`doc refs: ${result.docCount} docs, every reference resolves`);
23904
+ return;
23905
+ }
23906
+ console.error("doc refs: unresolved references");
23907
+ for (const f of result.findings) console.error(`- ${f.doc}:${f.line} [${f.kind}] ${f.detail}`);
23908
+ process.exitCode = 1;
23909
+ } catch (e) {
23910
+ await failGraceful(e.message);
23911
+ }
23912
+ });
23680
23913
  var docsAudit = program2.command("docs-audit").description("the docs janitor verdict ledger \u2014 record a dated run verdict, or read the dead-man status back");
23681
23914
  docsAudit.command("record").description("write a dated janitor verdict for one repo to the registry ledger (master-only server-side)").option("--repo <owner/name>", "the repo the verdict is for (default: the current repo)").option("--date <YYYY-MM-DD>", "the ISO day the run examined (default: today)").requiredOption("--sha-range <a..b>", "the git range the janitor read (e.g. <lastVerdictSha>..HEAD)").requiredOption("--outcome <kind>", "clean | refreshed | failed").option("--count <n>", "docs refreshed (required when --outcome refreshed)").option("--reason <text>", "why the run failed (required when --outcome failed)").requiredOption("--checker-vendor <vendor>", "which vendor's model actually ran the check").action(async (o) => {
23682
23915
  try {
@@ -23892,7 +24125,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
23892
24125
  if (dupe) return fail(`org project set: KEY "${dupe}" was passed to both --var and --set; --set is an alias of --var, so pass each KEY once`);
23893
24126
  if (o.secretsFile) {
23894
24127
  try {
23895
- vars.push(`secrets=${(0, import_node_fs28.readFileSync)(o.secretsFile, "utf8")}`);
24128
+ vars.push(`secrets=${(0, import_node_fs29.readFileSync)(o.secretsFile, "utf8")}`);
23896
24129
  } catch (e) {
23897
24130
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
23898
24131
  }
@@ -24527,11 +24760,11 @@ pr.command("view <number>").description("read a PR as structured JSON (merged st
24527
24760
  }
24528
24761
  });
24529
24762
  async function listCiWorkflowPaths(cwd = process.cwd()) {
24530
- const wfDir = (0, import_node_path25.join)(cwd, ".github", "workflows");
24531
- if (!(0, import_node_fs28.existsSync)(wfDir)) return [];
24532
- return (0, import_node_fs28.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
24763
+ const wfDir = (0, import_node_path26.join)(cwd, ".github", "workflows");
24764
+ if (!(0, import_node_fs29.existsSync)(wfDir)) return [];
24765
+ return (0, import_node_fs29.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
24533
24766
  try {
24534
- return workflowReportsPrChecks((0, import_node_fs28.readFileSync)((0, import_node_path25.join)(wfDir, name), "utf8"));
24767
+ return workflowReportsPrChecks((0, import_node_fs29.readFileSync)((0, import_node_path26.join)(wfDir, name), "utf8"));
24535
24768
  } catch {
24536
24769
  return true;
24537
24770
  }
@@ -24558,16 +24791,16 @@ function ciAuditDeps() {
24558
24791
  // gate re-seed step is skipped gracefully rather than failing mid-run.
24559
24792
  readSeedFile: (path2) => {
24560
24793
  if (!root) return null;
24561
- const fullPath = (0, import_node_path25.join)(root, path2);
24562
- return (0, import_node_fs28.existsSync)(fullPath) ? (0, import_node_fs28.readFileSync)(fullPath, "utf8") : null;
24794
+ const fullPath = (0, import_node_path26.join)(root, path2);
24795
+ return (0, import_node_fs29.existsSync)(fullPath) ? (0, import_node_fs29.readFileSync)(fullPath, "utf8") : null;
24563
24796
  }
24564
24797
  };
24565
24798
  }
24566
24799
  function hubRoot() {
24567
- const fromPkg = (0, import_node_path25.join)(__dirname, "..", "..");
24800
+ const fromPkg = (0, import_node_path26.join)(__dirname, "..", "..");
24568
24801
  const marker = "skills/bootstrap/seeds/manifest.json";
24569
- if ((0, import_node_fs28.existsSync)((0, import_node_path25.join)(fromPkg, marker))) return fromPkg;
24570
- if ((0, import_node_fs28.existsSync)((0, import_node_path25.join)(process.cwd(), marker))) return process.cwd();
24802
+ if ((0, import_node_fs29.existsSync)((0, import_node_path26.join)(fromPkg, marker))) return fromPkg;
24803
+ if ((0, import_node_fs29.existsSync)((0, import_node_path26.join)(process.cwd(), marker))) return process.cwd();
24571
24804
  return null;
24572
24805
  }
24573
24806
  pr.command("ci-policy").description("report merge CI policy: wait-for-checks vs no-ci (for grind/build agents)").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the current checkout)").action(async (o) => {
@@ -24806,7 +25039,7 @@ pr.command("merge <number>").description("merge a PR (squash by default) and cle
24806
25039
  localCleanup = await cleanupPrMergeLocalBranch(headRef, {
24807
25040
  beforeWorktrees,
24808
25041
  startingPath,
24809
- pathExists: (p) => (0, import_node_fs28.existsSync)(p),
25042
+ pathExists: (p) => (0, import_node_fs29.existsSync)(p),
24810
25043
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
24811
25044
  teardownWorktreeStage,
24812
25045
  deferredStore,
@@ -25146,10 +25379,10 @@ access.command("audit").description("audit collaborator roles + train-branch pus
25146
25379
  targets = resolution.targets;
25147
25380
  }
25148
25381
  const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
25149
- const fileMatrix = (0, import_node_fs28.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs28.readFileSync)("access-matrix.json", "utf8")) : {};
25382
+ const fileMatrix = (0, import_node_fs29.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs29.readFileSync)("access-matrix.json", "utf8")) : {};
25150
25383
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
25151
25384
  const derivedContracts = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
25152
- const fileContracts = (0, import_node_fs28.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs28.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
25385
+ const fileContracts = (0, import_node_fs29.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs29.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
25153
25386
  const dataAccess = mergeDataAccessContracts(fileContracts, derivedContracts);
25154
25387
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess);
25155
25388
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
@@ -25182,16 +25415,16 @@ function directoryBytes(path2) {
25182
25415
  let total = 0;
25183
25416
  let entries;
25184
25417
  try {
25185
- entries = (0, import_node_fs28.readdirSync)(path2, { withFileTypes: true });
25418
+ entries = (0, import_node_fs29.readdirSync)(path2, { withFileTypes: true });
25186
25419
  } catch {
25187
25420
  return 0;
25188
25421
  }
25189
25422
  for (const entry of entries) {
25190
- const child2 = (0, import_node_path25.join)(path2, entry.name);
25423
+ const child2 = (0, import_node_path26.join)(path2, entry.name);
25191
25424
  if (entry.isDirectory()) total += directoryBytes(child2);
25192
25425
  else {
25193
25426
  try {
25194
- total += (0, import_node_fs28.statSync)(child2).size;
25427
+ total += (0, import_node_fs29.statSync)(child2).size;
25195
25428
  } catch {
25196
25429
  }
25197
25430
  }
@@ -25199,25 +25432,25 @@ function directoryBytes(path2) {
25199
25432
  return total;
25200
25433
  }
25201
25434
  function listDirEntries(dir) {
25202
- return (0, import_node_fs28.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
25435
+ return (0, import_node_fs29.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
25203
25436
  }
25204
25437
  function readInstalledPluginRefs(home) {
25205
25438
  const p = installedPluginsPath(home);
25206
- if (!(0, import_node_fs28.existsSync)(p)) return [];
25439
+ if (!(0, import_node_fs29.existsSync)(p)) return [];
25207
25440
  try {
25208
- return installedPluginPaths((0, import_node_fs28.readFileSync)(p, "utf8"));
25441
+ return installedPluginPaths((0, import_node_fs29.readFileSync)(p, "utf8"));
25209
25442
  } catch {
25210
25443
  return null;
25211
25444
  }
25212
25445
  }
25213
25446
  function pluginCacheFsDeps(home, dirBytes) {
25214
25447
  return {
25215
- exists: (p) => (0, import_node_fs28.existsSync)(p),
25216
- listVersionDirs: (root) => (0, import_node_fs28.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
25448
+ exists: (p) => (0, import_node_fs29.existsSync)(p),
25449
+ listVersionDirs: (root) => (0, import_node_fs29.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
25217
25450
  dirBytes,
25218
- listStagingDirs: (root) => (0, import_node_fs28.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
25451
+ listStagingDirs: (root) => (0, import_node_fs29.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
25219
25452
  try {
25220
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path25.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs28.statSync)(p).mtimeMs) };
25453
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path26.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs29.statSync)(p).mtimeMs) };
25221
25454
  } catch {
25222
25455
  return { name: d.name, mtimeMs: Date.now() };
25223
25456
  }
@@ -25231,10 +25464,10 @@ function stagingApplyFsGuard(home) {
25231
25464
  return {
25232
25465
  referencedPaths: () => readInstalledPluginRefs(home),
25233
25466
  mtimeMs: (name) => {
25234
- const p = (0, import_node_path25.join)(stagingRoot, name);
25235
- if (!(0, import_node_fs28.existsSync)(p)) return null;
25467
+ const p = (0, import_node_path26.join)(stagingRoot, name);
25468
+ if (!(0, import_node_fs29.existsSync)(p)) return null;
25236
25469
  try {
25237
- return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs28.statSync)(q).mtimeMs);
25470
+ return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs29.statSync)(q).mtimeMs);
25238
25471
  } catch {
25239
25472
  return null;
25240
25473
  }
@@ -25250,7 +25483,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
25250
25483
  { withBytes: true }
25251
25484
  );
25252
25485
  const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
25253
- const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs28.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard((0, import_node_os8.homedir)())) : void 0;
25486
+ const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs29.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard((0, import_node_os8.homedir)())) : void 0;
25254
25487
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
25255
25488
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
25256
25489
  else console.log(renderPluginCachePlan(plan, result));
@@ -25283,7 +25516,7 @@ program2.command("session-start").description("run the SessionStart verbs (whoam
25283
25516
  readBoard,
25284
25517
  // #1813: warm the slice cache out-of-band (detached) so the ~20s live read
25285
25518
  // never costs banner time and next session's glance renders instantly within budget.
25286
- scheduleRefresh: () => spawnDetachedSelf(["board", "slice-refresh", "--quiet"], { spawn: import_node_child_process12.spawn, execPath: process.execPath, scriptPath: process.argv[1] })
25519
+ scheduleRefresh: () => spawnDetachedSelf(["board", "slice-refresh", "--quiet"], { spawn: import_node_child_process13.spawn, execPath: process.execPath, scriptPath: process.argv[1] })
25287
25520
  }),
25288
25521
  // command-ladder hint (#2609): compact gh→mmi-cli cheat sheet so agents reach for mmi-cli first,
25289
25522
  // not after a denied gh call. <1KB, pure in-memory — no network, no fs, fail-soft.
@@ -25314,7 +25547,7 @@ program2.command("session-start").description("run the SessionStart verbs (whoam
25314
25547
  for (const line of scratchGcLines(process.cwd())) consoleIo.log(line);
25315
25548
  const worktreeBanner = worktreeAutoProvisionBanner(process.cwd());
25316
25549
  if (worktreeBanner) {
25317
- spawnDetachedSelf(["worktree", "setup", "--quiet"], { spawn: import_node_child_process12.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
25550
+ spawnDetachedSelf(["worktree", "setup", "--quiet"], { spawn: import_node_child_process13.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
25318
25551
  consoleIo.log(worktreeBanner);
25319
25552
  }
25320
25553
  appendHookActivity(process.cwd(), { event: "SessionStart", script: "session-start", outcome: "ran", action: "session-start hook completed" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "3.40.0",
3
+ "version": "3.42.0",
4
4
  "description": "MMI Future CLI — the org dev toolbox (board, registry, keyless secrets, release train, bootstrap, doctor) and the cross-IDE engine the plugin's session-start hook drives.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",