@mutmutco/cli 3.117.1 → 3.119.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 +580 -526
  2. package/package.json +2 -2
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.119.0",
15824
+ tag: "v3.119.0",
15825
+ commit: "32fef9b214ee",
15826
+ npm: "@mutmutco/cli@3.119.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.119.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.119.0 and redeploy the Hub Lambda from tag v3.119.0 (32fef9b214ee); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15850
+ v3Target: "v3.119.0 (@mutmutco/cli@3.119.0, tag commit 32fef9b214ee \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
  }
@@ -24623,6 +24657,7 @@ function buildCommand(cmd, path2) {
24623
24657
  path: path2,
24624
24658
  ...aliases.length ? { aliases: [...aliases] } : {},
24625
24659
  house,
24660
+ canonical: canonicalPathFor(path2) ?? path2,
24626
24661
  arguments: cmd.registeredArguments.map(buildArgument),
24627
24662
  // A hand-parsed command registers no Commander options, so its declared set is merged in (#3682).
24628
24663
  options: [...cmd.options.map(buildOption), ...readDeclaredOptions(cmd)],
@@ -24864,8 +24899,8 @@ function consolidateCommandNamespaces(program3) {
24864
24899
  }
24865
24900
 
24866
24901
  // src/pi-plugin-registration.ts
24867
- var import_node_fs24 = require("node:fs");
24868
- var import_node_path22 = require("node:path");
24902
+ var import_node_fs25 = require("node:fs");
24903
+ var import_node_path23 = require("node:path");
24869
24904
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
24870
24905
 
24871
24906
  // src/plugin-cache-prune.ts
@@ -25123,48 +25158,48 @@ function newestExistingPiPlugin(home) {
25123
25158
  const cacheRoot = pluginCacheRoot(home);
25124
25159
  let names;
25125
25160
  try {
25126
- names = (0, import_node_fs24.readdirSync)(cacheRoot);
25161
+ names = (0, import_node_fs25.readdirSync)(cacheRoot);
25127
25162
  } catch {
25128
25163
  return void 0;
25129
25164
  }
25130
25165
  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;
25166
+ const candidate = (0, import_node_path23.join)(cacheRoot, version, ".pi-plugin");
25167
+ if ((0, import_node_fs25.existsSync)(candidate)) return candidate;
25133
25168
  }
25134
25169
  return void 0;
25135
25170
  }
25136
25171
  function expectedPiPluginPath(home, env, installedVersion) {
25137
25172
  const root = env.CLAUDE_PLUGIN_ROOT?.trim();
25138
- if (root && /[\\/]mutmutco[\\/]mmi[\\/]/.test(root)) return (0, import_node_path22.join)(root, ".pi-plugin");
25173
+ if (root && /[\\/]mutmutco[\\/]mmi[\\/]/.test(root)) return (0, import_node_path23.join)(root, ".pi-plugin");
25139
25174
  const version = installedVersion ?? runningPluginVersion(env);
25140
25175
  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;
25176
+ const pinned = (0, import_node_path23.join)(home, ".claude", "plugins", "cache", "mutmutco", "mmi", version, ".pi-plugin");
25177
+ if ((0, import_node_fs25.existsSync)(pinned)) return pinned;
25143
25178
  }
25144
25179
  return newestExistingPiPlugin(home);
25145
25180
  }
25146
25181
  function agentDirs(home, env = process.env) {
25147
25182
  const override = env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim();
25148
25183
  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 [];
25184
+ const jerv = (0, import_node_path23.join)(home, ".jerv", "agent");
25185
+ const pi = (0, import_node_path23.join)(home, ".pi", "agent");
25186
+ if (!(0, import_node_fs25.existsSync)(jerv) && !(0, import_node_fs25.existsSync)(pi)) return [];
25152
25187
  const dirs = [jerv];
25153
- if ((0, import_node_fs24.existsSync)(pi) && pi !== jerv) dirs.push(pi);
25188
+ if ((0, import_node_fs25.existsSync)(pi) && pi !== jerv) dirs.push(pi);
25154
25189
  return dirs;
25155
25190
  }
25156
25191
  function settingsPath(agentDir) {
25157
- return (0, import_node_path22.join)(agentDir, "settings.json");
25192
+ return (0, import_node_path23.join)(agentDir, "settings.json");
25158
25193
  }
25159
25194
  function readPiPluginState(home, env, installedVersion) {
25160
25195
  const dirs = agentDirs(home, env);
25161
25196
  if (dirs.length === 0) return void 0;
25162
25197
  const expectedPath = expectedPiPluginPath(home, env, installedVersion);
25163
25198
  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 };
25199
+ const file = dirs.map(settingsPath).find((p) => (0, import_node_fs25.existsSync)(p)) ?? settingsPath(dirs[0]);
25200
+ if (!(0, import_node_fs25.existsSync)(file)) return { expectedPath, settingsReadable: true };
25166
25201
  try {
25167
- const parsed = JSON.parse((0, import_node_fs24.readFileSync)(file, "utf8"));
25202
+ const parsed = JSON.parse((0, import_node_fs25.readFileSync)(file, "utf8"));
25168
25203
  const packages = Array.isArray(parsed.packages) ? parsed.packages : [];
25169
25204
  return { expectedPath, registeredPath: packages.find((p) => typeof p === "string" && isMmiPiPackage(p)), settingsReadable: true };
25170
25205
  } catch {
@@ -25188,20 +25223,20 @@ function acquirePiSettingsLock2(settingsFile) {
25188
25223
  return void 0;
25189
25224
  }
25190
25225
  function atomicWriteSettings(file, body) {
25191
- (0, import_node_fs24.mkdirSync)((0, import_node_path22.dirname)(file), { recursive: true });
25226
+ (0, import_node_fs25.mkdirSync)((0, import_node_path23.dirname)(file), { recursive: true });
25192
25227
  const tmp = `${file}.tmp-${process.pid}`;
25193
- (0, import_node_fs24.writeFileSync)(tmp, body, "utf8");
25228
+ (0, import_node_fs25.writeFileSync)(tmp, body, "utf8");
25194
25229
  try {
25195
- (0, import_node_fs24.renameSync)(tmp, file);
25230
+ (0, import_node_fs25.renameSync)(tmp, file);
25196
25231
  } catch (renameError) {
25197
- (0, import_node_fs24.rmSync)(tmp, { force: true });
25232
+ (0, import_node_fs25.rmSync)(tmp, { force: true });
25198
25233
  throw renameError;
25199
25234
  }
25200
25235
  }
25201
25236
  function healOneAgentDir(agentDir, expectedPath) {
25202
25237
  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) {
25238
+ const release = (0, import_node_fs25.existsSync)(file) ? acquirePiSettingsLock2(file) : void 0;
25239
+ if ((0, import_node_fs25.existsSync)(file) && !release) {
25205
25240
  return {
25206
25241
  ok: false,
25207
25242
  detail: `Pi's settings lock (${file}.lock) is held by another process; nothing written, retry on the next doctor run`,
@@ -25210,9 +25245,9 @@ function healOneAgentDir(agentDir, expectedPath) {
25210
25245
  }
25211
25246
  try {
25212
25247
  let parsed = {};
25213
- if ((0, import_node_fs24.existsSync)(file)) {
25248
+ if ((0, import_node_fs25.existsSync)(file)) {
25214
25249
  try {
25215
- const raw = JSON.parse((0, import_node_fs24.readFileSync)(file, "utf8"));
25250
+ const raw = JSON.parse((0, import_node_fs25.readFileSync)(file, "utf8"));
25216
25251
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
25217
25252
  return { ok: false, detail: "settings.json unreadable \u2014 nothing written (fail closed)" };
25218
25253
  }
@@ -25264,20 +25299,20 @@ function healPiPluginRegistration(home, env, installedVersion) {
25264
25299
  }
25265
25300
 
25266
25301
  // src/claude-binary-doctor.ts
25267
- var import_node_fs26 = require("node:fs");
25302
+ var import_node_fs27 = require("node:fs");
25268
25303
  var import_node_os11 = require("node:os");
25269
- var import_node_path24 = require("node:path");
25304
+ var import_node_path25 = require("node:path");
25270
25305
 
25271
25306
  // src/jerv-cli-spawn.ts
25272
- var import_node_fs25 = require("node:fs");
25307
+ var import_node_fs26 = require("node:fs");
25273
25308
  var import_node_os10 = require("node:os");
25274
- var import_node_path23 = require("node:path");
25309
+ var import_node_path24 = require("node:path");
25275
25310
  var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
25276
25311
  var POSIX_NAMES = ["jerv-cli"];
25277
- var JERV_CLI_ENTRY = (0, import_node_path23.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
25312
+ var JERV_CLI_ENTRY = (0, import_node_path24.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
25278
25313
  function pathEnvEntries(pathEnv, platform2 = process.platform) {
25279
25314
  if (platform2 !== "win32") {
25280
- return pathEnv.split(import_node_path23.delimiter).map((e) => e.trim()).filter(Boolean);
25315
+ return pathEnv.split(import_node_path24.delimiter).map((e) => e.trim()).filter(Boolean);
25281
25316
  }
25282
25317
  if (pathEnv.includes(";")) {
25283
25318
  return pathEnv.split(";").map((e) => e.trim()).filter(Boolean);
@@ -25310,10 +25345,10 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os10.hom
25310
25345
  push(normalizeSpawnPathEntry(entry, platform2));
25311
25346
  }
25312
25347
  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"));
25348
+ if (env.APPDATA) push((0, import_node_path24.join)(env.APPDATA, "npm"));
25349
+ if (env.LOCALAPPDATA) push((0, import_node_path24.join)(env.LOCALAPPDATA, "npm"));
25315
25350
  } else {
25316
- push((0, import_node_path23.join)(home, ".local", "bin"));
25351
+ push((0, import_node_path24.join)(home, ".local", "bin"));
25317
25352
  }
25318
25353
  return out;
25319
25354
  }
@@ -25321,23 +25356,23 @@ function jervCliCandidatePaths(env = process.env, home = (0, import_node_os10.ho
25321
25356
  const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
25322
25357
  const out = [];
25323
25358
  for (const dir of jervCliCandidateDirs(env, home, platform2)) {
25324
- for (const name of names) out.push((0, import_node_path23.join)(dir, name));
25359
+ for (const name of names) out.push((0, import_node_path24.join)(dir, name));
25325
25360
  }
25326
25361
  return out;
25327
25362
  }
25328
- function resolveJervCliPath(env = process.env, home = (0, import_node_os10.homedir)(), platform2 = process.platform, exists = import_node_fs25.existsSync) {
25363
+ function resolveJervCliPath(env = process.env, home = (0, import_node_os10.homedir)(), platform2 = process.platform, exists = import_node_fs26.existsSync) {
25329
25364
  for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
25330
25365
  if (exists(candidate)) return candidate;
25331
25366
  }
25332
25367
  return void 0;
25333
25368
  }
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);
25369
+ function resolveJervCliNodeEntry(shimPath, exists = import_node_fs26.existsSync) {
25370
+ const entry = (0, import_node_path24.join)((0, import_node_path24.dirname)(shimPath), JERV_CLI_ENTRY);
25336
25371
  return exists(entry) ? entry : void 0;
25337
25372
  }
25338
25373
  function jervCliExecFileArgs(args, opts = {}) {
25339
25374
  const platform2 = opts.platform ?? process.platform;
25340
- const exists = opts.exists ?? import_node_fs25.existsSync;
25375
+ const exists = opts.exists ?? import_node_fs26.existsSync;
25341
25376
  const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os10.homedir)(), platform2, exists);
25342
25377
  if (resolved) {
25343
25378
  const entry = resolveJervCliNodeEntry(resolved, exists);
@@ -25427,26 +25462,26 @@ function globalNodeModulesRoots(host) {
25427
25462
  out.push(dir);
25428
25463
  };
25429
25464
  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"));
25465
+ if (prefix) push(platform2 === "win32" ? (0, import_node_path25.join)(prefix, "node_modules") : (0, import_node_path25.join)(prefix, "lib", "node_modules"));
25431
25466
  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"));
25467
+ push((0, import_node_path25.join)(dir, "node_modules"));
25468
+ push((0, import_node_path25.join)((0, import_node_path25.dirname)(dir), "lib", "node_modules"));
25434
25469
  }
25435
25470
  return out;
25436
25471
  }
25437
25472
  function readHead(path2) {
25438
25473
  let fd;
25439
25474
  try {
25440
- fd = (0, import_node_fs26.openSync)(path2, "r");
25475
+ fd = (0, import_node_fs27.openSync)(path2, "r");
25441
25476
  const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
25442
- const read = (0, import_node_fs26.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
25477
+ const read = (0, import_node_fs27.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
25443
25478
  return buffer.subarray(0, read);
25444
25479
  } catch {
25445
25480
  return void 0;
25446
25481
  } finally {
25447
25482
  if (fd !== void 0) {
25448
25483
  try {
25449
- (0, import_node_fs26.closeSync)(fd);
25484
+ (0, import_node_fs27.closeSync)(fd);
25450
25485
  } catch {
25451
25486
  }
25452
25487
  }
@@ -25454,7 +25489,7 @@ function readHead(path2) {
25454
25489
  }
25455
25490
  function fileBytes(path2) {
25456
25491
  try {
25457
- return (0, import_node_fs26.statSync)(path2).size;
25492
+ return (0, import_node_fs27.statSync)(path2).size;
25458
25493
  } catch {
25459
25494
  return void 0;
25460
25495
  }
@@ -25468,17 +25503,17 @@ function readClaudeBinaryState(host = {}) {
25468
25503
  const arch = host.arch ?? process.arch;
25469
25504
  const magic = EXECUTABLE_MAGIC[platform2];
25470
25505
  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")));
25506
+ 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
25507
  if (!packageRoot) return void 0;
25473
25508
  const keys = platformPackageKeys(platform2, arch);
25474
25509
  const fallbackPackage = `${PACKAGE}-${keys[0]}`;
25475
25510
  let manifest;
25476
25511
  try {
25477
- manifest = JSON.parse((0, import_node_fs26.readFileSync)((0, import_node_path24.join)(packageRoot, "package.json"), "utf8"));
25512
+ manifest = JSON.parse((0, import_node_fs27.readFileSync)((0, import_node_path25.join)(packageRoot, "package.json"), "utf8"));
25478
25513
  } catch (e) {
25479
25514
  return {
25480
25515
  state: "unreadable",
25481
- binPath: (0, import_node_path24.join)(packageRoot, "package.json"),
25516
+ binPath: (0, import_node_path25.join)(packageRoot, "package.json"),
25482
25517
  expectedMagic: magic.name,
25483
25518
  platformPackage: fallbackPackage,
25484
25519
  error: `package.json could not be read \u2014 ${e.message}`
@@ -25495,17 +25530,17 @@ function readClaudeBinaryState(host = {}) {
25495
25530
  error: "package.json declares no `bin` entry \u2014 the executed file cannot be resolved"
25496
25531
  };
25497
25532
  }
25498
- const binPath = (0, import_node_path24.join)(packageRoot, binRelative);
25499
- const binName = (0, import_node_path24.basename)(binRelative);
25533
+ const binPath = (0, import_node_path25.join)(packageRoot, binRelative);
25534
+ const binName = (0, import_node_path25.basename)(binRelative);
25500
25535
  const optional = manifest.optionalDependencies;
25501
25536
  const publishes = (name) => typeof optional === "object" && optional !== null && Object.prototype.hasOwnProperty.call(optional, name);
25502
25537
  const published = keys.map((key) => `${PACKAGE}-${key}`).filter(publishes);
25503
25538
  if (published.length === 0) return void 0;
25504
25539
  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)
25540
+ (0, import_node_path25.join)(packageRoot, "node_modules", ...name.split("/"), binName),
25541
+ (0, import_node_path25.join)((0, import_node_path25.dirname)((0, import_node_path25.dirname)(packageRoot)), ...name.split("/"), binName)
25507
25542
  ];
25508
- const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs26.existsSync)(file)) })).find((c) => c.path);
25543
+ const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs27.existsSync)(file)) })).find((c) => c.path);
25509
25544
  const platformPackage = found?.name ?? published[0];
25510
25545
  let source;
25511
25546
  let sourceProblem;
@@ -25516,7 +25551,7 @@ function readClaudeBinaryState(host = {}) {
25516
25551
  } else {
25517
25552
  source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
25518
25553
  }
25519
- if (!(0, import_node_fs26.existsSync)(binPath)) {
25554
+ if (!(0, import_node_fs27.existsSync)(binPath)) {
25520
25555
  return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
25521
25556
  }
25522
25557
  const head = readHead(binPath);
@@ -25559,9 +25594,9 @@ function healClaudeBinary(host = {}, onStep) {
25559
25594
  const platform2 = host.platform ?? process.platform;
25560
25595
  const aside = `${probe.binPath}.stub-${Date.now()}`;
25561
25596
  let renamed = false;
25562
- if ((0, import_node_fs26.existsSync)(probe.binPath)) {
25597
+ if ((0, import_node_fs27.existsSync)(probe.binPath)) {
25563
25598
  try {
25564
- (0, import_node_fs26.renameSync)(probe.binPath, aside);
25599
+ (0, import_node_fs27.renameSync)(probe.binPath, aside);
25565
25600
  renamed = true;
25566
25601
  onStep?.(`renamed the stub aside: ${aside}`);
25567
25602
  } catch (e) {
@@ -25570,12 +25605,12 @@ function healClaudeBinary(host = {}, onStep) {
25570
25605
  }
25571
25606
  try {
25572
25607
  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);
25608
+ (0, import_node_fs27.copyFileSync)(probe.source.path, probe.binPath);
25609
+ if (platform2 !== "win32") (0, import_node_fs27.chmodSync)(probe.binPath, 493);
25575
25610
  } catch (e) {
25576
25611
  if (renamed) {
25577
25612
  try {
25578
- (0, import_node_fs26.renameSync)(aside, probe.binPath);
25613
+ (0, import_node_fs27.renameSync)(aside, probe.binPath);
25579
25614
  } catch {
25580
25615
  return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
25581
25616
  }
@@ -25589,7 +25624,7 @@ function healClaudeBinary(host = {}, onStep) {
25589
25624
  let kept = false;
25590
25625
  if (renamed) {
25591
25626
  try {
25592
- (0, import_node_fs26.rmSync)(aside);
25627
+ (0, import_node_fs27.rmSync)(aside);
25593
25628
  } catch {
25594
25629
  kept = true;
25595
25630
  }
@@ -26923,8 +26958,8 @@ async function announceRelease(deps, args) {
26923
26958
  // src/repo-index.ts
26924
26959
  var import_node_crypto4 = require("node:crypto");
26925
26960
  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");
26961
+ var import_node_fs28 = require("node:fs");
26962
+ var import_node_path26 = require("node:path");
26928
26963
  var REPO_INDEX_SCHEMA = 1;
26929
26964
  var HARD_DENY = [
26930
26965
  /(^|\/)\.env(\.|$)/i,
@@ -27049,11 +27084,11 @@ function loadReadmeHints(cwd, candidatePaths) {
27049
27084
  }
27050
27085
  for (const rel of readmes) {
27051
27086
  if (isHardDeniedPath(rel)) continue;
27052
- const abs = (0, import_node_path25.join)(cwd, ...rel.split("/"));
27053
- if (!(0, import_node_fs27.existsSync)(abs)) continue;
27087
+ const abs = (0, import_node_path26.join)(cwd, ...rel.split("/"));
27088
+ if (!(0, import_node_fs28.existsSync)(abs)) continue;
27054
27089
  let text;
27055
27090
  try {
27056
- text = (0, import_node_fs27.readFileSync)(abs, "utf8");
27091
+ text = (0, import_node_fs28.readFileSync)(abs, "utf8");
27057
27092
  } catch {
27058
27093
  continue;
27059
27094
  }
@@ -27066,7 +27101,7 @@ function loadReadmeHints(cwd, candidatePaths) {
27066
27101
  return hints;
27067
27102
  }
27068
27103
  function toPosix(p) {
27069
- return p.split(import_node_path25.sep).join("/");
27104
+ return p.split(import_node_path26.sep).join("/");
27070
27105
  }
27071
27106
  function listCandidatePaths(cwd, exec = import_node_child_process13.execFileSync) {
27072
27107
  try {
@@ -27088,11 +27123,11 @@ function rebuildRepoIndex(cwd, repoSlug2) {
27088
27123
  for (const rel of candidates) {
27089
27124
  if (ignored.has(rel)) continue;
27090
27125
  if (isHardDeniedPath(rel)) continue;
27091
- const abs = (0, import_node_path25.join)(cwd, ...rel.split("/"));
27092
- if (!(0, import_node_fs27.existsSync)(abs)) continue;
27126
+ const abs = (0, import_node_path26.join)(cwd, ...rel.split("/"));
27127
+ if (!(0, import_node_fs28.existsSync)(abs)) continue;
27093
27128
  let text;
27094
27129
  try {
27095
- text = (0, import_node_fs27.readFileSync)(abs, "utf8");
27130
+ text = (0, import_node_fs28.readFileSync)(abs, "utf8");
27096
27131
  } catch {
27097
27132
  continue;
27098
27133
  }
@@ -27117,16 +27152,16 @@ function rebuildRepoIndex(cwd, repoSlug2) {
27117
27152
  entries
27118
27153
  };
27119
27154
  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)}
27155
+ (0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(store), { recursive: true });
27156
+ (0, import_node_fs28.writeFileSync)(store, `${JSON.stringify(projection, null, 2)}
27122
27157
  `, "utf8");
27123
27158
  return projection;
27124
27159
  }
27125
27160
  function loadRepoIndex(cwd) {
27126
27161
  const store = repoIndexStorePath(cwd);
27127
- if (!(0, import_node_fs27.existsSync)(store)) return null;
27162
+ if (!(0, import_node_fs28.existsSync)(store)) return null;
27128
27163
  try {
27129
- const raw = JSON.parse((0, import_node_fs27.readFileSync)(store, "utf8"));
27164
+ const raw = JSON.parse((0, import_node_fs28.readFileSync)(store, "utf8"));
27130
27165
  if (raw?.schema !== REPO_INDEX_SCHEMA || !Array.isArray(raw.entries)) return null;
27131
27166
  return raw;
27132
27167
  } catch {
@@ -27198,7 +27233,7 @@ function inferRepoSlug(cwd, exec = import_node_child_process13.execFileSync) {
27198
27233
  if (m?.[1]) return m[1].toLowerCase();
27199
27234
  } catch {
27200
27235
  }
27201
- return ((0, import_node_path25.basename)(cwd) || "local").toLowerCase();
27236
+ return ((0, import_node_path26.basename)(cwd) || "local").toLowerCase();
27202
27237
  }
27203
27238
 
27204
27239
  // src/repo-index-cloud-client.ts
@@ -27338,9 +27373,9 @@ async function gcRepoIndexCloud(deps) {
27338
27373
  }
27339
27374
 
27340
27375
  // src/repo-index-sync.ts
27341
- var import_node_fs28 = require("node:fs");
27376
+ var import_node_fs29 = require("node:fs");
27342
27377
  var import_node_os12 = require("node:os");
27343
- var import_node_path26 = require("node:path");
27378
+ var import_node_path27 = require("node:path");
27344
27379
  var import_node_child_process14 = require("node:child_process");
27345
27380
  var MAX_EMBED_BACKFILL_ROUNDS = 40;
27346
27381
  function normalizeRepo(raw) {
@@ -27384,7 +27419,7 @@ async function syncEstateRepoIndex(opts) {
27384
27419
  const failed = [];
27385
27420
  const skipped = [];
27386
27421
  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-"));
27422
+ const dir = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os12.tmpdir)(), "mmi-repo-index-"));
27388
27423
  try {
27389
27424
  shallowClone(repo, dir, opts.githubToken);
27390
27425
  const built = rebuildRepoIndex(dir, repo);
@@ -27434,7 +27469,7 @@ async function syncEstateRepoIndex(opts) {
27434
27469
  failed.push({ repo, error: e.message });
27435
27470
  } finally {
27436
27471
  try {
27437
- (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
27472
+ (0, import_node_fs29.rmSync)(dir, { recursive: true, force: true });
27438
27473
  } catch {
27439
27474
  }
27440
27475
  }
@@ -27443,7 +27478,7 @@ async function syncEstateRepoIndex(opts) {
27443
27478
  }
27444
27479
 
27445
27480
  // src/repo-index-health.ts
27446
- var import_node_fs29 = require("node:fs");
27481
+ var import_node_fs30 = require("node:fs");
27447
27482
 
27448
27483
  // testdata/repo-index-golden-queries.json
27449
27484
  var repo_index_golden_queries_default = {
@@ -27485,7 +27520,7 @@ function assertGoldenSuite(raw, source) {
27485
27520
  function loadGoldenSuite(path2) {
27486
27521
  let text;
27487
27522
  try {
27488
- text = (0, import_node_fs29.readFileSync)(path2, "utf8");
27523
+ text = (0, import_node_fs30.readFileSync)(path2, "utf8");
27489
27524
  } catch (e) {
27490
27525
  throw new Error(`golden suite unreadable at ${path2}: ${e.message}`);
27491
27526
  }
@@ -27631,8 +27666,8 @@ async function runRepoIndexHealth(opts) {
27631
27666
 
27632
27667
  // src/spawn-policy-core.ts
27633
27668
  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");
27669
+ var import_node_fs31 = require("node:fs");
27670
+ var import_node_path28 = require("node:path");
27636
27671
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
27637
27672
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
27638
27673
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -27718,7 +27753,7 @@ function runSpawnPolicy(root) {
27718
27753
  for (const file of files) {
27719
27754
  let raw;
27720
27755
  try {
27721
- raw = (0, import_node_fs30.readFileSync)((0, import_node_path27.join)(root, file), "utf8");
27756
+ raw = (0, import_node_fs31.readFileSync)((0, import_node_path28.join)(root, file), "utf8");
27722
27757
  } catch {
27723
27758
  continue;
27724
27759
  }
@@ -27736,8 +27771,8 @@ function runSpawnPolicy(root) {
27736
27771
 
27737
27772
  // src/test-policy-core.ts
27738
27773
  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");
27774
+ var import_node_fs32 = require("node:fs");
27775
+ var import_node_path29 = require("node:path");
27741
27776
  var POLICY_FILE = "test-policy.json";
27742
27777
  var TEST_RE = /\.(?:test|spec)\.[cm]?[jt]sx?$/;
27743
27778
  var PY_TEST_RE = /(?:^|\/)test_[^/]*\.py$|_test\.py$/;
@@ -27790,7 +27825,7 @@ function isTestPath(path2) {
27790
27825
  return TEST_RE.test(path2) || PY_TEST_RE.test(path2);
27791
27826
  }
27792
27827
  function loadPolicy(root, readFile9 = readFileOrNull2) {
27793
- const raw = readFile9((0, import_node_path28.join)(root, POLICY_FILE));
27828
+ const raw = readFile9((0, import_node_path29.join)(root, POLICY_FILE));
27794
27829
  if (raw == null) return { mandatory: [], declared: false };
27795
27830
  try {
27796
27831
  return { ...JSON.parse(raw), declared: true };
@@ -27800,7 +27835,7 @@ function loadPolicy(root, readFile9 = readFileOrNull2) {
27800
27835
  }
27801
27836
  function readFileOrNull2(path2) {
27802
27837
  try {
27803
- return (0, import_node_fs31.readFileSync)(path2, "utf8");
27838
+ return (0, import_node_fs32.readFileSync)(path2, "utf8");
27804
27839
  } catch {
27805
27840
  return null;
27806
27841
  }
@@ -27827,12 +27862,12 @@ function classify(changed, policy, present = () => false) {
27827
27862
  const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
27828
27863
  return { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected };
27829
27864
  }
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)));
27865
+ function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs32.existsSync)(path2)) {
27866
+ return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path29.join)(root, p)));
27832
27867
  }
27833
- function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs31.existsSync)(path2)) {
27868
+ function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs32.existsSync)(path2)) {
27834
27869
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
27835
- return [...new Set(declared)].filter((p) => !exists((0, import_node_path28.join)(root, p)));
27870
+ return [...new Set(declared)].filter((p) => !exists((0, import_node_path29.join)(root, p)));
27836
27871
  }
27837
27872
  function evaluate(changed, policy, present = () => false) {
27838
27873
  const { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected } = classify(changed, policy, present);
@@ -28014,13 +28049,13 @@ function changedFilesSince(base, cwd) {
28014
28049
  }
28015
28050
  function runTestPolicy(root, deps = {}) {
28016
28051
  const policy = deps.policy ?? loadPolicy(root);
28017
- const exists = deps.exists ?? ((path2) => (0, import_node_fs31.existsSync)(path2));
28052
+ const exists = deps.exists ?? ((path2) => (0, import_node_fs32.existsSync)(path2));
28018
28053
  const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
28019
28054
  const base = deps.changed ? "(injected)" : resolveBase(root, deps.base);
28020
28055
  const refusal = deps.changed ? null : untrustworthyRange(root, base);
28021
28056
  const changed = deps.changed ?? (refusal ? [] : changedFilesSince(base, root));
28022
28057
  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));
28058
+ const present = (path2) => exists((0, import_node_path29.join)(root, path2));
28024
28059
  const removedByThisDiff = removedPaths(changed);
28025
28060
  const staleFindings = [];
28026
28061
  const unresolved = unresolvedProtectedEntries(policy, root, exists).filter((p) => !removedByThisDiff.has(p));
@@ -28058,8 +28093,8 @@ function runTestPolicy(root, deps = {}) {
28058
28093
  }
28059
28094
 
28060
28095
  // src/project-info-sync.ts
28061
- var import_node_fs32 = require("node:fs");
28062
- var import_node_path29 = require("node:path");
28096
+ var import_node_fs33 = require("node:fs");
28097
+ var import_node_path30 = require("node:path");
28063
28098
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
28064
28099
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
28065
28100
  projectV2 { id }
@@ -28104,14 +28139,14 @@ function sharedName(entries, fallback) {
28104
28139
  }
28105
28140
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
28106
28141
  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`);
28142
+ const readmePath = (0, import_node_path30.join)(repoRoot2, "README.md");
28143
+ if (!(0, import_node_fs33.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
28109
28144
  const entries = entriesFor(project2, projects);
28110
28145
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
28111
28146
  const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
28112
28147
  if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
28113
28148
  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)}.`;
28149
+ 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
28150
  const lines = [
28116
28151
  `# ${projectName}`,
28117
28152
  "",
@@ -28130,8 +28165,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
28130
28165
  const targetBase = `https://github.com/${targetRepo2}`;
28131
28166
  const targetBranch = branchFor(targetRepo2, projects);
28132
28167
  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)` : ""
28168
+ (0, import_node_fs33.existsSync)((0, import_node_path30.join)(repoRoot2, "docs", "org-readme.md")) ? `- [Org identity](${targetBase}/blob/${targetBranch}/docs/org-readme.md)` : "",
28169
+ (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
28170
  ].filter(Boolean);
28136
28171
  if (orgDocs.length) lines.push("", "## Organisation docs", "", ...orgDocs);
28137
28172
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines.join("\n")}
@@ -28916,8 +28951,8 @@ function writeError(res) {
28916
28951
  }
28917
28952
 
28918
28953
  // src/secrets-commands.ts
28919
- var import_node_fs33 = require("node:fs");
28920
- var import_node_path30 = require("node:path");
28954
+ var import_node_fs34 = require("node:fs");
28955
+ var import_node_path31 = require("node:path");
28921
28956
  var import_node_os13 = require("node:os");
28922
28957
 
28923
28958
  // src/secrets-diff.ts
@@ -29020,18 +29055,18 @@ function collectMap(value, previous = []) {
29020
29055
  return [...previous, value];
29021
29056
  }
29022
29057
  async function decryptRailsCredentials(input) {
29023
- const appDir = (0, import_node_path30.resolve)(input.appDir ?? process.cwd());
29058
+ const appDir = (0, import_node_path31.resolve)(input.appDir ?? process.cwd());
29024
29059
  const credentialsFile = input.credentialsFile ?? DEFAULT_RAILS_CREDENTIALS_FILE;
29025
29060
  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);
29061
+ const credentialsPath = (0, import_node_path31.resolve)(appDir, credentialsFile);
29062
+ const masterKeyPath = (0, import_node_path31.resolve)(appDir, masterKeyFile);
29028
29063
  const env = {
29029
29064
  ...process.env,
29030
29065
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
29031
29066
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
29032
29067
  };
29033
- if ((0, import_node_fs33.existsSync)(masterKeyPath)) {
29034
- env.RAILS_MASTER_KEY = (0, import_node_fs33.readFileSync)(masterKeyPath, "utf8").trim();
29068
+ if ((0, import_node_fs34.existsSync)(masterKeyPath)) {
29069
+ env.RAILS_MASTER_KEY = (0, import_node_fs34.readFileSync)(masterKeyPath, "utf8").trim();
29035
29070
  }
29036
29071
  const script = [
29037
29072
  'require "json"',
@@ -29041,9 +29076,9 @@ async function decryptRailsCredentials(input) {
29041
29076
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
29042
29077
  "puts JSON.generate(config.config)"
29043
29078
  ].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");
29079
+ const scriptDir = (0, import_node_fs34.mkdtempSync)((0, import_node_path31.join)((0, import_node_os13.tmpdir)(), "mmi-rails-decrypt-"));
29080
+ const scriptPath = (0, import_node_path31.join)(scriptDir, "decrypt.rb");
29081
+ (0, import_node_fs34.writeFileSync)(scriptPath, script, "utf8");
29047
29082
  try {
29048
29083
  const args = ["exec", "ruby", scriptPath];
29049
29084
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -29055,7 +29090,7 @@ async function decryptRailsCredentials(input) {
29055
29090
  });
29056
29091
  return JSON.parse(stdout);
29057
29092
  } finally {
29058
- (0, import_node_fs33.rmSync)(scriptDir, { recursive: true, force: true });
29093
+ (0, import_node_fs34.rmSync)(scriptDir, { recursive: true, force: true });
29059
29094
  }
29060
29095
  }
29061
29096
  async function readSecretStdin() {
@@ -29145,7 +29180,7 @@ function registerSecretsCommands(program3) {
29145
29180
  let body;
29146
29181
  if (o.file) {
29147
29182
  try {
29148
- body = (0, import_node_fs33.readFileSync)((0, import_node_path30.resolve)(o.file), "utf8");
29183
+ body = (0, import_node_fs34.readFileSync)((0, import_node_path31.resolve)(o.file), "utf8");
29149
29184
  } catch (e) {
29150
29185
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
29151
29186
  }
@@ -29250,7 +29285,7 @@ function registerSecretsCommands(program3) {
29250
29285
  {
29251
29286
  ...d,
29252
29287
  decryptRailsCredentials,
29253
- removeFile: (path2) => (0, import_node_fs33.unlinkSync)((0, import_node_path30.resolve)(o.appDir ?? process.cwd(), path2))
29288
+ removeFile: (path2) => (0, import_node_fs34.unlinkSync)((0, import_node_path31.resolve)(o.appDir ?? process.cwd(), path2))
29254
29289
  },
29255
29290
  {
29256
29291
  repo: o.repo,
@@ -29455,7 +29490,7 @@ function emitCliCallTelemetry(command) {
29455
29490
  }
29456
29491
 
29457
29492
  // src/box-commands.ts
29458
- var import_node_fs34 = require("node:fs");
29493
+ var import_node_fs35 = require("node:fs");
29459
29494
 
29460
29495
  // src/box.ts
29461
29496
  var BOX_KEYS = {
@@ -29658,7 +29693,7 @@ function registerBoxCommands(program3) {
29658
29693
  }
29659
29694
  if (o.json) console.log(JSON.stringify({ box: found, incomplete }, null, 2));
29660
29695
  else if (o.ssh && o.script) {
29661
- (0, import_node_fs34.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
29696
+ (0, import_node_fs35.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
29662
29697
  console.log(`wrote ${o.script} \u2014 run: bash "${o.script}"`);
29663
29698
  } else if (o.ssh) console.log(`${formatSshRecipe(found)}
29664
29699
  ${SSH_RECIPE_AGENT_NOTE}`);
@@ -29977,7 +30012,7 @@ function registerSchedulesCommands(program3) {
29977
30012
 
29978
30013
  // src/schedules-lift-command.ts
29979
30014
  var import_promises6 = require("node:fs/promises");
29980
- var import_node_path31 = require("node:path");
30015
+ var import_node_path32 = require("node:path");
29981
30016
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
29982
30017
  var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
29983
30018
  var SchedulesLiftUsageError = class extends Error {
@@ -30004,7 +30039,7 @@ async function readWorkflowFiles(dir) {
30004
30039
  const files = [];
30005
30040
  for (const name of names.sort()) {
30006
30041
  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") });
30042
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises6.readFile)((0, import_node_path32.join)(dir, name), "utf8") });
30008
30043
  }
30009
30044
  return files;
30010
30045
  }
@@ -30152,9 +30187,9 @@ function registerEdgeCommands(program3) {
30152
30187
  }
30153
30188
 
30154
30189
  // src/bootstrap-commands.ts
30155
- var import_node_fs35 = require("node:fs");
30190
+ var import_node_fs36 = require("node:fs");
30156
30191
  var import_node_os14 = require("node:os");
30157
- var import_node_path32 = require("node:path");
30192
+ var import_node_path33 = require("node:path");
30158
30193
 
30159
30194
  // src/bootstrap-drift.ts
30160
30195
  var import_node_crypto6 = require("node:crypto");
@@ -31034,13 +31069,13 @@ function registerBootstrapCommands(program3) {
31034
31069
  client: defaultGitHubClient(),
31035
31070
  projectMeta: meta,
31036
31071
  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,
31072
+ readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs36.existsSync)(path2) ? (0, import_node_fs36.readFileSync)(path2, "utf8") : null,
31038
31073
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
31039
31074
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
31040
31075
  // #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
31041
31076
  // permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
31042
31077
  // 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,
31078
+ sanctionedAdmins: (0, import_node_fs36.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs36.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
31044
31079
  requiredGcpApis: (() => {
31045
31080
  const v = meta?.requiredGcpApis;
31046
31081
  if (Array.isArray(v)) return v;
@@ -31093,14 +31128,14 @@ function registerBootstrapCommands(program3) {
31093
31128
  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
31129
  const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
31095
31130
  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`);
31131
+ 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
31132
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31098
31133
  if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
31099
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31134
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31100
31135
  const hubContents = /* @__PURE__ */ new Map();
31101
31136
  for (const s of manifest.seeds) {
31102
31137
  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);
31138
+ hubContents.set(s.target, (0, import_node_fs36.existsSync)(s.target) ? (0, import_node_fs36.readFileSync)(s.target, "utf8") : null);
31104
31139
  }
31105
31140
  let targets;
31106
31141
  let classOf = (_repo) => "deployable";
@@ -31179,10 +31214,10 @@ function registerBootstrapCommands(program3) {
31179
31214
  return fail(`bootstrap apply: ${e.message}`);
31180
31215
  }
31181
31216
  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`);
31217
+ 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
31218
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31184
31219
  if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
31185
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31220
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31186
31221
  const baseBranch = o.class === "content" ? "main" : "development";
31187
31222
  const slug = parsedRepo.slug;
31188
31223
  const onlyTarget = o.only.trim();
@@ -31193,16 +31228,16 @@ function registerBootstrapCommands(program3) {
31193
31228
  ${known}`);
31194
31229
  }
31195
31230
  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;
31231
+ const readFile9 = (p) => (0, import_node_fs36.existsSync)(p) ? (0, import_node_fs36.readFileSync)(p, "utf8") : null;
31197
31232
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
31198
31233
  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");
31234
+ 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`);
31235
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
31201
31236
  try {
31202
31237
  await gh(contentPutInputArgs(repo, target, tmp));
31203
31238
  } finally {
31204
31239
  try {
31205
- (0, import_node_fs35.unlinkSync)(tmp);
31240
+ (0, import_node_fs36.unlinkSync)(tmp);
31206
31241
  } catch {
31207
31242
  }
31208
31243
  }
@@ -31467,10 +31502,10 @@ LIVE apply to ${repo}:
31467
31502
  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
31503
  const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
31469
31504
  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`);
31505
+ 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
31506
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31472
31507
  if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
31473
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31508
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31474
31509
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
31475
31510
  if (!o.target) {
31476
31511
  return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
@@ -31479,8 +31514,8 @@ LIVE apply to ${repo}:
31479
31514
  const seed = propagatable.find((s) => s.target === o.target);
31480
31515
  if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no ownership:org + source:self seed in ${manifestPath}. Propagatable targets:
31481
31516
  ${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");
31517
+ 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`);
31518
+ const hubContent = (0, import_node_fs36.readFileSync)(seed.target, "utf8");
31484
31519
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
31485
31520
  const cfg = await loadConfig();
31486
31521
  const projects = await fetchProjectsList(registryClientDeps(cfg));
@@ -31489,9 +31524,9 @@ LIVE apply to ${repo}:
31489
31524
  }
31490
31525
  const rosterRepos2 = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
31491
31526
  let independentCount = rosterRepos2.length;
31492
- if ((0, import_node_fs35.existsSync)("projects.json")) {
31527
+ if ((0, import_node_fs36.existsSync)("projects.json")) {
31493
31528
  try {
31494
- const local = JSON.parse((0, import_node_fs35.readFileSync)("projects.json", "utf8"));
31529
+ const local = JSON.parse((0, import_node_fs36.readFileSync)("projects.json", "utf8"));
31495
31530
  const localRepos = /* @__PURE__ */ new Set();
31496
31531
  for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
31497
31532
  const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
@@ -31607,13 +31642,13 @@ LIVE apply to ${repo}:
31607
31642
  } catch {
31608
31643
  existingSha = void 0;
31609
31644
  }
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");
31645
+ 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`);
31646
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, hubContent, branch, existingSha)), "utf8");
31612
31647
  try {
31613
31648
  await gh(contentPutInputArgs(rec.repo, seed.target, tmp));
31614
31649
  } finally {
31615
31650
  try {
31616
- (0, import_node_fs35.unlinkSync)(tmp);
31651
+ (0, import_node_fs36.unlinkSync)(tmp);
31617
31652
  } catch {
31618
31653
  }
31619
31654
  }
@@ -31671,10 +31706,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31671
31706
  return fail(`bootstrap rollback: ${e.message}`);
31672
31707
  }
31673
31708
  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)`);
31709
+ 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
31710
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
31676
31711
  if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
31677
- const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
31712
+ const manifest = loadBootstrapSeeds((0, import_node_fs36.readFileSync)(manifestPath, "utf8"));
31678
31713
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
31679
31714
  if (!o.target) {
31680
31715
  return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
@@ -31691,10 +31726,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31691
31726
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
31692
31727
  let candidates;
31693
31728
  if (o.record) {
31694
- if (!(0, import_node_fs35.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
31729
+ if (!(0, import_node_fs36.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
31695
31730
  let parsed;
31696
31731
  try {
31697
- parsed = JSON.parse((0, import_node_fs35.readFileSync)(o.record, "utf8"));
31732
+ parsed = JSON.parse((0, import_node_fs36.readFileSync)(o.record, "utf8"));
31698
31733
  } catch (e) {
31699
31734
  return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
31700
31735
  }
@@ -31763,13 +31798,13 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31763
31798
  } catch {
31764
31799
  existingSha = void 0;
31765
31800
  }
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");
31801
+ 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`);
31802
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
31768
31803
  try {
31769
31804
  await gh(contentPutInputArgs(repo, seed.target, tmp));
31770
31805
  } finally {
31771
31806
  try {
31772
- (0, import_node_fs35.unlinkSync)(tmp);
31807
+ (0, import_node_fs36.unlinkSync)(tmp);
31773
31808
  } catch {
31774
31809
  }
31775
31810
  }
@@ -31791,12 +31826,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
31791
31826
  }
31792
31827
 
31793
31828
  // src/stage-commands.ts
31794
- var import_node_fs37 = require("node:fs");
31795
- var import_node_path34 = require("node:path");
31829
+ var import_node_fs38 = require("node:fs");
31830
+ var import_node_path35 = require("node:path");
31796
31831
 
31797
31832
  // src/port-registry.ts
31798
- var import_node_fs36 = require("node:fs");
31799
- var import_node_path33 = require("node:path");
31833
+ var import_node_fs37 = require("node:fs");
31834
+ var import_node_path34 = require("node:path");
31800
31835
 
31801
31836
  // ../infra/port-geometry.mjs
31802
31837
  var PORT_BLOCK = 100;
@@ -31810,8 +31845,8 @@ function nextPortBlock(registry2) {
31810
31845
  return [base, base + PORT_SPAN];
31811
31846
  }
31812
31847
  function loadPortRegistry(path2) {
31813
- if (!(0, import_node_fs36.existsSync)(path2)) return {};
31814
- const raw = JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8"));
31848
+ if (!(0, import_node_fs37.existsSync)(path2)) return {};
31849
+ const raw = JSON.parse((0, import_node_fs37.readFileSync)(path2, "utf8"));
31815
31850
  const out = {};
31816
31851
  for (const [key, value] of Object.entries(raw)) {
31817
31852
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -31825,9 +31860,9 @@ function ensurePortRange(repo, path2) {
31825
31860
  const existing = registry2[repo];
31826
31861
  if (existing) return existing;
31827
31862
  const range = nextPortBlock(registry2);
31828
- const raw = (0, import_node_fs36.existsSync)(path2) ? JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8")) : {};
31863
+ const raw = (0, import_node_fs37.existsSync)(path2) ? JSON.parse((0, import_node_fs37.readFileSync)(path2, "utf8")) : {};
31829
31864
  raw[repo] = range;
31830
- (0, import_node_fs36.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
31865
+ (0, import_node_fs37.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
31831
31866
  return range;
31832
31867
  }
31833
31868
  function portCursorSeed(registry2) {
@@ -31849,22 +31884,22 @@ function existingPortRange(repo, registry2) {
31849
31884
  return registry2[repo] ?? null;
31850
31885
  }
31851
31886
  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;
31887
+ const registryPath = (0, import_node_path34.join)(root, "infra", "port-ranges.json");
31888
+ const ddbScriptPath = (0, import_node_path34.join)(root, "infra", "port-ddb.mjs");
31889
+ if (!(0, import_node_fs37.existsSync)(registryPath) || !(0, import_node_fs37.existsSync)(ddbScriptPath)) return null;
31855
31890
  return { root, source, registryPath, ddbScriptPath };
31856
31891
  }
31857
31892
  function resolvePortRangeInfra(cwd, packageDir) {
31858
31893
  const direct = portRangeInfraAt(cwd, "cwd");
31859
31894
  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");
31895
+ for (let dir = cwd; ; dir = (0, import_node_path34.dirname)(dir)) {
31896
+ const sibling = portRangeInfraAt((0, import_node_path34.join)(dir, "MMI-Hub"), "sibling-hub");
31862
31897
  if (sibling) return sibling;
31863
- const parent = (0, import_node_path33.dirname)(dir);
31898
+ const parent = (0, import_node_path34.dirname)(dir);
31864
31899
  if (parent === dir) break;
31865
31900
  }
31866
31901
  if (packageDir) {
31867
- const pkgRoot = (0, import_node_path33.join)(packageDir, "..", "..");
31902
+ const pkgRoot = (0, import_node_path34.join)(packageDir, "..", "..");
31868
31903
  const pkgFrom = portRangeInfraAt(pkgRoot, "pkg-root");
31869
31904
  if (pkgFrom) return pkgFrom;
31870
31905
  }
@@ -32058,8 +32093,8 @@ function registerStageCommands(program3) {
32058
32093
  const portRange = portRangeMeta && typeof portRangeMeta.start === "number" && typeof portRangeMeta.end === "number" ? [portRangeMeta.start, portRangeMeta.end] : void 0;
32059
32094
  return decideStage({
32060
32095
  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"))
32096
+ hasCompose: (0, import_node_fs38.existsSync)((0, import_node_path35.join)(process.cwd(), "docker-compose.yml")),
32097
+ hasEnvExample: (0, import_node_fs38.existsSync)((0, import_node_path35.join)(process.cwd(), ".env.example"))
32063
32098
  });
32064
32099
  }
32065
32100
  async function fetchStageVaultEnvMerge() {
@@ -32550,9 +32585,9 @@ function registerBoardCommands(program3) {
32550
32585
  }
32551
32586
 
32552
32587
  // src/merge-cleanup.ts
32553
- var import_node_fs38 = require("node:fs");
32588
+ var import_node_fs39 = require("node:fs");
32554
32589
  var import_promises8 = require("node:fs/promises");
32555
- var import_node_path36 = require("node:path");
32590
+ var import_node_path37 = require("node:path");
32556
32591
  var import_node_os15 = require("node:os");
32557
32592
  var import_node_child_process18 = require("node:child_process");
32558
32593
 
@@ -32640,7 +32675,7 @@ function boardAdvanceFailureMessage(result) {
32640
32675
 
32641
32676
  // src/deferred-registry-store.ts
32642
32677
  var import_promises7 = require("node:fs/promises");
32643
- var import_node_path35 = require("node:path");
32678
+ var import_node_path36 = require("node:path");
32644
32679
  var sleep2 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
32645
32680
  async function atomicWrite(target, contents) {
32646
32681
  const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
@@ -32691,12 +32726,12 @@ function makeDeferredWorktreeStore(registryPath, lockOpts = {}) {
32691
32726
  },
32692
32727
  // Standalone atomic write — THROWS on failure (no best-effort swallow, #2846).
32693
32728
  write: async (entries) => {
32694
- await (0, import_promises7.mkdir)((0, import_node_path35.dirname)(registryPath), { recursive: true });
32729
+ await (0, import_promises7.mkdir)((0, import_node_path36.dirname)(registryPath), { recursive: true });
32695
32730
  await atomicWrite(registryPath, serializeDeferredWorktrees(entries));
32696
32731
  },
32697
32732
  // Serialized read-modify-write under the repo-wide lock (#2846).
32698
32733
  update: async (mutate) => {
32699
- await (0, import_promises7.mkdir)((0, import_node_path35.dirname)(registryPath), { recursive: true });
32734
+ await (0, import_promises7.mkdir)((0, import_node_path36.dirname)(registryPath), { recursive: true });
32700
32735
  const deadline = Date.now() + opts.maxWaitMs;
32701
32736
  for (; ; ) {
32702
32737
  const guard = await acquireLock(lockPath, opts, deadline);
@@ -32847,7 +32882,7 @@ var defaultLeaseCloseExec = (_cmd, args) => execJervCli(args, { timeout: GIT_TIM
32847
32882
  async function bestEffortLeaseClose(wtPath, exec = defaultLeaseCloseExec) {
32848
32883
  const step = "close jerv worktree lease";
32849
32884
  try {
32850
- await exec("jerv-cli", ["lease", "close", "--ref", wtPath]);
32885
+ await exec("jerv-cli", ["cli", "lease", "close", "--ref", wtPath]);
32851
32886
  return { step, status: "done" };
32852
32887
  } catch (e) {
32853
32888
  const err = e;
@@ -32867,7 +32902,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32867
32902
  );
32868
32903
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
32869
32904
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
32870
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path36.dirname)((0, import_node_path36.dirname)(worktreeGitRoot)) : repoRoot2;
32905
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path37.dirname)((0, import_node_path37.dirname)(worktreeGitRoot)) : repoRoot2;
32871
32906
  const gcActor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
32872
32907
  const owners = readWorktreeOwners(primaryRepoRoot);
32873
32908
  const removalNow = Date.now();
@@ -32924,7 +32959,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32924
32959
  const cleanup = await cleanupPrMergeLocalBranch(branch.branch, {
32925
32960
  beforeWorktrees,
32926
32961
  startingPath: branch.worktreePath,
32927
- pathExists: (p) => (0, import_node_fs38.existsSync)(p),
32962
+ pathExists: (p) => (0, import_node_fs39.existsSync)(p),
32928
32963
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
32929
32964
  teardownWorktreeStage,
32930
32965
  deferredStore,
@@ -32962,7 +32997,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
32962
32997
  let removalAttempted = false;
32963
32998
  try {
32964
32999
  const cleanupTarget = resolveSafeSiblingWorktreeCleanupTarget(wt.path, cleanupRoots, {
32965
- realpath: (path2) => (0, import_node_fs38.realpathSync)(path2)
33000
+ realpath: (path2) => (0, import_node_fs39.realpathSync)(path2)
32966
33001
  });
32967
33002
  if (!cleanupTarget.ok) {
32968
33003
  result.failed.push(`${wt.path}: ${cleanupTarget.reason}`);
@@ -33049,13 +33084,13 @@ async function composeOverrideBodyFile(prNumber, repoArgs, gh) {
33049
33084
  const commits = JSON.parse(raw).commits ?? [];
33050
33085
  const body = squashBodyWithOverride(commits.map((c) => ({ headline: c.messageHeadline ?? "", body: c.messageBody ?? "" })), process.cwd());
33051
33086
  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}
33087
+ const dir = (0, import_node_fs39.mkdtempSync)((0, import_node_path37.join)((0, import_node_os15.tmpdir)(), "mmi-squash-body-"));
33088
+ const path2 = (0, import_node_path37.join)(dir, "body.txt");
33089
+ (0, import_node_fs39.writeFileSync)(path2, `${body}
33055
33090
  `, "utf8");
33056
33091
  return { path: path2, cleanup: () => {
33057
33092
  try {
33058
- (0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
33093
+ (0, import_node_fs39.rmSync)(dir, { recursive: true, force: true });
33059
33094
  } catch {
33060
33095
  }
33061
33096
  } };
@@ -33177,13 +33212,13 @@ var realWorktreeDirRemover = {
33177
33212
  probe: (p) => {
33178
33213
  let st;
33179
33214
  try {
33180
- st = (0, import_node_fs38.lstatSync)(p);
33215
+ st = (0, import_node_fs39.lstatSync)(p);
33181
33216
  } catch {
33182
33217
  return null;
33183
33218
  }
33184
33219
  if (st.isSymbolicLink()) return "link";
33185
33220
  try {
33186
- (0, import_node_fs38.readlinkSync)(p);
33221
+ (0, import_node_fs39.readlinkSync)(p);
33187
33222
  return "link";
33188
33223
  } catch {
33189
33224
  }
@@ -33191,7 +33226,7 @@ var realWorktreeDirRemover = {
33191
33226
  },
33192
33227
  readdir: (p) => {
33193
33228
  try {
33194
- return (0, import_node_fs38.readdirSync)(p);
33229
+ return (0, import_node_fs39.readdirSync)(p);
33195
33230
  } catch {
33196
33231
  return [];
33197
33232
  }
@@ -33200,9 +33235,9 @@ var realWorktreeDirRemover = {
33200
33235
  // leaving the target); a file symlink with unlink. rmdir first, fall back to unlink.
33201
33236
  detachLink: (p) => {
33202
33237
  try {
33203
- (0, import_node_fs38.rmdirSync)(p);
33238
+ (0, import_node_fs39.rmdirSync)(p);
33204
33239
  } catch {
33205
- (0, import_node_fs38.unlinkSync)(p);
33240
+ (0, import_node_fs39.unlinkSync)(p);
33206
33241
  }
33207
33242
  },
33208
33243
  removeTree: (p) => (0, import_promises8.rm)(p, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
@@ -33235,9 +33270,9 @@ async function worktreeHasStageState(worktreePath) {
33235
33270
  }
33236
33271
  }
33237
33272
  function stageStateFileBelongsToWorktree(statePath, worktreePath) {
33238
- if (!(0, import_node_fs38.existsSync)(statePath)) return false;
33273
+ if (!(0, import_node_fs39.existsSync)(statePath)) return false;
33239
33274
  try {
33240
- const state = JSON.parse((0, import_node_fs38.readFileSync)(statePath, "utf8"));
33275
+ const state = JSON.parse((0, import_node_fs39.readFileSync)(statePath, "utf8"));
33241
33276
  const recordedCwd = typeof state.identity?.cwd === "string" ? state.identity.cwd : typeof state.cwd === "string" ? state.cwd : "";
33242
33277
  return Boolean(recordedCwd && isPathUnderDirectory2(recordedCwd, worktreePath));
33243
33278
  } catch {
@@ -33672,14 +33707,14 @@ async function checkDocsIndexAtHead(opts, deps) {
33672
33707
  }
33673
33708
 
33674
33709
  // src/worktree-lifecycle-commands.ts
33675
- var import_node_fs40 = require("node:fs");
33710
+ var import_node_fs41 = require("node:fs");
33676
33711
  var import_promises9 = require("node:fs/promises");
33677
- var import_node_path38 = require("node:path");
33712
+ var import_node_path39 = require("node:path");
33678
33713
 
33679
33714
  // src/worktree-install-cache.ts
33680
33715
  var import_node_crypto7 = require("node:crypto");
33681
- var import_node_fs39 = require("node:fs");
33682
- var import_node_path37 = require("node:path");
33716
+ var import_node_fs40 = require("node:fs");
33717
+ var import_node_path38 = require("node:path");
33683
33718
  var CACHE_DIR = "worktree-install-cache";
33684
33719
  var MANIFEST = "manifest.json";
33685
33720
  var NODE_MODULES2 = "node_modules";
@@ -33692,16 +33727,16 @@ var LOCKFILE_NAMES = [
33692
33727
  "package-lock.json"
33693
33728
  ];
33694
33729
  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 }),
33730
+ exists: import_node_fs40.existsSync,
33731
+ readFile: (path2) => (0, import_node_fs40.readFileSync)(path2, "utf8"),
33732
+ lstat: (path2) => (0, import_node_fs40.lstatSync)(path2),
33733
+ copyDir: (from, to) => (0, import_node_fs40.cpSync)(from, to, { recursive: true, force: true }),
33699
33734
  mkdirp: (path2) => {
33700
- (0, import_node_fs39.mkdirSync)(path2, { recursive: true });
33735
+ (0, import_node_fs40.mkdirSync)(path2, { recursive: true });
33701
33736
  },
33702
- writeFile: (path2, contents) => (0, import_node_fs39.writeFileSync)(path2, contents, "utf8"),
33737
+ writeFile: (path2, contents) => (0, import_node_fs40.writeFileSync)(path2, contents, "utf8"),
33703
33738
  rm: (path2) => {
33704
- (0, import_node_fs39.rmSync)(path2, { recursive: true, force: true });
33739
+ (0, import_node_fs40.rmSync)(path2, { recursive: true, force: true });
33705
33740
  }
33706
33741
  };
33707
33742
  function hashLockfileBytes(contents) {
@@ -33709,7 +33744,7 @@ function hashLockfileBytes(contents) {
33709
33744
  }
33710
33745
  function resolveWorktreeInstallLockfile(packageDir, fs2 = realWorktreeInstallCacheFs) {
33711
33746
  for (const name of LOCKFILE_NAMES) {
33712
- const path2 = (0, import_node_path37.join)(packageDir, name);
33747
+ const path2 = (0, import_node_path38.join)(packageDir, name);
33713
33748
  if (!fs2.exists(path2)) continue;
33714
33749
  try {
33715
33750
  const hash = hashLockfileBytes(fs2.readFile(path2));
@@ -33724,8 +33759,8 @@ function worktreeInstallCacheEntry(primaryRoot, lockfileHash) {
33724
33759
  const root = repoRuntimeStatePath(primaryRoot, CACHE_DIR, lockfileHash);
33725
33760
  return {
33726
33761
  root,
33727
- manifestPath: (0, import_node_path37.join)(root, MANIFEST),
33728
- nodeModulesPath: (0, import_node_path37.join)(root, NODE_MODULES2)
33762
+ manifestPath: (0, import_node_path38.join)(root, MANIFEST),
33763
+ nodeModulesPath: (0, import_node_path38.join)(root, NODE_MODULES2)
33729
33764
  };
33730
33765
  }
33731
33766
  function readWorktreeInstallCacheManifest(manifestPath, fs2 = realWorktreeInstallCacheFs) {
@@ -33765,7 +33800,7 @@ function invalidateWorktreeInstallCacheEntry(entry, fs2 = realWorktreeInstallCac
33765
33800
  }
33766
33801
  }
33767
33802
  function removeMaterializedTree(packageDir, fs2) {
33768
- const dest = (0, import_node_path37.join)(packageDir, NODE_MODULES2);
33803
+ const dest = (0, import_node_path38.join)(packageDir, NODE_MODULES2);
33769
33804
  if (!fs2.exists(dest)) return;
33770
33805
  fs2.rm(dest);
33771
33806
  if (fs2.exists(dest)) {
@@ -33773,7 +33808,7 @@ function removeMaterializedTree(packageDir, fs2) {
33773
33808
  }
33774
33809
  }
33775
33810
  function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeInstallCacheFs) {
33776
- const dest = (0, import_node_path37.join)(destPackageDir, NODE_MODULES2);
33811
+ const dest = (0, import_node_path38.join)(destPackageDir, NODE_MODULES2);
33777
33812
  try {
33778
33813
  if (fs2.exists(dest)) fs2.rm(dest);
33779
33814
  fs2.mkdirp(destPackageDir);
@@ -33788,7 +33823,7 @@ function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeI
33788
33823
  }
33789
33824
  }
33790
33825
  async function storeWorktreeInstallCacheEntry(primaryRoot, lockfile3, command, sourcePackageDir, fs2 = realWorktreeInstallCacheFs, now = Date.now()) {
33791
- const source = (0, import_node_path37.join)(sourcePackageDir, NODE_MODULES2);
33826
+ const source = (0, import_node_path38.join)(sourcePackageDir, NODE_MODULES2);
33792
33827
  if (!isMaterializableNodeModulesDir(source, fs2)) return;
33793
33828
  const entry = worktreeInstallCacheEntry(primaryRoot, lockfile3.hash);
33794
33829
  const manifest = {
@@ -34048,7 +34083,7 @@ function classifyStaleLeaks(input) {
34048
34083
  var defaultOrphanDirScanDeps = {
34049
34084
  listDirs: (root) => {
34050
34085
  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));
34086
+ return (0, import_node_fs41.readdirSync)(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path39.join)(root, e.name));
34052
34087
  } catch {
34053
34088
  return [];
34054
34089
  }
@@ -34214,13 +34249,13 @@ function registerWorktreeCommands(program3) {
34214
34249
  const detached = headBorn && !symbolicBranch;
34215
34250
  const branch = symbolicBranch || (detached ? "HEAD" : "");
34216
34251
  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();
34252
+ const gitFile = (0, import_node_path39.join)(wtPath, ".git");
34253
+ const isLinked = (0, import_node_fs41.existsSync)(gitFile) && (0, import_node_fs41.statSync)(gitFile).isFile();
34219
34254
  if (apply && !isLinked) {
34220
34255
  return fail("worktree land: run from inside the linked worktree you want to land (this is the primary checkout)");
34221
34256
  }
34222
34257
  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;
34258
+ const primaryCheckout = commonDir ? (0, import_node_path39.dirname)(commonDir) : wtPath;
34224
34259
  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
34260
  const orphan = classifyOrphanedWorktree({
34226
34261
  branch,
@@ -34494,10 +34529,10 @@ async function gatherWorktreeContext() {
34494
34529
  if (s) stages.push({ path: wt.path, port: s.port });
34495
34530
  }
34496
34531
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
34497
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path38.dirname)((0, import_node_path38.dirname)(worktreeGitRoot)) : repoRoot2;
34532
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path39.dirname)((0, import_node_path39.dirname)(worktreeGitRoot)) : repoRoot2;
34498
34533
  const wtRoot = siblingMmiWorktreesRoot(primaryRepoRoot);
34499
34534
  let orphanDirs = [];
34500
- if ((0, import_node_fs40.existsSync)(wtRoot)) {
34535
+ if ((0, import_node_fs41.existsSync)(wtRoot)) {
34501
34536
  orphanDirs = scanOrphanDirs(wtRoot, worktreeGitRoot, {
34502
34537
  ...defaultOrphanDirScanDeps,
34503
34538
  listDirs: (root) => worktreeScanDirs(root, primaryRepoRoot, defaultOrphanDirScanDeps.listDirs, isRepoCheckoutDir)
@@ -34533,7 +34568,7 @@ ${err.stderr ?? ""}`;
34533
34568
  }
34534
34569
 
34535
34570
  // src/issue-commands.ts
34536
- var import_node_fs41 = require("node:fs");
34571
+ var import_node_fs42 = require("node:fs");
34537
34572
  var import_node_crypto8 = require("node:crypto");
34538
34573
  var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
34539
34574
  var ReparentConflictError = class extends Error {
@@ -34551,7 +34586,7 @@ async function editIssue(client, options, deps = {}) {
34551
34586
  const url = `https://github.com/${repo}/issues/${parsed.number}`;
34552
34587
  const patch = {};
34553
34588
  let bodyChanged = false;
34554
- const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs41.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
34589
+ const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs42.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
34555
34590
  if (options.titleFile !== void 0) {
34556
34591
  patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
34557
34592
  } else if (options.title !== void 0) {
@@ -35156,7 +35191,7 @@ function extendCreateCommand(issue2, batchAttach) {
35156
35191
  if (opts.batch) {
35157
35192
  let specs;
35158
35193
  try {
35159
- const raw = (0, import_node_fs41.readFileSync)(opts.batch, "utf8");
35194
+ const raw = (0, import_node_fs42.readFileSync)(opts.batch, "utf8");
35160
35195
  specs = JSON.parse(raw);
35161
35196
  if (!Array.isArray(specs)) throw new Error("batch file must contain a JSON array");
35162
35197
  } catch (e) {
@@ -35231,8 +35266,8 @@ ${lines}`, {
35231
35266
  }
35232
35267
 
35233
35268
  // src/train-commands.ts
35234
- var import_node_fs42 = require("node:fs");
35235
- var import_node_path39 = require("node:path");
35269
+ var import_node_fs43 = require("node:fs");
35270
+ var import_node_path40 = require("node:path");
35236
35271
  var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
35237
35272
  function resolveReleaseBumpIntent(raw) {
35238
35273
  const intent = typeof raw === "string" ? raw.trim() : "";
@@ -35243,7 +35278,7 @@ function resolveReleaseBumpIntent(raw) {
35243
35278
  }
35244
35279
  function readRepoVersion() {
35245
35280
  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;
35281
+ return JSON.parse((0, import_node_fs43.readFileSync)((0, import_node_path40.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
35247
35282
  } catch {
35248
35283
  return void 0;
35249
35284
  }
@@ -35400,9 +35435,9 @@ function registerDeployCommands(program3) {
35400
35435
  }
35401
35436
 
35402
35437
  // src/discovery-commands.ts
35403
- var import_node_fs43 = require("node:fs");
35438
+ var import_node_fs44 = require("node:fs");
35404
35439
  var import_node_os16 = require("node:os");
35405
- var import_node_path40 = require("node:path");
35440
+ var import_node_path41 = require("node:path");
35406
35441
  var GC_GH_TIMEOUT_MS3 = 2e4;
35407
35442
  async function collectStatus() {
35408
35443
  const repo = await resolveRepo();
@@ -35592,8 +35627,8 @@ async function collectOnboardStatus(opts = {}) {
35592
35627
  }
35593
35628
  const home = (0, import_node_os16.homedir)();
35594
35629
  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)
35630
+ readKnown: () => readFileSyncSafe((0, import_node_path41.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs44.readFileSync),
35631
+ readSettings: () => readFileSyncSafe((0, import_node_path41.join)(home, ".claude", "settings.json"), import_node_fs44.readFileSync)
35597
35632
  });
35598
35633
  return { track, board, registry: registry2, secrets, plugin, estateCli, doors: opts.doors ?? [], nextCommand };
35599
35634
  }
@@ -35753,8 +35788,9 @@ function formatExplainCommand(cmd, rootName) {
35753
35788
  return lines.join("\n").trimEnd();
35754
35789
  }
35755
35790
  function formatExplainGroup(cmd, rootName) {
35791
+ const canonical = (node) => canonicalPathFor(node.path) ?? node.path;
35756
35792
  const lines = [
35757
- `${rootName} ${cmd.path}${cmd.description ? ` \u2014 ${cmd.description}` : ""}`,
35793
+ `${rootName} ${canonical(cmd)}${cmd.description ? ` \u2014 ${cmd.description}` : ""}`,
35758
35794
  `Category: ${cmd.category} \xB7 Discovery: ${cmd.discovery}`,
35759
35795
  "",
35760
35796
  "Commands:"
@@ -35764,7 +35800,7 @@ function formatExplainGroup(cmd, rootName) {
35764
35800
  const name = arg.variadic ? `${arg.name}...` : arg.name;
35765
35801
  return arg.required ? `<${name}>` : `[${name}]`;
35766
35802
  }).join(" ");
35767
- lines.push(` ${child2.path}${args ? ` ${args}` : ""}${child2.description ? ` \u2014 ${child2.description}` : ""}`);
35803
+ lines.push(` ${canonical(child2)}${args ? ` ${args}` : ""}${child2.description ? ` \u2014 ${child2.description}` : ""}`);
35768
35804
  }
35769
35805
  return lines.join("\n");
35770
35806
  }
@@ -35778,7 +35814,7 @@ function formatExplainLoop(playbook) {
35778
35814
  }
35779
35815
  function findCommandInManifest(manifest, commandPath3) {
35780
35816
  const visit = (command) => {
35781
- if (command.path === commandPath3) return command;
35817
+ if (command.path === commandPath3 || canonicalPathFor(command.path) === commandPath3) return command;
35782
35818
  for (const child2 of command.subcommands) {
35783
35819
  const found = visit(child2);
35784
35820
  if (found) return found;
@@ -36692,19 +36728,19 @@ function registerOrgHealthQuery(program3, deps = defaultOrgHealthQueryDeps()) {
36692
36728
  }
36693
36729
 
36694
36730
  // src/plugin-release-catchup.ts
36695
- var import_node_fs44 = require("node:fs");
36696
- var import_node_path41 = require("node:path");
36731
+ var import_node_fs45 = require("node:fs");
36732
+ var import_node_path42 = require("node:path");
36697
36733
  var import_node_os17 = require("node:os");
36698
36734
  var RELEASE_CATCHUP_TTL_MS = 24 * 60 * 60 * 1e3;
36699
36735
  var RELEASE_CATCHUP_DISABLE_ENV = "MMI_NO_RELEASE_CATCHUP";
36700
36736
  function releaseCatchupStatePath(env = process.env) {
36701
36737
  if (env.MMI_RELEASE_CATCHUP_STATE) return env.MMI_RELEASE_CATCHUP_STATE;
36702
36738
  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");
36739
+ const base2 = env.LOCALAPPDATA || (0, import_node_path42.join)((0, import_node_os17.homedir)(), "AppData", "Local");
36740
+ return (0, import_node_path42.join)(base2, "MMI Future", "mmi-cli", "release-catchup.json");
36705
36741
  }
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");
36742
+ const base = env.XDG_STATE_HOME || (0, import_node_path42.join)((0, import_node_os17.homedir)(), ".local", "state");
36743
+ return (0, import_node_path42.join)(base, "mmi-cli", "release-catchup.json");
36708
36744
  }
36709
36745
  function releaseCatchupDue(state, now, force = false) {
36710
36746
  if (force) return true;
@@ -36714,7 +36750,7 @@ function releaseCatchupDue(state, now, force = false) {
36714
36750
  function newestCachedPluginVersion(home) {
36715
36751
  let names;
36716
36752
  try {
36717
- names = (0, import_node_fs44.readdirSync)(pluginCacheRoot(home));
36753
+ names = (0, import_node_fs45.readdirSync)(pluginCacheRoot(home));
36718
36754
  } catch {
36719
36755
  return void 0;
36720
36756
  }
@@ -36722,15 +36758,15 @@ function newestCachedPluginVersion(home) {
36722
36758
  }
36723
36759
  function marketplaceClonePath(home) {
36724
36760
  try {
36725
- const parsed = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(home, ".claude", "plugins", "known_marketplaces.json"), "utf8"));
36761
+ const parsed = JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(home, ".claude", "plugins", "known_marketplaces.json"), "utf8"));
36726
36762
  if (parsed.mutmutco?.installLocation) return parsed.mutmutco.installLocation;
36727
36763
  } catch {
36728
36764
  }
36729
- return (0, import_node_path41.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
36765
+ return (0, import_node_path42.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
36730
36766
  }
36731
36767
  function readCatalogVersion(home) {
36732
36768
  try {
36733
- const parsed = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(marketplaceClonePath(home), ".claude-plugin", "marketplace.json"), "utf8"));
36769
+ const parsed = JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(marketplaceClonePath(home), ".claude-plugin", "marketplace.json"), "utf8"));
36734
36770
  return parsed.plugins?.find((p) => p.name === "mmi")?.version;
36735
36771
  } catch {
36736
36772
  return void 0;
@@ -36738,7 +36774,7 @@ function readCatalogVersion(home) {
36738
36774
  }
36739
36775
  function readMmiInstallRecord(home) {
36740
36776
  try {
36741
- const parsed = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(home, ".claude", "plugins", "installed_plugins.json"), "utf8"));
36777
+ const parsed = JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(home, ".claude", "plugins", "installed_plugins.json"), "utf8"));
36742
36778
  const record = parsed.plugins?.["mmi@mutmutco"]?.[0];
36743
36779
  return record?.version ? { version: record.version, gitCommitSha: record.gitCommitSha } : void 0;
36744
36780
  } catch {
@@ -36767,7 +36803,7 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
36767
36803
  cliUpdated = true;
36768
36804
  }
36769
36805
  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))) {
36806
+ if (!(0, import_node_fs45.existsSync)(pluginCacheRoot(home))) {
36771
36807
  deps.writeState(statePath, { checkedAt: deps.now(), latest });
36772
36808
  return {
36773
36809
  ok: true,
@@ -36800,8 +36836,8 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
36800
36836
  return { ok: false, detail: `${cliUpdateDetail}; plugin install record could not be cleared (still ${prior.version})` };
36801
36837
  }
36802
36838
  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)) {
36839
+ const payload = (0, import_node_path42.join)(pluginCacheRoot(home), latest, ".pi-plugin");
36840
+ if (!installed || !(0, import_node_fs45.existsSync)(payload)) {
36805
36841
  const why = installed ? `install of ${latest} did not produce a verifiable .pi-plugin payload` : `install of ${latest} failed`;
36806
36842
  if (!prior) return { ok: false, detail: `${cliUpdateDetail}; ${why}; no prior record to restore` };
36807
36843
  const rollback = await restorePriorRecord(home, prior, deps);
@@ -38774,6 +38810,7 @@ async function runDoctorClean(opts, io, deps) {
38774
38810
  });
38775
38811
  return;
38776
38812
  }
38813
+ const provenance = state.cachedAt === void 0 ? [] : [cachedSweepNote(state.cachedAt)];
38777
38814
  if (state.driftLines.length === 0) {
38778
38815
  emitNow({
38779
38816
  ok: true,
@@ -38781,7 +38818,7 @@ async function runDoctorClean(opts, io, deps) {
38781
38818
  id: "schedules-drift",
38782
38819
  label: "schedules drift",
38783
38820
  detail: "no drift",
38784
- verbose: ["no drift lines"]
38821
+ verbose: ["no drift lines", ...provenance]
38785
38822
  });
38786
38823
  return;
38787
38824
  }
@@ -38792,7 +38829,7 @@ async function runDoctorClean(opts, io, deps) {
38792
38829
  label: "schedules drift",
38793
38830
  detail: `${state.driftLines.length} drift line(s)`,
38794
38831
  fix: "run `mmi-cli harbour org schedules` / `org schedules register`",
38795
- verbose: state.driftLines
38832
+ verbose: [...state.driftLines, ...provenance]
38796
38833
  });
38797
38834
  } catch (e) {
38798
38835
  const message = e instanceof Error ? e.message : String(e);
@@ -39009,17 +39046,17 @@ function parseOriginRepo(remoteUrl) {
39009
39046
  }
39010
39047
  function ghHostsConfigPath(env, platform2) {
39011
39048
  const sep3 = platform2 === "win32" ? "\\" : "/";
39012
- const join39 = (...parts) => parts.join(sep3);
39049
+ const join40 = (...parts) => parts.join(sep3);
39013
39050
  const explicit = env.GH_CONFIG_DIR?.trim();
39014
- if (explicit) return join39(explicit, "hosts.yml");
39051
+ if (explicit) return join40(explicit, "hosts.yml");
39015
39052
  if (platform2 === "win32") {
39016
39053
  const appData = (env.AppData ?? env.APPDATA)?.trim();
39017
- return appData ? join39(appData, "GitHub CLI", "hosts.yml") : void 0;
39054
+ return appData ? join40(appData, "GitHub CLI", "hosts.yml") : void 0;
39018
39055
  }
39019
39056
  const xdg = env.XDG_CONFIG_HOME?.trim();
39020
- if (xdg) return join39(xdg, "gh", "hosts.yml");
39057
+ if (xdg) return join40(xdg, "gh", "hosts.yml");
39021
39058
  const home = env.HOME?.trim();
39022
- return home ? join39(home, ".config", "gh", "hosts.yml") : void 0;
39059
+ return home ? join40(home, ".config", "gh", "hosts.yml") : void 0;
39023
39060
  }
39024
39061
  function parseGhHostsAccounts(yaml, host = "github.com") {
39025
39062
  let hostIndent = null;
@@ -39069,9 +39106,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
39069
39106
  }
39070
39107
 
39071
39108
  // src/doctor-io.ts
39072
- var import_node_fs45 = require("node:fs");
39109
+ var import_node_fs46 = require("node:fs");
39073
39110
  var import_node_os18 = require("node:os");
39074
- var import_node_path42 = require("node:path");
39111
+ var import_node_path43 = require("node:path");
39075
39112
  var import_node_child_process19 = require("node:child_process");
39076
39113
  var import_node_util8 = require("node:util");
39077
39114
  var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process19.execFile);
@@ -39079,7 +39116,7 @@ var MMI_PLUGIN_ID2 = "mmi@mutmutco";
39079
39116
  function installedClaudePluginVersion() {
39080
39117
  try {
39081
39118
  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")
39119
+ (0, import_node_fs46.readFileSync)((0, import_node_path43.join)((0, import_node_os18.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
39083
39120
  );
39084
39121
  const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
39085
39122
  if (versions.length === 0) return void 0;
@@ -39090,7 +39127,7 @@ function installedClaudePluginVersion() {
39090
39127
  }
39091
39128
  function manifestVersion(path2) {
39092
39129
  try {
39093
- const manifest = JSON.parse((0, import_node_fs45.readFileSync)(path2, "utf8"));
39130
+ const manifest = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
39094
39131
  return typeof manifest.version === "string" && manifest.version.trim() ? manifest.version.trim() : void 0;
39095
39132
  } catch {
39096
39133
  return void 0;
@@ -39100,22 +39137,22 @@ function installedSurfacePluginVersion(surface) {
39100
39137
  const token = surfaceToken(surface);
39101
39138
  if (token === "kilo") {
39102
39139
  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();
39140
+ const stamp = (0, import_node_fs46.readFileSync)((0, import_node_path43.join)((0, import_node_os18.homedir)(), ".kilo", ".mmi-kilo-version"), "utf8").trim();
39104
39141
  return stamp || void 0;
39105
39142
  } catch {
39106
39143
  return void 0;
39107
39144
  }
39108
39145
  }
39109
39146
  if (token === "cursor") {
39110
- return manifestVersion((0, import_node_path42.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
39147
+ return manifestVersion((0, import_node_path43.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
39111
39148
  }
39112
39149
  if (token === "jervcode") {
39113
39150
  const entry = mmiPiWrapperEntry();
39114
39151
  if (!entry) return void 0;
39115
- return manifestVersion((0, import_node_path42.join)(decodeURIComponent(entry.replace(/^file:\/\/\/?/, "")), "package.json"));
39152
+ return manifestVersion((0, import_node_path43.join)(decodeURIComponent(entry.replace(/^file:\/\/\/?/, "")), "package.json"));
39116
39153
  }
39117
39154
  if (token === "kimi") {
39118
- return manifestVersion((0, import_node_path42.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
39155
+ return manifestVersion((0, import_node_path43.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
39119
39156
  }
39120
39157
  if (token === "claude") return installedClaudePluginVersion();
39121
39158
  if (token !== "codex") return void 0;
@@ -39153,13 +39190,13 @@ function worktreeRootSync() {
39153
39190
  }
39154
39191
  var gitignorePath = () => {
39155
39192
  const root = worktreeRootSync();
39156
- return root === null ? null : (0, import_node_path42.join)(root, ".gitignore");
39193
+ return root === null ? null : (0, import_node_path43.join)(root, ".gitignore");
39157
39194
  };
39158
39195
  function readGitignore() {
39159
39196
  const path2 = gitignorePath();
39160
39197
  if (path2 === null) return null;
39161
39198
  try {
39162
- return (0, import_node_fs45.readFileSync)(path2, "utf8");
39199
+ return (0, import_node_fs46.readFileSync)(path2, "utf8");
39163
39200
  } catch {
39164
39201
  return null;
39165
39202
  }
@@ -39168,7 +39205,7 @@ function writeGitignore(content) {
39168
39205
  const path2 = gitignorePath();
39169
39206
  if (path2 === null) return false;
39170
39207
  try {
39171
- (0, import_node_fs45.writeFileSync)(path2, content, "utf8");
39208
+ (0, import_node_fs46.writeFileSync)(path2, content, "utf8");
39172
39209
  return true;
39173
39210
  } catch {
39174
39211
  return false;
@@ -39187,7 +39224,7 @@ async function repoRoot() {
39187
39224
  }
39188
39225
  function hasRepoLocalWorktrees() {
39189
39226
  const root = worktreeRootSync();
39190
- return root !== null && (0, import_node_fs45.existsSync)((0, import_node_path42.join)(root, ".worktrees"));
39227
+ return root !== null && (0, import_node_fs46.existsSync)((0, import_node_path43.join)(root, ".worktrees"));
39191
39228
  }
39192
39229
 
39193
39230
  // src/index.ts
@@ -39206,8 +39243,8 @@ ${r.stderr ?? ""}`).catch(() => "");
39206
39243
  function ghMultiAccountCaveat(announcedLogin) {
39207
39244
  try {
39208
39245
  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")));
39246
+ if (!hostsPath || !(0, import_node_fs47.existsSync)(hostsPath)) return void 0;
39247
+ return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0, import_node_fs47.readFileSync)(hostsPath, "utf8")));
39211
39248
  } catch {
39212
39249
  return void 0;
39213
39250
  }
@@ -39215,7 +39252,7 @@ function ghMultiAccountCaveat(announcedLogin) {
39215
39252
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
39216
39253
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
39217
39254
  function envHealLockPath(home) {
39218
- return (0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
39255
+ return (0, import_node_path44.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
39219
39256
  }
39220
39257
  async function withEnvHealLock(what, run) {
39221
39258
  try {
@@ -39348,7 +39385,7 @@ function mmiDoctorDeps(opts = {}) {
39348
39385
  );
39349
39386
  const result = applyPluginCachePlan(
39350
39387
  plan,
39351
- (p) => (0, import_node_fs46.rmSync)(p, { recursive: true }),
39388
+ (p) => (0, import_node_fs47.rmSync)(p, { recursive: true }),
39352
39389
  stagingApplyFsGuard(configRoot)
39353
39390
  );
39354
39391
  return {
@@ -39402,8 +39439,8 @@ function mmiDoctorDeps(opts = {}) {
39402
39439
  const home = (0, import_node_os19.homedir)();
39403
39440
  const rows = marketplaceRows(
39404
39441
  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),
39442
+ readFileSyncSafe((0, import_node_path44.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs47.readFileSync),
39443
+ readFileSyncSafe((0, import_node_path44.join)(home, ".claude", "settings.json"), import_node_fs47.readFileSync),
39407
39444
  // #3974: this CLI heals these rows, so report mode names the doctor run rather than the hand
39408
39445
  // edit. #4792 narrows WHICH run: `applyOrgMarketplacePins` declines outright while Claude Code
39409
39446
  // is up, because the host owns this file and rewrites it from its own copy (#4083). Naming the
@@ -39415,7 +39452,7 @@ function mmiDoctorDeps(opts = {}) {
39415
39452
  hostBlocked ?? claudeCodeEnvMarkerPresent() ? "host-running" : "doctor"
39416
39453
  );
39417
39454
  const pending = readMarketplacePinPending(
39418
- (0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
39455
+ (0, import_node_path44.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
39419
39456
  MMI_MARKETPLACE_NAME
39420
39457
  );
39421
39458
  if (!pending) return rows;
@@ -39441,9 +39478,9 @@ function mmiDoctorDeps(opts = {}) {
39441
39478
  if (detectSurface(process.env) === "codex") return void 0;
39442
39479
  const home = (0, import_node_os19.homedir)();
39443
39480
  const names = [MMI_MARKETPLACE_NAME];
39444
- const result = applyOrgMarketplacePins((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), names);
39481
+ const result = applyOrgMarketplacePins((0, import_node_path44.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), names);
39445
39482
  if (result?.wrote) {
39446
- writeMarketplacePinPending((0, import_node_path43.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"), names);
39483
+ writeMarketplacePinPending((0, import_node_path44.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"), names);
39447
39484
  }
39448
39485
  return result;
39449
39486
  } catch {
@@ -39459,7 +39496,7 @@ function mmiDoctorDeps(opts = {}) {
39459
39496
  // adopted the generated routing index (MMG-Unlive: `docs/Archive/**` only, no index, no gate.yml) would
39460
39497
  // get a permanent — demanding an artifact it never asked for.
39461
39498
  docsIndexState: (root) => {
39462
- if (!(0, import_node_fs46.existsSync)((0, import_node_path43.join)(root, DOCS_INDEX_PATH))) return void 0;
39499
+ if (!(0, import_node_fs47.existsSync)((0, import_node_path44.join)(root, DOCS_INDEX_PATH))) return void 0;
39463
39500
  const real = createDocsIndexDeps(root);
39464
39501
  let docs2;
39465
39502
  const listDocs = () => docs2 ??= real.listDocs();
@@ -39468,7 +39505,7 @@ function mmiDoctorDeps(opts = {}) {
39468
39505
  },
39469
39506
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
39470
39507
  healDocsIndex: (root) => {
39471
- if (!(0, import_node_fs46.existsSync)((0, import_node_path43.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
39508
+ if (!(0, import_node_fs47.existsSync)((0, import_node_path44.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
39472
39509
  const real = createDocsIndexDeps(root);
39473
39510
  let docs2;
39474
39511
  const listDocs = () => docs2 ??= real.listDocs();
@@ -39496,6 +39533,7 @@ function mmiDoctorDeps(opts = {}) {
39496
39533
  // #4170: light board doctor with 15s ceiling. skipClaimLiveness keeps Phase 3 off.
39497
39534
  boardDoctorFix: async ({ fix } = {}) => {
39498
39535
  const BOARD_DOCTOR_TIMEOUT_MS = 15e3;
39536
+ let ceiling;
39499
39537
  try {
39500
39538
  const cfg = await loadConfigForRepo();
39501
39539
  const work = boardDoctor({
@@ -39506,7 +39544,7 @@ function mmiDoctorDeps(opts = {}) {
39506
39544
  const raced = await Promise.race([
39507
39545
  work.then((r) => ({ ...r, timedOut: false })),
39508
39546
  new Promise((resolve5) => {
39509
- setTimeout(() => resolve5({ timedOut: true, scanned: 0, findings: 0, fixed: 0, failed: 0 }), BOARD_DOCTOR_TIMEOUT_MS);
39547
+ ceiling = setTimeout(() => resolve5({ timedOut: true, scanned: 0, findings: 0, fixed: 0, failed: 0 }), BOARD_DOCTOR_TIMEOUT_MS);
39510
39548
  })
39511
39549
  ]);
39512
39550
  if (raced.timedOut) return { scanned: 0, findings: 0, fixed: 0, failed: 0, timedOut: true };
@@ -39518,11 +39556,20 @@ function mmiDoctorDeps(opts = {}) {
39518
39556
  };
39519
39557
  } catch (e) {
39520
39558
  return { scanned: 0, findings: 0, fixed: 0, failed: 0, readFailed: true, error: e instanceof Error ? e.message : String(e) };
39559
+ } finally {
39560
+ clearTimeout(ceiling);
39521
39561
  }
39522
39562
  },
39523
39563
  // #4171: schedules drift notebook — report-only, ~20s ceiling.
39564
+ // #4815: and throttled. The sweep behind it reads every workflow file in every org repo — 12s of a
39565
+ // 22s doctor — so a cached notebook under six hours old answers the row instead, saying so in its
39566
+ // evidence. Only a COMPLETE sweep is cached (see schedules-drift-cache.ts).
39524
39567
  schedulesDriftState: async () => {
39525
39568
  const SCHEDULES_DRIFT_TIMEOUT_MS = 2e4;
39569
+ const cachePath = schedulesDriftCachePath(repoRuntimeStatePath(process.cwd()));
39570
+ const cached = readSchedulesDriftCache(cachePath);
39571
+ if (cached) return { driftLines: cached.driftLines, incomplete: [], cachedAt: cached.at };
39572
+ let ceiling;
39526
39573
  try {
39527
39574
  const raced = await Promise.race([
39528
39575
  fetchNotebook().then((nb) => ({
@@ -39531,12 +39578,15 @@ function mmiDoctorDeps(opts = {}) {
39531
39578
  timedOut: false
39532
39579
  })),
39533
39580
  new Promise((resolve5) => {
39534
- setTimeout(() => resolve5({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
39581
+ ceiling = setTimeout(() => resolve5({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
39535
39582
  })
39536
39583
  ]);
39584
+ if (!raced.timedOut && raced.incomplete.length === 0) writeSchedulesDriftCache(cachePath, raced.driftLines);
39537
39585
  return raced;
39538
39586
  } catch (e) {
39539
39587
  return { driftLines: [], incomplete: [], readFailed: true, error: e instanceof Error ? e.message : String(e) };
39588
+ } finally {
39589
+ clearTimeout(ceiling);
39540
39590
  }
39541
39591
  },
39542
39592
  // #4173: estate commands absent from the running Commander program (stale global CLI).
@@ -39703,12 +39753,15 @@ function positionalTargetForm(cmd, opts = {}) {
39703
39753
  const args = cmd.registeredArguments ?? [];
39704
39754
  const first = args[0];
39705
39755
  if (!first) return void 0;
39706
- return formatPositionalTarget(commandPath2(cmd), first.name(), opts);
39756
+ return formatPositionalTarget(canonicalPathFor(commandPath2(cmd)) ?? commandPath2(cmd), first.name(), opts);
39707
39757
  }
39708
39758
  function resolveParseHint() {
39709
39759
  if (lastParseErrorKind === "unknown-command") {
39710
- const path3 = lastUnknownCommand ? suggestCommandPath(lastUnknownCommand, allCommandPaths()) : void 0;
39711
- return path3 ? `(did you mean \`mmi-cli ${path3}\`? ${DISCOVERY_HINT})` : STALE_HINT;
39760
+ const parent = resolveCommandFromArgv(program2, process.argv.slice(2));
39761
+ const candidates = parent && parent.commands.length ? parent.commands.filter((child2) => commandMetadata(child2)?.category !== "internal").map(commandPath2) : allCommandPaths();
39762
+ const path3 = lastUnknownCommand ? suggestCommandPath(lastUnknownCommand, candidates) : void 0;
39763
+ const canonical = path3 ? canonicalPathFor(path3) ?? path3 : void 0;
39764
+ return canonical ? `(did you mean \`mmi-cli ${canonical}\`? ${DISCOVERY_HINT})` : STALE_HINT;
39712
39765
  }
39713
39766
  if (lastParseErrorKind !== "bad-arguments") return STALE_HINT;
39714
39767
  const cmd = resolveCommandFromArgv(program2, process.argv.slice(2));
@@ -39818,19 +39871,19 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
39818
39871
  });
39819
39872
  var rules = program2.command("rules").description("org-managed .gitignore delivery");
39820
39873
  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;
39874
+ const path2 = (0, import_node_path44.join)(process.cwd(), ".gitignore");
39875
+ const current = (0, import_node_fs47.existsSync)(path2) ? (0, import_node_fs47.readFileSync)(path2, "utf8") : null;
39823
39876
  const plan = planManagedGitignore(current);
39824
39877
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
39825
39878
  if (opts.json) {
39826
- if (opts.write && plan.changed) (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
39879
+ if (opts.write && plan.changed) (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
39827
39880
  console.log(JSON.stringify(plan, null, 2));
39828
39881
  if (!opts.write && plan.changed) process.exitCode = 1;
39829
39882
  return;
39830
39883
  }
39831
39884
  if (opts.write) {
39832
39885
  if (plan.changed) {
39833
- (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
39886
+ (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
39834
39887
  console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
39835
39888
  } else {
39836
39889
  console.log("mmi-cli devops org rules gitignore: up to date");
@@ -39989,8 +40042,8 @@ gcCmd.option("--dry-run", "show what would be deleted (default)").option("--appl
39989
40042
  if (!Number.isFinite(limit) || limit < 1) return fail("worktree gc: --limit must be a positive integer");
39990
40043
  let root;
39991
40044
  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`);
40045
+ root = (0, import_node_path44.resolve)(o.root);
40046
+ 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
40047
  const gcRepoRoot = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
39995
40048
  if (isPathUnderDirectory2(gcRepoRoot, root)) {
39996
40049
  return fail(`worktree gc: --root ${root} contains this checkout \u2014 name a worktrees root, not the repo or an ancestor of it`);
@@ -40087,7 +40140,7 @@ async function currentWorktreeRemovalContext(command, force) {
40087
40140
  };
40088
40141
  }
40089
40142
  async function unprovenWorktreeReason(wtPath, repoRoot2) {
40090
- if (!(0, import_node_fs46.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
40143
+ if (!(0, import_node_fs47.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
40091
40144
  const porcelain = (await execFileP2("git", ["-C", repoRoot2, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
40092
40145
  const registered = parseWorktreePorcelainEntries(porcelain);
40093
40146
  if (!registered.length) {
@@ -40117,26 +40170,26 @@ function makeProvisionDeps(worktreeRoot, quiet, log) {
40117
40170
  function acquireWorktreeSetupLock(worktreeRoot) {
40118
40171
  const lockPath = repoRuntimeStatePath(worktreeRoot, "worktree-setup.lock");
40119
40172
  const take = () => {
40120
- const fd = (0, import_node_fs46.openSync)(lockPath, "wx");
40173
+ const fd = (0, import_node_fs47.openSync)(lockPath, "wx");
40121
40174
  try {
40122
- (0, import_node_fs46.writeSync)(fd, String(Date.now()));
40175
+ (0, import_node_fs47.writeSync)(fd, String(Date.now()));
40123
40176
  } finally {
40124
- (0, import_node_fs46.closeSync)(fd);
40177
+ (0, import_node_fs47.closeSync)(fd);
40125
40178
  }
40126
40179
  return () => {
40127
40180
  try {
40128
- (0, import_node_fs46.rmSync)(lockPath, { force: true });
40181
+ (0, import_node_fs47.rmSync)(lockPath, { force: true });
40129
40182
  } catch {
40130
40183
  }
40131
40184
  };
40132
40185
  };
40133
40186
  try {
40134
- (0, import_node_fs46.mkdirSync)((0, import_node_path43.dirname)(lockPath), { recursive: true });
40187
+ (0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(lockPath), { recursive: true });
40135
40188
  return take();
40136
40189
  } catch {
40137
40190
  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 });
40191
+ if (Date.now() - (0, import_node_fs47.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
40192
+ (0, import_node_fs47.rmSync)(lockPath, { force: true });
40140
40193
  return take();
40141
40194
  }
40142
40195
  } catch {
@@ -40282,6 +40335,7 @@ withExamples(mutating(
40282
40335
  let lease;
40283
40336
  try {
40284
40337
  await execJervCli([
40338
+ "cli",
40285
40339
  "lease",
40286
40340
  "open",
40287
40341
  "--kind",
@@ -41000,7 +41054,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
41000
41054
  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
41055
  if (o.secretsFile) {
41002
41056
  try {
41003
- vars.push(`secrets=${(0, import_node_fs46.readFileSync)(o.secretsFile, "utf8")}`);
41057
+ vars.push(`secrets=${(0, import_node_fs47.readFileSync)(o.secretsFile, "utf8")}`);
41004
41058
  } catch (e) {
41005
41059
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
41006
41060
  }
@@ -41768,11 +41822,11 @@ pr.command("view <number>").description("read a PR as structured JSON (merged st
41768
41822
  }
41769
41823
  });
41770
41824
  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) => {
41825
+ const wfDir = (0, import_node_path44.join)(cwd, ".github", "workflows");
41826
+ if (!(0, import_node_fs47.existsSync)(wfDir)) return [];
41827
+ return (0, import_node_fs47.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
41774
41828
  try {
41775
- return workflowReportsPrChecks((0, import_node_fs46.readFileSync)((0, import_node_path43.join)(wfDir, name), "utf8"));
41829
+ return workflowReportsPrChecks((0, import_node_fs47.readFileSync)((0, import_node_path44.join)(wfDir, name), "utf8"));
41776
41830
  } catch {
41777
41831
  return true;
41778
41832
  }
@@ -41824,16 +41878,16 @@ function ciAuditDeps() {
41824
41878
  // gate re-seed step is skipped gracefully rather than failing mid-run.
41825
41879
  readSeedFile: (path2) => {
41826
41880
  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;
41881
+ const fullPath = (0, import_node_path44.join)(root, path2);
41882
+ return (0, import_node_fs47.existsSync)(fullPath) ? (0, import_node_fs47.readFileSync)(fullPath, "utf8") : null;
41829
41883
  }
41830
41884
  };
41831
41885
  }
41832
41886
  function hubRoot() {
41833
- const fromPkg = (0, import_node_path43.join)(__dirname, "..", "..");
41887
+ const fromPkg = (0, import_node_path44.join)(__dirname, "..", "..");
41834
41888
  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();
41889
+ if ((0, import_node_fs47.existsSync)((0, import_node_path44.join)(fromPkg, marker))) return fromPkg;
41890
+ if ((0, import_node_fs47.existsSync)((0, import_node_path44.join)(process.cwd(), marker))) return process.cwd();
41837
41891
  return null;
41838
41892
  }
41839
41893
  async function waitLoopCorePool(label) {
@@ -42141,7 +42195,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
42141
42195
  }
42142
42196
  if (!repoForPostCleanup) throw e;
42143
42197
  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;
42198
+ const commitMessage = bodyFile ? (0, import_node_fs47.readFileSync)(bodyFile, "utf8") : void 0;
42145
42199
  await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
42146
42200
  body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
42147
42201
  timeoutMs: GH_MUTATION_TIMEOUT_MS
@@ -42237,7 +42291,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
42237
42291
  localCleanup = await cleanupPrMergeLocalBranch(headRef, {
42238
42292
  beforeWorktrees,
42239
42293
  startingPath,
42240
- pathExists: (p) => (0, import_node_fs46.existsSync)(p),
42294
+ pathExists: (p) => (0, import_node_fs47.existsSync)(p),
42241
42295
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
42242
42296
  teardownWorktreeStage,
42243
42297
  deferredStore,
@@ -42815,12 +42869,12 @@ access.command("audit").description("audit collaborator roles + train-branch pus
42815
42869
  targets = resolution.targets;
42816
42870
  }
42817
42871
  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")) : {};
42872
+ const fileMatrix = (0, import_node_fs47.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs47.readFileSync)("access-matrix.json", "utf8")) : {};
42819
42873
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
42820
42874
  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: {} };
42875
+ const fileContracts = (0, import_node_fs47.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs47.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
42822
42876
  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")) : {};
42877
+ const sanctioned = (0, import_node_fs47.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs47.readFileSync)("access-matrix.json", "utf8")) : {};
42824
42878
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
42825
42879
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
42826
42880
  if (!report.ok) process.exitCode = 1;
@@ -42852,16 +42906,16 @@ function directoryBytes(path2) {
42852
42906
  let total = 0;
42853
42907
  let entries;
42854
42908
  try {
42855
- entries = (0, import_node_fs46.readdirSync)(path2, { withFileTypes: true });
42909
+ entries = (0, import_node_fs47.readdirSync)(path2, { withFileTypes: true });
42856
42910
  } catch {
42857
42911
  return 0;
42858
42912
  }
42859
42913
  for (const entry of entries) {
42860
- const child2 = (0, import_node_path43.join)(path2, entry.name);
42914
+ const child2 = (0, import_node_path44.join)(path2, entry.name);
42861
42915
  if (entry.isDirectory()) total += directoryBytes(child2);
42862
42916
  else {
42863
42917
  try {
42864
- total += (0, import_node_fs46.statSync)(child2).size;
42918
+ total += (0, import_node_fs47.statSync)(child2).size;
42865
42919
  } catch {
42866
42920
  }
42867
42921
  }
@@ -42869,25 +42923,25 @@ function directoryBytes(path2) {
42869
42923
  return total;
42870
42924
  }
42871
42925
  function listDirEntries(dir) {
42872
- return (0, import_node_fs46.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
42926
+ return (0, import_node_fs47.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
42873
42927
  }
42874
42928
  function readInstalledPluginRefs(configRoot) {
42875
42929
  const p = installedPluginsPathForConfig(configRoot);
42876
- if (!(0, import_node_fs46.existsSync)(p)) return [];
42930
+ if (!(0, import_node_fs47.existsSync)(p)) return [];
42877
42931
  try {
42878
- return installedPluginPaths((0, import_node_fs46.readFileSync)(p, "utf8"));
42932
+ return installedPluginPaths((0, import_node_fs47.readFileSync)(p, "utf8"));
42879
42933
  } catch {
42880
42934
  return null;
42881
42935
  }
42882
42936
  }
42883
42937
  function pluginCacheFsDeps(configRoot, dirBytes) {
42884
42938
  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),
42939
+ exists: (p) => (0, import_node_fs47.existsSync)(p),
42940
+ listVersionDirs: (root) => (0, import_node_fs47.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
42887
42941
  dirBytes,
42888
- listStagingDirs: (root) => (0, import_node_fs46.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
42942
+ listStagingDirs: (root) => (0, import_node_fs47.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
42889
42943
  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) };
42944
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path44.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs47.statSync)(p).mtimeMs) };
42891
42945
  } catch {
42892
42946
  return { name: d.name, mtimeMs: Date.now() };
42893
42947
  }
@@ -42901,10 +42955,10 @@ function stagingApplyFsGuard(configRoot) {
42901
42955
  return {
42902
42956
  referencedPaths: () => readInstalledPluginRefs(configRoot),
42903
42957
  mtimeMs: (name) => {
42904
- const p = (0, import_node_path43.join)(stagingRoot, name);
42905
- if (!(0, import_node_fs46.existsSync)(p)) return null;
42958
+ const p = (0, import_node_path44.join)(stagingRoot, name);
42959
+ if (!(0, import_node_fs47.existsSync)(p)) return null;
42906
42960
  try {
42907
- return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs46.statSync)(q).mtimeMs);
42961
+ return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs47.statSync)(q).mtimeMs);
42908
42962
  } catch {
42909
42963
  return null;
42910
42964
  }
@@ -42930,7 +42984,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
42930
42984
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
42931
42985
  );
42932
42986
  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;
42987
+ const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs47.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
42934
42988
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
42935
42989
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
42936
42990
  else console.log(renderPluginCachePlan(plan, result));
@@ -42938,7 +42992,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
42938
42992
  });
42939
42993
  function readReleaseCatchupState(path2) {
42940
42994
  try {
42941
- const parsed = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
42995
+ const parsed = JSON.parse((0, import_node_fs47.readFileSync)(path2, "utf8"));
42942
42996
  return typeof parsed?.checkedAt === "number" ? parsed : void 0;
42943
42997
  } catch {
42944
42998
  return void 0;
@@ -42946,8 +43000,8 @@ function readReleaseCatchupState(path2) {
42946
43000
  }
42947
43001
  function writeReleaseCatchupState(path2, state) {
42948
43002
  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)}
43003
+ (0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(path2), { recursive: true });
43004
+ (0, import_node_fs47.writeFileSync)(path2, `${JSON.stringify(state)}
42951
43005
  `);
42952
43006
  } catch {
42953
43007
  }