@mutmutco/cli 3.117.1 → 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 +567 -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
  }
@@ -11642,8 +11676,8 @@ var NPM_INSTALL_TIMEOUT_MS = 12e4;
11642
11676
  var CLI_VERSION_PROBE_TIMEOUT_MS = 3e4;
11643
11677
  function resolveNpmSpawn(args) {
11644
11678
  if (!isWin) return { file: "npm", args };
11645
- const cli = (0, import_node_path16.join)((0, import_node_path16.dirname)(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
11646
- if ((0, import_node_fs17.existsSync)(cli)) return { file: process.execPath, args: [cli, ...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] };
11647
11681
  return { file: "cmd.exe", args: ["/c", "npm", ...args] };
11648
11682
  }
11649
11683
  async function npmSelfUpdateCli(target, onStep, deps = {}) {
@@ -11669,11 +11703,11 @@ async function npmSelfUpdateCli(target, onStep, deps = {}) {
11669
11703
  onStep?.(verified.detail, { alwaysShow: true });
11670
11704
  return verified.ok ? { ok: true, detail: `${command} exited 0 \u2014 ${verified.detail}` } : { ok: false, detail: `${command} exited 0 but ${verified.detail}` };
11671
11705
  }
11672
- 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) {
11673
11707
  const candidates = ["kilo.json", "kilo.jsonc", "opencode.json", "opencode.jsonc", "config.json"];
11674
- 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")]) {
11675
11709
  for (const file of candidates) {
11676
- const path2 = (0, import_node_path16.join)(dir, file);
11710
+ const path2 = (0, import_node_path17.join)(dir, file);
11677
11711
  if (!exists(path2)) continue;
11678
11712
  try {
11679
11713
  const stripped = read(path2).replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
@@ -11690,23 +11724,23 @@ function kiloConfigListsPlugin(configRoot, home = (0, import_node_os5.homedir)()
11690
11724
  return false;
11691
11725
  }
11692
11726
  function cursorLocalPluginRoot(env = process.env, home = (0, import_node_os5.homedir)()) {
11693
- 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");
11694
11728
  }
11695
- function cursorPluginTreeHealthy(root, exists = import_node_fs17.existsSync) {
11729
+ function cursorPluginTreeHealthy(root, exists = import_node_fs18.existsSync) {
11696
11730
  return [
11697
11731
  ".cursor-plugin/plugin.json",
11698
11732
  "skills/mmi/SKILL.md",
11699
11733
  "hooks/cursor-hooks.json",
11700
11734
  "scripts/hook-run.mjs",
11701
11735
  "scripts/hook-policy.mjs"
11702
- ].every((path2) => exists((0, import_node_path16.join)(root, ...path2.split("/"))));
11736
+ ].every((path2) => exists((0, import_node_path17.join)(root, ...path2.split("/"))));
11703
11737
  }
11704
- function kimiPluginTreeHealthy(root, exists = import_node_fs17.existsSync) {
11738
+ function kimiPluginTreeHealthy(root, exists = import_node_fs18.existsSync) {
11705
11739
  return [
11706
11740
  ".kimi-plugin/plugin.json",
11707
11741
  "skills/mmi/SKILL.md",
11708
11742
  "scripts/hook-run.mjs"
11709
- ].every((path2) => exists((0, import_node_path16.join)(root, ...path2.split("/"))));
11743
+ ].every((path2) => exists((0, import_node_path17.join)(root, ...path2.split("/"))));
11710
11744
  }
11711
11745
  var JERVCODE_WRAPPER_DIR = ".pi-plugin";
11712
11746
  function normalizePiEntry(value) {
@@ -11729,7 +11763,7 @@ function jervcodePackageFamily(entry) {
11729
11763
  function isMmiOwnedPiEntry(entry) {
11730
11764
  if (typeof entry !== "string") return false;
11731
11765
  try {
11732
- 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"));
11733
11767
  return pkg.name === "mmi";
11734
11768
  } catch {
11735
11769
  return false;
@@ -11751,9 +11785,9 @@ function mergeMmiPiPackageEntries(entries, packagePath) {
11751
11785
  };
11752
11786
  }
11753
11787
  function readPiSettings(path2) {
11754
- if (!(0, import_node_fs17.existsSync)(path2)) return void 0;
11788
+ if (!(0, import_node_fs18.existsSync)(path2)) return void 0;
11755
11789
  try {
11756
- const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
11790
+ const parsed = JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
11757
11791
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
11758
11792
  return parsed;
11759
11793
  } catch {
@@ -11761,8 +11795,8 @@ function readPiSettings(path2) {
11761
11795
  }
11762
11796
  }
11763
11797
  function jervcodeSettingsCandidates(env = process.env, home = (0, import_node_os5.homedir)()) {
11764
- const primary = (0, import_node_path16.join)(surfaceConfigRoot("jervcode", env, home), "settings.json");
11765
- 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");
11766
11800
  return legacy === primary ? [primary] : [primary, legacy];
11767
11801
  }
11768
11802
  function mmiPiWrapperEntry(env = process.env, home = (0, import_node_os5.homedir)()) {
@@ -11781,17 +11815,17 @@ function mmiPiWrapperEntry(env = process.env, home = (0, import_node_os5.homedir
11781
11815
  function mmiPiWrapperHealthy(entry) {
11782
11816
  if (!entry) return false;
11783
11817
  const wrapper = piEntryFsPath(entry);
11784
- 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"));
11785
11819
  }
11786
11820
  function findMmiPiSourceClone(home = (0, import_node_os5.homedir)()) {
11787
- 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");
11788
11822
  let best = null;
11789
11823
  try {
11790
- 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 })) {
11791
11825
  if (!entry.isDirectory() || !/^\d+\.\d+\.\d+$/.test(entry.name)) continue;
11792
- 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;
11793
11827
  if (!best || compareVersions(entry.name, best.version) > 0) {
11794
- 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 };
11795
11829
  }
11796
11830
  }
11797
11831
  } catch {
@@ -11816,8 +11850,8 @@ function acquirePiSettingsLock(settingsPath2) {
11816
11850
  return void 0;
11817
11851
  }
11818
11852
  function healOneJervCodeSettingsFile(settingsPath2, packagePath, version, nextLaunch) {
11819
- const release = (0, import_node_fs17.existsSync)(settingsPath2) ? acquirePiSettingsLock(settingsPath2) : void 0;
11820
- 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) {
11821
11855
  return {
11822
11856
  available: true,
11823
11857
  ok: false,
@@ -11845,14 +11879,14 @@ function healOneJervCodeSettingsFile(settingsPath2, packagePath, version, nextLa
11845
11879
  }
11846
11880
  current.packages = merged.next;
11847
11881
  try {
11848
- (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 });
11849
11883
  const tmp = `${settingsPath2}.tmp-${process.pid}`;
11850
- (0, import_node_fs17.writeFileSync)(tmp, `${JSON.stringify(current, null, 2)}
11884
+ (0, import_node_fs18.writeFileSync)(tmp, `${JSON.stringify(current, null, 2)}
11851
11885
  `, "utf8");
11852
11886
  try {
11853
- (0, import_node_fs17.renameSync)(tmp, settingsPath2);
11887
+ (0, import_node_fs18.renameSync)(tmp, settingsPath2);
11854
11888
  } catch (renameError) {
11855
- (0, import_node_fs17.rmSync)(tmp, { force: true });
11889
+ (0, import_node_fs18.rmSync)(tmp, { force: true });
11856
11890
  throw renameError;
11857
11891
  }
11858
11892
  } catch (error) {
@@ -11876,8 +11910,8 @@ function healJervCodePackageRegistration(opts = {}) {
11876
11910
  const nextLaunch = inSeat ? " \u2014 takes effect on the next seat launch" : "";
11877
11911
  const home = opts.home ?? (0, import_node_os5.homedir)();
11878
11912
  const agentDir = surfaceConfigRoot("jervcode", env, home);
11879
- const legacyPi = (0, import_node_path16.join)(home, ".pi", "agent");
11880
- 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)) {
11881
11915
  return { available: false, ok: true, changed: false, version: null, detail: "skipped \u2014 no Pi/JervCode install (no agent config dir)" };
11882
11916
  }
11883
11917
  const clone = opts.clone === void 0 ? findMmiPiSourceClone(home) : opts.clone;
@@ -11885,9 +11919,9 @@ function healJervCodePackageRegistration(opts = {}) {
11885
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)" };
11886
11920
  }
11887
11921
  const packagePath = `${clone.path.replace(/\\/g, "/").replace(/\/+$/, "")}/${JERVCODE_WRAPPER_DIR}`;
11888
- const targets = [(0, import_node_path16.join)(agentDir, "settings.json")];
11889
- const legacySettings = (0, import_node_path16.join)(legacyPi, "settings.json");
11890
- 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);
11891
11925
  const details = [];
11892
11926
  let anyChanged = false;
11893
11927
  for (const settingsPath2 of targets) {
@@ -11915,18 +11949,18 @@ function snapshotPluginGuardInput(surface = detectSurface(process.env), isOrgRep
11915
11949
  return {
11916
11950
  isOrgRepo,
11917
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.
11918
- 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.
11919
11953
  surface === "kilo" && kiloConfigListsPlugin(root) || // #4188: jervcode's install record is the settings-file packages[] entry itself.
11920
- 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()),
11921
11955
  // Kilo has no marketplace to clone — the config file IS the install record, so this dimension of
11922
11956
  // the shared guard table is vacuously satisfied. Same for jervcode's settings entry.
11923
11957
  marketplaceClonePresent: surface === "kimi" || surface === "kilo" || surface === "cursor" || surface === "jervcode" ? true : marketplaceClonePresent(surface, (0, import_node_os5.homedir)()),
11924
11958
  // Kimi keeps no plugin cache dir — installs are copied to plugins/managed/<id> and run from there.
11925
11959
  // Kilo (kilo-p1) keeps no cache dir either: the plugin's server() provisions ~/.kilo behind the
11926
11960
  // version stamp, so the stamp's presence is the cache signal.
11927
- 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(
11928
- codexStatus?.installed && codexStatus.enabled && codexStatus.version && (0, import_node_fs17.existsSync)((0, import_node_path16.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", codexStatus.version))
11929
- ) : (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"))
11930
11964
  };
11931
11965
  }
11932
11966
  async function runHostBinLogged(bin, args, opts) {
@@ -11946,11 +11980,11 @@ async function runPluginCli(bin, args, log) {
11946
11980
  function captureCodexHookLauncher() {
11947
11981
  const status = codexPluginStatus();
11948
11982
  if (!status.installed || !status.enabled || !status.version) return void 0;
11949
- 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);
11950
11984
  const files = ["mmi-hook", "mmi-hook.exe"].flatMap((name) => {
11951
- const path2 = (0, import_node_path16.join)(root, "bin", name);
11985
+ const path2 = (0, import_node_path17.join)(root, "bin", name);
11952
11986
  try {
11953
- return [{ name, content: (0, import_node_fs17.readFileSync)(path2) }];
11987
+ return [{ name, content: (0, import_node_fs18.readFileSync)(path2) }];
11954
11988
  } catch {
11955
11989
  return [];
11956
11990
  }
@@ -11958,13 +11992,13 @@ function captureCodexHookLauncher() {
11958
11992
  return files.length === 2 ? { root, files } : void 0;
11959
11993
  }
11960
11994
  function restoreCodexHookLauncher(snapshot) {
11961
- if (!snapshot || (0, import_node_fs17.existsSync)((0, import_node_path16.join)(snapshot.root, "scripts", "hook-run.mjs"))) return false;
11962
- const bin = (0, import_node_path16.join)(snapshot.root, "bin");
11963
- (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 });
11964
11998
  for (const file of snapshot.files) {
11965
- const path2 = (0, import_node_path16.join)(bin, file.name);
11966
- (0, import_node_fs17.writeFileSync)(path2, file.content);
11967
- 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);
11968
12002
  }
11969
12003
  return true;
11970
12004
  }
@@ -11973,10 +12007,10 @@ function canonicalCursorRemote(remote) {
11973
12007
  }
11974
12008
  async function installCursorPluginCheckout(env = process.env) {
11975
12009
  const configRoot = surfaceConfigRoot("cursor", env);
11976
- const pluginsRoot = (0, import_node_path16.join)(configRoot, "plugins");
11977
- 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");
11978
12012
  const source = env.MMI_CURSOR_PLUGIN_SOURCE?.trim();
11979
- if ((0, import_node_fs17.existsSync)(target) && !source) {
12013
+ if ((0, import_node_fs18.existsSync)(target) && !source) {
11980
12014
  try {
11981
12015
  const { stdout } = await runHostBin("git", ["-C", target, "remote", "get-url", "origin"], { timeout: 15e3 });
11982
12016
  if (!canonicalCursorRemote(stdout)) {
@@ -11986,15 +12020,15 @@ async function installCursorPluginCheckout(env = process.env) {
11986
12020
  return { ok: false, detail: `refused to replace unmanaged Cursor plugin directory at ${target}` };
11987
12021
  }
11988
12022
  }
11989
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.join)(pluginsRoot, "local"), { recursive: true });
11990
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.join)(pluginsRoot, "staging"), { recursive: true });
11991
- (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 });
11992
12026
  const suffix = `${Date.now()}-${process.pid}`;
11993
- const staged = (0, import_node_path16.join)(pluginsRoot, "staging", `mmi-${suffix}`);
11994
- 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}`);
11995
12029
  try {
11996
12030
  if (source) {
11997
- (0, import_node_fs17.cpSync)(source, staged, {
12031
+ (0, import_node_fs18.cpSync)(source, staged, {
11998
12032
  recursive: true,
11999
12033
  filter: (path2) => !path2.split(/[\\/]/).some((part) => part === ".git" || part === "node_modules")
12000
12034
  });
@@ -12005,18 +12039,18 @@ async function installCursorPluginCheckout(env = process.env) {
12005
12039
  });
12006
12040
  }
12007
12041
  if (!cursorPluginTreeHealthy(staged)) {
12008
- (0, import_node_fs17.rmSync)(staged, { recursive: true, force: true });
12042
+ (0, import_node_fs18.rmSync)(staged, { recursive: true, force: true });
12009
12043
  return { ok: false, detail: "downloaded Cursor plugin is incomplete; existing install was preserved" };
12010
12044
  }
12011
12045
  let movedOld = false;
12012
- if ((0, import_node_fs17.existsSync)(target)) {
12013
- (0, import_node_fs17.renameSync)(target, quarantined);
12046
+ if ((0, import_node_fs18.existsSync)(target)) {
12047
+ (0, import_node_fs18.renameSync)(target, quarantined);
12014
12048
  movedOld = true;
12015
12049
  }
12016
12050
  try {
12017
- (0, import_node_fs17.renameSync)(staged, target);
12051
+ (0, import_node_fs18.renameSync)(staged, target);
12018
12052
  } catch (error) {
12019
- 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);
12020
12054
  throw error;
12021
12055
  }
12022
12056
  return {
@@ -12024,7 +12058,7 @@ async function installCursorPluginCheckout(env = process.env) {
12024
12058
  detail: movedOld ? `installed canonical Cursor plugin; previous checkout quarantined at ${quarantined}` : `installed canonical Cursor plugin at ${target}`
12025
12059
  };
12026
12060
  } catch (error) {
12027
- 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 });
12028
12062
  return { ok: false, detail: error.message.trim().slice(0, 240).replace(/\s+/g, " ") };
12029
12063
  }
12030
12064
  }
@@ -12074,7 +12108,7 @@ async function applyPluginHeal(surface, log, opts) {
12074
12108
  const refSupported = await marketplaceAddRefSupported(bin);
12075
12109
  const { steps } = adaptHealStepsForRefSupport(tableSteps, refSupported);
12076
12110
  log(healBannerLine(bin, token, refSupported));
12077
- 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);
12078
12112
  const pins = token === "claude" ? captureMarketplacePins(readKnownMarketplacesFile(pinsPath), [MMI_MARKETPLACE_NAME, JERV_MARKETPLACE_NAME]) : /* @__PURE__ */ new Map();
12079
12113
  try {
12080
12114
  for (const step of steps) {
@@ -12149,7 +12183,7 @@ async function healActivePluginForDoctor(surface = detectSurface(process.env), o
12149
12183
  }
12150
12184
  function readKnownMarketplacesFile(path2) {
12151
12185
  try {
12152
- 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;
12153
12187
  } catch {
12154
12188
  return void 0;
12155
12189
  }
@@ -12179,7 +12213,7 @@ function writeMarketplacePinsOnDisk(path2, pins, succeeded, failedVerb, declineW
12179
12213
  const declined = declineWhileHostLive?.();
12180
12214
  if (declined) return declined;
12181
12215
  try {
12182
- (0, import_node_fs17.writeFileSync)(path2, next, "utf8");
12216
+ (0, import_node_fs18.writeFileSync)(path2, next, "utf8");
12183
12217
  } catch {
12184
12218
  return `could NOT ${failedVerb} ${[...pins.keys()].join(", ")} \u2014 set it by hand`;
12185
12219
  }
@@ -12219,15 +12253,15 @@ function applyOrgMarketplacePins(path2, names, hostIsRunning = claudeCodeIsRunni
12219
12253
  }
12220
12254
  function writeMarketplacePinPending(path2, names, now = Date.now()) {
12221
12255
  try {
12222
- (0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(path2), { recursive: true });
12223
- (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() })}
12224
12258
  `, "utf8");
12225
12259
  } catch {
12226
12260
  }
12227
12261
  }
12228
12262
  function readMarketplacePinPending(path2, name, now = Date.now()) {
12229
12263
  try {
12230
- const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
12264
+ const parsed = JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
12231
12265
  const at = typeof parsed.at === "string" ? Date.parse(parsed.at) : Number.NaN;
12232
12266
  if (parsed.v !== 1 || !Array.isArray(parsed.names) || !parsed.names.includes(name) || !Number.isFinite(at)) return void 0;
12233
12267
  if (now - at < 0 || now - at > 12 * 60 * 6e4) return void 0;
@@ -12785,9 +12819,9 @@ function renderAccessReport(report) {
12785
12819
  }
12786
12820
 
12787
12821
  // src/cli-doctor-shared.ts
12788
- var import_node_fs18 = require("node:fs");
12789
- var import_node_path18 = require("node:path");
12790
12822
  var import_node_fs19 = require("node:fs");
12823
+ var import_node_path19 = require("node:path");
12824
+ var import_node_fs20 = require("node:fs");
12791
12825
 
12792
12826
  // ../infra/registry-endpoints.mjs
12793
12827
  var PROJECTS_LIST_PATH = "/projects/list";
@@ -13701,7 +13735,7 @@ var import_node_os7 = require("node:os");
13701
13735
  // src/gh-create.ts
13702
13736
  var import_promises3 = require("node:fs/promises");
13703
13737
  var import_node_os6 = require("node:os");
13704
- var import_node_path17 = require("node:path");
13738
+ var import_node_path18 = require("node:path");
13705
13739
  var import_node_crypto3 = require("node:crypto");
13706
13740
 
13707
13741
  // src/board-priority.ts
@@ -13784,8 +13818,8 @@ async function bodyArgsViaFile(args, deps = {}) {
13784
13818
  const remove2 = deps.remove ?? import_promises3.unlink;
13785
13819
  const ensureDir = deps.ensureDir ?? import_promises3.mkdir;
13786
13820
  const dir = deps.dir ?? (0, import_node_os6.tmpdir)();
13787
- const file = (0, import_node_path17.join)(dir, `mmi-gh-body-${process.pid}-${(0, import_node_crypto3.randomBytes)(4).toString("hex")}.md`);
13788
- 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(() => {
13789
13823
  });
13790
13824
  await write(file, args[i + 1], "utf8");
13791
13825
  return {
@@ -15328,7 +15362,7 @@ async function localBranchHeads() {
15328
15362
  }
15329
15363
  async function currentRepoWorktreeGitRoot(repoRoot2) {
15330
15364
  const gitCommonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
15331
- return gitCommonDir ? (0, import_node_path18.resolve)(repoRoot2, gitCommonDir, "worktrees") : "";
15365
+ return gitCommonDir ? (0, import_node_path19.resolve)(repoRoot2, gitCommonDir, "worktrees") : "";
15332
15366
  }
15333
15367
  async function worktreeBranches() {
15334
15368
  const { stdout } = await execFileP2("git", ["worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS });
@@ -15348,18 +15382,18 @@ function resolveGitdirForWorktreeFile(worktreePath, content) {
15348
15382
  const match = /^gitdir:\s*(.+)\s*$/im.exec(content);
15349
15383
  if (!match?.[1]) return void 0;
15350
15384
  const raw = match[1].trim();
15351
- 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);
15352
15386
  }
15353
15387
  function metadataOwnsMissingWorktreeDir(worktreePath, worktreeGitRoot) {
15354
15388
  if (!worktreeGitRoot) return false;
15355
15389
  try {
15356
- const entries = (0, import_node_fs19.readdirSync)(worktreeGitRoot, { withFileTypes: true });
15390
+ const entries = (0, import_node_fs20.readdirSync)(worktreeGitRoot, { withFileTypes: true });
15357
15391
  for (const ent of entries) {
15358
15392
  if (!ent.isDirectory()) continue;
15359
15393
  try {
15360
- const gitdirPath = (0, import_node_fs18.readFileSync)((0, import_node_path18.join)(worktreeGitRoot, ent.name, "gitdir"), "utf8").trim();
15361
- const resolvedGitdir = (0, import_node_path18.isAbsolute)(gitdirPath) ? gitdirPath : (0, import_node_path18.resolve)(worktreeGitRoot, ent.name, gitdirPath);
15362
- 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;
15363
15397
  } catch {
15364
15398
  }
15365
15399
  }
@@ -15369,7 +15403,7 @@ function metadataOwnsMissingWorktreeDir(worktreePath, worktreeGitRoot) {
15369
15403
  }
15370
15404
  function pathExistsKnown(path2) {
15371
15405
  try {
15372
- (0, import_node_fs19.statSync)(path2);
15406
+ (0, import_node_fs20.statSync)(path2);
15373
15407
  return true;
15374
15408
  } catch (e) {
15375
15409
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
@@ -15378,10 +15412,10 @@ function pathExistsKnown(path2) {
15378
15412
  }
15379
15413
  }
15380
15414
  function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
15381
- const gitPath = (0, import_node_path18.join)(path2, ".git");
15415
+ const gitPath = (0, import_node_path19.join)(path2, ".git");
15382
15416
  let st;
15383
15417
  try {
15384
- st = (0, import_node_fs19.lstatSync)(gitPath);
15418
+ st = (0, import_node_fs20.lstatSync)(gitPath);
15385
15419
  } catch (e) {
15386
15420
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
15387
15421
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -15398,7 +15432,7 @@ function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
15398
15432
  if (st.isDirectory()) return { path: path2, gitType: "dir" };
15399
15433
  if (!st.isFile()) return { path: path2, gitType: "other" };
15400
15434
  try {
15401
- const gitFileContent = (0, import_node_fs18.readFileSync)(gitPath, "utf8");
15435
+ const gitFileContent = (0, import_node_fs19.readFileSync)(gitPath, "utf8");
15402
15436
  const gitdir = resolveGitdirForWorktreeFile(path2, gitFileContent);
15403
15437
  const gitDirExists = gitdir ? pathExistsKnown(gitdir) : false;
15404
15438
  return {
@@ -15415,7 +15449,7 @@ function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
15415
15449
  }
15416
15450
  function inspectDeadWorktreeDirContent(path2) {
15417
15451
  try {
15418
- return { entries: (0, import_node_fs19.readdirSync)(path2) };
15452
+ return { entries: (0, import_node_fs20.readdirSync)(path2) };
15419
15453
  } catch (e) {
15420
15454
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
15421
15455
  return { error: code ? `unable to inspect directory contents (${code})` : "unable to inspect directory contents" };
@@ -15432,7 +15466,7 @@ async function preservedBranches() {
15432
15466
  async function siblingWorktreeDirs(explicitRoot) {
15433
15467
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
15434
15468
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
15435
- 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;
15436
15470
  try {
15437
15471
  const dirs = explicitRoot ? listDirsIn(resolveExplicitScanRoot(explicitRoot, primaryRepoRoot)) : worktreeScanDirs(siblingMmiWorktreesRoot(primaryRepoRoot), primaryRepoRoot, listDirsIn, isRepoCheckoutDir);
15438
15472
  const agentDirs2 = listDirsIn(agentWorktreesRoot(primaryRepoRoot));
@@ -15443,18 +15477,18 @@ async function siblingWorktreeDirs(explicitRoot) {
15443
15477
  }
15444
15478
  function listDirsIn(dir) {
15445
15479
  try {
15446
- 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));
15447
15481
  } catch {
15448
15482
  return [];
15449
15483
  }
15450
15484
  }
15451
15485
  function isRepoCheckoutDir(dir) {
15452
- 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"));
15453
15487
  }
15454
15488
  function resolveExplicitScanRoot(explicitRoot, repoRoot2) {
15455
15489
  let rootDirs;
15456
15490
  try {
15457
- 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);
15458
15492
  } catch {
15459
15493
  return explicitRoot;
15460
15494
  }
@@ -15786,10 +15820,10 @@ var rollout_plan_default = {
15786
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)."
15787
15821
  },
15788
15822
  baseline: {
15789
- version: "3.117.1",
15790
- tag: "v3.117.1",
15791
- commit: "b413403fb412",
15792
- npm: "@mutmutco/cli@3.117.1"
15823
+ version: "3.118.0",
15824
+ tag: "v3.118.0",
15825
+ commit: "4f9600d3bf89",
15826
+ npm: "@mutmutco/cli@3.118.0"
15793
15827
  },
15794
15828
  exitCriterion: "fleet-n-of-n",
15795
15829
  hubOnlyShortcut: "forbidden",
@@ -15806,14 +15840,14 @@ var rollout_plan_default = {
15806
15840
  repo: "mutmutco/mmi-hub",
15807
15841
  role: "canary",
15808
15842
  schedule: "train",
15809
- v3Target: "v3.117.1"
15843
+ v3Target: "v3.118.0"
15810
15844
  }
15811
15845
  ],
15812
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.",
15813
15847
  rollback: {
15814
15848
  independent: true,
15815
- mechanism: "npm dist-tag latest -> 3.117.1 and redeploy the Hub Lambda from tag v3.117.1 (b413403fb412); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15816
- v3Target: "v3.117.1 (@mutmutco/cli@3.117.1, tag commit b413403fb412 \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)"
15817
15851
  }
15818
15852
  },
15819
15853
  {
@@ -17897,7 +17931,7 @@ function planTrainApplyRepoGuard(applyRepo, cwdRepo, rerun) {
17897
17931
  async function resolveFoldPaths(deps, model) {
17898
17932
  const helper = "scripts/release-distribution.mjs";
17899
17933
  if (model === "hub-serverless" || model === "registry-publish") {
17900
- if ((0, import_node_fs20.existsSync)(helper)) {
17934
+ if ((0, import_node_fs21.existsSync)(helper)) {
17901
17935
  let out;
17902
17936
  try {
17903
17937
  out = await deps.run("node", [helper, "changed-files"]);
@@ -18016,7 +18050,7 @@ async function restoreMainNpmPackIdentities(deps, version) {
18016
18050
  if (mainBom.version !== version) return void 0;
18017
18051
  let localBom;
18018
18052
  try {
18019
- localBom = JSON.parse((0, import_node_fs20.readFileSync)(bomPath, "utf8"));
18053
+ localBom = JSON.parse((0, import_node_fs21.readFileSync)(bomPath, "utf8"));
18020
18054
  } catch (e) {
18021
18055
  throw new Error(
18022
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).`
@@ -18034,14 +18068,14 @@ async function restoreMainNpmPackIdentities(deps, version) {
18034
18068
  restored += 1;
18035
18069
  }
18036
18070
  if (restored === 0) return void 0;
18037
- (0, import_node_fs20.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
18071
+ (0, import_node_fs21.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
18038
18072
  `);
18039
18073
  return `restored ${restored} npm-pack BOM identit${restored === 1 ? "y" : "ies"} from origin/main (#4503)`;
18040
18074
  }
18041
18075
  function publishVisibilityFor(surfaceId) {
18042
18076
  let raw;
18043
18077
  try {
18044
- raw = (0, import_node_fs20.readFileSync)("surfaces.json", "utf8");
18078
+ raw = (0, import_node_fs21.readFileSync)("surfaces.json", "utf8");
18045
18079
  } catch (e) {
18046
18080
  if (e.code === "ENOENT") return "unknown";
18047
18081
  throw trainReadFailure(
@@ -18062,7 +18096,7 @@ function publishVisibilityFor(surfaceId) {
18062
18096
  }
18063
18097
  function npmPackArtifactName(packagePath) {
18064
18098
  try {
18065
- 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"));
18066
18100
  return pkg.name || void 0;
18067
18101
  } catch {
18068
18102
  return void 0;
@@ -18071,7 +18105,7 @@ function npmPackArtifactName(packagePath) {
18071
18105
  async function refuseDivergentPublishedNpmPack(deps, version) {
18072
18106
  let localBom;
18073
18107
  try {
18074
- 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"));
18075
18109
  } catch (e) {
18076
18110
  throw new Error(
18077
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).`
@@ -19233,17 +19267,17 @@ async function dispatchDeploy(deps, ctx, stage, ref, model, watch, autoRunSince,
19233
19267
  return { note: `no manual dispatch: ${model} repo deploys via its own push-triggered workflow`, deployStatus: "pending" };
19234
19268
  }
19235
19269
  function readLocalGateWorkflows() {
19236
- const dir = (0, import_node_path19.join)(".github", "workflows");
19270
+ const dir = (0, import_node_path20.join)(".github", "workflows");
19237
19271
  let names;
19238
19272
  try {
19239
- names = (0, import_node_fs20.readdirSync)(dir);
19273
+ names = (0, import_node_fs21.readdirSync)(dir);
19240
19274
  } catch {
19241
19275
  return null;
19242
19276
  }
19243
19277
  const files = [];
19244
19278
  for (const name of names.filter(isGateWorkflowPath)) {
19245
19279
  try {
19246
- 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") });
19247
19281
  } catch {
19248
19282
  }
19249
19283
  }
@@ -21464,12 +21498,12 @@ async function runPrLand(prNumber, options, deps) {
21464
21498
  }
21465
21499
 
21466
21500
  // src/wave-status.ts
21467
- var import_node_fs22 = require("node:fs");
21501
+ var import_node_fs23 = require("node:fs");
21468
21502
 
21469
21503
  // src/stage-runner.ts
21470
21504
  var import_node_child_process9 = require("node:child_process");
21471
- var import_node_fs21 = require("node:fs");
21472
- var import_node_path20 = require("node:path");
21505
+ var import_node_fs22 = require("node:fs");
21506
+ var import_node_path21 = require("node:path");
21473
21507
  var import_node_net = require("node:net");
21474
21508
  var import_node_util5 = require("node:util");
21475
21509
 
@@ -21608,11 +21642,11 @@ function appendForceRecreate(up) {
21608
21642
  return `${up.trimEnd()} --force-recreate`;
21609
21643
  }
21610
21644
  function stageStatePath(cwd = process.cwd()) {
21611
- return (0, import_node_path20.join)(cwd, "tmp", "stage", "state.json");
21645
+ return (0, import_node_path21.join)(cwd, "tmp", "stage", "state.json");
21612
21646
  }
21613
21647
  function stageGlobalStatePath(cwd = process.cwd(), gitCommonDir = ".git") {
21614
- const dir = (0, import_node_path20.isAbsolute)(gitCommonDir) ? gitCommonDir : (0, import_node_path20.resolve)(cwd, gitCommonDir);
21615
- 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");
21616
21650
  }
21617
21651
  function normPath3(path2) {
21618
21652
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -21836,14 +21870,14 @@ function stageProcessEnv(stagePort, extraEnv) {
21836
21870
  }
21837
21871
  async function ensureStageRuntimeEnv(config, opts, cwd) {
21838
21872
  if (!config.ensureEnv) return;
21839
- const target = (0, import_node_path20.join)(cwd, config.ensureEnv.target);
21840
- const example = (0, import_node_path20.join)(cwd, config.ensureEnv.example);
21841
- if (!(0, import_node_fs21.existsSync)(target) && (0, import_node_fs21.existsSync)(example)) {
21842
- (0, import_node_fs21.copyFileSync)(example, target);
21843
- } else if ((0, import_node_fs21.existsSync)(target) && (0, import_node_fs21.existsSync)(example)) {
21844
- const stale = detectStaleEnvFile((0, import_node_fs21.readFileSync)(example, "utf8"), (0, import_node_fs21.readFileSync)(target, "utf8"), {
21845
- exampleMtimeMs: (0, import_node_fs21.statSync)(example).mtimeMs,
21846
- 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
21847
21881
  });
21848
21882
  if (stale) {
21849
21883
  const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running /stage`;
@@ -21851,8 +21885,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
21851
21885
  console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
21852
21886
  }
21853
21887
  }
21854
- if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs21.existsSync)(target)) {
21855
- (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");
21856
21890
  }
21857
21891
  }
21858
21892
  async function gitText(cwd, args) {
@@ -21882,20 +21916,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
21882
21916
  return void 0;
21883
21917
  }
21884
21918
  function readState(path2) {
21885
- if (!(0, import_node_fs21.existsSync)(path2)) return null;
21919
+ if (!(0, import_node_fs22.existsSync)(path2)) return null;
21886
21920
  try {
21887
- return JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
21921
+ return JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
21888
21922
  } catch {
21889
21923
  return null;
21890
21924
  }
21891
21925
  }
21892
21926
  function mkdirFor(path2) {
21893
21927
  const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
21894
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
21928
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
21895
21929
  }
21896
21930
  function writeState(path2, state) {
21897
21931
  mkdirFor(path2);
21898
- (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");
21899
21933
  }
21900
21934
  function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
21901
21935
  const reservation = {
@@ -21915,7 +21949,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd) {
21915
21949
  await shell(state.teardown.command.trim(), state.teardown.cwd || state.cwd || fallbackCwd, Math.max(timeoutMs, 1e4));
21916
21950
  }
21917
21951
  for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
21918
- (0, import_node_fs21.rmSync)(path2, { force: true });
21952
+ (0, import_node_fs22.rmSync)(path2, { force: true });
21919
21953
  }
21920
21954
  }
21921
21955
  async function killTree(pid) {
@@ -22073,8 +22107,8 @@ async function runStage(config = {}, opts = {}) {
22073
22107
  await ensureStageRuntimeEnv(config, opts, cwd);
22074
22108
  if (build) await shell(sub(build), cwd, timeoutMs, stageProcessEnv(stagePort, extraEnv));
22075
22109
  } catch (e) {
22076
- (0, import_node_fs21.rmSync)(statePath, { force: true });
22077
- 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 });
22078
22112
  throw e;
22079
22113
  }
22080
22114
  const started = await startStage(config, {
@@ -22095,9 +22129,9 @@ function parseNextFromHead(headText) {
22095
22129
  }
22096
22130
  function readStageSummary(worktreePath) {
22097
22131
  const statePath = stageStatePath(worktreePath);
22098
- if (!(0, import_node_fs22.existsSync)(statePath)) return void 0;
22132
+ if (!(0, import_node_fs23.existsSync)(statePath)) return void 0;
22099
22133
  try {
22100
- const state = JSON.parse((0, import_node_fs22.readFileSync)(statePath, "utf8"));
22134
+ const state = JSON.parse((0, import_node_fs23.readFileSync)(statePath, "utf8"));
22101
22135
  const port = typeof state.port === "number" ? state.port : void 0;
22102
22136
  if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
22103
22137
  return { port, url: typeof state.url === "string" ? state.url : void 0 };
@@ -22206,9 +22240,9 @@ var import_node_os19 = require("node:os");
22206
22240
 
22207
22241
  // src/board.ts
22208
22242
  var import_node_child_process10 = require("node:child_process");
22209
- var import_node_fs23 = require("node:fs");
22243
+ var import_node_fs24 = require("node:fs");
22210
22244
  var import_node_os8 = require("node:os");
22211
- var import_node_path21 = require("node:path");
22245
+ var import_node_path22 = require("node:path");
22212
22246
  var import_node_util6 = require("node:util");
22213
22247
 
22214
22248
  // src/board-dependency.ts
@@ -23955,17 +23989,17 @@ function probeLocalClaimSession(marker, now = Date.now()) {
23955
23989
  claimSessionProbeCache.set(cacheKey, { checkedAt: now, state });
23956
23990
  return state;
23957
23991
  };
23958
- 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");
23959
23993
  try {
23960
23994
  const wanted = `${marker.session}.jsonl`.toLowerCase();
23961
23995
  const pending = [root];
23962
23996
  while (pending.length) {
23963
23997
  const dir = pending.pop();
23964
- for (const entry of (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true })) {
23965
- 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);
23966
24000
  if (entry.isDirectory()) pending.push(path2);
23967
24001
  else if (entry.isFile() && entry.name.toLowerCase() === wanted) {
23968
- 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");
23969
24003
  }
23970
24004
  }
23971
24005
  }
@@ -24864,8 +24898,8 @@ function consolidateCommandNamespaces(program3) {
24864
24898
  }
24865
24899
 
24866
24900
  // src/pi-plugin-registration.ts
24867
- var import_node_fs24 = require("node:fs");
24868
- var import_node_path22 = require("node:path");
24901
+ var import_node_fs25 = require("node:fs");
24902
+ var import_node_path23 = require("node:path");
24869
24903
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
24870
24904
 
24871
24905
  // src/plugin-cache-prune.ts
@@ -25123,48 +25157,48 @@ function newestExistingPiPlugin(home) {
25123
25157
  const cacheRoot = pluginCacheRoot(home);
25124
25158
  let names;
25125
25159
  try {
25126
- names = (0, import_node_fs24.readdirSync)(cacheRoot);
25160
+ names = (0, import_node_fs25.readdirSync)(cacheRoot);
25127
25161
  } catch {
25128
25162
  return void 0;
25129
25163
  }
25130
25164
  for (const version of names.filter(isVersionDirName).sort((a, b) => compareVersions(b, a))) {
25131
- const candidate = (0, import_node_path22.join)(cacheRoot, version, ".pi-plugin");
25132
- 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;
25133
25167
  }
25134
25168
  return void 0;
25135
25169
  }
25136
25170
  function expectedPiPluginPath(home, env, installedVersion) {
25137
25171
  const root = env.CLAUDE_PLUGIN_ROOT?.trim();
25138
- 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");
25139
25173
  const version = installedVersion ?? runningPluginVersion(env);
25140
25174
  if (version) {
25141
- const pinned = (0, import_node_path22.join)(home, ".claude", "plugins", "cache", "mutmutco", "mmi", version, ".pi-plugin");
25142
- 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;
25143
25177
  }
25144
25178
  return newestExistingPiPlugin(home);
25145
25179
  }
25146
25180
  function agentDirs(home, env = process.env) {
25147
25181
  const override = env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim();
25148
25182
  if (override) return [override];
25149
- const jerv = (0, import_node_path22.join)(home, ".jerv", "agent");
25150
- const pi = (0, import_node_path22.join)(home, ".pi", "agent");
25151
- 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 [];
25152
25186
  const dirs = [jerv];
25153
- 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);
25154
25188
  return dirs;
25155
25189
  }
25156
25190
  function settingsPath(agentDir) {
25157
- return (0, import_node_path22.join)(agentDir, "settings.json");
25191
+ return (0, import_node_path23.join)(agentDir, "settings.json");
25158
25192
  }
25159
25193
  function readPiPluginState(home, env, installedVersion) {
25160
25194
  const dirs = agentDirs(home, env);
25161
25195
  if (dirs.length === 0) return void 0;
25162
25196
  const expectedPath = expectedPiPluginPath(home, env, installedVersion);
25163
25197
  if (!expectedPath) return void 0;
25164
- const file = dirs.map(settingsPath).find((p) => (0, import_node_fs24.existsSync)(p)) ?? settingsPath(dirs[0]);
25165
- 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 };
25166
25200
  try {
25167
- const parsed = JSON.parse((0, import_node_fs24.readFileSync)(file, "utf8"));
25201
+ const parsed = JSON.parse((0, import_node_fs25.readFileSync)(file, "utf8"));
25168
25202
  const packages = Array.isArray(parsed.packages) ? parsed.packages : [];
25169
25203
  return { expectedPath, registeredPath: packages.find((p) => typeof p === "string" && isMmiPiPackage(p)), settingsReadable: true };
25170
25204
  } catch {
@@ -25188,20 +25222,20 @@ function acquirePiSettingsLock2(settingsFile) {
25188
25222
  return void 0;
25189
25223
  }
25190
25224
  function atomicWriteSettings(file, body) {
25191
- (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 });
25192
25226
  const tmp = `${file}.tmp-${process.pid}`;
25193
- (0, import_node_fs24.writeFileSync)(tmp, body, "utf8");
25227
+ (0, import_node_fs25.writeFileSync)(tmp, body, "utf8");
25194
25228
  try {
25195
- (0, import_node_fs24.renameSync)(tmp, file);
25229
+ (0, import_node_fs25.renameSync)(tmp, file);
25196
25230
  } catch (renameError) {
25197
- (0, import_node_fs24.rmSync)(tmp, { force: true });
25231
+ (0, import_node_fs25.rmSync)(tmp, { force: true });
25198
25232
  throw renameError;
25199
25233
  }
25200
25234
  }
25201
25235
  function healOneAgentDir(agentDir, expectedPath) {
25202
25236
  const file = settingsPath(agentDir);
25203
- const release = (0, import_node_fs24.existsSync)(file) ? acquirePiSettingsLock2(file) : void 0;
25204
- 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) {
25205
25239
  return {
25206
25240
  ok: false,
25207
25241
  detail: `Pi's settings lock (${file}.lock) is held by another process; nothing written, retry on the next doctor run`,
@@ -25210,9 +25244,9 @@ function healOneAgentDir(agentDir, expectedPath) {
25210
25244
  }
25211
25245
  try {
25212
25246
  let parsed = {};
25213
- if ((0, import_node_fs24.existsSync)(file)) {
25247
+ if ((0, import_node_fs25.existsSync)(file)) {
25214
25248
  try {
25215
- const raw = JSON.parse((0, import_node_fs24.readFileSync)(file, "utf8"));
25249
+ const raw = JSON.parse((0, import_node_fs25.readFileSync)(file, "utf8"));
25216
25250
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25217
25251
  return { ok: false, detail: "settings.json unreadable \u2014 nothing written (fail closed)" };
25218
25252
  }
@@ -25264,20 +25298,20 @@ function healPiPluginRegistration(home, env, installedVersion) {
25264
25298
  }
25265
25299
 
25266
25300
  // src/claude-binary-doctor.ts
25267
- var import_node_fs26 = require("node:fs");
25301
+ var import_node_fs27 = require("node:fs");
25268
25302
  var import_node_os11 = require("node:os");
25269
- var import_node_path24 = require("node:path");
25303
+ var import_node_path25 = require("node:path");
25270
25304
 
25271
25305
  // src/jerv-cli-spawn.ts
25272
- var import_node_fs25 = require("node:fs");
25306
+ var import_node_fs26 = require("node:fs");
25273
25307
  var import_node_os10 = require("node:os");
25274
- var import_node_path23 = require("node:path");
25308
+ var import_node_path24 = require("node:path");
25275
25309
  var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
25276
25310
  var POSIX_NAMES = ["jerv-cli"];
25277
- 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");
25278
25312
  function pathEnvEntries(pathEnv, platform2 = process.platform) {
25279
25313
  if (platform2 !== "win32") {
25280
- 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);
25281
25315
  }
25282
25316
  if (pathEnv.includes(";")) {
25283
25317
  return pathEnv.split(";").map((e) => e.trim()).filter(Boolean);
@@ -25310,10 +25344,10 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os10.hom
25310
25344
  push(normalizeSpawnPathEntry(entry, platform2));
25311
25345
  }
25312
25346
  if (platform2 === "win32") {
25313
- if (env.APPDATA) push((0, import_node_path23.join)(env.APPDATA, "npm"));
25314
- 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"));
25315
25349
  } else {
25316
- push((0, import_node_path23.join)(home, ".local", "bin"));
25350
+ push((0, import_node_path24.join)(home, ".local", "bin"));
25317
25351
  }
25318
25352
  return out;
25319
25353
  }
@@ -25321,23 +25355,23 @@ function jervCliCandidatePaths(env = process.env, home = (0, import_node_os10.ho
25321
25355
  const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
25322
25356
  const out = [];
25323
25357
  for (const dir of jervCliCandidateDirs(env, home, platform2)) {
25324
- 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));
25325
25359
  }
25326
25360
  return out;
25327
25361
  }
25328
- 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) {
25329
25363
  for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
25330
25364
  if (exists(candidate)) return candidate;
25331
25365
  }
25332
25366
  return void 0;
25333
25367
  }
25334
- function resolveJervCliNodeEntry(shimPath, exists = import_node_fs25.existsSync) {
25335
- 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);
25336
25370
  return exists(entry) ? entry : void 0;
25337
25371
  }
25338
25372
  function jervCliExecFileArgs(args, opts = {}) {
25339
25373
  const platform2 = opts.platform ?? process.platform;
25340
- const exists = opts.exists ?? import_node_fs25.existsSync;
25374
+ const exists = opts.exists ?? import_node_fs26.existsSync;
25341
25375
  const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os10.homedir)(), platform2, exists);
25342
25376
  if (resolved) {
25343
25377
  const entry = resolveJervCliNodeEntry(resolved, exists);
@@ -25427,26 +25461,26 @@ function globalNodeModulesRoots(host) {
25427
25461
  out.push(dir);
25428
25462
  };
25429
25463
  const prefix = env.npm_config_prefix?.trim();
25430
- 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"));
25431
25465
  for (const dir of jervCliCandidateDirs(env, host.home ?? (0, import_node_os11.homedir)(), platform2)) {
25432
- push((0, import_node_path24.join)(dir, "node_modules"));
25433
- 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"));
25434
25468
  }
25435
25469
  return out;
25436
25470
  }
25437
25471
  function readHead(path2) {
25438
25472
  let fd;
25439
25473
  try {
25440
- fd = (0, import_node_fs26.openSync)(path2, "r");
25474
+ fd = (0, import_node_fs27.openSync)(path2, "r");
25441
25475
  const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
25442
- 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);
25443
25477
  return buffer.subarray(0, read);
25444
25478
  } catch {
25445
25479
  return void 0;
25446
25480
  } finally {
25447
25481
  if (fd !== void 0) {
25448
25482
  try {
25449
- (0, import_node_fs26.closeSync)(fd);
25483
+ (0, import_node_fs27.closeSync)(fd);
25450
25484
  } catch {
25451
25485
  }
25452
25486
  }
@@ -25454,7 +25488,7 @@ function readHead(path2) {
25454
25488
  }
25455
25489
  function fileBytes(path2) {
25456
25490
  try {
25457
- return (0, import_node_fs26.statSync)(path2).size;
25491
+ return (0, import_node_fs27.statSync)(path2).size;
25458
25492
  } catch {
25459
25493
  return void 0;
25460
25494
  }
@@ -25468,17 +25502,17 @@ function readClaudeBinaryState(host = {}) {
25468
25502
  const arch = host.arch ?? process.arch;
25469
25503
  const magic = EXECUTABLE_MAGIC[platform2];
25470
25504
  if (!magic) return void 0;
25471
- 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")));
25472
25506
  if (!packageRoot) return void 0;
25473
25507
  const keys = platformPackageKeys(platform2, arch);
25474
25508
  const fallbackPackage = `${PACKAGE}-${keys[0]}`;
25475
25509
  let manifest;
25476
25510
  try {
25477
- 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"));
25478
25512
  } catch (e) {
25479
25513
  return {
25480
25514
  state: "unreadable",
25481
- binPath: (0, import_node_path24.join)(packageRoot, "package.json"),
25515
+ binPath: (0, import_node_path25.join)(packageRoot, "package.json"),
25482
25516
  expectedMagic: magic.name,
25483
25517
  platformPackage: fallbackPackage,
25484
25518
  error: `package.json could not be read \u2014 ${e.message}`
@@ -25495,17 +25529,17 @@ function readClaudeBinaryState(host = {}) {
25495
25529
  error: "package.json declares no `bin` entry \u2014 the executed file cannot be resolved"
25496
25530
  };
25497
25531
  }
25498
- const binPath = (0, import_node_path24.join)(packageRoot, binRelative);
25499
- 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);
25500
25534
  const optional = manifest.optionalDependencies;
25501
25535
  const publishes = (name) => typeof optional === "object" && optional !== null && Object.prototype.hasOwnProperty.call(optional, name);
25502
25536
  const published = keys.map((key) => `${PACKAGE}-${key}`).filter(publishes);
25503
25537
  if (published.length === 0) return void 0;
25504
25538
  const binIn = (name) => [
25505
- (0, import_node_path24.join)(packageRoot, "node_modules", ...name.split("/"), binName),
25506
- (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)
25507
25541
  ];
25508
- 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);
25509
25543
  const platformPackage = found?.name ?? published[0];
25510
25544
  let source;
25511
25545
  let sourceProblem;
@@ -25516,7 +25550,7 @@ function readClaudeBinaryState(host = {}) {
25516
25550
  } else {
25517
25551
  source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
25518
25552
  }
25519
- if (!(0, import_node_fs26.existsSync)(binPath)) {
25553
+ if (!(0, import_node_fs27.existsSync)(binPath)) {
25520
25554
  return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
25521
25555
  }
25522
25556
  const head = readHead(binPath);
@@ -25559,9 +25593,9 @@ function healClaudeBinary(host = {}, onStep) {
25559
25593
  const platform2 = host.platform ?? process.platform;
25560
25594
  const aside = `${probe.binPath}.stub-${Date.now()}`;
25561
25595
  let renamed = false;
25562
- if ((0, import_node_fs26.existsSync)(probe.binPath)) {
25596
+ if ((0, import_node_fs27.existsSync)(probe.binPath)) {
25563
25597
  try {
25564
- (0, import_node_fs26.renameSync)(probe.binPath, aside);
25598
+ (0, import_node_fs27.renameSync)(probe.binPath, aside);
25565
25599
  renamed = true;
25566
25600
  onStep?.(`renamed the stub aside: ${aside}`);
25567
25601
  } catch (e) {
@@ -25570,12 +25604,12 @@ function healClaudeBinary(host = {}, onStep) {
25570
25604
  }
25571
25605
  try {
25572
25606
  onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
25573
- (0, import_node_fs26.copyFileSync)(probe.source.path, probe.binPath);
25574
- 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);
25575
25609
  } catch (e) {
25576
25610
  if (renamed) {
25577
25611
  try {
25578
- (0, import_node_fs26.renameSync)(aside, probe.binPath);
25612
+ (0, import_node_fs27.renameSync)(aside, probe.binPath);
25579
25613
  } catch {
25580
25614
  return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
25581
25615
  }
@@ -25589,7 +25623,7 @@ function healClaudeBinary(host = {}, onStep) {
25589
25623
  let kept = false;
25590
25624
  if (renamed) {
25591
25625
  try {
25592
- (0, import_node_fs26.rmSync)(aside);
25626
+ (0, import_node_fs27.rmSync)(aside);
25593
25627
  } catch {
25594
25628
  kept = true;
25595
25629
  }
@@ -26923,8 +26957,8 @@ async function announceRelease(deps, args) {
26923
26957
  // src/repo-index.ts
26924
26958
  var import_node_crypto4 = require("node:crypto");
26925
26959
  var import_node_child_process13 = require("node:child_process");
26926
- var import_node_fs27 = require("node:fs");
26927
- var import_node_path25 = require("node:path");
26960
+ var import_node_fs28 = require("node:fs");
26961
+ var import_node_path26 = require("node:path");
26928
26962
  var REPO_INDEX_SCHEMA = 1;
26929
26963
  var HARD_DENY = [
26930
26964
  /(^|\/)\.env(\.|$)/i,
@@ -27049,11 +27083,11 @@ function loadReadmeHints(cwd, candidatePaths) {
27049
27083
  }
27050
27084
  for (const rel of readmes) {
27051
27085
  if (isHardDeniedPath(rel)) continue;
27052
- const abs = (0, import_node_path25.join)(cwd, ...rel.split("/"));
27053
- 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;
27054
27088
  let text;
27055
27089
  try {
27056
- text = (0, import_node_fs27.readFileSync)(abs, "utf8");
27090
+ text = (0, import_node_fs28.readFileSync)(abs, "utf8");
27057
27091
  } catch {
27058
27092
  continue;
27059
27093
  }
@@ -27066,7 +27100,7 @@ function loadReadmeHints(cwd, candidatePaths) {
27066
27100
  return hints;
27067
27101
  }
27068
27102
  function toPosix(p) {
27069
- return p.split(import_node_path25.sep).join("/");
27103
+ return p.split(import_node_path26.sep).join("/");
27070
27104
  }
27071
27105
  function listCandidatePaths(cwd, exec = import_node_child_process13.execFileSync) {
27072
27106
  try {
@@ -27088,11 +27122,11 @@ function rebuildRepoIndex(cwd, repoSlug2) {
27088
27122
  for (const rel of candidates) {
27089
27123
  if (ignored.has(rel)) continue;
27090
27124
  if (isHardDeniedPath(rel)) continue;
27091
- const abs = (0, import_node_path25.join)(cwd, ...rel.split("/"));
27092
- 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;
27093
27127
  let text;
27094
27128
  try {
27095
- text = (0, import_node_fs27.readFileSync)(abs, "utf8");
27129
+ text = (0, import_node_fs28.readFileSync)(abs, "utf8");
27096
27130
  } catch {
27097
27131
  continue;
27098
27132
  }
@@ -27117,16 +27151,16 @@ function rebuildRepoIndex(cwd, repoSlug2) {
27117
27151
  entries
27118
27152
  };
27119
27153
  const store = repoIndexStorePath(cwd);
27120
- (0, import_node_fs27.mkdirSync)((0, import_node_path25.dirname)(store), { recursive: true });
27121
- (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)}
27122
27156
  `, "utf8");
27123
27157
  return projection;
27124
27158
  }
27125
27159
  function loadRepoIndex(cwd) {
27126
27160
  const store = repoIndexStorePath(cwd);
27127
- if (!(0, import_node_fs27.existsSync)(store)) return null;
27161
+ if (!(0, import_node_fs28.existsSync)(store)) return null;
27128
27162
  try {
27129
- const raw = JSON.parse((0, import_node_fs27.readFileSync)(store, "utf8"));
27163
+ const raw = JSON.parse((0, import_node_fs28.readFileSync)(store, "utf8"));
27130
27164
  if (raw?.schema !== REPO_INDEX_SCHEMA || !Array.isArray(raw.entries)) return null;
27131
27165
  return raw;
27132
27166
  } catch {
@@ -27198,7 +27232,7 @@ function inferRepoSlug(cwd, exec = import_node_child_process13.execFileSync) {
27198
27232
  if (m?.[1]) return m[1].toLowerCase();
27199
27233
  } catch {
27200
27234
  }
27201
- return ((0, import_node_path25.basename)(cwd) || "local").toLowerCase();
27235
+ return ((0, import_node_path26.basename)(cwd) || "local").toLowerCase();
27202
27236
  }
27203
27237
 
27204
27238
  // src/repo-index-cloud-client.ts
@@ -27338,9 +27372,9 @@ async function gcRepoIndexCloud(deps) {
27338
27372
  }
27339
27373
 
27340
27374
  // src/repo-index-sync.ts
27341
- var import_node_fs28 = require("node:fs");
27375
+ var import_node_fs29 = require("node:fs");
27342
27376
  var import_node_os12 = require("node:os");
27343
- var import_node_path26 = require("node:path");
27377
+ var import_node_path27 = require("node:path");
27344
27378
  var import_node_child_process14 = require("node:child_process");
27345
27379
  var MAX_EMBED_BACKFILL_ROUNDS = 40;
27346
27380
  function normalizeRepo(raw) {
@@ -27384,7 +27418,7 @@ async function syncEstateRepoIndex(opts) {
27384
27418
  const failed = [];
27385
27419
  const skipped = [];
27386
27420
  for (const repo of repos) {
27387
- 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-"));
27388
27422
  try {
27389
27423
  shallowClone(repo, dir, opts.githubToken);
27390
27424
  const built = rebuildRepoIndex(dir, repo);
@@ -27434,7 +27468,7 @@ async function syncEstateRepoIndex(opts) {
27434
27468
  failed.push({ repo, error: e.message });
27435
27469
  } finally {
27436
27470
  try {
27437
- (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
27471
+ (0, import_node_fs29.rmSync)(dir, { recursive: true, force: true });
27438
27472
  } catch {
27439
27473
  }
27440
27474
  }
@@ -27443,7 +27477,7 @@ async function syncEstateRepoIndex(opts) {
27443
27477
  }
27444
27478
 
27445
27479
  // src/repo-index-health.ts
27446
- var import_node_fs29 = require("node:fs");
27480
+ var import_node_fs30 = require("node:fs");
27447
27481
 
27448
27482
  // testdata/repo-index-golden-queries.json
27449
27483
  var repo_index_golden_queries_default = {
@@ -27485,7 +27519,7 @@ function assertGoldenSuite(raw, source) {
27485
27519
  function loadGoldenSuite(path2) {
27486
27520
  let text;
27487
27521
  try {
27488
- text = (0, import_node_fs29.readFileSync)(path2, "utf8");
27522
+ text = (0, import_node_fs30.readFileSync)(path2, "utf8");
27489
27523
  } catch (e) {
27490
27524
  throw new Error(`golden suite unreadable at ${path2}: ${e.message}`);
27491
27525
  }
@@ -27631,8 +27665,8 @@ async function runRepoIndexHealth(opts) {
27631
27665
 
27632
27666
  // src/spawn-policy-core.ts
27633
27667
  var import_node_child_process15 = require("node:child_process");
27634
- var import_node_fs30 = require("node:fs");
27635
- var import_node_path27 = require("node:path");
27668
+ var import_node_fs31 = require("node:fs");
27669
+ var import_node_path28 = require("node:path");
27636
27670
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
27637
27671
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
27638
27672
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -27718,7 +27752,7 @@ function runSpawnPolicy(root) {
27718
27752
  for (const file of files) {
27719
27753
  let raw;
27720
27754
  try {
27721
- 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");
27722
27756
  } catch {
27723
27757
  continue;
27724
27758
  }
@@ -27736,8 +27770,8 @@ function runSpawnPolicy(root) {
27736
27770
 
27737
27771
  // src/test-policy-core.ts
27738
27772
  var import_node_child_process16 = require("node:child_process");
27739
- var import_node_fs31 = require("node:fs");
27740
- var import_node_path28 = require("node:path");
27773
+ var import_node_fs32 = require("node:fs");
27774
+ var import_node_path29 = require("node:path");
27741
27775
  var POLICY_FILE = "test-policy.json";
27742
27776
  var TEST_RE = /\.(?:test|spec)\.[cm]?[jt]sx?$/;
27743
27777
  var PY_TEST_RE = /(?:^|\/)test_[^/]*\.py$|_test\.py$/;
@@ -27790,7 +27824,7 @@ function isTestPath(path2) {
27790
27824
  return TEST_RE.test(path2) || PY_TEST_RE.test(path2);
27791
27825
  }
27792
27826
  function loadPolicy(root, readFile9 = readFileOrNull2) {
27793
- const raw = readFile9((0, import_node_path28.join)(root, POLICY_FILE));
27827
+ const raw = readFile9((0, import_node_path29.join)(root, POLICY_FILE));
27794
27828
  if (raw == null) return { mandatory: [], declared: false };
27795
27829
  try {
27796
27830
  return { ...JSON.parse(raw), declared: true };
@@ -27800,7 +27834,7 @@ function loadPolicy(root, readFile9 = readFileOrNull2) {
27800
27834
  }
27801
27835
  function readFileOrNull2(path2) {
27802
27836
  try {
27803
- return (0, import_node_fs31.readFileSync)(path2, "utf8");
27837
+ return (0, import_node_fs32.readFileSync)(path2, "utf8");
27804
27838
  } catch {
27805
27839
  return null;
27806
27840
  }
@@ -27827,12 +27861,12 @@ function classify(changed, policy, present = () => false) {
27827
27861
  const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
27828
27862
  return { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected };
27829
27863
  }
27830
- function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs31.existsSync)(path2)) {
27831
- 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)));
27832
27866
  }
27833
- 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)) {
27834
27868
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
27835
- 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)));
27836
27870
  }
27837
27871
  function evaluate(changed, policy, present = () => false) {
27838
27872
  const { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected } = classify(changed, policy, present);
@@ -28014,13 +28048,13 @@ function changedFilesSince(base, cwd) {
28014
28048
  }
28015
28049
  function runTestPolicy(root, deps = {}) {
28016
28050
  const policy = deps.policy ?? loadPolicy(root);
28017
- const exists = deps.exists ?? ((path2) => (0, import_node_fs31.existsSync)(path2));
28051
+ const exists = deps.exists ?? ((path2) => (0, import_node_fs32.existsSync)(path2));
28018
28052
  const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
28019
28053
  const base = deps.changed ? "(injected)" : resolveBase(root, deps.base);
28020
28054
  const refusal = deps.changed ? null : untrustworthyRange(root, base);
28021
28055
  const changed = deps.changed ?? (refusal ? [] : changedFilesSince(base, root));
28022
28056
  const lookup = deps.override !== void 0 ? { override: deps.override, refusals: [] } : !deps.changed && !refusal ? readOverride(base, root) : { override: null, refusals: [] };
28023
- const present = (path2) => exists((0, import_node_path28.join)(root, path2));
28057
+ const present = (path2) => exists((0, import_node_path29.join)(root, path2));
28024
28058
  const removedByThisDiff = removedPaths(changed);
28025
28059
  const staleFindings = [];
28026
28060
  const unresolved = unresolvedProtectedEntries(policy, root, exists).filter((p) => !removedByThisDiff.has(p));
@@ -28058,8 +28092,8 @@ function runTestPolicy(root, deps = {}) {
28058
28092
  }
28059
28093
 
28060
28094
  // src/project-info-sync.ts
28061
- var import_node_fs32 = require("node:fs");
28062
- var import_node_path29 = require("node:path");
28095
+ var import_node_fs33 = require("node:fs");
28096
+ var import_node_path30 = require("node:path");
28063
28097
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
28064
28098
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
28065
28099
  projectV2 { id }
@@ -28104,14 +28138,14 @@ function sharedName(entries, fallback) {
28104
28138
  }
28105
28139
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
28106
28140
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
28107
- const readmePath = (0, import_node_path29.join)(repoRoot2, "README.md");
28108
- 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`);
28109
28143
  const entries = entriesFor(project2, projects);
28110
28144
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
28111
28145
  const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
28112
28146
  if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
28113
28147
  const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
28114
- 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)}.`;
28115
28149
  const lines = [
28116
28150
  `# ${projectName}`,
28117
28151
  "",
@@ -28130,8 +28164,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
28130
28164
  const targetBase = `https://github.com/${targetRepo2}`;
28131
28165
  const targetBranch = branchFor(targetRepo2, projects);
28132
28166
  const orgDocs = [
28133
- (0, import_node_fs32.existsSync)((0, import_node_path29.join)(repoRoot2, "docs", "org-readme.md")) ? `- [Org identity](${targetBase}/blob/${targetBranch}/docs/org-readme.md)` : "",
28134
- (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)` : ""
28135
28169
  ].filter(Boolean);
28136
28170
  if (orgDocs.length) lines.push("", "## Organisation docs", "", ...orgDocs);
28137
28171
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines.join("\n")}
@@ -28916,8 +28950,8 @@ function writeError(res) {
28916
28950
  }
28917
28951
 
28918
28952
  // src/secrets-commands.ts
28919
- var import_node_fs33 = require("node:fs");
28920
- var import_node_path30 = require("node:path");
28953
+ var import_node_fs34 = require("node:fs");
28954
+ var import_node_path31 = require("node:path");
28921
28955
  var import_node_os13 = require("node:os");
28922
28956
 
28923
28957
  // src/secrets-diff.ts
@@ -29020,18 +29054,18 @@ function collectMap(value, previous = []) {
29020
29054
  return [...previous, value];
29021
29055
  }
29022
29056
  async function decryptRailsCredentials(input) {
29023
- const appDir = (0, import_node_path30.resolve)(input.appDir ?? process.cwd());
29057
+ const appDir = (0, import_node_path31.resolve)(input.appDir ?? process.cwd());
29024
29058
  const credentialsFile = input.credentialsFile ?? DEFAULT_RAILS_CREDENTIALS_FILE;
29025
29059
  const masterKeyFile = input.masterKeyFile ?? DEFAULT_RAILS_MASTER_KEY_FILE;
29026
- const credentialsPath = (0, import_node_path30.resolve)(appDir, credentialsFile);
29027
- 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);
29028
29062
  const env = {
29029
29063
  ...process.env,
29030
29064
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
29031
29065
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
29032
29066
  };
29033
- if ((0, import_node_fs33.existsSync)(masterKeyPath)) {
29034
- 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();
29035
29069
  }
29036
29070
  const script = [
29037
29071
  'require "json"',
@@ -29041,9 +29075,9 @@ async function decryptRailsCredentials(input) {
29041
29075
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
29042
29076
  "puts JSON.generate(config.config)"
29043
29077
  ].join("\n");
29044
- const scriptDir = (0, import_node_fs33.mkdtempSync)((0, import_node_path30.join)((0, import_node_os13.tmpdir)(), "mmi-rails-decrypt-"));
29045
- const scriptPath = (0, import_node_path30.join)(scriptDir, "decrypt.rb");
29046
- (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");
29047
29081
  try {
29048
29082
  const args = ["exec", "ruby", scriptPath];
29049
29083
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -29055,7 +29089,7 @@ async function decryptRailsCredentials(input) {
29055
29089
  });
29056
29090
  return JSON.parse(stdout);
29057
29091
  } finally {
29058
- (0, import_node_fs33.rmSync)(scriptDir, { recursive: true, force: true });
29092
+ (0, import_node_fs34.rmSync)(scriptDir, { recursive: true, force: true });
29059
29093
  }
29060
29094
  }
29061
29095
  async function readSecretStdin() {
@@ -29145,7 +29179,7 @@ function registerSecretsCommands(program3) {
29145
29179
  let body;
29146
29180
  if (o.file) {
29147
29181
  try {
29148
- 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");
29149
29183
  } catch (e) {
29150
29184
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
29151
29185
  }
@@ -29250,7 +29284,7 @@ function registerSecretsCommands(program3) {
29250
29284
  {
29251
29285
  ...d,
29252
29286
  decryptRailsCredentials,
29253
- 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))
29254
29288
  },
29255
29289
  {
29256
29290
  repo: o.repo,
@@ -29455,7 +29489,7 @@ function emitCliCallTelemetry(command) {
29455
29489
  }
29456
29490
 
29457
29491
  // src/box-commands.ts
29458
- var import_node_fs34 = require("node:fs");
29492
+ var import_node_fs35 = require("node:fs");
29459
29493
 
29460
29494
  // src/box.ts
29461
29495
  var BOX_KEYS = {
@@ -29658,7 +29692,7 @@ function registerBoxCommands(program3) {
29658
29692
  }
29659
29693
  if (o.json) console.log(JSON.stringify({ box: found, incomplete }, null, 2));
29660
29694
  else if (o.ssh && o.script) {
29661
- (0, import_node_fs34.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
29695
+ (0, import_node_fs35.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
29662
29696
  console.log(`wrote ${o.script} \u2014 run: bash "${o.script}"`);
29663
29697
  } else if (o.ssh) console.log(`${formatSshRecipe(found)}
29664
29698
  ${SSH_RECIPE_AGENT_NOTE}`);
@@ -29977,7 +30011,7 @@ function registerSchedulesCommands(program3) {
29977
30011
 
29978
30012
  // src/schedules-lift-command.ts
29979
30013
  var import_promises6 = require("node:fs/promises");
29980
- var import_node_path31 = require("node:path");
30014
+ var import_node_path32 = require("node:path");
29981
30015
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
29982
30016
  var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
29983
30017
  var SchedulesLiftUsageError = class extends Error {
@@ -30004,7 +30038,7 @@ async function readWorkflowFiles(dir) {
30004
30038
  const files = [];
30005
30039
  for (const name of names.sort()) {
30006
30040
  if (!/\.ya?ml$/.test(name)) continue;
30007
- 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") });
30008
30042
  }
30009
30043
  return files;
30010
30044
  }
@@ -30152,9 +30186,9 @@ function registerEdgeCommands(program3) {
30152
30186
  }
30153
30187
 
30154
30188
  // src/bootstrap-commands.ts
30155
- var import_node_fs35 = require("node:fs");
30189
+ var import_node_fs36 = require("node:fs");
30156
30190
  var import_node_os14 = require("node:os");
30157
- var import_node_path32 = require("node:path");
30191
+ var import_node_path33 = require("node:path");
30158
30192
 
30159
30193
  // src/bootstrap-drift.ts
30160
30194
  var import_node_crypto6 = require("node:crypto");
@@ -31034,13 +31068,13 @@ function registerBootstrapCommands(program3) {
31034
31068
  client: defaultGitHubClient(),
31035
31069
  projectMeta: meta,
31036
31070
  deployModel: typeof meta?.deployModel === "string" ? meta.deployModel : void 0,
31037
- 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,
31038
31072
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
31039
31073
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
31040
31074
  // #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
31041
31075
  // permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
31042
31076
  // sanction, which is the pre-#3664 behaviour.
31043
- 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,
31044
31078
  requiredGcpApis: (() => {
31045
31079
  const v = meta?.requiredGcpApis;
31046
31080
  if (Array.isArray(v)) return v;
@@ -31093,14 +31127,14 @@ function registerBootstrapCommands(program3) {
31093
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 () => {
31094
31128
  const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
31095
31129
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31096
- 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`);
31097
31131
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31098
31132
  if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
31099
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31133
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31100
31134
  const hubContents = /* @__PURE__ */ new Map();
31101
31135
  for (const s of manifest.seeds) {
31102
31136
  if (s.ownership !== "org" || s.source !== "self") continue;
31103
- 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);
31104
31138
  }
31105
31139
  let targets;
31106
31140
  let classOf = (_repo) => "deployable";
@@ -31179,10 +31213,10 @@ function registerBootstrapCommands(program3) {
31179
31213
  return fail(`bootstrap apply: ${e.message}`);
31180
31214
  }
31181
31215
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31182
- 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`);
31183
31217
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31184
31218
  if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
31185
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31219
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31186
31220
  const baseBranch = o.class === "content" ? "main" : "development";
31187
31221
  const slug = parsedRepo.slug;
31188
31222
  const onlyTarget = o.only.trim();
@@ -31193,16 +31227,16 @@ function registerBootstrapCommands(program3) {
31193
31227
  ${known}`);
31194
31228
  }
31195
31229
  const gh = async (args) => execFileP2("gh", args, { timeout: 2e4 });
31196
- 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;
31197
31231
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
31198
31232
  const putSeed = async (target, content, ref, sha) => {
31199
- 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`);
31200
- (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");
31201
31235
  try {
31202
31236
  await gh(contentPutInputArgs(repo, target, tmp));
31203
31237
  } finally {
31204
31238
  try {
31205
- (0, import_node_fs35.unlinkSync)(tmp);
31239
+ (0, import_node_fs36.unlinkSync)(tmp);
31206
31240
  } catch {
31207
31241
  }
31208
31242
  }
@@ -31467,10 +31501,10 @@ LIVE apply to ${repo}:
31467
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 () => {
31468
31502
  const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
31469
31503
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31470
- 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`);
31471
31505
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31472
31506
  if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
31473
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31507
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31474
31508
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
31475
31509
  if (!o.target) {
31476
31510
  return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
@@ -31479,8 +31513,8 @@ LIVE apply to ${repo}:
31479
31513
  const seed = propagatable.find((s) => s.target === o.target);
31480
31514
  if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no ownership:org + source:self seed in ${manifestPath}. Propagatable targets:
31481
31515
  ${propagatable.map((s) => s.target).join("\n ")}`);
31482
- 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`);
31483
- 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");
31484
31518
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
31485
31519
  const cfg = await loadConfig();
31486
31520
  const projects = await fetchProjectsList(registryClientDeps(cfg));
@@ -31489,9 +31523,9 @@ LIVE apply to ${repo}:
31489
31523
  }
31490
31524
  const rosterRepos2 = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
31491
31525
  let independentCount = rosterRepos2.length;
31492
- if ((0, import_node_fs35.existsSync)("projects.json")) {
31526
+ if ((0, import_node_fs36.existsSync)("projects.json")) {
31493
31527
  try {
31494
- 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"));
31495
31529
  const localRepos = /* @__PURE__ */ new Set();
31496
31530
  for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
31497
31531
  const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
@@ -31607,13 +31641,13 @@ LIVE apply to ${repo}:
31607
31641
  } catch {
31608
31642
  existingSha = void 0;
31609
31643
  }
31610
- 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`);
31611
- (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");
31612
31646
  try {
31613
31647
  await gh(contentPutInputArgs(rec.repo, seed.target, tmp));
31614
31648
  } finally {
31615
31649
  try {
31616
- (0, import_node_fs35.unlinkSync)(tmp);
31650
+ (0, import_node_fs36.unlinkSync)(tmp);
31617
31651
  } catch {
31618
31652
  }
31619
31653
  }
@@ -31671,10 +31705,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31671
31705
  return fail(`bootstrap rollback: ${e.message}`);
31672
31706
  }
31673
31707
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
31674
- 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)`);
31675
31709
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31676
31710
  if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
31677
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31711
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31678
31712
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
31679
31713
  if (!o.target) {
31680
31714
  return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
@@ -31691,10 +31725,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31691
31725
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
31692
31726
  let candidates;
31693
31727
  if (o.record) {
31694
- 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`);
31695
31729
  let parsed;
31696
31730
  try {
31697
- parsed = JSON.parse((0, import_node_fs35.readFileSync)(o.record, "utf8"));
31731
+ parsed = JSON.parse((0, import_node_fs36.readFileSync)(o.record, "utf8"));
31698
31732
  } catch (e) {
31699
31733
  return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
31700
31734
  }
@@ -31763,13 +31797,13 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31763
31797
  } catch {
31764
31798
  existingSha = void 0;
31765
31799
  }
31766
- 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`);
31767
- (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");
31768
31802
  try {
31769
31803
  await gh(contentPutInputArgs(repo, seed.target, tmp));
31770
31804
  } finally {
31771
31805
  try {
31772
- (0, import_node_fs35.unlinkSync)(tmp);
31806
+ (0, import_node_fs36.unlinkSync)(tmp);
31773
31807
  } catch {
31774
31808
  }
31775
31809
  }
@@ -31791,12 +31825,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31791
31825
  }
31792
31826
 
31793
31827
  // src/stage-commands.ts
31794
- var import_node_fs37 = require("node:fs");
31795
- var import_node_path34 = require("node:path");
31828
+ var import_node_fs38 = require("node:fs");
31829
+ var import_node_path35 = require("node:path");
31796
31830
 
31797
31831
  // src/port-registry.ts
31798
- var import_node_fs36 = require("node:fs");
31799
- var import_node_path33 = require("node:path");
31832
+ var import_node_fs37 = require("node:fs");
31833
+ var import_node_path34 = require("node:path");
31800
31834
 
31801
31835
  // ../infra/port-geometry.mjs
31802
31836
  var PORT_BLOCK = 100;
@@ -31810,8 +31844,8 @@ function nextPortBlock(registry2) {
31810
31844
  return [base, base + PORT_SPAN];
31811
31845
  }
31812
31846
  function loadPortRegistry(path2) {
31813
- if (!(0, import_node_fs36.existsSync)(path2)) return {};
31814
- 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"));
31815
31849
  const out = {};
31816
31850
  for (const [key, value] of Object.entries(raw)) {
31817
31851
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -31825,9 +31859,9 @@ function ensurePortRange(repo, path2) {
31825
31859
  const existing = registry2[repo];
31826
31860
  if (existing) return existing;
31827
31861
  const range = nextPortBlock(registry2);
31828
- 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")) : {};
31829
31863
  raw[repo] = range;
31830
- (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");
31831
31865
  return range;
31832
31866
  }
31833
31867
  function portCursorSeed(registry2) {
@@ -31849,22 +31883,22 @@ function existingPortRange(repo, registry2) {
31849
31883
  return registry2[repo] ?? null;
31850
31884
  }
31851
31885
  function portRangeInfraAt(root, source) {
31852
- const registryPath = (0, import_node_path33.join)(root, "infra", "port-ranges.json");
31853
- const ddbScriptPath = (0, import_node_path33.join)(root, "infra", "port-ddb.mjs");
31854
- 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;
31855
31889
  return { root, source, registryPath, ddbScriptPath };
31856
31890
  }
31857
31891
  function resolvePortRangeInfra(cwd, packageDir) {
31858
31892
  const direct = portRangeInfraAt(cwd, "cwd");
31859
31893
  if (direct) return direct;
31860
- for (let dir = cwd; ; dir = (0, import_node_path33.dirname)(dir)) {
31861
- 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");
31862
31896
  if (sibling) return sibling;
31863
- const parent = (0, import_node_path33.dirname)(dir);
31897
+ const parent = (0, import_node_path34.dirname)(dir);
31864
31898
  if (parent === dir) break;
31865
31899
  }
31866
31900
  if (packageDir) {
31867
- const pkgRoot = (0, import_node_path33.join)(packageDir, "..", "..");
31901
+ const pkgRoot = (0, import_node_path34.join)(packageDir, "..", "..");
31868
31902
  const pkgFrom = portRangeInfraAt(pkgRoot, "pkg-root");
31869
31903
  if (pkgFrom) return pkgFrom;
31870
31904
  }
@@ -32058,8 +32092,8 @@ function registerStageCommands(program3) {
32058
32092
  const portRange = portRangeMeta && typeof portRangeMeta.start === "number" && typeof portRangeMeta.end === "number" ? [portRangeMeta.start, portRangeMeta.end] : void 0;
32059
32093
  return decideStage({
32060
32094
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
32061
- hasCompose: (0, import_node_fs37.existsSync)((0, import_node_path34.join)(process.cwd(), "docker-compose.yml")),
32062
- 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"))
32063
32097
  });
32064
32098
  }
32065
32099
  async function fetchStageVaultEnvMerge() {
@@ -32550,9 +32584,9 @@ function registerBoardCommands(program3) {
32550
32584
  }
32551
32585
 
32552
32586
  // src/merge-cleanup.ts
32553
- var import_node_fs38 = require("node:fs");
32587
+ var import_node_fs39 = require("node:fs");
32554
32588
  var import_promises8 = require("node:fs/promises");
32555
- var import_node_path36 = require("node:path");
32589
+ var import_node_path37 = require("node:path");
32556
32590
  var import_node_os15 = require("node:os");
32557
32591
  var import_node_child_process18 = require("node:child_process");
32558
32592
 
@@ -32640,7 +32674,7 @@ function boardAdvanceFailureMessage(result) {
32640
32674
 
32641
32675
  // src/deferred-registry-store.ts
32642
32676
  var import_promises7 = require("node:fs/promises");
32643
- var import_node_path35 = require("node:path");
32677
+ var import_node_path36 = require("node:path");
32644
32678
  var sleep2 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
32645
32679
  async function atomicWrite(target, contents) {
32646
32680
  const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
@@ -32691,12 +32725,12 @@ function makeDeferredWorktreeStore(registryPath, lockOpts = {}) {
32691
32725
  },
32692
32726
  // Standalone atomic write — THROWS on failure (no best-effort swallow, #2846).
32693
32727
  write: async (entries) => {
32694
- 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 });
32695
32729
  await atomicWrite(registryPath, serializeDeferredWorktrees(entries));
32696
32730
  },
32697
32731
  // Serialized read-modify-write under the repo-wide lock (#2846).
32698
32732
  update: async (mutate) => {
32699
- 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 });
32700
32734
  const deadline = Date.now() + opts.maxWaitMs;
32701
32735
  for (; ; ) {
32702
32736
  const guard = await acquireLock(lockPath, opts, deadline);
@@ -32867,7 +32901,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32867
32901
  );
32868
32902
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
32869
32903
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
32870
- 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;
32871
32905
  const gcActor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
32872
32906
  const owners = readWorktreeOwners(primaryRepoRoot);
32873
32907
  const removalNow = Date.now();
@@ -32924,7 +32958,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32924
32958
  const cleanup = await cleanupPrMergeLocalBranch(branch.branch, {
32925
32959
  beforeWorktrees,
32926
32960
  startingPath: branch.worktreePath,
32927
- pathExists: (p) => (0, import_node_fs38.existsSync)(p),
32961
+ pathExists: (p) => (0, import_node_fs39.existsSync)(p),
32928
32962
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
32929
32963
  teardownWorktreeStage,
32930
32964
  deferredStore,
@@ -32962,7 +32996,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32962
32996
  let removalAttempted = false;
32963
32997
  try {
32964
32998
  const cleanupTarget = resolveSafeSiblingWorktreeCleanupTarget(wt.path, cleanupRoots, {
32965
- realpath: (path2) => (0, import_node_fs38.realpathSync)(path2)
32999
+ realpath: (path2) => (0, import_node_fs39.realpathSync)(path2)
32966
33000
  });
32967
33001
  if (!cleanupTarget.ok) {
32968
33002
  result.failed.push(`${wt.path}: ${cleanupTarget.reason}`);
@@ -33049,13 +33083,13 @@ async function composeOverrideBodyFile(prNumber, repoArgs, gh) {
33049
33083
  const commits = JSON.parse(raw).commits ?? [];
33050
33084
  const body = squashBodyWithOverride(commits.map((c) => ({ headline: c.messageHeadline ?? "", body: c.messageBody ?? "" })), process.cwd());
33051
33085
  if (!body) return void 0;
33052
- const dir = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os15.tmpdir)(), "mmi-squash-body-"));
33053
- const path2 = (0, import_node_path36.join)(dir, "body.txt");
33054
- (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}
33055
33089
  `, "utf8");
33056
33090
  return { path: path2, cleanup: () => {
33057
33091
  try {
33058
- (0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
33092
+ (0, import_node_fs39.rmSync)(dir, { recursive: true, force: true });
33059
33093
  } catch {
33060
33094
  }
33061
33095
  } };
@@ -33177,13 +33211,13 @@ var realWorktreeDirRemover = {
33177
33211
  probe: (p) => {
33178
33212
  let st;
33179
33213
  try {
33180
- st = (0, import_node_fs38.lstatSync)(p);
33214
+ st = (0, import_node_fs39.lstatSync)(p);
33181
33215
  } catch {
33182
33216
  return null;
33183
33217
  }
33184
33218
  if (st.isSymbolicLink()) return "link";
33185
33219
  try {
33186
- (0, import_node_fs38.readlinkSync)(p);
33220
+ (0, import_node_fs39.readlinkSync)(p);
33187
33221
  return "link";
33188
33222
  } catch {
33189
33223
  }
@@ -33191,7 +33225,7 @@ var realWorktreeDirRemover = {
33191
33225
  },
33192
33226
  readdir: (p) => {
33193
33227
  try {
33194
- return (0, import_node_fs38.readdirSync)(p);
33228
+ return (0, import_node_fs39.readdirSync)(p);
33195
33229
  } catch {
33196
33230
  return [];
33197
33231
  }
@@ -33200,9 +33234,9 @@ var realWorktreeDirRemover = {
33200
33234
  // leaving the target); a file symlink with unlink. rmdir first, fall back to unlink.
33201
33235
  detachLink: (p) => {
33202
33236
  try {
33203
- (0, import_node_fs38.rmdirSync)(p);
33237
+ (0, import_node_fs39.rmdirSync)(p);
33204
33238
  } catch {
33205
- (0, import_node_fs38.unlinkSync)(p);
33239
+ (0, import_node_fs39.unlinkSync)(p);
33206
33240
  }
33207
33241
  },
33208
33242
  removeTree: (p) => (0, import_promises8.rm)(p, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
@@ -33235,9 +33269,9 @@ async function worktreeHasStageState(worktreePath) {
33235
33269
  }
33236
33270
  }
33237
33271
  function stageStateFileBelongsToWorktree(statePath, worktreePath) {
33238
- if (!(0, import_node_fs38.existsSync)(statePath)) return false;
33272
+ if (!(0, import_node_fs39.existsSync)(statePath)) return false;
33239
33273
  try {
33240
- const state = JSON.parse((0, import_node_fs38.readFileSync)(statePath, "utf8"));
33274
+ const state = JSON.parse((0, import_node_fs39.readFileSync)(statePath, "utf8"));
33241
33275
  const recordedCwd = typeof state.identity?.cwd === "string" ? state.identity.cwd : typeof state.cwd === "string" ? state.cwd : "";
33242
33276
  return Boolean(recordedCwd && isPathUnderDirectory2(recordedCwd, worktreePath));
33243
33277
  } catch {
@@ -33672,14 +33706,14 @@ async function checkDocsIndexAtHead(opts, deps) {
33672
33706
  }
33673
33707
 
33674
33708
  // src/worktree-lifecycle-commands.ts
33675
- var import_node_fs40 = require("node:fs");
33709
+ var import_node_fs41 = require("node:fs");
33676
33710
  var import_promises9 = require("node:fs/promises");
33677
- var import_node_path38 = require("node:path");
33711
+ var import_node_path39 = require("node:path");
33678
33712
 
33679
33713
  // src/worktree-install-cache.ts
33680
33714
  var import_node_crypto7 = require("node:crypto");
33681
- var import_node_fs39 = require("node:fs");
33682
- var import_node_path37 = require("node:path");
33715
+ var import_node_fs40 = require("node:fs");
33716
+ var import_node_path38 = require("node:path");
33683
33717
  var CACHE_DIR = "worktree-install-cache";
33684
33718
  var MANIFEST = "manifest.json";
33685
33719
  var NODE_MODULES2 = "node_modules";
@@ -33692,16 +33726,16 @@ var LOCKFILE_NAMES = [
33692
33726
  "package-lock.json"
33693
33727
  ];
33694
33728
  var realWorktreeInstallCacheFs = {
33695
- exists: import_node_fs39.existsSync,
33696
- readFile: (path2) => (0, import_node_fs39.readFileSync)(path2, "utf8"),
33697
- lstat: (path2) => (0, import_node_fs39.lstatSync)(path2),
33698
- 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 }),
33699
33733
  mkdirp: (path2) => {
33700
- (0, import_node_fs39.mkdirSync)(path2, { recursive: true });
33734
+ (0, import_node_fs40.mkdirSync)(path2, { recursive: true });
33701
33735
  },
33702
- writeFile: (path2, contents) => (0, import_node_fs39.writeFileSync)(path2, contents, "utf8"),
33736
+ writeFile: (path2, contents) => (0, import_node_fs40.writeFileSync)(path2, contents, "utf8"),
33703
33737
  rm: (path2) => {
33704
- (0, import_node_fs39.rmSync)(path2, { recursive: true, force: true });
33738
+ (0, import_node_fs40.rmSync)(path2, { recursive: true, force: true });
33705
33739
  }
33706
33740
  };
33707
33741
  function hashLockfileBytes(contents) {
@@ -33709,7 +33743,7 @@ function hashLockfileBytes(contents) {
33709
33743
  }
33710
33744
  function resolveWorktreeInstallLockfile(packageDir, fs2 = realWorktreeInstallCacheFs) {
33711
33745
  for (const name of LOCKFILE_NAMES) {
33712
- const path2 = (0, import_node_path37.join)(packageDir, name);
33746
+ const path2 = (0, import_node_path38.join)(packageDir, name);
33713
33747
  if (!fs2.exists(path2)) continue;
33714
33748
  try {
33715
33749
  const hash = hashLockfileBytes(fs2.readFile(path2));
@@ -33724,8 +33758,8 @@ function worktreeInstallCacheEntry(primaryRoot, lockfileHash) {
33724
33758
  const root = repoRuntimeStatePath(primaryRoot, CACHE_DIR, lockfileHash);
33725
33759
  return {
33726
33760
  root,
33727
- manifestPath: (0, import_node_path37.join)(root, MANIFEST),
33728
- 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)
33729
33763
  };
33730
33764
  }
33731
33765
  function readWorktreeInstallCacheManifest(manifestPath, fs2 = realWorktreeInstallCacheFs) {
@@ -33765,7 +33799,7 @@ function invalidateWorktreeInstallCacheEntry(entry, fs2 = realWorktreeInstallCac
33765
33799
  }
33766
33800
  }
33767
33801
  function removeMaterializedTree(packageDir, fs2) {
33768
- const dest = (0, import_node_path37.join)(packageDir, NODE_MODULES2);
33802
+ const dest = (0, import_node_path38.join)(packageDir, NODE_MODULES2);
33769
33803
  if (!fs2.exists(dest)) return;
33770
33804
  fs2.rm(dest);
33771
33805
  if (fs2.exists(dest)) {
@@ -33773,7 +33807,7 @@ function removeMaterializedTree(packageDir, fs2) {
33773
33807
  }
33774
33808
  }
33775
33809
  function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeInstallCacheFs) {
33776
- const dest = (0, import_node_path37.join)(destPackageDir, NODE_MODULES2);
33810
+ const dest = (0, import_node_path38.join)(destPackageDir, NODE_MODULES2);
33777
33811
  try {
33778
33812
  if (fs2.exists(dest)) fs2.rm(dest);
33779
33813
  fs2.mkdirp(destPackageDir);
@@ -33788,7 +33822,7 @@ function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeI
33788
33822
  }
33789
33823
  }
33790
33824
  async function storeWorktreeInstallCacheEntry(primaryRoot, lockfile3, command, sourcePackageDir, fs2 = realWorktreeInstallCacheFs, now = Date.now()) {
33791
- const source = (0, import_node_path37.join)(sourcePackageDir, NODE_MODULES2);
33825
+ const source = (0, import_node_path38.join)(sourcePackageDir, NODE_MODULES2);
33792
33826
  if (!isMaterializableNodeModulesDir(source, fs2)) return;
33793
33827
  const entry = worktreeInstallCacheEntry(primaryRoot, lockfile3.hash);
33794
33828
  const manifest = {
@@ -34048,7 +34082,7 @@ function classifyStaleLeaks(input) {
34048
34082
  var defaultOrphanDirScanDeps = {
34049
34083
  listDirs: (root) => {
34050
34084
  try {
34051
- 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));
34052
34086
  } catch {
34053
34087
  return [];
34054
34088
  }
@@ -34214,13 +34248,13 @@ function registerWorktreeCommands(program3) {
34214
34248
  const detached = headBorn && !symbolicBranch;
34215
34249
  const branch = symbolicBranch || (detached ? "HEAD" : "");
34216
34250
  if (!wtPath || !branch) return fail("worktree land: not inside a git worktree");
34217
- const gitFile = (0, import_node_path38.join)(wtPath, ".git");
34218
- 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();
34219
34253
  if (apply && !isLinked) {
34220
34254
  return fail("worktree land: run from inside the linked worktree you want to land (this is the primary checkout)");
34221
34255
  }
34222
34256
  const commonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
34223
- const primaryCheckout = commonDir ? (0, import_node_path38.dirname)(commonDir) : wtPath;
34257
+ const primaryCheckout = commonDir ? (0, import_node_path39.dirname)(commonDir) : wtPath;
34224
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);
34225
34259
  const orphan = classifyOrphanedWorktree({
34226
34260
  branch,
@@ -34494,10 +34528,10 @@ async function gatherWorktreeContext() {
34494
34528
  if (s) stages.push({ path: wt.path, port: s.port });
34495
34529
  }
34496
34530
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
34497
- 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;
34498
34532
  const wtRoot = siblingMmiWorktreesRoot(primaryRepoRoot);
34499
34533
  let orphanDirs = [];
34500
- if ((0, import_node_fs40.existsSync)(wtRoot)) {
34534
+ if ((0, import_node_fs41.existsSync)(wtRoot)) {
34501
34535
  orphanDirs = scanOrphanDirs(wtRoot, worktreeGitRoot, {
34502
34536
  ...defaultOrphanDirScanDeps,
34503
34537
  listDirs: (root) => worktreeScanDirs(root, primaryRepoRoot, defaultOrphanDirScanDeps.listDirs, isRepoCheckoutDir)
@@ -34533,7 +34567,7 @@ ${err.stderr ?? ""}`;
34533
34567
  }
34534
34568
 
34535
34569
  // src/issue-commands.ts
34536
- var import_node_fs41 = require("node:fs");
34570
+ var import_node_fs42 = require("node:fs");
34537
34571
  var import_node_crypto8 = require("node:crypto");
34538
34572
  var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
34539
34573
  var ReparentConflictError = class extends Error {
@@ -34551,7 +34585,7 @@ async function editIssue(client, options, deps = {}) {
34551
34585
  const url = `https://github.com/${repo}/issues/${parsed.number}`;
34552
34586
  const patch = {};
34553
34587
  let bodyChanged = false;
34554
- 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("") };
34555
34589
  if (options.titleFile !== void 0) {
34556
34590
  patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
34557
34591
  } else if (options.title !== void 0) {
@@ -35156,7 +35190,7 @@ function extendCreateCommand(issue2, batchAttach) {
35156
35190
  if (opts.batch) {
35157
35191
  let specs;
35158
35192
  try {
35159
- const raw = (0, import_node_fs41.readFileSync)(opts.batch, "utf8");
35193
+ const raw = (0, import_node_fs42.readFileSync)(opts.batch, "utf8");
35160
35194
  specs = JSON.parse(raw);
35161
35195
  if (!Array.isArray(specs)) throw new Error("batch file must contain a JSON array");
35162
35196
  } catch (e) {
@@ -35231,8 +35265,8 @@ ${lines}`, {
35231
35265
  }
35232
35266
 
35233
35267
  // src/train-commands.ts
35234
- var import_node_fs42 = require("node:fs");
35235
- var import_node_path39 = require("node:path");
35268
+ var import_node_fs43 = require("node:fs");
35269
+ var import_node_path40 = require("node:path");
35236
35270
  var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
35237
35271
  function resolveReleaseBumpIntent(raw) {
35238
35272
  const intent = typeof raw === "string" ? raw.trim() : "";
@@ -35243,7 +35277,7 @@ function resolveReleaseBumpIntent(raw) {
35243
35277
  }
35244
35278
  function readRepoVersion() {
35245
35279
  try {
35246
- 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;
35247
35281
  } catch {
35248
35282
  return void 0;
35249
35283
  }
@@ -35400,9 +35434,9 @@ function registerDeployCommands(program3) {
35400
35434
  }
35401
35435
 
35402
35436
  // src/discovery-commands.ts
35403
- var import_node_fs43 = require("node:fs");
35437
+ var import_node_fs44 = require("node:fs");
35404
35438
  var import_node_os16 = require("node:os");
35405
- var import_node_path40 = require("node:path");
35439
+ var import_node_path41 = require("node:path");
35406
35440
  var GC_GH_TIMEOUT_MS3 = 2e4;
35407
35441
  async function collectStatus() {
35408
35442
  const repo = await resolveRepo();
@@ -35592,8 +35626,8 @@ async function collectOnboardStatus(opts = {}) {
35592
35626
  }
35593
35627
  const home = (0, import_node_os16.homedir)();
35594
35628
  const plugin = onboardPluginGate({
35595
- readKnown: () => readFileSyncSafe((0, import_node_path40.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs43.readFileSync),
35596
- 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)
35597
35631
  });
35598
35632
  return { track, board, registry: registry2, secrets, plugin, estateCli, doors: opts.doors ?? [], nextCommand };
35599
35633
  }
@@ -36692,19 +36726,19 @@ function registerOrgHealthQuery(program3, deps = defaultOrgHealthQueryDeps()) {
36692
36726
  }
36693
36727
 
36694
36728
  // src/plugin-release-catchup.ts
36695
- var import_node_fs44 = require("node:fs");
36696
- var import_node_path41 = require("node:path");
36729
+ var import_node_fs45 = require("node:fs");
36730
+ var import_node_path42 = require("node:path");
36697
36731
  var import_node_os17 = require("node:os");
36698
36732
  var RELEASE_CATCHUP_TTL_MS = 24 * 60 * 60 * 1e3;
36699
36733
  var RELEASE_CATCHUP_DISABLE_ENV = "MMI_NO_RELEASE_CATCHUP";
36700
36734
  function releaseCatchupStatePath(env = process.env) {
36701
36735
  if (env.MMI_RELEASE_CATCHUP_STATE) return env.MMI_RELEASE_CATCHUP_STATE;
36702
36736
  if (process.platform === "win32") {
36703
- const base2 = env.LOCALAPPDATA || (0, import_node_path41.join)((0, import_node_os17.homedir)(), "AppData", "Local");
36704
- 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");
36705
36739
  }
36706
- const base = env.XDG_STATE_HOME || (0, import_node_path41.join)((0, import_node_os17.homedir)(), ".local", "state");
36707
- 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");
36708
36742
  }
36709
36743
  function releaseCatchupDue(state, now, force = false) {
36710
36744
  if (force) return true;
@@ -36714,7 +36748,7 @@ function releaseCatchupDue(state, now, force = false) {
36714
36748
  function newestCachedPluginVersion(home) {
36715
36749
  let names;
36716
36750
  try {
36717
- names = (0, import_node_fs44.readdirSync)(pluginCacheRoot(home));
36751
+ names = (0, import_node_fs45.readdirSync)(pluginCacheRoot(home));
36718
36752
  } catch {
36719
36753
  return void 0;
36720
36754
  }
@@ -36722,15 +36756,15 @@ function newestCachedPluginVersion(home) {
36722
36756
  }
36723
36757
  function marketplaceClonePath(home) {
36724
36758
  try {
36725
- 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"));
36726
36760
  if (parsed.mutmutco?.installLocation) return parsed.mutmutco.installLocation;
36727
36761
  } catch {
36728
36762
  }
36729
- return (0, import_node_path41.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
36763
+ return (0, import_node_path42.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
36730
36764
  }
36731
36765
  function readCatalogVersion(home) {
36732
36766
  try {
36733
- 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"));
36734
36768
  return parsed.plugins?.find((p) => p.name === "mmi")?.version;
36735
36769
  } catch {
36736
36770
  return void 0;
@@ -36738,7 +36772,7 @@ function readCatalogVersion(home) {
36738
36772
  }
36739
36773
  function readMmiInstallRecord(home) {
36740
36774
  try {
36741
- 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"));
36742
36776
  const record = parsed.plugins?.["mmi@mutmutco"]?.[0];
36743
36777
  return record?.version ? { version: record.version, gitCommitSha: record.gitCommitSha } : void 0;
36744
36778
  } catch {
@@ -36767,7 +36801,7 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
36767
36801
  cliUpdated = true;
36768
36802
  }
36769
36803
  const cliUpdateDetail = cliUpdated ? `CLI ${runningCli} \u2192 ${latest}; the next mmi-cli invocation runs ${latest}` : `CLI ${runningCli} is current against released ${latest}`;
36770
- if (!(0, import_node_fs44.existsSync)(pluginCacheRoot(home))) {
36804
+ if (!(0, import_node_fs45.existsSync)(pluginCacheRoot(home))) {
36771
36805
  deps.writeState(statePath, { checkedAt: deps.now(), latest });
36772
36806
  return {
36773
36807
  ok: true,
@@ -36800,8 +36834,8 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
36800
36834
  return { ok: false, detail: `${cliUpdateDetail}; plugin install record could not be cleared (still ${prior.version})` };
36801
36835
  }
36802
36836
  const installed = await deps.runClaude(["plugin", "install", "mmi@mutmutco"], "claude plugin install mmi@mutmutco");
36803
- const payload = (0, import_node_path41.join)(pluginCacheRoot(home), latest, ".pi-plugin");
36804
- 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)) {
36805
36839
  const why = installed ? `install of ${latest} did not produce a verifiable .pi-plugin payload` : `install of ${latest} failed`;
36806
36840
  if (!prior) return { ok: false, detail: `${cliUpdateDetail}; ${why}; no prior record to restore` };
36807
36841
  const rollback = await restorePriorRecord(home, prior, deps);
@@ -38774,6 +38808,7 @@ async function runDoctorClean(opts, io, deps) {
38774
38808
  });
38775
38809
  return;
38776
38810
  }
38811
+ const provenance = state.cachedAt === void 0 ? [] : [cachedSweepNote(state.cachedAt)];
38777
38812
  if (state.driftLines.length === 0) {
38778
38813
  emitNow({
38779
38814
  ok: true,
@@ -38781,7 +38816,7 @@ async function runDoctorClean(opts, io, deps) {
38781
38816
  id: "schedules-drift",
38782
38817
  label: "schedules drift",
38783
38818
  detail: "no drift",
38784
- verbose: ["no drift lines"]
38819
+ verbose: ["no drift lines", ...provenance]
38785
38820
  });
38786
38821
  return;
38787
38822
  }
@@ -38792,7 +38827,7 @@ async function runDoctorClean(opts, io, deps) {
38792
38827
  label: "schedules drift",
38793
38828
  detail: `${state.driftLines.length} drift line(s)`,
38794
38829
  fix: "run `mmi-cli harbour org schedules` / `org schedules register`",
38795
- verbose: state.driftLines
38830
+ verbose: [...state.driftLines, ...provenance]
38796
38831
  });
38797
38832
  } catch (e) {
38798
38833
  const message = e instanceof Error ? e.message : String(e);
@@ -39009,17 +39044,17 @@ function parseOriginRepo(remoteUrl) {
39009
39044
  }
39010
39045
  function ghHostsConfigPath(env, platform2) {
39011
39046
  const sep3 = platform2 === "win32" ? "\\" : "/";
39012
- const join39 = (...parts) => parts.join(sep3);
39047
+ const join40 = (...parts) => parts.join(sep3);
39013
39048
  const explicit = env.GH_CONFIG_DIR?.trim();
39014
- if (explicit) return join39(explicit, "hosts.yml");
39049
+ if (explicit) return join40(explicit, "hosts.yml");
39015
39050
  if (platform2 === "win32") {
39016
39051
  const appData = (env.AppData ?? env.APPDATA)?.trim();
39017
- return appData ? join39(appData, "GitHub CLI", "hosts.yml") : void 0;
39052
+ return appData ? join40(appData, "GitHub CLI", "hosts.yml") : void 0;
39018
39053
  }
39019
39054
  const xdg = env.XDG_CONFIG_HOME?.trim();
39020
- if (xdg) return join39(xdg, "gh", "hosts.yml");
39055
+ if (xdg) return join40(xdg, "gh", "hosts.yml");
39021
39056
  const home = env.HOME?.trim();
39022
- return home ? join39(home, ".config", "gh", "hosts.yml") : void 0;
39057
+ return home ? join40(home, ".config", "gh", "hosts.yml") : void 0;
39023
39058
  }
39024
39059
  function parseGhHostsAccounts(yaml, host = "github.com") {
39025
39060
  let hostIndent = null;
@@ -39069,9 +39104,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
39069
39104
  }
39070
39105
 
39071
39106
  // src/doctor-io.ts
39072
- var import_node_fs45 = require("node:fs");
39107
+ var import_node_fs46 = require("node:fs");
39073
39108
  var import_node_os18 = require("node:os");
39074
- var import_node_path42 = require("node:path");
39109
+ var import_node_path43 = require("node:path");
39075
39110
  var import_node_child_process19 = require("node:child_process");
39076
39111
  var import_node_util8 = require("node:util");
39077
39112
  var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process19.execFile);
@@ -39079,7 +39114,7 @@ var MMI_PLUGIN_ID2 = "mmi@mutmutco";
39079
39114
  function installedClaudePluginVersion() {
39080
39115
  try {
39081
39116
  const file = JSON.parse(
39082
- (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")
39083
39118
  );
39084
39119
  const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
39085
39120
  if (versions.length === 0) return void 0;
@@ -39090,7 +39125,7 @@ function installedClaudePluginVersion() {
39090
39125
  }
39091
39126
  function manifestVersion(path2) {
39092
39127
  try {
39093
- const manifest = JSON.parse((0, import_node_fs45.readFileSync)(path2, "utf8"));
39128
+ const manifest = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
39094
39129
  return typeof manifest.version === "string" && manifest.version.trim() ? manifest.version.trim() : void 0;
39095
39130
  } catch {
39096
39131
  return void 0;
@@ -39100,22 +39135,22 @@ function installedSurfacePluginVersion(surface) {
39100
39135
  const token = surfaceToken(surface);
39101
39136
  if (token === "kilo") {
39102
39137
  try {
39103
- 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();
39104
39139
  return stamp || void 0;
39105
39140
  } catch {
39106
39141
  return void 0;
39107
39142
  }
39108
39143
  }
39109
39144
  if (token === "cursor") {
39110
- 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"));
39111
39146
  }
39112
39147
  if (token === "jervcode") {
39113
39148
  const entry = mmiPiWrapperEntry();
39114
39149
  if (!entry) return void 0;
39115
- 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"));
39116
39151
  }
39117
39152
  if (token === "kimi") {
39118
- 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"));
39119
39154
  }
39120
39155
  if (token === "claude") return installedClaudePluginVersion();
39121
39156
  if (token !== "codex") return void 0;
@@ -39153,13 +39188,13 @@ function worktreeRootSync() {
39153
39188
  }
39154
39189
  var gitignorePath = () => {
39155
39190
  const root = worktreeRootSync();
39156
- return root === null ? null : (0, import_node_path42.join)(root, ".gitignore");
39191
+ return root === null ? null : (0, import_node_path43.join)(root, ".gitignore");
39157
39192
  };
39158
39193
  function readGitignore() {
39159
39194
  const path2 = gitignorePath();
39160
39195
  if (path2 === null) return null;
39161
39196
  try {
39162
- return (0, import_node_fs45.readFileSync)(path2, "utf8");
39197
+ return (0, import_node_fs46.readFileSync)(path2, "utf8");
39163
39198
  } catch {
39164
39199
  return null;
39165
39200
  }
@@ -39168,7 +39203,7 @@ function writeGitignore(content) {
39168
39203
  const path2 = gitignorePath();
39169
39204
  if (path2 === null) return false;
39170
39205
  try {
39171
- (0, import_node_fs45.writeFileSync)(path2, content, "utf8");
39206
+ (0, import_node_fs46.writeFileSync)(path2, content, "utf8");
39172
39207
  return true;
39173
39208
  } catch {
39174
39209
  return false;
@@ -39187,7 +39222,7 @@ async function repoRoot() {
39187
39222
  }
39188
39223
  function hasRepoLocalWorktrees() {
39189
39224
  const root = worktreeRootSync();
39190
- 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"));
39191
39226
  }
39192
39227
 
39193
39228
  // src/index.ts
@@ -39206,8 +39241,8 @@ ${r.stderr ?? ""}`).catch(() => "");
39206
39241
  function ghMultiAccountCaveat(announcedLogin) {
39207
39242
  try {
39208
39243
  const hostsPath = ghHostsConfigPath(process.env, process.platform);
39209
- if (!hostsPath || !(0, import_node_fs46.existsSync)(hostsPath)) return void 0;
39210
- 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")));
39211
39246
  } catch {
39212
39247
  return void 0;
39213
39248
  }
@@ -39215,7 +39250,7 @@ function ghMultiAccountCaveat(announcedLogin) {
39215
39250
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
39216
39251
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
39217
39252
  function envHealLockPath(home) {
39218
- 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");
39219
39254
  }
39220
39255
  async function withEnvHealLock(what, run) {
39221
39256
  try {
@@ -39348,7 +39383,7 @@ function mmiDoctorDeps(opts = {}) {
39348
39383
  );
39349
39384
  const result = applyPluginCachePlan(
39350
39385
  plan,
39351
- (p) => (0, import_node_fs46.rmSync)(p, { recursive: true }),
39386
+ (p) => (0, import_node_fs47.rmSync)(p, { recursive: true }),
39352
39387
  stagingApplyFsGuard(configRoot)
39353
39388
  );
39354
39389
  return {
@@ -39402,8 +39437,8 @@ function mmiDoctorDeps(opts = {}) {
39402
39437
  const home = (0, import_node_os19.homedir)();
39403
39438
  const rows = marketplaceRows(
39404
39439
  MMI_MARKETPLACE_NAME,
39405
- readFileSyncSafe((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
39406
- 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),
39407
39442
  // #3974: this CLI heals these rows, so report mode names the doctor run rather than the hand
39408
39443
  // edit. #4792 narrows WHICH run: `applyOrgMarketplacePins` declines outright while Claude Code
39409
39444
  // is up, because the host owns this file and rewrites it from its own copy (#4083). Naming the
@@ -39415,7 +39450,7 @@ function mmiDoctorDeps(opts = {}) {
39415
39450
  hostBlocked ?? claudeCodeEnvMarkerPresent() ? "host-running" : "doctor"
39416
39451
  );
39417
39452
  const pending = readMarketplacePinPending(
39418
- (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"),
39419
39454
  MMI_MARKETPLACE_NAME
39420
39455
  );
39421
39456
  if (!pending) return rows;
@@ -39441,9 +39476,9 @@ function mmiDoctorDeps(opts = {}) {
39441
39476
  if (detectSurface(process.env) === "codex") return void 0;
39442
39477
  const home = (0, import_node_os19.homedir)();
39443
39478
  const names = [MMI_MARKETPLACE_NAME];
39444
- 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);
39445
39480
  if (result?.wrote) {
39446
- 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);
39447
39482
  }
39448
39483
  return result;
39449
39484
  } catch {
@@ -39459,7 +39494,7 @@ function mmiDoctorDeps(opts = {}) {
39459
39494
  // adopted the generated routing index (MMG-Unlive: `docs/Archive/**` only, no index, no gate.yml) would
39460
39495
  // get a permanent — demanding an artifact it never asked for.
39461
39496
  docsIndexState: (root) => {
39462
- 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;
39463
39498
  const real = createDocsIndexDeps(root);
39464
39499
  let docs2;
39465
39500
  const listDocs = () => docs2 ??= real.listDocs();
@@ -39468,7 +39503,7 @@ function mmiDoctorDeps(opts = {}) {
39468
39503
  },
39469
39504
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
39470
39505
  healDocsIndex: (root) => {
39471
- 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 };
39472
39507
  const real = createDocsIndexDeps(root);
39473
39508
  let docs2;
39474
39509
  const listDocs = () => docs2 ??= real.listDocs();
@@ -39496,6 +39531,7 @@ function mmiDoctorDeps(opts = {}) {
39496
39531
  // #4170: light board doctor with 15s ceiling. skipClaimLiveness keeps Phase 3 off.
39497
39532
  boardDoctorFix: async ({ fix } = {}) => {
39498
39533
  const BOARD_DOCTOR_TIMEOUT_MS = 15e3;
39534
+ let ceiling;
39499
39535
  try {
39500
39536
  const cfg = await loadConfigForRepo();
39501
39537
  const work = boardDoctor({
@@ -39506,7 +39542,7 @@ function mmiDoctorDeps(opts = {}) {
39506
39542
  const raced = await Promise.race([
39507
39543
  work.then((r) => ({ ...r, timedOut: false })),
39508
39544
  new Promise((resolve5) => {
39509
- 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);
39510
39546
  })
39511
39547
  ]);
39512
39548
  if (raced.timedOut) return { scanned: 0, findings: 0, fixed: 0, failed: 0, timedOut: true };
@@ -39518,11 +39554,20 @@ function mmiDoctorDeps(opts = {}) {
39518
39554
  };
39519
39555
  } catch (e) {
39520
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);
39521
39559
  }
39522
39560
  },
39523
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).
39524
39565
  schedulesDriftState: async () => {
39525
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;
39526
39571
  try {
39527
39572
  const raced = await Promise.race([
39528
39573
  fetchNotebook().then((nb) => ({
@@ -39531,12 +39576,15 @@ function mmiDoctorDeps(opts = {}) {
39531
39576
  timedOut: false
39532
39577
  })),
39533
39578
  new Promise((resolve5) => {
39534
- setTimeout(() => resolve5({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
39579
+ ceiling = setTimeout(() => resolve5({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
39535
39580
  })
39536
39581
  ]);
39582
+ if (!raced.timedOut && raced.incomplete.length === 0) writeSchedulesDriftCache(cachePath, raced.driftLines);
39537
39583
  return raced;
39538
39584
  } catch (e) {
39539
39585
  return { driftLines: [], incomplete: [], readFailed: true, error: e instanceof Error ? e.message : String(e) };
39586
+ } finally {
39587
+ clearTimeout(ceiling);
39540
39588
  }
39541
39589
  },
39542
39590
  // #4173: estate commands absent from the running Commander program (stale global CLI).
@@ -39818,19 +39866,19 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
39818
39866
  });
39819
39867
  var rules = program2.command("rules").description("org-managed .gitignore delivery");
39820
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) => {
39821
- const path2 = (0, import_node_path43.join)(process.cwd(), ".gitignore");
39822
- 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;
39823
39871
  const plan = planManagedGitignore(current);
39824
39872
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
39825
39873
  if (opts.json) {
39826
- 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");
39827
39875
  console.log(JSON.stringify(plan, null, 2));
39828
39876
  if (!opts.write && plan.changed) process.exitCode = 1;
39829
39877
  return;
39830
39878
  }
39831
39879
  if (opts.write) {
39832
39880
  if (plan.changed) {
39833
- (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
39881
+ (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
39834
39882
  console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
39835
39883
  } else {
39836
39884
  console.log("mmi-cli devops org rules gitignore: up to date");
@@ -39989,8 +40037,8 @@ gcCmd.option("--dry-run", "show what would be deleted (default)").option("--appl
39989
40037
  if (!Number.isFinite(limit) || limit < 1) return fail("worktree gc: --limit must be a positive integer");
39990
40038
  let root;
39991
40039
  if (o.root !== void 0) {
39992
- root = (0, import_node_path43.resolve)(o.root);
39993
- 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`);
39994
40042
  const gcRepoRoot = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
39995
40043
  if (isPathUnderDirectory2(gcRepoRoot, root)) {
39996
40044
  return fail(`worktree gc: --root ${root} contains this checkout \u2014 name a worktrees root, not the repo or an ancestor of it`);
@@ -40087,7 +40135,7 @@ async function currentWorktreeRemovalContext(command, force) {
40087
40135
  };
40088
40136
  }
40089
40137
  async function unprovenWorktreeReason(wtPath, repoRoot2) {
40090
- 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`;
40091
40139
  const porcelain = (await execFileP2("git", ["-C", repoRoot2, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
40092
40140
  const registered = parseWorktreePorcelainEntries(porcelain);
40093
40141
  if (!registered.length) {
@@ -40117,26 +40165,26 @@ function makeProvisionDeps(worktreeRoot, quiet, log) {
40117
40165
  function acquireWorktreeSetupLock(worktreeRoot) {
40118
40166
  const lockPath = repoRuntimeStatePath(worktreeRoot, "worktree-setup.lock");
40119
40167
  const take = () => {
40120
- const fd = (0, import_node_fs46.openSync)(lockPath, "wx");
40168
+ const fd = (0, import_node_fs47.openSync)(lockPath, "wx");
40121
40169
  try {
40122
- (0, import_node_fs46.writeSync)(fd, String(Date.now()));
40170
+ (0, import_node_fs47.writeSync)(fd, String(Date.now()));
40123
40171
  } finally {
40124
- (0, import_node_fs46.closeSync)(fd);
40172
+ (0, import_node_fs47.closeSync)(fd);
40125
40173
  }
40126
40174
  return () => {
40127
40175
  try {
40128
- (0, import_node_fs46.rmSync)(lockPath, { force: true });
40176
+ (0, import_node_fs47.rmSync)(lockPath, { force: true });
40129
40177
  } catch {
40130
40178
  }
40131
40179
  };
40132
40180
  };
40133
40181
  try {
40134
- (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 });
40135
40183
  return take();
40136
40184
  } catch {
40137
40185
  try {
40138
- if (Date.now() - (0, import_node_fs46.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
40139
- (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 });
40140
40188
  return take();
40141
40189
  }
40142
40190
  } catch {
@@ -41000,7 +41048,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
41000
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`);
41001
41049
  if (o.secretsFile) {
41002
41050
  try {
41003
- vars.push(`secrets=${(0, import_node_fs46.readFileSync)(o.secretsFile, "utf8")}`);
41051
+ vars.push(`secrets=${(0, import_node_fs47.readFileSync)(o.secretsFile, "utf8")}`);
41004
41052
  } catch (e) {
41005
41053
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
41006
41054
  }
@@ -41768,11 +41816,11 @@ pr.command("view <number>").description("read a PR as structured JSON (merged st
41768
41816
  }
41769
41817
  });
41770
41818
  async function listCiWorkflowPaths(cwd = process.cwd()) {
41771
- const wfDir = (0, import_node_path43.join)(cwd, ".github", "workflows");
41772
- if (!(0, import_node_fs46.existsSync)(wfDir)) return [];
41773
- 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) => {
41774
41822
  try {
41775
- 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"));
41776
41824
  } catch {
41777
41825
  return true;
41778
41826
  }
@@ -41824,16 +41872,16 @@ function ciAuditDeps() {
41824
41872
  // gate re-seed step is skipped gracefully rather than failing mid-run.
41825
41873
  readSeedFile: (path2) => {
41826
41874
  if (!root) return null;
41827
- const fullPath = (0, import_node_path43.join)(root, path2);
41828
- 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;
41829
41877
  }
41830
41878
  };
41831
41879
  }
41832
41880
  function hubRoot() {
41833
- const fromPkg = (0, import_node_path43.join)(__dirname, "..", "..");
41881
+ const fromPkg = (0, import_node_path44.join)(__dirname, "..", "..");
41834
41882
  const marker = "skills/bootstrap/seeds/manifest.json";
41835
- if ((0, import_node_fs46.existsSync)((0, import_node_path43.join)(fromPkg, marker))) return fromPkg;
41836
- 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();
41837
41885
  return null;
41838
41886
  }
41839
41887
  async function waitLoopCorePool(label) {
@@ -42141,7 +42189,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
42141
42189
  }
42142
42190
  if (!repoForPostCleanup) throw e;
42143
42191
  console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
42144
- 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;
42145
42193
  await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
42146
42194
  body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
42147
42195
  timeoutMs: GH_MUTATION_TIMEOUT_MS
@@ -42237,7 +42285,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
42237
42285
  localCleanup = await cleanupPrMergeLocalBranch(headRef, {
42238
42286
  beforeWorktrees,
42239
42287
  startingPath,
42240
- pathExists: (p) => (0, import_node_fs46.existsSync)(p),
42288
+ pathExists: (p) => (0, import_node_fs47.existsSync)(p),
42241
42289
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
42242
42290
  teardownWorktreeStage,
42243
42291
  deferredStore,
@@ -42815,12 +42863,12 @@ access.command("audit").description("audit collaborator roles + train-branch pus
42815
42863
  targets = resolution.targets;
42816
42864
  }
42817
42865
  const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
42818
- 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")) : {};
42819
42867
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
42820
42868
  const derivedContracts = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
42821
- 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: {} };
42822
42870
  const dataAccess = mergeDataAccessContracts(fileContracts, derivedContracts);
42823
- 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")) : {};
42824
42872
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
42825
42873
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
42826
42874
  if (!report.ok) process.exitCode = 1;
@@ -42852,16 +42900,16 @@ function directoryBytes(path2) {
42852
42900
  let total = 0;
42853
42901
  let entries;
42854
42902
  try {
42855
- entries = (0, import_node_fs46.readdirSync)(path2, { withFileTypes: true });
42903
+ entries = (0, import_node_fs47.readdirSync)(path2, { withFileTypes: true });
42856
42904
  } catch {
42857
42905
  return 0;
42858
42906
  }
42859
42907
  for (const entry of entries) {
42860
- const child2 = (0, import_node_path43.join)(path2, entry.name);
42908
+ const child2 = (0, import_node_path44.join)(path2, entry.name);
42861
42909
  if (entry.isDirectory()) total += directoryBytes(child2);
42862
42910
  else {
42863
42911
  try {
42864
- total += (0, import_node_fs46.statSync)(child2).size;
42912
+ total += (0, import_node_fs47.statSync)(child2).size;
42865
42913
  } catch {
42866
42914
  }
42867
42915
  }
@@ -42869,25 +42917,25 @@ function directoryBytes(path2) {
42869
42917
  return total;
42870
42918
  }
42871
42919
  function listDirEntries(dir) {
42872
- 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() }));
42873
42921
  }
42874
42922
  function readInstalledPluginRefs(configRoot) {
42875
42923
  const p = installedPluginsPathForConfig(configRoot);
42876
- if (!(0, import_node_fs46.existsSync)(p)) return [];
42924
+ if (!(0, import_node_fs47.existsSync)(p)) return [];
42877
42925
  try {
42878
- return installedPluginPaths((0, import_node_fs46.readFileSync)(p, "utf8"));
42926
+ return installedPluginPaths((0, import_node_fs47.readFileSync)(p, "utf8"));
42879
42927
  } catch {
42880
42928
  return null;
42881
42929
  }
42882
42930
  }
42883
42931
  function pluginCacheFsDeps(configRoot, dirBytes) {
42884
42932
  return {
42885
- exists: (p) => (0, import_node_fs46.existsSync)(p),
42886
- 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),
42887
42935
  dirBytes,
42888
- 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) => {
42889
42937
  try {
42890
- 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) };
42891
42939
  } catch {
42892
42940
  return { name: d.name, mtimeMs: Date.now() };
42893
42941
  }
@@ -42901,10 +42949,10 @@ function stagingApplyFsGuard(configRoot) {
42901
42949
  return {
42902
42950
  referencedPaths: () => readInstalledPluginRefs(configRoot),
42903
42951
  mtimeMs: (name) => {
42904
- const p = (0, import_node_path43.join)(stagingRoot, name);
42905
- 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;
42906
42954
  try {
42907
- 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);
42908
42956
  } catch {
42909
42957
  return null;
42910
42958
  }
@@ -42930,7 +42978,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
42930
42978
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
42931
42979
  );
42932
42980
  const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
42933
- 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;
42934
42982
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
42935
42983
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
42936
42984
  else console.log(renderPluginCachePlan(plan, result));
@@ -42938,7 +42986,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
42938
42986
  });
42939
42987
  function readReleaseCatchupState(path2) {
42940
42988
  try {
42941
- const parsed = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
42989
+ const parsed = JSON.parse((0, import_node_fs47.readFileSync)(path2, "utf8"));
42942
42990
  return typeof parsed?.checkedAt === "number" ? parsed : void 0;
42943
42991
  } catch {
42944
42992
  return void 0;
@@ -42946,8 +42994,8 @@ function readReleaseCatchupState(path2) {
42946
42994
  }
42947
42995
  function writeReleaseCatchupState(path2, state) {
42948
42996
  try {
42949
- (0, import_node_fs46.mkdirSync)((0, import_node_path43.dirname)(path2), { recursive: true });
42950
- (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)}
42951
42999
  `);
42952
43000
  } catch {
42953
43001
  }