@mutmutco/claude-plugin 4.5.117 → 4.5.118

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.
package/cli/dist/main.cjs CHANGED
@@ -4751,7 +4751,7 @@ function useColor() {
4751
4751
  var program = new Command();
4752
4752
 
4753
4753
  // src/command-composition.ts
4754
- var import_node_fs55 = require("node:fs");
4754
+ var import_node_fs57 = require("node:fs");
4755
4755
  init_clean_exit();
4756
4756
  init_cli_shared();
4757
4757
 
@@ -5653,13 +5653,13 @@ function resolveVerbAliasShim(argv) {
5653
5653
  }
5654
5654
 
5655
5655
  // src/command-composition.ts
5656
- var import_node_os24 = require("node:os");
5657
- var import_node_path53 = require("node:path");
5656
+ var import_node_os25 = require("node:os");
5657
+ var import_node_path54 = require("node:path");
5658
5658
 
5659
5659
  // src/board-read.ts
5660
- var import_node_fs13 = require("node:fs");
5661
- var import_node_os9 = require("node:os");
5662
- var import_node_path11 = require("node:path");
5660
+ var import_node_fs14 = require("node:fs");
5661
+ var import_node_os10 = require("node:os");
5662
+ var import_node_path12 = require("node:path");
5663
5663
  init_cli_shared();
5664
5664
  init_github_client();
5665
5665
 
@@ -5667,21 +5667,35 @@ init_github_client();
5667
5667
  init_fetch_retry();
5668
5668
  init_client_version();
5669
5669
  var BOARD_SNAPSHOT_TIMEOUT_MS = 25e3;
5670
+ var BOARD_SNAPSHOT_EXIT_CODES = {
5671
+ "hub-unreachable": 20,
5672
+ "app-quota-exhausted": 21,
5673
+ refused: 22
5674
+ };
5675
+ var BoardSnapshotFailure = class extends Error {
5676
+ constructor(receipt) {
5677
+ super(receipt.reason);
5678
+ this.receipt = receipt;
5679
+ this.exitCode = BOARD_SNAPSHOT_EXIT_CODES[receipt.outcome];
5680
+ }
5681
+ receipt;
5682
+ exitCode;
5683
+ };
5670
5684
  function isSnapshotShape(body) {
5671
5685
  const b = body;
5672
5686
  const rate = b?.github?.rateLimit;
5673
5687
  const staleValid = b?.stale === void 0 || typeof b.stale === "object" && b.stale !== null && Number.isFinite(b.stale.ageMs) && b.stale.ageMs >= 0;
5674
- const githubValid = b?.github === void 0 || b.github.credential === "app_installation" && (rate === void 0 || Number.isFinite(rate?.limit) && Number.isFinite(rate?.remaining) && Number.isFinite(rate?.cost) && typeof rate?.resetAt === "string");
5688
+ const githubValid = b?.github === void 0 || b.github !== null && typeof b.github === "object" && b.github.credential === "app_installation" && (rate === void 0 || Number.isFinite(rate?.limit) && Number.isFinite(rate?.remaining) && Number.isFinite(rate?.cost) && typeof rate?.resetAt === "string");
5675
5689
  return Boolean(
5676
5690
  b && typeof b === "object" && typeof b.project?.id === "string" && typeof b.project?.title === "string" && typeof b.viewer === "string" && b.viewer.length > 0 && Array.isArray(b.nodes) && Array.isArray(b.writableRepos) && Array.isArray(b.unreadableRepos) && Array.isArray(b.pullRequests) && Array.isArray(b.warnings) && typeof b.partial === "boolean" && (b.source === void 0 || b.source === "live" || b.source === "cache") && (b.builtAt === void 0 || typeof b.builtAt === "string" && Number.isFinite(Date.parse(b.builtAt))) && (b.eventCursor === void 0 || Number.isInteger(b.eventCursor) && b.eventCursor >= 0) && githubValid && staleValid
5677
5691
  );
5678
5692
  }
5679
5693
  async function fetchHubBoardSnapshot(request, deps) {
5680
5694
  if (!deps.baseUrl) return { state: "unavailable", reason: "no Hub API URL (set MMI_HUB_URL or use a current MMI CLI/plugin build)" };
5681
- const token = await deps.token();
5682
- if (!token) return { state: "unavailable", reason: "no Hub session token (run `gh auth login`)" };
5683
5695
  let res;
5684
5696
  try {
5697
+ const token = await deps.token();
5698
+ if (!token) return { state: "unavailable", reason: "no Hub session token (run `gh auth login`)" };
5685
5699
  res = await fetchWithRetry(
5686
5700
  deps.fetch ?? fetch,
5687
5701
  `${deps.baseUrl.replace(/\/$/, "")}/board/snapshot`,
@@ -5715,10 +5729,26 @@ async function fetchHubBoardSnapshot(request, deps) {
5715
5729
  return {
5716
5730
  state: "unavailable",
5717
5731
  reason: `GitHub App quota exhausted${reset}`,
5732
+ appQuotaExhausted: true,
5733
+ pool: "graphql",
5734
+ ...typeof body2.resetAt === "string" ? { resetAt: body2.resetAt } : {},
5718
5735
  ...body2.github?.credential === "app_installation" && body2.github.resource === "graphql" && /^github-app-v1:[a-f0-9]{64}$/.test(body2.github.quotaScope ?? "") ? { quota: { status: "rate_limited", ...typeof body2.resetAt === "string" ? { resetAt: body2.resetAt } : {}, github: { credential: "app_installation", resource: "graphql", quotaScope: body2.github.quotaScope } } } : {}
5719
5736
  };
5720
5737
  }
5721
5738
  }
5739
+ if (res.status === 503) {
5740
+ const body2 = await res.json().catch(() => null);
5741
+ if (body2?.code === "github-rate-limited") {
5742
+ const reset = typeof body2.resetAt === "string" ? `; resets ${body2.resetAt}` : "; reset time unavailable";
5743
+ return {
5744
+ state: "unavailable",
5745
+ reason: `GitHub App allowance exhausted${reset}`,
5746
+ appQuotaExhausted: true,
5747
+ pool: "rest",
5748
+ ...typeof body2.resetAt === "string" ? { resetAt: body2.resetAt } : {}
5749
+ };
5750
+ }
5751
+ }
5722
5752
  if (!res.ok) return { state: "unavailable", reason: `board snapshot HTTP ${res.status}` };
5723
5753
  const body = await res.json().catch(() => null);
5724
5754
  if (!isSnapshotShape(body)) return { state: "unavailable", reason: "malformed board snapshot response" };
@@ -5816,6 +5846,18 @@ var activeQuotaScope;
5816
5846
  function activeAppQuotaScope() {
5817
5847
  return activeQuotaScope;
5818
5848
  }
5849
+ async function readAppVaultSecret(read) {
5850
+ try {
5851
+ return await read();
5852
+ } catch (e) {
5853
+ const reason = e.message;
5854
+ if (/^(Hub GitHub App allowance used up|rate limited)/.test(reason)) {
5855
+ throw new AppActorError(`app actor: the vault could not read the App credentials because GitHub is rate-limited, not a denial: ${reason}`, "mint-failed");
5856
+ }
5857
+ if (/^authority refused|\(HTTP 404\b/.test(reason)) return null;
5858
+ throw new AppActorError(`app actor: the vault read of the App credentials failed, not a denial: ${reason}`, "mint-failed");
5859
+ }
5860
+ }
5819
5861
  async function mintInstallationToken(deps) {
5820
5862
  const [appId, installationId, privateKey] = await Promise.all(APP_VAULT_KEYS.map((k) => deps.fetchSecret(k)));
5821
5863
  if (!appId || !installationId || !privateKey) {
@@ -6298,6 +6340,93 @@ function isReleaseShaDeployEnumerationCandidate(row, nonDeployEvents) {
6298
6340
 
6299
6341
  // src/pr-checks-rest.ts
6300
6342
  init_github_quota();
6343
+
6344
+ // src/rest-etag-cache.ts
6345
+ var import_node_crypto5 = require("node:crypto");
6346
+ var import_node_fs11 = require("node:fs");
6347
+ var import_node_os4 = require("node:os");
6348
+ var import_node_path9 = require("node:path");
6349
+ var MAX_AGE_MS = 24 * 60 * 6e4;
6350
+ var MAX_ENTRIES = 256;
6351
+ var MAX_BYTES = 16 * 1024 * 1024;
6352
+ var MAX_ENTRY_BYTES = 1024 * 1024;
6353
+ function restEtagCacheDir() {
6354
+ if (process.env.MMI_REST_ETAG_CACHE_DIR) return process.env.MMI_REST_ETAG_CACHE_DIR;
6355
+ return process.platform === "win32" ? (0, import_node_path9.join)(process.env.LOCALAPPDATA || (0, import_node_path9.join)((0, import_node_os4.homedir)(), "AppData", "Local"), "MMI Future", "mmi-cli", "rest-etags") : (0, import_node_path9.join)(process.env.XDG_CACHE_HOME || (0, import_node_path9.join)((0, import_node_os4.homedir)(), ".cache"), "mmi-cli", "rest-etags");
6356
+ }
6357
+ function entryPath(dir, key) {
6358
+ return (0, import_node_path9.join)(dir, `${(0, import_node_crypto5.createHash)("sha256").update(key).digest("hex")}.json`);
6359
+ }
6360
+ function readRestEtag(key, dir = restEtagCacheDir()) {
6361
+ if (dir === "off") return void 0;
6362
+ try {
6363
+ const path2 = entryPath(dir, key);
6364
+ if ((0, import_node_fs11.statSync)(path2).size > MAX_ENTRY_BYTES) return void 0;
6365
+ const entry = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
6366
+ const age = Date.now() - entry.storedAt;
6367
+ if (typeof entry.etag === "string" && entry.etag && !/[\r\n]/.test(entry.etag) && typeof entry.body === "string" && Number.isFinite(entry.storedAt) && age >= 0 && age <= MAX_AGE_MS) return entry;
6368
+ } catch {
6369
+ }
6370
+ return void 0;
6371
+ }
6372
+ function deleteRestEtag(key, dir = restEtagCacheDir()) {
6373
+ if (dir === "off") return;
6374
+ try {
6375
+ (0, import_node_fs11.rmSync)(entryPath(dir, key), { force: true });
6376
+ } catch {
6377
+ }
6378
+ }
6379
+ function prune(dir) {
6380
+ const now = Date.now();
6381
+ const files = (0, import_node_fs11.readdirSync)(dir).filter((name) => /^[a-f0-9]{64}\.json(?:\.tmp-.+)?$/.test(name)).flatMap((name) => {
6382
+ try {
6383
+ const path2 = (0, import_node_path9.join)(dir, name);
6384
+ const stat4 = (0, import_node_fs11.statSync)(path2);
6385
+ if (now - stat4.mtimeMs > MAX_AGE_MS) {
6386
+ (0, import_node_fs11.rmSync)(path2, { force: true });
6387
+ return [];
6388
+ }
6389
+ return name.endsWith(".json") ? [{ path: path2, size: stat4.size, at: stat4.mtimeMs }] : [];
6390
+ } catch {
6391
+ return [];
6392
+ }
6393
+ }).sort((a, b) => a.at - b.at);
6394
+ let bytes = files.reduce((sum, f) => sum + f.size, 0);
6395
+ let count = files.length;
6396
+ for (const file of files) {
6397
+ if (count <= MAX_ENTRIES && bytes <= MAX_BYTES) break;
6398
+ try {
6399
+ (0, import_node_fs11.rmSync)(file.path, { force: true });
6400
+ bytes -= file.size;
6401
+ count--;
6402
+ } catch {
6403
+ }
6404
+ }
6405
+ }
6406
+ function writeRestEtag(key, entry, dir = restEtagCacheDir()) {
6407
+ if (dir === "off") return;
6408
+ const path2 = entryPath(dir, key);
6409
+ const tmp = `${path2}.tmp-${process.pid}-${(0, import_node_crypto5.randomUUID)()}`;
6410
+ try {
6411
+ const data = JSON.stringify({ etag: entry.etag, body: entry.body, storedAt: Date.now() });
6412
+ if (Buffer.byteLength(data) > MAX_ENTRY_BYTES) {
6413
+ deleteRestEtag(key, dir);
6414
+ return;
6415
+ }
6416
+ (0, import_node_fs11.mkdirSync)(dir, { recursive: true, mode: 448 });
6417
+ (0, import_node_fs11.writeFileSync)(tmp, data, { mode: 384, flag: "wx" });
6418
+ (0, import_node_fs11.renameSync)(tmp, path2);
6419
+ prune(dir);
6420
+ } catch {
6421
+ } finally {
6422
+ try {
6423
+ (0, import_node_fs11.rmSync)(tmp, { force: true });
6424
+ } catch {
6425
+ }
6426
+ }
6427
+ }
6428
+
6429
+ // src/pr-checks-rest.ts
6301
6430
  var REST_GH_TIMEOUT_MS = 2e4;
6302
6431
  var pollTokenProvider;
6303
6432
  var pollTokenOnce;
@@ -6382,8 +6511,9 @@ function observedCorePool(source, nowMs) {
6382
6511
  async function defaultGhApi(args, env = process.env) {
6383
6512
  const appToken = await pollToken();
6384
6513
  const source = appToken ? "app" : "user";
6385
- const key = `${source}\0${args.join("\0")}`;
6386
- const cached = etagCache.get(key);
6514
+ const key = `${source}\0${env.GH_HOST || "github.com"}\0${args.join("\0")}`;
6515
+ const cached = etagCache.get(key) ?? readRestEtag(key);
6516
+ if (cached) etagCache.set(key, cached);
6387
6517
  let stdout;
6388
6518
  try {
6389
6519
  ({ stdout } = await execFileP("gh", ["api", "--include", ...cached ? ["-H", `If-None-Match: ${cached.etag}`] : [], ...args], {
@@ -6397,31 +6527,37 @@ async function defaultGhApi(args, env = process.env) {
6397
6527
  } catch (e) {
6398
6528
  const out = e.stdout;
6399
6529
  const errOut = typeof out === "string" ? out : void 0;
6400
- const status = errOut !== void 0 ? parseIncludedOutput(errOut).status : void 0;
6530
+ const status2 = errOut !== void 0 ? parseIncludedOutput(errOut).status : void 0;
6401
6531
  if (errOut !== void 0) notePoolHeaders(source, errOut, Date.now());
6402
- if (cached && status === 304) {
6532
+ if (cached && status2 === 304) {
6403
6533
  lastPollSource = source;
6404
6534
  return cached.body;
6405
6535
  }
6406
- if (status === 403 || status === 429) {
6536
+ if (status2 === 403 || status2 === 429) {
6407
6537
  const path2 = args.filter((a) => !a.startsWith("-")).join(" ") || args.join(" ");
6408
6538
  const refusal = errOut !== void 0 ? describeRefusal(errOut) : "no rate-limit headers or message";
6409
- if (status === 403 && /Resource not accessible by integration/i.test(refusal)) {
6539
+ if (status2 === 403 && /Resource not accessible by integration/i.test(refusal)) {
6410
6540
  throw new Error(
6411
6541
  `poll read refused: App token lacks permission for ${path2} (HTTP 403, response: ${refusal}) \u2014 reads never fall back to the owner's token (#8030); add the permission to APP_POLL_PERMISSIONS / the App installation`
6412
6542
  );
6413
6543
  }
6414
6544
  throw Object.assign(new Error(
6415
- `poll read refused on the ${source} pool (HTTP ${status}, response: ${refusal}) \u2014 reads stay on the ${source === "app" ? "App" : "ambient identity"} (#8030); the wait re-arms after reset`
6416
- ), { status, stdout: errOut, stderr: e.stderr });
6545
+ `poll read refused on the ${source} pool (HTTP ${status2}, response: ${refusal}) \u2014 reads stay on the ${source === "app" ? "App" : "ambient identity"} (#8030); the wait re-arms after reset`
6546
+ ), { status: status2, stdout: errOut, stderr: e.stderr });
6417
6547
  }
6418
6548
  throw e;
6419
6549
  }
6420
- const { body, etag, pages } = parseIncludedOutput(stdout);
6550
+ const { body, status, etag, pages } = parseIncludedOutput(stdout);
6421
6551
  notePoolHeaders(source, stdout, Date.now());
6422
6552
  lastPollSource = source;
6423
- if (etag && pages === 1) etagCache.set(key, { etag, body });
6424
- else etagCache.delete(key);
6553
+ if (cached && status === 304) return cached.body;
6554
+ if (status === 200 && etag && pages === 1) {
6555
+ etagCache.set(key, { etag, body });
6556
+ writeRestEtag(key, { etag, body });
6557
+ } else {
6558
+ etagCache.delete(key);
6559
+ deleteRestEtag(key);
6560
+ }
6425
6561
  return body;
6426
6562
  }
6427
6563
  function classifyCheckRun(run) {
@@ -8526,12 +8662,12 @@ async function fetchSchedulesList(deps) {
8526
8662
  return null;
8527
8663
  }
8528
8664
  }
8529
- async function fetchOrgConfig(deps) {
8665
+ async function fetchOrgConfig(deps, spendMinutes) {
8530
8666
  if (!deps.baseUrl) return null;
8531
8667
  const token = await deps.token();
8532
8668
  if (!token) return null;
8533
8669
  try {
8534
- const res = await retriedFetch(deps, `${deps.baseUrl.replace(/\/$/, "")}${ORG_CONFIG_PATH}`, {
8670
+ const res = await retriedFetch(deps, `${deps.baseUrl.replace(/\/$/, "")}${ORG_CONFIG_PATH}${spendMinutes === void 0 ? "" : `?github-spend-minutes=${spendMinutes}`}`, {
8535
8671
  method: "GET",
8536
8672
  headers: { Authorization: `Bearer ${token}` }
8537
8673
  });
@@ -9765,14 +9901,14 @@ async function secretsPreflight(deps, opts) {
9765
9901
 
9766
9902
  // src/secrets-execution.ts
9767
9903
  var import_node_child_process4 = require("node:child_process");
9768
- var import_node_os5 = require("node:os");
9904
+ var import_node_os6 = require("node:os");
9769
9905
  init_clean_exit();
9770
9906
 
9771
9907
  // src/gh-create.ts
9772
9908
  var import_promises = require("node:fs/promises");
9773
- var import_node_os4 = require("node:os");
9774
- var import_node_path9 = require("node:path");
9775
- var import_node_crypto5 = require("node:crypto");
9909
+ var import_node_os5 = require("node:os");
9910
+ var import_node_path10 = require("node:path");
9911
+ var import_node_crypto6 = require("node:crypto");
9776
9912
 
9777
9913
  // src/board-priority.ts
9778
9914
  var BOARD_PRIORITY_NAMES = ["Urgent", "High", "Medium", "Low"];
@@ -9858,9 +9994,9 @@ async function bodyArgsViaFile(args, deps = {}) {
9858
9994
  const write = deps.write ?? import_promises.writeFile;
9859
9995
  const remove2 = deps.remove ?? import_promises.unlink;
9860
9996
  const ensureDir = deps.ensureDir ?? import_promises.mkdir;
9861
- const dir = deps.dir ?? (0, import_node_os4.tmpdir)();
9862
- const file = (0, import_node_path9.join)(dir, `mmi-gh-body-${process.pid}-${(0, import_node_crypto5.randomBytes)(4).toString("hex")}.md`);
9863
- await ensureDir((0, import_node_path9.dirname)(file), { recursive: true }).catch(() => {
9997
+ const dir = deps.dir ?? (0, import_node_os5.tmpdir)();
9998
+ const file = (0, import_node_path10.join)(dir, `mmi-gh-body-${process.pid}-${(0, import_node_crypto6.randomBytes)(4).toString("hex")}.md`);
9999
+ await ensureDir((0, import_node_path10.dirname)(file), { recursive: true }).catch(() => {
9864
10000
  });
9865
10001
  await write(file, args[i + 1], "utf8");
9866
10002
  return {
@@ -10188,8 +10324,8 @@ async function defaultRestCreatePr(exec2, input, deps = {}) {
10188
10324
  const write = deps.write ?? import_promises.writeFile;
10189
10325
  const remove2 = deps.remove ?? import_promises.unlink;
10190
10326
  const ensureDir = deps.ensureDir ?? import_promises.mkdir;
10191
- const dir = deps.dir ?? (0, import_node_os4.tmpdir)();
10192
- const file = (0, import_node_path9.join)(dir, `mmi-rest-pr-${process.pid}-${(0, import_node_crypto5.randomBytes)(4).toString("hex")}.json`);
10327
+ const dir = deps.dir ?? (0, import_node_os5.tmpdir)();
10328
+ const file = (0, import_node_path10.join)(dir, `mmi-rest-pr-${process.pid}-${(0, import_node_crypto6.randomBytes)(4).toString("hex")}.json`);
10193
10329
  const payload = {
10194
10330
  title: input.title,
10195
10331
  head: input.head,
@@ -10197,7 +10333,7 @@ async function defaultRestCreatePr(exec2, input, deps = {}) {
10197
10333
  };
10198
10334
  if (input.base) payload.base = input.base;
10199
10335
  if (input.draft) payload.draft = true;
10200
- await ensureDir((0, import_node_path9.dirname)(file), { recursive: true }).catch(() => {
10336
+ await ensureDir((0, import_node_path10.dirname)(file), { recursive: true }).catch(() => {
10201
10337
  });
10202
10338
  await write(file, JSON.stringify(payload), "utf8");
10203
10339
  const args = [
@@ -11133,7 +11269,7 @@ function resolveSpawnTarget(command, args, platform2 = process.platform) {
11133
11269
  }
11134
11270
  function spawnExitCode(status, signal) {
11135
11271
  if (status != null) return status;
11136
- const signo = signal ? import_node_os5.constants.signals[signal] : void 0;
11272
+ const signo = signal ? import_node_os6.constants.signals[signal] : void 0;
11137
11273
  return signo ? 128 + signo : 1;
11138
11274
  }
11139
11275
  function defaultSpawn(command, args, env) {
@@ -11589,14 +11725,14 @@ function findDuplicateLesson(source, openLessons) {
11589
11725
  }
11590
11726
 
11591
11727
  // src/session-identity.ts
11592
- var import_node_crypto6 = require("node:crypto");
11593
- var import_node_os8 = require("node:os");
11728
+ var import_node_crypto7 = require("node:crypto");
11729
+ var import_node_os9 = require("node:os");
11594
11730
 
11595
11731
  // src/plugin-guard-io.ts
11596
- var import_node_fs12 = require("node:fs");
11732
+ var import_node_fs13 = require("node:fs");
11597
11733
  var import_node_child_process5 = require("node:child_process");
11598
- var import_node_path10 = require("node:path");
11599
- var import_node_os7 = require("node:os");
11734
+ var import_node_path11 = require("node:path");
11735
+ var import_node_os8 = require("node:os");
11600
11736
 
11601
11737
  // src/marketplace-autoupdate.ts
11602
11738
  var KNOWN_MARKETPLACES_RELATIVE = [".claude", "plugins", "known_marketplaces.json"];
@@ -11740,8 +11876,8 @@ function buildPluginGuardLine(state, opts = {}) {
11740
11876
  }
11741
11877
 
11742
11878
  // src/host-doc-lock.ts
11743
- var import_node_fs11 = require("node:fs");
11744
- var import_node_os6 = require("node:os");
11879
+ var import_node_fs12 = require("node:fs");
11880
+ var import_node_os7 = require("node:os");
11745
11881
  var SHARED_DOC_LOCK_STALE_MS = 3e4;
11746
11882
  var SHARED_DOC_LOCK_ATTEMPTS = 50;
11747
11883
  var SHARED_DOC_LOCK_INTERVAL_MS = 100;
@@ -11754,7 +11890,7 @@ function lockContent(options) {
11754
11890
  }
11755
11891
  function readHolder(lockPath) {
11756
11892
  try {
11757
- const parsed = JSON.parse((0, import_node_fs11.readFileSync)(lockPath, "utf8"));
11893
+ const parsed = JSON.parse((0, import_node_fs12.readFileSync)(lockPath, "utf8"));
11758
11894
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
11759
11895
  return parsed;
11760
11896
  } catch {
@@ -11766,7 +11902,7 @@ function lockAgeMs(lockPath, now) {
11766
11902
  const declared = typeof holder?.acquiredAt === "string" ? Date.parse(holder.acquiredAt) : Number.NaN;
11767
11903
  if (!Number.isNaN(declared)) return Math.max(0, now - declared);
11768
11904
  try {
11769
- return Math.max(0, now - (0, import_node_fs11.statSync)(lockPath).mtimeMs);
11905
+ return Math.max(0, now - (0, import_node_fs12.statSync)(lockPath).mtimeMs);
11770
11906
  } catch {
11771
11907
  return 0;
11772
11908
  }
@@ -11781,7 +11917,7 @@ function acquireSharedDocLock(documentPath, options) {
11781
11917
  const staleAfterMs = options.staleAfterMs ?? SHARED_DOC_LOCK_STALE_MS;
11782
11918
  const attempts = options.attempts ?? SHARED_DOC_LOCK_ATTEMPTS;
11783
11919
  const intervalMs = options.intervalMs ?? SHARED_DOC_LOCK_INTERVAL_MS;
11784
- const identity = { owner: options.owner, pid: process.pid, host: options.host ?? (0, import_node_os6.hostname)(), acquiredAt: (/* @__PURE__ */ new Date()).toISOString() };
11920
+ const identity = { owner: options.owner, pid: process.pid, host: options.host ?? (0, import_node_os7.hostname)(), acquiredAt: (/* @__PURE__ */ new Date()).toISOString() };
11785
11921
  const content = lockContent(identity);
11786
11922
  const sleep2 = (ms) => {
11787
11923
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
@@ -11789,9 +11925,9 @@ function acquireSharedDocLock(documentPath, options) {
11789
11925
  for (let attempt = 0; attempt < attempts; attempt += 1) {
11790
11926
  let fd;
11791
11927
  try {
11792
- fd = (0, import_node_fs11.openSync)(lockPath, "wx");
11793
- (0, import_node_fs11.writeSync)(fd, content);
11794
- (0, import_node_fs11.closeSync)(fd);
11928
+ fd = (0, import_node_fs12.openSync)(lockPath, "wx");
11929
+ (0, import_node_fs12.writeSync)(fd, content);
11930
+ (0, import_node_fs12.closeSync)(fd);
11795
11931
  return {
11796
11932
  documentPath,
11797
11933
  lockPath,
@@ -11804,11 +11940,11 @@ function acquireSharedDocLock(documentPath, options) {
11804
11940
  } catch (error) {
11805
11941
  if (fd !== void 0) {
11806
11942
  try {
11807
- (0, import_node_fs11.closeSync)(fd);
11943
+ (0, import_node_fs12.closeSync)(fd);
11808
11944
  } catch {
11809
11945
  }
11810
11946
  try {
11811
- (0, import_node_fs11.unlinkSync)(lockPath);
11947
+ (0, import_node_fs12.unlinkSync)(lockPath);
11812
11948
  } catch {
11813
11949
  }
11814
11950
  }
@@ -11817,12 +11953,12 @@ function acquireSharedDocLock(documentPath, options) {
11817
11953
  if (lockAgeMs(lockPath, Date.now()) >= staleAfterMs) {
11818
11954
  const aside = `${lockPath}.stale-${Date.now()}`;
11819
11955
  try {
11820
- (0, import_node_fs11.renameSync)(lockPath, aside);
11956
+ (0, import_node_fs12.renameSync)(lockPath, aside);
11821
11957
  } catch {
11822
11958
  continue;
11823
11959
  }
11824
11960
  try {
11825
- (0, import_node_fs11.rmSync)(aside, { force: true });
11961
+ (0, import_node_fs12.rmSync)(aside, { force: true });
11826
11962
  } catch {
11827
11963
  }
11828
11964
  continue;
@@ -11835,7 +11971,7 @@ function releaseSharedDocLock(handle) {
11835
11971
  try {
11836
11972
  const holder = readHolder(handle.lockPath);
11837
11973
  if (holder && holder.owner === handle.owner && Number(holder.pid) === handle.pid) {
11838
- (0, import_node_fs11.unlinkSync)(handle.lockPath);
11974
+ (0, import_node_fs12.unlinkSync)(handle.lockPath);
11839
11975
  }
11840
11976
  } catch {
11841
11977
  }
@@ -11982,25 +12118,25 @@ function runHostBin(bin, args, opts) {
11982
12118
  const argv = isWin ? ["/c", bin, ...args] : args;
11983
12119
  return step ? execFileHard(file, argv, { ...shared, step }) : execFileP(file, argv, shared);
11984
12120
  }
11985
- function hermesConfigRoot(env = process.env, home = (0, import_node_os7.homedir)(), platform2 = process.platform) {
12121
+ function hermesConfigRoot(env = process.env, home = (0, import_node_os8.homedir)(), platform2 = process.platform) {
11986
12122
  if (env.HERMES_HOME?.trim()) return env.HERMES_HOME.trim();
11987
- if (platform2 === "win32") return (0, import_node_path10.join)(env.LOCALAPPDATA?.trim() || (0, import_node_path10.join)(home, "AppData", "Local"), "hermes");
11988
- return (0, import_node_path10.join)(home, ".hermes");
12123
+ if (platform2 === "win32") return (0, import_node_path11.join)(env.LOCALAPPDATA?.trim() || (0, import_node_path11.join)(home, "AppData", "Local"), "hermes");
12124
+ return (0, import_node_path11.join)(home, ".hermes");
11989
12125
  }
11990
- function surfaceConfigRoot(surface, env = process.env, home = (0, import_node_os7.homedir)()) {
11991
- if (surface === "codex") return env.CODEX_HOME?.trim() || (0, import_node_path10.join)(home, ".codex");
12126
+ function surfaceConfigRoot(surface, env = process.env, home = (0, import_node_os8.homedir)()) {
12127
+ if (surface === "codex") return env.CODEX_HOME?.trim() || (0, import_node_path11.join)(home, ".codex");
11992
12128
  if (surface === "hermes") return hermesConfigRoot(env, home);
11993
12129
  if (surface === "jervcode") {
11994
- return env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim() || (0, import_node_path10.join)(home, ".jerv", "agent");
12130
+ return env.JERVCODE_CODING_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim() || (0, import_node_path11.join)(home, ".jerv", "agent");
11995
12131
  }
11996
- return (0, import_node_path10.join)(home, ".claude");
12132
+ return (0, import_node_path11.join)(home, ".claude");
11997
12133
  }
11998
12134
  var installedPluginsPath = (surface = detectSurface(process.env)) => {
11999
- return (0, import_node_path10.join)(surfaceConfigRoot(surface), "plugins", "installed_plugins.json");
12135
+ return (0, import_node_path11.join)(surfaceConfigRoot(surface), "plugins", "installed_plugins.json");
12000
12136
  };
12001
12137
  function readInstalledPlugins(surface = detectSurface(process.env)) {
12002
12138
  try {
12003
- return JSON.parse((0, import_node_fs12.readFileSync)(installedPluginsPath(surface), "utf8"));
12139
+ return JSON.parse((0, import_node_fs13.readFileSync)(installedPluginsPath(surface), "utf8"));
12004
12140
  } catch {
12005
12141
  return null;
12006
12142
  }
@@ -12009,15 +12145,15 @@ function marketplaceCloneCandidates(surface, home, env = process.env) {
12009
12145
  if (surface === "codex") {
12010
12146
  const root = surfaceConfigRoot(surface, env, home);
12011
12147
  return [
12012
- (0, import_node_path10.join)(root, ".tmp", "marketplaces", CODEX_MARKETPLACE),
12013
- (0, import_node_path10.join)(root, "plugins", "marketplaces", CODEX_MARKETPLACE)
12148
+ (0, import_node_path11.join)(root, ".tmp", "marketplaces", CODEX_MARKETPLACE),
12149
+ (0, import_node_path11.join)(root, "plugins", "marketplaces", CODEX_MARKETPLACE)
12014
12150
  ];
12015
12151
  }
12016
12152
  if (surface === "hermes") return [];
12017
12153
  if (surface === "jervcode") return [];
12018
- return [(0, import_node_path10.join)(home, ".claude", "plugins", "marketplaces", "mutmutco")];
12154
+ return [(0, import_node_path11.join)(home, ".claude", "plugins", "marketplaces", "mutmutco")];
12019
12155
  }
12020
- function marketplaceClonePresent(surface, home, exists = import_node_fs12.existsSync, env = process.env) {
12156
+ function marketplaceClonePresent(surface, home, exists = import_node_fs13.existsSync, env = process.env) {
12021
12157
  return marketplaceCloneCandidates(surface, home, env).some(exists);
12022
12158
  }
12023
12159
  function runHostBinSync(bin, args) {
@@ -12059,26 +12195,26 @@ async function fetchNpmReleasedVersion() {
12059
12195
  }
12060
12196
  }
12061
12197
  var JERVCODE_NPM_PACKAGE = "@mutmutco/pi-plugin";
12062
- function jervcodeAgentDirs(env = process.env, home = (0, import_node_os7.homedir)()) {
12198
+ function jervcodeAgentDirs(env = process.env, home = (0, import_node_os8.homedir)()) {
12063
12199
  const primary = surfaceConfigRoot("jervcode", env, home);
12064
- const legacy = (0, import_node_path10.join)(home, ".pi", "agent");
12200
+ const legacy = (0, import_node_path11.join)(home, ".pi", "agent");
12065
12201
  const dirs = [primary];
12066
12202
  if (legacy !== primary) dirs.push(legacy);
12067
- return dirs.filter((dir) => (0, import_node_fs12.existsSync)(dir));
12203
+ return dirs.filter((dir) => (0, import_node_fs13.existsSync)(dir));
12068
12204
  }
12069
12205
  function readPiSettings(path2) {
12070
- if (!(0, import_node_fs12.existsSync)(path2)) return void 0;
12206
+ if (!(0, import_node_fs13.existsSync)(path2)) return void 0;
12071
12207
  try {
12072
- const parsed = JSON.parse((0, import_node_fs12.readFileSync)(path2, "utf8"));
12208
+ const parsed = JSON.parse((0, import_node_fs13.readFileSync)(path2, "utf8"));
12073
12209
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
12074
12210
  return parsed;
12075
12211
  } catch {
12076
12212
  return null;
12077
12213
  }
12078
12214
  }
12079
- function mmiPiPackageEntry(env = process.env, home = (0, import_node_os7.homedir)()) {
12215
+ function mmiPiPackageEntry(env = process.env, home = (0, import_node_os8.homedir)()) {
12080
12216
  for (const dir of jervcodeAgentDirs(env, home)) {
12081
- const settings = readPiSettings((0, import_node_path10.join)(dir, "settings.json"));
12217
+ const settings = readPiSettings((0, import_node_path11.join)(dir, "settings.json"));
12082
12218
  const entries = Array.isArray(settings?.packages) ? settings.packages : [];
12083
12219
  for (const entry of entries) {
12084
12220
  if (typeof entry !== "string") continue;
@@ -12088,10 +12224,10 @@ function mmiPiPackageEntry(env = process.env, home = (0, import_node_os7.homedir
12088
12224
  return null;
12089
12225
  }
12090
12226
  var LEGACY_MMI_PI_PATH = /[/\\]mutmutco[/\\]mmi[/\\]\d+\.\d+\.\d+[/\\]\.pi-plugin[/\\]?$/i;
12091
- function legacyMmiPiPathEntries(env = process.env, home = (0, import_node_os7.homedir)()) {
12227
+ function legacyMmiPiPathEntries(env = process.env, home = (0, import_node_os8.homedir)()) {
12092
12228
  const found = [];
12093
12229
  for (const dir of jervcodeAgentDirs(env, home)) {
12094
- const settings = readPiSettings((0, import_node_path10.join)(dir, "settings.json"));
12230
+ const settings = readPiSettings((0, import_node_path11.join)(dir, "settings.json"));
12095
12231
  const entries = Array.isArray(settings?.packages) ? settings.packages : [];
12096
12232
  for (const entry of entries) {
12097
12233
  if (typeof entry === "string" && LEGACY_MMI_PI_PATH.test(entry) && !found.includes(entry)) found.push(entry);
@@ -12099,37 +12235,37 @@ function legacyMmiPiPathEntries(env = process.env, home = (0, import_node_os7.ho
12099
12235
  }
12100
12236
  return found;
12101
12237
  }
12102
- function mmiPiPackageRoot(env = process.env, home = (0, import_node_os7.homedir)()) {
12238
+ function mmiPiPackageRoot(env = process.env, home = (0, import_node_os8.homedir)()) {
12103
12239
  for (const dir of jervcodeAgentDirs(env, home)) {
12104
- const root = (0, import_node_path10.join)(dir, "npm", "node_modules", ...JERVCODE_NPM_PACKAGE.split("/"));
12105
- if ((0, import_node_fs12.existsSync)((0, import_node_path10.join)(root, "package.json"))) return root;
12240
+ const root = (0, import_node_path11.join)(dir, "npm", "node_modules", ...JERVCODE_NPM_PACKAGE.split("/"));
12241
+ if ((0, import_node_fs13.existsSync)((0, import_node_path11.join)(root, "package.json"))) return root;
12106
12242
  }
12107
12243
  return null;
12108
12244
  }
12109
- function installedJervCodePackageVersion(env = process.env, home = (0, import_node_os7.homedir)()) {
12245
+ function installedJervCodePackageVersion(env = process.env, home = (0, import_node_os8.homedir)()) {
12110
12246
  const root = mmiPiPackageRoot(env, home);
12111
12247
  if (!root) return void 0;
12112
12248
  try {
12113
- const manifest = JSON.parse((0, import_node_fs12.readFileSync)((0, import_node_path10.join)(root, "package.json"), "utf8"));
12249
+ const manifest = JSON.parse((0, import_node_fs13.readFileSync)((0, import_node_path11.join)(root, "package.json"), "utf8"));
12114
12250
  return typeof manifest.version === "string" ? manifest.version : void 0;
12115
12251
  } catch {
12116
12252
  return void 0;
12117
12253
  }
12118
12254
  }
12119
- function mmiPiPackageHealthy(env = process.env, home = (0, import_node_os7.homedir)()) {
12255
+ function mmiPiPackageHealthy(env = process.env, home = (0, import_node_os8.homedir)()) {
12120
12256
  const root = mmiPiPackageRoot(env, home);
12121
- return Boolean(root && (0, import_node_fs12.existsSync)((0, import_node_path10.join)(root, "skills", "bootstrap", "SKILL.md")));
12257
+ return Boolean(root && (0, import_node_fs13.existsSync)((0, import_node_path11.join)(root, "skills", "bootstrap", "SKILL.md")));
12122
12258
  }
12123
12259
  function piDoctorEnv(agentDir) {
12124
12260
  return { ...process.env, PI_CODING_AGENT_DIR: agentDir };
12125
12261
  }
12126
- function hermesPluginRoot(env = process.env, home = (0, import_node_os7.homedir)()) {
12127
- return (0, import_node_path10.join)(hermesConfigRoot(env, home), "plugins", "mmi");
12262
+ function hermesPluginRoot(env = process.env, home = (0, import_node_os8.homedir)()) {
12263
+ return (0, import_node_path11.join)(hermesConfigRoot(env, home), "plugins", "mmi");
12128
12264
  }
12129
- function hermesPluginTreeHealthy(root, exists = import_node_fs12.existsSync) {
12130
- if (!["plugin.yaml", "__init__.py"].every((file) => exists((0, import_node_path10.join)(root, file)))) return false;
12265
+ function hermesPluginTreeHealthy(root, exists = import_node_fs13.existsSync) {
12266
+ if (!["plugin.yaml", "__init__.py"].every((file) => exists((0, import_node_path11.join)(root, file)))) return false;
12131
12267
  try {
12132
- return (0, import_node_fs12.statSync)((0, import_node_path10.join)(root, "skills")).isDirectory();
12268
+ return (0, import_node_fs13.statSync)((0, import_node_path11.join)(root, "skills")).isDirectory();
12133
12269
  } catch {
12134
12270
  return false;
12135
12271
  }
@@ -12144,12 +12280,12 @@ function snapshotPluginGuardInput(surface = detectSurface(process.env), isOrgRep
12144
12280
  // Codex's native projection is authoritative; its legacy installed_plugins.json may be empty
12145
12281
  // while `plugin list --json` proves the managed plugin installed (#6111).
12146
12282
  installRecordPresent: surface === "codex" ? codexStatus?.installed === true : hasUserInstallRecord(installed, MMI_PLUGIN_ID) || hasProjectInstallRecord(installed, MMI_PLUGIN_ID, process.cwd()) || // #4188: jervcode's install record is the settings-file packages[] entry itself.
12147
- surface === "jervcode" && piEntry !== null || surface === "hermes" && (0, import_node_fs12.existsSync)(hermesPluginRoot()),
12283
+ surface === "jervcode" && piEntry !== null || surface === "hermes" && (0, import_node_fs13.existsSync)(hermesPluginRoot()),
12148
12284
  // JervCode's settings entry and native local surfaces have no marketplace clone.
12149
- marketplaceClonePresent: surface === "jervcode" || surface === "hermes" ? true : marketplaceClonePresent(surface, (0, import_node_os7.homedir)()),
12285
+ marketplaceClonePresent: surface === "jervcode" || surface === "hermes" ? true : marketplaceClonePresent(surface, (0, import_node_os8.homedir)()),
12150
12286
  pluginCachePresent: surface === "jervcode" ? mmiPiPackageHealthy() : surface === "hermes" ? hermesPluginTreeHealthy(hermesPluginRoot()) : surface === "codex" ? Boolean(
12151
- codexStatus?.installed && codexStatus.enabled && codexStatus.version && (0, import_node_fs12.existsSync)((0, import_node_path10.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", codexStatus.version))
12152
- ) : (0, import_node_fs12.existsSync)((0, import_node_path10.join)(root, "plugins", "cache", "mutmutco", "mmi"))
12287
+ codexStatus?.installed && codexStatus.enabled && codexStatus.version && (0, import_node_fs13.existsSync)((0, import_node_path11.join)(root, "plugins", "cache", CODEX_MARKETPLACE, "mmi", codexStatus.version))
12288
+ ) : (0, import_node_fs13.existsSync)((0, import_node_path11.join)(root, "plugins", "cache", "mutmutco", "mmi"))
12153
12289
  };
12154
12290
  }
12155
12291
  async function runPluginCli(bin, args, log) {
@@ -12196,7 +12332,7 @@ async function runHealSteps(host, tableSteps, deps) {
12196
12332
  const refSupported = needsRefProbe ? await marketplaceAddRefSupported(host) : true;
12197
12333
  const { steps } = adaptHealStepsForRefSupport(tableSteps, refSupported);
12198
12334
  if (deps.banner) log(deps.banner(refSupported));
12199
- const pinsPath = (0, import_node_path10.join)((0, import_node_os7.homedir)(), ...KNOWN_MARKETPLACES_RELATIVE);
12335
+ const pinsPath = (0, import_node_path11.join)((0, import_node_os8.homedir)(), ...KNOWN_MARKETPLACES_RELATIVE);
12200
12336
  const pins = host === "claude" ? captureMarketplacePins(readKnownMarketplacesFile(pinsPath), [MMI_MARKETPLACE_NAME, JERV_MARKETPLACE_NAME]) : /* @__PURE__ */ new Map();
12201
12337
  let failure;
12202
12338
  try {
@@ -12307,7 +12443,7 @@ async function healActivePluginForDoctor(surface = detectSurface(process.env), o
12307
12443
  }
12308
12444
  function readKnownMarketplacesFile(path2) {
12309
12445
  try {
12310
- return (0, import_node_fs12.existsSync)(path2) ? (0, import_node_fs12.readFileSync)(path2, "utf8") : void 0;
12446
+ return (0, import_node_fs13.existsSync)(path2) ? (0, import_node_fs13.readFileSync)(path2, "utf8") : void 0;
12311
12447
  } catch {
12312
12448
  return void 0;
12313
12449
  }
@@ -12341,11 +12477,11 @@ function writeMarketplacePinsOnDisk(path2, pins, succeeded, failedVerb, declineW
12341
12477
  if (declined) return declined;
12342
12478
  const tmp = `${path2}.tmp-${process.pid}`;
12343
12479
  try {
12344
- (0, import_node_fs12.writeFileSync)(tmp, next, "utf8");
12345
- (0, import_node_fs12.renameSync)(tmp, path2);
12480
+ (0, import_node_fs13.writeFileSync)(tmp, next, "utf8");
12481
+ (0, import_node_fs13.renameSync)(tmp, path2);
12346
12482
  } catch {
12347
12483
  try {
12348
- (0, import_node_fs12.rmSync)(tmp, { force: true });
12484
+ (0, import_node_fs13.rmSync)(tmp, { force: true });
12349
12485
  } catch {
12350
12486
  }
12351
12487
  return `could NOT ${failedVerb} ${[...pins.keys()].join(", ")} \u2014 set it by hand`;
@@ -12473,7 +12609,7 @@ function readSessionIdSource(env) {
12473
12609
  var synthesizedSessionId;
12474
12610
  function fallbackSessionId(surface) {
12475
12611
  if (!synthesizedSessionId) {
12476
- synthesizedSessionId = `${SYNTH_SESSION_PREFIX}${surface}-${process.pid}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
12612
+ synthesizedSessionId = `${SYNTH_SESSION_PREFIX}${surface}-${process.pid}-${(0, import_node_crypto7.randomBytes)(3).toString("hex")}`;
12477
12613
  }
12478
12614
  return synthesizedSessionId;
12479
12615
  }
@@ -12482,7 +12618,7 @@ function describeSessionIdentity(env = process.env) {
12482
12618
  return {
12483
12619
  session: readSessionId(env) ?? fallbackSessionId(surface),
12484
12620
  surface,
12485
- host: (0, import_node_os8.hostname)()
12621
+ host: (0, import_node_os9.hostname)()
12486
12622
  };
12487
12623
  }
12488
12624
  function formatSessionIdentity(identity) {
@@ -13182,7 +13318,7 @@ function renderBoardSource() {
13182
13318
  return "source: live";
13183
13319
  }
13184
13320
  async function collectBoardPreferringSnapshot(cfg, options, deps) {
13185
- if (options.snapshotOnly && !deps.snapshot) throw new Error("--snapshot-only needs the Hub snapshot transport (not with --direct)");
13321
+ if (options.snapshotOnly && !deps.snapshot) throw new BoardSnapshotFailure({ ok: false, outcome: "hub-unreachable", reason: "--snapshot-only needs the Hub snapshot transport (not with --direct)" });
13186
13322
  const attempt = deps.snapshot ? await fetchHubBoardSnapshot(
13187
13323
  {
13188
13324
  owner: cfg.projectOwner,
@@ -13195,6 +13331,7 @@ async function collectBoardPreferringSnapshot(cfg, options, deps) {
13195
13331
  deps.snapshot
13196
13332
  ) : void 0;
13197
13333
  if (attempt?.state === "refused") {
13334
+ if (options.snapshotOnly) throw new BoardSnapshotFailure({ ok: false, outcome: "refused", reason: attempt.reason });
13198
13335
  throw new Error(attempt.reason);
13199
13336
  }
13200
13337
  if (attempt?.state === "ok") {
@@ -13224,7 +13361,16 @@ async function collectBoardPreferringSnapshot(cfg, options, deps) {
13224
13361
  };
13225
13362
  }
13226
13363
  if (options.snapshotOnly && attempt?.state === "unavailable") {
13227
- throw Object.assign(new Error(`Hub board snapshot unavailable (${attempt.reason}) \u2014 --snapshot-only refuses the direct user-auth fallback`), { quota: attempt.quota });
13364
+ throw Object.assign(new BoardSnapshotFailure({
13365
+ ok: false,
13366
+ outcome: attempt.appQuotaExhausted ? "app-quota-exhausted" : "hub-unreachable",
13367
+ reason: `Hub board snapshot unavailable (${attempt.reason}) \u2014 --snapshot-only refuses the direct user-auth fallback`,
13368
+ ...attempt.resetAt ? { resetAt: attempt.resetAt } : {},
13369
+ ...attempt.pool ? { pool: attempt.pool } : {}
13370
+ }), { quota: attempt.quota });
13371
+ }
13372
+ if (attempt?.state === "unavailable" && attempt.appQuotaExhausted) {
13373
+ throw Object.assign(new Error(`Hub board snapshot unavailable (${attempt.reason}) \u2014 the personal-token fallback is refused while the org App allowance is exhausted; retry after the reset`), { quota: attempt.quota });
13228
13374
  }
13229
13375
  const collected = await collectBoardItems(cfg, { repo: options.repo, allowPartial: options.allowPartial, activeOnly: true }, deps);
13230
13376
  if (attempt?.state === "unavailable") {
@@ -13907,7 +14053,7 @@ var CLAIM_SESSION_ACTIVITY_MS = 30 * 6e4;
13907
14053
  var CLAIM_SESSION_PROBE_CACHE_MS = 6e4;
13908
14054
  var claimSessionProbeCache = /* @__PURE__ */ new Map();
13909
14055
  function probeLocalClaimSession(marker, now = Date.now()) {
13910
- if (!marker.session || !marker.host || marker.host.toLowerCase() !== (0, import_node_os9.hostname)().toLowerCase()) return void 0;
14056
+ if (!marker.session || !marker.host || marker.host.toLowerCase() !== (0, import_node_os10.hostname)().toLowerCase()) return void 0;
13911
14057
  if (!marker.surface?.toLowerCase().startsWith("claude")) return void 0;
13912
14058
  const cacheKey = `${marker.host.toLowerCase()}/${marker.session}`;
13913
14059
  const cached = claimSessionProbeCache.get(cacheKey);
@@ -13916,17 +14062,17 @@ function probeLocalClaimSession(marker, now = Date.now()) {
13916
14062
  claimSessionProbeCache.set(cacheKey, { checkedAt: now, state });
13917
14063
  return state;
13918
14064
  };
13919
- const root = (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".claude", "projects");
14065
+ const root = (0, import_node_path12.join)((0, import_node_os10.homedir)(), ".claude", "projects");
13920
14066
  try {
13921
14067
  const wanted = `${marker.session}.jsonl`.toLowerCase();
13922
14068
  const pending = [root];
13923
14069
  while (pending.length) {
13924
14070
  const dir = pending.pop();
13925
- for (const entry of (0, import_node_fs13.readdirSync)(dir, { withFileTypes: true })) {
13926
- const path2 = (0, import_node_path11.join)(dir, entry.name);
14071
+ for (const entry of (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true })) {
14072
+ const path2 = (0, import_node_path12.join)(dir, entry.name);
13927
14073
  if (entry.isDirectory()) pending.push(path2);
13928
14074
  else if (entry.isFile() && entry.name.toLowerCase() === wanted) {
13929
- return remember(now - (0, import_node_fs13.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
14075
+ return remember(now - (0, import_node_fs14.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
13930
14076
  }
13931
14077
  }
13932
14078
  }
@@ -15179,7 +15325,7 @@ async function propagateMayAutoMerge(repo, repoClass, rest) {
15179
15325
  }
15180
15326
 
15181
15327
  // src/bootstrap-apply.ts
15182
- var import_node_crypto7 = require("node:crypto");
15328
+ var import_node_crypto8 = require("node:crypto");
15183
15329
 
15184
15330
  // src/bootstrap-seeds.ts
15185
15331
  var PLACEHOLDER_RE = /\{\{([A-Z0-9_]+)\}\}/g;
@@ -15418,13 +15564,13 @@ function planManagedGitignore(current) {
15418
15564
  }
15419
15565
 
15420
15566
  // src/docs-index-command.ts
15421
- var import_node_fs15 = require("node:fs");
15422
- var import_node_path13 = require("node:path");
15567
+ var import_node_fs16 = require("node:fs");
15568
+ var import_node_path14 = require("node:path");
15423
15569
 
15424
15570
  // src/doc-refs-core.ts
15425
15571
  var import_node_child_process6 = require("node:child_process");
15426
- var import_node_fs14 = require("node:fs");
15427
- var import_node_path12 = require("node:path");
15572
+ var import_node_fs15 = require("node:fs");
15573
+ var import_node_path13 = require("node:path");
15428
15574
  var PIN_RE = /<!--\s*pinned by\s+([^:]+?)\s*:\s*"([^"]+)"[^"]*-->/;
15429
15575
  var PIN_MENTION_RE = /<!--\s*pinned by\b/;
15430
15576
  var FWD_RE = /<!--\s*forward-ref:\s*(\S+?)\s*-->/;
@@ -15483,7 +15629,7 @@ function checkPins(root, readFile10, docs) {
15483
15629
  findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
15484
15630
  continue;
15485
15631
  }
15486
- const source = readFile10((0, import_node_path12.join)(root, pin.file));
15632
+ const source = readFile10((0, import_node_path13.join)(root, pin.file));
15487
15633
  if (source == null) {
15488
15634
  findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
15489
15635
  continue;
@@ -15546,11 +15692,11 @@ function checkRefs(root, deps, docs) {
15546
15692
  for (const { ref } of extractRefs(markdown)) allFirstSegments.add(refFirstSegment(ref));
15547
15693
  }
15548
15694
  const tracked = allFirstSegments.size ? deps.trackedFirstSegments?.([...allFirstSegments]) ?? null : null;
15549
- const firstVerifiable = (first) => tracked ? tracked.has(first) : exists((0, import_node_path12.join)(root, first));
15695
+ const firstVerifiable = (first) => tracked ? tracked.has(first) : exists((0, import_node_path13.join)(root, first));
15550
15696
  const candidates = [];
15551
15697
  const direct = [];
15552
15698
  for (const [doc, markdown] of Object.entries(docs)) {
15553
- const docDir = import_node_path12.posix.dirname(doc);
15699
+ const docDir = import_node_path13.posix.dirname(doc);
15554
15700
  const base = docDir === "." ? "" : docDir;
15555
15701
  const covered = /* @__PURE__ */ new Set();
15556
15702
  const markers = [];
@@ -15559,21 +15705,21 @@ function checkRefs(root, deps, docs) {
15559
15705
  direct.push({ kind: "malformed-forward-ref", doc, line: fwd.line, detail: fwd.text });
15560
15706
  continue;
15561
15707
  }
15562
- const docRel = import_node_path12.posix.normalize(import_node_path12.posix.join(base, fwd.target));
15563
- const rootRel = import_node_path12.posix.normalize(fwd.target.replace(/^\/+/, ""));
15708
+ const docRel = import_node_path13.posix.normalize(import_node_path13.posix.join(base, fwd.target));
15709
+ const rootRel = import_node_path13.posix.normalize(fwd.target.replace(/^\/+/, ""));
15564
15710
  markers.push({ target: fwd.target, line: fwd.line, docRel, rootRel });
15565
15711
  covered.add(docRel);
15566
15712
  covered.add(rootRel);
15567
15713
  }
15568
15714
  const links = extractLinks(markdown).map(({ target, line }) => {
15569
- const resolved = import_node_path12.posix.normalize(import_node_path12.posix.join(base, target));
15570
- return { target, line, resolved, missing: !exists((0, import_node_path12.join)(root, resolved)) };
15715
+ const resolved = import_node_path13.posix.normalize(import_node_path13.posix.join(base, target));
15716
+ return { target, line, resolved, missing: !exists((0, import_node_path13.join)(root, resolved)) };
15571
15717
  });
15572
15718
  for (const marker of markers) {
15573
15719
  const coversMissing = links.some(
15574
15720
  (l) => l.missing && (l.resolved === marker.docRel || l.resolved === marker.rootRel)
15575
15721
  );
15576
- if (!coversMissing && (exists((0, import_node_path12.join)(root, marker.docRel)) || exists((0, import_node_path12.join)(root, marker.rootRel)))) {
15722
+ if (!coversMissing && (exists((0, import_node_path13.join)(root, marker.docRel)) || exists((0, import_node_path13.join)(root, marker.rootRel)))) {
15577
15723
  direct.push({
15578
15724
  kind: "stale-forward-ref",
15579
15725
  doc,
@@ -15584,7 +15730,7 @@ function checkRefs(root, deps, docs) {
15584
15730
  }
15585
15731
  for (const { ref, line } of extractRefs(markdown)) {
15586
15732
  if (!firstVerifiable(refFirstSegment(ref))) continue;
15587
- if (!exists((0, import_node_path12.join)(root, ref))) candidates.push({ kind: "missing-path", doc, line, detail: ref });
15733
+ if (!exists((0, import_node_path13.join)(root, ref))) candidates.push({ kind: "missing-path", doc, line, detail: ref });
15588
15734
  }
15589
15735
  for (const { target, line, resolved, missing } of links) {
15590
15736
  if (resolved.startsWith("..")) {
@@ -15632,24 +15778,24 @@ function checkCommands(docs, commandPaths) {
15632
15778
  return { ok: findings.length === 0, findings, warnings: [] };
15633
15779
  }
15634
15780
  function readFileOrNull(path2) {
15635
- return (0, import_node_fs14.existsSync)(path2) ? (0, import_node_fs14.readFileSync)(path2, "utf8") : null;
15781
+ return (0, import_node_fs15.existsSync)(path2) ? (0, import_node_fs15.readFileSync)(path2, "utf8") : null;
15636
15782
  }
15637
15783
  function walk(dir, root, out) {
15638
- for (const entry of (0, import_node_fs14.readdirSync)(dir)) {
15639
- const full = (0, import_node_path12.join)(dir, entry);
15640
- if ((0, import_node_fs14.statSync)(full).isDirectory()) walk(full, root, out);
15784
+ for (const entry of (0, import_node_fs15.readdirSync)(dir)) {
15785
+ const full = (0, import_node_path13.join)(dir, entry);
15786
+ if ((0, import_node_fs15.statSync)(full).isDirectory()) walk(full, root, out);
15641
15787
  else if (entry.endsWith(".md")) out.push(full.slice(root.length + 1).replaceAll("\\", "/"));
15642
15788
  }
15643
15789
  return out;
15644
15790
  }
15645
15791
  function defaultListDocs(root) {
15646
15792
  const docs = ["docs", "skills/org-guide", "skills/mmi-help"].flatMap((path2) => {
15647
- const directory = (0, import_node_path12.join)(root, path2);
15648
- return (0, import_node_fs14.existsSync)(directory) ? walk(directory, root, []) : [];
15793
+ const directory = (0, import_node_path13.join)(root, path2);
15794
+ return (0, import_node_fs15.existsSync)(directory) ? walk(directory, root, []) : [];
15649
15795
  }).filter(
15650
15796
  (rel) => !SKIP_WALK.some((skip) => rel.startsWith(skip))
15651
15797
  );
15652
- return [...ROOT_DOCS.filter((rel) => (0, import_node_fs14.existsSync)((0, import_node_path12.join)(root, rel))), ...docs];
15798
+ return [...ROOT_DOCS.filter((rel) => (0, import_node_fs15.existsSync)((0, import_node_path13.join)(root, rel))), ...docs];
15653
15799
  }
15654
15800
  var CHECK_IGNORE_MAX_BUFFER = 32 * 1024 * 1024;
15655
15801
  function defaultIsIgnored(root, relPaths, exec2 = import_node_child_process6.execFileSync) {
@@ -15701,7 +15847,7 @@ function defaultTrackedFirstSegments(root, firstSegments, exec2 = import_node_ch
15701
15847
  }
15702
15848
  function runDocRefs(root, deps = {}) {
15703
15849
  const readFile10 = deps.readFile ?? readFileOrNull;
15704
- const exists = deps.exists ?? import_node_fs14.existsSync;
15850
+ const exists = deps.exists ?? import_node_fs15.existsSync;
15705
15851
  const listDocs = deps.listDocs ?? defaultListDocs;
15706
15852
  const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
15707
15853
  const trackedFirstSegments = deps.trackedFirstSegments ?? ((segs) => defaultTrackedFirstSegments(root, segs));
@@ -15709,7 +15855,7 @@ function runDocRefs(root, deps = {}) {
15709
15855
  const walked = listDocs(root);
15710
15856
  const ignoredDocs = walked.length ? isIgnored(walked) : /* @__PURE__ */ new Set();
15711
15857
  const docs = Object.fromEntries(
15712
- walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile10((0, import_node_path12.join)(root, rel))]).filter(([, body]) => body != null)
15858
+ walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile10((0, import_node_path13.join)(root, rel))]).filter(([, body]) => body != null)
15713
15859
  );
15714
15860
  const refResult = checkRefs(root, { exists, isIgnored, trackedFirstSegments }, docs);
15715
15861
  const findings = [
@@ -15816,31 +15962,31 @@ function walkMarkdown(dir) {
15816
15962
  const stack = [dir];
15817
15963
  while (stack.length) {
15818
15964
  const current = stack.pop();
15819
- for (const entry of (0, import_node_fs15.readdirSync)(current, { withFileTypes: true })) {
15820
- const full = (0, import_node_path13.join)(current, entry.name);
15965
+ for (const entry of (0, import_node_fs16.readdirSync)(current, { withFileTypes: true })) {
15966
+ const full = (0, import_node_path14.join)(current, entry.name);
15821
15967
  if (entry.isDirectory()) {
15822
15968
  stack.push(full);
15823
15969
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
15824
- out.push((0, import_node_path13.relative)(dir, full).split(import_node_path13.sep).join("/"));
15970
+ out.push((0, import_node_path14.relative)(dir, full).split(import_node_path14.sep).join("/"));
15825
15971
  }
15826
15972
  }
15827
15973
  }
15828
15974
  return out;
15829
15975
  }
15830
15976
  function createDocsIndexDeps(repoRoot2) {
15831
- const docsDir = (0, import_node_path13.join)(repoRoot2, "docs");
15832
- const indexPath = (0, import_node_path13.join)(repoRoot2, DOCS_INDEX_PATH);
15977
+ const docsDir = (0, import_node_path14.join)(repoRoot2, "docs");
15978
+ const indexPath = (0, import_node_path14.join)(repoRoot2, DOCS_INDEX_PATH);
15833
15979
  return {
15834
15980
  listDocs: () => {
15835
- if (!(0, import_node_fs15.existsSync)(docsDir)) return [];
15981
+ if (!(0, import_node_fs16.existsSync)(docsDir)) return [];
15836
15982
  const walked = walkMarkdown(docsDir).filter(isRoutableDocsPath);
15837
15983
  if (!walked.length) return [];
15838
15984
  const ignored = defaultIsIgnored(repoRoot2, walked.map((rel) => `docs/${rel}`));
15839
15985
  return walked.filter((rel) => !ignored.has(`docs/${rel}`)).sort();
15840
15986
  },
15841
- readDoc: (relPath) => (0, import_node_fs15.readFileSync)((0, import_node_path13.join)(docsDir, relPath), "utf8"),
15842
- readIndex: () => (0, import_node_fs15.existsSync)(indexPath) ? (0, import_node_fs15.readFileSync)(indexPath, "utf8") : null,
15843
- writeIndex: (content) => (0, import_node_fs15.writeFileSync)(indexPath, content, "utf8")
15987
+ readDoc: (relPath) => (0, import_node_fs16.readFileSync)((0, import_node_path14.join)(docsDir, relPath), "utf8"),
15988
+ readIndex: () => (0, import_node_fs16.existsSync)(indexPath) ? (0, import_node_fs16.readFileSync)(indexPath, "utf8") : null,
15989
+ writeIndex: (content) => (0, import_node_fs16.writeFileSync)(indexPath, content, "utf8")
15844
15990
  };
15845
15991
  }
15846
15992
 
@@ -16446,7 +16592,7 @@ function planSeedAction(seed, exists) {
16446
16592
  return exists ? { target: seed.target, action: "update", ownership: "org", reason: "org-owned, refresh to current" } : { target: seed.target, action: "create", ownership: "org", reason: "org-owned, missing" };
16447
16593
  }
16448
16594
  var GATE_RENDER_NOTE = "# Rendered from the registry gate config by mmi-cli devops bootstrap apply <repo> --only gate.yml --from-config; edit the config, not this file.\n";
16449
- var gateHash = (body) => (0, import_node_crypto7.createHash)("sha256").update(body, "utf8").digest("hex");
16595
+ var gateHash = (body) => (0, import_node_crypto8.createHash)("sha256").update(body, "utf8").digest("hex");
16450
16596
  function parseGateRenderStamp(content) {
16451
16597
  const match = /^# mmi-gate-render: sha256=([a-f0-9]{64})\n/.exec(content);
16452
16598
  return match ? { hash: match[1], body: content.slice(match[0].length) } : null;
@@ -16753,8 +16899,8 @@ function contentPutInputArgs(repo, path2, inputFile) {
16753
16899
  }
16754
16900
 
16755
16901
  // src/train-apply-contracts.ts
16756
- var import_node_fs16 = require("node:fs");
16757
- var import_node_path14 = require("node:path");
16902
+ var import_node_fs17 = require("node:fs");
16903
+ var import_node_path15 = require("node:path");
16758
16904
  function reduceFollowUpOutcomes(outcomes) {
16759
16905
  if (outcomes.includes("failure")) return "failure";
16760
16906
  if (outcomes.includes("unresolved")) return "unresolved";
@@ -16834,7 +16980,7 @@ async function resolveFoldPaths(deps, model) {
16834
16980
  if (model === "vercel") return [];
16835
16981
  const helper = "scripts/release-distribution.mjs";
16836
16982
  if (model === "hub-serverless" || model === "registry-publish") {
16837
- if ((0, import_node_fs16.existsSync)(helper)) {
16983
+ if ((0, import_node_fs17.existsSync)(helper)) {
16838
16984
  let out;
16839
16985
  try {
16840
16986
  out = await deps.run("node", [helper, "changed-files"]);
@@ -16973,7 +17119,7 @@ async function restoreMainNpmPackIdentities(deps, version) {
16973
17119
  if (mainBom.version !== version) return void 0;
16974
17120
  let localBom;
16975
17121
  try {
16976
- localBom = JSON.parse((0, import_node_fs16.readFileSync)(bomPath, "utf8"));
17122
+ localBom = JSON.parse((0, import_node_fs17.readFileSync)(bomPath, "utf8"));
16977
17123
  } catch (e) {
16978
17124
  throw new Error(
16979
17125
  `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).`
@@ -16991,14 +17137,14 @@ async function restoreMainNpmPackIdentities(deps, version) {
16991
17137
  restored += 1;
16992
17138
  }
16993
17139
  if (restored === 0) return void 0;
16994
- (0, import_node_fs16.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
17140
+ (0, import_node_fs17.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
16995
17141
  `);
16996
17142
  return `restored ${restored} npm-pack BOM identit${restored === 1 ? "y" : "ies"} from origin/main (#4503)`;
16997
17143
  }
16998
17144
  function publishVisibilityFor(surfaceId) {
16999
17145
  let raw;
17000
17146
  try {
17001
- raw = (0, import_node_fs16.readFileSync)("surfaces.json", "utf8");
17147
+ raw = (0, import_node_fs17.readFileSync)("surfaces.json", "utf8");
17002
17148
  } catch (e) {
17003
17149
  if (e.code === "ENOENT") return "unknown";
17004
17150
  throw trainReadFailure(
@@ -17019,7 +17165,7 @@ function publishVisibilityFor(surfaceId) {
17019
17165
  }
17020
17166
  function npmPackArtifactName(packagePath) {
17021
17167
  try {
17022
- const pkg = JSON.parse((0, import_node_fs16.readFileSync)((0, import_node_path14.join)(packagePath, "package.json"), "utf8"));
17168
+ const pkg = JSON.parse((0, import_node_fs17.readFileSync)((0, import_node_path15.join)(packagePath, "package.json"), "utf8"));
17023
17169
  return pkg.name || void 0;
17024
17170
  } catch {
17025
17171
  return void 0;
@@ -17028,7 +17174,7 @@ function npmPackArtifactName(packagePath) {
17028
17174
  async function refuseDivergentPublishedNpmPack(deps, version) {
17029
17175
  let localBom;
17030
17176
  try {
17031
- localBom = JSON.parse((0, import_node_fs16.readFileSync)("distribution-bom.json", "utf8"));
17177
+ localBom = JSON.parse((0, import_node_fs17.readFileSync)("distribution-bom.json", "utf8"));
17032
17178
  } catch (e) {
17033
17179
  throw new Error(
17034
17180
  `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).`
@@ -17173,8 +17319,8 @@ function assertGitBashOnWindowsForJervHubRelease(repo, platform2 = process.platf
17173
17319
  }
17174
17320
 
17175
17321
  // src/train-apply-correlation.ts
17176
- var import_node_fs18 = require("node:fs");
17177
- var import_node_path16 = require("node:path");
17322
+ var import_node_fs19 = require("node:fs");
17323
+ var import_node_path17 = require("node:path");
17178
17324
 
17179
17325
  // src/fleet-lockstep-enforce.ts
17180
17326
  init_github_client();
@@ -17939,10 +18085,10 @@ var rollout_plan_default = {
17939
18085
  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)."
17940
18086
  },
17941
18087
  baseline: {
17942
- version: "4.5.117",
17943
- tag: "v4.5.117",
17944
- commit: "8ec1a0aa6b67",
17945
- npm: "@mutmutco/cli@4.5.117"
18088
+ version: "4.5.118",
18089
+ tag: "v4.5.118",
18090
+ commit: "4dc2fb2beb2b",
18091
+ npm: "@mutmutco/cli@4.5.118"
17946
18092
  },
17947
18093
  exitCriterion: "fleet-n-of-n",
17948
18094
  hubOnlyShortcut: "forbidden",
@@ -17959,14 +18105,14 @@ var rollout_plan_default = {
17959
18105
  repo: "mutmutco/mmi-hub",
17960
18106
  role: "canary",
17961
18107
  schedule: "train",
17962
- v3Target: "v4.5.117"
18108
+ v3Target: "v4.5.118"
17963
18109
  }
17964
18110
  ],
17965
18111
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
17966
18112
  rollback: {
17967
18113
  independent: true,
17968
- mechanism: "npm dist-tag latest -> 4.5.117 and redeploy the Hub Lambda from tag v4.5.117 (8ec1a0aa6b67); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17969
- v3Target: "v4.5.117 (@mutmutco/cli@4.5.117, tag commit 8ec1a0aa6b67 \u2014 last known-good release carrying the repo-index v4-only contract)"
18114
+ mechanism: "npm dist-tag latest -> 4.5.118 and redeploy the Hub Lambda from tag v4.5.118 (4dc2fb2beb2b); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
18115
+ v3Target: "v4.5.118 (@mutmutco/cli@4.5.118, tag commit 4dc2fb2beb2b \u2014 last known-good release carrying the repo-index v4-only contract)"
17970
18116
  }
17971
18117
  },
17972
18118
  {
@@ -18300,13 +18446,13 @@ function resolveIssueViewGhFields(normalized) {
18300
18446
  }
18301
18447
 
18302
18448
  // src/utf8-receipt.ts
18303
- var import_node_fs17 = require("node:fs");
18304
- var import_node_path15 = require("node:path");
18449
+ var import_node_fs18 = require("node:fs");
18450
+ var import_node_path16 = require("node:path");
18305
18451
  function writeUtf8Receipt(path2, text) {
18306
- (0, import_node_fs17.mkdirSync)((0, import_node_path15.dirname)(path2), { recursive: true });
18452
+ (0, import_node_fs18.mkdirSync)((0, import_node_path16.dirname)(path2), { recursive: true });
18307
18453
  const body = text.endsWith("\n") ? text : `${text}
18308
18454
  `;
18309
- (0, import_node_fs17.writeFileSync)(path2, body, "utf8");
18455
+ (0, import_node_fs18.writeFileSync)(path2, body, "utf8");
18310
18456
  return Buffer.byteLength(body, "utf8");
18311
18457
  }
18312
18458
 
@@ -20174,7 +20320,7 @@ function resolveReleaseAbortNpmPackage(meta, repo) {
20174
20320
  if (isHubControlRepo(repo)) return "@mutmutco/cli";
20175
20321
  const publishDir = typeof meta.publishDir === "string" && meta.publishDir.trim() ? meta.publishDir.trim() : ".";
20176
20322
  try {
20177
- const pkg = JSON.parse((0, import_node_fs18.readFileSync)((0, import_node_path16.join)(publishDir, "package.json"), "utf8"));
20323
+ const pkg = JSON.parse((0, import_node_fs19.readFileSync)((0, import_node_path17.join)(publishDir, "package.json"), "utf8"));
20178
20324
  const name = pkg.name?.trim();
20179
20325
  if (!name) throw new Error("missing name field");
20180
20326
  return name;
@@ -21102,9 +21248,9 @@ function parseVerifyBroker(stdout) {
21102
21248
  }
21103
21249
 
21104
21250
  // src/train-apply-deploy.ts
21105
- var import_node_fs19 = require("node:fs");
21106
- var import_node_os10 = require("node:os");
21107
- var import_node_path17 = require("node:path");
21251
+ var import_node_fs20 = require("node:fs");
21252
+ var import_node_os11 = require("node:os");
21253
+ var import_node_path18 = require("node:path");
21108
21254
 
21109
21255
  // src/vercel-deployments.ts
21110
21256
  var TERMINAL = /* @__PURE__ */ new Set(["success", "failure", "error", "inactive"]);
@@ -21243,7 +21389,7 @@ function mmiGetRedeployCommand(repo) {
21243
21389
  }
21244
21390
  function readLocalLauncherVersion(root = process.cwd()) {
21245
21391
  try {
21246
- const raw = (0, import_node_fs19.readFileSync)((0, import_node_path17.join)(root, "cli", "package.json"), "utf8");
21392
+ const raw = (0, import_node_fs20.readFileSync)((0, import_node_path18.join)(root, "cli", "package.json"), "utf8");
21247
21393
  const version = JSON.parse(raw).version;
21248
21394
  return typeof version === "string" && version.trim() ? version.trim() : null;
21249
21395
  } catch {
@@ -21252,7 +21398,7 @@ function readLocalLauncherVersion(root = process.cwd()) {
21252
21398
  }
21253
21399
  function readServedChannelUrl(product = HUB_SERVED_PRODUCT, root = process.cwd()) {
21254
21400
  try {
21255
- const raw = (0, import_node_fs19.readFileSync)((0, import_node_path17.join)(root, "config", `product.${product}.json`), "utf8");
21401
+ const raw = (0, import_node_fs20.readFileSync)((0, import_node_path18.join)(root, "config", `product.${product}.json`), "utf8");
21256
21402
  const host = JSON.parse(raw).host;
21257
21403
  if (typeof host !== "string" || !host.trim()) return null;
21258
21404
  return `${host.trim().replace(/\/+$/, "")}/release/version`;
@@ -21686,13 +21832,13 @@ async function runTaggedJervGatewayLocalWrapper(deps, tag, tagSha) {
21686
21832
  const reason = error instanceof Error ? error.message : String(error);
21687
21833
  throw new Error(`could not extract ${JERV_GATEWAY_RELEASE_DEPLOY_SCRIPT} from tagged commit ${tagSha.slice(0, 12)}: ${reason}`);
21688
21834
  }
21689
- const dir = (0, import_node_fs19.mkdtempSync)((0, import_node_path17.join)((0, import_node_os10.tmpdir)(), "jerv-gateway-release-deploy-"));
21690
- const extracted = (0, import_node_path17.join)(dir, "jerv-gateway-release-deploy.sh");
21835
+ const dir = (0, import_node_fs20.mkdtempSync)((0, import_node_path18.join)((0, import_node_os11.tmpdir)(), "jerv-gateway-release-deploy-"));
21836
+ const extracted = (0, import_node_path18.join)(dir, "jerv-gateway-release-deploy.sh");
21691
21837
  try {
21692
- (0, import_node_fs19.writeFileSync)(extracted, script, "utf8");
21838
+ (0, import_node_fs20.writeFileSync)(extracted, script, "utf8");
21693
21839
  return await deps.run("bash", [extracted, "--tag", tag]);
21694
21840
  } finally {
21695
- (0, import_node_fs19.rmSync)(dir, { recursive: true, force: true });
21841
+ (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
21696
21842
  }
21697
21843
  }
21698
21844
  async function appendJervGatewayReleaseDeploy(deps, repo, tag, tagSha, dispatch) {
@@ -22158,28 +22304,46 @@ async function runTenantControl(deps, options) {
22158
22304
  const watch = options.watch ?? tenantControlWatches(action);
22159
22305
  const base = { command: "tenant-control", repo, stage, action };
22160
22306
  const since = (deps.now ?? Date.now)();
22161
- const d = await deps.dispatchTenantControl({ repo, stage, action, lines: options.lines, edge: options.edge, since: options.logSince, until: options.logUntil, task: options.task, artifact: options.artifact, confirmDataLoss: options.confirmDataLoss });
22162
- if (!d.ok) {
22163
- const transport = d.category === "transport-failed";
22164
- return {
22165
- ...base,
22166
- dispatched: false,
22167
- conclusion: "failure",
22168
- category: action === "retire" ? transport ? "transport-failed" : "dispatch-rejected" : void 0,
22169
- note: transport ? `runtime tenant control ${action} dispatch failed (transport) \u2014 safe to retry` : `runtime tenant control ${action} rejected: ${d.error ?? "request rejected by the Hub"}`
22170
- };
22171
- }
22172
- const correlated = await correlateControlRun(deps, since, [stage, action, ...action === "run-task" && options.task ? [options.task] : []]);
22173
- if (correlated.read === "failed") {
22174
- return {
22175
- ...base,
22176
- dispatched: true,
22177
- conclusion: "failure",
22178
- category: action === "retire" ? "wait-timeout" : void 0,
22179
- note: `runtime tenant control ${action} dispatched, but its run could not be READ: ${correlated.error} \u2014 the run's outcome is unverified, not absent; check the Actions tab or retry once the read succeeds (#4713)`
22180
- };
22307
+ let runId;
22308
+ let runUrl;
22309
+ if (options.resume != null) {
22310
+ if (action !== "run-task") throw new Error("runtime tenant control: --resume is valid only for run-task");
22311
+ let view;
22312
+ try {
22313
+ view = JSON.parse(await deps.run("gh", ["run", "view", String(options.resume), "--repo", HUB_REPO2, "--json", "workflowName,displayTitle,url"]));
22314
+ } catch (e) {
22315
+ throw new Error(`runtime tenant control: run ${options.resume} could not be READ: ${e.message}`);
22316
+ }
22317
+ const f = (view.displayTitle ?? "").split(" ");
22318
+ if (view.workflowName !== "tenant-control" || f[0] !== "tenant-control" || f[1] !== (repo.split("/")[1] ?? "").toLowerCase() || f[2] !== stage || f[3] !== "run-task") {
22319
+ throw new Error(`runtime tenant control: run ${options.resume} is not a tenant-control run-task run for ${repo} ${stage} (title: ${view.displayTitle ?? "unreadable"}) \u2014 refusing to resume it`);
22320
+ }
22321
+ runId = options.resume;
22322
+ runUrl = view.url;
22323
+ } else {
22324
+ const d = await deps.dispatchTenantControl({ repo, stage, action, lines: options.lines, edge: options.edge, since: options.logSince, until: options.logUntil, task: options.task, artifact: options.artifact, confirmDataLoss: options.confirmDataLoss });
22325
+ if (!d.ok) {
22326
+ const transport = d.category === "transport-failed";
22327
+ return {
22328
+ ...base,
22329
+ dispatched: false,
22330
+ conclusion: "failure",
22331
+ category: action === "retire" ? transport ? "transport-failed" : "dispatch-rejected" : void 0,
22332
+ note: transport ? `runtime tenant control ${action} dispatch failed (transport) \u2014 safe to retry` : `runtime tenant control ${action} rejected: ${d.error ?? "request rejected by the Hub"}`
22333
+ };
22334
+ }
22335
+ const correlated = await correlateControlRun(deps, since, [stage, action, ...action === "run-task" && options.task ? [options.task] : []]);
22336
+ if (correlated.read === "failed") {
22337
+ return {
22338
+ ...base,
22339
+ dispatched: true,
22340
+ conclusion: "failure",
22341
+ category: action === "retire" ? "wait-timeout" : void 0,
22342
+ note: `runtime tenant control ${action} dispatched, but its run could not be READ: ${correlated.error} \u2014 the run's outcome is unverified, not absent; check the Actions tab or retry once the read succeeds (#4713)`
22343
+ };
22344
+ }
22345
+ ({ runId, runUrl } = correlated);
22181
22346
  }
22182
- const { runId, runUrl } = correlated;
22183
22347
  const conclusion = watch ? await watchTenantRun(deps, runId) : "pending";
22184
22348
  const result = { ...base, dispatched: true, runId, runUrl, conclusion, note: "" };
22185
22349
  if (action === "retire") {
@@ -22213,6 +22377,9 @@ async function runTenantControl(deps, options) {
22213
22377
  }
22214
22378
  }
22215
22379
  result.note = conclusion === "success" ? `tenant-control ${action} run succeeded` : conclusion === "failure" ? `tenant-control ${action} run failed \u2014 inspect the run` : runId == null ? `dispatched tenant-control.yml (${action}) \u2014 run not correlated; check the Actions tab` : `dispatched tenant-control.yml (${action}) \u2014 not watched`;
22380
+ if (conclusion === "pending" && runId != null && action === "run-task") {
22381
+ result.note += `; run ${runId} \u2014 resume without re-dispatching: mmi-cli devops runtime tenant control ${repo} ${stage} run-task --resume ${runId} --watch`;
22382
+ }
22216
22383
  return result;
22217
22384
  }
22218
22385
  function renderTenantControl(r) {
@@ -22232,9 +22399,9 @@ function renderTenantControl(r) {
22232
22399
  }
22233
22400
 
22234
22401
  // src/train-apply-phases.ts
22235
- var import_node_fs25 = require("node:fs");
22402
+ var import_node_fs26 = require("node:fs");
22236
22403
  var import_promises4 = require("node:fs/promises");
22237
- var import_node_path24 = require("node:path");
22404
+ var import_node_path25 = require("node:path");
22238
22405
 
22239
22406
  // src/actions-billing-preflight.ts
22240
22407
  var CANARY_WORKFLOW = "actions-job-start-canary.yml";
@@ -22542,14 +22709,14 @@ function assertPreOneZero(repo, meta, tag) {
22542
22709
 
22543
22710
  // src/train-doctor.ts
22544
22711
  var import_node_child_process9 = require("node:child_process");
22545
- var import_node_fs23 = require("node:fs");
22546
- var import_node_os14 = require("node:os");
22547
- var import_node_path23 = require("node:path");
22712
+ var import_node_fs24 = require("node:fs");
22713
+ var import_node_os15 = require("node:os");
22714
+ var import_node_path24 = require("node:path");
22548
22715
 
22549
22716
  // src/doctor-io.ts
22550
- var import_node_fs20 = require("node:fs");
22551
- var import_node_os11 = require("node:os");
22552
- var import_node_path18 = require("node:path");
22717
+ var import_node_fs21 = require("node:fs");
22718
+ var import_node_os12 = require("node:os");
22719
+ var import_node_path19 = require("node:path");
22553
22720
  var import_node_child_process7 = require("node:child_process");
22554
22721
  var import_node_util4 = require("node:util");
22555
22722
 
@@ -22562,8 +22729,8 @@ function nodeDiscardSinkPath(platform2 = process.platform) {
22562
22729
  var execFileP2 = (0, import_node_util4.promisify)(import_node_child_process7.execFile);
22563
22730
  function execFileCapture(file, args, opts = {}) {
22564
22731
  const sink = nodeDiscardSinkPath();
22565
- const inFd = (0, import_node_fs20.openSync)(sink, "r");
22566
- const errFd = (0, import_node_fs20.openSync)(sink, "w");
22732
+ const inFd = (0, import_node_fs21.openSync)(sink, "r");
22733
+ const errFd = (0, import_node_fs21.openSync)(sink, "w");
22567
22734
  try {
22568
22735
  return (0, import_node_child_process7.execFileSync)(file, args, {
22569
22736
  ...opts,
@@ -22571,17 +22738,17 @@ function execFileCapture(file, args, opts = {}) {
22571
22738
  stdio: [inFd, "pipe", errFd]
22572
22739
  });
22573
22740
  } finally {
22574
- (0, import_node_fs20.closeSync)(inFd);
22575
- (0, import_node_fs20.closeSync)(errFd);
22741
+ (0, import_node_fs21.closeSync)(inFd);
22742
+ (0, import_node_fs21.closeSync)(errFd);
22576
22743
  }
22577
22744
  }
22578
22745
  var MMI_PLUGIN_ID2 = "mmi@mutmutco";
22579
22746
  function stagedClaudePluginVersion() {
22580
22747
  try {
22581
- const stagingRoot = (0, import_node_path18.join)((0, import_node_os11.homedir)(), ".claude", "plugins", "staging");
22582
- const record = JSON.parse((0, import_node_fs20.readFileSync)((0, import_node_path18.join)(stagingRoot, "launch-target.json"), "utf8"));
22748
+ const stagingRoot = (0, import_node_path19.join)((0, import_node_os12.homedir)(), ".claude", "plugins", "staging");
22749
+ const record = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path19.join)(stagingRoot, "launch-target.json"), "utf8"));
22583
22750
  if (typeof record.target !== "string" || typeof record.incoming !== "string") return void 0;
22584
- const manifest = JSON.parse((0, import_node_fs20.readFileSync)((0, import_node_path18.join)(record.incoming, ".claude-plugin", "plugin.json"), "utf8"));
22751
+ const manifest = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path19.join)(record.incoming, ".claude-plugin", "plugin.json"), "utf8"));
22585
22752
  if (typeof manifest.version !== "string") return void 0;
22586
22753
  return manifest.version === record.target ? record.target : void 0;
22587
22754
  } catch {
@@ -22591,7 +22758,7 @@ function stagedClaudePluginVersion() {
22591
22758
  function installedClaudePluginVersion() {
22592
22759
  try {
22593
22760
  const file = JSON.parse(
22594
- (0, import_node_fs20.readFileSync)((0, import_node_path18.join)((0, import_node_os11.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
22761
+ (0, import_node_fs21.readFileSync)((0, import_node_path19.join)((0, import_node_os12.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
22595
22762
  );
22596
22763
  const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
22597
22764
  if (versions.length === 0) return void 0;
@@ -22603,12 +22770,12 @@ function installedClaudePluginVersion() {
22603
22770
  function readHermesPluginEvidence(env = process.env) {
22604
22771
  const host = hermesConfigRoot(env);
22605
22772
  const root = hermesPluginRoot(env);
22606
- const installRecordPresent = (0, import_node_fs20.existsSync)(root);
22607
- const manifestPath = (0, import_node_path18.join)(root, "plugin.yaml");
22773
+ const installRecordPresent = (0, import_node_fs21.existsSync)(root);
22774
+ const manifestPath = (0, import_node_path19.join)(root, "plugin.yaml");
22608
22775
  let installedVersion;
22609
22776
  let manifest = "missing";
22610
22777
  try {
22611
- const text = (0, import_node_fs20.readFileSync)(manifestPath, "utf8");
22778
+ const text = (0, import_node_fs21.readFileSync)(manifestPath, "utf8");
22612
22779
  let version;
22613
22780
  try {
22614
22781
  const parsed = JSON.parse(text).version;
@@ -22622,25 +22789,25 @@ function readHermesPluginEvidence(env = process.env) {
22622
22789
  if (version) {
22623
22790
  installedVersion = version;
22624
22791
  manifest = "valid";
22625
- } else if ((0, import_node_fs20.existsSync)(manifestPath)) manifest = "invalid";
22792
+ } else if ((0, import_node_fs21.existsSync)(manifestPath)) manifest = "invalid";
22626
22793
  } catch {
22627
- if ((0, import_node_fs20.existsSync)(manifestPath)) manifest = "invalid";
22794
+ if ((0, import_node_fs21.existsSync)(manifestPath)) manifest = "invalid";
22628
22795
  }
22629
22796
  let skills = false;
22630
22797
  try {
22631
- skills = (0, import_node_fs20.existsSync)((0, import_node_path18.join)(root, "skills")) && (0, import_node_fs20.statSync)((0, import_node_path18.join)(root, "skills")).isDirectory();
22798
+ skills = (0, import_node_fs21.existsSync)((0, import_node_path19.join)(root, "skills")) && (0, import_node_fs21.statSync)((0, import_node_path19.join)(root, "skills")).isDirectory();
22632
22799
  } catch {
22633
22800
  }
22634
22801
  let provisioned = false;
22635
- const provisionedRoot = (0, import_node_path18.join)(host, "skills", "mmi");
22802
+ const provisionedRoot = (0, import_node_path19.join)(host, "skills", "mmi");
22636
22803
  try {
22637
- provisioned = (0, import_node_fs20.existsSync)(provisionedRoot) && (0, import_node_fs20.statSync)(provisionedRoot).isDirectory();
22804
+ provisioned = (0, import_node_fs21.existsSync)(provisionedRoot) && (0, import_node_fs21.statSync)(provisionedRoot).isDirectory();
22638
22805
  } catch {
22639
22806
  }
22640
- const treeOk = (0, import_node_fs20.existsSync)((0, import_node_path18.join)(root, "__init__.py")) && skills && manifest === "valid";
22807
+ const treeOk = (0, import_node_fs21.existsSync)((0, import_node_path19.join)(root, "__init__.py")) && skills && manifest === "valid";
22641
22808
  const receipt = treeOk && !provisioned ? `hermes-skills-unprovisioned:${provisionedRoot}` : void 0;
22642
22809
  return {
22643
- hostPresent: (0, import_node_fs20.existsSync)(host),
22810
+ hostPresent: (0, import_node_fs21.existsSync)(host),
22644
22811
  installRecordPresent,
22645
22812
  manifest,
22646
22813
  payloadPresent: treeOk && provisioned,
@@ -22686,13 +22853,13 @@ function worktreeRootSync() {
22686
22853
  }
22687
22854
  var gitignorePath = () => {
22688
22855
  const root = worktreeRootSync();
22689
- return root === null ? null : (0, import_node_path18.join)(root, ".gitignore");
22856
+ return root === null ? null : (0, import_node_path19.join)(root, ".gitignore");
22690
22857
  };
22691
22858
  function readGitignore() {
22692
22859
  const path2 = gitignorePath();
22693
22860
  if (path2 === null) return null;
22694
22861
  try {
22695
- return (0, import_node_fs20.readFileSync)(path2, "utf8");
22862
+ return (0, import_node_fs21.readFileSync)(path2, "utf8");
22696
22863
  } catch {
22697
22864
  return null;
22698
22865
  }
@@ -22701,14 +22868,14 @@ function writeGitignore(content) {
22701
22868
  const path2 = gitignorePath();
22702
22869
  if (path2 === null) return false;
22703
22870
  try {
22704
- (0, import_node_fs20.writeFileSync)(path2, content, "utf8");
22871
+ (0, import_node_fs21.writeFileSync)(path2, content, "utf8");
22705
22872
  return true;
22706
22873
  } catch {
22707
22874
  return false;
22708
22875
  }
22709
22876
  }
22710
22877
  function lineEndingState(root) {
22711
- const attributesPresent = (0, import_node_fs20.existsSync)((0, import_node_path18.join)(root, ".gitattributes"));
22878
+ const attributesPresent = (0, import_node_fs21.existsSync)((0, import_node_path19.join)(root, ".gitattributes"));
22712
22879
  try {
22713
22880
  const output = execFileCapture("git", ["-C", root, "ls-files", "--eol", "--", ":(glob)**/*.sh"], {
22714
22881
  windowsHide: true
@@ -22751,18 +22918,18 @@ function compatHolds(range, version) {
22751
22918
  }
22752
22919
 
22753
22920
  // src/claude-binary-doctor.ts
22754
- var import_node_fs21 = require("node:fs");
22755
- var import_node_os13 = require("node:os");
22756
- var import_node_path20 = require("node:path");
22921
+ var import_node_fs22 = require("node:fs");
22922
+ var import_node_os14 = require("node:os");
22923
+ var import_node_path21 = require("node:path");
22757
22924
 
22758
22925
  // src/jerv-cli-spawn.ts
22759
- var import_node_os12 = require("node:os");
22760
- var import_node_path19 = require("node:path");
22926
+ var import_node_os13 = require("node:os");
22927
+ var import_node_path20 = require("node:path");
22761
22928
  init_cli_shared();
22762
- var JERV_CLI_ENTRY = (0, import_node_path19.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
22929
+ var JERV_CLI_ENTRY = (0, import_node_path20.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
22763
22930
  function pathEnvEntries(pathEnv, platform2 = process.platform) {
22764
22931
  if (platform2 !== "win32") {
22765
- return pathEnv.split(import_node_path19.delimiter).map((e) => e.trim()).filter(Boolean);
22932
+ return pathEnv.split(import_node_path20.delimiter).map((e) => e.trim()).filter(Boolean);
22766
22933
  }
22767
22934
  if (pathEnv.includes(";")) {
22768
22935
  return pathEnv.split(";").map((e) => e.trim()).filter(Boolean);
@@ -22781,7 +22948,7 @@ function normalizeSpawnPathEntry(entry, platform2 = process.platform) {
22781
22948
  if (msys) return `${msys[1].toUpperCase()}:\\${msys[2].replace(/\//g, "\\")}`;
22782
22949
  return trimmed;
22783
22950
  }
22784
- function jervCliCandidateDirs(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform) {
22951
+ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os13.homedir)(), platform2 = process.platform) {
22785
22952
  const seen = /* @__PURE__ */ new Set();
22786
22953
  const out = [];
22787
22954
  const push = (dir) => {
@@ -22795,10 +22962,10 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os12.hom
22795
22962
  push(normalizeSpawnPathEntry(entry, platform2));
22796
22963
  }
22797
22964
  if (platform2 === "win32") {
22798
- if (env.APPDATA) push((0, import_node_path19.join)(env.APPDATA, "npm"));
22799
- if (env.LOCALAPPDATA) push((0, import_node_path19.join)(env.LOCALAPPDATA, "npm"));
22965
+ if (env.APPDATA) push((0, import_node_path20.join)(env.APPDATA, "npm"));
22966
+ if (env.LOCALAPPDATA) push((0, import_node_path20.join)(env.LOCALAPPDATA, "npm"));
22800
22967
  } else {
22801
- push((0, import_node_path19.join)(home, ".local", "bin"));
22968
+ push((0, import_node_path20.join)(home, ".local", "bin"));
22802
22969
  }
22803
22970
  return out;
22804
22971
  }
@@ -22851,26 +23018,26 @@ function globalNodeModulesRoots(host) {
22851
23018
  out.push(dir);
22852
23019
  };
22853
23020
  const prefix = env.npm_config_prefix?.trim();
22854
- if (prefix) push(platform2 === "win32" ? (0, import_node_path20.join)(prefix, "node_modules") : (0, import_node_path20.join)(prefix, "lib", "node_modules"));
22855
- for (const dir of jervCliCandidateDirs(env, host.home ?? (0, import_node_os13.homedir)(), platform2)) {
22856
- push((0, import_node_path20.join)(dir, "node_modules"));
22857
- push((0, import_node_path20.join)((0, import_node_path20.dirname)(dir), "lib", "node_modules"));
23021
+ if (prefix) push(platform2 === "win32" ? (0, import_node_path21.join)(prefix, "node_modules") : (0, import_node_path21.join)(prefix, "lib", "node_modules"));
23022
+ for (const dir of jervCliCandidateDirs(env, host.home ?? (0, import_node_os14.homedir)(), platform2)) {
23023
+ push((0, import_node_path21.join)(dir, "node_modules"));
23024
+ push((0, import_node_path21.join)((0, import_node_path21.dirname)(dir), "lib", "node_modules"));
22858
23025
  }
22859
23026
  return out;
22860
23027
  }
22861
23028
  function readHead(path2) {
22862
23029
  let fd;
22863
23030
  try {
22864
- fd = (0, import_node_fs21.openSync)(path2, "r");
23031
+ fd = (0, import_node_fs22.openSync)(path2, "r");
22865
23032
  const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
22866
- const read = (0, import_node_fs21.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
23033
+ const read = (0, import_node_fs22.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
22867
23034
  return buffer.subarray(0, read);
22868
23035
  } catch {
22869
23036
  return void 0;
22870
23037
  } finally {
22871
23038
  if (fd !== void 0) {
22872
23039
  try {
22873
- (0, import_node_fs21.closeSync)(fd);
23040
+ (0, import_node_fs22.closeSync)(fd);
22874
23041
  } catch {
22875
23042
  }
22876
23043
  }
@@ -22878,7 +23045,7 @@ function readHead(path2) {
22878
23045
  }
22879
23046
  function fileBytes(path2) {
22880
23047
  try {
22881
- return (0, import_node_fs21.statSync)(path2).size;
23048
+ return (0, import_node_fs22.statSync)(path2).size;
22882
23049
  } catch {
22883
23050
  return void 0;
22884
23051
  }
@@ -22892,17 +23059,17 @@ function readClaudeBinaryState(host = {}) {
22892
23059
  const arch = host.arch ?? process.arch;
22893
23060
  const magic = EXECUTABLE_MAGIC[platform2];
22894
23061
  if (!magic) return void 0;
22895
- const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path20.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs21.existsSync)((0, import_node_path20.join)(dir, "package.json")));
23062
+ const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path21.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs22.existsSync)((0, import_node_path21.join)(dir, "package.json")));
22896
23063
  if (!packageRoot) return void 0;
22897
23064
  const keys = platformPackageKeys(platform2, arch);
22898
23065
  const fallbackPackage = `${PACKAGE}-${keys[0]}`;
22899
23066
  let manifest;
22900
23067
  try {
22901
- manifest = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path20.join)(packageRoot, "package.json"), "utf8"));
23068
+ manifest = JSON.parse((0, import_node_fs22.readFileSync)((0, import_node_path21.join)(packageRoot, "package.json"), "utf8"));
22902
23069
  } catch (e) {
22903
23070
  return {
22904
23071
  state: "unreadable",
22905
- binPath: (0, import_node_path20.join)(packageRoot, "package.json"),
23072
+ binPath: (0, import_node_path21.join)(packageRoot, "package.json"),
22906
23073
  expectedMagic: magic.name,
22907
23074
  platformPackage: fallbackPackage,
22908
23075
  error: `package.json could not be read \u2014 ${e.message}`
@@ -22919,17 +23086,17 @@ function readClaudeBinaryState(host = {}) {
22919
23086
  error: "package.json declares no `bin` entry \u2014 the executed file cannot be resolved"
22920
23087
  };
22921
23088
  }
22922
- const binPath = (0, import_node_path20.join)(packageRoot, binRelative);
22923
- const binName = (0, import_node_path20.basename)(binRelative);
23089
+ const binPath = (0, import_node_path21.join)(packageRoot, binRelative);
23090
+ const binName = (0, import_node_path21.basename)(binRelative);
22924
23091
  const optional = manifest.optionalDependencies;
22925
23092
  const publishes = (name) => typeof optional === "object" && optional !== null && Object.prototype.hasOwnProperty.call(optional, name);
22926
23093
  const published = keys.map((key) => `${PACKAGE}-${key}`).filter(publishes);
22927
23094
  if (published.length === 0) return void 0;
22928
23095
  const binIn = (name) => [
22929
- (0, import_node_path20.join)(packageRoot, "node_modules", ...name.split("/"), binName),
22930
- (0, import_node_path20.join)((0, import_node_path20.dirname)((0, import_node_path20.dirname)(packageRoot)), ...name.split("/"), binName)
23096
+ (0, import_node_path21.join)(packageRoot, "node_modules", ...name.split("/"), binName),
23097
+ (0, import_node_path21.join)((0, import_node_path21.dirname)((0, import_node_path21.dirname)(packageRoot)), ...name.split("/"), binName)
22931
23098
  ];
22932
- const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs21.existsSync)(file)) })).find((c) => c.path);
23099
+ const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs22.existsSync)(file)) })).find((c) => c.path);
22933
23100
  const platformPackage = found?.name ?? published[0];
22934
23101
  let source;
22935
23102
  let sourceProblem;
@@ -22940,7 +23107,7 @@ function readClaudeBinaryState(host = {}) {
22940
23107
  } else {
22941
23108
  source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
22942
23109
  }
22943
- if (!(0, import_node_fs21.existsSync)(binPath)) {
23110
+ if (!(0, import_node_fs22.existsSync)(binPath)) {
22944
23111
  return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
22945
23112
  }
22946
23113
  const head = readHead(binPath);
@@ -22983,9 +23150,9 @@ function healClaudeBinary(host = {}, onStep) {
22983
23150
  const platform2 = host.platform ?? process.platform;
22984
23151
  const aside = `${probe.binPath}.stub-${Date.now()}`;
22985
23152
  let renamed = false;
22986
- if ((0, import_node_fs21.existsSync)(probe.binPath)) {
23153
+ if ((0, import_node_fs22.existsSync)(probe.binPath)) {
22987
23154
  try {
22988
- (0, import_node_fs21.renameSync)(probe.binPath, aside);
23155
+ (0, import_node_fs22.renameSync)(probe.binPath, aside);
22989
23156
  renamed = true;
22990
23157
  onStep?.(`renamed the stub aside: ${aside}`);
22991
23158
  } catch (e) {
@@ -22994,12 +23161,12 @@ function healClaudeBinary(host = {}, onStep) {
22994
23161
  }
22995
23162
  try {
22996
23163
  onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
22997
- (0, import_node_fs21.copyFileSync)(probe.source.path, probe.binPath);
22998
- if (platform2 !== "win32") (0, import_node_fs21.chmodSync)(probe.binPath, 493);
23164
+ (0, import_node_fs22.copyFileSync)(probe.source.path, probe.binPath);
23165
+ if (platform2 !== "win32") (0, import_node_fs22.chmodSync)(probe.binPath, 493);
22999
23166
  } catch (e) {
23000
23167
  if (renamed) {
23001
23168
  try {
23002
- (0, import_node_fs21.renameSync)(aside, probe.binPath);
23169
+ (0, import_node_fs22.renameSync)(aside, probe.binPath);
23003
23170
  } catch {
23004
23171
  return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
23005
23172
  }
@@ -23013,7 +23180,7 @@ function healClaudeBinary(host = {}, onStep) {
23013
23180
  let kept = false;
23014
23181
  if (renamed) {
23015
23182
  try {
23016
- (0, import_node_fs21.rmSync)(aside);
23183
+ (0, import_node_fs22.rmSync)(aside);
23017
23184
  } catch {
23018
23185
  kept = true;
23019
23186
  }
@@ -23372,13 +23539,13 @@ function checkLineEndings(probe) {
23372
23539
  }
23373
23540
 
23374
23541
  // src/release-ledger.ts
23375
- var import_node_fs22 = require("node:fs");
23376
- var import_node_path22 = require("node:path");
23377
- var import_node_crypto8 = require("node:crypto");
23542
+ var import_node_fs23 = require("node:fs");
23543
+ var import_node_path23 = require("node:path");
23544
+ var import_node_crypto9 = require("node:crypto");
23378
23545
 
23379
23546
  // src/file-lock.ts
23380
23547
  var import_promises2 = require("node:fs/promises");
23381
- var import_node_path21 = require("node:path");
23548
+ var import_node_path22 = require("node:path");
23382
23549
  function pidIsDead(pid) {
23383
23550
  if (!Number.isInteger(pid) || pid <= 0) return false;
23384
23551
  if (pid === process.pid) return false;
@@ -23496,7 +23663,7 @@ async function withFileLock(lockPath, opts, fn) {
23496
23663
  }
23497
23664
  async function withFencedFileLock(lockPath, opts, fn) {
23498
23665
  const resolved = resolveFileLockOpts(opts);
23499
- await (0, import_promises2.mkdir)((0, import_node_path21.dirname)(lockPath), { recursive: true }).catch(() => void 0);
23666
+ await (0, import_promises2.mkdir)((0, import_node_path22.dirname)(lockPath), { recursive: true }).catch(() => void 0);
23500
23667
  const guard = await acquireFileLock(lockPath, resolved, Date.now() + resolved.maxWaitMs);
23501
23668
  try {
23502
23669
  return await fn(() => fileLockHeldBy(lockPath, guard.token));
@@ -23547,8 +23714,8 @@ function attachOutputNote(note, suffix) {
23547
23714
  }
23548
23715
  function writeFailingLegOutput(artifactPath, output) {
23549
23716
  const fileLines = lastNonEmptyLines(output, LEDGER_OUTPUT_FILE_LINES);
23550
- (0, import_node_fs22.mkdirSync)((0, import_node_path22.dirname)(artifactPath), { recursive: true });
23551
- (0, import_node_fs22.writeFileSync)(artifactPath, `${fileLines.join("\n")}
23717
+ (0, import_node_fs23.mkdirSync)((0, import_node_path23.dirname)(artifactPath), { recursive: true });
23718
+ (0, import_node_fs23.writeFileSync)(artifactPath, `${fileLines.join("\n")}
23552
23719
  `, "utf8");
23553
23720
  const tail = fileLines.slice(-LEDGER_OUTPUT_NOTE_LINES).join("\n");
23554
23721
  const noteSuffix = truncate(`failing-leg output: ${artifactPath}
@@ -23563,7 +23730,7 @@ function stampPhaseRecord(ledgerPath, tag, phase, entry, previousRetries, now) {
23563
23730
  if (raw) {
23564
23731
  try {
23565
23732
  const persisted = writeFailingLegOutput(
23566
- (0, import_node_path22.join)((0, import_node_path22.dirname)((0, import_node_path22.dirname)(ledgerPath)), "ledger-output", `${tag}-${phase}.txt`),
23733
+ (0, import_node_path23.join)((0, import_node_path23.dirname)((0, import_node_path23.dirname)(ledgerPath)), "ledger-output", `${tag}-${phase}.txt`),
23567
23734
  raw
23568
23735
  );
23569
23736
  note = attachOutputNote(note, persisted.noteSuffix);
@@ -23716,30 +23883,30 @@ function resolvePrimaryGitDir(cwd) {
23716
23883
  }
23717
23884
  let common;
23718
23885
  try {
23719
- common = (0, import_node_fs22.readFileSync)((0, import_node_path22.join)(gitDir, "commondir"), "utf8").trim();
23886
+ common = (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(gitDir, "commondir"), "utf8").trim();
23720
23887
  } catch (e) {
23721
23888
  if (e.code !== "ENOENT") {
23722
23889
  throw new ReleaseLedgerError("unreadable", `release ledger: the worktree gitdir's commondir pointer could not be READ (${e instanceof Error ? e.message : String(e)}) \u2014 a failed read is unverified, not primary (#5987/#4713)`);
23723
23890
  }
23724
23891
  }
23725
23892
  if (!common) return gitDir;
23726
- const commonDir = (0, import_node_path22.isAbsolute)(common) ? common : (0, import_node_path22.resolve)(gitDir, common);
23893
+ const commonDir = (0, import_node_path23.isAbsolute)(common) ? common : (0, import_node_path23.resolve)(gitDir, common);
23727
23894
  try {
23728
- (0, import_node_fs22.readFileSync)((0, import_node_path22.join)(commonDir, "HEAD"), "utf8");
23895
+ (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(commonDir, "HEAD"), "utf8");
23729
23896
  } catch (e) {
23730
23897
  throw new ReleaseLedgerError("no-checkout", `release ledger: the worktree's commondir pointer names ${commonDir}, which has no readable HEAD (${e instanceof Error ? e.message : String(e)}) \u2014 the primary checkout may have been removed; refusing to write the ledger into a doomed location`);
23731
23898
  }
23732
23899
  return commonDir;
23733
23900
  }
23734
23901
  function releaseLedgerPath(cwd) {
23735
- return (0, import_node_path22.join)(resolvePrimaryGitDir(cwd), "mmi-runtime", "release", "phases.json");
23902
+ return (0, import_node_path23.join)(resolvePrimaryGitDir(cwd), "mmi-runtime", "release", "phases.json");
23736
23903
  }
23737
23904
  function atomicWriteJson(path2, ledger) {
23738
- (0, import_node_fs22.mkdirSync)((0, import_node_path22.dirname)(path2), { recursive: true });
23739
- const tmp = `${path2}.tmp-${process.pid}-${(0, import_node_crypto8.randomBytes)(4).toString("hex")}`;
23740
- (0, import_node_fs22.writeFileSync)(tmp, `${JSON.stringify(ledger, null, 2)}
23905
+ (0, import_node_fs23.mkdirSync)((0, import_node_path23.dirname)(path2), { recursive: true });
23906
+ const tmp = `${path2}.tmp-${process.pid}-${(0, import_node_crypto9.randomBytes)(4).toString("hex")}`;
23907
+ (0, import_node_fs23.writeFileSync)(tmp, `${JSON.stringify(ledger, null, 2)}
23741
23908
  `, "utf8");
23742
- (0, import_node_fs22.renameSync)(tmp, path2);
23909
+ (0, import_node_fs23.renameSync)(tmp, path2);
23743
23910
  }
23744
23911
  var LEDGER_LOCK_OPTS = { label: "release ledger", staleMs: 18e4, deadHolderSteal: true };
23745
23912
  async function withLedgerLock(path2, fn, opts = {}) {
@@ -23751,16 +23918,16 @@ async function withLedgerLock(path2, fn, opts = {}) {
23751
23918
  }));
23752
23919
  }
23753
23920
  function checkoutRootFrom(cwd) {
23754
- let dir = (0, import_node_path22.resolve)(cwd);
23921
+ let dir = (0, import_node_path23.resolve)(cwd);
23755
23922
  for (; ; ) {
23756
23923
  if (resolveGitDir(dir)) return dir;
23757
- const parent = (0, import_node_path22.dirname)(dir);
23924
+ const parent = (0, import_node_path23.dirname)(dir);
23758
23925
  if (parent === dir) throw new ReleaseLedgerError("no-checkout", `train writer lock: no git checkout found above ${cwd}`);
23759
23926
  dir = parent;
23760
23927
  }
23761
23928
  }
23762
23929
  function trainWriterLockPath(cwd) {
23763
- return (0, import_node_path22.join)((0, import_node_path22.dirname)(releaseLedgerPath(checkoutRootFrom(cwd))), "train.lock");
23930
+ return (0, import_node_path23.join)((0, import_node_path23.dirname)(releaseLedgerPath(checkoutRootFrom(cwd))), "train.lock");
23764
23931
  }
23765
23932
  var TrainWriterBusyError = class extends Error {
23766
23933
  lockPath;
@@ -23786,7 +23953,7 @@ function describeTrainWriterToken(token) {
23786
23953
  function liveTrainWriterHolder(cwd) {
23787
23954
  let token;
23788
23955
  try {
23789
- token = (0, import_node_fs22.readFileSync)(trainWriterLockPath(cwd), "utf8");
23956
+ token = (0, import_node_fs23.readFileSync)(trainWriterLockPath(cwd), "utf8");
23790
23957
  } catch {
23791
23958
  return void 0;
23792
23959
  }
@@ -23808,7 +23975,7 @@ async function acquireTrainWriterLock(cwd, verb) {
23808
23975
  if (heldTrainWriter) heldTrainWriter.depth -= 1;
23809
23976
  };
23810
23977
  }
23811
- (0, import_node_fs22.mkdirSync)((0, import_node_path22.dirname)(lockPath), { recursive: true });
23978
+ (0, import_node_fs23.mkdirSync)((0, import_node_path23.dirname)(lockPath), { recursive: true });
23812
23979
  const opts = resolveFileLockOpts({ label: "train writer", staleMs: TRAIN_WRITER_STALE_MS, deadHolderSteal: true, maxWaitMs: 0, holder: verb });
23813
23980
  let guard;
23814
23981
  try {
@@ -23817,7 +23984,7 @@ async function acquireTrainWriterLock(cwd, verb) {
23817
23984
  if (!(e instanceof FileLockBusyError)) throw e;
23818
23985
  let token = "";
23819
23986
  try {
23820
- token = (0, import_node_fs22.readFileSync)(lockPath, "utf8");
23987
+ token = (0, import_node_fs23.readFileSync)(lockPath, "utf8");
23821
23988
  } catch {
23822
23989
  token = "";
23823
23990
  }
@@ -23852,7 +24019,7 @@ async function withReleaseLedger(path2, expected, fn, opts = {}) {
23852
24019
  let current;
23853
24020
  let raw;
23854
24021
  try {
23855
- raw = (0, import_node_fs22.readFileSync)(path2, "utf8");
24022
+ raw = (0, import_node_fs23.readFileSync)(path2, "utf8");
23856
24023
  } catch (e) {
23857
24024
  if (e.code !== "ENOENT") {
23858
24025
  throw new ReleaseLedgerError("unreadable", `release ledger at ${path2} could not be READ (${e instanceof Error ? e.message : String(e)}) \u2014 a failed read is unverified, not absent (#5987)`);
@@ -24521,7 +24688,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
24521
24688
  return withLedgerLock(path2, async (fence) => {
24522
24689
  let raw;
24523
24690
  try {
24524
- raw = (0, import_node_fs22.readFileSync)(path2, "utf8");
24691
+ raw = (0, import_node_fs23.readFileSync)(path2, "utf8");
24525
24692
  } catch (e) {
24526
24693
  if (e.code === "ENOENT") return { cleared: false };
24527
24694
  return { cleared: false, note: `release ledger at ${path2} could not be read for clearing (${e instanceof Error ? e.message : String(e)}) \u2014 left in place` };
@@ -24537,7 +24704,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
24537
24704
  } catch (e) {
24538
24705
  return { cleared: false, note: `release ledger at ${path2} belongs to ${ledger.tag} @ ${ledger.tagSha.slice(0, 12)} \u2014 not this release; left in place (${e instanceof Error ? e.message : String(e)})` };
24539
24706
  }
24540
- await fence(() => (0, import_node_fs22.unlinkSync)(path2));
24707
+ await fence(() => (0, import_node_fs23.unlinkSync)(path2));
24541
24708
  return { cleared: true, note: `cleared the release ledger at ${path2} for the live-proven aborted ${anchors.tag}` };
24542
24709
  }, { maxWaitMs });
24543
24710
  }
@@ -24697,7 +24864,7 @@ async function healStaleAlignmentLeg(deps, cwd, expected) {
24697
24864
  return withLedgerLock(path2, async (fence) => {
24698
24865
  let prior;
24699
24866
  try {
24700
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
24867
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
24701
24868
  } catch {
24702
24869
  return void 0;
24703
24870
  }
@@ -24722,7 +24889,7 @@ async function healUnfoldedRunLegs(deps, cwd, model) {
24722
24889
  const path2 = releaseLedgerPath(cwd);
24723
24890
  let prior;
24724
24891
  try {
24725
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
24892
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
24726
24893
  } catch {
24727
24894
  return void 0;
24728
24895
  }
@@ -24791,7 +24958,7 @@ async function supersedeContentCausedDeployLeg(deps, cwd) {
24791
24958
  return withLedgerLock(path2, async (fence) => {
24792
24959
  let prior;
24793
24960
  try {
24794
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
24961
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
24795
24962
  } catch (e) {
24796
24963
  throw new ReleaseLedgerError(
24797
24964
  "unreadable",
@@ -24888,11 +25055,11 @@ async function proveOriginPromotionOrArchived(deps, prior, path2, label, ref, fe
24888
25055
  if (!releaseAbsent) {
24889
25056
  throw new Error(`${label}: origin no longer has ${prior.tag} but its GitHub Release still exists \u2014 resolve the mixed external state before closing the ledger; nothing was written (${ref})`);
24890
25057
  }
24891
- const archivePath = (0, import_node_path22.join)((0, import_node_path22.dirname)(path2), `phases.archive-${prior.tag}.json`);
24892
- if ((0, import_node_fs22.existsSync)(archivePath)) {
25058
+ const archivePath = (0, import_node_path23.join)((0, import_node_path23.dirname)(path2), `phases.archive-${prior.tag}.json`);
25059
+ if ((0, import_node_fs23.existsSync)(archivePath)) {
24893
25060
  throw new Error(`${label}: archive already exists at ${archivePath} \u2014 preserving both ledger records; resolve the collision by hand; nothing was written (${ref})`);
24894
25061
  }
24895
- await fence(() => (0, import_node_fs22.renameSync)(path2, archivePath));
25062
+ await fence(() => (0, import_node_fs23.renameSync)(path2, archivePath));
24896
25063
  return "deleted";
24897
25064
  }
24898
25065
  async function supersedeContentCausedPublishLeg(deps, cwd) {
@@ -24900,7 +25067,7 @@ async function supersedeContentCausedPublishLeg(deps, cwd) {
24900
25067
  return withLedgerLock(path2, async (fence) => {
24901
25068
  let prior;
24902
25069
  try {
24903
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
25070
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
24904
25071
  } catch (e) {
24905
25072
  throw new ReleaseLedgerError(
24906
25073
  "unreadable",
@@ -24982,7 +25149,7 @@ async function supersedeContentCausedDeployAndPublishLegs(deps, cwd) {
24982
25149
  return withLedgerLock(path2, async (fence) => {
24983
25150
  let prior;
24984
25151
  try {
24985
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
25152
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
24986
25153
  } catch (e) {
24987
25154
  throw new ReleaseLedgerError(
24988
25155
  "unreadable",
@@ -25087,7 +25254,7 @@ async function supersedeContentCausedDeployAndPublishLegs(deps, cwd) {
25087
25254
  async function reverifyPriorRunLegs(deps, path2, targetTag) {
25088
25255
  let prior;
25089
25256
  try {
25090
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
25257
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
25091
25258
  } catch {
25092
25259
  return;
25093
25260
  }
@@ -25107,7 +25274,7 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
25107
25274
  return withLedgerLock(path2, async (fence) => {
25108
25275
  let raw;
25109
25276
  try {
25110
- raw = (0, import_node_fs22.readFileSync)(path2, "utf8");
25277
+ raw = (0, import_node_fs23.readFileSync)(path2, "utf8");
25111
25278
  } catch (e) {
25112
25279
  if (e.code === "ENOENT") return { ok: true };
25113
25280
  return { ok: false, error: `the release ledger at ${path2} could not be READ (${e instanceof Error ? e.message : String(e)}) \u2014 a failed read is unverified, not absent (#5987/#4713)` };
@@ -25145,15 +25312,15 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
25145
25312
  if (liveSha.toLowerCase() !== prior.tagSha.toLowerCase()) {
25146
25313
  return { ok: false, error: `the completed ${prior.tag} ledger says phases-green but origin reports ${liveSha.slice(0, 12) || "no tag"} \u2260 ${prior.tagSha.slice(0, 12)} \u2014 refusing to archive on unproven state; resolve by hand (#5987)` };
25147
25314
  }
25148
- const archivePath = (0, import_node_path22.join)((0, import_node_path22.dirname)(path2), `phases.archive-${prior.tag}.json`);
25315
+ const archivePath = (0, import_node_path23.join)((0, import_node_path23.dirname)(path2), `phases.archive-${prior.tag}.json`);
25149
25316
  try {
25150
- await fence(() => (0, import_node_fs22.unlinkSync)(archivePath));
25317
+ await fence(() => (0, import_node_fs23.unlinkSync)(archivePath));
25151
25318
  } catch (e) {
25152
25319
  if (e.code !== "ENOENT") {
25153
25320
  return { ok: false, error: `could not clear the stale archive at ${archivePath} (${e instanceof Error ? e.message : String(e)}) \u2014 the ledger for ${prior.tag} stays active (#5987)` };
25154
25321
  }
25155
25322
  }
25156
- await fence(() => (0, import_node_fs22.renameSync)(path2, archivePath));
25323
+ await fence(() => (0, import_node_fs23.renameSync)(path2, archivePath));
25157
25324
  return { ok: true, note: `archived the completed release ledger ${prior.tag} to ${archivePath} (live-proven at ${prior.tagSha.slice(0, 12)})` };
25158
25325
  });
25159
25326
  }
@@ -25181,7 +25348,7 @@ async function retryHotfixDeployLegs(deps, cwd, opts = {}) {
25181
25348
  return withLedgerLock(path2, async (fence) => {
25182
25349
  let prior;
25183
25350
  try {
25184
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
25351
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
25185
25352
  } catch (e) {
25186
25353
  throw new ReleaseLedgerError(
25187
25354
  "unreadable",
@@ -25372,10 +25539,10 @@ function readOriginWorkflowsDefault(root, ref) {
25372
25539
  }
25373
25540
  var NPM_REGISTRY = "https://registry.npmjs.org";
25374
25541
  async function probeRegistryWhoami(train) {
25375
- const dir = (0, import_node_fs23.mkdtempSync)((0, import_node_path23.join)((0, import_node_os14.tmpdir)(), "mmi-npmrc-"));
25376
- const rc = (0, import_node_path23.join)(dir, "npmrc");
25542
+ const dir = (0, import_node_fs24.mkdtempSync)((0, import_node_path24.join)((0, import_node_os15.tmpdir)(), "mmi-npmrc-"));
25543
+ const rc = (0, import_node_path24.join)(dir, "npmrc");
25377
25544
  try {
25378
- (0, import_node_fs23.writeFileSync)(rc, "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n");
25545
+ (0, import_node_fs24.writeFileSync)(rc, "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n");
25379
25546
  await train.runSelf(["secrets", "use", "npm/NPM_TOKEN", "--slug", "_org", "--", "npm", "whoami", "--registry", NPM_REGISTRY, "--userconfig", rc]);
25380
25547
  return { kind: "ok", detail: "the registry answered a login" };
25381
25548
  } catch (e) {
@@ -25386,7 +25553,7 @@ async function probeRegistryWhoami(train) {
25386
25553
  if (/\bE401\b|401 Unauthorized/.test(stderr)) return { kind: "rejected", detail: "npm whoami answered 401 Unauthorized" };
25387
25554
  return { kind: "unverified", detail: first };
25388
25555
  } finally {
25389
- (0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
25556
+ (0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
25390
25557
  }
25391
25558
  }
25392
25559
  var REGISTRY_TOKEN_ENV = /\b(NODE_AUTH_TOKEN|NPM_TOKEN)\b/;
@@ -25404,7 +25571,7 @@ var defaultDeps2 = {
25404
25571
  ledgerPath: releaseLedgerPath,
25405
25572
  readLedgerRaw: (path2) => {
25406
25573
  try {
25407
- return (0, import_node_fs23.readFileSync)(path2, "utf8");
25574
+ return (0, import_node_fs24.readFileSync)(path2, "utf8");
25408
25575
  } catch (e) {
25409
25576
  if (e.code === "ENOENT") return void 0;
25410
25577
  throw e;
@@ -25415,7 +25582,7 @@ var defaultDeps2 = {
25415
25582
  trainWriterHolder: liveTrainWriterHolder,
25416
25583
  readSurfacesRaw: (cwd) => {
25417
25584
  try {
25418
- return (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(cwd, "surfaces.json"), "utf8");
25585
+ return (0, import_node_fs24.readFileSync)((0, import_node_path24.join)(cwd, "surfaces.json"), "utf8");
25419
25586
  } catch {
25420
25587
  return void 0;
25421
25588
  }
@@ -26005,7 +26172,7 @@ function formatTrainDoctor(v) {
26005
26172
 
26006
26173
  // src/release-plain-words.ts
26007
26174
  var import_promises3 = require("node:fs/promises");
26008
- var import_node_fs24 = require("node:fs");
26175
+ var import_node_fs25 = require("node:fs");
26009
26176
  function releaseCutByNotes(cutBy) {
26010
26177
  return `## Internal
26011
26178
  Cut by ${formatSessionIdentity(cutBy)}
@@ -26030,7 +26197,7 @@ function validateSuiteReleaseSummary(path2) {
26030
26197
  if (!path2) throw new Error(`requires --announce-summary-file <path> before promoting any member \u2014 see ${SUMMARY_GUIDE}`);
26031
26198
  let content;
26032
26199
  try {
26033
- content = (0, import_node_fs24.readFileSync)(path2, "utf8");
26200
+ content = (0, import_node_fs25.readFileSync)(path2, "utf8");
26034
26201
  } catch (e) {
26035
26202
  throw new Error(`could not read summary file ${path2}: ${e.message} \u2014 see ${SUMMARY_GUIDE}`);
26036
26203
  }
@@ -26237,34 +26404,34 @@ function vercelVersionEnvDeps(deps) {
26237
26404
  // src/train-apply-phases.ts
26238
26405
  var TRAIN_BUMP_INTENTS = ["major", "minor", "patch"];
26239
26406
  function readLocalGateWorkflows() {
26240
- const dir = (0, import_node_path24.join)(".github", "workflows");
26407
+ const dir = (0, import_node_path25.join)(".github", "workflows");
26241
26408
  let names;
26242
26409
  try {
26243
- names = (0, import_node_fs25.readdirSync)(dir);
26410
+ names = (0, import_node_fs26.readdirSync)(dir);
26244
26411
  } catch {
26245
26412
  return null;
26246
26413
  }
26247
26414
  const files = [];
26248
26415
  for (const name of names.filter(isGateWorkflowPath)) {
26249
26416
  try {
26250
- files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs25.readFileSync)((0, import_node_path24.join)(dir, name), "utf8") });
26417
+ files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs26.readFileSync)((0, import_node_path25.join)(dir, name), "utf8") });
26251
26418
  } catch {
26252
26419
  }
26253
26420
  }
26254
26421
  return files;
26255
26422
  }
26256
26423
  function readLocalWorkflows() {
26257
- const dir = (0, import_node_path24.join)(".github", "workflows");
26424
+ const dir = (0, import_node_path25.join)(".github", "workflows");
26258
26425
  let names;
26259
26426
  try {
26260
- names = (0, import_node_fs25.readdirSync)(dir);
26427
+ names = (0, import_node_fs26.readdirSync)(dir);
26261
26428
  } catch {
26262
26429
  return null;
26263
26430
  }
26264
26431
  const files = [];
26265
26432
  for (const name of names.filter((n) => /\.ya?ml$/i.test(n))) {
26266
26433
  try {
26267
- files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs25.readFileSync)((0, import_node_path24.join)(dir, name), "utf8") });
26434
+ files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs26.readFileSync)((0, import_node_path25.join)(dir, name), "utf8") });
26268
26435
  } catch {
26269
26436
  }
26270
26437
  }
@@ -27146,7 +27313,7 @@ async function activeRcandLedgerCandidate(deps, cwd) {
27146
27313
  }
27147
27314
  let prior;
27148
27315
  try {
27149
- prior = parseReleaseLedger((0, import_node_fs25.readFileSync)(path2, "utf8"));
27316
+ prior = parseReleaseLedger((0, import_node_fs26.readFileSync)(path2, "utf8"));
27150
27317
  } catch {
27151
27318
  return void 0;
27152
27319
  }
@@ -30428,11 +30595,11 @@ function buildPluginCachePlan(home, running, deps, opts = {}) {
30428
30595
  return absent;
30429
30596
  }
30430
30597
  const versions = names.filter(isVersionDirName);
30431
- const prune = selectPrunablePluginVersions(versions, running, opts.installedVersion);
30432
- const pruneSet = new Set(prune);
30598
+ const prune2 = selectPrunablePluginVersions(versions, running, opts.installedVersion);
30599
+ const pruneSet = new Set(prune2);
30433
30600
  const keep = [...versions].sort((a, b) => compareVersions(b, a)).filter((v) => !pruneSet.has(v));
30434
- const bytes = opts.withBytes ? prune.reduce((sum, v) => sum + deps.dirBytes(`${cacheRoot}/${v}`), 0) : 0;
30435
- return { cacheRoot, present: true, keep, prune, bytes, running, ...stagingFields };
30601
+ const bytes = opts.withBytes ? prune2.reduce((sum, v) => sum + deps.dirBytes(`${cacheRoot}/${v}`), 0) : 0;
30602
+ return { cacheRoot, present: true, keep, prune: prune2, bytes, running, ...stagingFields };
30436
30603
  }
30437
30604
  function applyPluginCachePlan(plan, remove2, stagingGuard) {
30438
30605
  const removed = [];
@@ -30741,6 +30908,12 @@ function registerBoardCommands(program3) {
30741
30908
  if (!o.out) console.log(output);
30742
30909
  else console.log(`Wrote board read to ${o.out} (UTF-8, ${writeUtf8Receipt(o.out, output)} bytes)`);
30743
30910
  } catch (e) {
30911
+ if (e instanceof BoardSnapshotFailure) {
30912
+ if (o.json) console.log(JSON.stringify(e.receipt));
30913
+ console.error(`mmi-cli board read failed: ${e.message}`);
30914
+ process.exitCode = e.exitCode;
30915
+ return;
30916
+ }
30744
30917
  if (o.json && e && typeof e === "object" && "quota" in e && e.quota) console.log(JSON.stringify(e.quota));
30745
30918
  return failGraceful(`board read failed: ${withDiscoverMissDetail(e.message)}`);
30746
30919
  }
@@ -30781,7 +30954,7 @@ function registerBoardCommands(program3) {
30781
30954
  return `Claimed ${ref} for ${holder} - In Progress${reclaimed}`;
30782
30955
  }
30783
30956
  const board = program3.command("board").description("read, claim, show, and move Project v2 work items for the current repo");
30784
- board.command("read", { isDefault: true }).alias("list").description("read the board and print user-owned, claimable, and taken items").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo (defaults to git origin)").option("--direct", "bypass the Hub snapshot and read the live board through direct GitHub GraphQL").option("--snapshot-only", "fail instead of falling back to your personal GraphQL pool when the Hub snapshot is unavailable \u2014 for ambient readers such as sidebars (#7203)").option("--min-cursor <n>", "board-event cursor (from `oracle board events`) the Hub snapshot must postdate; a cached snapshot older than that event is rebuilt (#7240)").option("--bundle-details", "fetch body/comments only for user-owned and claimable issues").option("--bodies", "fetch body/comments for EVERY scoped row, including taken and unowned in-flight ones \u2014 for consumers that scope by Status rather than ownership (#4861); implies --bundle-details and costs one extra read per row").option("--allow-partial", "return partial board results when later page/detail reads fail").option("--out <path>", "write the output to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802)").addHelpText("after", "\nread is always the authoritative live GitHub Project v2 board (#4926).\n--direct skips the Hub snapshot and uses the existing direct GitHub GraphQL read immediately.\n--allow-partial applies to the paginated path and detail reads.\n\nWhen using Windows PowerShell 5.1, avoid shell redirects: PowerShell 5.1's `> file.json` is Out-File,\nwhich writes UTF-16LE with a BOM, and Node reading it as 'utf8' then fails JSON.parse at position 1\n(#5802). Use --out instead \u2014 the CLI writes the file itself as UTF-8:\n mmi-cli oracle board read --json --out .jerv/tmp/board.json\n").action((o) => runBoardRead(o));
30957
+ board.command("read", { isDefault: true }).alias("list").description("read the board and print user-owned, claimable, and taken items").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo (defaults to git origin)").option("--direct", "bypass the Hub snapshot and read the live board through direct GitHub GraphQL").option("--snapshot-only", "never fall back to your personal GraphQL pool; failure exits: 20 hub-unreachable, 21 app-quota-exhausted, 22 refused. With --json, stdout is {ok:false,outcome,reason[,resetAt,pool]} (pool is rest or graphql when known); success is unchanged").option("--min-cursor <n>", "board-event cursor (from `oracle board events`) the Hub snapshot must postdate; a cached snapshot older than that event is rebuilt (#7240)").option("--bundle-details", "fetch body/comments only for user-owned and claimable issues").option("--bodies", "fetch body/comments for EVERY scoped row, including taken and unowned in-flight ones \u2014 for consumers that scope by Status rather than ownership (#4861); implies --bundle-details and costs one extra read per row").option("--allow-partial", "return partial board results when later page/detail reads fail").option("--out <path>", "write the output to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802)").addHelpText("after", "\nread is always the authoritative live GitHub Project v2 board (#4926).\n--direct skips the Hub snapshot and uses the existing direct GitHub GraphQL read immediately.\n--allow-partial applies to the paginated path and detail reads.\n\nWhen using Windows PowerShell 5.1, avoid shell redirects: PowerShell 5.1's `> file.json` is Out-File,\nwhich writes UTF-16LE with a BOM, and Node reading it as 'utf8' then fails JSON.parse at position 1\n(#5802). Use --out instead \u2014 the CLI writes the file itself as UTF-8:\n mmi-cli oracle board read --json --out .jerv/tmp/board.json\n").action((o) => runBoardRead(o));
30785
30958
  board.command("events").description("content-free board/CI change records after a cursor, from the Hub event feed (no GitHub call) \u2014 for real-time sidebars (#7235)").option("--since <cursor>", "cursor from the previous answer; omit on first read (answers the head cursor with resync:true)").option("--wait <seconds>", "hold up to this long (max 120), polling every 2s, and return on the first event or resync", "0").option("--repo <owner/repo>", "repo whose Hub config to use (defaults to git origin)").option("--json", "machine-readable output (already the default)").addHelpText("after", "\nPrints {cursor, events, resync, more[, hidden]}. Pass the returned cursor as the next --since.\nresync:true means records were missed (retention ~1h, or a gap): re-read the board with\n`mmi-cli oracle board read --snapshot-only --json`.\n").action(async (o) => {
30786
30959
  try {
30787
30960
  if (o.since !== void 0 && !/^\d{1,15}$/.test(o.since)) throw new Error("--since must be a non-negative integer cursor");
@@ -31022,9 +31195,9 @@ function registerBoardCommands(program3) {
31022
31195
  }
31023
31196
 
31024
31197
  // src/bootstrap-commands.ts
31025
- var import_node_fs29 = require("node:fs");
31026
- var import_node_os17 = require("node:os");
31027
- var import_node_path28 = require("node:path");
31198
+ var import_node_fs30 = require("node:fs");
31199
+ var import_node_os18 = require("node:os");
31200
+ var import_node_path29 = require("node:path");
31028
31201
  init_cli_shared();
31029
31202
  init_clean_exit();
31030
31203
 
@@ -31208,8 +31381,8 @@ init_github_client();
31208
31381
  init_cli_shared();
31209
31382
 
31210
31383
  // src/port-registry.ts
31211
- var import_node_fs26 = require("node:fs");
31212
- var import_node_path25 = require("node:path");
31384
+ var import_node_fs27 = require("node:fs");
31385
+ var import_node_path26 = require("node:path");
31213
31386
 
31214
31387
  // ../infra/port-geometry.mjs
31215
31388
  var PORT_BLOCK = 100;
@@ -31223,8 +31396,8 @@ function nextPortBlock(registry2) {
31223
31396
  return [base, base + PORT_SPAN];
31224
31397
  }
31225
31398
  function loadPortRegistry(path2) {
31226
- if (!(0, import_node_fs26.existsSync)(path2)) return {};
31227
- const raw = JSON.parse((0, import_node_fs26.readFileSync)(path2, "utf8"));
31399
+ if (!(0, import_node_fs27.existsSync)(path2)) return {};
31400
+ const raw = JSON.parse((0, import_node_fs27.readFileSync)(path2, "utf8"));
31228
31401
  const out = {};
31229
31402
  for (const [key, value] of Object.entries(raw)) {
31230
31403
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -31252,22 +31425,22 @@ function existingPortRange(repo, registry2) {
31252
31425
  return registry2[repo] ?? null;
31253
31426
  }
31254
31427
  function portRangeInfraAt(root, source) {
31255
- const registryPath = (0, import_node_path25.join)(root, "infra", "port-ranges.json");
31256
- const ddbScriptPath = (0, import_node_path25.join)(root, "infra", "port-ddb.mjs");
31257
- if (!(0, import_node_fs26.existsSync)(registryPath) || !(0, import_node_fs26.existsSync)(ddbScriptPath)) return null;
31428
+ const registryPath = (0, import_node_path26.join)(root, "infra", "port-ranges.json");
31429
+ const ddbScriptPath = (0, import_node_path26.join)(root, "infra", "port-ddb.mjs");
31430
+ if (!(0, import_node_fs27.existsSync)(registryPath) || !(0, import_node_fs27.existsSync)(ddbScriptPath)) return null;
31258
31431
  return { root, source, registryPath, ddbScriptPath };
31259
31432
  }
31260
31433
  function resolvePortRangeInfra(cwd, packageDir) {
31261
31434
  const direct = portRangeInfraAt(cwd, "cwd");
31262
31435
  if (direct) return direct;
31263
- for (let dir = cwd; ; dir = (0, import_node_path25.dirname)(dir)) {
31264
- const sibling = portRangeInfraAt((0, import_node_path25.join)(dir, "MMI-Hub"), "sibling-hub");
31436
+ for (let dir = cwd; ; dir = (0, import_node_path26.dirname)(dir)) {
31437
+ const sibling = portRangeInfraAt((0, import_node_path26.join)(dir, "MMI-Hub"), "sibling-hub");
31265
31438
  if (sibling) return sibling;
31266
- const parent = (0, import_node_path25.dirname)(dir);
31439
+ const parent = (0, import_node_path26.dirname)(dir);
31267
31440
  if (parent === dir) break;
31268
31441
  }
31269
31442
  if (packageDir) {
31270
- const pkgRoot = (0, import_node_path25.join)(packageDir, "..", "..");
31443
+ const pkgRoot = (0, import_node_path26.join)(packageDir, "..", "..");
31271
31444
  const pkgFrom = portRangeInfraAt(pkgRoot, "pkg-root");
31272
31445
  if (pkgFrom) return pkgFrom;
31273
31446
  }
@@ -31284,7 +31457,7 @@ async function ensurePortRangeAtomic(repo, path2, allocate) {
31284
31457
  } catch (e) {
31285
31458
  const why = e.message;
31286
31459
  const missing = /@aws-sdk\/[\w-]+/.exec(why)?.[0];
31287
- throw new Error(`DDB port allocator failed for ${repo} \u2014 refusing to fall back to the frozen ${path2} (it would hand out a block the cursor already gave away). ` + (missing && /cannot find|not found|ERR_MODULE_NOT_FOUND/i.test(why) ? `Missing dependency ${missing}: run \`npm ci\` in ${(0, import_node_path25.dirname)(path2)}, then retry.` : "Check AWS credentials and that the registry table is reachable, then retry.") + ` Cause: ${why}`);
31460
+ throw new Error(`DDB port allocator failed for ${repo} \u2014 refusing to fall back to the frozen ${path2} (it would hand out a block the cursor already gave away). ` + (missing && /cannot find|not found|ERR_MODULE_NOT_FOUND/i.test(why) ? `Missing dependency ${missing}: run \`npm ci\` in ${(0, import_node_path26.dirname)(path2)}, then retry.` : "Check AWS credentials and that the registry table is reachable, then retry.") + ` Cause: ${why}`);
31288
31461
  }
31289
31462
  }
31290
31463
 
@@ -31336,13 +31509,13 @@ async function assignPersistedPortRange(repo, slug, reg, opts) {
31336
31509
  }
31337
31510
 
31338
31511
  // src/box-commands.ts
31339
- var import_node_fs28 = require("node:fs");
31512
+ var import_node_fs29 = require("node:fs");
31340
31513
  var import_node_child_process10 = require("node:child_process");
31341
- var import_node_os16 = require("node:os");
31342
- var import_node_path27 = require("node:path");
31514
+ var import_node_os17 = require("node:os");
31515
+ var import_node_path28 = require("node:path");
31343
31516
 
31344
31517
  // src/box-control.ts
31345
- var import_node_crypto9 = require("node:crypto");
31518
+ var import_node_crypto10 = require("node:crypto");
31346
31519
  var MANIFEST_PATH = "infra/box-control/manifest.json";
31347
31520
  var ALLOWED_POST = /* @__PURE__ */ new Set(["systemctl daemon-reload"]);
31348
31521
  function parseManifest(text) {
@@ -31389,7 +31562,7 @@ function filesForBox(files, box) {
31389
31562
  return files.flatMap((file) => file.targets.filter((t) => t.box === box).map((t) => ({ file, dest: t.dest })));
31390
31563
  }
31391
31564
  function md5(content) {
31392
- return (0, import_node_crypto9.createHash)("md5").update(content).digest("hex");
31565
+ return (0, import_node_crypto10.createHash)("md5").update(content).digest("hex");
31393
31566
  }
31394
31567
  function planRemoteScript(dests) {
31395
31568
  const lines2 = ["set -u"];
@@ -31468,9 +31641,9 @@ function applyRemoteScript(items, date) {
31468
31641
  init_clean_exit();
31469
31642
 
31470
31643
  // src/secrets-commands.ts
31471
- var import_node_fs27 = require("node:fs");
31472
- var import_node_path26 = require("node:path");
31473
- var import_node_os15 = require("node:os");
31644
+ var import_node_fs28 = require("node:fs");
31645
+ var import_node_path27 = require("node:path");
31646
+ var import_node_os16 = require("node:os");
31474
31647
  init_cli_shared();
31475
31648
  init_hub_auth();
31476
31649
  init_github_client();
@@ -32626,18 +32799,18 @@ function collectMap(value, previous = []) {
32626
32799
  return [...previous, value];
32627
32800
  }
32628
32801
  async function decryptRailsCredentials(input) {
32629
- const appDir = (0, import_node_path26.resolve)(input.appDir ?? process.cwd());
32802
+ const appDir = (0, import_node_path27.resolve)(input.appDir ?? process.cwd());
32630
32803
  const credentialsFile = input.credentialsFile ?? DEFAULT_RAILS_CREDENTIALS_FILE;
32631
32804
  const masterKeyFile = input.masterKeyFile ?? DEFAULT_RAILS_MASTER_KEY_FILE;
32632
- const credentialsPath = (0, import_node_path26.resolve)(appDir, credentialsFile);
32633
- const masterKeyPath = (0, import_node_path26.resolve)(appDir, masterKeyFile);
32805
+ const credentialsPath = (0, import_node_path27.resolve)(appDir, credentialsFile);
32806
+ const masterKeyPath = (0, import_node_path27.resolve)(appDir, masterKeyFile);
32634
32807
  const env = {
32635
32808
  ...process.env,
32636
32809
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
32637
32810
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
32638
32811
  };
32639
- if ((0, import_node_fs27.existsSync)(masterKeyPath)) {
32640
- env.RAILS_MASTER_KEY = (0, import_node_fs27.readFileSync)(masterKeyPath, "utf8").trim();
32812
+ if ((0, import_node_fs28.existsSync)(masterKeyPath)) {
32813
+ env.RAILS_MASTER_KEY = (0, import_node_fs28.readFileSync)(masterKeyPath, "utf8").trim();
32641
32814
  }
32642
32815
  const script = [
32643
32816
  'require "json"',
@@ -32647,9 +32820,9 @@ async function decryptRailsCredentials(input) {
32647
32820
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
32648
32821
  "puts JSON.generate(config.config)"
32649
32822
  ].join("\n");
32650
- const scriptDir = (0, import_node_fs27.mkdtempSync)((0, import_node_path26.join)((0, import_node_os15.tmpdir)(), "mmi-rails-decrypt-"));
32651
- const scriptPath = (0, import_node_path26.join)(scriptDir, "decrypt.rb");
32652
- (0, import_node_fs27.writeFileSync)(scriptPath, script, "utf8");
32823
+ const scriptDir = (0, import_node_fs28.mkdtempSync)((0, import_node_path27.join)((0, import_node_os16.tmpdir)(), "mmi-rails-decrypt-"));
32824
+ const scriptPath = (0, import_node_path27.join)(scriptDir, "decrypt.rb");
32825
+ (0, import_node_fs28.writeFileSync)(scriptPath, script, "utf8");
32653
32826
  try {
32654
32827
  const args = ["exec", "ruby", scriptPath];
32655
32828
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -32661,7 +32834,7 @@ async function decryptRailsCredentials(input) {
32661
32834
  });
32662
32835
  return JSON.parse(stdout);
32663
32836
  } finally {
32664
- (0, import_node_fs27.rmSync)(scriptDir, { recursive: true, force: true });
32837
+ (0, import_node_fs28.rmSync)(scriptDir, { recursive: true, force: true });
32665
32838
  }
32666
32839
  }
32667
32840
  async function readSecretStdin() {
@@ -32751,7 +32924,7 @@ function registerSecretsCommands(program3) {
32751
32924
  let body;
32752
32925
  if (o.file) {
32753
32926
  try {
32754
- body = (0, import_node_fs27.readFileSync)((0, import_node_path26.resolve)(o.file), "utf8");
32927
+ body = (0, import_node_fs28.readFileSync)((0, import_node_path27.resolve)(o.file), "utf8");
32755
32928
  } catch (e) {
32756
32929
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
32757
32930
  }
@@ -32887,7 +33060,7 @@ function registerSecretsCommands(program3) {
32887
33060
  {
32888
33061
  ...d,
32889
33062
  decryptRailsCredentials,
32890
- removeFile: (path2) => (0, import_node_fs27.unlinkSync)((0, import_node_path26.resolve)(o.appDir ?? process.cwd(), path2))
33063
+ removeFile: (path2) => (0, import_node_fs28.unlinkSync)((0, import_node_path27.resolve)(o.appDir ?? process.cwd(), path2))
32891
33064
  },
32892
33065
  {
32893
33066
  repo: o.repo,
@@ -33143,7 +33316,7 @@ function registerBoxCommands(program3) {
33143
33316
  }
33144
33317
  const remote = command && command.length ? command.join(" ") : void 0;
33145
33318
  const wroteScript = o.ssh && o.script ? o.script : null;
33146
- if (wroteScript) (0, import_node_fs28.writeFileSync)(wroteScript, sshRecipeScript(found, remote), "utf8");
33319
+ if (wroteScript) (0, import_node_fs29.writeFileSync)(wroteScript, sshRecipeScript(found, remote), "utf8");
33147
33320
  if (o.json) {
33148
33321
  console.log(JSON.stringify({
33149
33322
  box: found,
@@ -33217,17 +33390,17 @@ function hubGitShow(ref) {
33217
33390
  return (path2) => git3(["show", `${ref}:${path2}`]);
33218
33391
  }
33219
33392
  function runOnBox(found, script) {
33220
- const dir = (0, import_node_fs28.mkdtempSync)((0, import_node_path27.join)((0, import_node_os16.tmpdir)(), "mmi-box-control-"));
33393
+ const dir = (0, import_node_fs29.mkdtempSync)((0, import_node_path28.join)((0, import_node_os17.tmpdir)(), "mmi-box-control-"));
33221
33394
  try {
33222
- const recipe = (0, import_node_path27.join)(dir, "recipe.sh");
33223
- (0, import_node_fs28.writeFileSync)(recipe, sshRecipeScript(found, "sh -s"), "utf8");
33395
+ const recipe = (0, import_node_path28.join)(dir, "recipe.sh");
33396
+ (0, import_node_fs29.writeFileSync)(recipe, sshRecipeScript(found, "sh -s"), "utf8");
33224
33397
  const r = (0, import_node_child_process10.spawnSync)("bash", [recipe], { input: script, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 18e4, windowsHide: true });
33225
33398
  if (r.status !== 0) {
33226
33399
  throw new UnreadableError(`box control: the ssh session to ${found.name} failed (exit ${r.status ?? r.signal}): ${(r.stderr || "").trim().split("\n").slice(-3).join(" | ")}`);
33227
33400
  }
33228
33401
  return r.stdout;
33229
33402
  } finally {
33230
- (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
33403
+ (0, import_node_fs29.rmSync)(dir, { recursive: true, force: true });
33231
33404
  }
33232
33405
  }
33233
33406
  function formatControl(mode, box, rows) {
@@ -33355,7 +33528,7 @@ function renderDeployPortDoctor(report) {
33355
33528
  }
33356
33529
 
33357
33530
  // src/bootstrap-drift.ts
33358
- var import_node_crypto10 = require("node:crypto");
33531
+ var import_node_crypto11 = require("node:crypto");
33359
33532
  function byteComparableSeeds(manifest, cls) {
33360
33533
  return manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self" && s.classes.includes(cls));
33361
33534
  }
@@ -33375,7 +33548,7 @@ function compareSeedBytes(hubContent, repoContent) {
33375
33548
  return normalize(hubContent) === normalize(repoContent) ? "match" : "drift";
33376
33549
  }
33377
33550
  function seedContentHash(content) {
33378
- return (0, import_node_crypto10.createHash)("sha256").update(content.replace(/\r\n/g, "\n"), "utf8").digest("hex");
33551
+ return (0, import_node_crypto11.createHash)("sha256").update(content.replace(/\r\n/g, "\n"), "utf8").digest("hex");
33379
33552
  }
33380
33553
  function auditRepoSeedDrift(repo, seeds, hubContents, repoReads) {
33381
33554
  const byTarget = new Map(repoReads.map((r) => [r.target, r.content]));
@@ -33538,7 +33711,7 @@ function renderPropagationReport(plan) {
33538
33711
  }
33539
33712
 
33540
33713
  // src/bootstrap-propagation-identity.ts
33541
- var import_node_crypto11 = require("node:crypto");
33714
+ var import_node_crypto12 = require("node:crypto");
33542
33715
  var PROPAGATION_BRANCH_PREFIX = "seed-propagate-";
33543
33716
  var TARGET_MARKER_NAME = "mmi-bootstrap-propagation-target";
33544
33717
  function safeBranchPart(value, maxLength, fallback) {
@@ -33551,7 +33724,7 @@ function repoSlug2(repo) {
33551
33724
  function propagationBranch(repo, target) {
33552
33725
  const repoPart = safeBranchPart(repoSlug2(repo), 32, "repo");
33553
33726
  const targetPart = safeBranchPart(target, 48, "target");
33554
- const hash = (0, import_node_crypto11.createHash)("sha256").update(repo.trim().toLowerCase()).update("\0").update(target).digest("hex").slice(0, 12);
33727
+ const hash = (0, import_node_crypto12.createHash)("sha256").update(repo.trim().toLowerCase()).update("\0").update(target).digest("hex").slice(0, 12);
33555
33728
  return `${PROPAGATION_BRANCH_PREFIX}${repoPart}-${targetPart}-${hash}`;
33556
33729
  }
33557
33730
  function legacyPropagationBranch(repo) {
@@ -34763,7 +34936,7 @@ function renderBootstrapVerifyReport(report) {
34763
34936
  }
34764
34937
 
34765
34938
  // src/bootstrap-seed-delivery.ts
34766
- var import_node_crypto12 = require("node:crypto");
34939
+ var import_node_crypto13 = require("node:crypto");
34767
34940
  init_github_client();
34768
34941
  var SHA = /^[a-f0-9]{40}$/;
34769
34942
  async function readSeedFile(repo, target, ref, client) {
@@ -34796,7 +34969,7 @@ async function targetedSeedPlan(repo, slug, target, baseBranch, sourceSha, clien
34796
34969
  }
34797
34970
  const baseSha = base?.object?.sha;
34798
34971
  if (!baseSha || !SHA.test(baseSha) || !SHA.test(sourceSha)) throw new Error("bootstrap apply: seed identity is unreadable");
34799
- const identity = (0, import_node_crypto12.createHash)("sha256").update(JSON.stringify([repo.toLowerCase(), target, baseSha, sourceSha])).digest("hex").slice(0, 24);
34972
+ const identity = (0, import_node_crypto13.createHash)("sha256").update(JSON.stringify([repo.toLowerCase(), target, baseSha, sourceSha])).digest("hex").slice(0, 24);
34800
34973
  const delivery = planSeedDelivery(rules, slug, baseBranch, `bootstrap-seed-${identity}`);
34801
34974
  const scoped = forcePr && delivery.mode === "direct" ? { mode: "pr", ref: `bootstrap-seed-${identity}-${slug}`, branch: `bootstrap-seed-${identity}-${slug}`, reason: "registry gate render requires review" } : delivery;
34802
34975
  return { ...scoped, baseSha, baseBranch };
@@ -34862,12 +35035,12 @@ async function verifyTargetedSeedPr(repo, number, plan, target, expected, client
34862
35035
  // src/bootstrap-commands.ts
34863
35036
  var execGitForSeedSource = async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout;
34864
35037
  async function gateRenderDiff(current, rendered) {
34865
- const dir = (0, import_node_fs29.mkdtempSync)((0, import_node_path28.join)((0, import_node_os17.tmpdir)(), "mmi-gate-diff-"));
34866
- const before = (0, import_node_path28.join)(dir, "committed-gate.yml");
34867
- const after = (0, import_node_path28.join)(dir, "registry-render.yml");
35038
+ const dir = (0, import_node_fs30.mkdtempSync)((0, import_node_path29.join)((0, import_node_os18.tmpdir)(), "mmi-gate-diff-"));
35039
+ const before = (0, import_node_path29.join)(dir, "committed-gate.yml");
35040
+ const after = (0, import_node_path29.join)(dir, "registry-render.yml");
34868
35041
  try {
34869
- (0, import_node_fs29.writeFileSync)(before, current);
34870
- (0, import_node_fs29.writeFileSync)(after, rendered);
35042
+ (0, import_node_fs30.writeFileSync)(before, current);
35043
+ (0, import_node_fs30.writeFileSync)(after, rendered);
34871
35044
  try {
34872
35045
  return (await execFileP("git", ["diff", "--no-index", "--", before, after], { timeout: GIT_TIMEOUT_MS })).stdout;
34873
35046
  } catch (e) {
@@ -34876,7 +35049,7 @@ async function gateRenderDiff(current, rendered) {
34876
35049
  throw e;
34877
35050
  }
34878
35051
  } finally {
34879
- (0, import_node_fs29.rmSync)(dir, { recursive: true, force: true });
35052
+ (0, import_node_fs30.rmSync)(dir, { recursive: true, force: true });
34880
35053
  }
34881
35054
  }
34882
35055
  function bootstrapTrainDoctorDeps() {
@@ -34936,13 +35109,13 @@ function registerBootstrapCommands(program3) {
34936
35109
  })),
34937
35110
  pushAllowlistOwners: verifyOwners,
34938
35111
  pushAllowlistOwnersRead: verifyOwnersRead,
34939
- readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs29.existsSync)(path2) ? (0, import_node_fs29.readFileSync)(path2, "utf8") : null,
35112
+ readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs30.existsSync)(path2) ? (0, import_node_fs30.readFileSync)(path2, "utf8") : null,
34940
35113
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
34941
35114
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
34942
35115
  // #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
34943
35116
  // permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
34944
35117
  // sanction, which is the pre-#3664 behaviour.
34945
- sanctionedAdmins: (0, import_node_fs29.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs29.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
35118
+ sanctionedAdmins: (0, import_node_fs30.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs30.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
34946
35119
  requiredGcpApis: (() => {
34947
35120
  const v = meta?.requiredGcpApis;
34948
35121
  if (Array.isArray(v)) return v;
@@ -35020,14 +35193,14 @@ function registerBootstrapCommands(program3) {
35020
35193
  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 () => {
35021
35194
  const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
35022
35195
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
35023
- if (!(0, import_node_fs29.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`);
35196
+ if (!(0, import_node_fs30.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`);
35024
35197
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
35025
35198
  if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
35026
- const manifest = loadBootstrapSeeds((0, import_node_fs29.readFileSync)(manifestPath, "utf8"));
35199
+ const manifest = loadBootstrapSeeds((0, import_node_fs30.readFileSync)(manifestPath, "utf8"));
35027
35200
  const hubContents = /* @__PURE__ */ new Map();
35028
35201
  for (const s of manifest.seeds) {
35029
35202
  if (s.ownership !== "org" || s.source !== "self") continue;
35030
- hubContents.set(s.target, (0, import_node_fs29.existsSync)(s.target) ? (0, import_node_fs29.readFileSync)(s.target, "utf8") : null);
35203
+ hubContents.set(s.target, (0, import_node_fs30.existsSync)(s.target) ? (0, import_node_fs30.readFileSync)(s.target, "utf8") : null);
35031
35204
  }
35032
35205
  let targets;
35033
35206
  let classOf = (_repo) => "deployable";
@@ -35235,24 +35408,24 @@ function registerBootstrapCommands(program3) {
35235
35408
  return;
35236
35409
  }
35237
35410
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
35238
- if (!(0, import_node_fs29.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`);
35411
+ if (!(0, import_node_fs30.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`);
35239
35412
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
35240
35413
  if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
35241
- const manifest = loadBootstrapSeeds((0, import_node_fs29.readFileSync)(manifestPath, "utf8"));
35414
+ const manifest = loadBootstrapSeeds((0, import_node_fs30.readFileSync)(manifestPath, "utf8"));
35242
35415
  const baseBranch = o.class === "content" ? "main" : "development";
35243
35416
  const slug = parsedRepo.slug;
35244
35417
  const onlyTarget = o.fromConfig && o.only.trim() === "gate.yml" ? ".github/workflows/gate.yml" : o.only.trim();
35245
35418
  const gh2 = async (args) => execFileP("gh", args, { timeout: 2e4 });
35246
- const readFile10 = (p) => (0, import_node_fs29.existsSync)(p) ? (0, import_node_fs29.readFileSync)(p, "utf8") : null;
35419
+ const readFile10 = (p) => (0, import_node_fs30.existsSync)(p) ? (0, import_node_fs30.readFileSync)(p, "utf8") : null;
35247
35420
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
35248
35421
  const putSeed = async (target, content, ref, sha) => {
35249
- const tmp = (0, import_node_path28.join)((0, import_node_os17.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
35250
- (0, import_node_fs29.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
35422
+ const tmp = (0, import_node_path29.join)((0, import_node_os18.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
35423
+ (0, import_node_fs30.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
35251
35424
  try {
35252
35425
  await gh2(contentPutInputArgs(repo, target, tmp));
35253
35426
  } finally {
35254
35427
  try {
35255
- (0, import_node_fs29.unlinkSync)(tmp);
35428
+ (0, import_node_fs30.unlinkSync)(tmp);
35256
35429
  } catch {
35257
35430
  }
35258
35431
  }
@@ -35888,10 +36061,10 @@ LIVE apply to ${repo}:
35888
36061
  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 org-owned whole file or declared Hub-managed block)").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 () => {
35889
36062
  const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
35890
36063
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
35891
- if (!(0, import_node_fs29.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`);
36064
+ if (!(0, import_node_fs30.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`);
35892
36065
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
35893
36066
  if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
35894
- const manifest = loadBootstrapSeeds((0, import_node_fs29.readFileSync)(manifestPath, "utf8"));
36067
+ const manifest = loadBootstrapSeeds((0, import_node_fs30.readFileSync)(manifestPath, "utf8"));
35895
36068
  const propagatable = manifest.seeds.filter(isPropagatableSeed);
35896
36069
  if (!o.target) {
35897
36070
  return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
@@ -35900,9 +36073,9 @@ LIVE apply to ${repo}:
35900
36073
  const seed = propagatable.find((s) => s.target === o.target);
35901
36074
  if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no centrally propagatable seed in ${manifestPath}. Propagatable targets:
35902
36075
  ${propagatable.map((s) => s.target).join("\n ")}`);
35903
- if (!seed.managedBlock && !(0, import_node_fs29.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
35904
- const hubContent = seed.managedBlock ? null : (0, import_node_fs29.readFileSync)(seed.target, "utf8");
35905
- const readSeedFile2 = (path2) => (0, import_node_fs29.existsSync)(path2) ? (0, import_node_fs29.readFileSync)(path2, "utf8") : null;
36076
+ if (!seed.managedBlock && !(0, import_node_fs30.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
36077
+ const hubContent = seed.managedBlock ? null : (0, import_node_fs30.readFileSync)(seed.target, "utf8");
36078
+ const readSeedFile2 = (path2) => (0, import_node_fs30.existsSync)(path2) ? (0, import_node_fs30.readFileSync)(path2, "utf8") : null;
35906
36079
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
35907
36080
  const cfg = await loadConfig();
35908
36081
  const projects = await fetchProjectsList(registryClientDeps(cfg));
@@ -35911,9 +36084,9 @@ LIVE apply to ${repo}:
35911
36084
  }
35912
36085
  const rosterRepos = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
35913
36086
  let independentCount = rosterRepos.length;
35914
- if ((0, import_node_fs29.existsSync)("projects.json")) {
36087
+ if ((0, import_node_fs30.existsSync)("projects.json")) {
35915
36088
  try {
35916
- const local = JSON.parse((0, import_node_fs29.readFileSync)("projects.json", "utf8"));
36089
+ const local = JSON.parse((0, import_node_fs30.readFileSync)("projects.json", "utf8"));
35917
36090
  const localRepos = /* @__PURE__ */ new Set();
35918
36091
  for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
35919
36092
  const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
@@ -36083,15 +36256,15 @@ LIVE apply to ${repo}:
36083
36256
  } catch {
36084
36257
  existingSha = void 0;
36085
36258
  }
36086
- const tmp = (0, import_node_path28.join)((0, import_node_os17.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
36259
+ const tmp = (0, import_node_path29.join)((0, import_node_os18.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
36087
36260
  const desiredContent = desiredByRepo.get(rec.repo);
36088
36261
  if (desiredContent == null) return fail(`bootstrap propagate: no resolved content for ${rec.repo} ${seed.target} \u2014 refusing to write`);
36089
- (0, import_node_fs29.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha)), "utf8");
36262
+ (0, import_node_fs30.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha)), "utf8");
36090
36263
  try {
36091
36264
  await gh2(contentPutInputArgs(rec.repo, seed.target, tmp));
36092
36265
  } finally {
36093
36266
  try {
36094
- (0, import_node_fs29.unlinkSync)(tmp);
36267
+ (0, import_node_fs30.unlinkSync)(tmp);
36095
36268
  } catch {
36096
36269
  }
36097
36270
  }
@@ -36160,10 +36333,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
36160
36333
  return fail(`bootstrap rollback: ${e.message}`);
36161
36334
  }
36162
36335
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
36163
- if (!(0, import_node_fs29.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)`);
36336
+ if (!(0, import_node_fs30.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)`);
36164
36337
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
36165
36338
  if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
36166
- const manifest = loadBootstrapSeeds((0, import_node_fs29.readFileSync)(manifestPath, "utf8"));
36339
+ const manifest = loadBootstrapSeeds((0, import_node_fs30.readFileSync)(manifestPath, "utf8"));
36167
36340
  const propagatable = manifest.seeds.filter(isPropagatableSeed);
36168
36341
  if (!o.target) {
36169
36342
  return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
@@ -36180,10 +36353,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
36180
36353
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
36181
36354
  let candidates;
36182
36355
  if (o.record) {
36183
- if (!(0, import_node_fs29.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
36356
+ if (!(0, import_node_fs30.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
36184
36357
  let parsed;
36185
36358
  try {
36186
- parsed = JSON.parse((0, import_node_fs29.readFileSync)(o.record, "utf8"));
36359
+ parsed = JSON.parse((0, import_node_fs30.readFileSync)(o.record, "utf8"));
36187
36360
  } catch (e) {
36188
36361
  return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
36189
36362
  }
@@ -36260,13 +36433,13 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
36260
36433
  } catch {
36261
36434
  existingSha = void 0;
36262
36435
  }
36263
- const tmp = (0, import_node_path28.join)((0, import_node_os17.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
36264
- (0, import_node_fs29.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
36436
+ const tmp = (0, import_node_path29.join)((0, import_node_os18.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
36437
+ (0, import_node_fs30.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
36265
36438
  try {
36266
36439
  await gh2(contentPutInputArgs(repo, seed.target, tmp));
36267
36440
  } finally {
36268
36441
  try {
36269
- (0, import_node_fs29.unlinkSync)(tmp);
36442
+ (0, import_node_fs30.unlinkSync)(tmp);
36270
36443
  } catch {
36271
36444
  }
36272
36445
  }
@@ -36442,7 +36615,7 @@ init_github_client();
36442
36615
  init_cli_shared();
36443
36616
 
36444
36617
  // src/suite-status.ts
36445
- var import_node_crypto13 = require("node:crypto");
36618
+ var import_node_crypto14 = require("node:crypto");
36446
36619
  var SUITE_REPO = "mutmutco/MM-Work";
36447
36620
  var REPOS = {
36448
36621
  "mmi-scout": "mutmutco/MMI-Scout",
@@ -36470,7 +36643,7 @@ function parseSuiteMapping(body) {
36470
36643
  return void 0;
36471
36644
  }
36472
36645
  }
36473
- var sha256 = (b) => (0, import_node_crypto13.createHash)("sha256").update(b).digest("hex");
36646
+ var sha256 = (b) => (0, import_node_crypto14.createHash)("sha256").update(b).digest("hex");
36474
36647
  async function proveBundle(url, tag, fetchUrl) {
36475
36648
  const get = async (u) => {
36476
36649
  try {
@@ -36723,9 +36896,9 @@ async function waitSuiteDev(deps, opts) {
36723
36896
  }
36724
36897
 
36725
36898
  // src/suite-train.ts
36726
- var import_node_fs30 = require("node:fs");
36727
- var import_node_path29 = require("node:path");
36728
- var import_node_crypto14 = require("node:crypto");
36899
+ var import_node_fs31 = require("node:fs");
36900
+ var import_node_path30 = require("node:path");
36901
+ var import_node_crypto15 = require("node:crypto");
36729
36902
 
36730
36903
  // src/kit-version.ts
36731
36904
  var parse = (v) => /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(typeof v === "string" ? v.trim() : "");
@@ -36810,7 +36983,7 @@ function suiteReleaseTag(rc) {
36810
36983
  function readSuiteCut(path2) {
36811
36984
  let raw;
36812
36985
  try {
36813
- raw = (0, import_node_fs30.readFileSync)(path2, "utf8");
36986
+ raw = (0, import_node_fs31.readFileSync)(path2, "utf8");
36814
36987
  } catch (e) {
36815
36988
  if (e.code === "ENOENT") return void 0;
36816
36989
  throw e;
@@ -36826,11 +36999,11 @@ function readSuiteCut(path2) {
36826
36999
  return record;
36827
37000
  }
36828
37001
  function writeSuiteCut(path2, record) {
36829
- (0, import_node_fs30.mkdirSync)((0, import_node_path29.dirname)(path2), { recursive: true });
36830
- const temp = `${path2}.${(0, import_node_crypto14.randomBytes)(8).toString("hex")}.tmp`;
37002
+ (0, import_node_fs31.mkdirSync)((0, import_node_path30.dirname)(path2), { recursive: true });
37003
+ const temp = `${path2}.${(0, import_node_crypto15.randomBytes)(8).toString("hex")}.tmp`;
36831
37004
  try {
36832
- (0, import_node_fs30.writeFileSync)(temp, JSON.stringify(record, null, 2), { flag: "wx" });
36833
- (0, import_node_fs30.renameSync)(temp, path2);
37005
+ (0, import_node_fs31.writeFileSync)(temp, JSON.stringify(record, null, 2), { flag: "wx" });
37006
+ (0, import_node_fs31.renameSync)(temp, path2);
36834
37007
  } catch (e) {
36835
37008
  throw new Error(`suite cut record write failed at ${path2}: ${e.message}; stop, verify the file before retrying`);
36836
37009
  }
@@ -36879,25 +37052,25 @@ async function suiteMarkAbandoned(deps, ownerGo = false) {
36879
37052
  return tags.map((t) => `${t.repo}@${t.tag}`);
36880
37053
  }
36881
37054
  async function retireFailedLeadRcLedger(deps, ownerGo) {
36882
- if (!(0, import_node_fs30.existsSync)(deps.ledgerPath)) return void 0;
37055
+ if (!(0, import_node_fs31.existsSync)(deps.ledgerPath)) return void 0;
36883
37056
  return withLedgerLock(deps.ledgerPath, async (fence) => {
36884
- const ledger = parseReleaseLedger((0, import_node_fs30.readFileSync)(deps.ledgerPath, "utf8"));
37057
+ const ledger = parseReleaseLedger((0, import_node_fs31.readFileSync)(deps.ledgerPath, "utf8"));
36885
37058
  const states = Object.values(ledger.phases).map((p) => p.state);
36886
37059
  if (ledger.repo !== SUITE_REPO || ledger.lane !== "rcand" || ledger.phases.promotion.state === "complete" || !states.includes("failed")) return void 0;
36887
37060
  if (!ownerGo) throw new Error(`the lead's failed rcand ledger for ${ledger.tag} blocks every train; retire it with suite abandon --owner-go`);
36888
37061
  if ((await deps.rcHead())?.toLowerCase() === ledger.tagSha.toLowerCase()) throw new Error(`origin rc already points at ${ledger.tag}; it was promoted, so its ledger is not retired`);
36889
- const archive = (0, import_node_path29.join)((0, import_node_path29.dirname)(deps.ledgerPath), `phases.archive-${ledger.tag}.json`);
36890
- if ((0, import_node_fs30.existsSync)(archive)) throw new Error(`ledger archive already exists at ${archive}; inspect before retiring again`);
37062
+ const archive = (0, import_node_path30.join)((0, import_node_path30.dirname)(deps.ledgerPath), `phases.archive-${ledger.tag}.json`);
37063
+ if ((0, import_node_fs31.existsSync)(archive)) throw new Error(`ledger archive already exists at ${archive}; inspect before retiring again`);
36891
37064
  await deps.markAbandoned(SUITE_REPO, ledger.tag, ledger.tagSha);
36892
- await fence(() => (0, import_node_fs30.renameSync)(deps.ledgerPath, archive));
37065
+ await fence(() => (0, import_node_fs31.renameSync)(deps.ledgerPath, archive));
36893
37066
  return `${ledger.tag} (ledger archived to ${archive})`;
36894
37067
  });
36895
37068
  }
36896
37069
  function suiteAbandon(recordPath, ownerGo = false, now = /* @__PURE__ */ new Date()) {
36897
37070
  const record = abandonableCut(recordPath, ownerGo);
36898
37071
  const archive = `${recordPath}.abandoned-${record.leadDevelopment.slice(0, 12)}-${now.toISOString().replace(/[:.]/g, "")}.json`;
36899
- if ((0, import_node_fs30.existsSync)(archive)) throw new Error(`abandoned-cut archive already exists at ${archive}; inspect before abandoning again`);
36900
- (0, import_node_fs30.renameSync)(recordPath, archive);
37072
+ if ((0, import_node_fs31.existsSync)(archive)) throw new Error(`abandoned-cut archive already exists at ${archive}; inspect before abandoning again`);
37073
+ (0, import_node_fs31.renameSync)(recordPath, archive);
36901
37074
  return { archive, orphanTags: record.members.filter((m) => m.tag).map((m) => `${m.repo}@${m.tag}`) };
36902
37075
  }
36903
37076
  async function suiteRestoreMainPins(deps) {
@@ -36963,12 +37136,12 @@ async function suiteRcand(deps, opts) {
36963
37136
  }
36964
37137
  if ((record?.announcement === "sent" || record?.announcement === "skipped") && record.leadReleased) {
36965
37138
  const archive = `${deps.recordPath}.${record.leadRcTag}.json`;
36966
- if ((0, import_node_fs30.existsSync)(archive)) throw new Error(`suite cut archive already exists at ${archive}; inspect before a new cut`);
36967
- (0, import_node_fs30.renameSync)(deps.recordPath, archive);
37139
+ if ((0, import_node_fs31.existsSync)(archive)) throw new Error(`suite cut archive already exists at ${archive}; inspect before a new cut`);
37140
+ (0, import_node_fs31.renameSync)(deps.recordPath, archive);
36968
37141
  record = void 0;
36969
37142
  }
36970
37143
  if (record && !record.pinPr && !record.leadRcTag && record.members.every((m) => !m.tag)) {
36971
- (0, import_node_fs30.rmSync)(deps.recordPath, { force: true });
37144
+ (0, import_node_fs31.rmSync)(deps.recordPath, { force: true });
36972
37145
  record = void 0;
36973
37146
  }
36974
37147
  if (!record) {
@@ -37022,7 +37195,7 @@ async function suiteRcand(deps, opts) {
37022
37195
  quiet.push(member);
37023
37196
  }
37024
37197
  if (record.members.every((m) => m.carried || quiet.includes(m)) && await deps.contains(SUITE_REPO, record.leadDevelopment, record.leadPreviousRc)) {
37025
- (0, import_node_fs30.rmSync)(deps.recordPath, { force: true });
37198
+ (0, import_node_fs31.rmSync)(deps.recordPath, { force: true });
37026
37199
  throw new Error("nothing to promote: neither MM-Work nor any module has new development commits since its rc; no suite cut started");
37027
37200
  }
37028
37201
  for (const member of quiet) {
@@ -37040,7 +37213,7 @@ async function suiteRcand(deps, opts) {
37040
37213
  }
37041
37214
  if (refusals.length) {
37042
37215
  const untouched = record.members.every((m) => !m.tag) && !record.pinPr;
37043
- if (untouched) (0, import_node_fs30.rmSync)(deps.recordPath, { force: true });
37216
+ if (untouched) (0, import_node_fs31.rmSync)(deps.recordPath, { force: true });
37044
37217
  throw new Error(`module rc serving is not ready; ${untouched ? "no suite cut started" : "no new tag was cut"}:
37045
37218
  ${refusals.join("\n")}
37046
37219
  Each module must ship a live release that bind-mounts <deployPath>/data read-only and serves <data>/rc/module.js at /rc/module.js (docs/Guides/suite-trains.md).`);
@@ -37197,11 +37370,11 @@ Each member's live release must serve <data>/main/module.js at its main pin path
37197
37370
  }
37198
37371
  return record;
37199
37372
  }
37200
- var hotfixRecordPath = (deps) => (0, import_node_path29.join)((0, import_node_path29.dirname)(deps.recordPath), "hotfix.json");
37373
+ var hotfixRecordPath = (deps) => (0, import_node_path30.join)((0, import_node_path30.dirname)(deps.recordPath), "hotfix.json");
37201
37374
  function readSuiteHotfix(path2) {
37202
37375
  let raw;
37203
37376
  try {
37204
- raw = (0, import_node_fs30.readFileSync)(path2, "utf8");
37377
+ raw = (0, import_node_fs31.readFileSync)(path2, "utf8");
37205
37378
  } catch (e) {
37206
37379
  if (e.code === "ENOENT") return void 0;
37207
37380
  throw e;
@@ -37244,7 +37417,7 @@ async function suiteHotfix(deps, opts) {
37244
37417
  if (completed) record = void 0;
37245
37418
  if (record && record.repo !== found.repo) throw new Error(`an unfinished suite hotfix for ${record.repo} is recorded; finish it (rerun with that member) first`);
37246
37419
  if (!record?.tag) await deps.validateHotfixSummary();
37247
- if (completed) (0, import_node_fs30.renameSync)(path2, `${path2}.${completed.leadTag}.json`);
37420
+ if (completed) (0, import_node_fs31.renameSync)(path2, `${path2}.${completed.leadTag}.json`);
37248
37421
  const rec = record ?? { schema: "mmi-suite-hotfix/v1", member: found.id, repo: found.repo, from: opts.from, ...opts.ack?.length ? { ack: opts.ack } : {} };
37249
37422
  const save = () => writeSuiteHotfix(path2, rec);
37250
37423
  save();
@@ -37511,8 +37684,8 @@ async function runRcDataSwitch(deps, opts) {
37511
37684
  }
37512
37685
 
37513
37686
  // src/suite-train-io.ts
37514
- var import_node_fs44 = require("node:fs");
37515
- var import_node_path43 = require("node:path");
37687
+ var import_node_fs45 = require("node:fs");
37688
+ var import_node_path44 = require("node:path");
37516
37689
  init_cli_shared();
37517
37690
 
37518
37691
  // src/command-register-train-operations.ts
@@ -37867,8 +38040,8 @@ async function preflightHotfixBatchPicks(deps, sources, pickTolerated) {
37867
38040
  if (sources.length === 0) return { failures: [], skipped: [] };
37868
38041
  const { mkdtemp: mkdtemp2, rm: rm2 } = await import("node:fs/promises");
37869
38042
  const { tmpdir: tmpdir12 } = await import("node:os");
37870
- const { join: join47 } = await import("node:path");
37871
- const dir = await mkdtemp2(join47(tmpdir12(), "mmi-hotfix-preflight-"));
38043
+ const { join: join48 } = await import("node:path");
38044
+ const dir = await mkdtemp2(join48(tmpdir12(), "mmi-hotfix-preflight-"));
37872
38045
  const wt = { run: (file, args) => deps.run(file, file === "git" ? ["-C", dir, ...args] : args) };
37873
38046
  const failures = [];
37874
38047
  const skipped = [];
@@ -39189,9 +39362,9 @@ function checkHotfixCarries(options) {
39189
39362
  }
39190
39363
 
39191
39364
  // src/merge-cleanup.ts
39192
- var import_node_fs32 = require("node:fs");
39193
- var import_node_path31 = require("node:path");
39194
- var import_node_os18 = require("node:os");
39365
+ var import_node_fs33 = require("node:fs");
39366
+ var import_node_path32 = require("node:path");
39367
+ var import_node_os19 = require("node:os");
39195
39368
  init_cli_shared();
39196
39369
  init_github_client();
39197
39370
 
@@ -39505,8 +39678,8 @@ async function runPrLand(prNumber, options, deps) {
39505
39678
 
39506
39679
  // src/test-policy-core.ts
39507
39680
  var import_node_child_process13 = require("node:child_process");
39508
- var import_node_fs31 = require("node:fs");
39509
- var import_node_path30 = require("node:path");
39681
+ var import_node_fs32 = require("node:fs");
39682
+ var import_node_path31 = require("node:path");
39510
39683
 
39511
39684
  // src/test-command-policy-shared.mjs
39512
39685
  var import_node_child_process12 = require("node:child_process");
@@ -39982,7 +40155,7 @@ function isMeaningfulRow(file) {
39982
40155
  return file.meaningful !== false;
39983
40156
  }
39984
40157
  function loadPolicy(root, readFile10 = readFileOrNull2) {
39985
- const raw = readFile10((0, import_node_path30.join)(root, POLICY_FILE));
40158
+ const raw = readFile10((0, import_node_path31.join)(root, POLICY_FILE));
39986
40159
  if (raw == null) return { mandatory: [], declared: false };
39987
40160
  return parsePolicy(raw, POLICY_FILE);
39988
40161
  }
@@ -40059,7 +40232,7 @@ function loadPolicySource(root, explicitRef, diffBase) {
40059
40232
  }
40060
40233
  function readFileOrNull2(path2) {
40061
40234
  try {
40062
- return (0, import_node_fs31.readFileSync)(path2, "utf8");
40235
+ return (0, import_node_fs32.readFileSync)(path2, "utf8");
40063
40236
  } catch {
40064
40237
  return null;
40065
40238
  }
@@ -40087,12 +40260,12 @@ function classify(changed, policy, present = () => false) {
40087
40260
  const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
40088
40261
  return { mandatoryHits, untestedHits, testChanges, meaningfulTestChanges, addedTests, removedProtected };
40089
40262
  }
40090
- function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs31.existsSync)(path2)) {
40091
- return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path30.join)(root, p)));
40263
+ function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs32.existsSync)(path2)) {
40264
+ return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path31.join)(root, p)));
40092
40265
  }
40093
- function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs31.existsSync)(path2)) {
40266
+ function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs32.existsSync)(path2)) {
40094
40267
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
40095
- return [...new Set(declared)].filter((p) => !exists((0, import_node_path30.join)(root, p)));
40268
+ return [...new Set(declared)].filter((p) => !exists((0, import_node_path31.join)(root, p)));
40096
40269
  }
40097
40270
  function evaluate(changed, policy, present = () => false) {
40098
40271
  const { mandatoryHits, untestedHits, meaningfulTestChanges, addedTests, removedProtected } = classify(changed, policy, present);
@@ -40231,14 +40404,14 @@ function runTestPolicy(root, deps = {}) {
40231
40404
  }
40232
40405
  const loaded = deps.policy ? { policy: deps.policy, source: { ref: null, sha: null, path: POLICY_FILE } } : loadPolicySource(root, deps.policyRef, deps.base);
40233
40406
  const { policy, source: policySource } = loaded;
40234
- const exists = deps.exists ?? ((path2) => (0, import_node_fs31.existsSync)(path2));
40407
+ const exists = deps.exists ?? ((path2) => (0, import_node_fs32.existsSync)(path2));
40235
40408
  const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
40236
40409
  const base = deps.changed ? "(injected)" : deps.policyRef ? resolveHotfixBase(root) : resolveBase(root, deps.base);
40237
40410
  const refusal = deps.changed ? null : untrustworthyRange(root, base);
40238
40411
  const raw = deps.changed ?? (refusal ? [] : changedFilesSince(base, root));
40239
40412
  const changed = deps.changed ? raw : annotateChangeMeaning(raw, policy, (path2) => ({
40240
40413
  before: blobAt(base, path2, root),
40241
- after: readFileOrNull2((0, import_node_path30.join)(root, path2))
40414
+ after: readFileOrNull2((0, import_node_path31.join)(root, path2))
40242
40415
  }));
40243
40416
  const lookup = deps.override !== void 0 ? { override: deps.override, refusals: [] } : !deps.changed && !refusal ? readOverride2(base, root) : { override: null, refusals: [] };
40244
40417
  const policyRefusals = policy.declared === false ? [{
@@ -40248,8 +40421,8 @@ function runTestPolicy(root, deps = {}) {
40248
40421
  A gate with no policy cannot decide which test commands are required or permitted.
40249
40422
  ` + (deps.base === HOTFIX_DIFF_BASE ? ` Hotfix lane (--base ${HOTFIX_DIFF_BASE}): pass --policy-ref <exact-${HOTFIX_POLICY_REF}-commit> so the current policy is read from ${HOTFIX_POLICY_REF}.` : ` Restore ${POLICY_FILE} on this branch; the policy file belongs on every non-hotfix lane.`)
40250
40423
  }] : [];
40251
- const present = (path2) => exists((0, import_node_path30.join)(root, path2));
40252
- const policyTree = policySource.sha ? new Set(git2(["ls-tree", "-r", "-z", "--name-only", policySource.sha], root).split("\0").filter(Boolean).map((p) => (0, import_node_path30.join)(root, p))) : null;
40424
+ const present = (path2) => exists((0, import_node_path31.join)(root, path2));
40425
+ const policyTree = policySource.sha ? new Set(git2(["ls-tree", "-r", "-z", "--name-only", policySource.sha], root).split("\0").filter(Boolean).map((p) => (0, import_node_path31.join)(root, p))) : null;
40253
40426
  const policyTreeExists = policyTree ? (abs) => policyTree.has(abs) : exists;
40254
40427
  const where = policySource.sha ? `${policySource.ref}@${policySource.sha}` : "this worktree";
40255
40428
  const removedByThisDiff = removedPaths(changed);
@@ -40529,13 +40702,13 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
40529
40702
  return rewritten === base ? null : rewritten;
40530
40703
  }
40531
40704
  function writeSquashBodyFile(body) {
40532
- const dir = (0, import_node_fs32.mkdtempSync)((0, import_node_path31.join)((0, import_node_os18.tmpdir)(), "mmi-squash-body-"));
40533
- const path2 = (0, import_node_path31.join)(dir, "body.txt");
40534
- (0, import_node_fs32.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
40705
+ const dir = (0, import_node_fs33.mkdtempSync)((0, import_node_path32.join)((0, import_node_os19.tmpdir)(), "mmi-squash-body-"));
40706
+ const path2 = (0, import_node_path32.join)(dir, "body.txt");
40707
+ (0, import_node_fs33.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
40535
40708
  `, "utf8");
40536
40709
  return { path: path2, cleanup: () => {
40537
40710
  try {
40538
- (0, import_node_fs32.rmSync)(dir, { recursive: true, force: true });
40711
+ (0, import_node_fs33.rmSync)(dir, { recursive: true, force: true });
40539
40712
  } catch {
40540
40713
  }
40541
40714
  } };
@@ -40742,8 +40915,8 @@ async function deleteMergedRemoteBranch(options) {
40742
40915
  }
40743
40916
 
40744
40917
  // src/project-info-sync.ts
40745
- var import_node_fs33 = require("node:fs");
40746
- var import_node_path32 = require("node:path");
40918
+ var import_node_fs34 = require("node:fs");
40919
+ var import_node_path33 = require("node:path");
40747
40920
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
40748
40921
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
40749
40922
  projectV2 { id }
@@ -40790,14 +40963,14 @@ function sharedName(entries, fallback) {
40790
40963
  }
40791
40964
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
40792
40965
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
40793
- const readmePath = (0, import_node_path32.join)(repoRoot2, "README.md");
40794
- if (!(0, import_node_fs33.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
40966
+ const readmePath = (0, import_node_path33.join)(repoRoot2, "README.md");
40967
+ if (!(0, import_node_fs34.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
40795
40968
  const entries = entriesFor(project2, projects);
40796
40969
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
40797
40970
  const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
40798
40971
  if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
40799
40972
  const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
40800
- const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs33.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
40973
+ const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs34.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
40801
40974
  const lines2 = [
40802
40975
  `# ${projectName}`,
40803
40976
  "",
@@ -40816,8 +40989,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
40816
40989
  const targetBase = `https://github.com/${targetRepo2}`;
40817
40990
  const targetBranch = branchFor(targetRepo2, projects);
40818
40991
  const orgDocs = [
40819
- (0, import_node_fs33.existsSync)((0, import_node_path32.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
40820
- (0, import_node_fs33.existsSync)((0, import_node_path32.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
40992
+ (0, import_node_fs34.existsSync)((0, import_node_path33.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
40993
+ (0, import_node_fs34.existsSync)((0, import_node_path33.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
40821
40994
  ].filter(Boolean);
40822
40995
  if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
40823
40996
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
@@ -40839,8 +41012,8 @@ async function syncProjectInfo(plan, client, apply) {
40839
41012
  }
40840
41013
 
40841
41014
  // src/train-commands.ts
40842
- var import_node_fs34 = require("node:fs");
40843
- var import_node_path33 = require("node:path");
41015
+ var import_node_fs35 = require("node:fs");
41016
+ var import_node_path34 = require("node:path");
40844
41017
  init_cli_shared();
40845
41018
  init_clean_exit();
40846
41019
  init_client_version();
@@ -40855,7 +41028,7 @@ function resolveReleaseBumpIntent(raw) {
40855
41028
  }
40856
41029
  function readRepoVersion() {
40857
41030
  try {
40858
- return JSON.parse((0, import_node_fs34.readFileSync)((0, import_node_path33.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
41031
+ return JSON.parse((0, import_node_fs35.readFileSync)((0, import_node_path34.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
40859
41032
  } catch {
40860
41033
  return void 0;
40861
41034
  }
@@ -40966,7 +41139,7 @@ function releaseProgressVerdict(status, subject = "Release") {
40966
41139
 
40967
41140
  // src/suite-pin.ts
40968
41141
  var import_promises6 = require("node:fs/promises");
40969
- var import_node_path34 = require("node:path");
41142
+ var import_node_path35 = require("node:path");
40970
41143
  var SuitePinError = class _SuitePinError extends Error {
40971
41144
  diagnostic;
40972
41145
  constructor(repo, tag, error) {
@@ -41034,8 +41207,8 @@ async function openSuiteCutPinPr(deps, input) {
41034
41207
  if (input.carriedOnly) return { status: "unchanged" };
41035
41208
  throw new Error("pins already match without a merged cut PR \u2014 provenance unverified");
41036
41209
  }
41037
- await (0, import_promises6.mkdir)((0, import_node_path34.join)(deps.root, "tmp"), { recursive: true });
41038
- scratch = await (0, import_promises6.mkdtemp)((0, import_node_path34.join)(deps.root, "tmp", "suite-pin-"));
41210
+ await (0, import_promises6.mkdir)((0, import_node_path35.join)(deps.root, "tmp"), { recursive: true });
41211
+ scratch = await (0, import_promises6.mkdtemp)((0, import_node_path35.join)(deps.root, "tmp", "suite-pin-"));
41039
41212
  const run = (file, args) => deps.run(file, args, scratch);
41040
41213
  await run("git", ["clone", "--quiet", "--branch", prs.length ? branch : "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
41041
41214
  if (prs.length) {
@@ -41047,7 +41220,7 @@ async function openSuiteCutPinPr(deps, input) {
41047
41220
  await run("git", ["switch", "-c", branch]);
41048
41221
  }
41049
41222
  for (const stage of ["rc", "main"]) {
41050
- const path2 = (0, import_node_path34.join)(scratch, `${stage}-pins.json`);
41223
+ const path2 = (0, import_node_path35.join)(scratch, `${stage}-pins.json`);
41051
41224
  await (0, import_promises6.writeFile)(path2, JSON.stringify(input.pins.map((p) => ({ module: p.module, url: p[stage] }))));
41052
41225
  await run("node", ["scripts/pin-modules.mjs", "--stage", stage, "--pins", path2]);
41053
41226
  }
@@ -41100,12 +41273,12 @@ async function openSuiteRestorePinPr(deps, input) {
41100
41273
  }
41101
41274
  });
41102
41275
  if (!todo.length) return void 0;
41103
- await (0, import_promises6.mkdir)((0, import_node_path34.join)(deps.root, "tmp"), { recursive: true });
41104
- scratch = await (0, import_promises6.mkdtemp)((0, import_node_path34.join)(deps.root, "tmp", "suite-pin-"));
41276
+ await (0, import_promises6.mkdir)((0, import_node_path35.join)(deps.root, "tmp"), { recursive: true });
41277
+ scratch = await (0, import_promises6.mkdtemp)((0, import_node_path35.join)(deps.root, "tmp", "suite-pin-"));
41105
41278
  const run = (file, args) => deps.run(file, args, scratch);
41106
41279
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
41107
41280
  await run("git", ["switch", "-c", branch]);
41108
- const path2 = (0, import_node_path34.join)(scratch, "main-pins.json");
41281
+ const path2 = (0, import_node_path35.join)(scratch, "main-pins.json");
41109
41282
  await (0, import_promises6.writeFile)(path2, JSON.stringify(todo.map((p) => ({ module: p.module, url: p.prior }))));
41110
41283
  await run("node", ["scripts/pin-modules.mjs", "--stage", "main", "--pins", path2]);
41111
41284
  await run("git", ["add", "seed/modules.json"]);
@@ -41179,8 +41352,8 @@ async function openSuitePinPr(deps, input) {
41179
41352
  if (newer.length) return { status: "superseded", pr: newer[0].url, url: pin };
41180
41353
  const open2 = onBranch.find((p) => p.state === "OPEN");
41181
41354
  if (open2 && tagOf(open2.title ?? "") === tag) return { status: "pending", pr: open2.url, url: pin };
41182
- await (0, import_promises6.mkdir)((0, import_node_path34.join)(deps.root, "tmp"), { recursive: true });
41183
- scratch = await (0, import_promises6.mkdtemp)((0, import_node_path34.join)(deps.root, "tmp", "suite-pin-"));
41355
+ await (0, import_promises6.mkdir)((0, import_node_path35.join)(deps.root, "tmp"), { recursive: true });
41356
+ scratch = await (0, import_promises6.mkdtemp)((0, import_node_path35.join)(deps.root, "tmp", "suite-pin-"));
41184
41357
  const run = (file, args) => deps.run(file, args, scratch);
41185
41358
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
41186
41359
  await run("git", ["switch", "-c", branch]);
@@ -41220,7 +41393,7 @@ async function openSuitePinPr(deps, input) {
41220
41393
 
41221
41394
  // src/command-register-collaboration.ts
41222
41395
  var import_node_child_process17 = require("node:child_process");
41223
- var import_node_fs43 = require("node:fs");
41396
+ var import_node_fs44 = require("node:fs");
41224
41397
  var import_promises8 = require("node:fs/promises");
41225
41398
  init_clean_exit();
41226
41399
  init_cli_shared();
@@ -41244,11 +41417,11 @@ function spawnDetachedSelf(args, deps, opts = {}) {
41244
41417
  }
41245
41418
 
41246
41419
  // src/command-register-collaboration.ts
41247
- var import_node_path42 = require("node:path");
41420
+ var import_node_path43 = require("node:path");
41248
41421
  init_house_map();
41249
41422
 
41250
41423
  // src/issue-body.ts
41251
- var import_node_os19 = require("node:os");
41424
+ var import_node_os20 = require("node:os");
41252
41425
  init_error_codes();
41253
41426
  var TextArgError = class extends Error {
41254
41427
  constructor(message2, code, offendingFlag) {
@@ -41261,7 +41434,7 @@ var TextArgError = class extends Error {
41261
41434
  offendingFlag;
41262
41435
  };
41263
41436
  function emptyStdinMessage(fileFlag) {
41264
- if ((0, import_node_os19.platform)() === "win32") {
41437
+ if ((0, import_node_os20.platform)() === "win32") {
41265
41438
  return `${fileFlag} - read empty stdin (on Windows, ${fileFlag} - is unreliable through the npm .cmd shim \u2014 use ${fileFlag} <path>, or pipe to \`node cli/dist/index.cjs\` directly)`;
41266
41439
  }
41267
41440
  return `${fileFlag} - read empty stdin (nothing piped \u2014 pass a heredoc/pipe, or ${fileFlag} <path>)`;
@@ -41354,8 +41527,8 @@ init_github_client();
41354
41527
  init_github_quota();
41355
41528
 
41356
41529
  // src/issue-commands.ts
41357
- var import_node_fs35 = require("node:fs");
41358
- var import_node_crypto15 = require("node:crypto");
41530
+ var import_node_fs36 = require("node:fs");
41531
+ var import_node_crypto16 = require("node:crypto");
41359
41532
  init_cli_shared();
41360
41533
  init_clean_exit();
41361
41534
  init_error_codes();
@@ -41547,7 +41720,7 @@ async function editIssue(client, options, deps = {}) {
41547
41720
  const url = `https://github.com/${repo}/issues/${parsed.number}`;
41548
41721
  const patch = {};
41549
41722
  let bodyChanged = false;
41550
- const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs35.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
41723
+ const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs36.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
41551
41724
  if (options.titleFile !== void 0) {
41552
41725
  patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
41553
41726
  } else if (options.title !== void 0) {
@@ -41828,7 +42001,7 @@ function rowIdempotencyKey(batchKey, spec) {
41828
42001
  const identity = `${spec.type}
41829
42002
  ${spec.title.trim()}
41830
42003
  ${spec.body ?? ""}`;
41831
- const hash = (0, import_node_crypto15.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
42004
+ const hash = (0, import_node_crypto16.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
41832
42005
  return `${batchKey}:${hash}`;
41833
42006
  }
41834
42007
  var BATCH_SPEC_KEYS = /* @__PURE__ */ new Set(["type", "title", "body", "priority", "labels", "label", "parent", "repo", "surface"]);
@@ -42210,7 +42383,7 @@ function extendCreateCommand(issue, batchAttach) {
42210
42383
  if (opts.batch) {
42211
42384
  let specs;
42212
42385
  try {
42213
- const raw = (0, import_node_fs35.readFileSync)(opts.batch, "utf8");
42386
+ const raw = (0, import_node_fs36.readFileSync)(opts.batch, "utf8");
42214
42387
  specs = JSON.parse(raw);
42215
42388
  if (!Array.isArray(specs)) {
42216
42389
  const top = specs === null ? "null" : typeof specs === "object" ? `an object with keys: ${Object.keys(specs).join(", ") || "(none)"}` : `a ${typeof specs}`;
@@ -42287,8 +42460,8 @@ ${lines2}`, {
42287
42460
  }
42288
42461
 
42289
42462
  // src/post-merge-recon.ts
42290
- var import_node_fs36 = require("node:fs");
42291
- var import_node_path35 = require("node:path");
42463
+ var import_node_fs37 = require("node:fs");
42464
+ var import_node_path36 = require("node:path");
42292
42465
 
42293
42466
  // src/cross-repo-filing-issue.ts
42294
42467
  init_github_client();
@@ -42457,16 +42630,16 @@ function buildPostMergeReconRecovery(input) {
42457
42630
  }
42458
42631
  function writePostMergeReconRecovery(cwd, recovery) {
42459
42632
  const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
42460
- (0, import_node_fs36.mkdirSync)((0, import_node_path35.dirname)(path2), { recursive: true });
42461
- (0, import_node_fs36.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
42633
+ (0, import_node_fs37.mkdirSync)((0, import_node_path36.dirname)(path2), { recursive: true });
42634
+ (0, import_node_fs37.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
42462
42635
  `, "utf8");
42463
42636
  return path2;
42464
42637
  }
42465
42638
  function clearPostMergeReconRecovery(cwd, repo, pr) {
42466
42639
  const path2 = postMergeReconStatePath(cwd, repo, pr);
42467
- if (!(0, import_node_fs36.existsSync)(path2)) return;
42640
+ if (!(0, import_node_fs37.existsSync)(path2)) return;
42468
42641
  try {
42469
- (0, import_node_fs36.unlinkSync)(path2);
42642
+ (0, import_node_fs37.unlinkSync)(path2);
42470
42643
  } catch {
42471
42644
  }
42472
42645
  }
@@ -42942,9 +43115,9 @@ function registerPrLifecycleCommands(program3) {
42942
43115
 
42943
43116
  // src/review-verdict.ts
42944
43117
  var import_node_child_process14 = require("node:child_process");
42945
- var import_node_fs37 = require("node:fs");
42946
- var import_node_os20 = require("node:os");
42947
- var import_node_path36 = require("node:path");
43118
+ var import_node_fs38 = require("node:fs");
43119
+ var import_node_os21 = require("node:os");
43120
+ var import_node_path37 = require("node:path");
42948
43121
  init_cli_shared();
42949
43122
  var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
42950
43123
  var REVIEW_VERDICTS = ["PROCEED", "CORRECT", "ESCALATE"];
@@ -43109,15 +43282,15 @@ async function readPrIssueComments(number, repo) {
43109
43282
  return comments;
43110
43283
  }
43111
43284
  async function postPrCommentFromFile(number, repo, body) {
43112
- const dir = (0, import_node_fs37.mkdtempSync)((0, import_node_path36.join)((0, import_node_os20.tmpdir)(), "mmi-review-verdict-"));
43113
- const path2 = (0, import_node_path36.join)(dir, "body.md");
43285
+ const dir = (0, import_node_fs38.mkdtempSync)((0, import_node_path37.join)((0, import_node_os21.tmpdir)(), "mmi-review-verdict-"));
43286
+ const path2 = (0, import_node_path37.join)(dir, "body.md");
43114
43287
  try {
43115
- (0, import_node_fs37.writeFileSync)(path2, body, "utf8");
43288
+ (0, import_node_fs38.writeFileSync)(path2, body, "utf8");
43116
43289
  const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
43117
43290
  return stdout.trim();
43118
43291
  } finally {
43119
43292
  try {
43120
- (0, import_node_fs37.rmSync)(dir, { recursive: true, force: true });
43293
+ (0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
43121
43294
  } catch {
43122
43295
  }
43123
43296
  }
@@ -43351,18 +43524,18 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
43351
43524
  }
43352
43525
 
43353
43526
  // src/worktree-residue-sweep.ts
43354
- var import_node_fs42 = require("node:fs");
43355
- var import_node_path41 = require("node:path");
43527
+ var import_node_fs43 = require("node:fs");
43528
+ var import_node_path42 = require("node:path");
43356
43529
 
43357
43530
  // src/worktree-merge-cleanup.ts
43358
- var import_node_fs41 = require("node:fs");
43359
- var import_node_path40 = require("node:path");
43531
+ var import_node_fs42 = require("node:fs");
43532
+ var import_node_path41 = require("node:path");
43360
43533
  init_cli_shared();
43361
43534
 
43362
43535
  // src/stage-runner.ts
43363
43536
  var import_node_child_process16 = require("node:child_process");
43364
- var import_node_fs39 = require("node:fs");
43365
- var import_node_path38 = require("node:path");
43537
+ var import_node_fs40 = require("node:fs");
43538
+ var import_node_path39 = require("node:path");
43366
43539
  var import_node_net = require("node:net");
43367
43540
  var import_node_util5 = require("node:util");
43368
43541
 
@@ -43372,8 +43545,8 @@ function normalizeEol2(s) {
43372
43545
  }
43373
43546
 
43374
43547
  // src/env-detection.ts
43375
- var import_node_fs38 = require("node:fs");
43376
- var import_node_path37 = require("node:path");
43548
+ var import_node_fs39 = require("node:fs");
43549
+ var import_node_path38 = require("node:path");
43377
43550
  var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
43378
43551
  function isEnvBaseName(name) {
43379
43552
  return name.toLowerCase() === ".env";
@@ -43383,7 +43556,7 @@ function findEnvFiles(root) {
43383
43556
  const walk2 = (dir, rel) => {
43384
43557
  let entries;
43385
43558
  try {
43386
- entries = (0, import_node_fs38.readdirSync)(dir, { withFileTypes: true });
43559
+ entries = (0, import_node_fs39.readdirSync)(dir, { withFileTypes: true });
43387
43560
  } catch {
43388
43561
  return;
43389
43562
  }
@@ -43391,13 +43564,13 @@ function findEnvFiles(root) {
43391
43564
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
43392
43565
  if (entry.isDirectory()) {
43393
43566
  if (SKIPPED_DIRS.has(entry.name)) continue;
43394
- walk2((0, import_node_path37.join)(dir, entry.name), relPath);
43567
+ walk2((0, import_node_path38.join)(dir, entry.name), relPath);
43395
43568
  continue;
43396
43569
  }
43397
43570
  if (isEnvBaseName(entry.name)) {
43398
43571
  let isDir = false;
43399
43572
  try {
43400
- isDir = (0, import_node_fs38.lstatSync)((0, import_node_path37.join)(dir, entry.name)).isDirectory();
43573
+ isDir = (0, import_node_fs39.lstatSync)((0, import_node_path38.join)(dir, entry.name)).isDirectory();
43401
43574
  } catch {
43402
43575
  }
43403
43576
  if (!isDir) found.push(relPath);
@@ -43536,12 +43709,12 @@ var DOCKER_TIMEOUT_MS = 15e3;
43536
43709
  function stageBash() {
43537
43710
  if (process.platform !== "win32") return "bash";
43538
43711
  const configured = process.env.SHELL;
43539
- if (configured && (0, import_node_path38.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs39.existsSync)(configured)) return configured;
43712
+ if (configured && (0, import_node_path39.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs40.existsSync)(configured)) return configured;
43540
43713
  const candidates = [
43541
- (0, import_node_path38.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
43542
- ...process.env.LOCALAPPDATA ? [(0, import_node_path38.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
43714
+ (0, import_node_path39.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
43715
+ ...process.env.LOCALAPPDATA ? [(0, import_node_path39.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
43543
43716
  ];
43544
- const bash = candidates.find((path2) => (0, import_node_fs39.existsSync)(path2));
43717
+ const bash = candidates.find((path2) => (0, import_node_fs40.existsSync)(path2));
43545
43718
  if (!bash) throw new Error("Local stages require Git Bash on Windows. Install Git for Windows or set SHELL to its absolute bash.exe path.");
43546
43719
  return bash;
43547
43720
  }
@@ -43679,7 +43852,7 @@ function appendForceRecreate(up) {
43679
43852
  return `${up.trimEnd()} --force-recreate`;
43680
43853
  }
43681
43854
  function stageStatePath(cwd = process.cwd()) {
43682
- return (0, import_node_path38.join)(cwd, "tmp", "stage", "state.json");
43855
+ return (0, import_node_path39.join)(cwd, "tmp", "stage", "state.json");
43683
43856
  }
43684
43857
  function normPath(path2) {
43685
43858
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -43896,8 +44069,8 @@ function stageProcessEnv(stagePort, extraEnv) {
43896
44069
  }
43897
44070
  function composeResolvesPort(cwd) {
43898
44071
  if (process.env.PORT) return true;
43899
- const envFile = (0, import_node_path38.join)(cwd, ".env");
43900
- return (0, import_node_fs39.existsSync)(envFile) && envFileKeys((0, import_node_fs39.readFileSync)(envFile, "utf8")).has("PORT");
44072
+ const envFile = (0, import_node_path39.join)(cwd, ".env");
44073
+ return (0, import_node_fs40.existsSync)(envFile) && envFileKeys((0, import_node_fs40.readFileSync)(envFile, "utf8")).has("PORT");
43901
44074
  }
43902
44075
  function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
43903
44076
  const composeProject = config.env?.COMPOSE_PROJECT_NAME ?? vaultEnvMerge?.COMPOSE_PROJECT_NAME ?? stageComposeProjectName(cwd);
@@ -43912,13 +44085,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
43912
44085
  function stageComposeFiles(cwd) {
43913
44086
  const files = ["docker-compose.yml"];
43914
44087
  for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
43915
- if ((0, import_node_fs39.existsSync)((0, import_node_path38.join)(cwd, conventional))) files.push(conventional);
44088
+ if ((0, import_node_fs40.existsSync)((0, import_node_path39.join)(cwd, conventional))) files.push(conventional);
43916
44089
  }
43917
44090
  return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
43918
44091
  }
43919
44092
  async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
43920
44093
  const keys = Object.keys(vaultEnvMerge ?? {});
43921
- if (!keys.length || !(0, import_node_fs39.existsSync)((0, import_node_path38.join)(cwd, "docker-compose.yml"))) return {};
44094
+ if (!keys.length || !(0, import_node_fs40.existsSync)((0, import_node_path39.join)(cwd, "docker-compose.yml"))) return {};
43922
44095
  let configJson;
43923
44096
  try {
43924
44097
  const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
@@ -43934,21 +44107,21 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
43934
44107
  }
43935
44108
  const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys, runtimeEnvExcludes(configJson), runtimeEnvSelects(configJson));
43936
44109
  if (!body) return {};
43937
- const overridePath = (0, import_node_path38.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
43938
- (0, import_node_fs39.mkdirSync)((0, import_node_path38.join)(cwd, "tmp", "stage"), { recursive: true });
43939
- (0, import_node_fs39.writeFileSync)(overridePath, body, "utf8");
44110
+ const overridePath = (0, import_node_path39.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
44111
+ (0, import_node_fs40.mkdirSync)((0, import_node_path39.join)(cwd, "tmp", "stage"), { recursive: true });
44112
+ (0, import_node_fs40.writeFileSync)(overridePath, body, "utf8");
43940
44113
  return stageComposeFileEnv(stageComposeFiles(cwd));
43941
44114
  }
43942
44115
  async function ensureStageRuntimeEnv(config, opts, cwd) {
43943
44116
  if (!config.ensureEnv) return;
43944
- const target = (0, import_node_path38.join)(cwd, config.ensureEnv.target);
43945
- const example = (0, import_node_path38.join)(cwd, config.ensureEnv.example);
43946
- if (!(0, import_node_fs39.existsSync)(target) && (0, import_node_fs39.existsSync)(example)) {
43947
- (0, import_node_fs39.copyFileSync)(example, target);
43948
- } else if ((0, import_node_fs39.existsSync)(target) && (0, import_node_fs39.existsSync)(example)) {
43949
- const stale = detectStaleEnvFile((0, import_node_fs39.readFileSync)(example, "utf8"), (0, import_node_fs39.readFileSync)(target, "utf8"), {
43950
- exampleMtimeMs: (0, import_node_fs39.statSync)(example).mtimeMs,
43951
- targetMtimeMs: (0, import_node_fs39.statSync)(target).mtimeMs
44117
+ const target = (0, import_node_path39.join)(cwd, config.ensureEnv.target);
44118
+ const example = (0, import_node_path39.join)(cwd, config.ensureEnv.example);
44119
+ if (!(0, import_node_fs40.existsSync)(target) && (0, import_node_fs40.existsSync)(example)) {
44120
+ (0, import_node_fs40.copyFileSync)(example, target);
44121
+ } else if ((0, import_node_fs40.existsSync)(target) && (0, import_node_fs40.existsSync)(example)) {
44122
+ const stale = detectStaleEnvFile((0, import_node_fs40.readFileSync)(example, "utf8"), (0, import_node_fs40.readFileSync)(target, "utf8"), {
44123
+ exampleMtimeMs: (0, import_node_fs40.statSync)(example).mtimeMs,
44124
+ targetMtimeMs: (0, import_node_fs40.statSync)(target).mtimeMs
43952
44125
  });
43953
44126
  if (stale) {
43954
44127
  const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running /stage`;
@@ -43956,8 +44129,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
43956
44129
  console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
43957
44130
  }
43958
44131
  }
43959
- if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs39.existsSync)(target)) {
43960
- (0, import_node_fs39.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs39.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
44132
+ if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs40.existsSync)(target)) {
44133
+ (0, import_node_fs40.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs40.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
43961
44134
  }
43962
44135
  }
43963
44136
  async function gitText(cwd, args) {
@@ -43987,20 +44160,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
43987
44160
  return void 0;
43988
44161
  }
43989
44162
  function readState(path2) {
43990
- if (!(0, import_node_fs39.existsSync)(path2)) return null;
44163
+ if (!(0, import_node_fs40.existsSync)(path2)) return null;
43991
44164
  try {
43992
- return JSON.parse((0, import_node_fs39.readFileSync)(path2, "utf8"));
44165
+ return JSON.parse((0, import_node_fs40.readFileSync)(path2, "utf8"));
43993
44166
  } catch {
43994
44167
  return null;
43995
44168
  }
43996
44169
  }
43997
44170
  function mkdirFor(path2) {
43998
44171
  const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
43999
- (0, import_node_fs39.mkdirSync)(dir, { recursive: true });
44172
+ (0, import_node_fs40.mkdirSync)(dir, { recursive: true });
44000
44173
  }
44001
44174
  function writeState(path2, state) {
44002
44175
  mkdirFor(path2);
44003
- (0, import_node_fs39.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
44176
+ (0, import_node_fs40.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
44004
44177
  }
44005
44178
  function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
44006
44179
  const reservation = {
@@ -44029,7 +44202,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd, currentEn
44029
44202
  );
44030
44203
  }
44031
44204
  for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
44032
- (0, import_node_fs39.rmSync)(path2, { force: true });
44205
+ (0, import_node_fs40.rmSync)(path2, { force: true });
44033
44206
  }
44034
44207
  }
44035
44208
  async function killTree(pid) {
@@ -44276,8 +44449,8 @@ async function runStage(config = {}, opts = {}) {
44276
44449
  });
44277
44450
  }
44278
44451
  } catch (e) {
44279
- (0, import_node_fs39.rmSync)(statePath, { force: true });
44280
- if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs39.rmSync)(globalStatePath, { force: true });
44452
+ (0, import_node_fs40.rmSync)(statePath, { force: true });
44453
+ if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs40.rmSync)(globalStatePath, { force: true });
44281
44454
  throw e;
44282
44455
  }
44283
44456
  const started = await startStage(config, {
@@ -44292,8 +44465,8 @@ async function runStage(config = {}, opts = {}) {
44292
44465
  }
44293
44466
 
44294
44467
  // src/worktree-evidence-archive.ts
44295
- var import_node_fs40 = require("node:fs");
44296
- var import_node_path39 = require("node:path");
44468
+ var import_node_fs41 = require("node:fs");
44469
+ var import_node_path40 = require("node:path");
44297
44470
  var JERV_ARTIFACT_RUN_SCOPE_ENV_VARS = ["JERV_RUN_ID", ...SESSION_ID_ENV_VARS];
44298
44471
  function sanitizeArchiveSegment(value, max = 80) {
44299
44472
  const scrubbed = value.replace(/[^A-Za-z0-9._@+-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -44308,24 +44481,24 @@ function resolveArtifactRunScope(env = process.env) {
44308
44481
  }
44309
44482
  function defaultIsDirectory(path2) {
44310
44483
  try {
44311
- return (0, import_node_fs40.lstatSync)(path2).isDirectory();
44484
+ return (0, import_node_fs41.lstatSync)(path2).isDirectory();
44312
44485
  } catch {
44313
44486
  return false;
44314
44487
  }
44315
44488
  }
44316
44489
  function archiveWorktreeJervArtifacts(args, deps = {}) {
44317
- const exists = deps.exists ?? import_node_fs40.existsSync;
44490
+ const exists = deps.exists ?? import_node_fs41.existsSync;
44318
44491
  const isDirectory = deps.isDirectory ?? defaultIsDirectory;
44319
- const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs40.cpSync)(from, to, { recursive: true, force: true }));
44492
+ const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs41.cpSync)(from, to, { recursive: true, force: true }));
44320
44493
  const mkdirp = deps.mkdirp ?? ((path2) => {
44321
- (0, import_node_fs40.mkdirSync)(path2, { recursive: true });
44494
+ (0, import_node_fs41.mkdirSync)(path2, { recursive: true });
44322
44495
  });
44323
44496
  const env = deps.env ?? process.env;
44324
44497
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
44325
44498
  const resolveRoot = deps.resolveArchiveRoot ?? repoRuntimeStatePath;
44326
44499
  if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
44327
44500
  if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
44328
- const source = (0, import_node_path39.join)(args.worktreePath, ".jerv");
44501
+ const source = (0, import_node_path40.join)(args.worktreePath, ".jerv");
44329
44502
  if (!exists(source)) return { status: "absent" };
44330
44503
  if (!isDirectory(source)) return { status: "skipped", reason: "jerv-not-a-directory" };
44331
44504
  const runScope = resolveArtifactRunScope(env);
@@ -44333,7 +44506,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
44333
44506
  const stamp = now().toISOString().replace(/[:.]/g, "-");
44334
44507
  const dest = resolveRoot(args.primaryRoot, "jerv-artifacts", runScope, branchSlug, stamp, ".jerv");
44335
44508
  try {
44336
- mkdirp((0, import_node_path39.dirname)(dest));
44509
+ mkdirp((0, import_node_path40.dirname)(dest));
44337
44510
  copyDir(source, dest);
44338
44511
  if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
44339
44512
  return { status: "archived", path: dest, runScope };
@@ -44342,14 +44515,14 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
44342
44515
  }
44343
44516
  }
44344
44517
  function defaultStat(path2) {
44345
- const st = (0, import_node_fs40.statSync)(path2);
44518
+ const st = (0, import_node_fs41.statSync)(path2);
44346
44519
  return { mtimeMs: st.mtimeMs, size: st.size, isDirectory: () => st.isDirectory() };
44347
44520
  }
44348
44521
  function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
44349
- const exists = deps.exists ?? import_node_fs40.existsSync;
44522
+ const exists = deps.exists ?? import_node_fs41.existsSync;
44350
44523
  const stat4 = deps.stat ?? defaultStat;
44351
- const readdir2 = deps.readdir ?? import_node_fs40.readdirSync;
44352
- const tmpRoot = (0, import_node_path39.join)(worktreePath, "tmp");
44524
+ const readdir2 = deps.readdir ?? import_node_fs41.readdirSync;
44525
+ const tmpRoot = (0, import_node_path40.join)(worktreePath, "tmp");
44353
44526
  if (!exists(tmpRoot)) return [];
44354
44527
  const entries = [];
44355
44528
  const walk2 = (dir) => {
@@ -44360,14 +44533,14 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
44360
44533
  return;
44361
44534
  }
44362
44535
  for (const name of names) {
44363
- const full = (0, import_node_path39.join)(dir, name);
44536
+ const full = (0, import_node_path40.join)(dir, name);
44364
44537
  let st;
44365
44538
  try {
44366
44539
  st = stat4(full);
44367
44540
  } catch {
44368
44541
  continue;
44369
44542
  }
44370
- const relPath = (0, import_node_path39.relative)(worktreePath, full).replace(/\\/g, "/");
44543
+ const relPath = (0, import_node_path40.relative)(worktreePath, full).replace(/\\/g, "/");
44371
44544
  if (st.isDirectory()) {
44372
44545
  if (st.mtimeMs > newerThanMs) entries.push({ relPath, bytes: 0, mtimeMs: st.mtimeMs });
44373
44546
  walk2(full);
@@ -44381,10 +44554,10 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
44381
44554
  return entries;
44382
44555
  }
44383
44556
  function archiveWorktreeTmpArtifacts(args, deps = {}) {
44384
- const exists = deps.exists ?? import_node_fs40.existsSync;
44385
- const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs40.cpSync)(from, to, { recursive: true, force: true }));
44557
+ const exists = deps.exists ?? import_node_fs41.existsSync;
44558
+ const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs41.cpSync)(from, to, { recursive: true, force: true }));
44386
44559
  const mkdirp = deps.mkdirp ?? ((path2) => {
44387
- (0, import_node_fs40.mkdirSync)(path2, { recursive: true });
44560
+ (0, import_node_fs41.mkdirSync)(path2, { recursive: true });
44388
44561
  });
44389
44562
  const env = deps.env ?? process.env;
44390
44563
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
@@ -44392,7 +44565,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
44392
44565
  if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
44393
44566
  if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
44394
44567
  const scanned = scanWorktreeTmpEvidence(args.worktreePath, args.newerThanMs, deps);
44395
- const source = (0, import_node_path39.join)(args.worktreePath, "tmp");
44568
+ const source = (0, import_node_path40.join)(args.worktreePath, "tmp");
44396
44569
  if (!scanned.length) return { status: "absent" };
44397
44570
  if (!exists(source)) return { status: "absent" };
44398
44571
  const runScope = resolveArtifactRunScope(env);
@@ -44400,7 +44573,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
44400
44573
  const stamp = now().toISOString().replace(/[:.]/g, "-");
44401
44574
  const dest = resolveRoot(args.primaryRoot, "worktree-artifacts", runScope, branchSlug, stamp, "tmp");
44402
44575
  try {
44403
- mkdirp((0, import_node_path39.dirname)(dest));
44576
+ mkdirp((0, import_node_path40.dirname)(dest));
44404
44577
  copyDir(source, dest);
44405
44578
  if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
44406
44579
  const bytes = scanned.reduce((sum, e) => sum + e.bytes, 0);
@@ -44469,9 +44642,9 @@ function normPath2(p) {
44469
44642
  return p.replace(/\\/g, "/").replace(/\/+$/, "");
44470
44643
  }
44471
44644
  function unlinkNodeModulesJunction(wtPath) {
44472
- const nm = (0, import_node_path40.join)(wtPath, "node_modules");
44645
+ const nm = (0, import_node_path41.join)(wtPath, "node_modules");
44473
44646
  try {
44474
- if ((0, import_node_fs41.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs41.rmdirSync)(nm);
44647
+ if ((0, import_node_fs42.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs42.rmdirSync)(nm);
44475
44648
  return { ok: true };
44476
44649
  } catch (e) {
44477
44650
  if (e.code === "ENOENT") return { ok: true };
@@ -44482,8 +44655,8 @@ function defaultSleep2(ms) {
44482
44655
  return new Promise((resolve7) => setTimeout(resolve7, ms));
44483
44656
  }
44484
44657
  async function removeResidueDirectory(wtPath, options = {}) {
44485
- const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs41.rmdirSync, exists = import_node_fs41.existsSync } = options;
44486
- const removeRecursive = options.removeRecursive ?? ((path2) => (0, import_node_fs41.rmSync)(path2, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }));
44658
+ const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs42.rmdirSync, exists = import_node_fs42.existsSync } = options;
44659
+ const removeRecursive = options.removeRecursive ?? ((path2) => (0, import_node_fs42.rmSync)(path2, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }));
44487
44660
  const junction = unlinkNodeModulesJunction(wtPath);
44488
44661
  if (!junction.ok) return junction;
44489
44662
  try {
@@ -44606,28 +44779,28 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
44606
44779
  }
44607
44780
  async function listNestedIgnoredNodeModules(wtPath, execGit) {
44608
44781
  const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
44609
- return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path40.join)(wtPath, line.slice(0, -1)));
44782
+ return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path41.join)(wtPath, line.slice(0, -1)));
44610
44783
  }
44611
44784
  function safeRemoveTree(path2) {
44612
- const stat4 = (0, import_node_fs41.lstatSync)(path2);
44785
+ const stat4 = (0, import_node_fs42.lstatSync)(path2);
44613
44786
  if (stat4.isSymbolicLink()) {
44614
44787
  try {
44615
- (0, import_node_fs41.rmdirSync)(path2);
44788
+ (0, import_node_fs42.rmdirSync)(path2);
44616
44789
  } catch {
44617
- (0, import_node_fs41.unlinkSync)(path2);
44790
+ (0, import_node_fs42.unlinkSync)(path2);
44618
44791
  }
44619
44792
  return;
44620
44793
  }
44621
44794
  if (stat4.isDirectory()) {
44622
- for (const entry of (0, import_node_fs41.readdirSync)(path2)) safeRemoveTree((0, import_node_path40.join)(path2, entry));
44623
- (0, import_node_fs41.rmdirSync)(path2);
44795
+ for (const entry of (0, import_node_fs42.readdirSync)(path2)) safeRemoveTree((0, import_node_path41.join)(path2, entry));
44796
+ (0, import_node_fs42.rmdirSync)(path2);
44624
44797
  return;
44625
44798
  }
44626
- (0, import_node_fs41.unlinkSync)(path2);
44799
+ (0, import_node_fs42.unlinkSync)(path2);
44627
44800
  }
44628
44801
  async function removeWorktreeNodeModules(wtPath) {
44629
44802
  try {
44630
- safeRemoveTree((0, import_node_path40.join)(wtPath, "node_modules"));
44803
+ safeRemoveTree((0, import_node_path41.join)(wtPath, "node_modules"));
44631
44804
  return { ok: true };
44632
44805
  } catch (e) {
44633
44806
  if (e.code === "ENOENT") return { ok: true };
@@ -44639,7 +44812,7 @@ function errorMessage(e) {
44639
44812
  }
44640
44813
  function resolvedOrRaw(path2) {
44641
44814
  try {
44642
- return normPath2((0, import_node_fs41.realpathSync)(path2));
44815
+ return normPath2((0, import_node_fs42.realpathSync)(path2));
44643
44816
  } catch {
44644
44817
  return normPath2(path2);
44645
44818
  }
@@ -44647,10 +44820,10 @@ function resolvedOrRaw(path2) {
44647
44820
  function unlinkEscapingReparsePoints(root, primaryRoot) {
44648
44821
  let realRoot;
44649
44822
  try {
44650
- if ((0, import_node_fs41.lstatSync)(root).isSymbolicLink()) {
44823
+ if ((0, import_node_fs42.lstatSync)(root).isSymbolicLink()) {
44651
44824
  return { ok: false, error: `delete root ${normPath2(root)} is a reparse point resolving to ${resolvedOrRaw(root)}` };
44652
44825
  }
44653
- realRoot = normPath2((0, import_node_fs41.realpathSync)(root));
44826
+ realRoot = normPath2((0, import_node_fs42.realpathSync)(root));
44654
44827
  } catch (e) {
44655
44828
  if (e.code === "ENOENT") return { ok: true, unlinked: [] };
44656
44829
  return { ok: false, error: `cannot resolve delete root ${normPath2(root)}: ${errorMessage(e)}` };
@@ -44666,17 +44839,17 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
44666
44839
  const dir = stack.pop();
44667
44840
  let entries;
44668
44841
  try {
44669
- entries = (0, import_node_fs41.readdirSync)(dir, { withFileTypes: true });
44842
+ entries = (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true });
44670
44843
  } catch (e) {
44671
44844
  if (e.code === "ENOENT") continue;
44672
44845
  return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
44673
44846
  }
44674
44847
  for (const entry of entries) {
44675
- const child2 = (0, import_node_path40.join)(dir, entry.name);
44848
+ const child2 = (0, import_node_path41.join)(dir, entry.name);
44676
44849
  if (entry.isSymbolicLink()) {
44677
44850
  let target = "";
44678
44851
  try {
44679
- target = normPath2((0, import_node_fs41.realpathSync)(child2));
44852
+ target = normPath2((0, import_node_fs42.realpathSync)(child2));
44680
44853
  } catch {
44681
44854
  target = "";
44682
44855
  }
@@ -44859,7 +45032,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
44859
45032
  return report;
44860
45033
  }
44861
45034
  const execGit = options.execGit ?? (async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout);
44862
- const pathExists = options.pathExists ?? import_node_fs41.existsSync;
45035
+ const pathExists = options.pathExists ?? import_node_fs42.existsSync;
44863
45036
  let afterWorktrees = [];
44864
45037
  try {
44865
45038
  afterWorktrees = parseGitWorktreePorcelain(await execGit(["worktree", "list", "--porcelain"]));
@@ -44999,7 +45172,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
44999
45172
  const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
45000
45173
  if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
45001
45174
  unlinkedReparsePoints.push(...preHelperGuard.unlinked);
45002
- if (pathExists((0, import_node_path40.join)(wtPath, "node_modules"))) {
45175
+ if (pathExists((0, import_node_path41.join)(wtPath, "node_modules"))) {
45003
45176
  const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
45004
45177
  if (!nmRemoved.ok) {
45005
45178
  report.worktree = {
@@ -45135,18 +45308,18 @@ function renderPrMergeCleanupLines(cleanup) {
45135
45308
  // src/worktree-residue-sweep.ts
45136
45309
  var RESIDUE_LEDGER_FILE = "mmi-worktree-residue.json";
45137
45310
  function canonicalWorktreeRoot(primary) {
45138
- return (0, import_node_path41.join)((0, import_node_path41.dirname)(primary), "mmi-worktrees", (0, import_node_path41.basename)(primary));
45311
+ return (0, import_node_path42.join)((0, import_node_path42.dirname)(primary), "mmi-worktrees", (0, import_node_path42.basename)(primary));
45139
45312
  }
45140
45313
  function norm(p) {
45141
45314
  const s = p.replace(/\\/g, "/").replace(/\/+$/, "");
45142
45315
  return process.platform === "win32" ? s.toLowerCase() : s;
45143
45316
  }
45144
45317
  function residueLedgerPath(gitCommonDir) {
45145
- return (0, import_node_path41.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
45318
+ return (0, import_node_path42.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
45146
45319
  }
45147
45320
  function readPaths(file, deps) {
45148
45321
  try {
45149
- const parsed = JSON.parse((deps.readLedger ?? ((f) => (0, import_node_fs42.readFileSync)(f, "utf8")))(file));
45322
+ const parsed = JSON.parse((deps.readLedger ?? ((f) => (0, import_node_fs43.readFileSync)(f, "utf8")))(file));
45150
45323
  return Array.isArray(parsed) ? parsed.filter((p) => typeof p === "string") : [];
45151
45324
  } catch {
45152
45325
  return [];
@@ -45155,8 +45328,8 @@ function readPaths(file, deps) {
45155
45328
  function writePaths(file, paths, deps) {
45156
45329
  try {
45157
45330
  const write = deps.writeLedger ?? ((f, t) => {
45158
- (0, import_node_fs42.mkdirSync)((0, import_node_path41.dirname)(f), { recursive: true });
45159
- (0, import_node_fs42.writeFileSync)(f, t, "utf8");
45331
+ (0, import_node_fs43.mkdirSync)((0, import_node_path42.dirname)(f), { recursive: true });
45332
+ (0, import_node_fs43.writeFileSync)(f, t, "utf8");
45160
45333
  });
45161
45334
  write(file, `${JSON.stringify([...new Set(paths)], null, 1)}
45162
45335
  `);
@@ -45170,17 +45343,17 @@ function recordResidue(gitCommonDir, path2, deps = {}) {
45170
45343
  writePaths(file, paths, deps);
45171
45344
  }
45172
45345
  async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
45173
- const exists = deps.exists ?? import_node_fs42.existsSync;
45174
- const readDir = deps.readDir ?? ((p) => (0, import_node_fs42.readdirSync)(p));
45346
+ const exists = deps.exists ?? import_node_fs43.existsSync;
45347
+ const readDir = deps.readDir ?? ((p) => (0, import_node_fs43.readdirSync)(p));
45175
45348
  const isDir = deps.isDir ?? ((p) => {
45176
45349
  try {
45177
- return (0, import_node_fs42.statSync)(p).isDirectory();
45350
+ return (0, import_node_fs43.statSync)(p).isDirectory();
45178
45351
  } catch {
45179
45352
  return false;
45180
45353
  }
45181
45354
  });
45182
45355
  const removeRecorded = deps.removeRecorded ?? ((p) => removeResidueDirectory(p));
45183
- const removeEmpty = deps.removeEmpty ?? ((p) => (0, import_node_fs42.rmdirSync)(p));
45356
+ const removeEmpty = deps.removeEmpty ?? ((p) => (0, import_node_fs43.rmdirSync)(p));
45184
45357
  const report = { swept: [], kept: [], dropped: [], emptyRemoved: [], unrecorded: [] };
45185
45358
  const live = new Set(registered.map(norm));
45186
45359
  const primary = registered[0] ? norm(registered[0]) : void 0;
@@ -45215,7 +45388,7 @@ async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
45215
45388
  } catch {
45216
45389
  }
45217
45390
  for (const name of children) {
45218
- const child2 = (0, import_node_path41.join)(root, name);
45391
+ const child2 = (0, import_node_path42.join)(root, name);
45219
45392
  const key = norm(child2);
45220
45393
  if (live.has(key) || key === primary || keptKeys.has(key) || !isDir(child2)) continue;
45221
45394
  let entries;
@@ -45258,10 +45431,10 @@ function argvWantsJson2() {
45258
45431
  return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
45259
45432
  }
45260
45433
  function hubRoot() {
45261
- const fromPkg = (0, import_node_path42.join)(__dirname, "..", "..");
45434
+ const fromPkg = (0, import_node_path43.join)(__dirname, "..", "..");
45262
45435
  const marker = "skills/bootstrap/seeds/manifest.json";
45263
- if ((0, import_node_fs43.existsSync)((0, import_node_path42.join)(fromPkg, marker))) return fromPkg;
45264
- if ((0, import_node_fs43.existsSync)((0, import_node_path42.join)(process.cwd(), marker))) return process.cwd();
45436
+ if ((0, import_node_fs44.existsSync)((0, import_node_path43.join)(fromPkg, marker))) return fromPkg;
45437
+ if ((0, import_node_fs44.existsSync)((0, import_node_path43.join)(process.cwd(), marker))) return process.cwd();
45265
45438
  return null;
45266
45439
  }
45267
45440
  function ciAuditDeps() {
@@ -45273,8 +45446,8 @@ function ciAuditDeps() {
45273
45446
  getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
45274
45447
  readSeedFile: (path2) => {
45275
45448
  if (!root) return null;
45276
- const fullPath = (0, import_node_path42.join)(root, path2);
45277
- return (0, import_node_fs43.existsSync)(fullPath) ? (0, import_node_fs43.readFileSync)(fullPath, "utf8") : null;
45449
+ const fullPath = (0, import_node_path43.join)(root, path2);
45450
+ return (0, import_node_fs44.existsSync)(fullPath) ? (0, import_node_fs44.readFileSync)(fullPath, "utf8") : null;
45278
45451
  }
45279
45452
  };
45280
45453
  }
@@ -46037,11 +46210,11 @@ ${list}`);
46037
46210
  }
46038
46211
  });
46039
46212
  async function listCiWorkflowPaths(cwd = process.cwd()) {
46040
- const wfDir = (0, import_node_path42.join)(cwd, ".github", "workflows");
46041
- if (!(0, import_node_fs43.existsSync)(wfDir)) return [];
46042
- return (0, import_node_fs43.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
46213
+ const wfDir = (0, import_node_path43.join)(cwd, ".github", "workflows");
46214
+ if (!(0, import_node_fs44.existsSync)(wfDir)) return [];
46215
+ return (0, import_node_fs44.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
46043
46216
  try {
46044
- return workflowReportsPrChecks((0, import_node_fs43.readFileSync)((0, import_node_path42.join)(wfDir, name), "utf8"));
46217
+ return workflowReportsPrChecks((0, import_node_fs44.readFileSync)((0, import_node_path43.join)(wfDir, name), "utf8"));
46045
46218
  } catch {
46046
46219
  return true;
46047
46220
  }
@@ -46246,7 +46419,7 @@ ${list}`);
46246
46419
  jsonParity(pr.command("review-verdict <number>").description("post an explicit review verdict comment: computes the PR diff patch-id and head sha, renders the v1 contract body, and posts it as a PR comment").requiredOption("--repo <owner/repo>", "target repo").requiredOption("--verdict <verdict>", `one of ${REVIEW_VERDICTS.join("|")}`).requiredOption("--scope <text>", "one line: what was reviewed").requiredOption("--risk <text>", "one line: the residual risk").option("--unverified <text>", "a claim the reviewer could not verify (repeatable)", (v, acc) => [...acc, v], []).requiredOption("--reviewer <id>", "reviewer seat or model id").option("--findings-file <path>", "Markdown findings appended after the JSON block")).action(async (number, o) => {
46247
46420
  if (!isReviewVerdict(o.verdict)) return fail(`pr review-verdict: --verdict must be one of ${REVIEW_VERDICTS.join("|")} (got ${o.verdict})`);
46248
46421
  const verdict = o.verdict;
46249
- const findings = o.findingsFile ? (0, import_node_fs43.readFileSync)(o.findingsFile, "utf8") : void 0;
46422
+ const findings = o.findingsFile ? (0, import_node_fs44.readFileSync)(o.findingsFile, "utf8") : void 0;
46250
46423
  let patch;
46251
46424
  let head;
46252
46425
  try {
@@ -46523,7 +46696,7 @@ ${list}`);
46523
46696
  const mergeSquashBody = squashBodyTextForMerge(
46524
46697
  closingGuardInput,
46525
46698
  method === "--squash",
46526
- o.squashBodyFile ? (0, import_node_fs43.readFileSync)(o.squashBodyFile, "utf8") : void 0
46699
+ o.squashBodyFile ? (0, import_node_fs44.readFileSync)(o.squashBodyFile, "utf8") : void 0
46527
46700
  );
46528
46701
  if (!o.squashBodyFile) warnSquashBodyClosingStrip("pr merge", closingGuardInput, mergeSquashBody);
46529
46702
  const closingGuardVerdict = evaluateClosingGuard(closingGuardInput, {
@@ -46555,7 +46728,7 @@ ${list}`);
46555
46728
  const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
46556
46729
  let foreignCheckout;
46557
46730
  if (foreignCwd) {
46558
- const sibling = (0, import_node_path42.join)((0, import_node_path42.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
46731
+ const sibling = (0, import_node_path43.join)((0, import_node_path43.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
46559
46732
  const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
46560
46733
  if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
46561
46734
  const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
@@ -46653,7 +46826,7 @@ ${list}`);
46653
46826
  }
46654
46827
  if (!repoForPostCleanup) throw e;
46655
46828
  console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
46656
- const commitMessage = bodyFile ? (0, import_node_fs43.readFileSync)(bodyFile, "utf8") : void 0;
46829
+ const commitMessage = bodyFile ? (0, import_node_fs44.readFileSync)(bodyFile, "utf8") : void 0;
46657
46830
  await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
46658
46831
  body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
46659
46832
  timeoutMs: GH_MUTATION_TIMEOUT_MS
@@ -46767,7 +46940,7 @@ ${list}`);
46767
46940
  let residueSweep;
46768
46941
  if (!(foreignCwd && !foreignCheckout)) {
46769
46942
  try {
46770
- gitCommonDir = (0, import_node_path42.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
46943
+ gitCommonDir = (0, import_node_path43.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
46771
46944
  residueSweep = await sweepWorktreeResidue(gitCommonDir, beforeWorktrees.map((w) => w.path));
46772
46945
  } catch {
46773
46946
  }
@@ -46785,7 +46958,7 @@ ${list}`);
46785
46958
  preserveWorktree: o.preserveWorktree,
46786
46959
  gcAcknowledged: o.gc,
46787
46960
  expectedHeadOid: headRefOid,
46788
- pathExists: (p) => (0, import_node_fs43.existsSync)(p),
46961
+ pathExists: (p) => (0, import_node_fs44.existsSync)(p),
46789
46962
  // #5899: pin cleanup git calls to the main checkout — the task worktree this process may be
46790
46963
  // standing in is removed mid-cleanup, so a cwd-relative invocation fails with
46791
46964
  // 'fatal: not a git repository' and leaves a spurious partial-cleanup exit.
@@ -48017,18 +48190,18 @@ function rcRunCauseFromLog(log) {
48017
48190
  function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
48018
48191
  return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
48019
48192
  }
48020
- var suiteStateDir = (root) => (0, import_node_path43.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
48193
+ var suiteStateDir = (root) => (0, import_node_path44.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
48021
48194
  function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
48022
- const recordPath = (0, import_node_path43.join)(suiteStateDir(root), "cut.json");
48023
- const base = (0, import_node_path43.join)(suiteStateDir(root), "checkouts");
48195
+ const recordPath = (0, import_node_path44.join)(suiteStateDir(root), "cut.json");
48196
+ const base = (0, import_node_path44.join)(suiteStateDir(root), "checkouts");
48024
48197
  const checkout = async (repo) => {
48025
48198
  if (repo === SUITE_REPO) return root;
48026
- const target = (0, import_node_path43.join)(base, repo.split("/")[1]);
48027
- if (!(0, import_node_fs44.existsSync)(target)) {
48028
- (0, import_node_fs44.mkdirSync)(base, { recursive: true });
48199
+ const target = (0, import_node_path44.join)(base, repo.split("/")[1]);
48200
+ if (!(0, import_node_fs45.existsSync)(target)) {
48201
+ (0, import_node_fs45.mkdirSync)(base, { recursive: true });
48029
48202
  await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
48030
48203
  }
48031
- if (!(0, import_node_fs44.existsSync)((0, import_node_path43.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
48204
+ if (!(0, import_node_fs45.existsSync)((0, import_node_path44.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
48032
48205
  const origin = await exec("git", ["remote", "get-url", "origin"], target);
48033
48206
  if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
48034
48207
  throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
@@ -48351,9 +48524,9 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
48351
48524
  const body = await gh(["release", "view", leadTag, "--repo", SUITE_REPO, "--json", "body", "--jq", ".body"]);
48352
48525
  if (parseSuiteMapping(body)) return;
48353
48526
  const dir = suiteStateDir(root);
48354
- (0, import_node_fs44.mkdirSync)(dir, { recursive: true });
48355
- const file = (0, import_node_path43.join)(dir, `notes-${leadTag}.md`);
48356
- (0, import_node_fs44.writeFileSync)(file, `${body}
48527
+ (0, import_node_fs45.mkdirSync)(dir, { recursive: true });
48528
+ const file = (0, import_node_path44.join)(dir, `notes-${leadTag}.md`);
48529
+ (0, import_node_fs45.writeFileSync)(file, `${body}
48357
48530
 
48358
48531
  ${suiteMappingBlock(leadTag, mapping)}`);
48359
48532
  await gh(["release", "edit", leadTag, "--repo", SUITE_REPO, "--notes-file", file]);
@@ -48394,7 +48567,7 @@ ${suiteMappingBlock(leadTag, mapping)}`);
48394
48567
 
48395
48568
  // src/suite-commands.ts
48396
48569
  init_cli_shared();
48397
- var import_node_fs45 = require("node:fs");
48570
+ var import_node_fs46 = require("node:fs");
48398
48571
  function parseMemberSummaryFiles(entries) {
48399
48572
  const memberSummaryFiles = {};
48400
48573
  for (const entry of entries) {
@@ -48476,7 +48649,7 @@ function registerSuiteCommands(program3) {
48476
48649
  try {
48477
48650
  const io = suiteTrainIo(root);
48478
48651
  retired = await retireFailedLeadRcLedger({ ledgerPath: releaseLedgerPath(root), rcHead: () => io.head(SUITE_REPO, "rc").then((h) => h ?? void 0), markAbandoned: io.markAbandoned }, o.ownerGo === true);
48479
- if (retired && !(0, import_node_fs45.existsSync)(io.recordPath)) {
48652
+ if (retired && !(0, import_node_fs46.existsSync)(io.recordPath)) {
48480
48653
  console.log(o.json ? JSON.stringify({ retiredLeadRc: retired }, null, 2) : `suite abandon: retired the lead's failed, never-promoted rc candidate ${retired}; marked abandoned on origin (#7854)`);
48481
48654
  return;
48482
48655
  }
@@ -48665,9 +48838,9 @@ function suiteStatusDeps(github, registry2) {
48665
48838
 
48666
48839
  // src/packages-adopt-export.ts
48667
48840
  var import_node_child_process18 = require("node:child_process");
48668
- var import_node_fs46 = require("node:fs");
48669
- var import_node_os21 = require("node:os");
48670
- var import_node_path44 = require("node:path");
48841
+ var import_node_fs47 = require("node:fs");
48842
+ var import_node_os22 = require("node:os");
48843
+ var import_node_path45 = require("node:path");
48671
48844
  var import_node_util6 = require("node:util");
48672
48845
  init_cli_shared();
48673
48846
 
@@ -49287,38 +49460,38 @@ function expectedFromRun(run, opts) {
49287
49460
  }
49288
49461
  async function adoptExport(opts, deps) {
49289
49462
  if (!/^sha256:[0-9a-f]{64}$/.test(opts.digest)) throw new Error("--digest must be sha256:<64 hex>, from the export run summary");
49290
- const packagePath = (0, import_node_path44.join)(opts.dir, "package.json");
49291
- const lockPath = (0, import_node_path44.join)(opts.dir, "package-lock.json");
49292
- const packageText = (0, import_node_fs46.readFileSync)(packagePath, "utf8");
49293
- const lockText = (0, import_node_fs46.readFileSync)(lockPath, "utf8");
49294
- const work = (0, import_node_fs46.mkdtempSync)((0, import_node_path44.join)((0, import_node_os21.tmpdir)(), "mmi-adopt-export-"));
49463
+ const packagePath = (0, import_node_path45.join)(opts.dir, "package.json");
49464
+ const lockPath = (0, import_node_path45.join)(opts.dir, "package-lock.json");
49465
+ const packageText = (0, import_node_fs47.readFileSync)(packagePath, "utf8");
49466
+ const lockText = (0, import_node_fs47.readFileSync)(lockPath, "utf8");
49467
+ const work = (0, import_node_fs47.mkdtempSync)((0, import_node_path45.join)((0, import_node_os22.tmpdir)(), "mmi-adopt-export-"));
49295
49468
  try {
49296
49469
  const run = JSON.parse((await deps.ghApi(`repos/${EXPORT_REPO}/actions/runs/${opts.run}`)).toString("utf8"));
49297
- (0, import_node_fs46.writeFileSync)((0, import_node_path44.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
49298
- (0, import_node_fs46.writeFileSync)((0, import_node_path44.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
49299
- (0, import_node_fs46.writeFileSync)((0, import_node_path44.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
49300
- const script = (0, import_node_path44.join)(work, "package_export.py");
49301
- (0, import_node_fs46.writeFileSync)(script, package_export_default);
49470
+ (0, import_node_fs47.writeFileSync)((0, import_node_path45.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
49471
+ (0, import_node_fs47.writeFileSync)((0, import_node_path45.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
49472
+ (0, import_node_fs47.writeFileSync)((0, import_node_path45.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
49473
+ const script = (0, import_node_path45.join)(work, "package_export.py");
49474
+ (0, import_node_fs47.writeFileSync)(script, package_export_default);
49302
49475
  await deps.python(script, ["verify", work, opts.ds, opts.screens]);
49303
- const verified = (0, import_node_path44.join)(work, "verified");
49304
- const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs46.readFileSync)((0, import_node_path44.join)(verified, `${short3}.metadata.json`), "utf8"))]));
49476
+ const verified = (0, import_node_path45.join)(work, "verified");
49477
+ const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs47.readFileSync)((0, import_node_path45.join)(verified, `${short3}.metadata.json`), "utf8"))]));
49305
49478
  const plan = planAdoption(packageText, lockText, metadata);
49306
49479
  for (const { name } of plan.result.adopted) {
49307
49480
  const short3 = PACKAGES.find((p) => p.name === name).short;
49308
- await deps.npm(["cache", "add", (0, import_node_path44.join)(verified, `${short3}.tgz`)], opts.dir);
49481
+ await deps.npm(["cache", "add", (0, import_node_path45.join)(verified, `${short3}.tgz`)], opts.dir);
49309
49482
  }
49310
- (0, import_node_fs46.writeFileSync)(packagePath, plan.packageText);
49311
- (0, import_node_fs46.writeFileSync)(lockPath, plan.lockText);
49483
+ (0, import_node_fs47.writeFileSync)(packagePath, plan.packageText);
49484
+ (0, import_node_fs47.writeFileSync)(lockPath, plan.lockText);
49312
49485
  try {
49313
49486
  await deps.npm(["ci", "--offline", "--ignore-scripts", "--no-audit", "--no-fund"], opts.dir);
49314
49487
  } catch (error) {
49315
- (0, import_node_fs46.writeFileSync)(packagePath, packageText);
49316
- (0, import_node_fs46.writeFileSync)(lockPath, lockText);
49488
+ (0, import_node_fs47.writeFileSync)(packagePath, packageText);
49489
+ (0, import_node_fs47.writeFileSync)(lockPath, lockText);
49317
49490
  throw new Error(`npm ci --offline failed, package.json and package-lock.json restored: ${error.message}`);
49318
49491
  }
49319
49492
  return plan.result;
49320
49493
  } finally {
49321
- (0, import_node_fs46.rmSync)(work, { recursive: true, force: true });
49494
+ (0, import_node_fs47.rmSync)(work, { recursive: true, force: true });
49322
49495
  }
49323
49496
  }
49324
49497
  var execFileBuffer = (0, import_node_util6.promisify)(import_node_child_process18.execFile);
@@ -49383,12 +49556,12 @@ function registerPackagesCommands(program3) {
49383
49556
  init_cli_shared();
49384
49557
 
49385
49558
  // src/wave-status.ts
49386
- var import_node_fs47 = require("node:fs");
49559
+ var import_node_fs48 = require("node:fs");
49387
49560
  function readStageSummary(worktreePath) {
49388
49561
  const statePath = stageStatePath(worktreePath);
49389
- if (!(0, import_node_fs47.existsSync)(statePath)) return void 0;
49562
+ if (!(0, import_node_fs48.existsSync)(statePath)) return void 0;
49390
49563
  try {
49391
- const state = JSON.parse((0, import_node_fs47.readFileSync)(statePath, "utf8"));
49564
+ const state = JSON.parse((0, import_node_fs48.readFileSync)(statePath, "utf8"));
49392
49565
  const port = typeof state.port === "number" ? state.port : void 0;
49393
49566
  if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
49394
49567
  return { port, url: typeof state.url === "string" ? state.url : void 0 };
@@ -49445,9 +49618,9 @@ async function collectWaveStatus(deps) {
49445
49618
  // src/discovery-commands.ts
49446
49619
  init_github_client();
49447
49620
  init_cli_shared();
49448
- var import_node_fs48 = require("node:fs");
49449
- var import_node_os22 = require("node:os");
49450
- var import_node_path45 = require("node:path");
49621
+ var import_node_fs49 = require("node:fs");
49622
+ var import_node_os23 = require("node:os");
49623
+ var import_node_path46 = require("node:path");
49451
49624
  var GC_GH_TIMEOUT_MS3 = 2e4;
49452
49625
  async function collectStatus() {
49453
49626
  const repo = await resolveRepo();
@@ -49636,10 +49809,10 @@ async function collectOnboardStatus(opts = {}) {
49636
49809
  else if (top) nextCommand = `mmi-cli oracle board claim ${top.number} # ${top.title}`;
49637
49810
  else nextCommand = "mmi-cli oracle board read \u2014 no claimable items found";
49638
49811
  }
49639
- const home = (0, import_node_os22.homedir)();
49812
+ const home = (0, import_node_os23.homedir)();
49640
49813
  const plugin = onboardPluginGate({
49641
- readKnown: () => readFileSyncSafe((0, import_node_path45.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs48.readFileSync),
49642
- readSettings: () => readFileSyncSafe((0, import_node_path45.join)(home, ".claude", "settings.json"), import_node_fs48.readFileSync)
49814
+ readKnown: () => readFileSyncSafe((0, import_node_path46.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs49.readFileSync),
49815
+ readSettings: () => readFileSyncSafe((0, import_node_path46.join)(home, ".claude", "settings.json"), import_node_fs49.readFileSync)
49643
49816
  });
49644
49817
  return {
49645
49818
  guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
@@ -51831,6 +52004,9 @@ function registerOrgHealthQuery(program3, deps = defaultOrgHealthQueryDeps()) {
51831
52004
  });
51832
52005
  }
51833
52006
 
52007
+ // src/api-read.ts
52008
+ var import_node_fs50 = require("node:fs");
52009
+
51834
52010
  // src/app-read-broker.ts
51835
52011
  init_cli_shared();
51836
52012
  var OWNER_REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
@@ -52200,7 +52376,10 @@ var CONTENTS_QUERY_RE = /^ref=[^&\s]+$/;
52200
52376
  var ACTIONS_RUNS_RE = new RegExp(`^repos/${NAME}/${NAME}/actions/runs$`);
52201
52377
  var ACTIONS_RUN_RE = new RegExp(`^repos/${NAME}/${NAME}/actions/runs/\\d+$`);
52202
52378
  var ACTIONS_JOBS_RE = new RegExp(`^repos/${NAME}/${NAME}/actions/runs/\\d+/jobs$`);
52203
- var API_GET_ALLOWED_SHAPES = "repos/{owner}/{repo}/pulls/{n}/files, repos/{owner}/{repo}/compare/{a}...{b}, repos/{owner}/{repo}/contents/{path}[?ref=<branch>], repos/{owner}/{repo}/actions/runs, repos/{owner}/{repo}/actions/runs/{id}, repos/{owner}/{repo}/actions/runs/{id}/jobs";
52379
+ var ACTIONS_ARTIFACTS_RE = new RegExp(`^repos/${NAME}/${NAME}/actions/runs/\\d+/artifacts$`);
52380
+ var ACTIONS_ARTIFACT_ZIP_RE = new RegExp(`^repos/${NAME}/${NAME}/actions/artifacts/\\d+/zip$`);
52381
+ var ACTIONS_JOB_LOGS_RE = new RegExp(`^repos/${NAME}/${NAME}/actions/jobs/\\d+/logs$`);
52382
+ var API_GET_ALLOWED_SHAPES = "repos/{owner}/{repo}/pulls/{n}/files, repos/{owner}/{repo}/compare/{a}...{b}, repos/{owner}/{repo}/contents/{path}[?ref=<branch>], repos/{owner}/{repo}/actions/runs, repos/{owner}/{repo}/actions/runs/{id}, repos/{owner}/{repo}/actions/runs/{id}/jobs, repos/{owner}/{repo}/actions/runs/{id}/artifacts, repos/{owner}/{repo}/actions/artifacts/{id}/zip (needs --out <file>), repos/{owner}/{repo}/actions/jobs/{id}/logs (needs --out <file>)";
52204
52383
  function parseApiGetPath(rawPath) {
52205
52384
  const path2 = rawPath.trim();
52206
52385
  const refuse = () => new Error(`api get: refusing '${rawPath}' \u2014 only these GET reads are allowed (#7219): ${API_GET_ALLOWED_SHAPES}`);
@@ -52210,6 +52389,9 @@ function parseApiGetPath(rawPath) {
52210
52389
  if (ACTIONS_RUNS_RE.test(path2)) return { kind: "actions-runs", path: path2, paginate: true };
52211
52390
  if (ACTIONS_RUN_RE.test(path2)) return { kind: "actions-run", path: path2, paginate: false };
52212
52391
  if (ACTIONS_JOBS_RE.test(path2)) return { kind: "actions-jobs", path: path2, paginate: true };
52392
+ if (ACTIONS_ARTIFACTS_RE.test(path2)) return { kind: "actions-artifacts", path: path2, paginate: true };
52393
+ if (ACTIONS_ARTIFACT_ZIP_RE.test(path2)) return { kind: "actions-artifact-zip", path: path2, paginate: false };
52394
+ if (ACTIONS_JOB_LOGS_RE.test(path2)) return { kind: "actions-job-logs", path: path2, paginate: false };
52213
52395
  const q = path2.indexOf("?");
52214
52396
  const base = q === -1 ? path2 : path2.slice(0, q);
52215
52397
  const query = q === -1 ? "" : path2.slice(q + 1);
@@ -52218,6 +52400,8 @@ function parseApiGetPath(rawPath) {
52218
52400
  }
52219
52401
  throw new Error(`api get: refusing '${rawPath}' \u2014 only these GET reads are allowed (#7219): ${API_GET_ALLOWED_SHAPES}`);
52220
52402
  }
52403
+ var ZIP_TIMEOUT_MS = 12e4;
52404
+ var ZIP_MAX_BUFFER = 512 * 1024 * 1024;
52221
52405
  function buildApiGetArgs(path2, accept) {
52222
52406
  const req = parseApiGetPath(path2);
52223
52407
  const args = ["api", req.path];
@@ -52230,22 +52414,28 @@ async function runApiGet(run, path2, accept) {
52230
52414
  return run(buildApiGetArgs(path2, accept), GIT_TIMEOUT_MS);
52231
52415
  }
52232
52416
  function registerApiReadCommands(program3, overrides) {
52233
- const spawn6 = overrides?.runner ?? (async (args, timeoutMs, env) => (await execFileP("gh", args, { timeout: timeoutMs, ...env ? { env } : {} })).stdout);
52234
- const api = program3.command("api").description("bounded GitHub REST reads for automation \u2014 GET only, allowlisted paths (pull files, compare, contents, actions runs/jobs)");
52417
+ const spawn6 = overrides?.runner ?? (async (args, timeoutMs, env, binary) => (await execFileP("gh", args, { timeout: timeoutMs, ...binary ? { encoding: "latin1", maxBuffer: ZIP_MAX_BUFFER } : {}, ...env ? { env } : {} })).stdout);
52418
+ const api = program3.command("api").description("bounded GitHub REST reads for automation \u2014 GET only, allowlisted paths (pull files, compare, contents, actions runs/jobs/artifacts)");
52235
52419
  api.command("get").description("GET one allowlisted REST path and print the response body to stdout (JSON, or raw file bytes with --accept raw); refuses everything outside the allowlist").option("--accept <type>", "response media type: json (default) or raw (file bytes)", (v) => {
52236
52420
  acceptHeaderFor(v);
52237
52421
  return v.trim().toLowerCase();
52238
- }, "json").argument("<path>", "allowlisted GET path (shapes named on refusal)", (v) => parseApiGetPath(v)).action(async (req, o) => {
52422
+ }, "json").option("--out <file>", "write the response bytes to this file instead of stdout (required for, and only valid with, actions/artifacts/{id}/zip)").argument("<path>", "allowlisted GET path (shapes named on refusal)", (v) => parseApiGetPath(v)).action(async (req, o) => {
52423
+ const zip = req.kind === "actions-artifact-zip" || req.kind === "actions-job-logs";
52424
+ if (zip !== (o.out !== void 0)) return fail(`api get: --out <file> is required for, and only valid with, repos/{owner}/{repo}/actions/artifacts/{id}/zip and repos/{owner}/{repo}/actions/jobs/{id}/logs`);
52239
52425
  const actionsRoute = req.kind.startsWith("actions-");
52240
52426
  if (actionsRoute) requireBrokerApp("api get");
52241
52427
  const env = actionsRoute || process.env.MMI_ACTOR === "app" ? brokerChildEnv() : void 0;
52242
52428
  let body;
52243
52429
  try {
52244
52430
  body = await runApiGet(
52245
- async (args, timeoutMs) => spawn6(args, timeoutMs, env),
52431
+ async (args, timeoutMs) => zip ? spawn6(args, ZIP_TIMEOUT_MS, env, true) : spawn6(args, timeoutMs, env),
52246
52432
  req.path,
52247
52433
  o.accept
52248
52434
  );
52435
+ if (zip) {
52436
+ (0, import_node_fs50.writeFileSync)(o.out, body, "latin1");
52437
+ return;
52438
+ }
52249
52439
  } catch (e) {
52250
52440
  const err = e;
52251
52441
  return fail(`api get: ${(err.stderr || err.message || String(e)).trim()}`);
@@ -53102,8 +53292,8 @@ function registerSessionReport(program3) {
53102
53292
  }
53103
53293
 
53104
53294
  // src/stage-commands.ts
53105
- var import_node_fs49 = require("node:fs");
53106
- var import_node_path46 = require("node:path");
53295
+ var import_node_fs51 = require("node:fs");
53296
+ var import_node_path47 = require("node:path");
53107
53297
  init_cli_shared();
53108
53298
  init_clean_exit();
53109
53299
 
@@ -53351,8 +53541,8 @@ function registerStageCommands(program3) {
53351
53541
  const repo = Array.isArray(project2?.repos) && typeof project2.repos[0] === "string" ? project2.repos[0] : slug;
53352
53542
  const resolution = decideStage({
53353
53543
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
53354
- hasCompose: (0, import_node_fs49.existsSync)((0, import_node_path46.join)(process.cwd(), "docker-compose.yml")),
53355
- hasEnvExample: (0, import_node_fs49.existsSync)((0, import_node_path46.join)(process.cwd(), ".env.example")),
53544
+ hasCompose: (0, import_node_fs51.existsSync)((0, import_node_path47.join)(process.cwd(), "docker-compose.yml")),
53545
+ hasEnvExample: (0, import_node_fs51.existsSync)((0, import_node_path47.join)(process.cwd(), ".env.example")),
53356
53546
  repo
53357
53547
  });
53358
53548
  if (resolution.source === "derived" && resolution.derived) {
@@ -53644,23 +53834,23 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
53644
53834
  }
53645
53835
 
53646
53836
  // src/tenant-artifact.ts
53647
- var import_node_crypto16 = require("node:crypto");
53648
- var import_node_fs50 = require("node:fs");
53837
+ var import_node_crypto17 = require("node:crypto");
53838
+ var import_node_fs52 = require("node:fs");
53649
53839
  var import_promises11 = require("node:fs/promises");
53650
- var import_node_path47 = require("node:path");
53840
+ var import_node_path48 = require("node:path");
53651
53841
  var ARTIFACT_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
53652
- var MAX_BYTES = 5 * 1024 * 1024 * 1024;
53842
+ var MAX_BYTES2 = 5 * 1024 * 1024 * 1024;
53653
53843
  async function sha256File(path2) {
53654
- const hash = (0, import_node_crypto16.createHash)("sha256");
53655
- for await (const chunk of (0, import_node_fs50.createReadStream)(path2)) hash.update(chunk);
53844
+ const hash = (0, import_node_crypto17.createHash)("sha256");
53845
+ for await (const chunk of (0, import_node_fs52.createReadStream)(path2)) hash.update(chunk);
53656
53846
  return hash.digest("hex");
53657
53847
  }
53658
53848
  async function putTenantArtifact(repo, stage, inputPath, deps) {
53659
53849
  if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
53660
- const path2 = (0, import_node_path47.resolve)(inputPath);
53850
+ const path2 = (0, import_node_path48.resolve)(inputPath);
53661
53851
  const info = await (0, import_promises11.stat)(path2);
53662
53852
  if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
53663
- if (!Number.isSafeInteger(info.size) || info.size < 1 || info.size > MAX_BYTES) throw new Error(`tenant artifact put: file must be 1..${MAX_BYTES} bytes`);
53853
+ if (!Number.isSafeInteger(info.size) || info.size < 1 || info.size > MAX_BYTES2) throw new Error(`tenant artifact put: file must be 1..${MAX_BYTES2} bytes`);
53664
53854
  const sha2563 = await sha256File(path2);
53665
53855
  const prepared = await tenantArtifactUpload({ repo, stage, size: info.size, sha256: sha2563 }, deps);
53666
53856
  if (!prepared.ok) {
@@ -53675,7 +53865,7 @@ async function putTenantArtifact(repo, stage, inputPath, deps) {
53675
53865
  return [key, value];
53676
53866
  }));
53677
53867
  headers["content-length"] = String(info.size);
53678
- const stream = (0, import_node_fs50.createReadStream)(path2);
53868
+ const stream = (0, import_node_fs52.createReadStream)(path2);
53679
53869
  let uploaded;
53680
53870
  try {
53681
53871
  uploaded = await fetch(body.uploadUrl, {
@@ -53814,7 +54004,7 @@ function renderVerifySecrets(body) {
53814
54004
  }
53815
54005
 
53816
54006
  // src/command-register-developer.ts
53817
- var import_node_fs54 = require("node:fs");
54007
+ var import_node_fs56 = require("node:fs");
53818
54008
  init_clean_exit();
53819
54009
  init_cli_shared();
53820
54010
  init_error_codes();
@@ -53847,7 +54037,7 @@ async function resolveWhoami(deps) {
53847
54037
  }
53848
54038
 
53849
54039
  // src/command-register-developer.ts
53850
- var import_node_path52 = require("node:path");
54040
+ var import_node_path53 = require("node:path");
53851
54041
  init_house_map();
53852
54042
  init_hub_url();
53853
54043
 
@@ -53881,28 +54071,28 @@ async function executeWaveLand(plan, deps) {
53881
54071
 
53882
54072
  // src/dist-drift.ts
53883
54073
  var import_node_child_process19 = require("node:child_process");
53884
- var import_node_crypto18 = require("node:crypto");
53885
- var import_node_fs52 = require("node:fs");
53886
- var import_node_os23 = require("node:os");
53887
- var import_node_path49 = require("node:path");
54074
+ var import_node_crypto19 = require("node:crypto");
54075
+ var import_node_fs54 = require("node:fs");
54076
+ var import_node_os24 = require("node:os");
54077
+ var import_node_path50 = require("node:path");
53888
54078
 
53889
54079
  // ../scripts/distribution-digest.mjs
53890
- var import_node_crypto17 = require("node:crypto");
53891
- var import_node_fs51 = require("node:fs");
53892
- var import_node_path48 = require("node:path");
54080
+ var import_node_crypto18 = require("node:crypto");
54081
+ var import_node_fs53 = require("node:fs");
54082
+ var import_node_path49 = require("node:path");
53893
54083
  var slash = (value) => value.replaceAll("\\", "/");
53894
54084
  function repoPath(root, declaredPath, label) {
53895
- const absoluteRoot = (0, import_node_path48.resolve)(root);
53896
- const target = (0, import_node_path48.resolve)(root, declaredPath);
53897
- if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path48.sep}`)) {
54085
+ const absoluteRoot = (0, import_node_path49.resolve)(root);
54086
+ const target = (0, import_node_path49.resolve)(root, declaredPath);
54087
+ if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path49.sep}`)) {
53898
54088
  throw new Error(`${label} ${declaredPath} escapes the repository root`);
53899
54089
  }
53900
54090
  return target;
53901
54091
  }
53902
54092
  function digestFiles(files) {
53903
- const hash = (0, import_node_crypto17.createHash)("sha256");
54093
+ const hash = (0, import_node_crypto18.createHash)("sha256");
53904
54094
  for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
53905
- const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs51.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs51.readFileSync)(file.absolute);
54095
+ const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs53.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs53.readFileSync)(file.absolute);
53906
54096
  hash.update(file.relative, "utf8");
53907
54097
  hash.update("\0");
53908
54098
  hash.update(file.stat.isSymbolicLink() ? "symlink" : "file", "utf8");
@@ -53917,8 +54107,8 @@ function digestFiles(files) {
53917
54107
  function digestPackedFiles(packageRoot, packedFiles) {
53918
54108
  return digestFiles(packedFiles.map((path2) => {
53919
54109
  const absolute = repoPath(packageRoot, path2, "packed artifact identity path");
53920
- if (!(0, import_node_fs51.existsSync)(absolute)) throw new Error(`packed artifact identity path ${path2} does not exist`);
53921
- return { absolute, relative: slash(path2), stat: (0, import_node_fs51.lstatSync)(absolute) };
54110
+ if (!(0, import_node_fs53.existsSync)(absolute)) throw new Error(`packed artifact identity path ${path2} does not exist`);
54111
+ return { absolute, relative: slash(path2), stat: (0, import_node_fs53.lstatSync)(absolute) };
53922
54112
  }));
53923
54113
  }
53924
54114
 
@@ -53930,7 +54120,7 @@ var DIST_ARTIFACTS = [
53930
54120
  ];
53931
54121
  var BOM_DIST_TREE_ID = "mmi-cli-dist";
53932
54122
  var ABSENT = "absent";
53933
- var sha2562 = (bytes) => `sha256:${(0, import_node_crypto18.createHash)("sha256").update(bytes).digest("hex")}`;
54123
+ var sha2562 = (bytes) => `sha256:${(0, import_node_crypto19.createHash)("sha256").update(bytes).digest("hex")}`;
53934
54124
  function artifactDrift(path2, committedBytes, rebuiltBytes) {
53935
54125
  const committed = committedBytes ? sha2562(committedBytes) : ABSENT;
53936
54126
  const rebuiltExpected = rebuiltBytes ? sha2562(rebuiltBytes) : ABSENT;
@@ -54002,13 +54192,13 @@ function renderDistDriftReceipt(receipt) {
54002
54192
  return lines2;
54003
54193
  }
54004
54194
  function readOrNull(path2) {
54005
- return (0, import_node_fs52.existsSync)(path2) ? (0, import_node_fs52.readFileSync)(path2) : null;
54195
+ return (0, import_node_fs54.existsSync)(path2) ? (0, import_node_fs54.readFileSync)(path2) : null;
54006
54196
  }
54007
54197
  function walkFiles(root) {
54008
54198
  const files = [];
54009
54199
  const walk2 = (directory) => {
54010
- for (const entry of (0, import_node_fs52.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54011
- const child2 = (0, import_node_path49.join)(directory, entry.name);
54200
+ for (const entry of (0, import_node_fs54.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54201
+ const child2 = (0, import_node_path50.join)(directory, entry.name);
54012
54202
  if (entry.isDirectory()) walk2(child2);
54013
54203
  else files.push(child2);
54014
54204
  }
@@ -54018,10 +54208,10 @@ function walkFiles(root) {
54018
54208
  }
54019
54209
  function bomPathFor(root) {
54020
54210
  try {
54021
- const registry2 = JSON.parse((0, import_node_fs52.readFileSync)((0, import_node_path49.join)(root, "surfaces.json"), "utf8"));
54022
- return (0, import_node_path49.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
54211
+ const registry2 = JSON.parse((0, import_node_fs54.readFileSync)((0, import_node_path50.join)(root, "surfaces.json"), "utf8"));
54212
+ return (0, import_node_path50.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
54023
54213
  } catch {
54024
- return (0, import_node_path49.join)(root, "distribution-bom.json");
54214
+ return (0, import_node_path50.join)(root, "distribution-bom.json");
54025
54215
  }
54026
54216
  }
54027
54217
  function rebuildTo(packageRoot, outDir) {
@@ -54034,35 +54224,35 @@ function rebuildTo(packageRoot, outDir) {
54034
54224
  });
54035
54225
  }
54036
54226
  function runDistStatus(root) {
54037
- const stage = (0, import_node_fs52.mkdtempSync)((0, import_node_path49.join)((0, import_node_os23.tmpdir)(), "mmi-dist-drift-"));
54227
+ const stage = (0, import_node_fs54.mkdtempSync)((0, import_node_path50.join)((0, import_node_os24.tmpdir)(), "mmi-dist-drift-"));
54038
54228
  let overlayCount = 0;
54039
54229
  try {
54040
- const cliOut = (0, import_node_path49.join)(stage, "cli-dist");
54041
- const hubOut = (0, import_node_path49.join)(stage, "hub-dist");
54042
- rebuildTo((0, import_node_path49.join)(root, "cli"), cliOut);
54043
- rebuildTo((0, import_node_path49.join)(root, "updater"), hubOut);
54230
+ const cliOut = (0, import_node_path50.join)(stage, "cli-dist");
54231
+ const hubOut = (0, import_node_path50.join)(stage, "hub-dist");
54232
+ rebuildTo((0, import_node_path50.join)(root, "cli"), cliOut);
54233
+ rebuildTo((0, import_node_path50.join)(root, "updater"), hubOut);
54044
54234
  const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
54045
54235
  const rebuilt = (path2) => {
54046
54236
  const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
54047
- return spec ? readOrNull((0, import_node_path49.join)(outDirFor(spec.packageDir), spec.output)) : null;
54237
+ return spec ? readOrNull((0, import_node_path50.join)(outDirFor(spec.packageDir), spec.output)) : null;
54048
54238
  };
54049
- const committed = (path2) => readOrNull((0, import_node_path49.join)(root, path2));
54050
- const tree = (path2) => readOrNull((0, import_node_path49.join)(root, path2));
54051
- const distRoot = (0, import_node_path49.join)(root, "cli", "dist");
54052
- const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path49.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
54053
- const bom = JSON.parse((0, import_node_fs52.readFileSync)(bomPathFor(root), "utf8"));
54239
+ const committed = (path2) => readOrNull((0, import_node_path50.join)(root, path2));
54240
+ const tree = (path2) => readOrNull((0, import_node_path50.join)(root, path2));
54241
+ const distRoot = (0, import_node_path50.join)(root, "cli", "dist");
54242
+ const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path50.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
54243
+ const bom = JSON.parse((0, import_node_fs54.readFileSync)(bomPathFor(root), "utf8"));
54054
54244
  const digest = (entries) => {
54055
- const overlay = (0, import_node_path49.join)(stage, `overlay-${overlayCount++}`);
54245
+ const overlay = (0, import_node_path50.join)(stage, `overlay-${overlayCount++}`);
54056
54246
  for (const entry of entries) {
54057
- const target = (0, import_node_path49.join)(overlay, entry.path);
54058
- (0, import_node_fs52.mkdirSync)((0, import_node_path49.dirname)(target), { recursive: true });
54059
- (0, import_node_fs52.writeFileSync)(target, entry.bytes);
54247
+ const target = (0, import_node_path50.join)(overlay, entry.path);
54248
+ (0, import_node_fs54.mkdirSync)((0, import_node_path50.dirname)(target), { recursive: true });
54249
+ (0, import_node_fs54.writeFileSync)(target, entry.bytes);
54060
54250
  }
54061
54251
  return digestPackedFiles(overlay, entries.map((entry) => entry.path));
54062
54252
  };
54063
54253
  return computeDistDriftReceipt({ committed, tree, rebuilt, distTree, bom, digest });
54064
54254
  } finally {
54065
- (0, import_node_fs52.rmSync)(stage, { recursive: true, force: true });
54255
+ (0, import_node_fs54.rmSync)(stage, { recursive: true, force: true });
54066
54256
  }
54067
54257
  }
54068
54258
 
@@ -54163,7 +54353,7 @@ init_hub_auth();
54163
54353
 
54164
54354
  // src/schedules-lift-command.ts
54165
54355
  var import_promises12 = require("node:fs/promises");
54166
- var import_node_path50 = require("node:path");
54356
+ var import_node_path51 = require("node:path");
54167
54357
  init_clean_exit();
54168
54358
  init_cli_shared();
54169
54359
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
@@ -54192,7 +54382,7 @@ async function readWorkflowFiles(dir) {
54192
54382
  const files = [];
54193
54383
  for (const name of names.sort()) {
54194
54384
  if (!/\.ya?ml$/.test(name)) continue;
54195
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises12.readFile)((0, import_node_path50.join)(dir, name), "utf8") });
54385
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises12.readFile)((0, import_node_path51.join)(dir, name), "utf8") });
54196
54386
  }
54197
54387
  return files;
54198
54388
  }
@@ -54275,8 +54465,8 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
54275
54465
 
54276
54466
  // src/spawn-policy-core.ts
54277
54467
  var import_node_child_process20 = require("node:child_process");
54278
- var import_node_fs53 = require("node:fs");
54279
- var import_node_path51 = require("node:path");
54468
+ var import_node_fs55 = require("node:fs");
54469
+ var import_node_path52 = require("node:path");
54280
54470
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
54281
54471
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
54282
54472
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -54362,7 +54552,7 @@ function runSpawnPolicy(root) {
54362
54552
  for (const file of files) {
54363
54553
  let raw;
54364
54554
  try {
54365
- raw = (0, import_node_fs53.readFileSync)((0, import_node_path51.join)(root, file), "utf8");
54555
+ raw = (0, import_node_fs55.readFileSync)((0, import_node_path52.join)(root, file), "utf8");
54366
54556
  } catch {
54367
54557
  continue;
54368
54558
  }
@@ -54382,19 +54572,19 @@ function runSpawnPolicy(root) {
54382
54572
  function registerDeveloperCommands(program3) {
54383
54573
  const rules = program3.command("rules").description("org-managed .gitignore delivery");
54384
54574
  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) => {
54385
- const path2 = (0, import_node_path52.join)(process.cwd(), ".gitignore");
54386
- const current = (0, import_node_fs54.existsSync)(path2) ? (0, import_node_fs54.readFileSync)(path2, "utf8") : null;
54575
+ const path2 = (0, import_node_path53.join)(process.cwd(), ".gitignore");
54576
+ const current = (0, import_node_fs56.existsSync)(path2) ? (0, import_node_fs56.readFileSync)(path2, "utf8") : null;
54387
54577
  const plan = planManagedGitignore(current);
54388
54578
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
54389
54579
  if (opts.json) {
54390
- if (opts.write && plan.changed) (0, import_node_fs54.writeFileSync)(path2, plan.content, "utf8");
54580
+ if (opts.write && plan.changed) (0, import_node_fs56.writeFileSync)(path2, plan.content, "utf8");
54391
54581
  console.log(JSON.stringify(plan, null, 2));
54392
54582
  if (!opts.write && plan.changed) process.exitCode = 1;
54393
54583
  return;
54394
54584
  }
54395
54585
  if (opts.write) {
54396
54586
  if (plan.changed) {
54397
- (0, import_node_fs54.writeFileSync)(path2, plan.content, "utf8");
54587
+ (0, import_node_fs56.writeFileSync)(path2, plan.content, "utf8");
54398
54588
  console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
54399
54589
  } else {
54400
54590
  console.log("mmi-cli devops org rules gitignore: up to date");
@@ -54657,12 +54847,12 @@ ${r.stderr ?? ""}`).catch(() => "");
54657
54847
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
54658
54848
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
54659
54849
  function envHealLockPath(home) {
54660
- return (0, import_node_path53.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
54850
+ return (0, import_node_path54.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
54661
54851
  }
54662
54852
  async function withEnvHealLock(what, run) {
54663
54853
  try {
54664
54854
  return await withFileLock(
54665
- envHealLockPath((0, import_node_os24.homedir)()),
54855
+ envHealLockPath((0, import_node_os25.homedir)()),
54666
54856
  { staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
54667
54857
  run
54668
54858
  );
@@ -54759,7 +54949,7 @@ function mmiDoctorDeps(opts = {}) {
54759
54949
  const configRoot = surfaceConfigRoot(surface);
54760
54950
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
54761
54951
  const plan = buildPluginCachePlan(
54762
- (0, import_node_os24.homedir)(),
54952
+ (0, import_node_os25.homedir)(),
54763
54953
  running,
54764
54954
  pluginCacheFsDeps(configRoot, () => 0),
54765
54955
  { configRoot, includeStaging: surface !== "codex" }
@@ -54787,14 +54977,14 @@ function mmiDoctorDeps(opts = {}) {
54787
54977
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
54788
54978
  const installed = installedActivePluginVersion(surface);
54789
54979
  const plan = buildPluginCachePlan(
54790
- (0, import_node_os24.homedir)(),
54980
+ (0, import_node_os25.homedir)(),
54791
54981
  running,
54792
54982
  pluginCacheFsDeps(configRoot, () => 0),
54793
54983
  { configRoot, includeStaging: surface !== "codex", installedVersion: installed }
54794
54984
  );
54795
54985
  const result = applyPluginCachePlan(
54796
54986
  plan,
54797
- (p) => (0, import_node_fs55.rmSync)(p, { recursive: true }),
54987
+ (p) => (0, import_node_fs57.rmSync)(p, { recursive: true }),
54798
54988
  stagingApplyFsGuard(configRoot)
54799
54989
  );
54800
54990
  return {
@@ -54829,7 +55019,7 @@ function mmiDoctorDeps(opts = {}) {
54829
55019
  // has no generated routing index would
54830
55020
  // get a permanent — demanding an artifact it never asked for.
54831
55021
  docsIndexState: (root) => {
54832
- if (!(0, import_node_fs55.existsSync)((0, import_node_path53.join)(root, DOCS_INDEX_PATH))) return void 0;
55022
+ if (!(0, import_node_fs57.existsSync)((0, import_node_path54.join)(root, DOCS_INDEX_PATH))) return void 0;
54833
55023
  const real = createDocsIndexDeps(root);
54834
55024
  let docs;
54835
55025
  const listDocs = () => docs ??= real.listDocs();
@@ -54838,7 +55028,7 @@ function mmiDoctorDeps(opts = {}) {
54838
55028
  },
54839
55029
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
54840
55030
  healDocsIndex: (root) => {
54841
- if (!(0, import_node_fs55.existsSync)((0, import_node_path53.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
55031
+ if (!(0, import_node_fs57.existsSync)((0, import_node_path54.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
54842
55032
  const real = createDocsIndexDeps(root);
54843
55033
  let docs;
54844
55034
  const listDocs = () => docs ??= real.listDocs();
@@ -55187,10 +55377,13 @@ program2.addHelpText(
55187
55377
  var appActorCommand = "poll";
55188
55378
  function appActorDeps() {
55189
55379
  return {
55190
- fetchSecret: async (key) => fetchSecretValue(makeSecretsDeps(await loadConfig()), key, {
55191
- repo: APP_VAULT_REPO,
55192
- attribution: { command: appActorCommand, via: formatSessionIdentity(describeSessionIdentity()) }
55193
- }),
55380
+ fetchSecret: async (key) => {
55381
+ const deps = makeSecretsDeps(await loadConfig());
55382
+ return readAppVaultSecret(() => fetchSecretValue(deps, key, {
55383
+ repo: APP_VAULT_REPO,
55384
+ attribution: { command: appActorCommand, via: formatSessionIdentity(describeSessionIdentity()) }
55385
+ }, true));
55386
+ },
55194
55387
  fetch: (url, init) => fetch(url, init)
55195
55388
  };
55196
55389
  }
@@ -55218,8 +55411,9 @@ async function reportWrite(label, res) {
55218
55411
  return failGraceful(`${label}: HTTP ${res.status}${detail ? ` \u2014 ${detail}` : ""}`);
55219
55412
  }
55220
55413
  var tenant = program2.command("tenant").description("tenant runtime control through Hub authority");
55221
- tenant.command("control <owner/repo> <stage> <action>").description("bounded tenant control plus value-free vault/broker verification; dev/main retire needs master and exact data-loss confirmation").option("--watch", "block on the dispatched run and report its conclusion (status/retire/verify-secrets/verify-broker/logs watch by default)").option("--lines <n>", "logs only: trailing lines of the tenant service to return (1-2000, default 200)").option("--since <utc>", "logs only: read the journal from this UTC time, e.g. 2026-10-07T13:10Z (includes replaced containers)").option("--until <utc>", "logs only: read the journal up to this UTC time").option("--edge", "logs only: Caddy journal for this stage\u2019s hosts (default window: last 15 minutes)").option("--task <name>", "run-task only: registry-declared task name (never a command)").option("--artifact <id>", "run-task only: opaque id returned by tenant artifact put").option("--confirm-data-loss <owner/repo/stage>", "dev/main retire only: exact target to decommission; without it show the dry-run plan").option("--json", "machine-readable output").action(async (repo, stage, action, o) => {
55414
+ tenant.command("control <owner/repo> <stage> <action>").description("bounded tenant control plus value-free vault/broker verification; dev/main retire needs master and exact data-loss confirmation").option("--watch", "block on the dispatched run and report its conclusion (status/retire/verify-secrets/verify-broker/logs watch by default)").option("--lines <n>", "logs only: trailing lines of the tenant service to return (1-2000, default 200)").option("--since <utc>", "logs only: read the journal from this UTC time, e.g. 2026-10-07T13:10Z (includes replaced containers)").option("--until <utc>", "logs only: read the journal up to this UTC time").option("--edge", "logs only: Caddy journal for this stage\u2019s hosts (default window: last 15 minutes)").option("--task <name>", "run-task only: registry-declared task name (never a command)").option("--artifact <id>", "run-task only: opaque id returned by tenant artifact put").option("--resume <run-id>", "run-task only: re-attach to an already-dispatched run (read-only, never re-dispatches) and print its receipt").option("--confirm-data-loss <owner/repo/stage>", "dev/main retire only: exact target to decommission; without it show the dry-run plan").option("--json", "machine-readable output").action(async (repo, stage, action, o) => {
55222
55415
  try {
55416
+ if (o.resume !== void 0 && (action !== "run-task" || !/^\d+$/.test(o.resume) || o.task || o.artifact)) return fail("runtime tenant control: --resume <run-id> is run-task-only, takes a numeric run id, and cannot be combined with --task/--artifact");
55223
55417
  if (o.confirmDataLoss !== void 0 && (action !== "retire" || stage === "rc")) return fail("runtime tenant control: --confirm-data-loss is dev/main retire-only");
55224
55418
  if (action === "retire" && (stage === "dev" || stage === "main")) {
55225
55419
  if (o.confirmDataLoss !== void 0 && o.confirmDataLoss !== `${repo}/${stage}`) return fail(`runtime tenant control: --confirm-data-loss must match ${repo}/${stage} exactly`);
@@ -55244,11 +55438,11 @@ Dry run: pass --confirm-data-loss ${repo}/${stage} to decommission.`);
55244
55438
  if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?Z$/.test(value)) return fail(`runtime tenant control: ${flag} must be a UTC time like 2026-10-07T13:10Z`);
55245
55439
  }
55246
55440
  if (action === "run-task") {
55247
- if (!o.task) return fail("runtime tenant control: run-task requires --task <declared-name>");
55441
+ if (!o.task && o.resume === void 0) return fail("runtime tenant control: run-task requires --task <declared-name>");
55248
55442
  } else if (o.task || o.artifact) {
55249
55443
  return fail("runtime tenant control: --task/--artifact are valid only for run-task");
55250
55444
  }
55251
- const result = await runTenantControl(trainApplyDeps(), { repo, stage, action, watch: o.watch, lines: lines2, edge: o.edge, logSince: o.since, logUntil: o.until, task: o.task, artifact: o.artifact, confirmDataLoss: o.confirmDataLoss });
55445
+ const result = await runTenantControl(trainApplyDeps(), { repo, stage, action, watch: o.watch, lines: lines2, edge: o.edge, logSince: o.since, logUntil: o.until, task: o.task, artifact: o.artifact, confirmDataLoss: o.confirmDataLoss, resume: o.resume === void 0 ? void 0 : Number(o.resume) });
55252
55446
  if (!o.json && action === "verify-secrets" && result.secrets) {
55253
55447
  const body = { ok: result.conclusion === "success", secrets: result.secrets, ssmStatus: result.conclusion === "success" ? "Success" : "Failed", raw: result.secretsRaw };
55254
55448
  const { lines: lines3, failure } = renderVerifySecrets(body);
@@ -55552,7 +55746,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
55552
55746
  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`);
55553
55747
  if (o.secretsFile) {
55554
55748
  try {
55555
- vars.push(`secrets=${(0, import_node_fs55.readFileSync)(o.secretsFile, "utf8")}`);
55749
+ vars.push(`secrets=${(0, import_node_fs57.readFileSync)(o.secretsFile, "utf8")}`);
55556
55750
  } catch (e) {
55557
55751
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
55558
55752
  }
@@ -55821,9 +56015,11 @@ projectTenantTasks.command("declare <name>").description("register a NEW tenant
55821
56015
  if (!res.ok) process.exitCode = 1;
55822
56016
  });
55823
56017
  var registry = program2.command("registry").description("the DDB org registry \u2014 org-level constants");
55824
- registry.command("org").description("the org config (account id, region, orgProjectId, sagaApiUrl)").option("--json", "machine-readable output").action(async (_o) => {
56018
+ registry.command("org").description("the org config (account id, region, orgProjectId, sagaApiUrl)").option("--json", "machine-readable output").option("--github-spend-minutes <minutes>", "master-only App spend by route, caller and pool over the last 1\u201360 minutes").action(async (_o) => {
56019
+ const minutes = _o.githubSpendMinutes === void 0 ? void 0 : Number(_o.githubSpendMinutes);
56020
+ if (minutes !== void 0 && (!Number.isInteger(minutes) || minutes < 1 || minutes > 60)) return fail("github-spend-minutes must be an integer from 1 to 60");
55825
56021
  const cfg = await loadConfig();
55826
- const org = await fetchOrgConfig(registryClientDeps(cfg));
56022
+ const org = await fetchOrgConfig(registryClientDeps(cfg), minutes);
55827
56023
  if (!org) return failGraceful("org config get: Hub API unreachable, unseeded, or this repo is not bootstrapped");
55828
56024
  console.log(JSON.stringify(org));
55829
56025
  });
@@ -55940,16 +56136,16 @@ function ciAuditDeps2() {
55940
56136
  // gate re-seed step is skipped gracefully rather than failing mid-run.
55941
56137
  readSeedFile: (path2) => {
55942
56138
  if (!root) return null;
55943
- const fullPath = (0, import_node_path53.join)(root, path2);
55944
- return (0, import_node_fs55.existsSync)(fullPath) ? (0, import_node_fs55.readFileSync)(fullPath, "utf8") : null;
56139
+ const fullPath = (0, import_node_path54.join)(root, path2);
56140
+ return (0, import_node_fs57.existsSync)(fullPath) ? (0, import_node_fs57.readFileSync)(fullPath, "utf8") : null;
55945
56141
  }
55946
56142
  };
55947
56143
  }
55948
56144
  function hubRoot2() {
55949
- const fromPkg = (0, import_node_path53.join)(__dirname, "..", "..");
56145
+ const fromPkg = (0, import_node_path54.join)(__dirname, "..", "..");
55950
56146
  const marker = "skills/bootstrap/seeds/manifest.json";
55951
- if ((0, import_node_fs55.existsSync)((0, import_node_path53.join)(fromPkg, marker))) return fromPkg;
55952
- if ((0, import_node_fs55.existsSync)((0, import_node_path53.join)(process.cwd(), marker))) return process.cwd();
56147
+ if ((0, import_node_fs57.existsSync)((0, import_node_path54.join)(fromPkg, marker))) return fromPkg;
56148
+ if ((0, import_node_fs57.existsSync)((0, import_node_path54.join)(process.cwd(), marker))) return process.cwd();
55953
56149
  return null;
55954
56150
  }
55955
56151
  registerQueryCommands(program2);
@@ -56079,10 +56275,10 @@ access.command("audit").description("audit collaborator roles + train-branch pus
56079
56275
  targets = resolution.targets;
56080
56276
  }
56081
56277
  const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
56082
- const fileMatrix = (0, import_node_fs55.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs55.readFileSync)("access-matrix.json", "utf8")) : {};
56278
+ const fileMatrix = (0, import_node_fs57.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs57.readFileSync)("access-matrix.json", "utf8")) : {};
56083
56279
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
56084
56280
  const dataAccess = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
56085
- const sanctioned = (0, import_node_fs55.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs55.readFileSync)("access-matrix.json", "utf8")) : {};
56281
+ const sanctioned = (0, import_node_fs57.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs57.readFileSync)("access-matrix.json", "utf8")) : {};
56086
56282
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
56087
56283
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
56088
56284
  if (!report.ok) process.exitCode = 1;
@@ -56113,16 +56309,16 @@ function directoryBytes(path2) {
56113
56309
  let total = 0;
56114
56310
  let entries;
56115
56311
  try {
56116
- entries = (0, import_node_fs55.readdirSync)(path2, { withFileTypes: true });
56312
+ entries = (0, import_node_fs57.readdirSync)(path2, { withFileTypes: true });
56117
56313
  } catch {
56118
56314
  return 0;
56119
56315
  }
56120
56316
  for (const entry of entries) {
56121
- const child2 = (0, import_node_path53.join)(path2, entry.name);
56317
+ const child2 = (0, import_node_path54.join)(path2, entry.name);
56122
56318
  if (entry.isDirectory()) total += directoryBytes(child2);
56123
56319
  else {
56124
56320
  try {
56125
- total += (0, import_node_fs55.statSync)(child2).size;
56321
+ total += (0, import_node_fs57.statSync)(child2).size;
56126
56322
  } catch {
56127
56323
  }
56128
56324
  }
@@ -56130,25 +56326,25 @@ function directoryBytes(path2) {
56130
56326
  return total;
56131
56327
  }
56132
56328
  function listDirEntries(dir) {
56133
- return (0, import_node_fs55.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
56329
+ return (0, import_node_fs57.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
56134
56330
  }
56135
56331
  function readInstalledPluginRefs(configRoot) {
56136
56332
  const p = installedPluginsPathForConfig(configRoot);
56137
- if (!(0, import_node_fs55.existsSync)(p)) return [];
56333
+ if (!(0, import_node_fs57.existsSync)(p)) return [];
56138
56334
  try {
56139
- return installedPluginPaths((0, import_node_fs55.readFileSync)(p, "utf8"));
56335
+ return installedPluginPaths((0, import_node_fs57.readFileSync)(p, "utf8"));
56140
56336
  } catch {
56141
56337
  return null;
56142
56338
  }
56143
56339
  }
56144
56340
  function pluginCacheFsDeps(configRoot, dirBytes) {
56145
56341
  return {
56146
- exists: (p) => (0, import_node_fs55.existsSync)(p),
56147
- listVersionDirs: (root) => (0, import_node_fs55.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
56342
+ exists: (p) => (0, import_node_fs57.existsSync)(p),
56343
+ listVersionDirs: (root) => (0, import_node_fs57.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
56148
56344
  dirBytes,
56149
- listStagingDirs: (root) => (0, import_node_fs55.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
56345
+ listStagingDirs: (root) => (0, import_node_fs57.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
56150
56346
  try {
56151
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path53.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs55.statSync)(p).mtimeMs) };
56347
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path54.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs57.statSync)(p).mtimeMs) };
56152
56348
  } catch {
56153
56349
  return { name: d.name, mtimeMs: Date.now() };
56154
56350
  }
@@ -56162,10 +56358,10 @@ function stagingApplyFsGuard(configRoot) {
56162
56358
  return {
56163
56359
  referencedPaths: () => readInstalledPluginRefs(configRoot),
56164
56360
  mtimeMs: (name) => {
56165
- const p = (0, import_node_path53.join)(stagingRoot, name);
56166
- if (!(0, import_node_fs55.existsSync)(p)) return null;
56361
+ const p = (0, import_node_path54.join)(stagingRoot, name);
56362
+ if (!(0, import_node_fs57.existsSync)(p)) return null;
56167
56363
  try {
56168
- return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs55.statSync)(q).mtimeMs);
56364
+ return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs57.statSync)(q).mtimeMs);
56169
56365
  } catch {
56170
56366
  return null;
56171
56367
  }
@@ -56185,13 +56381,13 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
56185
56381
  return;
56186
56382
  }
56187
56383
  const plan = buildPluginCachePlan(
56188
- (0, import_node_os24.homedir)(),
56384
+ (0, import_node_os25.homedir)(),
56189
56385
  running,
56190
56386
  pluginCacheFsDeps(configRoot, directoryBytes),
56191
56387
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
56192
56388
  );
56193
56389
  const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
56194
- const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs55.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
56390
+ const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs57.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
56195
56391
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
56196
56392
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
56197
56393
  else console.log(renderPluginCachePlan(plan, result));