@mutmutco/cli 3.117.0 → 3.118.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 +574 -519
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -5000,7 +5000,7 @@ var program = new Command();
5000
5000
 
5001
5001
  // src/index.ts
5002
5002
  var import_promises11 = require("node:fs/promises");
5003
- var import_node_fs46 = require("node:fs");
5003
+ var import_node_fs47 = require("node:fs");
5004
5004
  var import_node_child_process20 = require("node:child_process");
5005
5005
 
5006
5006
  // src/cli-shared.ts
@@ -8708,6 +8708,40 @@ function cachedReadNote(cachedAt, now = Date.now()) {
8708
8708
  return `(cached ${hours < 1 ? "<1" : hours}h ago \u2014 the banner reads npm at most once a day)`;
8709
8709
  }
8710
8710
 
8711
+ // src/schedules-drift-cache.ts
8712
+ var import_node_fs13 = require("node:fs");
8713
+ var import_node_path11 = require("node:path");
8714
+ var SCHEDULES_DRIFT_CACHE_MS = 6 * 36e5;
8715
+ function schedulesDriftCachePath(runtimeRoot) {
8716
+ return (0, import_node_path11.join)(runtimeRoot, "head-ts", ".schedules-drift");
8717
+ }
8718
+ function readSchedulesDriftCache(cachePath, now = Date.now(), read = import_node_fs13.readFileSync) {
8719
+ let parsed;
8720
+ try {
8721
+ parsed = JSON.parse(read(cachePath, "utf8"));
8722
+ } catch {
8723
+ return void 0;
8724
+ }
8725
+ if (!parsed || typeof parsed !== "object") return void 0;
8726
+ const { driftLines, at } = parsed;
8727
+ if (!Array.isArray(driftLines) || driftLines.some((l) => typeof l !== "string")) return void 0;
8728
+ if (typeof at !== "number" || !Number.isFinite(at)) return void 0;
8729
+ const age = now - at;
8730
+ if (age < 0 || age >= SCHEDULES_DRIFT_CACHE_MS) return void 0;
8731
+ return { driftLines, at };
8732
+ }
8733
+ function writeSchedulesDriftCache(cachePath, driftLines, now = Date.now()) {
8734
+ try {
8735
+ (0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(cachePath), { recursive: true });
8736
+ (0, import_node_fs13.writeFileSync)(cachePath, JSON.stringify({ driftLines, at: now }), "utf8");
8737
+ } catch {
8738
+ }
8739
+ }
8740
+ function cachedSweepNote(cachedAt, now = Date.now()) {
8741
+ const hours = cacheAgeHours(cachedAt, now);
8742
+ return `cached ${hours < 1 ? "<1" : hours}h ago \u2014 doctor sweeps the org notebook at most every ${SCHEDULES_DRIFT_CACHE_MS / 36e5}h (run \`mmi-cli harbour org schedules\` for a live read)`;
8743
+ }
8744
+
8711
8745
  // src/marketplace-autoupdate.ts
8712
8746
  var KNOWN_MARKETPLACES_RELATIVE = [".claude", "plugins", "known_marketplaces.json"];
8713
8747
  var MMI_MARKETPLACE_NAME = "mutmutco";
@@ -8919,8 +8953,8 @@ function marketplaceRows(name, known, settings, remedy = "manual") {
8919
8953
  }
8920
8954
 
8921
8955
  // src/hook-activity.ts
8922
- var import_node_fs13 = require("node:fs");
8923
- var import_node_path11 = require("node:path");
8956
+ var import_node_fs14 = require("node:fs");
8957
+ var import_node_path12 = require("node:path");
8924
8958
  var DEFAULT_SURFACE = "claude";
8925
8959
  function activityLogPath(cwd) {
8926
8960
  return repoRuntimeStatePath(cwd, "hooks", "activity.jsonl");
@@ -8933,20 +8967,20 @@ function appendHookActivity(cwd, entry) {
8933
8967
  surface: DEFAULT_SURFACE,
8934
8968
  ...entry
8935
8969
  };
8936
- (0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(path2), { recursive: true });
8937
- (0, import_node_fs13.appendFileSync)(path2, `${JSON.stringify(line)}
8970
+ (0, import_node_fs14.mkdirSync)((0, import_node_path12.dirname)(path2), { recursive: true });
8971
+ (0, import_node_fs14.appendFileSync)(path2, `${JSON.stringify(line)}
8938
8972
  `, "utf8");
8939
8973
  } catch {
8940
8974
  }
8941
8975
  }
8942
8976
 
8943
8977
  // src/worktree.ts
8944
- var import_node_fs14 = require("node:fs");
8945
- var import_node_path13 = require("node:path");
8978
+ var import_node_fs15 = require("node:fs");
8979
+ var import_node_path14 = require("node:path");
8946
8980
 
8947
8981
  // src/file-lock.ts
8948
8982
  var import_promises2 = require("node:fs/promises");
8949
- var import_node_path12 = require("node:path");
8983
+ var import_node_path13 = require("node:path");
8950
8984
  var sleep = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
8951
8985
  var IMMEDIATE_RETRY_BUDGET = 3;
8952
8986
  var FileLockBusyError = class extends Error {
@@ -9031,7 +9065,7 @@ async function releaseFileLock(lockPath, guard) {
9031
9065
  }
9032
9066
  async function withFileLock(lockPath, opts, fn) {
9033
9067
  const resolved = resolveFileLockOpts(opts);
9034
- await (0, import_promises2.mkdir)((0, import_node_path12.dirname)(lockPath), { recursive: true }).catch(() => void 0);
9068
+ await (0, import_promises2.mkdir)((0, import_node_path13.dirname)(lockPath), { recursive: true }).catch(() => void 0);
9035
9069
  const guard = await acquireFileLock(lockPath, resolved, Date.now() + resolved.maxWaitMs);
9036
9070
  try {
9037
9071
  return await fn();
@@ -9058,35 +9092,35 @@ var PROVISION_ENV_MARKER = "MMI_PROVISION_RUNNING";
9058
9092
  var realFsProbe = {
9059
9093
  isDir: (p) => {
9060
9094
  try {
9061
- return (0, import_node_fs14.statSync)(p).isDirectory();
9095
+ return (0, import_node_fs15.statSync)(p).isDirectory();
9062
9096
  } catch {
9063
9097
  return false;
9064
9098
  }
9065
9099
  },
9066
9100
  isFile: (p) => {
9067
9101
  try {
9068
- return (0, import_node_fs14.statSync)(p).isFile();
9102
+ return (0, import_node_fs15.statSync)(p).isFile();
9069
9103
  } catch {
9070
9104
  return false;
9071
9105
  }
9072
9106
  },
9073
9107
  listDirs: (p) => {
9074
9108
  try {
9075
- return (0, import_node_fs14.readdirSync)(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
9109
+ return (0, import_node_fs15.readdirSync)(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
9076
9110
  } catch {
9077
9111
  return [];
9078
9112
  }
9079
9113
  },
9080
9114
  readFile: (p) => {
9081
9115
  try {
9082
- return (0, import_node_fs14.readFileSync)(p, "utf8");
9116
+ return (0, import_node_fs15.readFileSync)(p, "utf8");
9083
9117
  } catch {
9084
9118
  return void 0;
9085
9119
  }
9086
9120
  }
9087
9121
  };
9088
9122
  function declaredProvision(fs2, abs) {
9089
- const raw = fs2.readFile?.((0, import_node_path13.join)(abs, PKG));
9123
+ const raw = fs2.readFile?.((0, import_node_path14.join)(abs, PKG));
9090
9124
  if (raw === void 0) return void 0;
9091
9125
  try {
9092
9126
  const scripts = JSON.parse(raw).scripts;
@@ -9098,13 +9132,13 @@ function declaredProvision(fs2, abs) {
9098
9132
  }
9099
9133
  function scanInstallDirs(root, fs2 = realFsProbe) {
9100
9134
  const factsFor = (dir) => {
9101
- const abs = dir ? (0, import_node_path13.join)(root, dir) : root;
9102
- const match = LOCKFILE_INSTALLS.find((c) => fs2.isFile((0, import_node_path13.join)(abs, c.lockfile)));
9103
- const hasPackageJson = fs2.isFile((0, import_node_path13.join)(abs, PKG));
9135
+ const abs = dir ? (0, import_node_path14.join)(root, dir) : root;
9136
+ const match = LOCKFILE_INSTALLS.find((c) => fs2.isFile((0, import_node_path14.join)(abs, c.lockfile)));
9137
+ const hasPackageJson = fs2.isFile((0, import_node_path14.join)(abs, PKG));
9104
9138
  return {
9105
9139
  dir,
9106
9140
  hasPackageJson,
9107
- hasNodeModules: fs2.isDir((0, import_node_path13.join)(abs, NODE_MODULES)),
9141
+ hasNodeModules: fs2.isDir((0, import_node_path14.join)(abs, NODE_MODULES)),
9108
9142
  install: match?.command,
9109
9143
  provision: hasPackageJson ? declaredProvision(fs2, abs) : void 0
9110
9144
  };
@@ -9120,7 +9154,7 @@ function npmInstallTargets(dirs) {
9120
9154
  }));
9121
9155
  }
9122
9156
  function isLinkedWorktree(root, fs2 = realFsProbe) {
9123
- return fs2.isFile((0, import_node_path13.join)(root, ".git"));
9157
+ return fs2.isFile((0, import_node_path14.join)(root, ".git"));
9124
9158
  }
9125
9159
  function worktreeAutoProvisionBanner(root, fs2 = realFsProbe) {
9126
9160
  if (!isLinkedWorktree(root, fs2)) return null;
@@ -9130,8 +9164,8 @@ function worktreeAutoProvisionBanner(root, fs2 = realFsProbe) {
9130
9164
  return `[worktree] provisioning tooling in the background (deps in ${where} + local config) \u2014 \`mmi-cli worktree setup\` to redo`;
9131
9165
  }
9132
9166
  function defaultCopyFile(from, to) {
9133
- (0, import_node_fs14.mkdirSync)((0, import_node_path13.dirname)(to), { recursive: true });
9134
- (0, import_node_fs14.copyFileSync)(from, to);
9167
+ (0, import_node_fs15.mkdirSync)((0, import_node_path14.dirname)(to), { recursive: true });
9168
+ (0, import_node_fs15.copyFileSync)(from, to);
9135
9169
  }
9136
9170
  async function runDeclaredProvision(target, cwd, runInstall) {
9137
9171
  const previous = process.env[PROVISION_ENV_MARKER];
@@ -9161,7 +9195,7 @@ async function provisionWorktree(worktreeRoot, deps) {
9161
9195
  const targets = npmInstallTargets(allDirs);
9162
9196
  if (deps.validateInstall) {
9163
9197
  for (const dir of allDirs.filter((d) => d.hasPackageJson && (d.provision ?? d.install) && d.hasNodeModules)) {
9164
- const cwd = dir.dir ? (0, import_node_path13.join)(worktreeRoot, dir.dir) : worktreeRoot;
9198
+ const cwd = dir.dir ? (0, import_node_path14.join)(worktreeRoot, dir.dir) : worktreeRoot;
9165
9199
  if (!await deps.validateInstall(cwd)) {
9166
9200
  targets.push({
9167
9201
  dir: dir.dir,
@@ -9175,7 +9209,7 @@ async function provisionWorktree(worktreeRoot, deps) {
9175
9209
  const skippedInstall = allDirs.filter((d) => d.hasPackageJson && d.hasNodeModules && !targetDirs.has(d.dir)).map((d) => d.dir);
9176
9210
  const installed = [];
9177
9211
  for (const target of targets) {
9178
- const cwd = target.dir ? (0, import_node_path13.join)(worktreeRoot, target.dir) : worktreeRoot;
9212
+ const cwd = target.dir ? (0, import_node_path14.join)(worktreeRoot, target.dir) : worktreeRoot;
9179
9213
  log(`installing deps: ${target.command} in ${target.dir || "."}`);
9180
9214
  if (target.declared) await runDeclaredProvision(target, cwd, deps.runInstall);
9181
9215
  else await deps.runInstall(target.command, cwd);
@@ -9185,7 +9219,7 @@ async function provisionWorktree(worktreeRoot, deps) {
9185
9219
  const copySkipped = [];
9186
9220
  const primary = await deps.primaryCheckout();
9187
9221
  for (const rel of LOCAL_ONLY_FILES) {
9188
- const dest = (0, import_node_path13.join)(worktreeRoot, rel);
9222
+ const dest = (0, import_node_path14.join)(worktreeRoot, rel);
9189
9223
  if (fs2.isFile(dest)) {
9190
9224
  copySkipped.push({ file: rel, reason: "already-present" });
9191
9225
  continue;
@@ -9194,11 +9228,11 @@ async function provisionWorktree(worktreeRoot, deps) {
9194
9228
  copySkipped.push({ file: rel, reason: "no-primary" });
9195
9229
  continue;
9196
9230
  }
9197
- if (!fs2.isFile((0, import_node_path13.join)(primary, rel))) {
9231
+ if (!fs2.isFile((0, import_node_path14.join)(primary, rel))) {
9198
9232
  copySkipped.push({ file: rel, reason: "absent-in-primary" });
9199
9233
  continue;
9200
9234
  }
9201
- copyFile((0, import_node_path13.join)(primary, rel), dest);
9235
+ copyFile((0, import_node_path14.join)(primary, rel), dest);
9202
9236
  copied.push(rel);
9203
9237
  log(`copied local config: ${rel}`);
9204
9238
  }
@@ -9212,12 +9246,12 @@ function capWorktreeDirName(name, max = 40) {
9212
9246
  }
9213
9247
  function defaultWorktreePath(repoRoot2, branch) {
9214
9248
  const safe = capWorktreeDirName(branch.replace(/[/\\]+/g, "-"));
9215
- return (0, import_node_path13.join)((0, import_node_path13.dirname)(repoRoot2), "mmi-worktrees", (0, import_node_path13.basename)(repoRoot2), safe);
9249
+ return (0, import_node_path14.join)((0, import_node_path14.dirname)(repoRoot2), "mmi-worktrees", (0, import_node_path14.basename)(repoRoot2), safe);
9216
9250
  }
9217
9251
  async function primaryCheckoutRootOf(git2) {
9218
9252
  try {
9219
9253
  const out = (await git2(["rev-parse", "--path-format=absolute", "--git-common-dir"])).trim();
9220
- return out ? (0, import_node_path13.dirname)(out) : void 0;
9254
+ return out ? (0, import_node_path14.dirname)(out) : void 0;
9221
9255
  } catch {
9222
9256
  return void 0;
9223
9257
  }
@@ -9355,7 +9389,7 @@ function commandLadderHint() {
9355
9389
  }
9356
9390
 
9357
9391
  // src/index.ts
9358
- var import_node_path43 = require("node:path");
9392
+ var import_node_path44 = require("node:path");
9359
9393
 
9360
9394
  // src/merge-ci-policy.ts
9361
9395
  function resolveMergeCiPolicy(input) {
@@ -10015,13 +10049,13 @@ function planManagedGitignore(current) {
10015
10049
  }
10016
10050
 
10017
10051
  // src/docs-index-command.ts
10018
- var import_node_fs16 = require("node:fs");
10019
- var import_node_path15 = require("node:path");
10052
+ var import_node_fs17 = require("node:fs");
10053
+ var import_node_path16 = require("node:path");
10020
10054
 
10021
10055
  // src/doc-refs-core.ts
10022
10056
  var import_node_child_process5 = require("node:child_process");
10023
- var import_node_fs15 = require("node:fs");
10024
- var import_node_path14 = require("node:path");
10057
+ var import_node_fs16 = require("node:fs");
10058
+ var import_node_path15 = require("node:path");
10025
10059
  var PIN_RE = /<!--\s*pinned by\s+([^:]+?)\s*:\s*"([^"]+)"[^"]*-->/;
10026
10060
  var PIN_MENTION_RE = /<!--\s*pinned by\b/;
10027
10061
  var FWD_RE = /<!--\s*forward-ref:\s*(\S+?)\s*-->/;
@@ -10080,7 +10114,7 @@ function checkPins(root, readFile9, docs2) {
10080
10114
  findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
10081
10115
  continue;
10082
10116
  }
10083
- const source = readFile9((0, import_node_path14.join)(root, pin.file));
10117
+ const source = readFile9((0, import_node_path15.join)(root, pin.file));
10084
10118
  if (source == null) {
10085
10119
  findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
10086
10120
  continue;
@@ -10142,11 +10176,11 @@ function checkRefs(root, deps, docs2) {
10142
10176
  for (const { ref } of extractRefs(markdown)) allFirstSegments.add(refFirstSegment(ref));
10143
10177
  }
10144
10178
  const tracked = allFirstSegments.size ? deps.trackedFirstSegments?.([...allFirstSegments]) ?? null : null;
10145
- const firstVerifiable = (first) => tracked ? tracked.has(first) : exists((0, import_node_path14.join)(root, first));
10179
+ const firstVerifiable = (first) => tracked ? tracked.has(first) : exists((0, import_node_path15.join)(root, first));
10146
10180
  const candidates = [];
10147
10181
  const direct = [];
10148
10182
  for (const [doc, markdown] of Object.entries(docs2)) {
10149
- const docDir = import_node_path14.posix.dirname(doc);
10183
+ const docDir = import_node_path15.posix.dirname(doc);
10150
10184
  const base = docDir === "." ? "" : docDir;
10151
10185
  const covered = /* @__PURE__ */ new Set();
10152
10186
  const markers = [];
@@ -10155,21 +10189,21 @@ function checkRefs(root, deps, docs2) {
10155
10189
  direct.push({ kind: "malformed-forward-ref", doc, line: fwd.line, detail: fwd.text });
10156
10190
  continue;
10157
10191
  }
10158
- const docRel = import_node_path14.posix.normalize(import_node_path14.posix.join(base, fwd.target));
10159
- const rootRel = import_node_path14.posix.normalize(fwd.target.replace(/^\/+/, ""));
10192
+ const docRel = import_node_path15.posix.normalize(import_node_path15.posix.join(base, fwd.target));
10193
+ const rootRel = import_node_path15.posix.normalize(fwd.target.replace(/^\/+/, ""));
10160
10194
  markers.push({ target: fwd.target, line: fwd.line, docRel, rootRel });
10161
10195
  covered.add(docRel);
10162
10196
  covered.add(rootRel);
10163
10197
  }
10164
10198
  const links = extractLinks(markdown).map(({ target, line }) => {
10165
- const resolved = import_node_path14.posix.normalize(import_node_path14.posix.join(base, target));
10166
- return { target, line, resolved, missing: !exists((0, import_node_path14.join)(root, resolved)) };
10199
+ const resolved = import_node_path15.posix.normalize(import_node_path15.posix.join(base, target));
10200
+ return { target, line, resolved, missing: !exists((0, import_node_path15.join)(root, resolved)) };
10167
10201
  });
10168
10202
  for (const marker of markers) {
10169
10203
  const coversMissing = links.some(
10170
10204
  (l) => l.missing && (l.resolved === marker.docRel || l.resolved === marker.rootRel)
10171
10205
  );
10172
- if (!coversMissing && (exists((0, import_node_path14.join)(root, marker.docRel)) || exists((0, import_node_path14.join)(root, marker.rootRel)))) {
10206
+ if (!coversMissing && (exists((0, import_node_path15.join)(root, marker.docRel)) || exists((0, import_node_path15.join)(root, marker.rootRel)))) {
10173
10207
  direct.push({
10174
10208
  kind: "stale-forward-ref",
10175
10209
  doc,
@@ -10180,7 +10214,7 @@ function checkRefs(root, deps, docs2) {
10180
10214
  }
10181
10215
  for (const { ref, line } of extractRefs(markdown)) {
10182
10216
  if (!firstVerifiable(refFirstSegment(ref))) continue;
10183
- if (!exists((0, import_node_path14.join)(root, ref))) candidates.push({ kind: "missing-path", doc, line, detail: ref });
10217
+ if (!exists((0, import_node_path15.join)(root, ref))) candidates.push({ kind: "missing-path", doc, line, detail: ref });
10184
10218
  }
10185
10219
  for (const { target, line, resolved, missing } of links) {
10186
10220
  if (resolved.startsWith("..")) {
@@ -10228,22 +10262,22 @@ function checkCommands(docs2, commandPaths) {
10228
10262
  return { ok: findings.length === 0, findings, warnings: [] };
10229
10263
  }
10230
10264
  function readFileOrNull(path2) {
10231
- return (0, import_node_fs15.existsSync)(path2) ? (0, import_node_fs15.readFileSync)(path2, "utf8") : null;
10265
+ return (0, import_node_fs16.existsSync)(path2) ? (0, import_node_fs16.readFileSync)(path2, "utf8") : null;
10232
10266
  }
10233
10267
  function walk(dir, root, out) {
10234
- for (const entry of (0, import_node_fs15.readdirSync)(dir)) {
10235
- const full = (0, import_node_path14.join)(dir, entry);
10236
- if ((0, import_node_fs15.statSync)(full).isDirectory()) walk(full, root, out);
10268
+ for (const entry of (0, import_node_fs16.readdirSync)(dir)) {
10269
+ const full = (0, import_node_path15.join)(dir, entry);
10270
+ if ((0, import_node_fs16.statSync)(full).isDirectory()) walk(full, root, out);
10237
10271
  else if (entry.endsWith(".md")) out.push(full.slice(root.length + 1).replaceAll("\\", "/"));
10238
10272
  }
10239
10273
  return out;
10240
10274
  }
10241
10275
  function defaultListDocs(root) {
10242
- const docsDir = (0, import_node_path14.join)(root, "docs");
10243
- const docs2 = ((0, import_node_fs15.existsSync)(docsDir) ? walk(docsDir, root, []) : []).filter(
10276
+ const docsDir = (0, import_node_path15.join)(root, "docs");
10277
+ const docs2 = ((0, import_node_fs16.existsSync)(docsDir) ? walk(docsDir, root, []) : []).filter(
10244
10278
  (rel) => !SKIP_WALK.some((skip) => rel.startsWith(skip))
10245
10279
  );
10246
- return [...ROOT_DOCS.filter((rel) => (0, import_node_fs15.existsSync)((0, import_node_path14.join)(root, rel))), ...docs2];
10280
+ return [...ROOT_DOCS.filter((rel) => (0, import_node_fs16.existsSync)((0, import_node_path15.join)(root, rel))), ...docs2];
10247
10281
  }
10248
10282
  var CHECK_IGNORE_MAX_BUFFER = 32 * 1024 * 1024;
10249
10283
  function defaultIsIgnored(root, relPaths, exec = import_node_child_process5.execFileSync) {
@@ -10295,7 +10329,7 @@ function defaultTrackedFirstSegments(root, firstSegments, exec = import_node_chi
10295
10329
  }
10296
10330
  function runDocRefs(root, deps = {}) {
10297
10331
  const readFile9 = deps.readFile ?? readFileOrNull;
10298
- const exists = deps.exists ?? import_node_fs15.existsSync;
10332
+ const exists = deps.exists ?? import_node_fs16.existsSync;
10299
10333
  const listDocs = deps.listDocs ?? defaultListDocs;
10300
10334
  const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
10301
10335
  const trackedFirstSegments = deps.trackedFirstSegments ?? ((segs) => defaultTrackedFirstSegments(root, segs));
@@ -10303,7 +10337,7 @@ function runDocRefs(root, deps = {}) {
10303
10337
  const walked = listDocs(root);
10304
10338
  const ignoredDocs = walked.length ? isIgnored(walked) : /* @__PURE__ */ new Set();
10305
10339
  const docs2 = Object.fromEntries(
10306
- walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile9((0, import_node_path14.join)(root, rel))]).filter(([, body]) => body != null)
10340
+ walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile9((0, import_node_path15.join)(root, rel))]).filter(([, body]) => body != null)
10307
10341
  );
10308
10342
  const refResult = checkRefs(root, { exists, isIgnored, trackedFirstSegments }, docs2);
10309
10343
  const findings = [
@@ -10410,31 +10444,31 @@ function walkMarkdown(dir) {
10410
10444
  const stack = [dir];
10411
10445
  while (stack.length) {
10412
10446
  const current = stack.pop();
10413
- for (const entry of (0, import_node_fs16.readdirSync)(current, { withFileTypes: true })) {
10414
- const full = (0, import_node_path15.join)(current, entry.name);
10447
+ for (const entry of (0, import_node_fs17.readdirSync)(current, { withFileTypes: true })) {
10448
+ const full = (0, import_node_path16.join)(current, entry.name);
10415
10449
  if (entry.isDirectory()) {
10416
10450
  stack.push(full);
10417
10451
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
10418
- out.push((0, import_node_path15.relative)(dir, full).split(import_node_path15.sep).join("/"));
10452
+ out.push((0, import_node_path16.relative)(dir, full).split(import_node_path16.sep).join("/"));
10419
10453
  }
10420
10454
  }
10421
10455
  }
10422
10456
  return out;
10423
10457
  }
10424
10458
  function createDocsIndexDeps(repoRoot2) {
10425
- const docsDir = (0, import_node_path15.join)(repoRoot2, "docs");
10426
- const indexPath = (0, import_node_path15.join)(repoRoot2, DOCS_INDEX_PATH);
10459
+ const docsDir = (0, import_node_path16.join)(repoRoot2, "docs");
10460
+ const indexPath = (0, import_node_path16.join)(repoRoot2, DOCS_INDEX_PATH);
10427
10461
  return {
10428
10462
  listDocs: () => {
10429
- if (!(0, import_node_fs16.existsSync)(docsDir)) return [];
10463
+ if (!(0, import_node_fs17.existsSync)(docsDir)) return [];
10430
10464
  const walked = walkMarkdown(docsDir).filter(isRoutableDocsPath);
10431
10465
  if (!walked.length) return [];
10432
10466
  const ignored = defaultIsIgnored(repoRoot2, walked.map((rel) => `docs/${rel}`));
10433
10467
  return walked.filter((rel) => !ignored.has(`docs/${rel}`)).sort();
10434
10468
  },
10435
- readDoc: (relPath) => (0, import_node_fs16.readFileSync)((0, import_node_path15.join)(docsDir, relPath), "utf8"),
10436
- readIndex: () => (0, import_node_fs16.existsSync)(indexPath) ? (0, import_node_fs16.readFileSync)(indexPath, "utf8") : null,
10437
- writeIndex: (content) => (0, import_node_fs16.writeFileSync)(indexPath, content, "utf8")
10469
+ readDoc: (relPath) => (0, import_node_fs17.readFileSync)((0, import_node_path16.join)(docsDir, relPath), "utf8"),
10470
+ readIndex: () => (0, import_node_fs17.existsSync)(indexPath) ? (0, import_node_fs17.readFileSync)(indexPath, "utf8") : null,
10471
+ writeIndex: (content) => (0, import_node_fs17.writeFileSync)(indexPath, content, "utf8")
10438
10472
  };
10439
10473
  }
10440
10474
 
@@ -11219,14 +11253,14 @@ function parseVerifyBroker(stdout) {
11219
11253
  }
11220
11254
 
11221
11255
  // src/train-apply.ts
11222
- var import_node_fs20 = require("node:fs");
11256
+ var import_node_fs21 = require("node:fs");
11223
11257
  var import_promises4 = require("node:fs/promises");
11224
- var import_node_path19 = require("node:path");
11258
+ var import_node_path20 = require("node:path");
11225
11259
 
11226
11260
  // src/plugin-guard-io.ts
11227
- var import_node_fs17 = require("node:fs");
11261
+ var import_node_fs18 = require("node:fs");
11228
11262
  var import_node_child_process7 = require("node:child_process");
11229
- var import_node_path16 = require("node:path");
11263
+ var import_node_path17 = require("node:path");
11230
11264
  var import_node_os5 = require("node:os");
11231
11265
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
11232
11266
 
@@ -11529,21 +11563,21 @@ function runHostBin(bin, args, opts) {
11529
11563
  return step ? execFileHard(file, argv, { ...shared, step }) : execFileP2(file, argv, shared);
11530
11564
  }
11531
11565
  function surfaceConfigRoot(surface, env = process.env, home = (0, import_node_os5.homedir)()) {
11532
- if (surface === "codex") return env.CODEX_HOME?.trim() || (0, import_node_path16.join)(home, ".codex");
11533
- if (surface === "kimi") return env.KIMI_CODE_HOME?.trim() || (0, import_node_path16.join)(home, ".kimi-code");
11534
- if (surface === "kilo") return env.KILO_CONFIG_DIR?.trim() || (0, import_node_path16.join)(home, ".config", "kilo");
11535
- if (surface === "cursor") return (0, import_node_path16.join)(home, ".cursor");
11566
+ if (surface === "codex") return env.CODEX_HOME?.trim() || (0, import_node_path17.join)(home, ".codex");
11567
+ if (surface === "kimi") return env.KIMI_CODE_HOME?.trim() || (0, import_node_path17.join)(home, ".kimi-code");
11568
+ if (surface === "kilo") return env.KILO_CONFIG_DIR?.trim() || (0, import_node_path17.join)(home, ".config", "kilo");
11569
+ if (surface === "cursor") return (0, import_node_path17.join)(home, ".cursor");
11536
11570
  if (surface === "jervcode") {
11537
- return env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim() || (0, import_node_path16.join)(home, ".jerv", "agent");
11571
+ return env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim() || (0, import_node_path17.join)(home, ".jerv", "agent");
11538
11572
  }
11539
- return (0, import_node_path16.join)(home, ".claude");
11573
+ return (0, import_node_path17.join)(home, ".claude");
11540
11574
  }
11541
11575
  var installedPluginsPath = (surface = detectSurface(process.env)) => {
11542
- return (0, import_node_path16.join)(surfaceConfigRoot(surface), "plugins", "installed_plugins.json");
11576
+ return (0, import_node_path17.join)(surfaceConfigRoot(surface), "plugins", "installed_plugins.json");
11543
11577
  };
11544
11578
  function readInstalledPlugins(surface = detectSurface(process.env)) {
11545
11579
  try {
11546
- return JSON.parse((0, import_node_fs17.readFileSync)(installedPluginsPath(surface), "utf8"));
11580
+ return JSON.parse((0, import_node_fs18.readFileSync)(installedPluginsPath(surface), "utf8"));
11547
11581
  } catch {
11548
11582
  return null;
11549
11583
  }
@@ -11552,17 +11586,17 @@ function marketplaceCloneCandidates(surface, home, env = process.env) {
11552
11586
  if (surface === "codex") {
11553
11587
  const root = surfaceConfigRoot(surface, env, home);
11554
11588
  return [
11555
- (0, import_node_path16.join)(root, ".tmp", "marketplaces", CODEX_MARKETPLACE),
11556
- (0, import_node_path16.join)(root, "plugins", "marketplaces", CODEX_MARKETPLACE)
11589
+ (0, import_node_path17.join)(root, ".tmp", "marketplaces", CODEX_MARKETPLACE),
11590
+ (0, import_node_path17.join)(root, "plugins", "marketplaces", CODEX_MARKETPLACE)
11557
11591
  ];
11558
11592
  }
11559
11593
  if (surface === "kimi") return [];
11560
11594
  if (surface === "kilo") return [];
11561
11595
  if (surface === "cursor") return [];
11562
11596
  if (surface === "jervcode") return [];
11563
- return [(0, import_node_path16.join)(home, ".claude", "plugins", "marketplaces", "mutmutco")];
11597
+ return [(0, import_node_path17.join)(home, ".claude", "plugins", "marketplaces", "mutmutco")];
11564
11598
  }
11565
- function marketplaceClonePresent(surface, home, exists = import_node_fs17.existsSync, env = process.env) {
11599
+ function marketplaceClonePresent(surface, home, exists = import_node_fs18.existsSync, env = process.env) {
11566
11600
  return marketplaceCloneCandidates(surface, home, env).some(exists);
11567
11601
  }
11568
11602
  function runHostBinSync(bin, args) {
@@ -11594,7 +11628,7 @@ function codexPluginStatus() {
11594
11628
  }
11595
11629
  function countCodexHookCommands(path2) {
11596
11630
  try {
11597
- const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
11631
+ const parsed = JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
11598
11632
  let count = 0;
11599
11633
  for (const groups of Object.values(parsed.hooks ?? {})) {
11600
11634
  for (const group of groups) {
@@ -11611,11 +11645,11 @@ function codexHookTrustState(status = codexPluginStatus()) {
11611
11645
  return { applicable: false, trusted: false, trustedCount: 0, requiredCount: 0 };
11612
11646
  }
11613
11647
  const root = surfaceConfigRoot("codex");
11614
- const hooksPath = (0, import_node_path16.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", status.version, "hooks", "codex-hooks.json");
11648
+ const hooksPath = (0, import_node_path17.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", status.version, "hooks", "codex-hooks.json");
11615
11649
  const requiredCount = countCodexHookCommands(hooksPath);
11616
11650
  let config = "";
11617
11651
  try {
11618
- config = (0, import_node_fs17.readFileSync)((0, import_node_path16.join)(root, "config.toml"), "utf8");
11652
+ config = (0, import_node_fs18.readFileSync)((0, import_node_path17.join)(root, "config.toml"), "utf8");
11619
11653
  } catch {
11620
11654
  return { applicable: true, trusted: false, trustedCount: 0, requiredCount };
11621
11655
  }
@@ -11640,14 +11674,21 @@ async function fetchNpmReleasedVersion() {
11640
11674
  }
11641
11675
  var NPM_INSTALL_TIMEOUT_MS = 12e4;
11642
11676
  var CLI_VERSION_PROBE_TIMEOUT_MS = 3e4;
11677
+ function resolveNpmSpawn(args) {
11678
+ if (!isWin) return { file: "npm", args };
11679
+ const cli = (0, import_node_path17.join)((0, import_node_path17.dirname)(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
11680
+ if ((0, import_node_fs18.existsSync)(cli)) return { file: process.execPath, args: [cli, ...args] };
11681
+ return { file: "cmd.exe", args: ["/c", "npm", ...args] };
11682
+ }
11643
11683
  async function npmSelfUpdateCli(target, onStep, deps = {}) {
11644
11684
  const command = cliUpdateCommand(target);
11645
11685
  const args = npmSelfUpdateArgs(`@mutmutco/cli@${target ?? "latest"}`);
11646
11686
  onStep?.(command);
11647
11687
  let last = "";
11688
+ const spawnSpec = resolveNpmSpawn(args);
11648
11689
  const result = await (deps.run ?? runNpmStreaming)({
11649
- file: isWin ? "cmd.exe" : "npm",
11650
- args: isWin ? ["/c", "npm", ...args] : args,
11690
+ file: spawnSpec.file,
11691
+ args: spawnSpec.args,
11651
11692
  timeoutMs: NPM_INSTALL_TIMEOUT_MS,
11652
11693
  onLine: (line) => {
11653
11694
  const message = narrateNpmLine(line);
@@ -11662,11 +11703,11 @@ async function npmSelfUpdateCli(target, onStep, deps = {}) {
11662
11703
  onStep?.(verified.detail, { alwaysShow: true });
11663
11704
  return verified.ok ? { ok: true, detail: `${command} exited 0 \u2014 ${verified.detail}` } : { ok: false, detail: `${command} exited 0 but ${verified.detail}` };
11664
11705
  }
11665
- function kiloConfigListsPlugin(configRoot, home = (0, import_node_os5.homedir)(), read = (p) => (0, import_node_fs17.readFileSync)(p, "utf8"), exists = import_node_fs17.existsSync) {
11706
+ function kiloConfigListsPlugin(configRoot, home = (0, import_node_os5.homedir)(), read = (p) => (0, import_node_fs18.readFileSync)(p, "utf8"), exists = import_node_fs18.existsSync) {
11666
11707
  const candidates = ["kilo.json", "kilo.jsonc", "opencode.json", "opencode.jsonc", "config.json"];
11667
- for (const dir of [configRoot, (0, import_node_path16.join)(home, ".kilo")]) {
11708
+ for (const dir of [configRoot, (0, import_node_path17.join)(home, ".kilo")]) {
11668
11709
  for (const file of candidates) {
11669
- const path2 = (0, import_node_path16.join)(dir, file);
11710
+ const path2 = (0, import_node_path17.join)(dir, file);
11670
11711
  if (!exists(path2)) continue;
11671
11712
  try {
11672
11713
  const stripped = read(path2).replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
@@ -11683,23 +11724,23 @@ function kiloConfigListsPlugin(configRoot, home = (0, import_node_os5.homedir)()
11683
11724
  return false;
11684
11725
  }
11685
11726
  function cursorLocalPluginRoot(env = process.env, home = (0, import_node_os5.homedir)()) {
11686
- return (0, import_node_path16.join)(surfaceConfigRoot("cursor", env, home), "plugins", "local", "mmi");
11727
+ return (0, import_node_path17.join)(surfaceConfigRoot("cursor", env, home), "plugins", "local", "mmi");
11687
11728
  }
11688
- function cursorPluginTreeHealthy(root, exists = import_node_fs17.existsSync) {
11729
+ function cursorPluginTreeHealthy(root, exists = import_node_fs18.existsSync) {
11689
11730
  return [
11690
11731
  ".cursor-plugin/plugin.json",
11691
11732
  "skills/mmi/SKILL.md",
11692
11733
  "hooks/cursor-hooks.json",
11693
11734
  "scripts/hook-run.mjs",
11694
11735
  "scripts/hook-policy.mjs"
11695
- ].every((path2) => exists((0, import_node_path16.join)(root, ...path2.split("/"))));
11736
+ ].every((path2) => exists((0, import_node_path17.join)(root, ...path2.split("/"))));
11696
11737
  }
11697
- function kimiPluginTreeHealthy(root, exists = import_node_fs17.existsSync) {
11738
+ function kimiPluginTreeHealthy(root, exists = import_node_fs18.existsSync) {
11698
11739
  return [
11699
11740
  ".kimi-plugin/plugin.json",
11700
11741
  "skills/mmi/SKILL.md",
11701
11742
  "scripts/hook-run.mjs"
11702
- ].every((path2) => exists((0, import_node_path16.join)(root, ...path2.split("/"))));
11743
+ ].every((path2) => exists((0, import_node_path17.join)(root, ...path2.split("/"))));
11703
11744
  }
11704
11745
  var JERVCODE_WRAPPER_DIR = ".pi-plugin";
11705
11746
  function normalizePiEntry(value) {
@@ -11722,7 +11763,7 @@ function jervcodePackageFamily(entry) {
11722
11763
  function isMmiOwnedPiEntry(entry) {
11723
11764
  if (typeof entry !== "string") return false;
11724
11765
  try {
11725
- const pkg = JSON.parse((0, import_node_fs17.readFileSync)((0, import_node_path16.join)(piEntryFsPath(entry), "package.json"), "utf8"));
11766
+ const pkg = JSON.parse((0, import_node_fs18.readFileSync)((0, import_node_path17.join)(piEntryFsPath(entry), "package.json"), "utf8"));
11726
11767
  return pkg.name === "mmi";
11727
11768
  } catch {
11728
11769
  return false;
@@ -11744,9 +11785,9 @@ function mergeMmiPiPackageEntries(entries, packagePath) {
11744
11785
  };
11745
11786
  }
11746
11787
  function readPiSettings(path2) {
11747
- if (!(0, import_node_fs17.existsSync)(path2)) return void 0;
11788
+ if (!(0, import_node_fs18.existsSync)(path2)) return void 0;
11748
11789
  try {
11749
- const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
11790
+ const parsed = JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
11750
11791
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
11751
11792
  return parsed;
11752
11793
  } catch {
@@ -11754,8 +11795,8 @@ function readPiSettings(path2) {
11754
11795
  }
11755
11796
  }
11756
11797
  function jervcodeSettingsCandidates(env = process.env, home = (0, import_node_os5.homedir)()) {
11757
- const primary = (0, import_node_path16.join)(surfaceConfigRoot("jervcode", env, home), "settings.json");
11758
- const legacy = (0, import_node_path16.join)(home, ".pi", "agent", "settings.json");
11798
+ const primary = (0, import_node_path17.join)(surfaceConfigRoot("jervcode", env, home), "settings.json");
11799
+ const legacy = (0, import_node_path17.join)(home, ".pi", "agent", "settings.json");
11759
11800
  return legacy === primary ? [primary] : [primary, legacy];
11760
11801
  }
11761
11802
  function mmiPiWrapperEntry(env = process.env, home = (0, import_node_os5.homedir)()) {
@@ -11774,17 +11815,17 @@ function mmiPiWrapperEntry(env = process.env, home = (0, import_node_os5.homedir
11774
11815
  function mmiPiWrapperHealthy(entry) {
11775
11816
  if (!entry) return false;
11776
11817
  const wrapper = piEntryFsPath(entry);
11777
- return isMmiOwnedPiEntry(entry) && (0, import_node_fs17.existsSync)((0, import_node_path16.join)((0, import_node_path16.dirname)(wrapper), "skills", "mmi", "SKILL.md"));
11818
+ return isMmiOwnedPiEntry(entry) && (0, import_node_fs18.existsSync)((0, import_node_path17.join)((0, import_node_path17.dirname)(wrapper), "skills", "mmi", "SKILL.md"));
11778
11819
  }
11779
11820
  function findMmiPiSourceClone(home = (0, import_node_os5.homedir)()) {
11780
- const cacheRoot = (0, import_node_path16.join)(home, ".claude", "plugins", "cache", "mutmutco", "mmi");
11821
+ const cacheRoot = (0, import_node_path17.join)(home, ".claude", "plugins", "cache", "mutmutco", "mmi");
11781
11822
  let best = null;
11782
11823
  try {
11783
- for (const entry of (0, import_node_fs17.readdirSync)(cacheRoot, { withFileTypes: true })) {
11824
+ for (const entry of (0, import_node_fs18.readdirSync)(cacheRoot, { withFileTypes: true })) {
11784
11825
  if (!entry.isDirectory() || !/^\d+\.\d+\.\d+$/.test(entry.name)) continue;
11785
- if (!(0, import_node_fs17.existsSync)((0, import_node_path16.join)(cacheRoot, entry.name, JERVCODE_WRAPPER_DIR, "package.json"))) continue;
11826
+ if (!(0, import_node_fs18.existsSync)((0, import_node_path17.join)(cacheRoot, entry.name, JERVCODE_WRAPPER_DIR, "package.json"))) continue;
11786
11827
  if (!best || compareVersions(entry.name, best.version) > 0) {
11787
- best = { path: (0, import_node_path16.join)(cacheRoot, entry.name), version: entry.name };
11828
+ best = { path: (0, import_node_path17.join)(cacheRoot, entry.name), version: entry.name };
11788
11829
  }
11789
11830
  }
11790
11831
  } catch {
@@ -11809,8 +11850,8 @@ function acquirePiSettingsLock(settingsPath2) {
11809
11850
  return void 0;
11810
11851
  }
11811
11852
  function healOneJervCodeSettingsFile(settingsPath2, packagePath, version, nextLaunch) {
11812
- const release = (0, import_node_fs17.existsSync)(settingsPath2) ? acquirePiSettingsLock(settingsPath2) : void 0;
11813
- if ((0, import_node_fs17.existsSync)(settingsPath2) && !release) {
11853
+ const release = (0, import_node_fs18.existsSync)(settingsPath2) ? acquirePiSettingsLock(settingsPath2) : void 0;
11854
+ if ((0, import_node_fs18.existsSync)(settingsPath2) && !release) {
11814
11855
  return {
11815
11856
  available: true,
11816
11857
  ok: false,
@@ -11838,14 +11879,14 @@ function healOneJervCodeSettingsFile(settingsPath2, packagePath, version, nextLa
11838
11879
  }
11839
11880
  current.packages = merged.next;
11840
11881
  try {
11841
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(settingsPath2), { recursive: true });
11882
+ (0, import_node_fs18.mkdirSync)((0, import_node_path17.dirname)(settingsPath2), { recursive: true });
11842
11883
  const tmp = `${settingsPath2}.tmp-${process.pid}`;
11843
- (0, import_node_fs17.writeFileSync)(tmp, `${JSON.stringify(current, null, 2)}
11884
+ (0, import_node_fs18.writeFileSync)(tmp, `${JSON.stringify(current, null, 2)}
11844
11885
  `, "utf8");
11845
11886
  try {
11846
- (0, import_node_fs17.renameSync)(tmp, settingsPath2);
11887
+ (0, import_node_fs18.renameSync)(tmp, settingsPath2);
11847
11888
  } catch (renameError) {
11848
- (0, import_node_fs17.rmSync)(tmp, { force: true });
11889
+ (0, import_node_fs18.rmSync)(tmp, { force: true });
11849
11890
  throw renameError;
11850
11891
  }
11851
11892
  } catch (error) {
@@ -11869,8 +11910,8 @@ function healJervCodePackageRegistration(opts = {}) {
11869
11910
  const nextLaunch = inSeat ? " \u2014 takes effect on the next seat launch" : "";
11870
11911
  const home = opts.home ?? (0, import_node_os5.homedir)();
11871
11912
  const agentDir = surfaceConfigRoot("jervcode", env, home);
11872
- const legacyPi = (0, import_node_path16.join)(home, ".pi", "agent");
11873
- if (!(0, import_node_fs17.existsSync)(agentDir) && !(0, import_node_fs17.existsSync)(legacyPi)) {
11913
+ const legacyPi = (0, import_node_path17.join)(home, ".pi", "agent");
11914
+ if (!(0, import_node_fs18.existsSync)(agentDir) && !(0, import_node_fs18.existsSync)(legacyPi)) {
11874
11915
  return { available: false, ok: true, changed: false, version: null, detail: "skipped \u2014 no Pi/JervCode install (no agent config dir)" };
11875
11916
  }
11876
11917
  const clone = opts.clone === void 0 ? findMmiPiSourceClone(home) : opts.clone;
@@ -11878,9 +11919,9 @@ function healJervCodePackageRegistration(opts = {}) {
11878
11919
  return { available: true, ok: true, changed: false, version: null, detail: "skipped \u2014 no installed MMI clone carries the pi wrapper (install the Claude plugin first)" };
11879
11920
  }
11880
11921
  const packagePath = `${clone.path.replace(/\\/g, "/").replace(/\/+$/, "")}/${JERVCODE_WRAPPER_DIR}`;
11881
- const targets = [(0, import_node_path16.join)(agentDir, "settings.json")];
11882
- const legacySettings = (0, import_node_path16.join)(legacyPi, "settings.json");
11883
- if ((0, import_node_fs17.existsSync)(legacyPi) && legacySettings !== targets[0]) targets.push(legacySettings);
11922
+ const targets = [(0, import_node_path17.join)(agentDir, "settings.json")];
11923
+ const legacySettings = (0, import_node_path17.join)(legacyPi, "settings.json");
11924
+ if ((0, import_node_fs18.existsSync)(legacyPi) && legacySettings !== targets[0]) targets.push(legacySettings);
11884
11925
  const details = [];
11885
11926
  let anyChanged = false;
11886
11927
  for (const settingsPath2 of targets) {
@@ -11908,18 +11949,18 @@ function snapshotPluginGuardInput(surface = detectSurface(process.env), isOrgRep
11908
11949
  return {
11909
11950
  isOrgRepo,
11910
11951
  installRecordPresent: hasUserInstallRecord(installed, MMI_PLUGIN_ID) || hasProjectInstallRecord(installed, MMI_PLUGIN_ID, process.cwd()) || // Kimi's managed plugin directory is its native install record; it has no Claude-style ledger.
11911
- surface === "kimi" && (0, import_node_fs17.existsSync)((0, import_node_path16.join)(root, "plugins", "managed", "mmi")) || // kilo-p1: the install record is the config file itself.
11952
+ surface === "kimi" && (0, import_node_fs18.existsSync)((0, import_node_path17.join)(root, "plugins", "managed", "mmi")) || // kilo-p1: the install record is the config file itself.
11912
11953
  surface === "kilo" && kiloConfigListsPlugin(root) || // #4188: jervcode's install record is the settings-file packages[] entry itself.
11913
- surface === "jervcode" && piEntry !== null || surface === "cursor" && (0, import_node_fs17.existsSync)(cursorLocalPluginRoot()),
11954
+ surface === "jervcode" && piEntry !== null || surface === "cursor" && (0, import_node_fs18.existsSync)(cursorLocalPluginRoot()),
11914
11955
  // Kilo has no marketplace to clone — the config file IS the install record, so this dimension of
11915
11956
  // the shared guard table is vacuously satisfied. Same for jervcode's settings entry.
11916
11957
  marketplaceClonePresent: surface === "kimi" || surface === "kilo" || surface === "cursor" || surface === "jervcode" ? true : marketplaceClonePresent(surface, (0, import_node_os5.homedir)()),
11917
11958
  // Kimi keeps no plugin cache dir — installs are copied to plugins/managed/<id> and run from there.
11918
11959
  // Kilo (kilo-p1) keeps no cache dir either: the plugin's server() provisions ~/.kilo behind the
11919
11960
  // version stamp, so the stamp's presence is the cache signal.
11920
- pluginCachePresent: surface === "jervcode" ? mmiPiWrapperHealthy(piEntry) : surface === "kilo" ? (0, import_node_fs17.existsSync)((0, import_node_path16.join)((0, import_node_os5.homedir)(), ".kilo", ".mmi-kilo-version")) : surface === "kimi" ? kimiPluginTreeHealthy((0, import_node_path16.join)(root, "plugins", "managed", "mmi")) : surface === "cursor" ? cursorPluginTreeHealthy(cursorLocalPluginRoot()) : surface === "codex" ? Boolean(
11921
- codexStatus?.installed && codexStatus.enabled && codexStatus.version && (0, import_node_fs17.existsSync)((0, import_node_path16.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", codexStatus.version))
11922
- ) : (0, import_node_fs17.existsSync)((0, import_node_path16.join)(root, "plugins", "cache", "mutmutco", "mmi"))
11961
+ pluginCachePresent: surface === "jervcode" ? mmiPiWrapperHealthy(piEntry) : surface === "kilo" ? (0, import_node_fs18.existsSync)((0, import_node_path17.join)((0, import_node_os5.homedir)(), ".kilo", ".mmi-kilo-version")) : surface === "kimi" ? kimiPluginTreeHealthy((0, import_node_path17.join)(root, "plugins", "managed", "mmi")) : surface === "cursor" ? cursorPluginTreeHealthy(cursorLocalPluginRoot()) : surface === "codex" ? Boolean(
11962
+ codexStatus?.installed && codexStatus.enabled && codexStatus.version && (0, import_node_fs18.existsSync)((0, import_node_path17.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", codexStatus.version))
11963
+ ) : (0, import_node_fs18.existsSync)((0, import_node_path17.join)(root, "plugins", "cache", "mutmutco", "mmi"))
11923
11964
  };
11924
11965
  }
11925
11966
  async function runHostBinLogged(bin, args, opts) {
@@ -11939,11 +11980,11 @@ async function runPluginCli(bin, args, log) {
11939
11980
  function captureCodexHookLauncher() {
11940
11981
  const status = codexPluginStatus();
11941
11982
  if (!status.installed || !status.enabled || !status.version) return void 0;
11942
- const root = (0, import_node_path16.join)(surfaceConfigRoot("codex"), "plugins", "cache", CODEX_MARKETPLACE, "mmi", status.version);
11983
+ const root = (0, import_node_path17.join)(surfaceConfigRoot("codex"), "plugins", "cache", CODEX_MARKETPLACE, "mmi", status.version);
11943
11984
  const files = ["mmi-hook", "mmi-hook.exe"].flatMap((name) => {
11944
- const path2 = (0, import_node_path16.join)(root, "bin", name);
11985
+ const path2 = (0, import_node_path17.join)(root, "bin", name);
11945
11986
  try {
11946
- return [{ name, content: (0, import_node_fs17.readFileSync)(path2) }];
11987
+ return [{ name, content: (0, import_node_fs18.readFileSync)(path2) }];
11947
11988
  } catch {
11948
11989
  return [];
11949
11990
  }
@@ -11951,13 +11992,13 @@ function captureCodexHookLauncher() {
11951
11992
  return files.length === 2 ? { root, files } : void 0;
11952
11993
  }
11953
11994
  function restoreCodexHookLauncher(snapshot) {
11954
- if (!snapshot || (0, import_node_fs17.existsSync)((0, import_node_path16.join)(snapshot.root, "scripts", "hook-run.mjs"))) return false;
11955
- const bin = (0, import_node_path16.join)(snapshot.root, "bin");
11956
- (0, import_node_fs17.mkdirSync)(bin, { recursive: true });
11995
+ if (!snapshot || (0, import_node_fs18.existsSync)((0, import_node_path17.join)(snapshot.root, "scripts", "hook-run.mjs"))) return false;
11996
+ const bin = (0, import_node_path17.join)(snapshot.root, "bin");
11997
+ (0, import_node_fs18.mkdirSync)(bin, { recursive: true });
11957
11998
  for (const file of snapshot.files) {
11958
- const path2 = (0, import_node_path16.join)(bin, file.name);
11959
- (0, import_node_fs17.writeFileSync)(path2, file.content);
11960
- if (file.name === "mmi-hook") (0, import_node_fs17.chmodSync)(path2, 493);
11999
+ const path2 = (0, import_node_path17.join)(bin, file.name);
12000
+ (0, import_node_fs18.writeFileSync)(path2, file.content);
12001
+ if (file.name === "mmi-hook") (0, import_node_fs18.chmodSync)(path2, 493);
11961
12002
  }
11962
12003
  return true;
11963
12004
  }
@@ -11966,10 +12007,10 @@ function canonicalCursorRemote(remote) {
11966
12007
  }
11967
12008
  async function installCursorPluginCheckout(env = process.env) {
11968
12009
  const configRoot = surfaceConfigRoot("cursor", env);
11969
- const pluginsRoot = (0, import_node_path16.join)(configRoot, "plugins");
11970
- const target = (0, import_node_path16.join)(pluginsRoot, "local", "mmi");
12010
+ const pluginsRoot = (0, import_node_path17.join)(configRoot, "plugins");
12011
+ const target = (0, import_node_path17.join)(pluginsRoot, "local", "mmi");
11971
12012
  const source = env.MMI_CURSOR_PLUGIN_SOURCE?.trim();
11972
- if ((0, import_node_fs17.existsSync)(target) && !source) {
12013
+ if ((0, import_node_fs18.existsSync)(target) && !source) {
11973
12014
  try {
11974
12015
  const { stdout } = await runHostBin("git", ["-C", target, "remote", "get-url", "origin"], { timeout: 15e3 });
11975
12016
  if (!canonicalCursorRemote(stdout)) {
@@ -11979,15 +12020,15 @@ async function installCursorPluginCheckout(env = process.env) {
11979
12020
  return { ok: false, detail: `refused to replace unmanaged Cursor plugin directory at ${target}` };
11980
12021
  }
11981
12022
  }
11982
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.join)(pluginsRoot, "local"), { recursive: true });
11983
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.join)(pluginsRoot, "staging"), { recursive: true });
11984
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.join)(pluginsRoot, "quarantine"), { recursive: true });
12023
+ (0, import_node_fs18.mkdirSync)((0, import_node_path17.join)(pluginsRoot, "local"), { recursive: true });
12024
+ (0, import_node_fs18.mkdirSync)((0, import_node_path17.join)(pluginsRoot, "staging"), { recursive: true });
12025
+ (0, import_node_fs18.mkdirSync)((0, import_node_path17.join)(pluginsRoot, "quarantine"), { recursive: true });
11985
12026
  const suffix = `${Date.now()}-${process.pid}`;
11986
- const staged = (0, import_node_path16.join)(pluginsRoot, "staging", `mmi-${suffix}`);
11987
- const quarantined = (0, import_node_path16.join)(pluginsRoot, "quarantine", `mmi-${suffix}`);
12027
+ const staged = (0, import_node_path17.join)(pluginsRoot, "staging", `mmi-${suffix}`);
12028
+ const quarantined = (0, import_node_path17.join)(pluginsRoot, "quarantine", `mmi-${suffix}`);
11988
12029
  try {
11989
12030
  if (source) {
11990
- (0, import_node_fs17.cpSync)(source, staged, {
12031
+ (0, import_node_fs18.cpSync)(source, staged, {
11991
12032
  recursive: true,
11992
12033
  filter: (path2) => !path2.split(/[\\/]/).some((part) => part === ".git" || part === "node_modules")
11993
12034
  });
@@ -11998,18 +12039,18 @@ async function installCursorPluginCheckout(env = process.env) {
11998
12039
  });
11999
12040
  }
12000
12041
  if (!cursorPluginTreeHealthy(staged)) {
12001
- (0, import_node_fs17.rmSync)(staged, { recursive: true, force: true });
12042
+ (0, import_node_fs18.rmSync)(staged, { recursive: true, force: true });
12002
12043
  return { ok: false, detail: "downloaded Cursor plugin is incomplete; existing install was preserved" };
12003
12044
  }
12004
12045
  let movedOld = false;
12005
- if ((0, import_node_fs17.existsSync)(target)) {
12006
- (0, import_node_fs17.renameSync)(target, quarantined);
12046
+ if ((0, import_node_fs18.existsSync)(target)) {
12047
+ (0, import_node_fs18.renameSync)(target, quarantined);
12007
12048
  movedOld = true;
12008
12049
  }
12009
12050
  try {
12010
- (0, import_node_fs17.renameSync)(staged, target);
12051
+ (0, import_node_fs18.renameSync)(staged, target);
12011
12052
  } catch (error) {
12012
- if (movedOld && !(0, import_node_fs17.existsSync)(target)) (0, import_node_fs17.renameSync)(quarantined, target);
12053
+ if (movedOld && !(0, import_node_fs18.existsSync)(target)) (0, import_node_fs18.renameSync)(quarantined, target);
12013
12054
  throw error;
12014
12055
  }
12015
12056
  return {
@@ -12017,7 +12058,7 @@ async function installCursorPluginCheckout(env = process.env) {
12017
12058
  detail: movedOld ? `installed canonical Cursor plugin; previous checkout quarantined at ${quarantined}` : `installed canonical Cursor plugin at ${target}`
12018
12059
  };
12019
12060
  } catch (error) {
12020
- if ((0, import_node_fs17.existsSync)(staged)) (0, import_node_fs17.rmSync)(staged, { recursive: true, force: true });
12061
+ if ((0, import_node_fs18.existsSync)(staged)) (0, import_node_fs18.rmSync)(staged, { recursive: true, force: true });
12021
12062
  return { ok: false, detail: error.message.trim().slice(0, 240).replace(/\s+/g, " ") };
12022
12063
  }
12023
12064
  }
@@ -12067,7 +12108,7 @@ async function applyPluginHeal(surface, log, opts) {
12067
12108
  const refSupported = await marketplaceAddRefSupported(bin);
12068
12109
  const { steps } = adaptHealStepsForRefSupport(tableSteps, refSupported);
12069
12110
  log(healBannerLine(bin, token, refSupported));
12070
- const pinsPath = (0, import_node_path16.join)((0, import_node_os5.homedir)(), ...KNOWN_MARKETPLACES_RELATIVE);
12111
+ const pinsPath = (0, import_node_path17.join)((0, import_node_os5.homedir)(), ...KNOWN_MARKETPLACES_RELATIVE);
12071
12112
  const pins = token === "claude" ? captureMarketplacePins(readKnownMarketplacesFile(pinsPath), [MMI_MARKETPLACE_NAME, JERV_MARKETPLACE_NAME]) : /* @__PURE__ */ new Map();
12072
12113
  try {
12073
12114
  for (const step of steps) {
@@ -12142,7 +12183,7 @@ async function healActivePluginForDoctor(surface = detectSurface(process.env), o
12142
12183
  }
12143
12184
  function readKnownMarketplacesFile(path2) {
12144
12185
  try {
12145
- return (0, import_node_fs17.existsSync)(path2) ? (0, import_node_fs17.readFileSync)(path2, "utf8") : void 0;
12186
+ return (0, import_node_fs18.existsSync)(path2) ? (0, import_node_fs18.readFileSync)(path2, "utf8") : void 0;
12146
12187
  } catch {
12147
12188
  return void 0;
12148
12189
  }
@@ -12172,7 +12213,7 @@ function writeMarketplacePinsOnDisk(path2, pins, succeeded, failedVerb, declineW
12172
12213
  const declined = declineWhileHostLive?.();
12173
12214
  if (declined) return declined;
12174
12215
  try {
12175
- (0, import_node_fs17.writeFileSync)(path2, next, "utf8");
12216
+ (0, import_node_fs18.writeFileSync)(path2, next, "utf8");
12176
12217
  } catch {
12177
12218
  return `could NOT ${failedVerb} ${[...pins.keys()].join(", ")} \u2014 set it by hand`;
12178
12219
  }
@@ -12212,15 +12253,15 @@ function applyOrgMarketplacePins(path2, names, hostIsRunning = claudeCodeIsRunni
12212
12253
  }
12213
12254
  function writeMarketplacePinPending(path2, names, now = Date.now()) {
12214
12255
  try {
12215
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(path2), { recursive: true });
12216
- (0, import_node_fs17.writeFileSync)(path2, `${JSON.stringify({ v: 1, names: [...names], at: new Date(now).toISOString() })}
12256
+ (0, import_node_fs18.mkdirSync)((0, import_node_path17.dirname)(path2), { recursive: true });
12257
+ (0, import_node_fs18.writeFileSync)(path2, `${JSON.stringify({ v: 1, names: [...names], at: new Date(now).toISOString() })}
12217
12258
  `, "utf8");
12218
12259
  } catch {
12219
12260
  }
12220
12261
  }
12221
12262
  function readMarketplacePinPending(path2, name, now = Date.now()) {
12222
12263
  try {
12223
- const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
12264
+ const parsed = JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
12224
12265
  const at = typeof parsed.at === "string" ? Date.parse(parsed.at) : Number.NaN;
12225
12266
  if (parsed.v !== 1 || !Array.isArray(parsed.names) || !parsed.names.includes(name) || !Number.isFinite(at)) return void 0;
12226
12267
  if (now - at < 0 || now - at > 12 * 60 * 6e4) return void 0;
@@ -12778,9 +12819,9 @@ function renderAccessReport(report) {
12778
12819
  }
12779
12820
 
12780
12821
  // src/cli-doctor-shared.ts
12781
- var import_node_fs18 = require("node:fs");
12782
- var import_node_path18 = require("node:path");
12783
12822
  var import_node_fs19 = require("node:fs");
12823
+ var import_node_path19 = require("node:path");
12824
+ var import_node_fs20 = require("node:fs");
12784
12825
 
12785
12826
  // ../infra/registry-endpoints.mjs
12786
12827
  var PROJECTS_LIST_PATH = "/projects/list";
@@ -13694,7 +13735,7 @@ var import_node_os7 = require("node:os");
13694
13735
  // src/gh-create.ts
13695
13736
  var import_promises3 = require("node:fs/promises");
13696
13737
  var import_node_os6 = require("node:os");
13697
- var import_node_path17 = require("node:path");
13738
+ var import_node_path18 = require("node:path");
13698
13739
  var import_node_crypto3 = require("node:crypto");
13699
13740
 
13700
13741
  // src/board-priority.ts
@@ -13777,8 +13818,8 @@ async function bodyArgsViaFile(args, deps = {}) {
13777
13818
  const remove2 = deps.remove ?? import_promises3.unlink;
13778
13819
  const ensureDir = deps.ensureDir ?? import_promises3.mkdir;
13779
13820
  const dir = deps.dir ?? (0, import_node_os6.tmpdir)();
13780
- const file = (0, import_node_path17.join)(dir, `mmi-gh-body-${process.pid}-${(0, import_node_crypto3.randomBytes)(4).toString("hex")}.md`);
13781
- await ensureDir((0, import_node_path17.dirname)(file), { recursive: true }).catch(() => {
13821
+ const file = (0, import_node_path18.join)(dir, `mmi-gh-body-${process.pid}-${(0, import_node_crypto3.randomBytes)(4).toString("hex")}.md`);
13822
+ await ensureDir((0, import_node_path18.dirname)(file), { recursive: true }).catch(() => {
13782
13823
  });
13783
13824
  await write(file, args[i + 1], "utf8");
13784
13825
  return {
@@ -15321,7 +15362,7 @@ async function localBranchHeads() {
15321
15362
  }
15322
15363
  async function currentRepoWorktreeGitRoot(repoRoot2) {
15323
15364
  const gitCommonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
15324
- return gitCommonDir ? (0, import_node_path18.resolve)(repoRoot2, gitCommonDir, "worktrees") : "";
15365
+ return gitCommonDir ? (0, import_node_path19.resolve)(repoRoot2, gitCommonDir, "worktrees") : "";
15325
15366
  }
15326
15367
  async function worktreeBranches() {
15327
15368
  const { stdout } = await execFileP2("git", ["worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS });
@@ -15341,18 +15382,18 @@ function resolveGitdirForWorktreeFile(worktreePath, content) {
15341
15382
  const match = /^gitdir:\s*(.+)\s*$/im.exec(content);
15342
15383
  if (!match?.[1]) return void 0;
15343
15384
  const raw = match[1].trim();
15344
- return (0, import_node_path18.isAbsolute)(raw) ? raw : (0, import_node_path18.resolve)(worktreePath, raw);
15385
+ return (0, import_node_path19.isAbsolute)(raw) ? raw : (0, import_node_path19.resolve)(worktreePath, raw);
15345
15386
  }
15346
15387
  function metadataOwnsMissingWorktreeDir(worktreePath, worktreeGitRoot) {
15347
15388
  if (!worktreeGitRoot) return false;
15348
15389
  try {
15349
- const entries = (0, import_node_fs19.readdirSync)(worktreeGitRoot, { withFileTypes: true });
15390
+ const entries = (0, import_node_fs20.readdirSync)(worktreeGitRoot, { withFileTypes: true });
15350
15391
  for (const ent of entries) {
15351
15392
  if (!ent.isDirectory()) continue;
15352
15393
  try {
15353
- const gitdirPath = (0, import_node_fs18.readFileSync)((0, import_node_path18.join)(worktreeGitRoot, ent.name, "gitdir"), "utf8").trim();
15354
- const resolvedGitdir = (0, import_node_path18.isAbsolute)(gitdirPath) ? gitdirPath : (0, import_node_path18.resolve)(worktreeGitRoot, ent.name, gitdirPath);
15355
- if (sameWorktreeMetadataPath((0, import_node_path18.dirname)(resolvedGitdir), worktreePath)) return true;
15394
+ const gitdirPath = (0, import_node_fs19.readFileSync)((0, import_node_path19.join)(worktreeGitRoot, ent.name, "gitdir"), "utf8").trim();
15395
+ const resolvedGitdir = (0, import_node_path19.isAbsolute)(gitdirPath) ? gitdirPath : (0, import_node_path19.resolve)(worktreeGitRoot, ent.name, gitdirPath);
15396
+ if (sameWorktreeMetadataPath((0, import_node_path19.dirname)(resolvedGitdir), worktreePath)) return true;
15356
15397
  } catch {
15357
15398
  }
15358
15399
  }
@@ -15362,7 +15403,7 @@ function metadataOwnsMissingWorktreeDir(worktreePath, worktreeGitRoot) {
15362
15403
  }
15363
15404
  function pathExistsKnown(path2) {
15364
15405
  try {
15365
- (0, import_node_fs19.statSync)(path2);
15406
+ (0, import_node_fs20.statSync)(path2);
15366
15407
  return true;
15367
15408
  } catch (e) {
15368
15409
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
@@ -15371,10 +15412,10 @@ function pathExistsKnown(path2) {
15371
15412
  }
15372
15413
  }
15373
15414
  function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
15374
- const gitPath = (0, import_node_path18.join)(path2, ".git");
15415
+ const gitPath = (0, import_node_path19.join)(path2, ".git");
15375
15416
  let st;
15376
15417
  try {
15377
- st = (0, import_node_fs19.lstatSync)(gitPath);
15418
+ st = (0, import_node_fs20.lstatSync)(gitPath);
15378
15419
  } catch (e) {
15379
15420
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
15380
15421
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -15391,7 +15432,7 @@ function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
15391
15432
  if (st.isDirectory()) return { path: path2, gitType: "dir" };
15392
15433
  if (!st.isFile()) return { path: path2, gitType: "other" };
15393
15434
  try {
15394
- const gitFileContent = (0, import_node_fs18.readFileSync)(gitPath, "utf8");
15435
+ const gitFileContent = (0, import_node_fs19.readFileSync)(gitPath, "utf8");
15395
15436
  const gitdir = resolveGitdirForWorktreeFile(path2, gitFileContent);
15396
15437
  const gitDirExists = gitdir ? pathExistsKnown(gitdir) : false;
15397
15438
  return {
@@ -15408,7 +15449,7 @@ function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
15408
15449
  }
15409
15450
  function inspectDeadWorktreeDirContent(path2) {
15410
15451
  try {
15411
- return { entries: (0, import_node_fs19.readdirSync)(path2) };
15452
+ return { entries: (0, import_node_fs20.readdirSync)(path2) };
15412
15453
  } catch (e) {
15413
15454
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
15414
15455
  return { error: code ? `unable to inspect directory contents (${code})` : "unable to inspect directory contents" };
@@ -15425,7 +15466,7 @@ async function preservedBranches() {
15425
15466
  async function siblingWorktreeDirs(explicitRoot) {
15426
15467
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
15427
15468
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
15428
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path18.dirname)((0, import_node_path18.dirname)(worktreeGitRoot)) : repoRoot2;
15469
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path19.dirname)((0, import_node_path19.dirname)(worktreeGitRoot)) : repoRoot2;
15429
15470
  try {
15430
15471
  const dirs = explicitRoot ? listDirsIn(resolveExplicitScanRoot(explicitRoot, primaryRepoRoot)) : worktreeScanDirs(siblingMmiWorktreesRoot(primaryRepoRoot), primaryRepoRoot, listDirsIn, isRepoCheckoutDir);
15431
15472
  const agentDirs2 = listDirsIn(agentWorktreesRoot(primaryRepoRoot));
@@ -15436,18 +15477,18 @@ async function siblingWorktreeDirs(explicitRoot) {
15436
15477
  }
15437
15478
  function listDirsIn(dir) {
15438
15479
  try {
15439
- return (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => (0, import_node_path18.join)(dir, ent.name));
15480
+ return (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => (0, import_node_path19.join)(dir, ent.name));
15440
15481
  } catch {
15441
15482
  return [];
15442
15483
  }
15443
15484
  }
15444
15485
  function isRepoCheckoutDir(dir) {
15445
- return (0, import_node_fs19.existsSync)((0, import_node_path18.join)(dir, ".git"));
15486
+ return (0, import_node_fs20.existsSync)((0, import_node_path19.join)(dir, ".git"));
15446
15487
  }
15447
15488
  function resolveExplicitScanRoot(explicitRoot, repoRoot2) {
15448
15489
  let rootDirs;
15449
15490
  try {
15450
- rootDirs = (0, import_node_fs19.readdirSync)(explicitRoot, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => ent.name);
15491
+ rootDirs = (0, import_node_fs20.readdirSync)(explicitRoot, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => ent.name);
15451
15492
  } catch {
15452
15493
  return explicitRoot;
15453
15494
  }
@@ -15779,10 +15820,10 @@ var rollout_plan_default = {
15779
15820
  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)."
15780
15821
  },
15781
15822
  baseline: {
15782
- version: "3.117.0",
15783
- tag: "v3.117.0",
15784
- commit: "12488a5818a0",
15785
- npm: "@mutmutco/cli@3.117.0"
15823
+ version: "3.118.0",
15824
+ tag: "v3.118.0",
15825
+ commit: "4f9600d3bf89",
15826
+ npm: "@mutmutco/cli@3.118.0"
15786
15827
  },
15787
15828
  exitCriterion: "fleet-n-of-n",
15788
15829
  hubOnlyShortcut: "forbidden",
@@ -15799,14 +15840,14 @@ var rollout_plan_default = {
15799
15840
  repo: "mutmutco/mmi-hub",
15800
15841
  role: "canary",
15801
15842
  schedule: "train",
15802
- v3Target: "v3.117.0"
15843
+ v3Target: "v3.118.0"
15803
15844
  }
15804
15845
  ],
15805
15846
  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.",
15806
15847
  rollback: {
15807
15848
  independent: true,
15808
- mechanism: "npm dist-tag latest -> 3.117.0 and redeploy the Hub Lambda from tag v3.117.0 (12488a5818a0); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15809
- v3Target: "v3.117.0 (@mutmutco/cli@3.117.0, tag commit 12488a5818a0 \u2014 the preserved latest-v3 distribution, D6b)"
15849
+ mechanism: "npm dist-tag latest -> 3.118.0 and redeploy the Hub Lambda from tag v3.118.0 (4f9600d3bf89); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15850
+ v3Target: "v3.118.0 (@mutmutco/cli@3.118.0, tag commit 4f9600d3bf89 \u2014 the preserved latest-v3 distribution, D6b)"
15810
15851
  }
15811
15852
  },
15812
15853
  {
@@ -17890,7 +17931,7 @@ function planTrainApplyRepoGuard(applyRepo, cwdRepo, rerun) {
17890
17931
  async function resolveFoldPaths(deps, model) {
17891
17932
  const helper = "scripts/release-distribution.mjs";
17892
17933
  if (model === "hub-serverless" || model === "registry-publish") {
17893
- if ((0, import_node_fs20.existsSync)(helper)) {
17934
+ if ((0, import_node_fs21.existsSync)(helper)) {
17894
17935
  let out;
17895
17936
  try {
17896
17937
  out = await deps.run("node", [helper, "changed-files"]);
@@ -18009,7 +18050,7 @@ async function restoreMainNpmPackIdentities(deps, version) {
18009
18050
  if (mainBom.version !== version) return void 0;
18010
18051
  let localBom;
18011
18052
  try {
18012
- localBom = JSON.parse((0, import_node_fs20.readFileSync)(bomPath, "utf8"));
18053
+ localBom = JSON.parse((0, import_node_fs21.readFileSync)(bomPath, "utf8"));
18013
18054
  } catch (e) {
18014
18055
  throw new Error(
18015
18056
  `version fold refused: ${bomPath} written by this fold's prepare is unreadable (${describeReadError(e)}) \u2014 cannot restore the published ${version} npm-pack identities from origin/main (#4503/#4713).`
@@ -18027,14 +18068,14 @@ async function restoreMainNpmPackIdentities(deps, version) {
18027
18068
  restored += 1;
18028
18069
  }
18029
18070
  if (restored === 0) return void 0;
18030
- (0, import_node_fs20.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
18071
+ (0, import_node_fs21.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
18031
18072
  `);
18032
18073
  return `restored ${restored} npm-pack BOM identit${restored === 1 ? "y" : "ies"} from origin/main (#4503)`;
18033
18074
  }
18034
18075
  function publishVisibilityFor(surfaceId) {
18035
18076
  let raw;
18036
18077
  try {
18037
- raw = (0, import_node_fs20.readFileSync)("surfaces.json", "utf8");
18078
+ raw = (0, import_node_fs21.readFileSync)("surfaces.json", "utf8");
18038
18079
  } catch (e) {
18039
18080
  if (e.code === "ENOENT") return "unknown";
18040
18081
  throw trainReadFailure(
@@ -18055,7 +18096,7 @@ function publishVisibilityFor(surfaceId) {
18055
18096
  }
18056
18097
  function npmPackArtifactName(packagePath) {
18057
18098
  try {
18058
- const pkg = JSON.parse((0, import_node_fs20.readFileSync)((0, import_node_path19.join)(packagePath, "package.json"), "utf8"));
18099
+ const pkg = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path20.join)(packagePath, "package.json"), "utf8"));
18059
18100
  return pkg.name || void 0;
18060
18101
  } catch {
18061
18102
  return void 0;
@@ -18064,7 +18105,7 @@ function npmPackArtifactName(packagePath) {
18064
18105
  async function refuseDivergentPublishedNpmPack(deps, version) {
18065
18106
  let localBom;
18066
18107
  try {
18067
- localBom = JSON.parse((0, import_node_fs20.readFileSync)("distribution-bom.json", "utf8"));
18108
+ localBom = JSON.parse((0, import_node_fs21.readFileSync)("distribution-bom.json", "utf8"));
18068
18109
  } catch (e) {
18069
18110
  throw new Error(
18070
18111
  `version fold refused: distribution-bom.json written by this fold's prepare is unreadable (${e instanceof Error ? e.message.split("\n")[0] : String(e)}) \u2014 cannot compare the same-PATCH ${version} npm-pack identities against published npm (#4503/#4662).`
@@ -19226,17 +19267,17 @@ async function dispatchDeploy(deps, ctx, stage, ref, model, watch, autoRunSince,
19226
19267
  return { note: `no manual dispatch: ${model} repo deploys via its own push-triggered workflow`, deployStatus: "pending" };
19227
19268
  }
19228
19269
  function readLocalGateWorkflows() {
19229
- const dir = (0, import_node_path19.join)(".github", "workflows");
19270
+ const dir = (0, import_node_path20.join)(".github", "workflows");
19230
19271
  let names;
19231
19272
  try {
19232
- names = (0, import_node_fs20.readdirSync)(dir);
19273
+ names = (0, import_node_fs21.readdirSync)(dir);
19233
19274
  } catch {
19234
19275
  return null;
19235
19276
  }
19236
19277
  const files = [];
19237
19278
  for (const name of names.filter(isGateWorkflowPath)) {
19238
19279
  try {
19239
- files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs20.readFileSync)((0, import_node_path19.join)(dir, name), "utf8") });
19280
+ files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs21.readFileSync)((0, import_node_path20.join)(dir, name), "utf8") });
19240
19281
  } catch {
19241
19282
  }
19242
19283
  }
@@ -21457,12 +21498,12 @@ async function runPrLand(prNumber, options, deps) {
21457
21498
  }
21458
21499
 
21459
21500
  // src/wave-status.ts
21460
- var import_node_fs22 = require("node:fs");
21501
+ var import_node_fs23 = require("node:fs");
21461
21502
 
21462
21503
  // src/stage-runner.ts
21463
21504
  var import_node_child_process9 = require("node:child_process");
21464
- var import_node_fs21 = require("node:fs");
21465
- var import_node_path20 = require("node:path");
21505
+ var import_node_fs22 = require("node:fs");
21506
+ var import_node_path21 = require("node:path");
21466
21507
  var import_node_net = require("node:net");
21467
21508
  var import_node_util5 = require("node:util");
21468
21509
 
@@ -21601,11 +21642,11 @@ function appendForceRecreate(up) {
21601
21642
  return `${up.trimEnd()} --force-recreate`;
21602
21643
  }
21603
21644
  function stageStatePath(cwd = process.cwd()) {
21604
- return (0, import_node_path20.join)(cwd, "tmp", "stage", "state.json");
21645
+ return (0, import_node_path21.join)(cwd, "tmp", "stage", "state.json");
21605
21646
  }
21606
21647
  function stageGlobalStatePath(cwd = process.cwd(), gitCommonDir = ".git") {
21607
- const dir = (0, import_node_path20.isAbsolute)(gitCommonDir) ? gitCommonDir : (0, import_node_path20.resolve)(cwd, gitCommonDir);
21608
- return (0, import_node_path20.join)(dir, "mmi", "stage", "state.json");
21648
+ const dir = (0, import_node_path21.isAbsolute)(gitCommonDir) ? gitCommonDir : (0, import_node_path21.resolve)(cwd, gitCommonDir);
21649
+ return (0, import_node_path21.join)(dir, "mmi", "stage", "state.json");
21609
21650
  }
21610
21651
  function normPath3(path2) {
21611
21652
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -21829,14 +21870,14 @@ function stageProcessEnv(stagePort, extraEnv) {
21829
21870
  }
21830
21871
  async function ensureStageRuntimeEnv(config, opts, cwd) {
21831
21872
  if (!config.ensureEnv) return;
21832
- const target = (0, import_node_path20.join)(cwd, config.ensureEnv.target);
21833
- const example = (0, import_node_path20.join)(cwd, config.ensureEnv.example);
21834
- if (!(0, import_node_fs21.existsSync)(target) && (0, import_node_fs21.existsSync)(example)) {
21835
- (0, import_node_fs21.copyFileSync)(example, target);
21836
- } else if ((0, import_node_fs21.existsSync)(target) && (0, import_node_fs21.existsSync)(example)) {
21837
- const stale = detectStaleEnvFile((0, import_node_fs21.readFileSync)(example, "utf8"), (0, import_node_fs21.readFileSync)(target, "utf8"), {
21838
- exampleMtimeMs: (0, import_node_fs21.statSync)(example).mtimeMs,
21839
- targetMtimeMs: (0, import_node_fs21.statSync)(target).mtimeMs
21873
+ const target = (0, import_node_path21.join)(cwd, config.ensureEnv.target);
21874
+ const example = (0, import_node_path21.join)(cwd, config.ensureEnv.example);
21875
+ if (!(0, import_node_fs22.existsSync)(target) && (0, import_node_fs22.existsSync)(example)) {
21876
+ (0, import_node_fs22.copyFileSync)(example, target);
21877
+ } else if ((0, import_node_fs22.existsSync)(target) && (0, import_node_fs22.existsSync)(example)) {
21878
+ const stale = detectStaleEnvFile((0, import_node_fs22.readFileSync)(example, "utf8"), (0, import_node_fs22.readFileSync)(target, "utf8"), {
21879
+ exampleMtimeMs: (0, import_node_fs22.statSync)(example).mtimeMs,
21880
+ targetMtimeMs: (0, import_node_fs22.statSync)(target).mtimeMs
21840
21881
  });
21841
21882
  if (stale) {
21842
21883
  const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running /stage`;
@@ -21844,8 +21885,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
21844
21885
  console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
21845
21886
  }
21846
21887
  }
21847
- if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs21.existsSync)(target)) {
21848
- (0, import_node_fs21.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs21.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
21888
+ if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs22.existsSync)(target)) {
21889
+ (0, import_node_fs22.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs22.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
21849
21890
  }
21850
21891
  }
21851
21892
  async function gitText(cwd, args) {
@@ -21875,20 +21916,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
21875
21916
  return void 0;
21876
21917
  }
21877
21918
  function readState(path2) {
21878
- if (!(0, import_node_fs21.existsSync)(path2)) return null;
21919
+ if (!(0, import_node_fs22.existsSync)(path2)) return null;
21879
21920
  try {
21880
- return JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
21921
+ return JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
21881
21922
  } catch {
21882
21923
  return null;
21883
21924
  }
21884
21925
  }
21885
21926
  function mkdirFor(path2) {
21886
21927
  const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
21887
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
21928
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
21888
21929
  }
21889
21930
  function writeState(path2, state) {
21890
21931
  mkdirFor(path2);
21891
- (0, import_node_fs21.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
21932
+ (0, import_node_fs22.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
21892
21933
  }
21893
21934
  function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
21894
21935
  const reservation = {
@@ -21908,7 +21949,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd) {
21908
21949
  await shell(state.teardown.command.trim(), state.teardown.cwd || state.cwd || fallbackCwd, Math.max(timeoutMs, 1e4));
21909
21950
  }
21910
21951
  for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
21911
- (0, import_node_fs21.rmSync)(path2, { force: true });
21952
+ (0, import_node_fs22.rmSync)(path2, { force: true });
21912
21953
  }
21913
21954
  }
21914
21955
  async function killTree(pid) {
@@ -22066,8 +22107,8 @@ async function runStage(config = {}, opts = {}) {
22066
22107
  await ensureStageRuntimeEnv(config, opts, cwd);
22067
22108
  if (build) await shell(sub(build), cwd, timeoutMs, stageProcessEnv(stagePort, extraEnv));
22068
22109
  } catch (e) {
22069
- (0, import_node_fs21.rmSync)(statePath, { force: true });
22070
- if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs21.rmSync)(globalStatePath, { force: true });
22110
+ (0, import_node_fs22.rmSync)(statePath, { force: true });
22111
+ if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs22.rmSync)(globalStatePath, { force: true });
22071
22112
  throw e;
22072
22113
  }
22073
22114
  const started = await startStage(config, {
@@ -22088,9 +22129,9 @@ function parseNextFromHead(headText) {
22088
22129
  }
22089
22130
  function readStageSummary(worktreePath) {
22090
22131
  const statePath = stageStatePath(worktreePath);
22091
- if (!(0, import_node_fs22.existsSync)(statePath)) return void 0;
22132
+ if (!(0, import_node_fs23.existsSync)(statePath)) return void 0;
22092
22133
  try {
22093
- const state = JSON.parse((0, import_node_fs22.readFileSync)(statePath, "utf8"));
22134
+ const state = JSON.parse((0, import_node_fs23.readFileSync)(statePath, "utf8"));
22094
22135
  const port = typeof state.port === "number" ? state.port : void 0;
22095
22136
  if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
22096
22137
  return { port, url: typeof state.url === "string" ? state.url : void 0 };
@@ -22199,9 +22240,9 @@ var import_node_os19 = require("node:os");
22199
22240
 
22200
22241
  // src/board.ts
22201
22242
  var import_node_child_process10 = require("node:child_process");
22202
- var import_node_fs23 = require("node:fs");
22243
+ var import_node_fs24 = require("node:fs");
22203
22244
  var import_node_os8 = require("node:os");
22204
- var import_node_path21 = require("node:path");
22245
+ var import_node_path22 = require("node:path");
22205
22246
  var import_node_util6 = require("node:util");
22206
22247
 
22207
22248
  // src/board-dependency.ts
@@ -23948,17 +23989,17 @@ function probeLocalClaimSession(marker, now = Date.now()) {
23948
23989
  claimSessionProbeCache.set(cacheKey, { checkedAt: now, state });
23949
23990
  return state;
23950
23991
  };
23951
- const root = (0, import_node_path21.join)((0, import_node_os8.homedir)(), ".claude", "projects");
23992
+ const root = (0, import_node_path22.join)((0, import_node_os8.homedir)(), ".claude", "projects");
23952
23993
  try {
23953
23994
  const wanted = `${marker.session}.jsonl`.toLowerCase();
23954
23995
  const pending = [root];
23955
23996
  while (pending.length) {
23956
23997
  const dir = pending.pop();
23957
- for (const entry of (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true })) {
23958
- const path2 = (0, import_node_path21.join)(dir, entry.name);
23998
+ for (const entry of (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true })) {
23999
+ const path2 = (0, import_node_path22.join)(dir, entry.name);
23959
24000
  if (entry.isDirectory()) pending.push(path2);
23960
24001
  else if (entry.isFile() && entry.name.toLowerCase() === wanted) {
23961
- return remember(now - (0, import_node_fs23.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
24002
+ return remember(now - (0, import_node_fs24.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
23962
24003
  }
23963
24004
  }
23964
24005
  }
@@ -24857,8 +24898,8 @@ function consolidateCommandNamespaces(program3) {
24857
24898
  }
24858
24899
 
24859
24900
  // src/pi-plugin-registration.ts
24860
- var import_node_fs24 = require("node:fs");
24861
- var import_node_path22 = require("node:path");
24901
+ var import_node_fs25 = require("node:fs");
24902
+ var import_node_path23 = require("node:path");
24862
24903
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
24863
24904
 
24864
24905
  // src/plugin-cache-prune.ts
@@ -25116,48 +25157,48 @@ function newestExistingPiPlugin(home) {
25116
25157
  const cacheRoot = pluginCacheRoot(home);
25117
25158
  let names;
25118
25159
  try {
25119
- names = (0, import_node_fs24.readdirSync)(cacheRoot);
25160
+ names = (0, import_node_fs25.readdirSync)(cacheRoot);
25120
25161
  } catch {
25121
25162
  return void 0;
25122
25163
  }
25123
25164
  for (const version of names.filter(isVersionDirName).sort((a, b) => compareVersions(b, a))) {
25124
- const candidate = (0, import_node_path22.join)(cacheRoot, version, ".pi-plugin");
25125
- if ((0, import_node_fs24.existsSync)(candidate)) return candidate;
25165
+ const candidate = (0, import_node_path23.join)(cacheRoot, version, ".pi-plugin");
25166
+ if ((0, import_node_fs25.existsSync)(candidate)) return candidate;
25126
25167
  }
25127
25168
  return void 0;
25128
25169
  }
25129
25170
  function expectedPiPluginPath(home, env, installedVersion) {
25130
25171
  const root = env.CLAUDE_PLUGIN_ROOT?.trim();
25131
- if (root && /[\\/]mutmutco[\\/]mmi[\\/]/.test(root)) return (0, import_node_path22.join)(root, ".pi-plugin");
25172
+ if (root && /[\\/]mutmutco[\\/]mmi[\\/]/.test(root)) return (0, import_node_path23.join)(root, ".pi-plugin");
25132
25173
  const version = installedVersion ?? runningPluginVersion(env);
25133
25174
  if (version) {
25134
- const pinned = (0, import_node_path22.join)(home, ".claude", "plugins", "cache", "mutmutco", "mmi", version, ".pi-plugin");
25135
- if ((0, import_node_fs24.existsSync)(pinned)) return pinned;
25175
+ const pinned = (0, import_node_path23.join)(home, ".claude", "plugins", "cache", "mutmutco", "mmi", version, ".pi-plugin");
25176
+ if ((0, import_node_fs25.existsSync)(pinned)) return pinned;
25136
25177
  }
25137
25178
  return newestExistingPiPlugin(home);
25138
25179
  }
25139
25180
  function agentDirs(home, env = process.env) {
25140
25181
  const override = env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim();
25141
25182
  if (override) return [override];
25142
- const jerv = (0, import_node_path22.join)(home, ".jerv", "agent");
25143
- const pi = (0, import_node_path22.join)(home, ".pi", "agent");
25144
- if (!(0, import_node_fs24.existsSync)(jerv) && !(0, import_node_fs24.existsSync)(pi)) return [];
25183
+ const jerv = (0, import_node_path23.join)(home, ".jerv", "agent");
25184
+ const pi = (0, import_node_path23.join)(home, ".pi", "agent");
25185
+ if (!(0, import_node_fs25.existsSync)(jerv) && !(0, import_node_fs25.existsSync)(pi)) return [];
25145
25186
  const dirs = [jerv];
25146
- if ((0, import_node_fs24.existsSync)(pi) && pi !== jerv) dirs.push(pi);
25187
+ if ((0, import_node_fs25.existsSync)(pi) && pi !== jerv) dirs.push(pi);
25147
25188
  return dirs;
25148
25189
  }
25149
25190
  function settingsPath(agentDir) {
25150
- return (0, import_node_path22.join)(agentDir, "settings.json");
25191
+ return (0, import_node_path23.join)(agentDir, "settings.json");
25151
25192
  }
25152
25193
  function readPiPluginState(home, env, installedVersion) {
25153
25194
  const dirs = agentDirs(home, env);
25154
25195
  if (dirs.length === 0) return void 0;
25155
25196
  const expectedPath = expectedPiPluginPath(home, env, installedVersion);
25156
25197
  if (!expectedPath) return void 0;
25157
- const file = dirs.map(settingsPath).find((p) => (0, import_node_fs24.existsSync)(p)) ?? settingsPath(dirs[0]);
25158
- if (!(0, import_node_fs24.existsSync)(file)) return { expectedPath, settingsReadable: true };
25198
+ const file = dirs.map(settingsPath).find((p) => (0, import_node_fs25.existsSync)(p)) ?? settingsPath(dirs[0]);
25199
+ if (!(0, import_node_fs25.existsSync)(file)) return { expectedPath, settingsReadable: true };
25159
25200
  try {
25160
- const parsed = JSON.parse((0, import_node_fs24.readFileSync)(file, "utf8"));
25201
+ const parsed = JSON.parse((0, import_node_fs25.readFileSync)(file, "utf8"));
25161
25202
  const packages = Array.isArray(parsed.packages) ? parsed.packages : [];
25162
25203
  return { expectedPath, registeredPath: packages.find((p) => typeof p === "string" && isMmiPiPackage(p)), settingsReadable: true };
25163
25204
  } catch {
@@ -25181,20 +25222,20 @@ function acquirePiSettingsLock2(settingsFile) {
25181
25222
  return void 0;
25182
25223
  }
25183
25224
  function atomicWriteSettings(file, body) {
25184
- (0, import_node_fs24.mkdirSync)((0, import_node_path22.dirname)(file), { recursive: true });
25225
+ (0, import_node_fs25.mkdirSync)((0, import_node_path23.dirname)(file), { recursive: true });
25185
25226
  const tmp = `${file}.tmp-${process.pid}`;
25186
- (0, import_node_fs24.writeFileSync)(tmp, body, "utf8");
25227
+ (0, import_node_fs25.writeFileSync)(tmp, body, "utf8");
25187
25228
  try {
25188
- (0, import_node_fs24.renameSync)(tmp, file);
25229
+ (0, import_node_fs25.renameSync)(tmp, file);
25189
25230
  } catch (renameError) {
25190
- (0, import_node_fs24.rmSync)(tmp, { force: true });
25231
+ (0, import_node_fs25.rmSync)(tmp, { force: true });
25191
25232
  throw renameError;
25192
25233
  }
25193
25234
  }
25194
25235
  function healOneAgentDir(agentDir, expectedPath) {
25195
25236
  const file = settingsPath(agentDir);
25196
- const release = (0, import_node_fs24.existsSync)(file) ? acquirePiSettingsLock2(file) : void 0;
25197
- if ((0, import_node_fs24.existsSync)(file) && !release) {
25237
+ const release = (0, import_node_fs25.existsSync)(file) ? acquirePiSettingsLock2(file) : void 0;
25238
+ if ((0, import_node_fs25.existsSync)(file) && !release) {
25198
25239
  return {
25199
25240
  ok: false,
25200
25241
  detail: `Pi's settings lock (${file}.lock) is held by another process; nothing written, retry on the next doctor run`,
@@ -25203,9 +25244,9 @@ function healOneAgentDir(agentDir, expectedPath) {
25203
25244
  }
25204
25245
  try {
25205
25246
  let parsed = {};
25206
- if ((0, import_node_fs24.existsSync)(file)) {
25247
+ if ((0, import_node_fs25.existsSync)(file)) {
25207
25248
  try {
25208
- const raw = JSON.parse((0, import_node_fs24.readFileSync)(file, "utf8"));
25249
+ const raw = JSON.parse((0, import_node_fs25.readFileSync)(file, "utf8"));
25209
25250
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25210
25251
  return { ok: false, detail: "settings.json unreadable \u2014 nothing written (fail closed)" };
25211
25252
  }
@@ -25257,20 +25298,20 @@ function healPiPluginRegistration(home, env, installedVersion) {
25257
25298
  }
25258
25299
 
25259
25300
  // src/claude-binary-doctor.ts
25260
- var import_node_fs26 = require("node:fs");
25301
+ var import_node_fs27 = require("node:fs");
25261
25302
  var import_node_os11 = require("node:os");
25262
- var import_node_path24 = require("node:path");
25303
+ var import_node_path25 = require("node:path");
25263
25304
 
25264
25305
  // src/jerv-cli-spawn.ts
25265
- var import_node_fs25 = require("node:fs");
25306
+ var import_node_fs26 = require("node:fs");
25266
25307
  var import_node_os10 = require("node:os");
25267
- var import_node_path23 = require("node:path");
25308
+ var import_node_path24 = require("node:path");
25268
25309
  var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
25269
25310
  var POSIX_NAMES = ["jerv-cli"];
25270
- var JERV_CLI_ENTRY = (0, import_node_path23.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
25311
+ var JERV_CLI_ENTRY = (0, import_node_path24.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
25271
25312
  function pathEnvEntries(pathEnv, platform2 = process.platform) {
25272
25313
  if (platform2 !== "win32") {
25273
- return pathEnv.split(import_node_path23.delimiter).map((e) => e.trim()).filter(Boolean);
25314
+ return pathEnv.split(import_node_path24.delimiter).map((e) => e.trim()).filter(Boolean);
25274
25315
  }
25275
25316
  if (pathEnv.includes(";")) {
25276
25317
  return pathEnv.split(";").map((e) => e.trim()).filter(Boolean);
@@ -25303,10 +25344,10 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os10.hom
25303
25344
  push(normalizeSpawnPathEntry(entry, platform2));
25304
25345
  }
25305
25346
  if (platform2 === "win32") {
25306
- if (env.APPDATA) push((0, import_node_path23.join)(env.APPDATA, "npm"));
25307
- if (env.LOCALAPPDATA) push((0, import_node_path23.join)(env.LOCALAPPDATA, "npm"));
25347
+ if (env.APPDATA) push((0, import_node_path24.join)(env.APPDATA, "npm"));
25348
+ if (env.LOCALAPPDATA) push((0, import_node_path24.join)(env.LOCALAPPDATA, "npm"));
25308
25349
  } else {
25309
- push((0, import_node_path23.join)(home, ".local", "bin"));
25350
+ push((0, import_node_path24.join)(home, ".local", "bin"));
25310
25351
  }
25311
25352
  return out;
25312
25353
  }
@@ -25314,23 +25355,23 @@ function jervCliCandidatePaths(env = process.env, home = (0, import_node_os10.ho
25314
25355
  const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
25315
25356
  const out = [];
25316
25357
  for (const dir of jervCliCandidateDirs(env, home, platform2)) {
25317
- for (const name of names) out.push((0, import_node_path23.join)(dir, name));
25358
+ for (const name of names) out.push((0, import_node_path24.join)(dir, name));
25318
25359
  }
25319
25360
  return out;
25320
25361
  }
25321
- function resolveJervCliPath(env = process.env, home = (0, import_node_os10.homedir)(), platform2 = process.platform, exists = import_node_fs25.existsSync) {
25362
+ function resolveJervCliPath(env = process.env, home = (0, import_node_os10.homedir)(), platform2 = process.platform, exists = import_node_fs26.existsSync) {
25322
25363
  for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
25323
25364
  if (exists(candidate)) return candidate;
25324
25365
  }
25325
25366
  return void 0;
25326
25367
  }
25327
- function resolveJervCliNodeEntry(shimPath, exists = import_node_fs25.existsSync) {
25328
- const entry = (0, import_node_path23.join)((0, import_node_path23.dirname)(shimPath), JERV_CLI_ENTRY);
25368
+ function resolveJervCliNodeEntry(shimPath, exists = import_node_fs26.existsSync) {
25369
+ const entry = (0, import_node_path24.join)((0, import_node_path24.dirname)(shimPath), JERV_CLI_ENTRY);
25329
25370
  return exists(entry) ? entry : void 0;
25330
25371
  }
25331
25372
  function jervCliExecFileArgs(args, opts = {}) {
25332
25373
  const platform2 = opts.platform ?? process.platform;
25333
- const exists = opts.exists ?? import_node_fs25.existsSync;
25374
+ const exists = opts.exists ?? import_node_fs26.existsSync;
25334
25375
  const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os10.homedir)(), platform2, exists);
25335
25376
  if (resolved) {
25336
25377
  const entry = resolveJervCliNodeEntry(resolved, exists);
@@ -25420,26 +25461,26 @@ function globalNodeModulesRoots(host) {
25420
25461
  out.push(dir);
25421
25462
  };
25422
25463
  const prefix = env.npm_config_prefix?.trim();
25423
- if (prefix) push(platform2 === "win32" ? (0, import_node_path24.join)(prefix, "node_modules") : (0, import_node_path24.join)(prefix, "lib", "node_modules"));
25464
+ if (prefix) push(platform2 === "win32" ? (0, import_node_path25.join)(prefix, "node_modules") : (0, import_node_path25.join)(prefix, "lib", "node_modules"));
25424
25465
  for (const dir of jervCliCandidateDirs(env, host.home ?? (0, import_node_os11.homedir)(), platform2)) {
25425
- push((0, import_node_path24.join)(dir, "node_modules"));
25426
- push((0, import_node_path24.join)((0, import_node_path24.dirname)(dir), "lib", "node_modules"));
25466
+ push((0, import_node_path25.join)(dir, "node_modules"));
25467
+ push((0, import_node_path25.join)((0, import_node_path25.dirname)(dir), "lib", "node_modules"));
25427
25468
  }
25428
25469
  return out;
25429
25470
  }
25430
25471
  function readHead(path2) {
25431
25472
  let fd;
25432
25473
  try {
25433
- fd = (0, import_node_fs26.openSync)(path2, "r");
25474
+ fd = (0, import_node_fs27.openSync)(path2, "r");
25434
25475
  const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
25435
- const read = (0, import_node_fs26.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
25476
+ const read = (0, import_node_fs27.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
25436
25477
  return buffer.subarray(0, read);
25437
25478
  } catch {
25438
25479
  return void 0;
25439
25480
  } finally {
25440
25481
  if (fd !== void 0) {
25441
25482
  try {
25442
- (0, import_node_fs26.closeSync)(fd);
25483
+ (0, import_node_fs27.closeSync)(fd);
25443
25484
  } catch {
25444
25485
  }
25445
25486
  }
@@ -25447,7 +25488,7 @@ function readHead(path2) {
25447
25488
  }
25448
25489
  function fileBytes(path2) {
25449
25490
  try {
25450
- return (0, import_node_fs26.statSync)(path2).size;
25491
+ return (0, import_node_fs27.statSync)(path2).size;
25451
25492
  } catch {
25452
25493
  return void 0;
25453
25494
  }
@@ -25461,17 +25502,17 @@ function readClaudeBinaryState(host = {}) {
25461
25502
  const arch = host.arch ?? process.arch;
25462
25503
  const magic = EXECUTABLE_MAGIC[platform2];
25463
25504
  if (!magic) return void 0;
25464
- const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path24.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs26.existsSync)((0, import_node_path24.join)(dir, "package.json")));
25505
+ const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path25.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs27.existsSync)((0, import_node_path25.join)(dir, "package.json")));
25465
25506
  if (!packageRoot) return void 0;
25466
25507
  const keys = platformPackageKeys(platform2, arch);
25467
25508
  const fallbackPackage = `${PACKAGE}-${keys[0]}`;
25468
25509
  let manifest;
25469
25510
  try {
25470
- manifest = JSON.parse((0, import_node_fs26.readFileSync)((0, import_node_path24.join)(packageRoot, "package.json"), "utf8"));
25511
+ manifest = JSON.parse((0, import_node_fs27.readFileSync)((0, import_node_path25.join)(packageRoot, "package.json"), "utf8"));
25471
25512
  } catch (e) {
25472
25513
  return {
25473
25514
  state: "unreadable",
25474
- binPath: (0, import_node_path24.join)(packageRoot, "package.json"),
25515
+ binPath: (0, import_node_path25.join)(packageRoot, "package.json"),
25475
25516
  expectedMagic: magic.name,
25476
25517
  platformPackage: fallbackPackage,
25477
25518
  error: `package.json could not be read \u2014 ${e.message}`
@@ -25488,17 +25529,17 @@ function readClaudeBinaryState(host = {}) {
25488
25529
  error: "package.json declares no `bin` entry \u2014 the executed file cannot be resolved"
25489
25530
  };
25490
25531
  }
25491
- const binPath = (0, import_node_path24.join)(packageRoot, binRelative);
25492
- const binName = (0, import_node_path24.basename)(binRelative);
25532
+ const binPath = (0, import_node_path25.join)(packageRoot, binRelative);
25533
+ const binName = (0, import_node_path25.basename)(binRelative);
25493
25534
  const optional = manifest.optionalDependencies;
25494
25535
  const publishes = (name) => typeof optional === "object" && optional !== null && Object.prototype.hasOwnProperty.call(optional, name);
25495
25536
  const published = keys.map((key) => `${PACKAGE}-${key}`).filter(publishes);
25496
25537
  if (published.length === 0) return void 0;
25497
25538
  const binIn = (name) => [
25498
- (0, import_node_path24.join)(packageRoot, "node_modules", ...name.split("/"), binName),
25499
- (0, import_node_path24.join)((0, import_node_path24.dirname)((0, import_node_path24.dirname)(packageRoot)), ...name.split("/"), binName)
25539
+ (0, import_node_path25.join)(packageRoot, "node_modules", ...name.split("/"), binName),
25540
+ (0, import_node_path25.join)((0, import_node_path25.dirname)((0, import_node_path25.dirname)(packageRoot)), ...name.split("/"), binName)
25500
25541
  ];
25501
- const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs26.existsSync)(file)) })).find((c) => c.path);
25542
+ const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs27.existsSync)(file)) })).find((c) => c.path);
25502
25543
  const platformPackage = found?.name ?? published[0];
25503
25544
  let source;
25504
25545
  let sourceProblem;
@@ -25509,7 +25550,7 @@ function readClaudeBinaryState(host = {}) {
25509
25550
  } else {
25510
25551
  source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
25511
25552
  }
25512
- if (!(0, import_node_fs26.existsSync)(binPath)) {
25553
+ if (!(0, import_node_fs27.existsSync)(binPath)) {
25513
25554
  return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
25514
25555
  }
25515
25556
  const head = readHead(binPath);
@@ -25552,9 +25593,9 @@ function healClaudeBinary(host = {}, onStep) {
25552
25593
  const platform2 = host.platform ?? process.platform;
25553
25594
  const aside = `${probe.binPath}.stub-${Date.now()}`;
25554
25595
  let renamed = false;
25555
- if ((0, import_node_fs26.existsSync)(probe.binPath)) {
25596
+ if ((0, import_node_fs27.existsSync)(probe.binPath)) {
25556
25597
  try {
25557
- (0, import_node_fs26.renameSync)(probe.binPath, aside);
25598
+ (0, import_node_fs27.renameSync)(probe.binPath, aside);
25558
25599
  renamed = true;
25559
25600
  onStep?.(`renamed the stub aside: ${aside}`);
25560
25601
  } catch (e) {
@@ -25563,12 +25604,12 @@ function healClaudeBinary(host = {}, onStep) {
25563
25604
  }
25564
25605
  try {
25565
25606
  onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
25566
- (0, import_node_fs26.copyFileSync)(probe.source.path, probe.binPath);
25567
- if (platform2 !== "win32") (0, import_node_fs26.chmodSync)(probe.binPath, 493);
25607
+ (0, import_node_fs27.copyFileSync)(probe.source.path, probe.binPath);
25608
+ if (platform2 !== "win32") (0, import_node_fs27.chmodSync)(probe.binPath, 493);
25568
25609
  } catch (e) {
25569
25610
  if (renamed) {
25570
25611
  try {
25571
- (0, import_node_fs26.renameSync)(aside, probe.binPath);
25612
+ (0, import_node_fs27.renameSync)(aside, probe.binPath);
25572
25613
  } catch {
25573
25614
  return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
25574
25615
  }
@@ -25582,7 +25623,7 @@ function healClaudeBinary(host = {}, onStep) {
25582
25623
  let kept = false;
25583
25624
  if (renamed) {
25584
25625
  try {
25585
- (0, import_node_fs26.rmSync)(aside);
25626
+ (0, import_node_fs27.rmSync)(aside);
25586
25627
  } catch {
25587
25628
  kept = true;
25588
25629
  }
@@ -26916,8 +26957,8 @@ async function announceRelease(deps, args) {
26916
26957
  // src/repo-index.ts
26917
26958
  var import_node_crypto4 = require("node:crypto");
26918
26959
  var import_node_child_process13 = require("node:child_process");
26919
- var import_node_fs27 = require("node:fs");
26920
- var import_node_path25 = require("node:path");
26960
+ var import_node_fs28 = require("node:fs");
26961
+ var import_node_path26 = require("node:path");
26921
26962
  var REPO_INDEX_SCHEMA = 1;
26922
26963
  var HARD_DENY = [
26923
26964
  /(^|\/)\.env(\.|$)/i,
@@ -27042,11 +27083,11 @@ function loadReadmeHints(cwd, candidatePaths) {
27042
27083
  }
27043
27084
  for (const rel of readmes) {
27044
27085
  if (isHardDeniedPath(rel)) continue;
27045
- const abs = (0, import_node_path25.join)(cwd, ...rel.split("/"));
27046
- if (!(0, import_node_fs27.existsSync)(abs)) continue;
27086
+ const abs = (0, import_node_path26.join)(cwd, ...rel.split("/"));
27087
+ if (!(0, import_node_fs28.existsSync)(abs)) continue;
27047
27088
  let text;
27048
27089
  try {
27049
- text = (0, import_node_fs27.readFileSync)(abs, "utf8");
27090
+ text = (0, import_node_fs28.readFileSync)(abs, "utf8");
27050
27091
  } catch {
27051
27092
  continue;
27052
27093
  }
@@ -27059,7 +27100,7 @@ function loadReadmeHints(cwd, candidatePaths) {
27059
27100
  return hints;
27060
27101
  }
27061
27102
  function toPosix(p) {
27062
- return p.split(import_node_path25.sep).join("/");
27103
+ return p.split(import_node_path26.sep).join("/");
27063
27104
  }
27064
27105
  function listCandidatePaths(cwd, exec = import_node_child_process13.execFileSync) {
27065
27106
  try {
@@ -27081,11 +27122,11 @@ function rebuildRepoIndex(cwd, repoSlug2) {
27081
27122
  for (const rel of candidates) {
27082
27123
  if (ignored.has(rel)) continue;
27083
27124
  if (isHardDeniedPath(rel)) continue;
27084
- const abs = (0, import_node_path25.join)(cwd, ...rel.split("/"));
27085
- if (!(0, import_node_fs27.existsSync)(abs)) continue;
27125
+ const abs = (0, import_node_path26.join)(cwd, ...rel.split("/"));
27126
+ if (!(0, import_node_fs28.existsSync)(abs)) continue;
27086
27127
  let text;
27087
27128
  try {
27088
- text = (0, import_node_fs27.readFileSync)(abs, "utf8");
27129
+ text = (0, import_node_fs28.readFileSync)(abs, "utf8");
27089
27130
  } catch {
27090
27131
  continue;
27091
27132
  }
@@ -27110,16 +27151,16 @@ function rebuildRepoIndex(cwd, repoSlug2) {
27110
27151
  entries
27111
27152
  };
27112
27153
  const store = repoIndexStorePath(cwd);
27113
- (0, import_node_fs27.mkdirSync)((0, import_node_path25.dirname)(store), { recursive: true });
27114
- (0, import_node_fs27.writeFileSync)(store, `${JSON.stringify(projection, null, 2)}
27154
+ (0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(store), { recursive: true });
27155
+ (0, import_node_fs28.writeFileSync)(store, `${JSON.stringify(projection, null, 2)}
27115
27156
  `, "utf8");
27116
27157
  return projection;
27117
27158
  }
27118
27159
  function loadRepoIndex(cwd) {
27119
27160
  const store = repoIndexStorePath(cwd);
27120
- if (!(0, import_node_fs27.existsSync)(store)) return null;
27161
+ if (!(0, import_node_fs28.existsSync)(store)) return null;
27121
27162
  try {
27122
- const raw = JSON.parse((0, import_node_fs27.readFileSync)(store, "utf8"));
27163
+ const raw = JSON.parse((0, import_node_fs28.readFileSync)(store, "utf8"));
27123
27164
  if (raw?.schema !== REPO_INDEX_SCHEMA || !Array.isArray(raw.entries)) return null;
27124
27165
  return raw;
27125
27166
  } catch {
@@ -27191,7 +27232,7 @@ function inferRepoSlug(cwd, exec = import_node_child_process13.execFileSync) {
27191
27232
  if (m?.[1]) return m[1].toLowerCase();
27192
27233
  } catch {
27193
27234
  }
27194
- return ((0, import_node_path25.basename)(cwd) || "local").toLowerCase();
27235
+ return ((0, import_node_path26.basename)(cwd) || "local").toLowerCase();
27195
27236
  }
27196
27237
 
27197
27238
  // src/repo-index-cloud-client.ts
@@ -27331,9 +27372,9 @@ async function gcRepoIndexCloud(deps) {
27331
27372
  }
27332
27373
 
27333
27374
  // src/repo-index-sync.ts
27334
- var import_node_fs28 = require("node:fs");
27375
+ var import_node_fs29 = require("node:fs");
27335
27376
  var import_node_os12 = require("node:os");
27336
- var import_node_path26 = require("node:path");
27377
+ var import_node_path27 = require("node:path");
27337
27378
  var import_node_child_process14 = require("node:child_process");
27338
27379
  var MAX_EMBED_BACKFILL_ROUNDS = 40;
27339
27380
  function normalizeRepo(raw) {
@@ -27377,7 +27418,7 @@ async function syncEstateRepoIndex(opts) {
27377
27418
  const failed = [];
27378
27419
  const skipped = [];
27379
27420
  for (const repo of repos) {
27380
- const dir = (0, import_node_fs28.mkdtempSync)((0, import_node_path26.join)((0, import_node_os12.tmpdir)(), "mmi-repo-index-"));
27421
+ const dir = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os12.tmpdir)(), "mmi-repo-index-"));
27381
27422
  try {
27382
27423
  shallowClone(repo, dir, opts.githubToken);
27383
27424
  const built = rebuildRepoIndex(dir, repo);
@@ -27427,7 +27468,7 @@ async function syncEstateRepoIndex(opts) {
27427
27468
  failed.push({ repo, error: e.message });
27428
27469
  } finally {
27429
27470
  try {
27430
- (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
27471
+ (0, import_node_fs29.rmSync)(dir, { recursive: true, force: true });
27431
27472
  } catch {
27432
27473
  }
27433
27474
  }
@@ -27436,7 +27477,7 @@ async function syncEstateRepoIndex(opts) {
27436
27477
  }
27437
27478
 
27438
27479
  // src/repo-index-health.ts
27439
- var import_node_fs29 = require("node:fs");
27480
+ var import_node_fs30 = require("node:fs");
27440
27481
 
27441
27482
  // testdata/repo-index-golden-queries.json
27442
27483
  var repo_index_golden_queries_default = {
@@ -27478,7 +27519,7 @@ function assertGoldenSuite(raw, source) {
27478
27519
  function loadGoldenSuite(path2) {
27479
27520
  let text;
27480
27521
  try {
27481
- text = (0, import_node_fs29.readFileSync)(path2, "utf8");
27522
+ text = (0, import_node_fs30.readFileSync)(path2, "utf8");
27482
27523
  } catch (e) {
27483
27524
  throw new Error(`golden suite unreadable at ${path2}: ${e.message}`);
27484
27525
  }
@@ -27624,8 +27665,8 @@ async function runRepoIndexHealth(opts) {
27624
27665
 
27625
27666
  // src/spawn-policy-core.ts
27626
27667
  var import_node_child_process15 = require("node:child_process");
27627
- var import_node_fs30 = require("node:fs");
27628
- var import_node_path27 = require("node:path");
27668
+ var import_node_fs31 = require("node:fs");
27669
+ var import_node_path28 = require("node:path");
27629
27670
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
27630
27671
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
27631
27672
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -27711,7 +27752,7 @@ function runSpawnPolicy(root) {
27711
27752
  for (const file of files) {
27712
27753
  let raw;
27713
27754
  try {
27714
- raw = (0, import_node_fs30.readFileSync)((0, import_node_path27.join)(root, file), "utf8");
27755
+ raw = (0, import_node_fs31.readFileSync)((0, import_node_path28.join)(root, file), "utf8");
27715
27756
  } catch {
27716
27757
  continue;
27717
27758
  }
@@ -27729,8 +27770,8 @@ function runSpawnPolicy(root) {
27729
27770
 
27730
27771
  // src/test-policy-core.ts
27731
27772
  var import_node_child_process16 = require("node:child_process");
27732
- var import_node_fs31 = require("node:fs");
27733
- var import_node_path28 = require("node:path");
27773
+ var import_node_fs32 = require("node:fs");
27774
+ var import_node_path29 = require("node:path");
27734
27775
  var POLICY_FILE = "test-policy.json";
27735
27776
  var TEST_RE = /\.(?:test|spec)\.[cm]?[jt]sx?$/;
27736
27777
  var PY_TEST_RE = /(?:^|\/)test_[^/]*\.py$|_test\.py$/;
@@ -27783,7 +27824,7 @@ function isTestPath(path2) {
27783
27824
  return TEST_RE.test(path2) || PY_TEST_RE.test(path2);
27784
27825
  }
27785
27826
  function loadPolicy(root, readFile9 = readFileOrNull2) {
27786
- const raw = readFile9((0, import_node_path28.join)(root, POLICY_FILE));
27827
+ const raw = readFile9((0, import_node_path29.join)(root, POLICY_FILE));
27787
27828
  if (raw == null) return { mandatory: [], declared: false };
27788
27829
  try {
27789
27830
  return { ...JSON.parse(raw), declared: true };
@@ -27793,7 +27834,7 @@ function loadPolicy(root, readFile9 = readFileOrNull2) {
27793
27834
  }
27794
27835
  function readFileOrNull2(path2) {
27795
27836
  try {
27796
- return (0, import_node_fs31.readFileSync)(path2, "utf8");
27837
+ return (0, import_node_fs32.readFileSync)(path2, "utf8");
27797
27838
  } catch {
27798
27839
  return null;
27799
27840
  }
@@ -27820,12 +27861,12 @@ function classify(changed, policy, present = () => false) {
27820
27861
  const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
27821
27862
  return { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected };
27822
27863
  }
27823
- function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs31.existsSync)(path2)) {
27824
- return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path28.join)(root, p)));
27864
+ function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs32.existsSync)(path2)) {
27865
+ return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path29.join)(root, p)));
27825
27866
  }
27826
- function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs31.existsSync)(path2)) {
27867
+ function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs32.existsSync)(path2)) {
27827
27868
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
27828
- return [...new Set(declared)].filter((p) => !exists((0, import_node_path28.join)(root, p)));
27869
+ return [...new Set(declared)].filter((p) => !exists((0, import_node_path29.join)(root, p)));
27829
27870
  }
27830
27871
  function evaluate(changed, policy, present = () => false) {
27831
27872
  const { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected } = classify(changed, policy, present);
@@ -28007,13 +28048,13 @@ function changedFilesSince(base, cwd) {
28007
28048
  }
28008
28049
  function runTestPolicy(root, deps = {}) {
28009
28050
  const policy = deps.policy ?? loadPolicy(root);
28010
- const exists = deps.exists ?? ((path2) => (0, import_node_fs31.existsSync)(path2));
28051
+ const exists = deps.exists ?? ((path2) => (0, import_node_fs32.existsSync)(path2));
28011
28052
  const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
28012
28053
  const base = deps.changed ? "(injected)" : resolveBase(root, deps.base);
28013
28054
  const refusal = deps.changed ? null : untrustworthyRange(root, base);
28014
28055
  const changed = deps.changed ?? (refusal ? [] : changedFilesSince(base, root));
28015
28056
  const lookup = deps.override !== void 0 ? { override: deps.override, refusals: [] } : !deps.changed && !refusal ? readOverride(base, root) : { override: null, refusals: [] };
28016
- const present = (path2) => exists((0, import_node_path28.join)(root, path2));
28057
+ const present = (path2) => exists((0, import_node_path29.join)(root, path2));
28017
28058
  const removedByThisDiff = removedPaths(changed);
28018
28059
  const staleFindings = [];
28019
28060
  const unresolved = unresolvedProtectedEntries(policy, root, exists).filter((p) => !removedByThisDiff.has(p));
@@ -28051,8 +28092,8 @@ function runTestPolicy(root, deps = {}) {
28051
28092
  }
28052
28093
 
28053
28094
  // src/project-info-sync.ts
28054
- var import_node_fs32 = require("node:fs");
28055
- var import_node_path29 = require("node:path");
28095
+ var import_node_fs33 = require("node:fs");
28096
+ var import_node_path30 = require("node:path");
28056
28097
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
28057
28098
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
28058
28099
  projectV2 { id }
@@ -28097,14 +28138,14 @@ function sharedName(entries, fallback) {
28097
28138
  }
28098
28139
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
28099
28140
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
28100
- const readmePath = (0, import_node_path29.join)(repoRoot2, "README.md");
28101
- if (!(0, import_node_fs32.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
28141
+ const readmePath = (0, import_node_path30.join)(repoRoot2, "README.md");
28142
+ if (!(0, import_node_fs33.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
28102
28143
  const entries = entriesFor(project2, projects);
28103
28144
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
28104
28145
  const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
28105
28146
  if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
28106
28147
  const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
28107
- const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs32.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
28148
+ const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs33.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
28108
28149
  const lines = [
28109
28150
  `# ${projectName}`,
28110
28151
  "",
@@ -28123,8 +28164,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
28123
28164
  const targetBase = `https://github.com/${targetRepo2}`;
28124
28165
  const targetBranch = branchFor(targetRepo2, projects);
28125
28166
  const orgDocs = [
28126
- (0, import_node_fs32.existsSync)((0, import_node_path29.join)(repoRoot2, "docs", "org-readme.md")) ? `- [Org identity](${targetBase}/blob/${targetBranch}/docs/org-readme.md)` : "",
28127
- (0, import_node_fs32.existsSync)((0, import_node_path29.join)(repoRoot2, "docs", "org-architecture.md")) ? `- [Org architecture](${targetBase}/blob/${targetBranch}/docs/org-architecture.md)` : ""
28167
+ (0, import_node_fs33.existsSync)((0, import_node_path30.join)(repoRoot2, "docs", "org-readme.md")) ? `- [Org identity](${targetBase}/blob/${targetBranch}/docs/org-readme.md)` : "",
28168
+ (0, import_node_fs33.existsSync)((0, import_node_path30.join)(repoRoot2, "docs", "org-architecture.md")) ? `- [Org architecture](${targetBase}/blob/${targetBranch}/docs/org-architecture.md)` : ""
28128
28169
  ].filter(Boolean);
28129
28170
  if (orgDocs.length) lines.push("", "## Organisation docs", "", ...orgDocs);
28130
28171
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines.join("\n")}
@@ -28909,8 +28950,8 @@ function writeError(res) {
28909
28950
  }
28910
28951
 
28911
28952
  // src/secrets-commands.ts
28912
- var import_node_fs33 = require("node:fs");
28913
- var import_node_path30 = require("node:path");
28953
+ var import_node_fs34 = require("node:fs");
28954
+ var import_node_path31 = require("node:path");
28914
28955
  var import_node_os13 = require("node:os");
28915
28956
 
28916
28957
  // src/secrets-diff.ts
@@ -29013,18 +29054,18 @@ function collectMap(value, previous = []) {
29013
29054
  return [...previous, value];
29014
29055
  }
29015
29056
  async function decryptRailsCredentials(input) {
29016
- const appDir = (0, import_node_path30.resolve)(input.appDir ?? process.cwd());
29057
+ const appDir = (0, import_node_path31.resolve)(input.appDir ?? process.cwd());
29017
29058
  const credentialsFile = input.credentialsFile ?? DEFAULT_RAILS_CREDENTIALS_FILE;
29018
29059
  const masterKeyFile = input.masterKeyFile ?? DEFAULT_RAILS_MASTER_KEY_FILE;
29019
- const credentialsPath = (0, import_node_path30.resolve)(appDir, credentialsFile);
29020
- const masterKeyPath = (0, import_node_path30.resolve)(appDir, masterKeyFile);
29060
+ const credentialsPath = (0, import_node_path31.resolve)(appDir, credentialsFile);
29061
+ const masterKeyPath = (0, import_node_path31.resolve)(appDir, masterKeyFile);
29021
29062
  const env = {
29022
29063
  ...process.env,
29023
29064
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
29024
29065
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
29025
29066
  };
29026
- if ((0, import_node_fs33.existsSync)(masterKeyPath)) {
29027
- env.RAILS_MASTER_KEY = (0, import_node_fs33.readFileSync)(masterKeyPath, "utf8").trim();
29067
+ if ((0, import_node_fs34.existsSync)(masterKeyPath)) {
29068
+ env.RAILS_MASTER_KEY = (0, import_node_fs34.readFileSync)(masterKeyPath, "utf8").trim();
29028
29069
  }
29029
29070
  const script = [
29030
29071
  'require "json"',
@@ -29034,9 +29075,9 @@ async function decryptRailsCredentials(input) {
29034
29075
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
29035
29076
  "puts JSON.generate(config.config)"
29036
29077
  ].join("\n");
29037
- const scriptDir = (0, import_node_fs33.mkdtempSync)((0, import_node_path30.join)((0, import_node_os13.tmpdir)(), "mmi-rails-decrypt-"));
29038
- const scriptPath = (0, import_node_path30.join)(scriptDir, "decrypt.rb");
29039
- (0, import_node_fs33.writeFileSync)(scriptPath, script, "utf8");
29078
+ const scriptDir = (0, import_node_fs34.mkdtempSync)((0, import_node_path31.join)((0, import_node_os13.tmpdir)(), "mmi-rails-decrypt-"));
29079
+ const scriptPath = (0, import_node_path31.join)(scriptDir, "decrypt.rb");
29080
+ (0, import_node_fs34.writeFileSync)(scriptPath, script, "utf8");
29040
29081
  try {
29041
29082
  const args = ["exec", "ruby", scriptPath];
29042
29083
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -29048,7 +29089,7 @@ async function decryptRailsCredentials(input) {
29048
29089
  });
29049
29090
  return JSON.parse(stdout);
29050
29091
  } finally {
29051
- (0, import_node_fs33.rmSync)(scriptDir, { recursive: true, force: true });
29092
+ (0, import_node_fs34.rmSync)(scriptDir, { recursive: true, force: true });
29052
29093
  }
29053
29094
  }
29054
29095
  async function readSecretStdin() {
@@ -29138,7 +29179,7 @@ function registerSecretsCommands(program3) {
29138
29179
  let body;
29139
29180
  if (o.file) {
29140
29181
  try {
29141
- body = (0, import_node_fs33.readFileSync)((0, import_node_path30.resolve)(o.file), "utf8");
29182
+ body = (0, import_node_fs34.readFileSync)((0, import_node_path31.resolve)(o.file), "utf8");
29142
29183
  } catch (e) {
29143
29184
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
29144
29185
  }
@@ -29243,7 +29284,7 @@ function registerSecretsCommands(program3) {
29243
29284
  {
29244
29285
  ...d,
29245
29286
  decryptRailsCredentials,
29246
- removeFile: (path2) => (0, import_node_fs33.unlinkSync)((0, import_node_path30.resolve)(o.appDir ?? process.cwd(), path2))
29287
+ removeFile: (path2) => (0, import_node_fs34.unlinkSync)((0, import_node_path31.resolve)(o.appDir ?? process.cwd(), path2))
29247
29288
  },
29248
29289
  {
29249
29290
  repo: o.repo,
@@ -29448,7 +29489,7 @@ function emitCliCallTelemetry(command) {
29448
29489
  }
29449
29490
 
29450
29491
  // src/box-commands.ts
29451
- var import_node_fs34 = require("node:fs");
29492
+ var import_node_fs35 = require("node:fs");
29452
29493
 
29453
29494
  // src/box.ts
29454
29495
  var BOX_KEYS = {
@@ -29651,7 +29692,7 @@ function registerBoxCommands(program3) {
29651
29692
  }
29652
29693
  if (o.json) console.log(JSON.stringify({ box: found, incomplete }, null, 2));
29653
29694
  else if (o.ssh && o.script) {
29654
- (0, import_node_fs34.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
29695
+ (0, import_node_fs35.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
29655
29696
  console.log(`wrote ${o.script} \u2014 run: bash "${o.script}"`);
29656
29697
  } else if (o.ssh) console.log(`${formatSshRecipe(found)}
29657
29698
  ${SSH_RECIPE_AGENT_NOTE}`);
@@ -29970,7 +30011,7 @@ function registerSchedulesCommands(program3) {
29970
30011
 
29971
30012
  // src/schedules-lift-command.ts
29972
30013
  var import_promises6 = require("node:fs/promises");
29973
- var import_node_path31 = require("node:path");
30014
+ var import_node_path32 = require("node:path");
29974
30015
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
29975
30016
  var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
29976
30017
  var SchedulesLiftUsageError = class extends Error {
@@ -29997,7 +30038,7 @@ async function readWorkflowFiles(dir) {
29997
30038
  const files = [];
29998
30039
  for (const name of names.sort()) {
29999
30040
  if (!/\.ya?ml$/.test(name)) continue;
30000
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises6.readFile)((0, import_node_path31.join)(dir, name), "utf8") });
30041
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises6.readFile)((0, import_node_path32.join)(dir, name), "utf8") });
30001
30042
  }
30002
30043
  return files;
30003
30044
  }
@@ -30145,9 +30186,9 @@ function registerEdgeCommands(program3) {
30145
30186
  }
30146
30187
 
30147
30188
  // src/bootstrap-commands.ts
30148
- var import_node_fs35 = require("node:fs");
30189
+ var import_node_fs36 = require("node:fs");
30149
30190
  var import_node_os14 = require("node:os");
30150
- var import_node_path32 = require("node:path");
30191
+ var import_node_path33 = require("node:path");
30151
30192
 
30152
30193
  // src/bootstrap-drift.ts
30153
30194
  var import_node_crypto6 = require("node:crypto");
@@ -31027,13 +31068,13 @@ function registerBootstrapCommands(program3) {
31027
31068
  client: defaultGitHubClient(),
31028
31069
  projectMeta: meta,
31029
31070
  deployModel: typeof meta?.deployModel === "string" ? meta.deployModel : void 0,
31030
- readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs35.existsSync)(path2) ? (0, import_node_fs35.readFileSync)(path2, "utf8") : null,
31071
+ readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs36.existsSync)(path2) ? (0, import_node_fs36.readFileSync)(path2, "utf8") : null,
31031
31072
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
31032
31073
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
31033
31074
  // #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
31034
31075
  // permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
31035
31076
  // sanction, which is the pre-#3664 behaviour.
31036
- sanctionedAdmins: (0, import_node_fs35.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs35.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
31077
+ sanctionedAdmins: (0, import_node_fs36.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs36.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
31037
31078
  requiredGcpApis: (() => {
31038
31079
  const v = meta?.requiredGcpApis;
31039
31080
  if (Array.isArray(v)) return v;
@@ -31086,14 +31127,14 @@ function registerBootstrapCommands(program3) {
31086
31127
  bootstrap.command("drift").description("#3818: compare every org-owned whole-file seed against MMI-Hub's copy across the registry roster; read-only").option("--repo <owner/repo>", "audit one repo instead of the roster (never a fleet verdict)").option("--json", "machine-readable output").action(async () => {
31087
31128
  const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
31088
31129
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31089
- if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap drift: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the reference this compares against`);
31130
+ if (!(0, import_node_fs36.existsSync)(manifestPath)) return fail(`bootstrap drift: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the reference this compares against`);
31090
31131
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31091
31132
  if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
31092
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31133
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31093
31134
  const hubContents = /* @__PURE__ */ new Map();
31094
31135
  for (const s of manifest.seeds) {
31095
31136
  if (s.ownership !== "org" || s.source !== "self") continue;
31096
- hubContents.set(s.target, (0, import_node_fs35.existsSync)(s.target) ? (0, import_node_fs35.readFileSync)(s.target, "utf8") : null);
31137
+ hubContents.set(s.target, (0, import_node_fs36.existsSync)(s.target) ? (0, import_node_fs36.readFileSync)(s.target, "utf8") : null);
31097
31138
  }
31098
31139
  let targets;
31099
31140
  let classOf = (_repo) => "deployable";
@@ -31172,10 +31213,10 @@ function registerBootstrapCommands(program3) {
31172
31213
  return fail(`bootstrap apply: ${e.message}`);
31173
31214
  }
31174
31215
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31175
- if (!(0, import_node_fs35.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`);
31216
+ if (!(0, import_node_fs36.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`);
31176
31217
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31177
31218
  if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
31178
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31219
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31179
31220
  const baseBranch = o.class === "content" ? "main" : "development";
31180
31221
  const slug = parsedRepo.slug;
31181
31222
  const onlyTarget = o.only.trim();
@@ -31186,16 +31227,16 @@ function registerBootstrapCommands(program3) {
31186
31227
  ${known}`);
31187
31228
  }
31188
31229
  const gh = async (args) => execFileP2("gh", args, { timeout: 2e4 });
31189
- const readFile9 = (p) => (0, import_node_fs35.existsSync)(p) ? (0, import_node_fs35.readFileSync)(p, "utf8") : null;
31230
+ const readFile9 = (p) => (0, import_node_fs36.existsSync)(p) ? (0, import_node_fs36.readFileSync)(p, "utf8") : null;
31190
31231
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
31191
31232
  const putSeed = async (target, content, ref, sha) => {
31192
- const tmp = (0, import_node_path32.join)((0, import_node_os14.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
31193
- (0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
31233
+ const tmp = (0, import_node_path33.join)((0, import_node_os14.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
31234
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
31194
31235
  try {
31195
31236
  await gh(contentPutInputArgs(repo, target, tmp));
31196
31237
  } finally {
31197
31238
  try {
31198
- (0, import_node_fs35.unlinkSync)(tmp);
31239
+ (0, import_node_fs36.unlinkSync)(tmp);
31199
31240
  } catch {
31200
31241
  }
31201
31242
  }
@@ -31460,10 +31501,10 @@ LIVE apply to ${repo}:
31460
31501
  bootstrap.command("propagate").description("#4238: re-entrant canary\u2192wave tick \u2014 plan (or, with --execute, open) per-repo PRs fanning an org-owned seed out to the fleet").option("--target <path>", "the manifest target to propagate (an ownership:org + source:self seed, e.g. .github/workflows/agent-pr.yml)").option("--execute", "LIVE tick via gh (master-gated) \u2014 opens/reuses per-repo seed-propagate PRs; dry-run prints the plan only").option("--json", "machine-readable output").action(async () => {
31461
31502
  const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
31462
31503
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31463
- if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap propagate: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the desired state this tick propagates`);
31504
+ if (!(0, import_node_fs36.existsSync)(manifestPath)) return fail(`bootstrap propagate: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the desired state this tick propagates`);
31464
31505
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31465
31506
  if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
31466
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31507
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31467
31508
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
31468
31509
  if (!o.target) {
31469
31510
  return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
@@ -31472,8 +31513,8 @@ LIVE apply to ${repo}:
31472
31513
  const seed = propagatable.find((s) => s.target === o.target);
31473
31514
  if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no ownership:org + source:self seed in ${manifestPath}. Propagatable targets:
31474
31515
  ${propagatable.map((s) => s.target).join("\n ")}`);
31475
- if (!(0, import_node_fs35.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
31476
- const hubContent = (0, import_node_fs35.readFileSync)(seed.target, "utf8");
31516
+ if (!(0, import_node_fs36.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
31517
+ const hubContent = (0, import_node_fs36.readFileSync)(seed.target, "utf8");
31477
31518
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
31478
31519
  const cfg = await loadConfig();
31479
31520
  const projects = await fetchProjectsList(registryClientDeps(cfg));
@@ -31482,9 +31523,9 @@ LIVE apply to ${repo}:
31482
31523
  }
31483
31524
  const rosterRepos2 = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
31484
31525
  let independentCount = rosterRepos2.length;
31485
- if ((0, import_node_fs35.existsSync)("projects.json")) {
31526
+ if ((0, import_node_fs36.existsSync)("projects.json")) {
31486
31527
  try {
31487
- const local = JSON.parse((0, import_node_fs35.readFileSync)("projects.json", "utf8"));
31528
+ const local = JSON.parse((0, import_node_fs36.readFileSync)("projects.json", "utf8"));
31488
31529
  const localRepos = /* @__PURE__ */ new Set();
31489
31530
  for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
31490
31531
  const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
@@ -31600,13 +31641,13 @@ LIVE apply to ${repo}:
31600
31641
  } catch {
31601
31642
  existingSha = void 0;
31602
31643
  }
31603
- const tmp = (0, import_node_path32.join)((0, import_node_os14.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
31604
- (0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, hubContent, branch, existingSha)), "utf8");
31644
+ const tmp = (0, import_node_path33.join)((0, import_node_os14.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
31645
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, hubContent, branch, existingSha)), "utf8");
31605
31646
  try {
31606
31647
  await gh(contentPutInputArgs(rec.repo, seed.target, tmp));
31607
31648
  } finally {
31608
31649
  try {
31609
- (0, import_node_fs35.unlinkSync)(tmp);
31650
+ (0, import_node_fs36.unlinkSync)(tmp);
31610
31651
  } catch {
31611
31652
  }
31612
31653
  }
@@ -31664,10 +31705,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31664
31705
  return fail(`bootstrap rollback: ${e.message}`);
31665
31706
  }
31666
31707
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31667
- if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap rollback: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the manifest names which targets are org-owned and therefore propagated (and rollback-able)`);
31708
+ if (!(0, import_node_fs36.existsSync)(manifestPath)) return fail(`bootstrap rollback: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the manifest names which targets are org-owned and therefore propagated (and rollback-able)`);
31668
31709
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31669
31710
  if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
31670
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31711
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31671
31712
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
31672
31713
  if (!o.target) {
31673
31714
  return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
@@ -31684,10 +31725,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31684
31725
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
31685
31726
  let candidates;
31686
31727
  if (o.record) {
31687
- if (!(0, import_node_fs35.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
31728
+ if (!(0, import_node_fs36.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
31688
31729
  let parsed;
31689
31730
  try {
31690
- parsed = JSON.parse((0, import_node_fs35.readFileSync)(o.record, "utf8"));
31731
+ parsed = JSON.parse((0, import_node_fs36.readFileSync)(o.record, "utf8"));
31691
31732
  } catch (e) {
31692
31733
  return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
31693
31734
  }
@@ -31756,13 +31797,13 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31756
31797
  } catch {
31757
31798
  existingSha = void 0;
31758
31799
  }
31759
- const tmp = (0, import_node_path32.join)((0, import_node_os14.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
31760
- (0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
31800
+ const tmp = (0, import_node_path33.join)((0, import_node_os14.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
31801
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
31761
31802
  try {
31762
31803
  await gh(contentPutInputArgs(repo, seed.target, tmp));
31763
31804
  } finally {
31764
31805
  try {
31765
- (0, import_node_fs35.unlinkSync)(tmp);
31806
+ (0, import_node_fs36.unlinkSync)(tmp);
31766
31807
  } catch {
31767
31808
  }
31768
31809
  }
@@ -31784,12 +31825,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31784
31825
  }
31785
31826
 
31786
31827
  // src/stage-commands.ts
31787
- var import_node_fs37 = require("node:fs");
31788
- var import_node_path34 = require("node:path");
31828
+ var import_node_fs38 = require("node:fs");
31829
+ var import_node_path35 = require("node:path");
31789
31830
 
31790
31831
  // src/port-registry.ts
31791
- var import_node_fs36 = require("node:fs");
31792
- var import_node_path33 = require("node:path");
31832
+ var import_node_fs37 = require("node:fs");
31833
+ var import_node_path34 = require("node:path");
31793
31834
 
31794
31835
  // ../infra/port-geometry.mjs
31795
31836
  var PORT_BLOCK = 100;
@@ -31803,8 +31844,8 @@ function nextPortBlock(registry2) {
31803
31844
  return [base, base + PORT_SPAN];
31804
31845
  }
31805
31846
  function loadPortRegistry(path2) {
31806
- if (!(0, import_node_fs36.existsSync)(path2)) return {};
31807
- const raw = JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8"));
31847
+ if (!(0, import_node_fs37.existsSync)(path2)) return {};
31848
+ const raw = JSON.parse((0, import_node_fs37.readFileSync)(path2, "utf8"));
31808
31849
  const out = {};
31809
31850
  for (const [key, value] of Object.entries(raw)) {
31810
31851
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -31818,9 +31859,9 @@ function ensurePortRange(repo, path2) {
31818
31859
  const existing = registry2[repo];
31819
31860
  if (existing) return existing;
31820
31861
  const range = nextPortBlock(registry2);
31821
- const raw = (0, import_node_fs36.existsSync)(path2) ? JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8")) : {};
31862
+ const raw = (0, import_node_fs37.existsSync)(path2) ? JSON.parse((0, import_node_fs37.readFileSync)(path2, "utf8")) : {};
31822
31863
  raw[repo] = range;
31823
- (0, import_node_fs36.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
31864
+ (0, import_node_fs37.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
31824
31865
  return range;
31825
31866
  }
31826
31867
  function portCursorSeed(registry2) {
@@ -31842,22 +31883,22 @@ function existingPortRange(repo, registry2) {
31842
31883
  return registry2[repo] ?? null;
31843
31884
  }
31844
31885
  function portRangeInfraAt(root, source) {
31845
- const registryPath = (0, import_node_path33.join)(root, "infra", "port-ranges.json");
31846
- const ddbScriptPath = (0, import_node_path33.join)(root, "infra", "port-ddb.mjs");
31847
- if (!(0, import_node_fs36.existsSync)(registryPath) || !(0, import_node_fs36.existsSync)(ddbScriptPath)) return null;
31886
+ const registryPath = (0, import_node_path34.join)(root, "infra", "port-ranges.json");
31887
+ const ddbScriptPath = (0, import_node_path34.join)(root, "infra", "port-ddb.mjs");
31888
+ if (!(0, import_node_fs37.existsSync)(registryPath) || !(0, import_node_fs37.existsSync)(ddbScriptPath)) return null;
31848
31889
  return { root, source, registryPath, ddbScriptPath };
31849
31890
  }
31850
31891
  function resolvePortRangeInfra(cwd, packageDir) {
31851
31892
  const direct = portRangeInfraAt(cwd, "cwd");
31852
31893
  if (direct) return direct;
31853
- for (let dir = cwd; ; dir = (0, import_node_path33.dirname)(dir)) {
31854
- const sibling = portRangeInfraAt((0, import_node_path33.join)(dir, "MMI-Hub"), "sibling-hub");
31894
+ for (let dir = cwd; ; dir = (0, import_node_path34.dirname)(dir)) {
31895
+ const sibling = portRangeInfraAt((0, import_node_path34.join)(dir, "MMI-Hub"), "sibling-hub");
31855
31896
  if (sibling) return sibling;
31856
- const parent = (0, import_node_path33.dirname)(dir);
31897
+ const parent = (0, import_node_path34.dirname)(dir);
31857
31898
  if (parent === dir) break;
31858
31899
  }
31859
31900
  if (packageDir) {
31860
- const pkgRoot = (0, import_node_path33.join)(packageDir, "..", "..");
31901
+ const pkgRoot = (0, import_node_path34.join)(packageDir, "..", "..");
31861
31902
  const pkgFrom = portRangeInfraAt(pkgRoot, "pkg-root");
31862
31903
  if (pkgFrom) return pkgFrom;
31863
31904
  }
@@ -32051,8 +32092,8 @@ function registerStageCommands(program3) {
32051
32092
  const portRange = portRangeMeta && typeof portRangeMeta.start === "number" && typeof portRangeMeta.end === "number" ? [portRangeMeta.start, portRangeMeta.end] : void 0;
32052
32093
  return decideStage({
32053
32094
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
32054
- hasCompose: (0, import_node_fs37.existsSync)((0, import_node_path34.join)(process.cwd(), "docker-compose.yml")),
32055
- hasEnvExample: (0, import_node_fs37.existsSync)((0, import_node_path34.join)(process.cwd(), ".env.example"))
32095
+ hasCompose: (0, import_node_fs38.existsSync)((0, import_node_path35.join)(process.cwd(), "docker-compose.yml")),
32096
+ hasEnvExample: (0, import_node_fs38.existsSync)((0, import_node_path35.join)(process.cwd(), ".env.example"))
32056
32097
  });
32057
32098
  }
32058
32099
  async function fetchStageVaultEnvMerge() {
@@ -32543,9 +32584,9 @@ function registerBoardCommands(program3) {
32543
32584
  }
32544
32585
 
32545
32586
  // src/merge-cleanup.ts
32546
- var import_node_fs38 = require("node:fs");
32587
+ var import_node_fs39 = require("node:fs");
32547
32588
  var import_promises8 = require("node:fs/promises");
32548
- var import_node_path36 = require("node:path");
32589
+ var import_node_path37 = require("node:path");
32549
32590
  var import_node_os15 = require("node:os");
32550
32591
  var import_node_child_process18 = require("node:child_process");
32551
32592
 
@@ -32633,7 +32674,7 @@ function boardAdvanceFailureMessage(result) {
32633
32674
 
32634
32675
  // src/deferred-registry-store.ts
32635
32676
  var import_promises7 = require("node:fs/promises");
32636
- var import_node_path35 = require("node:path");
32677
+ var import_node_path36 = require("node:path");
32637
32678
  var sleep2 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
32638
32679
  async function atomicWrite(target, contents) {
32639
32680
  const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
@@ -32684,12 +32725,12 @@ function makeDeferredWorktreeStore(registryPath, lockOpts = {}) {
32684
32725
  },
32685
32726
  // Standalone atomic write — THROWS on failure (no best-effort swallow, #2846).
32686
32727
  write: async (entries) => {
32687
- await (0, import_promises7.mkdir)((0, import_node_path35.dirname)(registryPath), { recursive: true });
32728
+ await (0, import_promises7.mkdir)((0, import_node_path36.dirname)(registryPath), { recursive: true });
32688
32729
  await atomicWrite(registryPath, serializeDeferredWorktrees(entries));
32689
32730
  },
32690
32731
  // Serialized read-modify-write under the repo-wide lock (#2846).
32691
32732
  update: async (mutate) => {
32692
- await (0, import_promises7.mkdir)((0, import_node_path35.dirname)(registryPath), { recursive: true });
32733
+ await (0, import_promises7.mkdir)((0, import_node_path36.dirname)(registryPath), { recursive: true });
32693
32734
  const deadline = Date.now() + opts.maxWaitMs;
32694
32735
  for (; ; ) {
32695
32736
  const guard = await acquireLock(lockPath, opts, deadline);
@@ -32860,7 +32901,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32860
32901
  );
32861
32902
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
32862
32903
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
32863
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path36.dirname)((0, import_node_path36.dirname)(worktreeGitRoot)) : repoRoot2;
32904
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path37.dirname)((0, import_node_path37.dirname)(worktreeGitRoot)) : repoRoot2;
32864
32905
  const gcActor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
32865
32906
  const owners = readWorktreeOwners(primaryRepoRoot);
32866
32907
  const removalNow = Date.now();
@@ -32917,7 +32958,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32917
32958
  const cleanup = await cleanupPrMergeLocalBranch(branch.branch, {
32918
32959
  beforeWorktrees,
32919
32960
  startingPath: branch.worktreePath,
32920
- pathExists: (p) => (0, import_node_fs38.existsSync)(p),
32961
+ pathExists: (p) => (0, import_node_fs39.existsSync)(p),
32921
32962
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
32922
32963
  teardownWorktreeStage,
32923
32964
  deferredStore,
@@ -32955,7 +32996,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32955
32996
  let removalAttempted = false;
32956
32997
  try {
32957
32998
  const cleanupTarget = resolveSafeSiblingWorktreeCleanupTarget(wt.path, cleanupRoots, {
32958
- realpath: (path2) => (0, import_node_fs38.realpathSync)(path2)
32999
+ realpath: (path2) => (0, import_node_fs39.realpathSync)(path2)
32959
33000
  });
32960
33001
  if (!cleanupTarget.ok) {
32961
33002
  result.failed.push(`${wt.path}: ${cleanupTarget.reason}`);
@@ -33042,13 +33083,13 @@ async function composeOverrideBodyFile(prNumber, repoArgs, gh) {
33042
33083
  const commits = JSON.parse(raw).commits ?? [];
33043
33084
  const body = squashBodyWithOverride(commits.map((c) => ({ headline: c.messageHeadline ?? "", body: c.messageBody ?? "" })), process.cwd());
33044
33085
  if (!body) return void 0;
33045
- const dir = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os15.tmpdir)(), "mmi-squash-body-"));
33046
- const path2 = (0, import_node_path36.join)(dir, "body.txt");
33047
- (0, import_node_fs38.writeFileSync)(path2, `${body}
33086
+ const dir = (0, import_node_fs39.mkdtempSync)((0, import_node_path37.join)((0, import_node_os15.tmpdir)(), "mmi-squash-body-"));
33087
+ const path2 = (0, import_node_path37.join)(dir, "body.txt");
33088
+ (0, import_node_fs39.writeFileSync)(path2, `${body}
33048
33089
  `, "utf8");
33049
33090
  return { path: path2, cleanup: () => {
33050
33091
  try {
33051
- (0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
33092
+ (0, import_node_fs39.rmSync)(dir, { recursive: true, force: true });
33052
33093
  } catch {
33053
33094
  }
33054
33095
  } };
@@ -33170,13 +33211,13 @@ var realWorktreeDirRemover = {
33170
33211
  probe: (p) => {
33171
33212
  let st;
33172
33213
  try {
33173
- st = (0, import_node_fs38.lstatSync)(p);
33214
+ st = (0, import_node_fs39.lstatSync)(p);
33174
33215
  } catch {
33175
33216
  return null;
33176
33217
  }
33177
33218
  if (st.isSymbolicLink()) return "link";
33178
33219
  try {
33179
- (0, import_node_fs38.readlinkSync)(p);
33220
+ (0, import_node_fs39.readlinkSync)(p);
33180
33221
  return "link";
33181
33222
  } catch {
33182
33223
  }
@@ -33184,7 +33225,7 @@ var realWorktreeDirRemover = {
33184
33225
  },
33185
33226
  readdir: (p) => {
33186
33227
  try {
33187
- return (0, import_node_fs38.readdirSync)(p);
33228
+ return (0, import_node_fs39.readdirSync)(p);
33188
33229
  } catch {
33189
33230
  return [];
33190
33231
  }
@@ -33193,9 +33234,9 @@ var realWorktreeDirRemover = {
33193
33234
  // leaving the target); a file symlink with unlink. rmdir first, fall back to unlink.
33194
33235
  detachLink: (p) => {
33195
33236
  try {
33196
- (0, import_node_fs38.rmdirSync)(p);
33237
+ (0, import_node_fs39.rmdirSync)(p);
33197
33238
  } catch {
33198
- (0, import_node_fs38.unlinkSync)(p);
33239
+ (0, import_node_fs39.unlinkSync)(p);
33199
33240
  }
33200
33241
  },
33201
33242
  removeTree: (p) => (0, import_promises8.rm)(p, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
@@ -33228,9 +33269,9 @@ async function worktreeHasStageState(worktreePath) {
33228
33269
  }
33229
33270
  }
33230
33271
  function stageStateFileBelongsToWorktree(statePath, worktreePath) {
33231
- if (!(0, import_node_fs38.existsSync)(statePath)) return false;
33272
+ if (!(0, import_node_fs39.existsSync)(statePath)) return false;
33232
33273
  try {
33233
- const state = JSON.parse((0, import_node_fs38.readFileSync)(statePath, "utf8"));
33274
+ const state = JSON.parse((0, import_node_fs39.readFileSync)(statePath, "utf8"));
33234
33275
  const recordedCwd = typeof state.identity?.cwd === "string" ? state.identity.cwd : typeof state.cwd === "string" ? state.cwd : "";
33235
33276
  return Boolean(recordedCwd && isPathUnderDirectory2(recordedCwd, worktreePath));
33236
33277
  } catch {
@@ -33665,14 +33706,14 @@ async function checkDocsIndexAtHead(opts, deps) {
33665
33706
  }
33666
33707
 
33667
33708
  // src/worktree-lifecycle-commands.ts
33668
- var import_node_fs40 = require("node:fs");
33709
+ var import_node_fs41 = require("node:fs");
33669
33710
  var import_promises9 = require("node:fs/promises");
33670
- var import_node_path38 = require("node:path");
33711
+ var import_node_path39 = require("node:path");
33671
33712
 
33672
33713
  // src/worktree-install-cache.ts
33673
33714
  var import_node_crypto7 = require("node:crypto");
33674
- var import_node_fs39 = require("node:fs");
33675
- var import_node_path37 = require("node:path");
33715
+ var import_node_fs40 = require("node:fs");
33716
+ var import_node_path38 = require("node:path");
33676
33717
  var CACHE_DIR = "worktree-install-cache";
33677
33718
  var MANIFEST = "manifest.json";
33678
33719
  var NODE_MODULES2 = "node_modules";
@@ -33685,16 +33726,16 @@ var LOCKFILE_NAMES = [
33685
33726
  "package-lock.json"
33686
33727
  ];
33687
33728
  var realWorktreeInstallCacheFs = {
33688
- exists: import_node_fs39.existsSync,
33689
- readFile: (path2) => (0, import_node_fs39.readFileSync)(path2, "utf8"),
33690
- lstat: (path2) => (0, import_node_fs39.lstatSync)(path2),
33691
- copyDir: (from, to) => (0, import_node_fs39.cpSync)(from, to, { recursive: true, force: true }),
33729
+ exists: import_node_fs40.existsSync,
33730
+ readFile: (path2) => (0, import_node_fs40.readFileSync)(path2, "utf8"),
33731
+ lstat: (path2) => (0, import_node_fs40.lstatSync)(path2),
33732
+ copyDir: (from, to) => (0, import_node_fs40.cpSync)(from, to, { recursive: true, force: true }),
33692
33733
  mkdirp: (path2) => {
33693
- (0, import_node_fs39.mkdirSync)(path2, { recursive: true });
33734
+ (0, import_node_fs40.mkdirSync)(path2, { recursive: true });
33694
33735
  },
33695
- writeFile: (path2, contents) => (0, import_node_fs39.writeFileSync)(path2, contents, "utf8"),
33736
+ writeFile: (path2, contents) => (0, import_node_fs40.writeFileSync)(path2, contents, "utf8"),
33696
33737
  rm: (path2) => {
33697
- (0, import_node_fs39.rmSync)(path2, { recursive: true, force: true });
33738
+ (0, import_node_fs40.rmSync)(path2, { recursive: true, force: true });
33698
33739
  }
33699
33740
  };
33700
33741
  function hashLockfileBytes(contents) {
@@ -33702,7 +33743,7 @@ function hashLockfileBytes(contents) {
33702
33743
  }
33703
33744
  function resolveWorktreeInstallLockfile(packageDir, fs2 = realWorktreeInstallCacheFs) {
33704
33745
  for (const name of LOCKFILE_NAMES) {
33705
- const path2 = (0, import_node_path37.join)(packageDir, name);
33746
+ const path2 = (0, import_node_path38.join)(packageDir, name);
33706
33747
  if (!fs2.exists(path2)) continue;
33707
33748
  try {
33708
33749
  const hash = hashLockfileBytes(fs2.readFile(path2));
@@ -33717,8 +33758,8 @@ function worktreeInstallCacheEntry(primaryRoot, lockfileHash) {
33717
33758
  const root = repoRuntimeStatePath(primaryRoot, CACHE_DIR, lockfileHash);
33718
33759
  return {
33719
33760
  root,
33720
- manifestPath: (0, import_node_path37.join)(root, MANIFEST),
33721
- nodeModulesPath: (0, import_node_path37.join)(root, NODE_MODULES2)
33761
+ manifestPath: (0, import_node_path38.join)(root, MANIFEST),
33762
+ nodeModulesPath: (0, import_node_path38.join)(root, NODE_MODULES2)
33722
33763
  };
33723
33764
  }
33724
33765
  function readWorktreeInstallCacheManifest(manifestPath, fs2 = realWorktreeInstallCacheFs) {
@@ -33758,7 +33799,7 @@ function invalidateWorktreeInstallCacheEntry(entry, fs2 = realWorktreeInstallCac
33758
33799
  }
33759
33800
  }
33760
33801
  function removeMaterializedTree(packageDir, fs2) {
33761
- const dest = (0, import_node_path37.join)(packageDir, NODE_MODULES2);
33802
+ const dest = (0, import_node_path38.join)(packageDir, NODE_MODULES2);
33762
33803
  if (!fs2.exists(dest)) return;
33763
33804
  fs2.rm(dest);
33764
33805
  if (fs2.exists(dest)) {
@@ -33766,7 +33807,7 @@ function removeMaterializedTree(packageDir, fs2) {
33766
33807
  }
33767
33808
  }
33768
33809
  function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeInstallCacheFs) {
33769
- const dest = (0, import_node_path37.join)(destPackageDir, NODE_MODULES2);
33810
+ const dest = (0, import_node_path38.join)(destPackageDir, NODE_MODULES2);
33770
33811
  try {
33771
33812
  if (fs2.exists(dest)) fs2.rm(dest);
33772
33813
  fs2.mkdirp(destPackageDir);
@@ -33781,7 +33822,7 @@ function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeI
33781
33822
  }
33782
33823
  }
33783
33824
  async function storeWorktreeInstallCacheEntry(primaryRoot, lockfile3, command, sourcePackageDir, fs2 = realWorktreeInstallCacheFs, now = Date.now()) {
33784
- const source = (0, import_node_path37.join)(sourcePackageDir, NODE_MODULES2);
33825
+ const source = (0, import_node_path38.join)(sourcePackageDir, NODE_MODULES2);
33785
33826
  if (!isMaterializableNodeModulesDir(source, fs2)) return;
33786
33827
  const entry = worktreeInstallCacheEntry(primaryRoot, lockfile3.hash);
33787
33828
  const manifest = {
@@ -34041,7 +34082,7 @@ function classifyStaleLeaks(input) {
34041
34082
  var defaultOrphanDirScanDeps = {
34042
34083
  listDirs: (root) => {
34043
34084
  try {
34044
- return (0, import_node_fs40.readdirSync)(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path38.join)(root, e.name));
34085
+ return (0, import_node_fs41.readdirSync)(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path39.join)(root, e.name));
34045
34086
  } catch {
34046
34087
  return [];
34047
34088
  }
@@ -34207,13 +34248,13 @@ function registerWorktreeCommands(program3) {
34207
34248
  const detached = headBorn && !symbolicBranch;
34208
34249
  const branch = symbolicBranch || (detached ? "HEAD" : "");
34209
34250
  if (!wtPath || !branch) return fail("worktree land: not inside a git worktree");
34210
- const gitFile = (0, import_node_path38.join)(wtPath, ".git");
34211
- const isLinked = (0, import_node_fs40.existsSync)(gitFile) && (0, import_node_fs40.statSync)(gitFile).isFile();
34251
+ const gitFile = (0, import_node_path39.join)(wtPath, ".git");
34252
+ const isLinked = (0, import_node_fs41.existsSync)(gitFile) && (0, import_node_fs41.statSync)(gitFile).isFile();
34212
34253
  if (apply && !isLinked) {
34213
34254
  return fail("worktree land: run from inside the linked worktree you want to land (this is the primary checkout)");
34214
34255
  }
34215
34256
  const commonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
34216
- const primaryCheckout = commonDir ? (0, import_node_path38.dirname)(commonDir) : wtPath;
34257
+ const primaryCheckout = commonDir ? (0, import_node_path39.dirname)(commonDir) : wtPath;
34217
34258
  const localBranchNames = await execFileP2("git", ["-C", primaryCheckout, "for-each-ref", "--format=%(refname:short)", "refs/heads"], { timeout: GIT_TIMEOUT_MS }).then(({ stdout }) => new Set((stdout || "").split("\n").map((l) => l.trim()).filter(Boolean))).catch(() => void 0);
34218
34259
  const orphan = classifyOrphanedWorktree({
34219
34260
  branch,
@@ -34487,10 +34528,10 @@ async function gatherWorktreeContext() {
34487
34528
  if (s) stages.push({ path: wt.path, port: s.port });
34488
34529
  }
34489
34530
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
34490
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path38.dirname)((0, import_node_path38.dirname)(worktreeGitRoot)) : repoRoot2;
34531
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path39.dirname)((0, import_node_path39.dirname)(worktreeGitRoot)) : repoRoot2;
34491
34532
  const wtRoot = siblingMmiWorktreesRoot(primaryRepoRoot);
34492
34533
  let orphanDirs = [];
34493
- if ((0, import_node_fs40.existsSync)(wtRoot)) {
34534
+ if ((0, import_node_fs41.existsSync)(wtRoot)) {
34494
34535
  orphanDirs = scanOrphanDirs(wtRoot, worktreeGitRoot, {
34495
34536
  ...defaultOrphanDirScanDeps,
34496
34537
  listDirs: (root) => worktreeScanDirs(root, primaryRepoRoot, defaultOrphanDirScanDeps.listDirs, isRepoCheckoutDir)
@@ -34526,7 +34567,7 @@ ${err.stderr ?? ""}`;
34526
34567
  }
34527
34568
 
34528
34569
  // src/issue-commands.ts
34529
- var import_node_fs41 = require("node:fs");
34570
+ var import_node_fs42 = require("node:fs");
34530
34571
  var import_node_crypto8 = require("node:crypto");
34531
34572
  var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
34532
34573
  var ReparentConflictError = class extends Error {
@@ -34544,7 +34585,7 @@ async function editIssue(client, options, deps = {}) {
34544
34585
  const url = `https://github.com/${repo}/issues/${parsed.number}`;
34545
34586
  const patch = {};
34546
34587
  let bodyChanged = false;
34547
- const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs41.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
34588
+ const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs42.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
34548
34589
  if (options.titleFile !== void 0) {
34549
34590
  patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
34550
34591
  } else if (options.title !== void 0) {
@@ -35149,7 +35190,7 @@ function extendCreateCommand(issue2, batchAttach) {
35149
35190
  if (opts.batch) {
35150
35191
  let specs;
35151
35192
  try {
35152
- const raw = (0, import_node_fs41.readFileSync)(opts.batch, "utf8");
35193
+ const raw = (0, import_node_fs42.readFileSync)(opts.batch, "utf8");
35153
35194
  specs = JSON.parse(raw);
35154
35195
  if (!Array.isArray(specs)) throw new Error("batch file must contain a JSON array");
35155
35196
  } catch (e) {
@@ -35224,8 +35265,8 @@ ${lines}`, {
35224
35265
  }
35225
35266
 
35226
35267
  // src/train-commands.ts
35227
- var import_node_fs42 = require("node:fs");
35228
- var import_node_path39 = require("node:path");
35268
+ var import_node_fs43 = require("node:fs");
35269
+ var import_node_path40 = require("node:path");
35229
35270
  var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
35230
35271
  function resolveReleaseBumpIntent(raw) {
35231
35272
  const intent = typeof raw === "string" ? raw.trim() : "";
@@ -35236,7 +35277,7 @@ function resolveReleaseBumpIntent(raw) {
35236
35277
  }
35237
35278
  function readRepoVersion() {
35238
35279
  try {
35239
- return JSON.parse((0, import_node_fs42.readFileSync)((0, import_node_path39.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
35280
+ return JSON.parse((0, import_node_fs43.readFileSync)((0, import_node_path40.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
35240
35281
  } catch {
35241
35282
  return void 0;
35242
35283
  }
@@ -35393,9 +35434,9 @@ function registerDeployCommands(program3) {
35393
35434
  }
35394
35435
 
35395
35436
  // src/discovery-commands.ts
35396
- var import_node_fs43 = require("node:fs");
35437
+ var import_node_fs44 = require("node:fs");
35397
35438
  var import_node_os16 = require("node:os");
35398
- var import_node_path40 = require("node:path");
35439
+ var import_node_path41 = require("node:path");
35399
35440
  var GC_GH_TIMEOUT_MS3 = 2e4;
35400
35441
  async function collectStatus() {
35401
35442
  const repo = await resolveRepo();
@@ -35585,8 +35626,8 @@ async function collectOnboardStatus(opts = {}) {
35585
35626
  }
35586
35627
  const home = (0, import_node_os16.homedir)();
35587
35628
  const plugin = onboardPluginGate({
35588
- readKnown: () => readFileSyncSafe((0, import_node_path40.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs43.readFileSync),
35589
- readSettings: () => readFileSyncSafe((0, import_node_path40.join)(home, ".claude", "settings.json"), import_node_fs43.readFileSync)
35629
+ readKnown: () => readFileSyncSafe((0, import_node_path41.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs44.readFileSync),
35630
+ readSettings: () => readFileSyncSafe((0, import_node_path41.join)(home, ".claude", "settings.json"), import_node_fs44.readFileSync)
35590
35631
  });
35591
35632
  return { track, board, registry: registry2, secrets, plugin, estateCli, doors: opts.doors ?? [], nextCommand };
35592
35633
  }
@@ -36685,19 +36726,19 @@ function registerOrgHealthQuery(program3, deps = defaultOrgHealthQueryDeps()) {
36685
36726
  }
36686
36727
 
36687
36728
  // src/plugin-release-catchup.ts
36688
- var import_node_fs44 = require("node:fs");
36689
- var import_node_path41 = require("node:path");
36729
+ var import_node_fs45 = require("node:fs");
36730
+ var import_node_path42 = require("node:path");
36690
36731
  var import_node_os17 = require("node:os");
36691
36732
  var RELEASE_CATCHUP_TTL_MS = 24 * 60 * 60 * 1e3;
36692
36733
  var RELEASE_CATCHUP_DISABLE_ENV = "MMI_NO_RELEASE_CATCHUP";
36693
36734
  function releaseCatchupStatePath(env = process.env) {
36694
36735
  if (env.MMI_RELEASE_CATCHUP_STATE) return env.MMI_RELEASE_CATCHUP_STATE;
36695
36736
  if (process.platform === "win32") {
36696
- const base2 = env.LOCALAPPDATA || (0, import_node_path41.join)((0, import_node_os17.homedir)(), "AppData", "Local");
36697
- return (0, import_node_path41.join)(base2, "MMI Future", "mmi-cli", "release-catchup.json");
36737
+ const base2 = env.LOCALAPPDATA || (0, import_node_path42.join)((0, import_node_os17.homedir)(), "AppData", "Local");
36738
+ return (0, import_node_path42.join)(base2, "MMI Future", "mmi-cli", "release-catchup.json");
36698
36739
  }
36699
- const base = env.XDG_STATE_HOME || (0, import_node_path41.join)((0, import_node_os17.homedir)(), ".local", "state");
36700
- return (0, import_node_path41.join)(base, "mmi-cli", "release-catchup.json");
36740
+ const base = env.XDG_STATE_HOME || (0, import_node_path42.join)((0, import_node_os17.homedir)(), ".local", "state");
36741
+ return (0, import_node_path42.join)(base, "mmi-cli", "release-catchup.json");
36701
36742
  }
36702
36743
  function releaseCatchupDue(state, now, force = false) {
36703
36744
  if (force) return true;
@@ -36707,7 +36748,7 @@ function releaseCatchupDue(state, now, force = false) {
36707
36748
  function newestCachedPluginVersion(home) {
36708
36749
  let names;
36709
36750
  try {
36710
- names = (0, import_node_fs44.readdirSync)(pluginCacheRoot(home));
36751
+ names = (0, import_node_fs45.readdirSync)(pluginCacheRoot(home));
36711
36752
  } catch {
36712
36753
  return void 0;
36713
36754
  }
@@ -36715,15 +36756,15 @@ function newestCachedPluginVersion(home) {
36715
36756
  }
36716
36757
  function marketplaceClonePath(home) {
36717
36758
  try {
36718
- const parsed = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(home, ".claude", "plugins", "known_marketplaces.json"), "utf8"));
36759
+ const parsed = JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(home, ".claude", "plugins", "known_marketplaces.json"), "utf8"));
36719
36760
  if (parsed.mutmutco?.installLocation) return parsed.mutmutco.installLocation;
36720
36761
  } catch {
36721
36762
  }
36722
- return (0, import_node_path41.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
36763
+ return (0, import_node_path42.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
36723
36764
  }
36724
36765
  function readCatalogVersion(home) {
36725
36766
  try {
36726
- const parsed = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(marketplaceClonePath(home), ".claude-plugin", "marketplace.json"), "utf8"));
36767
+ const parsed = JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(marketplaceClonePath(home), ".claude-plugin", "marketplace.json"), "utf8"));
36727
36768
  return parsed.plugins?.find((p) => p.name === "mmi")?.version;
36728
36769
  } catch {
36729
36770
  return void 0;
@@ -36731,7 +36772,7 @@ function readCatalogVersion(home) {
36731
36772
  }
36732
36773
  function readMmiInstallRecord(home) {
36733
36774
  try {
36734
- const parsed = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(home, ".claude", "plugins", "installed_plugins.json"), "utf8"));
36775
+ const parsed = JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(home, ".claude", "plugins", "installed_plugins.json"), "utf8"));
36735
36776
  const record = parsed.plugins?.["mmi@mutmutco"]?.[0];
36736
36777
  return record?.version ? { version: record.version, gitCommitSha: record.gitCommitSha } : void 0;
36737
36778
  } catch {
@@ -36760,7 +36801,7 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
36760
36801
  cliUpdated = true;
36761
36802
  }
36762
36803
  const cliUpdateDetail = cliUpdated ? `CLI ${runningCli} \u2192 ${latest}; the next mmi-cli invocation runs ${latest}` : `CLI ${runningCli} is current against released ${latest}`;
36763
- if (!(0, import_node_fs44.existsSync)(pluginCacheRoot(home))) {
36804
+ if (!(0, import_node_fs45.existsSync)(pluginCacheRoot(home))) {
36764
36805
  deps.writeState(statePath, { checkedAt: deps.now(), latest });
36765
36806
  return {
36766
36807
  ok: true,
@@ -36793,8 +36834,8 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
36793
36834
  return { ok: false, detail: `${cliUpdateDetail}; plugin install record could not be cleared (still ${prior.version})` };
36794
36835
  }
36795
36836
  const installed = await deps.runClaude(["plugin", "install", "mmi@mutmutco"], "claude plugin install mmi@mutmutco");
36796
- const payload = (0, import_node_path41.join)(pluginCacheRoot(home), latest, ".pi-plugin");
36797
- if (!installed || !(0, import_node_fs44.existsSync)(payload)) {
36837
+ const payload = (0, import_node_path42.join)(pluginCacheRoot(home), latest, ".pi-plugin");
36838
+ if (!installed || !(0, import_node_fs45.existsSync)(payload)) {
36798
36839
  const why = installed ? `install of ${latest} did not produce a verifiable .pi-plugin payload` : `install of ${latest} failed`;
36799
36840
  if (!prior) return { ok: false, detail: `${cliUpdateDetail}; ${why}; no prior record to restore` };
36800
36841
  const rollback = await restorePriorRecord(home, prior, deps);
@@ -38767,6 +38808,7 @@ async function runDoctorClean(opts, io, deps) {
38767
38808
  });
38768
38809
  return;
38769
38810
  }
38811
+ const provenance = state.cachedAt === void 0 ? [] : [cachedSweepNote(state.cachedAt)];
38770
38812
  if (state.driftLines.length === 0) {
38771
38813
  emitNow({
38772
38814
  ok: true,
@@ -38774,7 +38816,7 @@ async function runDoctorClean(opts, io, deps) {
38774
38816
  id: "schedules-drift",
38775
38817
  label: "schedules drift",
38776
38818
  detail: "no drift",
38777
- verbose: ["no drift lines"]
38819
+ verbose: ["no drift lines", ...provenance]
38778
38820
  });
38779
38821
  return;
38780
38822
  }
@@ -38785,7 +38827,7 @@ async function runDoctorClean(opts, io, deps) {
38785
38827
  label: "schedules drift",
38786
38828
  detail: `${state.driftLines.length} drift line(s)`,
38787
38829
  fix: "run `mmi-cli harbour org schedules` / `org schedules register`",
38788
- verbose: state.driftLines
38830
+ verbose: [...state.driftLines, ...provenance]
38789
38831
  });
38790
38832
  } catch (e) {
38791
38833
  const message = e instanceof Error ? e.message : String(e);
@@ -39002,17 +39044,17 @@ function parseOriginRepo(remoteUrl) {
39002
39044
  }
39003
39045
  function ghHostsConfigPath(env, platform2) {
39004
39046
  const sep3 = platform2 === "win32" ? "\\" : "/";
39005
- const join39 = (...parts) => parts.join(sep3);
39047
+ const join40 = (...parts) => parts.join(sep3);
39006
39048
  const explicit = env.GH_CONFIG_DIR?.trim();
39007
- if (explicit) return join39(explicit, "hosts.yml");
39049
+ if (explicit) return join40(explicit, "hosts.yml");
39008
39050
  if (platform2 === "win32") {
39009
39051
  const appData = (env.AppData ?? env.APPDATA)?.trim();
39010
- return appData ? join39(appData, "GitHub CLI", "hosts.yml") : void 0;
39052
+ return appData ? join40(appData, "GitHub CLI", "hosts.yml") : void 0;
39011
39053
  }
39012
39054
  const xdg = env.XDG_CONFIG_HOME?.trim();
39013
- if (xdg) return join39(xdg, "gh", "hosts.yml");
39055
+ if (xdg) return join40(xdg, "gh", "hosts.yml");
39014
39056
  const home = env.HOME?.trim();
39015
- return home ? join39(home, ".config", "gh", "hosts.yml") : void 0;
39057
+ return home ? join40(home, ".config", "gh", "hosts.yml") : void 0;
39016
39058
  }
39017
39059
  function parseGhHostsAccounts(yaml, host = "github.com") {
39018
39060
  let hostIndent = null;
@@ -39062,9 +39104,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
39062
39104
  }
39063
39105
 
39064
39106
  // src/doctor-io.ts
39065
- var import_node_fs45 = require("node:fs");
39107
+ var import_node_fs46 = require("node:fs");
39066
39108
  var import_node_os18 = require("node:os");
39067
- var import_node_path42 = require("node:path");
39109
+ var import_node_path43 = require("node:path");
39068
39110
  var import_node_child_process19 = require("node:child_process");
39069
39111
  var import_node_util8 = require("node:util");
39070
39112
  var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process19.execFile);
@@ -39072,7 +39114,7 @@ var MMI_PLUGIN_ID2 = "mmi@mutmutco";
39072
39114
  function installedClaudePluginVersion() {
39073
39115
  try {
39074
39116
  const file = JSON.parse(
39075
- (0, import_node_fs45.readFileSync)((0, import_node_path42.join)((0, import_node_os18.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
39117
+ (0, import_node_fs46.readFileSync)((0, import_node_path43.join)((0, import_node_os18.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
39076
39118
  );
39077
39119
  const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
39078
39120
  if (versions.length === 0) return void 0;
@@ -39083,7 +39125,7 @@ function installedClaudePluginVersion() {
39083
39125
  }
39084
39126
  function manifestVersion(path2) {
39085
39127
  try {
39086
- const manifest = JSON.parse((0, import_node_fs45.readFileSync)(path2, "utf8"));
39128
+ const manifest = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
39087
39129
  return typeof manifest.version === "string" && manifest.version.trim() ? manifest.version.trim() : void 0;
39088
39130
  } catch {
39089
39131
  return void 0;
@@ -39093,22 +39135,22 @@ function installedSurfacePluginVersion(surface) {
39093
39135
  const token = surfaceToken(surface);
39094
39136
  if (token === "kilo") {
39095
39137
  try {
39096
- const stamp = (0, import_node_fs45.readFileSync)((0, import_node_path42.join)((0, import_node_os18.homedir)(), ".kilo", ".mmi-kilo-version"), "utf8").trim();
39138
+ const stamp = (0, import_node_fs46.readFileSync)((0, import_node_path43.join)((0, import_node_os18.homedir)(), ".kilo", ".mmi-kilo-version"), "utf8").trim();
39097
39139
  return stamp || void 0;
39098
39140
  } catch {
39099
39141
  return void 0;
39100
39142
  }
39101
39143
  }
39102
39144
  if (token === "cursor") {
39103
- return manifestVersion((0, import_node_path42.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
39145
+ return manifestVersion((0, import_node_path43.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
39104
39146
  }
39105
39147
  if (token === "jervcode") {
39106
39148
  const entry = mmiPiWrapperEntry();
39107
39149
  if (!entry) return void 0;
39108
- return manifestVersion((0, import_node_path42.join)(decodeURIComponent(entry.replace(/^file:\/\/\/?/, "")), "package.json"));
39150
+ return manifestVersion((0, import_node_path43.join)(decodeURIComponent(entry.replace(/^file:\/\/\/?/, "")), "package.json"));
39109
39151
  }
39110
39152
  if (token === "kimi") {
39111
- return manifestVersion((0, import_node_path42.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
39153
+ return manifestVersion((0, import_node_path43.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
39112
39154
  }
39113
39155
  if (token === "claude") return installedClaudePluginVersion();
39114
39156
  if (token !== "codex") return void 0;
@@ -39146,13 +39188,13 @@ function worktreeRootSync() {
39146
39188
  }
39147
39189
  var gitignorePath = () => {
39148
39190
  const root = worktreeRootSync();
39149
- return root === null ? null : (0, import_node_path42.join)(root, ".gitignore");
39191
+ return root === null ? null : (0, import_node_path43.join)(root, ".gitignore");
39150
39192
  };
39151
39193
  function readGitignore() {
39152
39194
  const path2 = gitignorePath();
39153
39195
  if (path2 === null) return null;
39154
39196
  try {
39155
- return (0, import_node_fs45.readFileSync)(path2, "utf8");
39197
+ return (0, import_node_fs46.readFileSync)(path2, "utf8");
39156
39198
  } catch {
39157
39199
  return null;
39158
39200
  }
@@ -39161,7 +39203,7 @@ function writeGitignore(content) {
39161
39203
  const path2 = gitignorePath();
39162
39204
  if (path2 === null) return false;
39163
39205
  try {
39164
- (0, import_node_fs45.writeFileSync)(path2, content, "utf8");
39206
+ (0, import_node_fs46.writeFileSync)(path2, content, "utf8");
39165
39207
  return true;
39166
39208
  } catch {
39167
39209
  return false;
@@ -39180,7 +39222,7 @@ async function repoRoot() {
39180
39222
  }
39181
39223
  function hasRepoLocalWorktrees() {
39182
39224
  const root = worktreeRootSync();
39183
- return root !== null && (0, import_node_fs45.existsSync)((0, import_node_path42.join)(root, ".worktrees"));
39225
+ return root !== null && (0, import_node_fs46.existsSync)((0, import_node_path43.join)(root, ".worktrees"));
39184
39226
  }
39185
39227
 
39186
39228
  // src/index.ts
@@ -39199,8 +39241,8 @@ ${r.stderr ?? ""}`).catch(() => "");
39199
39241
  function ghMultiAccountCaveat(announcedLogin) {
39200
39242
  try {
39201
39243
  const hostsPath = ghHostsConfigPath(process.env, process.platform);
39202
- if (!hostsPath || !(0, import_node_fs46.existsSync)(hostsPath)) return void 0;
39203
- return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0, import_node_fs46.readFileSync)(hostsPath, "utf8")));
39244
+ if (!hostsPath || !(0, import_node_fs47.existsSync)(hostsPath)) return void 0;
39245
+ return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0, import_node_fs47.readFileSync)(hostsPath, "utf8")));
39204
39246
  } catch {
39205
39247
  return void 0;
39206
39248
  }
@@ -39208,7 +39250,7 @@ function ghMultiAccountCaveat(announcedLogin) {
39208
39250
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
39209
39251
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
39210
39252
  function envHealLockPath(home) {
39211
- return (0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
39253
+ return (0, import_node_path44.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
39212
39254
  }
39213
39255
  async function withEnvHealLock(what, run) {
39214
39256
  try {
@@ -39341,7 +39383,7 @@ function mmiDoctorDeps(opts = {}) {
39341
39383
  );
39342
39384
  const result = applyPluginCachePlan(
39343
39385
  plan,
39344
- (p) => (0, import_node_fs46.rmSync)(p, { recursive: true }),
39386
+ (p) => (0, import_node_fs47.rmSync)(p, { recursive: true }),
39345
39387
  stagingApplyFsGuard(configRoot)
39346
39388
  );
39347
39389
  return {
@@ -39395,8 +39437,8 @@ function mmiDoctorDeps(opts = {}) {
39395
39437
  const home = (0, import_node_os19.homedir)();
39396
39438
  const rows = marketplaceRows(
39397
39439
  MMI_MARKETPLACE_NAME,
39398
- readFileSyncSafe((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
39399
- readFileSyncSafe((0, import_node_path43.join)(home, ".claude", "settings.json"), import_node_fs46.readFileSync),
39440
+ readFileSyncSafe((0, import_node_path44.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs47.readFileSync),
39441
+ readFileSyncSafe((0, import_node_path44.join)(home, ".claude", "settings.json"), import_node_fs47.readFileSync),
39400
39442
  // #3974: this CLI heals these rows, so report mode names the doctor run rather than the hand
39401
39443
  // edit. #4792 narrows WHICH run: `applyOrgMarketplacePins` declines outright while Claude Code
39402
39444
  // is up, because the host owns this file and rewrites it from its own copy (#4083). Naming the
@@ -39408,7 +39450,7 @@ function mmiDoctorDeps(opts = {}) {
39408
39450
  hostBlocked ?? claudeCodeEnvMarkerPresent() ? "host-running" : "doctor"
39409
39451
  );
39410
39452
  const pending = readMarketplacePinPending(
39411
- (0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
39453
+ (0, import_node_path44.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
39412
39454
  MMI_MARKETPLACE_NAME
39413
39455
  );
39414
39456
  if (!pending) return rows;
@@ -39434,9 +39476,9 @@ function mmiDoctorDeps(opts = {}) {
39434
39476
  if (detectSurface(process.env) === "codex") return void 0;
39435
39477
  const home = (0, import_node_os19.homedir)();
39436
39478
  const names = [MMI_MARKETPLACE_NAME];
39437
- const result = applyOrgMarketplacePins((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), names);
39479
+ const result = applyOrgMarketplacePins((0, import_node_path44.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), names);
39438
39480
  if (result?.wrote) {
39439
- writeMarketplacePinPending((0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"), names);
39481
+ writeMarketplacePinPending((0, import_node_path44.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"), names);
39440
39482
  }
39441
39483
  return result;
39442
39484
  } catch {
@@ -39452,7 +39494,7 @@ function mmiDoctorDeps(opts = {}) {
39452
39494
  // adopted the generated routing index (MMG-Unlive: `docs/Archive/**` only, no index, no gate.yml) would
39453
39495
  // get a permanent — demanding an artifact it never asked for.
39454
39496
  docsIndexState: (root) => {
39455
- if (!(0, import_node_fs46.existsSync)((0, import_node_path43.join)(root, DOCS_INDEX_PATH))) return void 0;
39497
+ if (!(0, import_node_fs47.existsSync)((0, import_node_path44.join)(root, DOCS_INDEX_PATH))) return void 0;
39456
39498
  const real = createDocsIndexDeps(root);
39457
39499
  let docs2;
39458
39500
  const listDocs = () => docs2 ??= real.listDocs();
@@ -39461,7 +39503,7 @@ function mmiDoctorDeps(opts = {}) {
39461
39503
  },
39462
39504
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
39463
39505
  healDocsIndex: (root) => {
39464
- if (!(0, import_node_fs46.existsSync)((0, import_node_path43.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
39506
+ if (!(0, import_node_fs47.existsSync)((0, import_node_path44.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
39465
39507
  const real = createDocsIndexDeps(root);
39466
39508
  let docs2;
39467
39509
  const listDocs = () => docs2 ??= real.listDocs();
@@ -39489,6 +39531,7 @@ function mmiDoctorDeps(opts = {}) {
39489
39531
  // #4170: light board doctor with 15s ceiling. skipClaimLiveness keeps Phase 3 off.
39490
39532
  boardDoctorFix: async ({ fix } = {}) => {
39491
39533
  const BOARD_DOCTOR_TIMEOUT_MS = 15e3;
39534
+ let ceiling;
39492
39535
  try {
39493
39536
  const cfg = await loadConfigForRepo();
39494
39537
  const work = boardDoctor({
@@ -39499,7 +39542,7 @@ function mmiDoctorDeps(opts = {}) {
39499
39542
  const raced = await Promise.race([
39500
39543
  work.then((r) => ({ ...r, timedOut: false })),
39501
39544
  new Promise((resolve5) => {
39502
- setTimeout(() => resolve5({ timedOut: true, scanned: 0, findings: 0, fixed: 0, failed: 0 }), BOARD_DOCTOR_TIMEOUT_MS);
39545
+ ceiling = setTimeout(() => resolve5({ timedOut: true, scanned: 0, findings: 0, fixed: 0, failed: 0 }), BOARD_DOCTOR_TIMEOUT_MS);
39503
39546
  })
39504
39547
  ]);
39505
39548
  if (raced.timedOut) return { scanned: 0, findings: 0, fixed: 0, failed: 0, timedOut: true };
@@ -39511,11 +39554,20 @@ function mmiDoctorDeps(opts = {}) {
39511
39554
  };
39512
39555
  } catch (e) {
39513
39556
  return { scanned: 0, findings: 0, fixed: 0, failed: 0, readFailed: true, error: e instanceof Error ? e.message : String(e) };
39557
+ } finally {
39558
+ clearTimeout(ceiling);
39514
39559
  }
39515
39560
  },
39516
39561
  // #4171: schedules drift notebook — report-only, ~20s ceiling.
39562
+ // #4815: and throttled. The sweep behind it reads every workflow file in every org repo — 12s of a
39563
+ // 22s doctor — so a cached notebook under six hours old answers the row instead, saying so in its
39564
+ // evidence. Only a COMPLETE sweep is cached (see schedules-drift-cache.ts).
39517
39565
  schedulesDriftState: async () => {
39518
39566
  const SCHEDULES_DRIFT_TIMEOUT_MS = 2e4;
39567
+ const cachePath = schedulesDriftCachePath(repoRuntimeStatePath(process.cwd()));
39568
+ const cached = readSchedulesDriftCache(cachePath);
39569
+ if (cached) return { driftLines: cached.driftLines, incomplete: [], cachedAt: cached.at };
39570
+ let ceiling;
39519
39571
  try {
39520
39572
  const raced = await Promise.race([
39521
39573
  fetchNotebook().then((nb) => ({
@@ -39524,12 +39576,15 @@ function mmiDoctorDeps(opts = {}) {
39524
39576
  timedOut: false
39525
39577
  })),
39526
39578
  new Promise((resolve5) => {
39527
- setTimeout(() => resolve5({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
39579
+ ceiling = setTimeout(() => resolve5({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
39528
39580
  })
39529
39581
  ]);
39582
+ if (!raced.timedOut && raced.incomplete.length === 0) writeSchedulesDriftCache(cachePath, raced.driftLines);
39530
39583
  return raced;
39531
39584
  } catch (e) {
39532
39585
  return { driftLines: [], incomplete: [], readFailed: true, error: e instanceof Error ? e.message : String(e) };
39586
+ } finally {
39587
+ clearTimeout(ceiling);
39533
39588
  }
39534
39589
  },
39535
39590
  // #4173: estate commands absent from the running Commander program (stale global CLI).
@@ -39811,19 +39866,19 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
39811
39866
  });
39812
39867
  var rules = program2.command("rules").description("org-managed .gitignore delivery");
39813
39868
  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) => {
39814
- const path2 = (0, import_node_path43.join)(process.cwd(), ".gitignore");
39815
- const current = (0, import_node_fs46.existsSync)(path2) ? (0, import_node_fs46.readFileSync)(path2, "utf8") : null;
39869
+ const path2 = (0, import_node_path44.join)(process.cwd(), ".gitignore");
39870
+ const current = (0, import_node_fs47.existsSync)(path2) ? (0, import_node_fs47.readFileSync)(path2, "utf8") : null;
39816
39871
  const plan = planManagedGitignore(current);
39817
39872
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
39818
39873
  if (opts.json) {
39819
- if (opts.write && plan.changed) (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
39874
+ if (opts.write && plan.changed) (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
39820
39875
  console.log(JSON.stringify(plan, null, 2));
39821
39876
  if (!opts.write && plan.changed) process.exitCode = 1;
39822
39877
  return;
39823
39878
  }
39824
39879
  if (opts.write) {
39825
39880
  if (plan.changed) {
39826
- (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
39881
+ (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
39827
39882
  console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
39828
39883
  } else {
39829
39884
  console.log("mmi-cli devops org rules gitignore: up to date");
@@ -39982,8 +40037,8 @@ gcCmd.option("--dry-run", "show what would be deleted (default)").option("--appl
39982
40037
  if (!Number.isFinite(limit) || limit < 1) return fail("worktree gc: --limit must be a positive integer");
39983
40038
  let root;
39984
40039
  if (o.root !== void 0) {
39985
- root = (0, import_node_path43.resolve)(o.root);
39986
- if (!(0, import_node_fs46.existsSync)(root) || !(0, import_node_fs46.statSync)(root).isDirectory()) return fail(`worktree gc: --root ${o.root} is not a directory`);
40040
+ root = (0, import_node_path44.resolve)(o.root);
40041
+ if (!(0, import_node_fs47.existsSync)(root) || !(0, import_node_fs47.statSync)(root).isDirectory()) return fail(`worktree gc: --root ${o.root} is not a directory`);
39987
40042
  const gcRepoRoot = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
39988
40043
  if (isPathUnderDirectory2(gcRepoRoot, root)) {
39989
40044
  return fail(`worktree gc: --root ${root} contains this checkout \u2014 name a worktrees root, not the repo or an ancestor of it`);
@@ -40080,7 +40135,7 @@ async function currentWorktreeRemovalContext(command, force) {
40080
40135
  };
40081
40136
  }
40082
40137
  async function unprovenWorktreeReason(wtPath, repoRoot2) {
40083
- if (!(0, import_node_fs46.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
40138
+ if (!(0, import_node_fs47.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
40084
40139
  const porcelain = (await execFileP2("git", ["-C", repoRoot2, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
40085
40140
  const registered = parseWorktreePorcelainEntries(porcelain);
40086
40141
  if (!registered.length) {
@@ -40110,26 +40165,26 @@ function makeProvisionDeps(worktreeRoot, quiet, log) {
40110
40165
  function acquireWorktreeSetupLock(worktreeRoot) {
40111
40166
  const lockPath = repoRuntimeStatePath(worktreeRoot, "worktree-setup.lock");
40112
40167
  const take = () => {
40113
- const fd = (0, import_node_fs46.openSync)(lockPath, "wx");
40168
+ const fd = (0, import_node_fs47.openSync)(lockPath, "wx");
40114
40169
  try {
40115
- (0, import_node_fs46.writeSync)(fd, String(Date.now()));
40170
+ (0, import_node_fs47.writeSync)(fd, String(Date.now()));
40116
40171
  } finally {
40117
- (0, import_node_fs46.closeSync)(fd);
40172
+ (0, import_node_fs47.closeSync)(fd);
40118
40173
  }
40119
40174
  return () => {
40120
40175
  try {
40121
- (0, import_node_fs46.rmSync)(lockPath, { force: true });
40176
+ (0, import_node_fs47.rmSync)(lockPath, { force: true });
40122
40177
  } catch {
40123
40178
  }
40124
40179
  };
40125
40180
  };
40126
40181
  try {
40127
- (0, import_node_fs46.mkdirSync)((0, import_node_path43.dirname)(lockPath), { recursive: true });
40182
+ (0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(lockPath), { recursive: true });
40128
40183
  return take();
40129
40184
  } catch {
40130
40185
  try {
40131
- if (Date.now() - (0, import_node_fs46.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
40132
- (0, import_node_fs46.rmSync)(lockPath, { force: true });
40186
+ if (Date.now() - (0, import_node_fs47.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
40187
+ (0, import_node_fs47.rmSync)(lockPath, { force: true });
40133
40188
  return take();
40134
40189
  }
40135
40190
  } catch {
@@ -40993,7 +41048,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
40993
41048
  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`);
40994
41049
  if (o.secretsFile) {
40995
41050
  try {
40996
- vars.push(`secrets=${(0, import_node_fs46.readFileSync)(o.secretsFile, "utf8")}`);
41051
+ vars.push(`secrets=${(0, import_node_fs47.readFileSync)(o.secretsFile, "utf8")}`);
40997
41052
  } catch (e) {
40998
41053
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
40999
41054
  }
@@ -41761,11 +41816,11 @@ pr.command("view <number>").description("read a PR as structured JSON (merged st
41761
41816
  }
41762
41817
  });
41763
41818
  async function listCiWorkflowPaths(cwd = process.cwd()) {
41764
- const wfDir = (0, import_node_path43.join)(cwd, ".github", "workflows");
41765
- if (!(0, import_node_fs46.existsSync)(wfDir)) return [];
41766
- return (0, import_node_fs46.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
41819
+ const wfDir = (0, import_node_path44.join)(cwd, ".github", "workflows");
41820
+ if (!(0, import_node_fs47.existsSync)(wfDir)) return [];
41821
+ return (0, import_node_fs47.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
41767
41822
  try {
41768
- return workflowReportsPrChecks((0, import_node_fs46.readFileSync)((0, import_node_path43.join)(wfDir, name), "utf8"));
41823
+ return workflowReportsPrChecks((0, import_node_fs47.readFileSync)((0, import_node_path44.join)(wfDir, name), "utf8"));
41769
41824
  } catch {
41770
41825
  return true;
41771
41826
  }
@@ -41817,16 +41872,16 @@ function ciAuditDeps() {
41817
41872
  // gate re-seed step is skipped gracefully rather than failing mid-run.
41818
41873
  readSeedFile: (path2) => {
41819
41874
  if (!root) return null;
41820
- const fullPath = (0, import_node_path43.join)(root, path2);
41821
- return (0, import_node_fs46.existsSync)(fullPath) ? (0, import_node_fs46.readFileSync)(fullPath, "utf8") : null;
41875
+ const fullPath = (0, import_node_path44.join)(root, path2);
41876
+ return (0, import_node_fs47.existsSync)(fullPath) ? (0, import_node_fs47.readFileSync)(fullPath, "utf8") : null;
41822
41877
  }
41823
41878
  };
41824
41879
  }
41825
41880
  function hubRoot() {
41826
- const fromPkg = (0, import_node_path43.join)(__dirname, "..", "..");
41881
+ const fromPkg = (0, import_node_path44.join)(__dirname, "..", "..");
41827
41882
  const marker = "skills/bootstrap/seeds/manifest.json";
41828
- if ((0, import_node_fs46.existsSync)((0, import_node_path43.join)(fromPkg, marker))) return fromPkg;
41829
- if ((0, import_node_fs46.existsSync)((0, import_node_path43.join)(process.cwd(), marker))) return process.cwd();
41883
+ if ((0, import_node_fs47.existsSync)((0, import_node_path44.join)(fromPkg, marker))) return fromPkg;
41884
+ if ((0, import_node_fs47.existsSync)((0, import_node_path44.join)(process.cwd(), marker))) return process.cwd();
41830
41885
  return null;
41831
41886
  }
41832
41887
  async function waitLoopCorePool(label) {
@@ -42134,7 +42189,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
42134
42189
  }
42135
42190
  if (!repoForPostCleanup) throw e;
42136
42191
  console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
42137
- const commitMessage = bodyFile ? (0, import_node_fs46.readFileSync)(bodyFile, "utf8") : void 0;
42192
+ const commitMessage = bodyFile ? (0, import_node_fs47.readFileSync)(bodyFile, "utf8") : void 0;
42138
42193
  await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
42139
42194
  body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
42140
42195
  timeoutMs: GH_MUTATION_TIMEOUT_MS
@@ -42230,7 +42285,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
42230
42285
  localCleanup = await cleanupPrMergeLocalBranch(headRef, {
42231
42286
  beforeWorktrees,
42232
42287
  startingPath,
42233
- pathExists: (p) => (0, import_node_fs46.existsSync)(p),
42288
+ pathExists: (p) => (0, import_node_fs47.existsSync)(p),
42234
42289
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
42235
42290
  teardownWorktreeStage,
42236
42291
  deferredStore,
@@ -42808,12 +42863,12 @@ access.command("audit").description("audit collaborator roles + train-branch pus
42808
42863
  targets = resolution.targets;
42809
42864
  }
42810
42865
  const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
42811
- const fileMatrix = (0, import_node_fs46.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs46.readFileSync)("access-matrix.json", "utf8")) : {};
42866
+ const fileMatrix = (0, import_node_fs47.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs47.readFileSync)("access-matrix.json", "utf8")) : {};
42812
42867
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
42813
42868
  const derivedContracts = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
42814
- const fileContracts = (0, import_node_fs46.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs46.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
42869
+ const fileContracts = (0, import_node_fs47.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs47.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
42815
42870
  const dataAccess = mergeDataAccessContracts(fileContracts, derivedContracts);
42816
- const sanctioned = (0, import_node_fs46.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs46.readFileSync)("access-matrix.json", "utf8")) : {};
42871
+ const sanctioned = (0, import_node_fs47.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs47.readFileSync)("access-matrix.json", "utf8")) : {};
42817
42872
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
42818
42873
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
42819
42874
  if (!report.ok) process.exitCode = 1;
@@ -42845,16 +42900,16 @@ function directoryBytes(path2) {
42845
42900
  let total = 0;
42846
42901
  let entries;
42847
42902
  try {
42848
- entries = (0, import_node_fs46.readdirSync)(path2, { withFileTypes: true });
42903
+ entries = (0, import_node_fs47.readdirSync)(path2, { withFileTypes: true });
42849
42904
  } catch {
42850
42905
  return 0;
42851
42906
  }
42852
42907
  for (const entry of entries) {
42853
- const child2 = (0, import_node_path43.join)(path2, entry.name);
42908
+ const child2 = (0, import_node_path44.join)(path2, entry.name);
42854
42909
  if (entry.isDirectory()) total += directoryBytes(child2);
42855
42910
  else {
42856
42911
  try {
42857
- total += (0, import_node_fs46.statSync)(child2).size;
42912
+ total += (0, import_node_fs47.statSync)(child2).size;
42858
42913
  } catch {
42859
42914
  }
42860
42915
  }
@@ -42862,25 +42917,25 @@ function directoryBytes(path2) {
42862
42917
  return total;
42863
42918
  }
42864
42919
  function listDirEntries(dir) {
42865
- return (0, import_node_fs46.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
42920
+ return (0, import_node_fs47.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
42866
42921
  }
42867
42922
  function readInstalledPluginRefs(configRoot) {
42868
42923
  const p = installedPluginsPathForConfig(configRoot);
42869
- if (!(0, import_node_fs46.existsSync)(p)) return [];
42924
+ if (!(0, import_node_fs47.existsSync)(p)) return [];
42870
42925
  try {
42871
- return installedPluginPaths((0, import_node_fs46.readFileSync)(p, "utf8"));
42926
+ return installedPluginPaths((0, import_node_fs47.readFileSync)(p, "utf8"));
42872
42927
  } catch {
42873
42928
  return null;
42874
42929
  }
42875
42930
  }
42876
42931
  function pluginCacheFsDeps(configRoot, dirBytes) {
42877
42932
  return {
42878
- exists: (p) => (0, import_node_fs46.existsSync)(p),
42879
- listVersionDirs: (root) => (0, import_node_fs46.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
42933
+ exists: (p) => (0, import_node_fs47.existsSync)(p),
42934
+ listVersionDirs: (root) => (0, import_node_fs47.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
42880
42935
  dirBytes,
42881
- listStagingDirs: (root) => (0, import_node_fs46.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
42936
+ listStagingDirs: (root) => (0, import_node_fs47.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
42882
42937
  try {
42883
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path43.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs46.statSync)(p).mtimeMs) };
42938
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path44.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs47.statSync)(p).mtimeMs) };
42884
42939
  } catch {
42885
42940
  return { name: d.name, mtimeMs: Date.now() };
42886
42941
  }
@@ -42894,10 +42949,10 @@ function stagingApplyFsGuard(configRoot) {
42894
42949
  return {
42895
42950
  referencedPaths: () => readInstalledPluginRefs(configRoot),
42896
42951
  mtimeMs: (name) => {
42897
- const p = (0, import_node_path43.join)(stagingRoot, name);
42898
- if (!(0, import_node_fs46.existsSync)(p)) return null;
42952
+ const p = (0, import_node_path44.join)(stagingRoot, name);
42953
+ if (!(0, import_node_fs47.existsSync)(p)) return null;
42899
42954
  try {
42900
- return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs46.statSync)(q).mtimeMs);
42955
+ return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs47.statSync)(q).mtimeMs);
42901
42956
  } catch {
42902
42957
  return null;
42903
42958
  }
@@ -42923,7 +42978,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
42923
42978
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
42924
42979
  );
42925
42980
  const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
42926
- const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs46.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
42981
+ const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs47.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
42927
42982
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
42928
42983
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
42929
42984
  else console.log(renderPluginCachePlan(plan, result));
@@ -42931,7 +42986,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
42931
42986
  });
42932
42987
  function readReleaseCatchupState(path2) {
42933
42988
  try {
42934
- const parsed = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
42989
+ const parsed = JSON.parse((0, import_node_fs47.readFileSync)(path2, "utf8"));
42935
42990
  return typeof parsed?.checkedAt === "number" ? parsed : void 0;
42936
42991
  } catch {
42937
42992
  return void 0;
@@ -42939,8 +42994,8 @@ function readReleaseCatchupState(path2) {
42939
42994
  }
42940
42995
  function writeReleaseCatchupState(path2, state) {
42941
42996
  try {
42942
- (0, import_node_fs46.mkdirSync)((0, import_node_path43.dirname)(path2), { recursive: true });
42943
- (0, import_node_fs46.writeFileSync)(path2, `${JSON.stringify(state)}
42997
+ (0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(path2), { recursive: true });
42998
+ (0, import_node_fs47.writeFileSync)(path2, `${JSON.stringify(state)}
42944
42999
  `);
42945
43000
  } catch {
42946
43001
  }