@mutmutco/cli 4.3.44 → 4.3.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +3 -4
  2. package/dist/main.cjs +338 -508
  3. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -3416,7 +3416,7 @@ function useColor() {
3416
3416
  var program = new Command();
3417
3417
 
3418
3418
  // src/command-composition.ts
3419
- var import_node_fs50 = require("node:fs");
3419
+ var import_node_fs48 = require("node:fs");
3420
3420
 
3421
3421
  // src/clean-exit.ts
3422
3422
  var UNDICI_GLOBAL_DISPATCHER_SYMBOL = Object.getOwnPropertySymbols(globalThis).find(
@@ -5252,16 +5252,14 @@ var GUIDES = /* @__PURE__ */ new Map([
5252
5252
  did_you_mean: "oracle issue edit"
5253
5253
  }
5254
5254
  ],
5255
- // #5968: `worktree create` names a capability the HOST CLI owns, not an mmi-cli route. The default
5256
- // envelope built `mmi-cli explain jervcode worktree-create --json` — an explain hop that itself
5257
- // dead-ends on ERR_NOT_FOUND — so the guide carries the corrected command directly.
5255
+ // Worktree creation belongs to Git or the selected host, not an MMI command.
5258
5256
  [
5259
5257
  "worktree:create",
5260
5258
  {
5261
- hint: "no `worktree create` in mmi-cli \u2014 worktree lifecycle lives on the host CLI: `jervcode worktree-create`",
5262
- expected: ["jervcode worktree-create"],
5263
- did_you_mean: "jervcode worktree-create",
5264
- corrected_command: "jervcode worktree-create --help"
5259
+ hint: "no `worktree create` in mmi-cli \u2014 after claiming the issue, use Git or your host to create an isolated worktree",
5260
+ expected: ["git worktree add"],
5261
+ did_you_mean: "git worktree add",
5262
+ corrected_command: "git worktree -h"
5265
5263
  }
5266
5264
  ]
5267
5265
  ]);
@@ -5304,8 +5302,8 @@ function resolveVerbAliasShim(argv) {
5304
5302
  }
5305
5303
 
5306
5304
  // src/command-composition.ts
5307
- var import_node_os22 = require("node:os");
5308
- var import_node_path47 = require("node:path");
5305
+ var import_node_os21 = require("node:os");
5306
+ var import_node_path46 = require("node:path");
5309
5307
 
5310
5308
  // src/board-read.ts
5311
5309
  var import_node_fs13 = require("node:fs");
@@ -7348,7 +7346,7 @@ var OWNER = "mutmutco";
7348
7346
  var SSM_ROOT = "/mmi-future";
7349
7347
  var PROJECT_TIER_SEGMENT = "dev";
7350
7348
  var ORG_INFRA_SLUG = "_org";
7351
- var JERV_VAULT_POINTER = "Not in the MMI vault? Jerv service, personal API and model-provider credentials live in the separate Jerv AWS Vault \u2014 enumerate: `jerv-cli vault list`; consume keyless: `jerv-cli vault use <KEY> -- <cmd>` (values are never printed).";
7349
+ var MMI_VAULT_GUIDANCE = 'Check MMI access with `mmi-cli oracle org access capabilities`; a master can locate credentials with `mmi-cli vault secrets find "<what it is for>"`.';
7352
7350
  var KEY_MAX_PATH_SEGMENTS = 4;
7353
7351
  var KEY_RE = new RegExp(`^(?:[a-z0-9][a-z0-9-]*/){0,${KEY_MAX_PATH_SEGMENTS}}[A-Za-z][A-Za-z0-9_]*$`);
7354
7352
  function isValidSecretKey(key) {
@@ -7365,7 +7363,7 @@ function secretParamName(slug, key) {
7365
7363
  return `${SSM_ROOT}/${slug}/${key}`;
7366
7364
  }
7367
7365
  function formatSecretList(items) {
7368
- if (!items.length) return `no secrets \u2014 ${JERV_VAULT_POINTER}`;
7366
+ if (!items.length) return `no secrets \u2014 ${MMI_VAULT_GUIDANCE}`;
7369
7367
  const width = Math.max(...items.map((i) => i.key.length));
7370
7368
  return items.map((i) => {
7371
7369
  const head = `${i.canManage ? "*" : " "} ${i.key.padEnd(width)} ${i.tier}`;
@@ -7558,7 +7556,7 @@ function formatCapabilities(r) {
7558
7556
  const items = [...r.capabilities ?? []].sort((a, b) => a.scope.localeCompare(b.scope));
7559
7557
  if (!items.length) return `${head}
7560
7558
 
7561
- no vault credentials visible \u2014 ${JERV_VAULT_POINTER}`;
7559
+ no vault credentials visible \u2014 ${MMI_VAULT_GUIDANCE}`;
7562
7560
  const width = Math.max(...items.map((i) => i.scope.length));
7563
7561
  const lines2 = items.map(
7564
7562
  (i) => `${i.accessible ? "+" : " "} ${i.scope.padEnd(width)} ${i.tier.padEnd(7)} ${i.grantScope ? `${i.reason} (${i.grantScope})` : i.reason}`
@@ -7682,7 +7680,7 @@ function resolveNotFoundGuidance(input) {
7682
7680
  `Secret ${key} was not found at ${tried}, and no key named ${leaf} is visible to you.`,
7683
7681
  `Locate it by intent first: \`mmi-cli vault secrets find "<what it is for>"\` \u2014 it returns the exact keyless-use command.`,
7684
7682
  mnemonic,
7685
- JERV_VAULT_POINTER
7683
+ MMI_VAULT_GUIDANCE
7686
7684
  ];
7687
7685
  if (isMaster) {
7688
7686
  lines2.push("You are master: if it truly does not exist yet, create it with `mmi-cli vault secrets set` rather than requesting a grant from yourself.");
@@ -8792,7 +8790,7 @@ async function secretsVerify(deps, key, opts) {
8792
8790
  if (!value) {
8793
8791
  deps.err(`${key}: ABSENT or unreachable at this coordinate \u2014 no value could be read`);
8794
8792
  deps.err(`Locate a key across every vault you can reach: mmi-cli oracle org access capabilities${opts.repo ? ` --repo ${opts.repo}` : ""}`);
8795
- deps.err(JERV_VAULT_POINTER);
8793
+ deps.err(MMI_VAULT_GUIDANCE);
8796
8794
  return false;
8797
8795
  }
8798
8796
  deps.log(`${key}: PRESENT (${value.length} chars) \u2014 reachability only; no provider verifier is configured for ${secretLeafName(key)}, so the credential itself was not validated`);
@@ -9632,7 +9630,7 @@ async function loadConfigForBoardSelector(selector, repoOption) {
9632
9630
  var SKILL_LESSON_LABEL = "skill-lesson";
9633
9631
  var SKILL_LESSON_FILE_LABELS = [SKILL_LESSON_LABEL, LEARNING_LABEL2];
9634
9632
  var SKILL_LESSON_LOOP_KIND = "lesson";
9635
- var SKILL_NAMES = ["bootstrap", "epic", "hotfix", "rcand", "release", "secrets", "stage"];
9633
+ var SKILL_NAMES = ["board", "bootstrap", "epic", "hotfix", "rcand", "release", "secrets", "stage"];
9636
9634
  function assertSkillName(name) {
9637
9635
  const match = SKILL_NAMES.find((skill) => skill === name);
9638
9636
  if (!match) throw new Error(`unknown skill "${name}" \u2014 expected one of: ${SKILL_NAMES.join(", ")}`);
@@ -9661,11 +9659,6 @@ ${buildSkillLessonBody(body, sourceRepo, pluginSha)}`;
9661
9659
  function findDuplicateLesson(source, openLessons) {
9662
9660
  return findDuplicateReport(source, openLessons);
9663
9661
  }
9664
- var SKILL_LESSON_DEPRECATION_NOTICE = "mmi-cli learning skill-lesson is deprecated \u2014 file the retro with the jerv_learning_note tool in-session (origin retro), or `jervcode learn --origin retro --surface skills` on a machine path. This verb still files.";
9665
- function warnSkillLessonDeprecated(write = (line) => void process.stderr.write(line)) {
9666
- write(`${SKILL_LESSON_DEPRECATION_NOTICE}
9667
- `);
9668
- }
9669
9662
 
9670
9663
  // src/session-identity.ts
9671
9664
  var import_node_crypto4 = require("node:crypto");
@@ -15710,10 +15703,10 @@ var rollout_plan_default = {
15710
15703
  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)."
15711
15704
  },
15712
15705
  baseline: {
15713
- version: "4.3.44",
15714
- tag: "v4.3.44",
15715
- commit: "405d6e3283b9",
15716
- npm: "@mutmutco/cli@4.3.44"
15706
+ version: "4.3.45",
15707
+ tag: "v4.3.45",
15708
+ commit: "519cee3af091",
15709
+ npm: "@mutmutco/cli@4.3.45"
15717
15710
  },
15718
15711
  exitCriterion: "fleet-n-of-n",
15719
15712
  hubOnlyShortcut: "forbidden",
@@ -15730,14 +15723,14 @@ var rollout_plan_default = {
15730
15723
  repo: "mutmutco/mmi-hub",
15731
15724
  role: "canary",
15732
15725
  schedule: "train",
15733
- v3Target: "v4.3.44"
15726
+ v3Target: "v4.3.45"
15734
15727
  }
15735
15728
  ],
15736
15729
  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.",
15737
15730
  rollback: {
15738
15731
  independent: true,
15739
- mechanism: "npm dist-tag latest -> 4.3.44 and redeploy the Hub Lambda from tag v4.3.44 (405d6e3283b9); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15740
- v3Target: "v4.3.44 (@mutmutco/cli@4.3.44, tag commit 405d6e3283b9 \u2014 last known-good release carrying the repo-index v4-only contract)"
15732
+ mechanism: "npm dist-tag latest -> 4.3.45 and redeploy the Hub Lambda from tag v4.3.45 (519cee3af091); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15733
+ v3Target: "v4.3.45 (@mutmutco/cli@4.3.45, tag commit 519cee3af091 \u2014 last known-good release carrying the repo-index v4-only contract)"
15741
15734
  }
15742
15735
  },
15743
15736
  {
@@ -19126,7 +19119,7 @@ function renderTenantControl(r) {
19126
19119
  }
19127
19120
 
19128
19121
  // src/train-apply-phases.ts
19129
- var import_node_fs24 = require("node:fs");
19122
+ var import_node_fs23 = require("node:fs");
19130
19123
  var import_promises3 = require("node:fs/promises");
19131
19124
  var import_node_path23 = require("node:path");
19132
19125
 
@@ -19381,7 +19374,7 @@ Resume it: ${resumeCommand}
19381
19374
 
19382
19375
  // src/train-doctor.ts
19383
19376
  var import_node_child_process9 = require("node:child_process");
19384
- var import_node_fs23 = require("node:fs");
19377
+ var import_node_fs22 = require("node:fs");
19385
19378
  var import_node_os13 = require("node:os");
19386
19379
  var import_node_path22 = require("node:path");
19387
19380
 
@@ -19592,16 +19585,13 @@ function compatHolds(range, version) {
19592
19585
  }
19593
19586
 
19594
19587
  // src/claude-binary-doctor.ts
19595
- var import_node_fs21 = require("node:fs");
19588
+ var import_node_fs20 = require("node:fs");
19596
19589
  var import_node_os12 = require("node:os");
19597
19590
  var import_node_path19 = require("node:path");
19598
19591
 
19599
19592
  // src/jerv-cli-spawn.ts
19600
- var import_node_fs20 = require("node:fs");
19601
19593
  var import_node_os11 = require("node:os");
19602
19594
  var import_node_path18 = require("node:path");
19603
- var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
19604
- var POSIX_NAMES = ["jerv-cli"];
19605
19595
  var JERV_CLI_ENTRY = (0, import_node_path18.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
19606
19596
  function pathEnvEntries(pathEnv, platform2 = process.platform) {
19607
19597
  if (platform2 !== "win32") {
@@ -19645,67 +19635,6 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os11.hom
19645
19635
  }
19646
19636
  return out;
19647
19637
  }
19648
- function jervCliCandidatePaths(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform) {
19649
- const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
19650
- const out = [];
19651
- for (const dir of jervCliCandidateDirs(env, home, platform2)) {
19652
- for (const name of names) out.push((0, import_node_path18.join)(dir, name));
19653
- }
19654
- return out;
19655
- }
19656
- function resolveJervCliPath(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform, exists = import_node_fs20.existsSync) {
19657
- for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
19658
- if (exists(candidate)) return candidate;
19659
- }
19660
- return void 0;
19661
- }
19662
- function resolveJervCliNodeEntry(shimPath, exists = import_node_fs20.existsSync) {
19663
- const entry = (0, import_node_path18.join)((0, import_node_path18.dirname)(shimPath), JERV_CLI_ENTRY);
19664
- return exists(entry) ? entry : void 0;
19665
- }
19666
- function jervCliExecFileArgs(args, opts = {}) {
19667
- const platform2 = opts.platform ?? process.platform;
19668
- const exists = opts.exists ?? import_node_fs20.existsSync;
19669
- const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os11.homedir)(), platform2, exists);
19670
- if (resolved) {
19671
- const entry = resolveJervCliNodeEntry(resolved, exists);
19672
- if (entry) {
19673
- return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
19674
- }
19675
- }
19676
- const bin = resolved ?? "jerv-cli";
19677
- if (platform2 === "win32") {
19678
- return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
19679
- }
19680
- return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
19681
- }
19682
- function formatJervCliSpawnFailure(err, plan, candidates) {
19683
- const base = (err.stderr?.trim() || err.message.trim()).split("\n")[0] || "spawn failed";
19684
- const code = err.code;
19685
- if (code !== "ENOENT" && !/\bENOENT\b/i.test(base)) return base;
19686
- const tried = candidates.length > 0 ? candidates.join(" | ") : "(no candidates)";
19687
- return `${base} [via=${plan.via} file=${plan.file}; tried: ${tried}]`;
19688
- }
19689
- function isEnoent(err) {
19690
- const code = err.code;
19691
- if (code === "ENOENT") return true;
19692
- return /\bENOENT\b/i.test(err.message ?? "");
19693
- }
19694
- function execJervCli(args, options = {}) {
19695
- const env = options.env ?? process.env;
19696
- const candidates = jervCliCandidatePaths(env);
19697
- const plan = jervCliExecFileArgs(args, { env });
19698
- return execFileP(plan.file, plan.args, options).catch((err) => {
19699
- if (!isEnoent(err)) throw err;
19700
- const wrapped = new Error(formatJervCliSpawnFailure(err, plan, candidates));
19701
- Object.assign(wrapped, {
19702
- code: "ENOENT",
19703
- stderr: err.stderr,
19704
- cause: err
19705
- });
19706
- throw wrapped;
19707
- });
19708
- }
19709
19638
 
19710
19639
  // src/claude-binary-doctor.ts
19711
19640
  var PACKAGE = "@anthropic-ai/claude-code";
@@ -19765,16 +19694,16 @@ function globalNodeModulesRoots(host) {
19765
19694
  function readHead(path2) {
19766
19695
  let fd;
19767
19696
  try {
19768
- fd = (0, import_node_fs21.openSync)(path2, "r");
19697
+ fd = (0, import_node_fs20.openSync)(path2, "r");
19769
19698
  const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
19770
- const read = (0, import_node_fs21.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
19699
+ const read = (0, import_node_fs20.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
19771
19700
  return buffer.subarray(0, read);
19772
19701
  } catch {
19773
19702
  return void 0;
19774
19703
  } finally {
19775
19704
  if (fd !== void 0) {
19776
19705
  try {
19777
- (0, import_node_fs21.closeSync)(fd);
19706
+ (0, import_node_fs20.closeSync)(fd);
19778
19707
  } catch {
19779
19708
  }
19780
19709
  }
@@ -19782,7 +19711,7 @@ function readHead(path2) {
19782
19711
  }
19783
19712
  function fileBytes(path2) {
19784
19713
  try {
19785
- return (0, import_node_fs21.statSync)(path2).size;
19714
+ return (0, import_node_fs20.statSync)(path2).size;
19786
19715
  } catch {
19787
19716
  return void 0;
19788
19717
  }
@@ -19796,13 +19725,13 @@ function readClaudeBinaryState(host = {}) {
19796
19725
  const arch = host.arch ?? process.arch;
19797
19726
  const magic = EXECUTABLE_MAGIC[platform2];
19798
19727
  if (!magic) return void 0;
19799
- const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path19.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs21.existsSync)((0, import_node_path19.join)(dir, "package.json")));
19728
+ const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path19.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs20.existsSync)((0, import_node_path19.join)(dir, "package.json")));
19800
19729
  if (!packageRoot) return void 0;
19801
19730
  const keys = platformPackageKeys(platform2, arch);
19802
19731
  const fallbackPackage = `${PACKAGE}-${keys[0]}`;
19803
19732
  let manifest;
19804
19733
  try {
19805
- manifest = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path19.join)(packageRoot, "package.json"), "utf8"));
19734
+ manifest = JSON.parse((0, import_node_fs20.readFileSync)((0, import_node_path19.join)(packageRoot, "package.json"), "utf8"));
19806
19735
  } catch (e) {
19807
19736
  return {
19808
19737
  state: "unreadable",
@@ -19833,7 +19762,7 @@ function readClaudeBinaryState(host = {}) {
19833
19762
  (0, import_node_path19.join)(packageRoot, "node_modules", ...name.split("/"), binName),
19834
19763
  (0, import_node_path19.join)((0, import_node_path19.dirname)((0, import_node_path19.dirname)(packageRoot)), ...name.split("/"), binName)
19835
19764
  ];
19836
- const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs21.existsSync)(file)) })).find((c) => c.path);
19765
+ const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs20.existsSync)(file)) })).find((c) => c.path);
19837
19766
  const platformPackage = found?.name ?? published[0];
19838
19767
  let source;
19839
19768
  let sourceProblem;
@@ -19844,7 +19773,7 @@ function readClaudeBinaryState(host = {}) {
19844
19773
  } else {
19845
19774
  source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
19846
19775
  }
19847
- if (!(0, import_node_fs21.existsSync)(binPath)) {
19776
+ if (!(0, import_node_fs20.existsSync)(binPath)) {
19848
19777
  return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
19849
19778
  }
19850
19779
  const head = readHead(binPath);
@@ -19887,9 +19816,9 @@ function healClaudeBinary(host = {}, onStep) {
19887
19816
  const platform2 = host.platform ?? process.platform;
19888
19817
  const aside = `${probe.binPath}.stub-${Date.now()}`;
19889
19818
  let renamed = false;
19890
- if ((0, import_node_fs21.existsSync)(probe.binPath)) {
19819
+ if ((0, import_node_fs20.existsSync)(probe.binPath)) {
19891
19820
  try {
19892
- (0, import_node_fs21.renameSync)(probe.binPath, aside);
19821
+ (0, import_node_fs20.renameSync)(probe.binPath, aside);
19893
19822
  renamed = true;
19894
19823
  onStep?.(`renamed the stub aside: ${aside}`);
19895
19824
  } catch (e) {
@@ -19898,12 +19827,12 @@ function healClaudeBinary(host = {}, onStep) {
19898
19827
  }
19899
19828
  try {
19900
19829
  onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
19901
- (0, import_node_fs21.copyFileSync)(probe.source.path, probe.binPath);
19902
- if (platform2 !== "win32") (0, import_node_fs21.chmodSync)(probe.binPath, 493);
19830
+ (0, import_node_fs20.copyFileSync)(probe.source.path, probe.binPath);
19831
+ if (platform2 !== "win32") (0, import_node_fs20.chmodSync)(probe.binPath, 493);
19903
19832
  } catch (e) {
19904
19833
  if (renamed) {
19905
19834
  try {
19906
- (0, import_node_fs21.renameSync)(aside, probe.binPath);
19835
+ (0, import_node_fs20.renameSync)(aside, probe.binPath);
19907
19836
  } catch {
19908
19837
  return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
19909
19838
  }
@@ -19917,7 +19846,7 @@ function healClaudeBinary(host = {}, onStep) {
19917
19846
  let kept = false;
19918
19847
  if (renamed) {
19919
19848
  try {
19920
- (0, import_node_fs21.rmSync)(aside);
19849
+ (0, import_node_fs20.rmSync)(aside);
19921
19850
  } catch {
19922
19851
  kept = true;
19923
19852
  }
@@ -20276,7 +20205,7 @@ function checkLineEndings(probe) {
20276
20205
  }
20277
20206
 
20278
20207
  // src/release-ledger.ts
20279
- var import_node_fs22 = require("node:fs");
20208
+ var import_node_fs21 = require("node:fs");
20280
20209
  var import_node_path21 = require("node:path");
20281
20210
  var import_node_crypto5 = require("node:crypto");
20282
20211
 
@@ -20533,7 +20462,7 @@ function resolvePrimaryGitDir(cwd) {
20533
20462
  }
20534
20463
  let common;
20535
20464
  try {
20536
- common = (0, import_node_fs22.readFileSync)((0, import_node_path21.join)(gitDir, "commondir"), "utf8").trim();
20465
+ common = (0, import_node_fs21.readFileSync)((0, import_node_path21.join)(gitDir, "commondir"), "utf8").trim();
20537
20466
  } catch (e) {
20538
20467
  if (e.code !== "ENOENT") {
20539
20468
  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)`);
@@ -20542,7 +20471,7 @@ function resolvePrimaryGitDir(cwd) {
20542
20471
  if (!common) return gitDir;
20543
20472
  const commonDir = (0, import_node_path21.isAbsolute)(common) ? common : (0, import_node_path21.resolve)(gitDir, common);
20544
20473
  try {
20545
- (0, import_node_fs22.readFileSync)((0, import_node_path21.join)(commonDir, "HEAD"), "utf8");
20474
+ (0, import_node_fs21.readFileSync)((0, import_node_path21.join)(commonDir, "HEAD"), "utf8");
20546
20475
  } catch (e) {
20547
20476
  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`);
20548
20477
  }
@@ -20552,18 +20481,18 @@ function releaseLedgerPath(cwd) {
20552
20481
  return (0, import_node_path21.join)(resolvePrimaryGitDir(cwd), "mmi-runtime", "release", "phases.json");
20553
20482
  }
20554
20483
  function atomicWriteJson(path2, ledger) {
20555
- (0, import_node_fs22.mkdirSync)((0, import_node_path21.dirname)(path2), { recursive: true });
20484
+ (0, import_node_fs21.mkdirSync)((0, import_node_path21.dirname)(path2), { recursive: true });
20556
20485
  const tmp = `${path2}.tmp-${process.pid}-${(0, import_node_crypto5.randomBytes)(4).toString("hex")}`;
20557
- (0, import_node_fs22.writeFileSync)(tmp, `${JSON.stringify(ledger, null, 2)}
20486
+ (0, import_node_fs21.writeFileSync)(tmp, `${JSON.stringify(ledger, null, 2)}
20558
20487
  `, "utf8");
20559
- (0, import_node_fs22.renameSync)(tmp, path2);
20488
+ (0, import_node_fs21.renameSync)(tmp, path2);
20560
20489
  }
20561
20490
  async function withReleaseLedger(path2, expected, fn, opts = {}) {
20562
20491
  return withFileLock(`${path2}.lock`, { label: "release ledger", maxWaitMs: opts.maxWaitMs ?? 5e3 }, async () => {
20563
20492
  let current;
20564
20493
  let raw;
20565
20494
  try {
20566
- raw = (0, import_node_fs22.readFileSync)(path2, "utf8");
20495
+ raw = (0, import_node_fs21.readFileSync)(path2, "utf8");
20567
20496
  } catch (e) {
20568
20497
  if (e.code !== "ENOENT") {
20569
20498
  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)`);
@@ -21197,7 +21126,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
21197
21126
  return withFileLock(`${path2}.lock`, { label: "release ledger", maxWaitMs }, async () => {
21198
21127
  let raw;
21199
21128
  try {
21200
- raw = (0, import_node_fs22.readFileSync)(path2, "utf8");
21129
+ raw = (0, import_node_fs21.readFileSync)(path2, "utf8");
21201
21130
  } catch (e) {
21202
21131
  if (e.code === "ENOENT") return { cleared: false };
21203
21132
  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` };
@@ -21213,7 +21142,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
21213
21142
  } catch (e) {
21214
21143
  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)})` };
21215
21144
  }
21216
- (0, import_node_fs22.unlinkSync)(path2);
21145
+ (0, import_node_fs21.unlinkSync)(path2);
21217
21146
  return { cleared: true, note: `cleared the release ledger at ${path2} for the live-proven aborted ${anchors.tag}` };
21218
21147
  });
21219
21148
  }
@@ -21316,7 +21245,7 @@ async function healStaleAlignmentLeg(deps, cwd, expected) {
21316
21245
  return withFileLock(`${path2}.lock`, { label: "release ledger" }, async () => {
21317
21246
  let prior;
21318
21247
  try {
21319
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
21248
+ prior = parseReleaseLedger((0, import_node_fs21.readFileSync)(path2, "utf8"));
21320
21249
  } catch {
21321
21250
  return void 0;
21322
21251
  }
@@ -21336,7 +21265,7 @@ async function healStaleAlignmentLeg(deps, cwd, expected) {
21336
21265
  async function reverifyPriorRunLegs(deps, path2, targetTag) {
21337
21266
  let prior;
21338
21267
  try {
21339
- prior = parseReleaseLedger((0, import_node_fs22.readFileSync)(path2, "utf8"));
21268
+ prior = parseReleaseLedger((0, import_node_fs21.readFileSync)(path2, "utf8"));
21340
21269
  } catch {
21341
21270
  return;
21342
21271
  }
@@ -21356,7 +21285,7 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
21356
21285
  return withFileLock(`${path2}.lock`, { label: "release ledger" }, async () => {
21357
21286
  let raw;
21358
21287
  try {
21359
- raw = (0, import_node_fs22.readFileSync)(path2, "utf8");
21288
+ raw = (0, import_node_fs21.readFileSync)(path2, "utf8");
21360
21289
  } catch (e) {
21361
21290
  if (e.code === "ENOENT") return { ok: true };
21362
21291
  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)` };
@@ -21395,13 +21324,13 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
21395
21324
  }
21396
21325
  const archivePath = (0, import_node_path21.join)((0, import_node_path21.dirname)(path2), `phases.archive-${prior.tag}.json`);
21397
21326
  try {
21398
- (0, import_node_fs22.unlinkSync)(archivePath);
21327
+ (0, import_node_fs21.unlinkSync)(archivePath);
21399
21328
  } catch (e) {
21400
21329
  if (e.code !== "ENOENT") {
21401
21330
  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)` };
21402
21331
  }
21403
21332
  }
21404
- (0, import_node_fs22.renameSync)(path2, archivePath);
21333
+ (0, import_node_fs21.renameSync)(path2, archivePath);
21405
21334
  return { ok: true, note: `archived the completed release ledger ${prior.tag} to ${archivePath} (live-proven at ${prior.tagSha.slice(0, 12)})` };
21406
21335
  });
21407
21336
  }
@@ -21498,10 +21427,10 @@ function readOriginWorkflowsDefault(root, ref) {
21498
21427
  }
21499
21428
  var NPM_REGISTRY = "https://registry.npmjs.org";
21500
21429
  async function probeRegistryWhoami(train) {
21501
- const dir = (0, import_node_fs23.mkdtempSync)((0, import_node_path22.join)((0, import_node_os13.tmpdir)(), "mmi-npmrc-"));
21430
+ const dir = (0, import_node_fs22.mkdtempSync)((0, import_node_path22.join)((0, import_node_os13.tmpdir)(), "mmi-npmrc-"));
21502
21431
  const rc = (0, import_node_path22.join)(dir, "npmrc");
21503
21432
  try {
21504
- (0, import_node_fs23.writeFileSync)(rc, "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n");
21433
+ (0, import_node_fs22.writeFileSync)(rc, "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n");
21505
21434
  await train.runSelf(["secrets", "use", "npm/NPM_TOKEN", "--slug", "_org", "--", "npm", "whoami", "--registry", NPM_REGISTRY, "--userconfig", rc]);
21506
21435
  return { kind: "ok", detail: "the registry answered a login" };
21507
21436
  } catch (e) {
@@ -21512,7 +21441,7 @@ async function probeRegistryWhoami(train) {
21512
21441
  if (/\bE401\b|401 Unauthorized/.test(stderr)) return { kind: "rejected", detail: "npm whoami answered 401 Unauthorized" };
21513
21442
  return { kind: "unverified", detail: first };
21514
21443
  } finally {
21515
- (0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
21444
+ (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
21516
21445
  }
21517
21446
  }
21518
21447
  var REGISTRY_TOKEN_ENV = /\b(NODE_AUTH_TOKEN|NPM_TOKEN)\b/;
@@ -21530,7 +21459,7 @@ var defaultDeps2 = {
21530
21459
  ledgerPath: releaseLedgerPath,
21531
21460
  readLedgerRaw: (path2) => {
21532
21461
  try {
21533
- return (0, import_node_fs23.readFileSync)(path2, "utf8");
21462
+ return (0, import_node_fs22.readFileSync)(path2, "utf8");
21534
21463
  } catch (e) {
21535
21464
  if (e.code === "ENOENT") return void 0;
21536
21465
  throw e;
@@ -21539,7 +21468,7 @@ var defaultDeps2 = {
21539
21468
  healAlignmentLeg: healStaleAlignmentLeg,
21540
21469
  readSurfacesRaw: (cwd) => {
21541
21470
  try {
21542
- return (0, import_node_fs23.readFileSync)((0, import_node_path22.join)(cwd, "surfaces.json"), "utf8");
21471
+ return (0, import_node_fs22.readFileSync)((0, import_node_path22.join)(cwd, "surfaces.json"), "utf8");
21543
21472
  } catch {
21544
21473
  return void 0;
21545
21474
  }
@@ -22029,14 +21958,14 @@ function readLocalGateWorkflows() {
22029
21958
  const dir = (0, import_node_path23.join)(".github", "workflows");
22030
21959
  let names;
22031
21960
  try {
22032
- names = (0, import_node_fs24.readdirSync)(dir);
21961
+ names = (0, import_node_fs23.readdirSync)(dir);
22033
21962
  } catch {
22034
21963
  return null;
22035
21964
  }
22036
21965
  const files = [];
22037
21966
  for (const name of names.filter(isGateWorkflowPath)) {
22038
21967
  try {
22039
- files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs24.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
21968
+ files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
22040
21969
  } catch {
22041
21970
  }
22042
21971
  }
@@ -22046,14 +21975,14 @@ function readLocalWorkflows() {
22046
21975
  const dir = (0, import_node_path23.join)(".github", "workflows");
22047
21976
  let names;
22048
21977
  try {
22049
- names = (0, import_node_fs24.readdirSync)(dir);
21978
+ names = (0, import_node_fs23.readdirSync)(dir);
22050
21979
  } catch {
22051
21980
  return null;
22052
21981
  }
22053
21982
  const files = [];
22054
21983
  for (const name of names.filter((n) => /\.ya?ml$/i.test(n))) {
22055
21984
  try {
22056
- files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs24.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
21985
+ files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
22057
21986
  } catch {
22058
21987
  }
22059
21988
  }
@@ -22823,7 +22752,7 @@ async function activeRcandLedgerCandidate(deps, cwd) {
22823
22752
  }
22824
22753
  let prior;
22825
22754
  try {
22826
- prior = parseReleaseLedger((0, import_node_fs24.readFileSync)(path2, "utf8"));
22755
+ prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
22827
22756
  } catch {
22828
22757
  return void 0;
22829
22758
  }
@@ -25874,22 +25803,6 @@ async function loadConfigForBoardSelector2(selector, repoOption) {
25874
25803
  return loadConfigForRepo(repoFromSelector(selector) ?? repoOption);
25875
25804
  }
25876
25805
 
25877
- // src/statusline-invalidate.ts
25878
- var import_node_child_process10 = require("node:child_process");
25879
- function invalidateStatuslineBoardCache() {
25880
- try {
25881
- const child2 = (0, import_node_child_process10.spawn)("jerv-cli", ["lane", "ops", "invalidate-board"], {
25882
- detached: true,
25883
- stdio: "ignore",
25884
- windowsHide: true
25885
- });
25886
- child2.on("error", () => {
25887
- });
25888
- child2.unref();
25889
- } catch {
25890
- }
25891
- }
25892
-
25893
25806
  // src/board-commands.ts
25894
25807
  function refuseRateLimited(e, json) {
25895
25808
  if (!isRateLimitedError(e)) return false;
@@ -25990,7 +25903,6 @@ function registerBoardCommands(program3) {
25990
25903
  check: o.check,
25991
25904
  allowPartial: o.allowPartial
25992
25905
  }, { snapshot: registryClientDeps(config) });
25993
- if (!result.checked) invalidateStatuslineBoardCache();
25994
25906
  if (o.json) return console.log(JSON.stringify(result));
25995
25907
  console.log(claimVerdict(result.item.ref, result));
25996
25908
  printClaimWarnings(result.warnings);
@@ -26012,7 +25924,6 @@ function registerBoardCommands(program3) {
26012
25924
  check: o.check,
26013
25925
  allowPartial: o.allowPartial
26014
25926
  }, { snapshot: registryClientDeps(config) });
26015
- if (bulk.results.some((r) => r.claimed && !r.checked)) invalidateStatuslineBoardCache();
26016
25927
  if (o.json) {
26017
25928
  console.log(JSON.stringify(bulk.results));
26018
25929
  printClaimWarnings(bulk.warnings, true);
@@ -26068,7 +25979,6 @@ function registerBoardCommands(program3) {
26068
25979
  repo: o.repo,
26069
25980
  allowPartial: o.allowPartial
26070
25981
  });
26071
- if (bulk.results.some((r) => r.moved)) invalidateStatuslineBoardCache();
26072
25982
  if (o.json) {
26073
25983
  console.log(JSON.stringify(bulk.results));
26074
25984
  } else {
@@ -26093,7 +26003,6 @@ function registerBoardCommands(program3) {
26093
26003
  if (issueRefs.length === 1) {
26094
26004
  try {
26095
26005
  const result = await moveBoardItem({ config: await loadConfigForBoardSelector2(issueRefs[0], o.repo), selector: issueRefs[0], status: canonicalStatus, repo: o.repo, allowPartial: o.allowPartial });
26096
- invalidateStatuslineBoardCache();
26097
26006
  if (o.json) return console.log(JSON.stringify(result));
26098
26007
  console.log(result.archived ? `Already terminal ${result.item.ref}: ${result.warning}` : result.partial ? `Partially moved ${result.item.ref}: ${result.warning}` : `Moved ${result.item.ref} -> ${result.status}`);
26099
26008
  } catch (e) {
@@ -26145,7 +26054,6 @@ function registerBoardCommands(program3) {
26145
26054
  force: o.force,
26146
26055
  allowPartial: o.allowPartial
26147
26056
  });
26148
- invalidateStatuslineBoardCache();
26149
26057
  if (o.json) return console.log(JSON.stringify(result));
26150
26058
  console.log(result.partial ? `Partially unclaimed ${result.item.ref}: ${result.warning}` : `Unclaimed ${result.item.ref} -> ${result.status}`);
26151
26059
  } catch (e) {
@@ -26159,7 +26067,6 @@ function registerBoardCommands(program3) {
26159
26067
  repo: o.repo,
26160
26068
  apply: o.apply
26161
26069
  });
26162
- if (result.archived.length) invalidateStatuslineBoardCache();
26163
26070
  if (o.json) return console.log(JSON.stringify(result));
26164
26071
  console.log(o.apply ? `board archive-done: archived ${result.archived.length}/${result.candidates.length}, failed ${result.failures.length}` : `board archive-done: would archive ${result.candidates.length} closed Done cards (scanned ${result.scanned}; pass --apply to write)`);
26165
26072
  if (result.failures.length) process.exitCode = 1;
@@ -26195,7 +26102,7 @@ function registerBoardCommands(program3) {
26195
26102
  }
26196
26103
 
26197
26104
  // src/bootstrap-commands.ts
26198
- var import_node_fs26 = require("node:fs");
26105
+ var import_node_fs25 = require("node:fs");
26199
26106
  var import_node_os14 = require("node:os");
26200
26107
  var import_node_path25 = require("node:path");
26201
26108
 
@@ -26362,7 +26269,7 @@ function renderSteps(title, steps) {
26362
26269
  }
26363
26270
 
26364
26271
  // src/port-registry.ts
26365
- var import_node_fs25 = require("node:fs");
26272
+ var import_node_fs24 = require("node:fs");
26366
26273
  var import_node_path24 = require("node:path");
26367
26274
 
26368
26275
  // ../infra/port-geometry.mjs
@@ -26377,8 +26284,8 @@ function nextPortBlock(registry2) {
26377
26284
  return [base, base + PORT_SPAN];
26378
26285
  }
26379
26286
  function loadPortRegistry(path2) {
26380
- if (!(0, import_node_fs25.existsSync)(path2)) return {};
26381
- const raw = JSON.parse((0, import_node_fs25.readFileSync)(path2, "utf8"));
26287
+ if (!(0, import_node_fs24.existsSync)(path2)) return {};
26288
+ const raw = JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8"));
26382
26289
  const out = {};
26383
26290
  for (const [key, value] of Object.entries(raw)) {
26384
26291
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -26392,9 +26299,9 @@ function ensurePortRange(repo, path2) {
26392
26299
  const existing = registry2[repo];
26393
26300
  if (existing) return existing;
26394
26301
  const range = nextPortBlock(registry2);
26395
- const raw = (0, import_node_fs25.existsSync)(path2) ? JSON.parse((0, import_node_fs25.readFileSync)(path2, "utf8")) : {};
26302
+ const raw = (0, import_node_fs24.existsSync)(path2) ? JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8")) : {};
26396
26303
  raw[repo] = range;
26397
- (0, import_node_fs25.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
26304
+ (0, import_node_fs24.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
26398
26305
  return range;
26399
26306
  }
26400
26307
  function portCursorSeed(registry2) {
@@ -26418,7 +26325,7 @@ function existingPortRange(repo, registry2) {
26418
26325
  function portRangeInfraAt(root, source) {
26419
26326
  const registryPath = (0, import_node_path24.join)(root, "infra", "port-ranges.json");
26420
26327
  const ddbScriptPath = (0, import_node_path24.join)(root, "infra", "port-ddb.mjs");
26421
- if (!(0, import_node_fs25.existsSync)(registryPath) || !(0, import_node_fs25.existsSync)(ddbScriptPath)) return null;
26328
+ if (!(0, import_node_fs24.existsSync)(registryPath) || !(0, import_node_fs24.existsSync)(ddbScriptPath)) return null;
26422
26329
  return { root, source, registryPath, ddbScriptPath };
26423
26330
  }
26424
26331
  function resolvePortRangeInfra(cwd, packageDir) {
@@ -27900,13 +27807,13 @@ function registerBootstrapCommands(program3) {
27900
27807
  deployFactsRead: deployFacts !== null,
27901
27808
  pushAllowlistOwners: verifyOwners,
27902
27809
  pushAllowlistOwnersRead: verifyOwnersRead,
27903
- readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs26.existsSync)(path2) ? (0, import_node_fs26.readFileSync)(path2, "utf8") : null,
27810
+ readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs25.existsSync)(path2) ? (0, import_node_fs25.readFileSync)(path2, "utf8") : null,
27904
27811
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
27905
27812
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
27906
27813
  // #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
27907
27814
  // permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
27908
27815
  // sanction, which is the pre-#3664 behaviour.
27909
- sanctionedAdmins: (0, import_node_fs26.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs26.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
27816
+ sanctionedAdmins: (0, import_node_fs25.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs25.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
27910
27817
  requiredGcpApis: (() => {
27911
27818
  const v = meta?.requiredGcpApis;
27912
27819
  if (Array.isArray(v)) return v;
@@ -27984,14 +27891,14 @@ function registerBootstrapCommands(program3) {
27984
27891
  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 () => {
27985
27892
  const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
27986
27893
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
27987
- if (!(0, import_node_fs26.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`);
27894
+ if (!(0, import_node_fs25.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`);
27988
27895
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
27989
27896
  if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
27990
- const manifest = loadBootstrapSeeds((0, import_node_fs26.readFileSync)(manifestPath, "utf8"));
27897
+ const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
27991
27898
  const hubContents = /* @__PURE__ */ new Map();
27992
27899
  for (const s of manifest.seeds) {
27993
27900
  if (s.ownership !== "org" || s.source !== "self") continue;
27994
- hubContents.set(s.target, (0, import_node_fs26.existsSync)(s.target) ? (0, import_node_fs26.readFileSync)(s.target, "utf8") : null);
27901
+ hubContents.set(s.target, (0, import_node_fs25.existsSync)(s.target) ? (0, import_node_fs25.readFileSync)(s.target, "utf8") : null);
27995
27902
  }
27996
27903
  let targets;
27997
27904
  let classOf = (_repo) => "deployable";
@@ -28154,10 +28061,10 @@ function registerBootstrapCommands(program3) {
28154
28061
  return;
28155
28062
  }
28156
28063
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
28157
- if (!(0, import_node_fs26.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`);
28064
+ if (!(0, import_node_fs25.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`);
28158
28065
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
28159
28066
  if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
28160
- const manifest = loadBootstrapSeeds((0, import_node_fs26.readFileSync)(manifestPath, "utf8"));
28067
+ const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
28161
28068
  const baseBranch = o.class === "content" ? "main" : "development";
28162
28069
  const slug = parsedRepo.slug;
28163
28070
  const onlyTarget = o.only.trim();
@@ -28169,16 +28076,16 @@ function registerBootstrapCommands(program3) {
28169
28076
  }
28170
28077
  const onlyManagedBlock = onlyTarget ? seedsToApply[0]?.managedBlock != null : false;
28171
28078
  const gh = async (args) => execFileP("gh", args, { timeout: 2e4 });
28172
- const readFile9 = (p) => (0, import_node_fs26.existsSync)(p) ? (0, import_node_fs26.readFileSync)(p, "utf8") : null;
28079
+ const readFile9 = (p) => (0, import_node_fs25.existsSync)(p) ? (0, import_node_fs25.readFileSync)(p, "utf8") : null;
28173
28080
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
28174
28081
  const putSeed = async (target, content, ref, sha) => {
28175
28082
  const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
28176
- (0, import_node_fs26.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
28083
+ (0, import_node_fs25.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
28177
28084
  try {
28178
28085
  await gh(contentPutInputArgs(repo, target, tmp));
28179
28086
  } finally {
28180
28087
  try {
28181
- (0, import_node_fs26.unlinkSync)(tmp);
28088
+ (0, import_node_fs25.unlinkSync)(tmp);
28182
28089
  } catch {
28183
28090
  }
28184
28091
  }
@@ -28627,10 +28534,10 @@ LIVE apply to ${repo}:
28627
28534
  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 () => {
28628
28535
  const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
28629
28536
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
28630
- if (!(0, import_node_fs26.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`);
28537
+ if (!(0, import_node_fs25.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`);
28631
28538
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
28632
28539
  if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
28633
- const manifest = loadBootstrapSeeds((0, import_node_fs26.readFileSync)(manifestPath, "utf8"));
28540
+ const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
28634
28541
  const propagatable = manifest.seeds.filter(isPropagatableSeed);
28635
28542
  if (!o.target) {
28636
28543
  return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
@@ -28639,9 +28546,9 @@ LIVE apply to ${repo}:
28639
28546
  const seed = propagatable.find((s) => s.target === o.target);
28640
28547
  if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no centrally propagatable seed in ${manifestPath}. Propagatable targets:
28641
28548
  ${propagatable.map((s) => s.target).join("\n ")}`);
28642
- if (!seed.managedBlock && !(0, import_node_fs26.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
28643
- const hubContent = seed.managedBlock ? null : (0, import_node_fs26.readFileSync)(seed.target, "utf8");
28644
- const readSeedFile2 = (path2) => (0, import_node_fs26.existsSync)(path2) ? (0, import_node_fs26.readFileSync)(path2, "utf8") : null;
28549
+ if (!seed.managedBlock && !(0, import_node_fs25.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
28550
+ const hubContent = seed.managedBlock ? null : (0, import_node_fs25.readFileSync)(seed.target, "utf8");
28551
+ const readSeedFile2 = (path2) => (0, import_node_fs25.existsSync)(path2) ? (0, import_node_fs25.readFileSync)(path2, "utf8") : null;
28645
28552
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
28646
28553
  const cfg = await loadConfig();
28647
28554
  const projects = await fetchProjectsList(registryClientDeps(cfg));
@@ -28650,9 +28557,9 @@ LIVE apply to ${repo}:
28650
28557
  }
28651
28558
  const rosterRepos = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
28652
28559
  let independentCount = rosterRepos.length;
28653
- if ((0, import_node_fs26.existsSync)("projects.json")) {
28560
+ if ((0, import_node_fs25.existsSync)("projects.json")) {
28654
28561
  try {
28655
- const local = JSON.parse((0, import_node_fs26.readFileSync)("projects.json", "utf8"));
28562
+ const local = JSON.parse((0, import_node_fs25.readFileSync)("projects.json", "utf8"));
28656
28563
  const localRepos = /* @__PURE__ */ new Set();
28657
28564
  for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
28658
28565
  const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
@@ -28816,12 +28723,12 @@ LIVE apply to ${repo}:
28816
28723
  const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
28817
28724
  const desiredContent = desiredByRepo.get(rec.repo);
28818
28725
  if (desiredContent == null) return fail(`bootstrap propagate: no resolved content for ${rec.repo} ${seed.target} \u2014 refusing to write`);
28819
- (0, import_node_fs26.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha)), "utf8");
28726
+ (0, import_node_fs25.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha)), "utf8");
28820
28727
  try {
28821
28728
  await gh(contentPutInputArgs(rec.repo, seed.target, tmp));
28822
28729
  } finally {
28823
28730
  try {
28824
- (0, import_node_fs26.unlinkSync)(tmp);
28731
+ (0, import_node_fs25.unlinkSync)(tmp);
28825
28732
  } catch {
28826
28733
  }
28827
28734
  }
@@ -28888,10 +28795,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
28888
28795
  return fail(`bootstrap rollback: ${e.message}`);
28889
28796
  }
28890
28797
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
28891
- if (!(0, import_node_fs26.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)`);
28798
+ if (!(0, import_node_fs25.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)`);
28892
28799
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
28893
28800
  if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
28894
- const manifest = loadBootstrapSeeds((0, import_node_fs26.readFileSync)(manifestPath, "utf8"));
28801
+ const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
28895
28802
  const propagatable = manifest.seeds.filter(isPropagatableSeed);
28896
28803
  if (!o.target) {
28897
28804
  return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
@@ -28908,10 +28815,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
28908
28815
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
28909
28816
  let candidates;
28910
28817
  if (o.record) {
28911
- if (!(0, import_node_fs26.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
28818
+ if (!(0, import_node_fs25.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
28912
28819
  let parsed;
28913
28820
  try {
28914
- parsed = JSON.parse((0, import_node_fs26.readFileSync)(o.record, "utf8"));
28821
+ parsed = JSON.parse((0, import_node_fs25.readFileSync)(o.record, "utf8"));
28915
28822
  } catch (e) {
28916
28823
  return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
28917
28824
  }
@@ -28989,12 +28896,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
28989
28896
  existingSha = void 0;
28990
28897
  }
28991
28898
  const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
28992
- (0, import_node_fs26.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
28899
+ (0, import_node_fs25.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
28993
28900
  try {
28994
28901
  await gh(contentPutInputArgs(repo, seed.target, tmp));
28995
28902
  } finally {
28996
28903
  try {
28997
- (0, import_node_fs26.unlinkSync)(tmp);
28904
+ (0, import_node_fs25.unlinkSync)(tmp);
28998
28905
  } catch {
28999
28906
  }
29000
28907
  }
@@ -30008,7 +29915,7 @@ function renderDeployPortDoctor(report) {
30008
29915
  }
30009
29916
 
30010
29917
  // src/wave-status.ts
30011
- var import_node_fs29 = require("node:fs");
29918
+ var import_node_fs28 = require("node:fs");
30012
29919
 
30013
29920
  // src/git-worktree-observation.ts
30014
29921
  function parseGitWorktreePorcelain(text) {
@@ -30038,8 +29945,8 @@ function deriveComposeProjectName(worktreePath) {
30038
29945
  }
30039
29946
 
30040
29947
  // src/stage-runner.ts
30041
- var import_node_child_process11 = require("node:child_process");
30042
- var import_node_fs28 = require("node:fs");
29948
+ var import_node_child_process10 = require("node:child_process");
29949
+ var import_node_fs27 = require("node:fs");
30043
29950
  var import_node_path27 = require("node:path");
30044
29951
  var import_node_net = require("node:net");
30045
29952
  var import_node_util5 = require("node:util");
@@ -30050,7 +29957,7 @@ function normalizeEol2(s) {
30050
29957
  }
30051
29958
 
30052
29959
  // src/env-detection.ts
30053
- var import_node_fs27 = require("node:fs");
29960
+ var import_node_fs26 = require("node:fs");
30054
29961
  var import_node_path26 = require("node:path");
30055
29962
  var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
30056
29963
  function isEnvBaseName(name) {
@@ -30061,7 +29968,7 @@ function findEnvFiles(root) {
30061
29968
  const walk2 = (dir, rel) => {
30062
29969
  let entries;
30063
29970
  try {
30064
- entries = (0, import_node_fs27.readdirSync)(dir, { withFileTypes: true });
29971
+ entries = (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true });
30065
29972
  } catch {
30066
29973
  return;
30067
29974
  }
@@ -30075,7 +29982,7 @@ function findEnvFiles(root) {
30075
29982
  if (isEnvBaseName(entry.name)) {
30076
29983
  let isDir = false;
30077
29984
  try {
30078
- isDir = (0, import_node_fs27.lstatSync)((0, import_node_path26.join)(dir, entry.name)).isDirectory();
29985
+ isDir = (0, import_node_fs26.lstatSync)((0, import_node_path26.join)(dir, entry.name)).isDirectory();
30079
29986
  } catch {
30080
29987
  }
30081
29988
  if (!isDir) found.push(relPath);
@@ -30132,17 +30039,17 @@ function stageComposeFileEnv(files) {
30132
30039
  }
30133
30040
 
30134
30041
  // src/stage-runner.ts
30135
- var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process11.execFile);
30042
+ var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process10.execFile);
30136
30043
  var DOCKER_TIMEOUT_MS = 15e3;
30137
30044
  function stageBash() {
30138
30045
  if (process.platform !== "win32") return "bash";
30139
30046
  const configured = process.env.SHELL;
30140
- if (configured && (0, import_node_path27.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs28.existsSync)(configured)) return configured;
30047
+ if (configured && (0, import_node_path27.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs27.existsSync)(configured)) return configured;
30141
30048
  const candidates = [
30142
30049
  (0, import_node_path27.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
30143
30050
  ...process.env.LOCALAPPDATA ? [(0, import_node_path27.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
30144
30051
  ];
30145
- const bash = candidates.find((path2) => (0, import_node_fs28.existsSync)(path2));
30052
+ const bash = candidates.find((path2) => (0, import_node_fs27.existsSync)(path2));
30146
30053
  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.");
30147
30054
  return bash;
30148
30055
  }
@@ -30491,7 +30398,7 @@ function stageProcessEnv(stagePort, extraEnv) {
30491
30398
  function composeResolvesPort(cwd) {
30492
30399
  if (process.env.PORT) return true;
30493
30400
  const envFile = (0, import_node_path27.join)(cwd, ".env");
30494
- return (0, import_node_fs28.existsSync)(envFile) && envFileKeys((0, import_node_fs28.readFileSync)(envFile, "utf8")).has("PORT");
30401
+ return (0, import_node_fs27.existsSync)(envFile) && envFileKeys((0, import_node_fs27.readFileSync)(envFile, "utf8")).has("PORT");
30495
30402
  }
30496
30403
  function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
30497
30404
  return {
@@ -30504,13 +30411,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
30504
30411
  function stageComposeFiles(cwd) {
30505
30412
  const files = ["docker-compose.yml"];
30506
30413
  for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
30507
- if ((0, import_node_fs28.existsSync)((0, import_node_path27.join)(cwd, conventional))) files.push(conventional);
30414
+ if ((0, import_node_fs27.existsSync)((0, import_node_path27.join)(cwd, conventional))) files.push(conventional);
30508
30415
  }
30509
30416
  return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
30510
30417
  }
30511
30418
  async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
30512
30419
  const keys = Object.keys(vaultEnvMerge ?? {});
30513
- if (!keys.length || !(0, import_node_fs28.existsSync)((0, import_node_path27.join)(cwd, "docker-compose.yml"))) return {};
30420
+ if (!keys.length || !(0, import_node_fs27.existsSync)((0, import_node_path27.join)(cwd, "docker-compose.yml"))) return {};
30514
30421
  let configJson;
30515
30422
  try {
30516
30423
  const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
@@ -30527,20 +30434,20 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
30527
30434
  const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys);
30528
30435
  if (!body) return {};
30529
30436
  const overridePath = (0, import_node_path27.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
30530
- (0, import_node_fs28.mkdirSync)((0, import_node_path27.join)(cwd, "tmp", "stage"), { recursive: true });
30531
- (0, import_node_fs28.writeFileSync)(overridePath, body, "utf8");
30437
+ (0, import_node_fs27.mkdirSync)((0, import_node_path27.join)(cwd, "tmp", "stage"), { recursive: true });
30438
+ (0, import_node_fs27.writeFileSync)(overridePath, body, "utf8");
30532
30439
  return stageComposeFileEnv(stageComposeFiles(cwd));
30533
30440
  }
30534
30441
  async function ensureStageRuntimeEnv(config, opts, cwd) {
30535
30442
  if (!config.ensureEnv) return;
30536
30443
  const target = (0, import_node_path27.join)(cwd, config.ensureEnv.target);
30537
30444
  const example = (0, import_node_path27.join)(cwd, config.ensureEnv.example);
30538
- if (!(0, import_node_fs28.existsSync)(target) && (0, import_node_fs28.existsSync)(example)) {
30539
- (0, import_node_fs28.copyFileSync)(example, target);
30540
- } else if ((0, import_node_fs28.existsSync)(target) && (0, import_node_fs28.existsSync)(example)) {
30541
- const stale = detectStaleEnvFile((0, import_node_fs28.readFileSync)(example, "utf8"), (0, import_node_fs28.readFileSync)(target, "utf8"), {
30542
- exampleMtimeMs: (0, import_node_fs28.statSync)(example).mtimeMs,
30543
- targetMtimeMs: (0, import_node_fs28.statSync)(target).mtimeMs
30445
+ if (!(0, import_node_fs27.existsSync)(target) && (0, import_node_fs27.existsSync)(example)) {
30446
+ (0, import_node_fs27.copyFileSync)(example, target);
30447
+ } else if ((0, import_node_fs27.existsSync)(target) && (0, import_node_fs27.existsSync)(example)) {
30448
+ const stale = detectStaleEnvFile((0, import_node_fs27.readFileSync)(example, "utf8"), (0, import_node_fs27.readFileSync)(target, "utf8"), {
30449
+ exampleMtimeMs: (0, import_node_fs27.statSync)(example).mtimeMs,
30450
+ targetMtimeMs: (0, import_node_fs27.statSync)(target).mtimeMs
30544
30451
  });
30545
30452
  if (stale) {
30546
30453
  const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running /stage`;
@@ -30548,8 +30455,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
30548
30455
  console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
30549
30456
  }
30550
30457
  }
30551
- if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs28.existsSync)(target)) {
30552
- (0, import_node_fs28.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs28.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
30458
+ if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs27.existsSync)(target)) {
30459
+ (0, import_node_fs27.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs27.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
30553
30460
  }
30554
30461
  }
30555
30462
  async function gitText(cwd, args) {
@@ -30579,20 +30486,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
30579
30486
  return void 0;
30580
30487
  }
30581
30488
  function readState(path2) {
30582
- if (!(0, import_node_fs28.existsSync)(path2)) return null;
30489
+ if (!(0, import_node_fs27.existsSync)(path2)) return null;
30583
30490
  try {
30584
- return JSON.parse((0, import_node_fs28.readFileSync)(path2, "utf8"));
30491
+ return JSON.parse((0, import_node_fs27.readFileSync)(path2, "utf8"));
30585
30492
  } catch {
30586
30493
  return null;
30587
30494
  }
30588
30495
  }
30589
30496
  function mkdirFor(path2) {
30590
30497
  const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
30591
- (0, import_node_fs28.mkdirSync)(dir, { recursive: true });
30498
+ (0, import_node_fs27.mkdirSync)(dir, { recursive: true });
30592
30499
  }
30593
30500
  function writeState(path2, state) {
30594
30501
  mkdirFor(path2);
30595
- (0, import_node_fs28.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
30502
+ (0, import_node_fs27.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
30596
30503
  }
30597
30504
  function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
30598
30505
  const reservation = {
@@ -30621,7 +30528,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd, currentEn
30621
30528
  );
30622
30529
  }
30623
30530
  for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
30624
- (0, import_node_fs28.rmSync)(path2, { force: true });
30531
+ (0, import_node_fs27.rmSync)(path2, { force: true });
30625
30532
  }
30626
30533
  }
30627
30534
  async function killTree(pid) {
@@ -30715,7 +30622,7 @@ async function startStage(config = {}, opts = {}) {
30715
30622
  let up = sub(config.up.trim());
30716
30623
  if (opts.forceRecreate) up = appendForceRecreate(up);
30717
30624
  const identity = await resolveStageIdentity(cwd);
30718
- const child2 = (0, import_node_child_process11.spawn)(bash, ["-c", up], {
30625
+ const child2 = (0, import_node_child_process10.spawn)(bash, ["-c", up], {
30719
30626
  cwd,
30720
30627
  // POSIX-only: the process group exists for the group-kill in stopStage. On win32 teardown is
30721
30628
  // `taskkill /T /F` (no group needed), and detached+shell defeats windowsHide — every spawn would
@@ -30808,8 +30715,8 @@ async function runStage(config = {}, opts = {}) {
30808
30715
  });
30809
30716
  }
30810
30717
  } catch (e) {
30811
- (0, import_node_fs28.rmSync)(statePath, { force: true });
30812
- if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs28.rmSync)(globalStatePath, { force: true });
30718
+ (0, import_node_fs27.rmSync)(statePath, { force: true });
30719
+ if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs27.rmSync)(globalStatePath, { force: true });
30813
30720
  throw e;
30814
30721
  }
30815
30722
  const started = await startStage(config, {
@@ -30826,9 +30733,9 @@ async function runStage(config = {}, opts = {}) {
30826
30733
  // src/wave-status.ts
30827
30734
  function readStageSummary(worktreePath) {
30828
30735
  const statePath = stageStatePath(worktreePath);
30829
- if (!(0, import_node_fs29.existsSync)(statePath)) return void 0;
30736
+ if (!(0, import_node_fs28.existsSync)(statePath)) return void 0;
30830
30737
  try {
30831
- const state = JSON.parse((0, import_node_fs29.readFileSync)(statePath, "utf8"));
30738
+ const state = JSON.parse((0, import_node_fs28.readFileSync)(statePath, "utf8"));
30832
30739
  const port = typeof state.port === "number" ? state.port : void 0;
30833
30740
  if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
30834
30741
  return { port, url: typeof state.url === "string" ? state.url : void 0 };
@@ -30883,7 +30790,7 @@ async function collectWaveStatus(deps) {
30883
30790
  }
30884
30791
 
30885
30792
  // src/discovery-commands.ts
30886
- var import_node_fs30 = require("node:fs");
30793
+ var import_node_fs29 = require("node:fs");
30887
30794
  var import_node_os15 = require("node:os");
30888
30795
  var import_node_path28 = require("node:path");
30889
30796
  var GC_GH_TIMEOUT_MS = 2e4;
@@ -31075,8 +30982,8 @@ async function collectOnboardStatus(opts = {}) {
31075
30982
  }
31076
30983
  const home = (0, import_node_os15.homedir)();
31077
30984
  const plugin = onboardPluginGate({
31078
- readKnown: () => readFileSyncSafe((0, import_node_path28.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs30.readFileSync),
31079
- readSettings: () => readFileSyncSafe((0, import_node_path28.join)(home, ".claude", "settings.json"), import_node_fs30.readFileSync)
30985
+ readKnown: () => readFileSyncSafe((0, import_node_path28.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs29.readFileSync),
30986
+ readSettings: () => readFileSyncSafe((0, import_node_path28.join)(home, ".claude", "settings.json"), import_node_fs29.readFileSync)
31080
30987
  });
31081
30988
  return {
31082
30989
  guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
@@ -33029,7 +32936,7 @@ function parseOriginRepo(remoteUrl) {
33029
32936
  }
33030
32937
 
33031
32938
  // src/issue-commands.ts
33032
- var import_node_fs31 = require("node:fs");
32939
+ var import_node_fs30 = require("node:fs");
33033
32940
  var import_node_crypto10 = require("node:crypto");
33034
32941
 
33035
32942
  // src/issue-body.ts
@@ -33279,7 +33186,7 @@ async function editIssue(client, options, deps = {}) {
33279
33186
  const url = `https://github.com/${repo}/issues/${parsed.number}`;
33280
33187
  const patch = {};
33281
33188
  let bodyChanged = false;
33282
- const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs31.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
33189
+ const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs30.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
33283
33190
  if (options.titleFile !== void 0) {
33284
33191
  patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
33285
33192
  } else if (options.title !== void 0) {
@@ -33935,7 +33842,7 @@ function extendCreateCommand(issue, batchAttach) {
33935
33842
  if (opts.batch) {
33936
33843
  let specs;
33937
33844
  try {
33938
- const raw = (0, import_node_fs31.readFileSync)(opts.batch, "utf8");
33845
+ const raw = (0, import_node_fs30.readFileSync)(opts.batch, "utf8");
33939
33846
  specs = JSON.parse(raw);
33940
33847
  if (!Array.isArray(specs)) {
33941
33848
  const top = specs === null ? "null" : typeof specs === "object" ? `an object with keys: ${Object.keys(specs).join(", ") || "(none)"}` : `a ${typeof specs}`;
@@ -33987,7 +33894,6 @@ ${lines2}`, {
33987
33894
  surface: batchSurface,
33988
33895
  noSurface: batchNoSurface
33989
33896
  }, { attach: batchAttach });
33990
- if (result.created.some((row) => !row.idempotent)) invalidateStatuslineBoardCache();
33991
33897
  console.log(JSON.stringify(result));
33992
33898
  if (result.failures.length) process.exitCode = 1;
33993
33899
  } catch (e) {
@@ -35095,7 +35001,7 @@ function registerPrLifecycleCommands(program3) {
35095
35001
  }
35096
35002
 
35097
35003
  // src/project-info-sync.ts
35098
- var import_node_fs32 = require("node:fs");
35004
+ var import_node_fs31 = require("node:fs");
35099
35005
  var import_node_path29 = require("node:path");
35100
35006
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
35101
35007
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
@@ -35144,13 +35050,13 @@ function sharedName(entries, fallback) {
35144
35050
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
35145
35051
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
35146
35052
  const readmePath = (0, import_node_path29.join)(repoRoot2, "README.md");
35147
- if (!(0, import_node_fs32.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
35053
+ if (!(0, import_node_fs31.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
35148
35054
  const entries = entriesFor(project2, projects);
35149
35055
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
35150
35056
  const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
35151
35057
  if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
35152
35058
  const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
35153
- const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs32.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
35059
+ const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs31.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
35154
35060
  const lines2 = [
35155
35061
  `# ${projectName}`,
35156
35062
  "",
@@ -35169,8 +35075,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
35169
35075
  const targetBase = `https://github.com/${targetRepo2}`;
35170
35076
  const targetBranch = branchFor(targetRepo2, projects);
35171
35077
  const orgDocs = [
35172
- (0, import_node_fs32.existsSync)((0, import_node_path29.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
35173
- (0, import_node_fs32.existsSync)((0, import_node_path29.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
35078
+ (0, import_node_fs31.existsSync)((0, import_node_path29.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
35079
+ (0, import_node_fs31.existsSync)((0, import_node_path29.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
35174
35080
  ].filter(Boolean);
35175
35081
  if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
35176
35082
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
@@ -35271,9 +35177,9 @@ function writeError(res) {
35271
35177
 
35272
35178
  // src/schedules-commands.ts
35273
35179
  var import_promises5 = require("node:fs/promises");
35274
- var import_node_child_process12 = require("node:child_process");
35180
+ var import_node_child_process11 = require("node:child_process");
35275
35181
  var import_node_util6 = require("node:util");
35276
- var execFileP4 = (0, import_node_util6.promisify)(import_node_child_process12.execFile);
35182
+ var execFileP4 = (0, import_node_util6.promisify)(import_node_child_process11.execFile);
35277
35183
  var AWS_REGION = "eu-central-1";
35278
35184
  var AWS_TIMEOUT_MS = 3e4;
35279
35185
  var AWS_RETRY_DELAY_MS = 1500;
@@ -35588,7 +35494,7 @@ function registerSchedulesCommands(program3) {
35588
35494
  }
35589
35495
 
35590
35496
  // src/secrets-commands.ts
35591
- var import_node_fs33 = require("node:fs");
35497
+ var import_node_fs32 = require("node:fs");
35592
35498
  var import_node_path30 = require("node:path");
35593
35499
  var import_node_os17 = require("node:os");
35594
35500
 
@@ -35702,8 +35608,8 @@ async function decryptRailsCredentials(input) {
35702
35608
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
35703
35609
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
35704
35610
  };
35705
- if ((0, import_node_fs33.existsSync)(masterKeyPath)) {
35706
- env.RAILS_MASTER_KEY = (0, import_node_fs33.readFileSync)(masterKeyPath, "utf8").trim();
35611
+ if ((0, import_node_fs32.existsSync)(masterKeyPath)) {
35612
+ env.RAILS_MASTER_KEY = (0, import_node_fs32.readFileSync)(masterKeyPath, "utf8").trim();
35707
35613
  }
35708
35614
  const script = [
35709
35615
  'require "json"',
@@ -35713,9 +35619,9 @@ async function decryptRailsCredentials(input) {
35713
35619
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
35714
35620
  "puts JSON.generate(config.config)"
35715
35621
  ].join("\n");
35716
- const scriptDir = (0, import_node_fs33.mkdtempSync)((0, import_node_path30.join)((0, import_node_os17.tmpdir)(), "mmi-rails-decrypt-"));
35622
+ const scriptDir = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os17.tmpdir)(), "mmi-rails-decrypt-"));
35717
35623
  const scriptPath = (0, import_node_path30.join)(scriptDir, "decrypt.rb");
35718
- (0, import_node_fs33.writeFileSync)(scriptPath, script, "utf8");
35624
+ (0, import_node_fs32.writeFileSync)(scriptPath, script, "utf8");
35719
35625
  try {
35720
35626
  const args = ["exec", "ruby", scriptPath];
35721
35627
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -35727,7 +35633,7 @@ async function decryptRailsCredentials(input) {
35727
35633
  });
35728
35634
  return JSON.parse(stdout);
35729
35635
  } finally {
35730
- (0, import_node_fs33.rmSync)(scriptDir, { recursive: true, force: true });
35636
+ (0, import_node_fs32.rmSync)(scriptDir, { recursive: true, force: true });
35731
35637
  }
35732
35638
  }
35733
35639
  async function readSecretStdin() {
@@ -35817,7 +35723,7 @@ function registerSecretsCommands(program3) {
35817
35723
  let body;
35818
35724
  if (o.file) {
35819
35725
  try {
35820
- body = (0, import_node_fs33.readFileSync)((0, import_node_path30.resolve)(o.file), "utf8");
35726
+ body = (0, import_node_fs32.readFileSync)((0, import_node_path30.resolve)(o.file), "utf8");
35821
35727
  } catch (e) {
35822
35728
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
35823
35729
  }
@@ -35925,7 +35831,7 @@ function registerSecretsCommands(program3) {
35925
35831
  {
35926
35832
  ...d,
35927
35833
  decryptRailsCredentials,
35928
- removeFile: (path2) => (0, import_node_fs33.unlinkSync)((0, import_node_path30.resolve)(o.appDir ?? process.cwd(), path2))
35834
+ removeFile: (path2) => (0, import_node_fs32.unlinkSync)((0, import_node_path30.resolve)(o.appDir ?? process.cwd(), path2))
35929
35835
  },
35930
35836
  {
35931
35837
  repo: o.repo,
@@ -36087,7 +35993,7 @@ function registerSessionReport(program3) {
36087
35993
  }
36088
35994
 
36089
35995
  // src/stage-commands.ts
36090
- var import_node_fs34 = require("node:fs");
35996
+ var import_node_fs33 = require("node:fs");
36091
35997
  var import_node_path31 = require("node:path");
36092
35998
 
36093
35999
  // src/stage-default.ts
@@ -36372,8 +36278,8 @@ function registerStageCommands(program3) {
36372
36278
  return {
36373
36279
  resolution: decideStage({
36374
36280
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
36375
- hasCompose: (0, import_node_fs34.existsSync)((0, import_node_path31.join)(process.cwd(), "docker-compose.yml")),
36376
- hasEnvExample: (0, import_node_fs34.existsSync)((0, import_node_path31.join)(process.cwd(), ".env.example")),
36281
+ hasCompose: (0, import_node_fs33.existsSync)((0, import_node_path31.join)(process.cwd(), "docker-compose.yml")),
36282
+ hasEnvExample: (0, import_node_fs33.existsSync)((0, import_node_path31.join)(process.cwd(), ".env.example")),
36377
36283
  repo
36378
36284
  }),
36379
36285
  project: project2,
@@ -36634,14 +36540,14 @@ function registerStageCommands(program3) {
36634
36540
 
36635
36541
  // src/tenant-artifact.ts
36636
36542
  var import_node_crypto11 = require("node:crypto");
36637
- var import_node_fs35 = require("node:fs");
36543
+ var import_node_fs34 = require("node:fs");
36638
36544
  var import_promises6 = require("node:fs/promises");
36639
36545
  var import_node_path32 = require("node:path");
36640
36546
  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}$/;
36641
36547
  var MAX_BYTES = 5 * 1024 * 1024 * 1024;
36642
36548
  async function sha256File(path2) {
36643
36549
  const hash = (0, import_node_crypto11.createHash)("sha256");
36644
- for await (const chunk of (0, import_node_fs35.createReadStream)(path2)) hash.update(chunk);
36550
+ for await (const chunk of (0, import_node_fs34.createReadStream)(path2)) hash.update(chunk);
36645
36551
  return hash.digest("hex");
36646
36552
  }
36647
36553
  async function putTenantArtifact(repo, stage, inputPath, deps) {
@@ -36664,7 +36570,7 @@ async function putTenantArtifact(repo, stage, inputPath, deps) {
36664
36570
  return [key, value];
36665
36571
  }));
36666
36572
  headers["content-length"] = String(info.size);
36667
- const stream = (0, import_node_fs35.createReadStream)(path2);
36573
+ const stream = (0, import_node_fs34.createReadStream)(path2);
36668
36574
  let uploaded;
36669
36575
  try {
36670
36576
  uploaded = await fetch(body.uploadUrl, {
@@ -36803,8 +36709,8 @@ function renderVerifySecrets(body) {
36803
36709
  }
36804
36710
 
36805
36711
  // src/command-register-collaboration.ts
36806
- var import_node_child_process17 = require("node:child_process");
36807
- var import_node_fs43 = require("node:fs");
36712
+ var import_node_child_process16 = require("node:child_process");
36713
+ var import_node_fs41 = require("node:fs");
36808
36714
  var import_promises7 = require("node:fs/promises");
36809
36715
 
36810
36716
  // src/session-runtime.ts
@@ -36824,7 +36730,7 @@ function spawnDetachedSelf(args, deps, opts = {}) {
36824
36730
  }
36825
36731
 
36826
36732
  // src/command-register-collaboration.ts
36827
- var import_node_path40 = require("node:path");
36733
+ var import_node_path39 = require("node:path");
36828
36734
 
36829
36735
  // src/attach-to-project.ts
36830
36736
  function boardAttachRateLimitedReceipt(resetEpochSeconds) {
@@ -37070,7 +36976,7 @@ async function runPrLand(prNumber, options, deps) {
37070
36976
  }
37071
36977
 
37072
36978
  // src/merge-cleanup.ts
37073
- var import_node_fs37 = require("node:fs");
36979
+ var import_node_fs36 = require("node:fs");
37074
36980
  var import_node_path34 = require("node:path");
37075
36981
  var import_node_os18 = require("node:os");
37076
36982
 
@@ -37177,12 +37083,12 @@ function boardAdvanceFailureMessage(result) {
37177
37083
  }
37178
37084
 
37179
37085
  // src/test-policy-core.ts
37180
- var import_node_child_process14 = require("node:child_process");
37181
- var import_node_fs36 = require("node:fs");
37086
+ var import_node_child_process13 = require("node:child_process");
37087
+ var import_node_fs35 = require("node:fs");
37182
37088
  var import_node_path33 = require("node:path");
37183
37089
 
37184
37090
  // src/test-command-policy-shared.mjs
37185
- var import_node_child_process13 = require("node:child_process");
37091
+ var import_node_child_process12 = require("node:child_process");
37186
37092
  var TEST_COMMAND_CLASS = "test";
37187
37093
  var TRAILER_KEY = "Test-Policy-Override";
37188
37094
  var OVERRIDE_RE = /^Test-Policy-Override:\s*(.+)$/im;
@@ -37299,7 +37205,7 @@ function evaluateTestCommandPolicy({ paths, mandatory, regulated = true, overrid
37299
37205
  };
37300
37206
  }
37301
37207
  function git(args, cwd) {
37302
- return (0, import_node_child_process13.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37208
+ return (0, import_node_child_process12.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37303
37209
  }
37304
37210
  function parseScope(value) {
37305
37211
  const scoped = /^\[([^\]]*)\]\s*([\s\S]*)$/.exec(value);
@@ -37732,7 +37638,7 @@ function loadPolicySource(root, explicitRef, diffBase) {
37732
37638
  }
37733
37639
  function readFileOrNull2(path2) {
37734
37640
  try {
37735
- return (0, import_node_fs36.readFileSync)(path2, "utf8");
37641
+ return (0, import_node_fs35.readFileSync)(path2, "utf8");
37736
37642
  } catch {
37737
37643
  return null;
37738
37644
  }
@@ -37760,10 +37666,10 @@ function classify(changed, policy, present = () => false) {
37760
37666
  const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
37761
37667
  return { mandatoryHits, untestedHits, testChanges, meaningfulTestChanges, addedTests, removedProtected };
37762
37668
  }
37763
- function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs36.existsSync)(path2)) {
37669
+ function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs35.existsSync)(path2)) {
37764
37670
  return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path33.join)(root, p)));
37765
37671
  }
37766
- function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs36.existsSync)(path2)) {
37672
+ function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs35.existsSync)(path2)) {
37767
37673
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
37768
37674
  return [...new Set(declared)].filter((p) => !exists((0, import_node_path33.join)(root, p)));
37769
37675
  }
@@ -37798,14 +37704,14 @@ function evaluate(changed, policy, present = () => false) {
37798
37704
  return findings;
37799
37705
  }
37800
37706
  function git2(args, cwd) {
37801
- return (0, import_node_child_process14.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37707
+ return (0, import_node_child_process13.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37802
37708
  }
37803
37709
  var COAUTHOR_KEY = "Co-authored-by";
37804
37710
  var GH_MESSAGE_SEPARATOR = /^-{5,}$/;
37805
37711
  var LIFTED_KEYS = new RegExp(`^(?:${TRAILER_KEY}|${COAUTHOR_KEY}):`, "i");
37806
37712
  function parseTrailers(message2, cwd) {
37807
37713
  try {
37808
- return (0, import_node_child_process14.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
37714
+ return (0, import_node_child_process13.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
37809
37715
  windowsHide: true,
37810
37716
  cwd,
37811
37717
  input: message2,
@@ -37904,7 +37810,7 @@ function runTestPolicy(root, deps = {}) {
37904
37810
  }
37905
37811
  const loaded = deps.policy ? { policy: deps.policy, source: { ref: null, sha: null, path: POLICY_FILE } } : loadPolicySource(root, deps.policyRef, deps.base);
37906
37812
  const { policy, source: policySource } = loaded;
37907
- const exists = deps.exists ?? ((path2) => (0, import_node_fs36.existsSync)(path2));
37813
+ const exists = deps.exists ?? ((path2) => (0, import_node_fs35.existsSync)(path2));
37908
37814
  const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
37909
37815
  const base = deps.changed ? "(injected)" : deps.policyRef ? resolveHotfixBase(root) : resolveBase(root, deps.base);
37910
37816
  const refusal = deps.changed ? null : untrustworthyRange(root, base);
@@ -38140,13 +38046,13 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
38140
38046
  return rewritten === base ? null : rewritten;
38141
38047
  }
38142
38048
  function writeSquashBodyFile(body) {
38143
- const dir = (0, import_node_fs37.mkdtempSync)((0, import_node_path34.join)((0, import_node_os18.tmpdir)(), "mmi-squash-body-"));
38049
+ const dir = (0, import_node_fs36.mkdtempSync)((0, import_node_path34.join)((0, import_node_os18.tmpdir)(), "mmi-squash-body-"));
38144
38050
  const path2 = (0, import_node_path34.join)(dir, "body.txt");
38145
- (0, import_node_fs37.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
38051
+ (0, import_node_fs36.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
38146
38052
  `, "utf8");
38147
38053
  return { path: path2, cleanup: () => {
38148
38054
  try {
38149
- (0, import_node_fs37.rmSync)(dir, { recursive: true, force: true });
38055
+ (0, import_node_fs36.rmSync)(dir, { recursive: true, force: true });
38150
38056
  } catch {
38151
38057
  }
38152
38058
  } };
@@ -38353,7 +38259,7 @@ async function deleteMergedRemoteBranch(options) {
38353
38259
  }
38354
38260
 
38355
38261
  // src/post-merge-recon.ts
38356
- var import_node_fs38 = require("node:fs");
38262
+ var import_node_fs37 = require("node:fs");
38357
38263
  var import_node_path35 = require("node:path");
38358
38264
 
38359
38265
  // src/cross-repo-filing-issue.ts
@@ -38520,16 +38426,16 @@ function buildPostMergeReconRecovery(input) {
38520
38426
  }
38521
38427
  function writePostMergeReconRecovery(cwd, recovery) {
38522
38428
  const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
38523
- (0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(path2), { recursive: true });
38524
- (0, import_node_fs38.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
38429
+ (0, import_node_fs37.mkdirSync)((0, import_node_path35.dirname)(path2), { recursive: true });
38430
+ (0, import_node_fs37.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
38525
38431
  `, "utf8");
38526
38432
  return path2;
38527
38433
  }
38528
38434
  function clearPostMergeReconRecovery(cwd, repo, pr) {
38529
38435
  const path2 = postMergeReconStatePath(cwd, repo, pr);
38530
- if (!(0, import_node_fs38.existsSync)(path2)) return;
38436
+ if (!(0, import_node_fs37.existsSync)(path2)) return;
38531
38437
  try {
38532
- (0, import_node_fs38.unlinkSync)(path2);
38438
+ (0, import_node_fs37.unlinkSync)(path2);
38533
38439
  } catch {
38534
38440
  }
38535
38441
  }
@@ -38560,8 +38466,8 @@ function postMergeReconWarnings(input) {
38560
38466
  }
38561
38467
 
38562
38468
  // src/review-verdict.ts
38563
- var import_node_child_process15 = require("node:child_process");
38564
- var import_node_fs39 = require("node:fs");
38469
+ var import_node_child_process14 = require("node:child_process");
38470
+ var import_node_fs38 = require("node:fs");
38565
38471
  var import_node_os19 = require("node:os");
38566
38472
  var import_node_path36 = require("node:path");
38567
38473
  var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
@@ -38659,8 +38565,8 @@ async function checkPrReview(number, repo, head, deps = {
38659
38565
  }
38660
38566
  function computePrPatchId(number, repo) {
38661
38567
  return new Promise((resolve7, reject) => {
38662
- const gh = (0, import_node_child_process15.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
38663
- const git3 = (0, import_node_child_process15.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
38568
+ const gh = (0, import_node_child_process14.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
38569
+ const git3 = (0, import_node_child_process14.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
38664
38570
  let out = "";
38665
38571
  let ghErr = "";
38666
38572
  let gitErr = "";
@@ -38727,29 +38633,29 @@ async function readPrIssueComments(number, repo) {
38727
38633
  return comments;
38728
38634
  }
38729
38635
  async function postPrCommentFromFile(number, repo, body) {
38730
- const dir = (0, import_node_fs39.mkdtempSync)((0, import_node_path36.join)((0, import_node_os19.tmpdir)(), "mmi-review-verdict-"));
38636
+ const dir = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os19.tmpdir)(), "mmi-review-verdict-"));
38731
38637
  const path2 = (0, import_node_path36.join)(dir, "body.md");
38732
38638
  try {
38733
- (0, import_node_fs39.writeFileSync)(path2, body, "utf8");
38639
+ (0, import_node_fs38.writeFileSync)(path2, body, "utf8");
38734
38640
  const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
38735
38641
  return stdout.trim();
38736
38642
  } finally {
38737
38643
  try {
38738
- (0, import_node_fs39.rmSync)(dir, { recursive: true, force: true });
38644
+ (0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
38739
38645
  } catch {
38740
38646
  }
38741
38647
  }
38742
38648
  }
38743
38649
 
38744
38650
  // src/pr-create-docs-check.ts
38745
- var import_node_child_process16 = require("node:child_process");
38651
+ var import_node_child_process15 = require("node:child_process");
38746
38652
  var GIT_TIMEOUT_MS2 = 15e3;
38747
38653
  function catFileBatch(root, ref, paths) {
38748
38654
  if (paths.length === 0) return Promise.resolve([]);
38749
38655
  return new Promise((resolve7) => {
38750
38656
  const chunks = [];
38751
38657
  let settled = false;
38752
- const child2 = (0, import_node_child_process16.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
38658
+ const child2 = (0, import_node_child_process15.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
38753
38659
  const finish = () => {
38754
38660
  if (settled) return;
38755
38661
  settled = true;
@@ -38919,69 +38825,12 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
38919
38825
  }
38920
38826
 
38921
38827
  // src/worktree-merge-cleanup.ts
38922
- var import_node_fs42 = require("node:fs");
38923
- var import_node_path39 = require("node:path");
38924
-
38925
- // src/jervcode-node-modules-cleanup.ts
38926
38828
  var import_node_fs40 = require("node:fs");
38927
- var import_node_os20 = require("node:os");
38928
- var import_node_path37 = require("node:path");
38929
- var JERVCODE_PACKAGE_ENTRY = (0, import_node_path37.join)("node_modules", "@jervaise", "jervcode", "dist", "launcher-entry.js");
38930
- var WIN_NAMES2 = ["jervcode.cmd", "jervcode"];
38931
- var POSIX_NAMES2 = ["jervcode"];
38932
- var NODE_MODULES_CLEANUP_TIMEOUT_MS = 3e5;
38933
- function jervcodeCandidatePaths(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform) {
38934
- const names = platform2 === "win32" ? WIN_NAMES2 : POSIX_NAMES2;
38935
- const out = [];
38936
- for (const dir of jervCliCandidateDirs(env, home, platform2)) {
38937
- for (const name of names) out.push((0, import_node_path37.join)(dir, name));
38938
- }
38939
- return out;
38940
- }
38941
- function resolveJervcodePath(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform, exists = import_node_fs40.existsSync) {
38942
- for (const candidate of jervcodeCandidatePaths(env, home, platform2)) {
38943
- if (exists(candidate)) return candidate;
38944
- }
38945
- return void 0;
38946
- }
38947
- function jervcodeExecFileArgs(args, opts = {}) {
38948
- const platform2 = opts.platform ?? process.platform;
38949
- const exists = opts.exists ?? import_node_fs40.existsSync;
38950
- const resolved = resolveJervcodePath(opts.env ?? process.env, opts.home ?? (0, import_node_os20.homedir)(), platform2, exists);
38951
- if (resolved) {
38952
- const entry = (0, import_node_path37.join)((0, import_node_path37.join)(resolved, ".."), JERVCODE_PACKAGE_ENTRY);
38953
- if (exists(entry)) {
38954
- return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
38955
- }
38956
- }
38957
- const bin = resolved ?? "jervcode";
38958
- if (platform2 === "win32") {
38959
- return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
38960
- }
38961
- return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
38962
- }
38963
- async function removeWorktreeNodeModulesViaHelper(wtPath, opts = {}) {
38964
- const { cwd, timeoutMs = NODE_MODULES_CLEANUP_TIMEOUT_MS } = opts;
38965
- const env = opts.env ?? process.env;
38966
- const exec = opts.exec ?? execFileP;
38967
- const candidates = jervcodeCandidatePaths(env, opts.home, opts.platform ?? process.platform);
38968
- const plan = jervcodeExecFileArgs(["worktree-node-modules-cleanup", "--worktree", wtPath], opts);
38969
- const execOptions = { timeout: timeoutMs, ...cwd ? { cwd } : {} };
38970
- try {
38971
- await exec(plan.file, plan.args, execOptions);
38972
- return { ok: true };
38973
- } catch (e) {
38974
- const err = e;
38975
- const base = formatJervCliSpawnFailure(err, plan, candidates);
38976
- const stderr = typeof err.stderr === "string" ? err.stderr.trim() : "";
38977
- const detail = stderr.split("\n")[0] || base;
38978
- return { ok: false, error: `jervcode worktree-node-modules-cleanup failed: ${detail}` };
38979
- }
38980
- }
38829
+ var import_node_path38 = require("node:path");
38981
38830
 
38982
38831
  // src/worktree-evidence-archive.ts
38983
- var import_node_fs41 = require("node:fs");
38984
- var import_node_path38 = require("node:path");
38832
+ var import_node_fs39 = require("node:fs");
38833
+ var import_node_path37 = require("node:path");
38985
38834
  var JERV_ARTIFACT_RUN_SCOPE_ENV_VARS = ["JERV_RUN_ID", ...SESSION_ID_ENV_VARS];
38986
38835
  function sanitizeArchiveSegment(value, max = 80) {
38987
38836
  const scrubbed = value.replace(/[^A-Za-z0-9._@+-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -38996,24 +38845,24 @@ function resolveArtifactRunScope(env = process.env) {
38996
38845
  }
38997
38846
  function defaultIsDirectory(path2) {
38998
38847
  try {
38999
- return (0, import_node_fs41.lstatSync)(path2).isDirectory();
38848
+ return (0, import_node_fs39.lstatSync)(path2).isDirectory();
39000
38849
  } catch {
39001
38850
  return false;
39002
38851
  }
39003
38852
  }
39004
38853
  function archiveWorktreeJervArtifacts(args, deps = {}) {
39005
- const exists = deps.exists ?? import_node_fs41.existsSync;
38854
+ const exists = deps.exists ?? import_node_fs39.existsSync;
39006
38855
  const isDirectory = deps.isDirectory ?? defaultIsDirectory;
39007
- const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs41.cpSync)(from, to, { recursive: true, force: true }));
38856
+ const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs39.cpSync)(from, to, { recursive: true, force: true }));
39008
38857
  const mkdirp = deps.mkdirp ?? ((path2) => {
39009
- (0, import_node_fs41.mkdirSync)(path2, { recursive: true });
38858
+ (0, import_node_fs39.mkdirSync)(path2, { recursive: true });
39010
38859
  });
39011
38860
  const env = deps.env ?? process.env;
39012
38861
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
39013
38862
  const resolveRoot = deps.resolveArchiveRoot ?? repoRuntimeStatePath;
39014
38863
  if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
39015
38864
  if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
39016
- const source = (0, import_node_path38.join)(args.worktreePath, ".jerv");
38865
+ const source = (0, import_node_path37.join)(args.worktreePath, ".jerv");
39017
38866
  if (!exists(source)) return { status: "absent" };
39018
38867
  if (!isDirectory(source)) return { status: "skipped", reason: "jerv-not-a-directory" };
39019
38868
  const runScope = resolveArtifactRunScope(env);
@@ -39021,7 +38870,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
39021
38870
  const stamp = now().toISOString().replace(/[:.]/g, "-");
39022
38871
  const dest = resolveRoot(args.primaryRoot, "jerv-artifacts", runScope, branchSlug, stamp, ".jerv");
39023
38872
  try {
39024
- mkdirp((0, import_node_path38.dirname)(dest));
38873
+ mkdirp((0, import_node_path37.dirname)(dest));
39025
38874
  copyDir(source, dest);
39026
38875
  if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
39027
38876
  return { status: "archived", path: dest, runScope };
@@ -39030,14 +38879,14 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
39030
38879
  }
39031
38880
  }
39032
38881
  function defaultStat(path2) {
39033
- const st = (0, import_node_fs41.statSync)(path2);
38882
+ const st = (0, import_node_fs39.statSync)(path2);
39034
38883
  return { mtimeMs: st.mtimeMs, size: st.size, isDirectory: () => st.isDirectory() };
39035
38884
  }
39036
38885
  function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
39037
- const exists = deps.exists ?? import_node_fs41.existsSync;
38886
+ const exists = deps.exists ?? import_node_fs39.existsSync;
39038
38887
  const stat4 = deps.stat ?? defaultStat;
39039
- const readdir2 = deps.readdir ?? import_node_fs41.readdirSync;
39040
- const tmpRoot = (0, import_node_path38.join)(worktreePath, "tmp");
38888
+ const readdir2 = deps.readdir ?? import_node_fs39.readdirSync;
38889
+ const tmpRoot = (0, import_node_path37.join)(worktreePath, "tmp");
39041
38890
  if (!exists(tmpRoot)) return [];
39042
38891
  const entries = [];
39043
38892
  const walk2 = (dir) => {
@@ -39048,14 +38897,14 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
39048
38897
  return;
39049
38898
  }
39050
38899
  for (const name of names) {
39051
- const full = (0, import_node_path38.join)(dir, name);
38900
+ const full = (0, import_node_path37.join)(dir, name);
39052
38901
  let st;
39053
38902
  try {
39054
38903
  st = stat4(full);
39055
38904
  } catch {
39056
38905
  continue;
39057
38906
  }
39058
- const relPath = (0, import_node_path38.relative)(worktreePath, full).replace(/\\/g, "/");
38907
+ const relPath = (0, import_node_path37.relative)(worktreePath, full).replace(/\\/g, "/");
39059
38908
  if (st.isDirectory()) {
39060
38909
  if (st.mtimeMs > newerThanMs) entries.push({ relPath, bytes: 0, mtimeMs: st.mtimeMs });
39061
38910
  walk2(full);
@@ -39069,10 +38918,10 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
39069
38918
  return entries;
39070
38919
  }
39071
38920
  function archiveWorktreeTmpArtifacts(args, deps = {}) {
39072
- const exists = deps.exists ?? import_node_fs41.existsSync;
39073
- const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs41.cpSync)(from, to, { recursive: true, force: true }));
38921
+ const exists = deps.exists ?? import_node_fs39.existsSync;
38922
+ const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs39.cpSync)(from, to, { recursive: true, force: true }));
39074
38923
  const mkdirp = deps.mkdirp ?? ((path2) => {
39075
- (0, import_node_fs41.mkdirSync)(path2, { recursive: true });
38924
+ (0, import_node_fs39.mkdirSync)(path2, { recursive: true });
39076
38925
  });
39077
38926
  const env = deps.env ?? process.env;
39078
38927
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
@@ -39080,7 +38929,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
39080
38929
  if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
39081
38930
  if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
39082
38931
  const scanned = scanWorktreeTmpEvidence(args.worktreePath, args.newerThanMs, deps);
39083
- const source = (0, import_node_path38.join)(args.worktreePath, "tmp");
38932
+ const source = (0, import_node_path37.join)(args.worktreePath, "tmp");
39084
38933
  if (!scanned.length) return { status: "absent" };
39085
38934
  if (!exists(source)) return { status: "absent" };
39086
38935
  const runScope = resolveArtifactRunScope(env);
@@ -39088,7 +38937,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
39088
38937
  const stamp = now().toISOString().replace(/[:.]/g, "-");
39089
38938
  const dest = resolveRoot(args.primaryRoot, "worktree-artifacts", runScope, branchSlug, stamp, "tmp");
39090
38939
  try {
39091
- mkdirp((0, import_node_path38.dirname)(dest));
38940
+ mkdirp((0, import_node_path37.dirname)(dest));
39092
38941
  copyDir(source, dest);
39093
38942
  if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
39094
38943
  const bytes = scanned.reduce((sum, e) => sum + e.bytes, 0);
@@ -39157,9 +39006,9 @@ function normPath2(p) {
39157
39006
  return p.replace(/\\/g, "/").replace(/\/+$/, "");
39158
39007
  }
39159
39008
  function unlinkNodeModulesJunction(wtPath) {
39160
- const nm = (0, import_node_path39.join)(wtPath, "node_modules");
39009
+ const nm = (0, import_node_path38.join)(wtPath, "node_modules");
39161
39010
  try {
39162
- if ((0, import_node_fs42.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs42.rmdirSync)(nm);
39011
+ if ((0, import_node_fs40.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs40.rmdirSync)(nm);
39163
39012
  return { ok: true };
39164
39013
  } catch (e) {
39165
39014
  if (e.code === "ENOENT") return { ok: true };
@@ -39170,8 +39019,8 @@ function defaultSleep2(ms) {
39170
39019
  return new Promise((resolve7) => setTimeout(resolve7, ms));
39171
39020
  }
39172
39021
  async function removeResidueDirectory(wtPath, options = {}) {
39173
- const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs42.rmdirSync, exists = import_node_fs42.existsSync } = options;
39174
- const removeRecursive = options.removeRecursive ?? ((path2) => (0, import_node_fs42.rmSync)(path2, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }));
39022
+ const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs40.rmdirSync, exists = import_node_fs40.existsSync } = options;
39023
+ const removeRecursive = options.removeRecursive ?? ((path2) => (0, import_node_fs40.rmSync)(path2, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }));
39175
39024
  const junction = unlinkNodeModulesJunction(wtPath);
39176
39025
  if (!junction.ok) return junction;
39177
39026
  try {
@@ -39217,7 +39066,7 @@ function isWindowsCwdLockResidueError(error) {
39217
39066
  }
39218
39067
  function deferredCwdLockRemediation(wtPath) {
39219
39068
  const quote = (path2) => path2.replace(/'/g, "''");
39220
- return `After this command exits: jervcode worktree-cleanup --worktree '${quote(wtPath)}'`;
39069
+ return `After leaving the directory and closing its handles, remove it only if empty: [System.IO.Directory]::Delete('${quote(wtPath)}', $false)`;
39221
39070
  }
39222
39071
  function primaryCheckoutBranchRemediation(primaryRoot, baseRef, branch) {
39223
39072
  const quote = (value) => value.replace(/'/g, "''");
@@ -39294,31 +39143,40 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
39294
39143
  }
39295
39144
  async function listNestedIgnoredNodeModules(wtPath, execGit) {
39296
39145
  const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
39297
- return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path39.join)(wtPath, line.slice(0, -1)));
39146
+ return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path38.join)(wtPath, line.slice(0, -1)));
39298
39147
  }
39299
39148
  function safeRemoveTree(path2) {
39300
- const stat4 = (0, import_node_fs42.lstatSync)(path2);
39149
+ const stat4 = (0, import_node_fs40.lstatSync)(path2);
39301
39150
  if (stat4.isSymbolicLink()) {
39302
39151
  try {
39303
- (0, import_node_fs42.rmdirSync)(path2);
39152
+ (0, import_node_fs40.rmdirSync)(path2);
39304
39153
  } catch {
39305
- (0, import_node_fs42.unlinkSync)(path2);
39154
+ (0, import_node_fs40.unlinkSync)(path2);
39306
39155
  }
39307
39156
  return;
39308
39157
  }
39309
39158
  if (stat4.isDirectory()) {
39310
- for (const entry of (0, import_node_fs42.readdirSync)(path2)) safeRemoveTree((0, import_node_path39.join)(path2, entry));
39311
- (0, import_node_fs42.rmdirSync)(path2);
39159
+ for (const entry of (0, import_node_fs40.readdirSync)(path2)) safeRemoveTree((0, import_node_path38.join)(path2, entry));
39160
+ (0, import_node_fs40.rmdirSync)(path2);
39312
39161
  return;
39313
39162
  }
39314
- (0, import_node_fs42.unlinkSync)(path2);
39163
+ (0, import_node_fs40.unlinkSync)(path2);
39164
+ }
39165
+ async function removeWorktreeNodeModules(wtPath) {
39166
+ try {
39167
+ safeRemoveTree((0, import_node_path38.join)(wtPath, "node_modules"));
39168
+ return { ok: true };
39169
+ } catch (e) {
39170
+ if (e.code === "ENOENT") return { ok: true };
39171
+ return { ok: false, error: errorMessage(e) };
39172
+ }
39315
39173
  }
39316
39174
  function errorMessage(e) {
39317
39175
  return e instanceof Error ? e.message : String(e);
39318
39176
  }
39319
39177
  function resolvedOrRaw(path2) {
39320
39178
  try {
39321
- return normPath2((0, import_node_fs42.realpathSync)(path2));
39179
+ return normPath2((0, import_node_fs40.realpathSync)(path2));
39322
39180
  } catch {
39323
39181
  return normPath2(path2);
39324
39182
  }
@@ -39326,10 +39184,10 @@ function resolvedOrRaw(path2) {
39326
39184
  function unlinkEscapingReparsePoints(root, primaryRoot) {
39327
39185
  let realRoot;
39328
39186
  try {
39329
- if ((0, import_node_fs42.lstatSync)(root).isSymbolicLink()) {
39187
+ if ((0, import_node_fs40.lstatSync)(root).isSymbolicLink()) {
39330
39188
  return { ok: false, error: `delete root ${normPath2(root)} is a reparse point resolving to ${resolvedOrRaw(root)}` };
39331
39189
  }
39332
- realRoot = normPath2((0, import_node_fs42.realpathSync)(root));
39190
+ realRoot = normPath2((0, import_node_fs40.realpathSync)(root));
39333
39191
  } catch (e) {
39334
39192
  if (e.code === "ENOENT") return { ok: true, unlinked: [] };
39335
39193
  return { ok: false, error: `cannot resolve delete root ${normPath2(root)}: ${errorMessage(e)}` };
@@ -39345,16 +39203,16 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
39345
39203
  const dir = stack.pop();
39346
39204
  let entries;
39347
39205
  try {
39348
- entries = (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true });
39206
+ entries = (0, import_node_fs40.readdirSync)(dir, { withFileTypes: true });
39349
39207
  } catch (e) {
39350
39208
  return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
39351
39209
  }
39352
39210
  for (const entry of entries) {
39353
- const child2 = (0, import_node_path39.join)(dir, entry.name);
39211
+ const child2 = (0, import_node_path38.join)(dir, entry.name);
39354
39212
  if (entry.isSymbolicLink()) {
39355
39213
  let target = "";
39356
39214
  try {
39357
- target = normPath2((0, import_node_fs42.realpathSync)(child2));
39215
+ target = normPath2((0, import_node_fs40.realpathSync)(child2));
39358
39216
  } catch {
39359
39217
  target = "";
39360
39218
  }
@@ -39383,8 +39241,7 @@ async function describePreCleanFailure(wtPath, execGit, error) {
39383
39241
  const shown = remaining.slice(0, 10).join(", ");
39384
39242
  const more = remaining.length > 10 ? ` (+${remaining.length - 10} more)` : "";
39385
39243
  const quote = (path2) => path2.replace(/'/g, "''");
39386
- const nested = remaining.find((path2) => path2.endsWith("node_modules/") && path2 !== "node_modules/");
39387
- const remediation = remaining.includes("node_modules/") ? `jervcode worktree-node-modules-cleanup --worktree '${quote(wtPath)}'` : nested ? `Remove-Item -LiteralPath '${quote((0, import_node_path39.join)(wtPath, nested.slice(0, -1)))}' -Recurse -Force` : void 0;
39244
+ const remediation = remaining.some((path2) => path2.endsWith("node_modules/")) ? `Close handles to '${quote(wtPath)}' and retry MMI PR landing from the primary checkout` : void 0;
39388
39245
  return { ok: false, error: `${error}; remaining ignored paths: ${shown}${more}`, ...remediation ? { remediation } : {} };
39389
39246
  }
39390
39247
  function formatWorktreeRemovalFailureDetail(options) {
@@ -39538,7 +39395,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
39538
39395
  return report;
39539
39396
  }
39540
39397
  const execGit = options.execGit ?? (async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout);
39541
- const pathExists = options.pathExists ?? import_node_fs42.existsSync;
39398
+ const pathExists = options.pathExists ?? import_node_fs40.existsSync;
39542
39399
  let afterWorktrees = [];
39543
39400
  try {
39544
39401
  afterWorktrees = parseGitWorktreePorcelain(await execGit(["worktree", "list", "--porcelain"]));
@@ -39678,8 +39535,8 @@ async function cleanupPrMergeLocalBranch(branch, options) {
39678
39535
  const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
39679
39536
  if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
39680
39537
  unlinkedReparsePoints.push(...preHelperGuard.unlinked);
39681
- if (pathExists((0, import_node_path39.join)(wtPath, "node_modules"))) {
39682
- const nmRemoved = await (options.removeRealNodeModules ?? ((p) => removeWorktreeNodeModulesViaHelper(p, { cwd: mainWorktreePath })))(wtPath);
39538
+ if (pathExists((0, import_node_path38.join)(wtPath, "node_modules"))) {
39539
+ const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
39683
39540
  if (!nmRemoved.ok) {
39684
39541
  report.worktree = {
39685
39542
  path: wtPath,
@@ -39690,7 +39547,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
39690
39547
  stageTeardown,
39691
39548
  tmpEvidenceCount: tmpEvidence.length,
39692
39549
  ...unlinkedReparsePoints.length ? { unlinkedReparsePoints } : {},
39693
- remediation: `jervcode worktree-node-modules-cleanup --worktree '${wtPath.replace(/'/g, "''")}'`
39550
+ remediation: `Close handles to '${wtPath.replace(/'/g, "''")}' and retry MMI PR landing from the primary checkout`
39694
39551
  };
39695
39552
  report.localBranch = { name: branch, status: "not-attempted", reason: "worktree-pre-clean-failed" };
39696
39553
  return report;
@@ -39845,10 +39702,10 @@ function argvWantsJson2() {
39845
39702
  return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
39846
39703
  }
39847
39704
  function hubRoot() {
39848
- const fromPkg = (0, import_node_path40.join)(__dirname, "..", "..");
39705
+ const fromPkg = (0, import_node_path39.join)(__dirname, "..", "..");
39849
39706
  const marker = "skills/bootstrap/seeds/manifest.json";
39850
- if ((0, import_node_fs43.existsSync)((0, import_node_path40.join)(fromPkg, marker))) return fromPkg;
39851
- if ((0, import_node_fs43.existsSync)((0, import_node_path40.join)(process.cwd(), marker))) return process.cwd();
39707
+ if ((0, import_node_fs41.existsSync)((0, import_node_path39.join)(fromPkg, marker))) return fromPkg;
39708
+ if ((0, import_node_fs41.existsSync)((0, import_node_path39.join)(process.cwd(), marker))) return process.cwd();
39852
39709
  return null;
39853
39710
  }
39854
39711
  function ciAuditDeps() {
@@ -39860,8 +39717,8 @@ function ciAuditDeps() {
39860
39717
  getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
39861
39718
  readSeedFile: (path2) => {
39862
39719
  if (!root) return null;
39863
- const fullPath = (0, import_node_path40.join)(root, path2);
39864
- return (0, import_node_fs43.existsSync)(fullPath) ? (0, import_node_fs43.readFileSync)(fullPath, "utf8") : null;
39720
+ const fullPath = (0, import_node_path39.join)(root, path2);
39721
+ return (0, import_node_fs41.existsSync)(fullPath) ? (0, import_node_fs41.readFileSync)(fullPath, "utf8") : null;
39865
39722
  }
39866
39723
  };
39867
39724
  }
@@ -39943,7 +39800,7 @@ function scheduleRelatedDiscovery(o) {
39943
39800
  try {
39944
39801
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
39945
39802
  if (o.repo) args.push("--repo", o.repo);
39946
- spawnDetachedSelf(args, { spawn: import_node_child_process17.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
39803
+ spawnDetachedSelf(args, { spawn: import_node_child_process16.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
39947
39804
  } catch {
39948
39805
  }
39949
39806
  }
@@ -40153,7 +40010,6 @@ function registerCollaborationCommands(program3) {
40153
40010
  }
40154
40011
  }
40155
40012
  if (o.related !== false) scheduleRelatedDiscovery({ repo: o.repo, number: created.number, title, body });
40156
- invalidateStatuslineBoardCache();
40157
40013
  console.log(JSON.stringify({
40158
40014
  ...created,
40159
40015
  label: issueType,
@@ -40396,7 +40252,6 @@ ${list}`);
40396
40252
  }
40397
40253
  }
40398
40254
  program3.command("skill-lesson").description("file a skill-lesson on the Hub board (GitHub auth, dedups open lessons) and print {number,url} JSON").addOption(new Option("--skill <name>", `which skill misfired (${SKILL_NAMES.join(" | ")})`).makeOptionMandatory().choices([...SKILL_NAMES])).option("--title <title>", "one-line summary of what misfired").option("--title-file <path|->", "read the one-line summary from a UTF-8 file, or from stdin with -").option("--body <body>", "lesson body: what misfired, the evidence, and the proposed amendment (markdown)").option("--body-file <path|->", "read the lesson body from a UTF-8 file, or from stdin with -").option("--priority <priority>", "urgent | high | medium | low (defaults to medium; sets the board Priority field only, #416)").option("--repo <owner/repo>", `target repo (defaults to the org Hub: ${HUB_REPO})`).option("--force", "file a new issue even when an open lesson looks like a duplicate").option("--json", "machine-readable output (already the default \u2014 skill-lesson always prints JSON)").action(async (o) => {
40399
- warnSkillLessonDeprecated();
40400
40255
  const targetRepo2 = o.repo ?? HUB_REPO;
40401
40256
  const sourceRepo = await resolveRepo(void 0);
40402
40257
  const pluginSha = await resolvePluginSha();
@@ -40497,7 +40352,6 @@ ${list}`);
40497
40352
  process.exitCode = 1;
40498
40353
  return;
40499
40354
  }
40500
- invalidateStatuslineBoardCache();
40501
40355
  console.log(JSON.stringify(created));
40502
40356
  }), [
40503
40357
  'mmi-cli devops pr create --title "Add the schema" --body "Closes #2680"',
@@ -40535,11 +40389,11 @@ ${list}`);
40535
40389
  }
40536
40390
  });
40537
40391
  async function listCiWorkflowPaths(cwd = process.cwd()) {
40538
- const wfDir = (0, import_node_path40.join)(cwd, ".github", "workflows");
40539
- if (!(0, import_node_fs43.existsSync)(wfDir)) return [];
40540
- return (0, import_node_fs43.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
40392
+ const wfDir = (0, import_node_path39.join)(cwd, ".github", "workflows");
40393
+ if (!(0, import_node_fs41.existsSync)(wfDir)) return [];
40394
+ return (0, import_node_fs41.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
40541
40395
  try {
40542
- return workflowReportsPrChecks((0, import_node_fs43.readFileSync)((0, import_node_path40.join)(wfDir, name), "utf8"));
40396
+ return workflowReportsPrChecks((0, import_node_fs41.readFileSync)((0, import_node_path39.join)(wfDir, name), "utf8"));
40543
40397
  } catch {
40544
40398
  return true;
40545
40399
  }
@@ -40735,7 +40589,7 @@ ${list}`);
40735
40589
  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) => {
40736
40590
  if (!isReviewVerdict(o.verdict)) return fail(`pr review-verdict: --verdict must be one of ${REVIEW_VERDICTS.join("|")} (got ${o.verdict})`);
40737
40591
  const verdict = o.verdict;
40738
- const findings = o.findingsFile ? (0, import_node_fs43.readFileSync)(o.findingsFile, "utf8") : void 0;
40592
+ const findings = o.findingsFile ? (0, import_node_fs41.readFileSync)(o.findingsFile, "utf8") : void 0;
40739
40593
  let patch;
40740
40594
  let head;
40741
40595
  try {
@@ -40929,7 +40783,6 @@ ${list}`);
40929
40783
  ...crossRepoFilingIssue.status !== "not-applicable" ? { crossRepoFilingIssue } : {},
40930
40784
  ...recovery ? { postMergeReconRecovery: recovery } : {}
40931
40785
  });
40932
- invalidateStatuslineBoardCache();
40933
40786
  for (const line of postMergeReconWarnings({
40934
40787
  context: "pr land",
40935
40788
  boardAdvance,
@@ -40983,7 +40836,7 @@ ${list}`);
40983
40836
  const mergeSquashBody = squashBodyTextForMerge(
40984
40837
  closingGuardInput,
40985
40838
  method === "--squash",
40986
- o.squashBodyFile ? (0, import_node_fs43.readFileSync)(o.squashBodyFile, "utf8") : void 0
40839
+ o.squashBodyFile ? (0, import_node_fs41.readFileSync)(o.squashBodyFile, "utf8") : void 0
40987
40840
  );
40988
40841
  if (!o.squashBodyFile) warnSquashBodyClosingStrip("pr merge", closingGuardInput, mergeSquashBody);
40989
40842
  const closingGuardVerdict = evaluateClosingGuard(closingGuardInput, {
@@ -41015,7 +40868,7 @@ ${list}`);
41015
40868
  const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
41016
40869
  let foreignCheckout;
41017
40870
  if (foreignCwd) {
41018
- const sibling = (0, import_node_path40.join)((0, import_node_path40.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
40871
+ const sibling = (0, import_node_path39.join)((0, import_node_path39.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
41019
40872
  const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
41020
40873
  if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
41021
40874
  const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
@@ -41113,7 +40966,7 @@ ${list}`);
41113
40966
  }
41114
40967
  if (!repoForPostCleanup) throw e;
41115
40968
  console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
41116
- const commitMessage = bodyFile ? (0, import_node_fs43.readFileSync)(bodyFile, "utf8") : void 0;
40969
+ const commitMessage = bodyFile ? (0, import_node_fs41.readFileSync)(bodyFile, "utf8") : void 0;
41117
40970
  await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
41118
40971
  body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
41119
40972
  timeoutMs: GH_MUTATION_TIMEOUT_MS
@@ -41233,7 +41086,7 @@ ${list}`);
41233
41086
  preserveWorktree: o.preserveWorktree,
41234
41087
  gcAcknowledged: o.gc,
41235
41088
  expectedHeadOid: headRefOid,
41236
- pathExists: (p) => (0, import_node_fs43.existsSync)(p),
41089
+ pathExists: (p) => (0, import_node_fs41.existsSync)(p),
41237
41090
  // #5899: pin cleanup git calls to the main checkout — the task worktree this process may be
41238
41091
  // standing in is removed mid-cleanup, so a cwd-relative invocation fails with
41239
41092
  // 'fatal: not a git repository' and leaves a spurious partial-cleanup exit.
@@ -41298,7 +41151,6 @@ ${list}`);
41298
41151
  } else if (repoForPostCleanup) {
41299
41152
  clearPostMergeReconRecovery(process.cwd(), repoForPostCleanup, number);
41300
41153
  }
41301
- invalidateStatuslineBoardCache();
41302
41154
  const devDeploy = devDeployPlan.applicable && devDeployDeps && remoteNotAttemptedReason !== "pr-already-merged" ? await dispatchDevDeploy(repoForPostCleanup, devDeployDeps) : void 0;
41303
41155
  const devDeployManual = devDeployPlan.applicable ? devDeployPlan.manualPointer : void 0;
41304
41156
  let observedMethod;
@@ -41355,7 +41207,7 @@ ${list}`);
41355
41207
  }
41356
41208
 
41357
41209
  // src/command-register-developer.ts
41358
- var import_node_fs48 = require("node:fs");
41210
+ var import_node_fs46 = require("node:fs");
41359
41211
 
41360
41212
  // src/whoami.ts
41361
41213
  async function resolveWhoami(deps) {
@@ -41385,7 +41237,7 @@ async function resolveWhoami(deps) {
41385
41237
  }
41386
41238
 
41387
41239
  // src/command-register-developer.ts
41388
- var import_node_path45 = require("node:path");
41240
+ var import_node_path44 = require("node:path");
41389
41241
 
41390
41242
  // src/wave-land.ts
41391
41243
  function planWaveLand(prs) {
@@ -41416,7 +41268,7 @@ async function executeWaveLand(plan, deps) {
41416
41268
  }
41417
41269
 
41418
41270
  // src/box-commands.ts
41419
- var import_node_fs44 = require("node:fs");
41271
+ var import_node_fs42 = require("node:fs");
41420
41272
 
41421
41273
  // src/box.ts
41422
41274
  var BOX_KEYS = {
@@ -41618,7 +41470,7 @@ function registerBoxCommands(program3) {
41618
41470
  return;
41619
41471
  }
41620
41472
  const wroteScript = o.ssh && o.script ? o.script : null;
41621
- if (wroteScript) (0, import_node_fs44.writeFileSync)(wroteScript, sshRecipeScript(found), "utf8");
41473
+ if (wroteScript) (0, import_node_fs42.writeFileSync)(wroteScript, sshRecipeScript(found), "utf8");
41622
41474
  if (o.json) {
41623
41475
  console.log(JSON.stringify({
41624
41476
  box: found,
@@ -41638,21 +41490,21 @@ ${SSH_RECIPE_AGENT_NOTE}`);
41638
41490
  }
41639
41491
 
41640
41492
  // src/dist-drift.ts
41641
- var import_node_child_process18 = require("node:child_process");
41493
+ var import_node_child_process17 = require("node:child_process");
41642
41494
  var import_node_crypto13 = require("node:crypto");
41643
- var import_node_fs46 = require("node:fs");
41644
- var import_node_os21 = require("node:os");
41645
- var import_node_path42 = require("node:path");
41495
+ var import_node_fs44 = require("node:fs");
41496
+ var import_node_os20 = require("node:os");
41497
+ var import_node_path41 = require("node:path");
41646
41498
 
41647
41499
  // ../scripts/distribution-digest.mjs
41648
41500
  var import_node_crypto12 = require("node:crypto");
41649
- var import_node_fs45 = require("node:fs");
41650
- var import_node_path41 = require("node:path");
41501
+ var import_node_fs43 = require("node:fs");
41502
+ var import_node_path40 = require("node:path");
41651
41503
  var slash = (value) => value.replaceAll("\\", "/");
41652
41504
  function repoPath(root, declaredPath, label) {
41653
- const absoluteRoot = (0, import_node_path41.resolve)(root);
41654
- const target = (0, import_node_path41.resolve)(root, declaredPath);
41655
- if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path41.sep}`)) {
41505
+ const absoluteRoot = (0, import_node_path40.resolve)(root);
41506
+ const target = (0, import_node_path40.resolve)(root, declaredPath);
41507
+ if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path40.sep}`)) {
41656
41508
  throw new Error(`${label} ${declaredPath} escapes the repository root`);
41657
41509
  }
41658
41510
  return target;
@@ -41660,7 +41512,7 @@ function repoPath(root, declaredPath, label) {
41660
41512
  function digestFiles(files) {
41661
41513
  const hash = (0, import_node_crypto12.createHash)("sha256");
41662
41514
  for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
41663
- const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs45.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs45.readFileSync)(file.absolute);
41515
+ const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs43.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs43.readFileSync)(file.absolute);
41664
41516
  hash.update(file.relative, "utf8");
41665
41517
  hash.update("\0");
41666
41518
  hash.update(file.stat.isSymbolicLink() ? "symlink" : "file", "utf8");
@@ -41675,8 +41527,8 @@ function digestFiles(files) {
41675
41527
  function digestPackedFiles(packageRoot, packedFiles) {
41676
41528
  return digestFiles(packedFiles.map((path2) => {
41677
41529
  const absolute = repoPath(packageRoot, path2, "packed artifact identity path");
41678
- if (!(0, import_node_fs45.existsSync)(absolute)) throw new Error(`packed artifact identity path ${path2} does not exist`);
41679
- return { absolute, relative: slash(path2), stat: (0, import_node_fs45.lstatSync)(absolute) };
41530
+ if (!(0, import_node_fs43.existsSync)(absolute)) throw new Error(`packed artifact identity path ${path2} does not exist`);
41531
+ return { absolute, relative: slash(path2), stat: (0, import_node_fs43.lstatSync)(absolute) };
41680
41532
  }));
41681
41533
  }
41682
41534
 
@@ -41760,13 +41612,13 @@ function renderDistDriftReceipt(receipt) {
41760
41612
  return lines2;
41761
41613
  }
41762
41614
  function readOrNull(path2) {
41763
- return (0, import_node_fs46.existsSync)(path2) ? (0, import_node_fs46.readFileSync)(path2) : null;
41615
+ return (0, import_node_fs44.existsSync)(path2) ? (0, import_node_fs44.readFileSync)(path2) : null;
41764
41616
  }
41765
41617
  function walkFiles(root) {
41766
41618
  const files = [];
41767
41619
  const walk2 = (directory) => {
41768
- for (const entry of (0, import_node_fs46.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
41769
- const child2 = (0, import_node_path42.join)(directory, entry.name);
41620
+ for (const entry of (0, import_node_fs44.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
41621
+ const child2 = (0, import_node_path41.join)(directory, entry.name);
41770
41622
  if (entry.isDirectory()) walk2(child2);
41771
41623
  else files.push(child2);
41772
41624
  }
@@ -41776,14 +41628,14 @@ function walkFiles(root) {
41776
41628
  }
41777
41629
  function bomPathFor(root) {
41778
41630
  try {
41779
- const registry2 = JSON.parse((0, import_node_fs46.readFileSync)((0, import_node_path42.join)(root, "surfaces.json"), "utf8"));
41780
- return (0, import_node_path42.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
41631
+ const registry2 = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(root, "surfaces.json"), "utf8"));
41632
+ return (0, import_node_path41.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
41781
41633
  } catch {
41782
- return (0, import_node_path42.join)(root, "distribution-bom.json");
41634
+ return (0, import_node_path41.join)(root, "distribution-bom.json");
41783
41635
  }
41784
41636
  }
41785
41637
  function rebuildTo(packageRoot, outDir) {
41786
- (0, import_node_child_process18.execFileSync)(process.execPath, ["build.mjs"], {
41638
+ (0, import_node_child_process17.execFileSync)(process.execPath, ["build.mjs"], {
41787
41639
  cwd: packageRoot,
41788
41640
  env: { ...process.env, MMI_DIST_OUTDIR: outDir },
41789
41641
  windowsHide: true,
@@ -41792,35 +41644,35 @@ function rebuildTo(packageRoot, outDir) {
41792
41644
  });
41793
41645
  }
41794
41646
  function runDistStatus(root) {
41795
- const stage = (0, import_node_fs46.mkdtempSync)((0, import_node_path42.join)((0, import_node_os21.tmpdir)(), "mmi-dist-drift-"));
41647
+ const stage = (0, import_node_fs44.mkdtempSync)((0, import_node_path41.join)((0, import_node_os20.tmpdir)(), "mmi-dist-drift-"));
41796
41648
  let overlayCount = 0;
41797
41649
  try {
41798
- const cliOut = (0, import_node_path42.join)(stage, "cli-dist");
41799
- const hubOut = (0, import_node_path42.join)(stage, "hub-dist");
41800
- rebuildTo((0, import_node_path42.join)(root, "cli"), cliOut);
41801
- rebuildTo((0, import_node_path42.join)(root, "updater"), hubOut);
41650
+ const cliOut = (0, import_node_path41.join)(stage, "cli-dist");
41651
+ const hubOut = (0, import_node_path41.join)(stage, "hub-dist");
41652
+ rebuildTo((0, import_node_path41.join)(root, "cli"), cliOut);
41653
+ rebuildTo((0, import_node_path41.join)(root, "updater"), hubOut);
41802
41654
  const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
41803
41655
  const rebuilt = (path2) => {
41804
41656
  const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
41805
- return spec ? readOrNull((0, import_node_path42.join)(outDirFor(spec.packageDir), spec.output)) : null;
41657
+ return spec ? readOrNull((0, import_node_path41.join)(outDirFor(spec.packageDir), spec.output)) : null;
41806
41658
  };
41807
- const committed = (path2) => readOrNull((0, import_node_path42.join)(root, path2));
41808
- const tree = (path2) => readOrNull((0, import_node_path42.join)(root, path2));
41809
- const distRoot = (0, import_node_path42.join)(root, "cli", "dist");
41810
- const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path42.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
41811
- const bom = JSON.parse((0, import_node_fs46.readFileSync)(bomPathFor(root), "utf8"));
41659
+ const committed = (path2) => readOrNull((0, import_node_path41.join)(root, path2));
41660
+ const tree = (path2) => readOrNull((0, import_node_path41.join)(root, path2));
41661
+ const distRoot = (0, import_node_path41.join)(root, "cli", "dist");
41662
+ const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path41.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
41663
+ const bom = JSON.parse((0, import_node_fs44.readFileSync)(bomPathFor(root), "utf8"));
41812
41664
  const digest = (entries) => {
41813
- const overlay = (0, import_node_path42.join)(stage, `overlay-${overlayCount++}`);
41665
+ const overlay = (0, import_node_path41.join)(stage, `overlay-${overlayCount++}`);
41814
41666
  for (const entry of entries) {
41815
- const target = (0, import_node_path42.join)(overlay, entry.path);
41816
- (0, import_node_fs46.mkdirSync)((0, import_node_path42.dirname)(target), { recursive: true });
41817
- (0, import_node_fs46.writeFileSync)(target, entry.bytes);
41667
+ const target = (0, import_node_path41.join)(overlay, entry.path);
41668
+ (0, import_node_fs44.mkdirSync)((0, import_node_path41.dirname)(target), { recursive: true });
41669
+ (0, import_node_fs44.writeFileSync)(target, entry.bytes);
41818
41670
  }
41819
41671
  return digestPackedFiles(overlay, entries.map((entry) => entry.path));
41820
41672
  };
41821
41673
  return computeDistDriftReceipt({ committed, tree, rebuilt, distTree, bom, digest });
41822
41674
  } finally {
41823
- (0, import_node_fs46.rmSync)(stage, { recursive: true, force: true });
41675
+ (0, import_node_fs44.rmSync)(stage, { recursive: true, force: true });
41824
41676
  }
41825
41677
  }
41826
41678
 
@@ -41892,7 +41744,7 @@ function registerEdgeCommands(program3) {
41892
41744
 
41893
41745
  // src/schedules-lift-command.ts
41894
41746
  var import_promises8 = require("node:fs/promises");
41895
- var import_node_path43 = require("node:path");
41747
+ var import_node_path42 = require("node:path");
41896
41748
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
41897
41749
  var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
41898
41750
  var SchedulesLiftUsageError = class extends Error {
@@ -41919,7 +41771,7 @@ async function readWorkflowFiles(dir) {
41919
41771
  const files = [];
41920
41772
  for (const name of names.sort()) {
41921
41773
  if (!/\.ya?ml$/.test(name)) continue;
41922
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises8.readFile)((0, import_node_path43.join)(dir, name), "utf8") });
41774
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises8.readFile)((0, import_node_path42.join)(dir, name), "utf8") });
41923
41775
  }
41924
41776
  return files;
41925
41777
  }
@@ -42001,9 +41853,9 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
42001
41853
  }
42002
41854
 
42003
41855
  // src/spawn-policy-core.ts
42004
- var import_node_child_process19 = require("node:child_process");
42005
- var import_node_fs47 = require("node:fs");
42006
- var import_node_path44 = require("node:path");
41856
+ var import_node_child_process18 = require("node:child_process");
41857
+ var import_node_fs45 = require("node:fs");
41858
+ var import_node_path43 = require("node:path");
42007
41859
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
42008
41860
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
42009
41861
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -42072,7 +41924,7 @@ function findViolationsInSource(raw) {
42072
41924
  return found;
42073
41925
  }
42074
41926
  function policedFiles(root) {
42075
- const r = (0, import_node_child_process19.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
41927
+ const r = (0, import_node_child_process18.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
42076
41928
  cwd: root,
42077
41929
  encoding: "utf8",
42078
41930
  windowsHide: true,
@@ -42089,7 +41941,7 @@ function runSpawnPolicy(root) {
42089
41941
  for (const file of files) {
42090
41942
  let raw;
42091
41943
  try {
42092
- raw = (0, import_node_fs47.readFileSync)((0, import_node_path44.join)(root, file), "utf8");
41944
+ raw = (0, import_node_fs45.readFileSync)((0, import_node_path43.join)(root, file), "utf8");
42093
41945
  } catch {
42094
41946
  continue;
42095
41947
  }
@@ -42109,19 +41961,19 @@ function runSpawnPolicy(root) {
42109
41961
  function registerDeveloperCommands(program3) {
42110
41962
  const rules = program3.command("rules").description("org-managed .gitignore delivery");
42111
41963
  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) => {
42112
- const path2 = (0, import_node_path45.join)(process.cwd(), ".gitignore");
42113
- const current = (0, import_node_fs48.existsSync)(path2) ? (0, import_node_fs48.readFileSync)(path2, "utf8") : null;
41964
+ const path2 = (0, import_node_path44.join)(process.cwd(), ".gitignore");
41965
+ const current = (0, import_node_fs46.existsSync)(path2) ? (0, import_node_fs46.readFileSync)(path2, "utf8") : null;
42114
41966
  const plan = planManagedGitignore(current);
42115
41967
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
42116
41968
  if (opts.json) {
42117
- if (opts.write && plan.changed) (0, import_node_fs48.writeFileSync)(path2, plan.content, "utf8");
41969
+ if (opts.write && plan.changed) (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
42118
41970
  console.log(JSON.stringify(plan, null, 2));
42119
41971
  if (!opts.write && plan.changed) process.exitCode = 1;
42120
41972
  return;
42121
41973
  }
42122
41974
  if (opts.write) {
42123
41975
  if (plan.changed) {
42124
- (0, import_node_fs48.writeFileSync)(path2, plan.content, "utf8");
41976
+ (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
42125
41977
  console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
42126
41978
  } else {
42127
41979
  console.log("mmi-cli devops org rules gitignore: up to date");
@@ -43674,12 +43526,12 @@ async function findInFlightHotfixVersion(deps, ctx, latestMainTag, workflows = H
43674
43526
  }
43675
43527
 
43676
43528
  // src/hotfix-coverage.ts
43677
- var import_node_child_process20 = require("node:child_process");
43529
+ var import_node_child_process19 = require("node:child_process");
43678
43530
  var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
43679
43531
  function checkHotfixCoverage(options = {}) {
43680
43532
  const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
43681
43533
  const ack = (options.ack ?? []).filter(Boolean);
43682
- const git3 = options.git ?? ((args, opts) => (0, import_node_child_process20.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
43534
+ const git3 = options.git ?? ((args, opts) => (0, import_node_child_process19.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
43683
43535
  const revList = (range) => {
43684
43536
  const out = git3(["rev-list", "--no-merges", range]).trim();
43685
43537
  return out ? out.split("\n") : [];
@@ -43747,7 +43599,7 @@ function checkHotfixCoverage(options = {}) {
43747
43599
  }
43748
43600
  function checkHotfixCarries(options) {
43749
43601
  const { cwd = process.cwd(), branch, baseRef, targets } = options;
43750
- const git3 = options.git ?? ((args, opts) => (0, import_node_child_process20.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
43602
+ const git3 = options.git ?? ((args, opts) => (0, import_node_child_process19.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
43751
43603
  const isAncestor = (sha, ref) => {
43752
43604
  try {
43753
43605
  git3(["merge-base", "--is-ancestor", sha, ref]);
@@ -43779,8 +43631,8 @@ function checkHotfixCarries(options) {
43779
43631
  }
43780
43632
 
43781
43633
  // src/train-commands.ts
43782
- var import_node_fs49 = require("node:fs");
43783
- var import_node_path46 = require("node:path");
43634
+ var import_node_fs47 = require("node:fs");
43635
+ var import_node_path45 = require("node:path");
43784
43636
  var INVOKED_ARGV = process.argv.slice(2);
43785
43637
  var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
43786
43638
  function resolveReleaseBumpIntent(raw) {
@@ -43792,7 +43644,7 @@ function resolveReleaseBumpIntent(raw) {
43792
43644
  }
43793
43645
  function readRepoVersion() {
43794
43646
  try {
43795
- return JSON.parse((0, import_node_fs49.readFileSync)((0, import_node_path46.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
43647
+ return JSON.parse((0, import_node_fs47.readFileSync)((0, import_node_path45.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
43796
43648
  } catch {
43797
43649
  return void 0;
43798
43650
  }
@@ -44127,21 +43979,6 @@ function hotfixFollowUpLegs(runs, foldPort, alignment, foldNote, deployNote) {
44127
43979
  }
44128
43980
  return legs;
44129
43981
  }
44130
- var JERV_POWERTOOLS_REPO = "mutmutco/Jerv-PowerTools";
44131
- async function runPostReleaseJervDoctor(repo) {
44132
- if (repo.toLowerCase() !== JERV_POWERTOOLS_REPO.toLowerCase()) return void 0;
44133
- try {
44134
- await execJervCli(["doctor"], { timeout: 10 * 6e4 });
44135
- return { status: "completed", note: "jerv-cli doctor completed on this owner machine" };
44136
- } catch (e) {
44137
- const err = e;
44138
- const detail = (err.stderr?.trim() || err.message || "unknown doctor failure").split(/\r?\n/)[0];
44139
- return {
44140
- status: "reported-issues",
44141
- note: `jerv-cli doctor ran but reported issues (${detail})`
44142
- };
44143
- }
44144
- }
44145
43982
  async function runProjectInfoSyncLeg(cb, repo, sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms))) {
44146
43983
  for (let attempt = 0; ; attempt++) {
44147
43984
  try {
@@ -44206,9 +44043,6 @@ function renderTrainApply(commandName, r) {
44206
44043
  if (r.projectInfoSync) {
44207
44044
  base = `${base}; project info: ${r.projectInfoSync.note}`;
44208
44045
  }
44209
- if (r.postReleaseJervDoctor) {
44210
- base = `${base}; Jerv convergence: ${r.postReleaseJervDoctor.note}`;
44211
- }
44212
44046
  if (r.announceNote) base = `${base}; announce: ${r.announceNote}`;
44213
44047
  if (r.releaseVerdict) {
44214
44048
  const v = r.releaseVerdict;
@@ -44410,7 +44244,6 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
44410
44244
  const raw = await runTrainApply(commandName, trainApplyDeps(), { watch: o.watch, announceSummaryFile: o.announceSummaryFile, ack, dev: o.dev });
44411
44245
  const result = raw.workflowRuns ? { ...raw, workflowRuns: raw.workflowRuns.map(workflowRunWithEvidence) } : raw;
44412
44246
  let projectInfoSync;
44413
- const postReleaseJervDoctor = commandName === "release" ? await runPostReleaseJervDoctor(result.repo) : void 0;
44414
44247
  if (commandName === "release") {
44415
44248
  projectInfoSync = await runProjectInfoSyncLeg(runProjectInfoSyncCallback, result.repo);
44416
44249
  }
@@ -44418,7 +44251,6 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
44418
44251
  const reported = {
44419
44252
  ...result,
44420
44253
  ...projectInfoSync ? { projectInfoSync } : {},
44421
- ...postReleaseJervDoctor ? { postReleaseJervDoctor } : {},
44422
44254
  ...releaseVerdict ? { releaseVerdict } : {}
44423
44255
  };
44424
44256
  const output = o.json ? JSON.stringify(reported, null, 2) : renderTrainApply(commandName, reported);
@@ -44491,7 +44323,6 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
44491
44323
  ...r.checkout ? [` - checkout: ${r.checkout.note}`] : [],
44492
44324
  ...r.localSync && localTrainSyncBannerLine(r.localSync) ? [` - local sync: ${localTrainSyncBannerLine(r.localSync)}`] : [],
44493
44325
  ...r.projectInfoSync ? [` - project info: ${r.projectInfoSync.note}`] : [],
44494
- ...r.postReleaseJervDoctor ? [` - Jerv convergence: ${r.postReleaseJervDoctor.note}`] : [],
44495
44326
  ` - next: mmi-cli devops hotfix status ${r.tag} (no back-merge of the FIX \u2014 development already has it; the version fold above is ported for you, #4410)`,
44496
44327
  ...r.ledger ? formatReleaseLedgerReport(r.ledger).map((line) => ` ${line}`) : []
44497
44328
  ].join("\n");
@@ -44552,9 +44383,8 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
44552
44383
  hotfixCmd.command("start").description("cherry-pick one or more merged development PRs (or SHAs) onto hotfix/vX.Y.Z from origin/main, bump the distribution, open the main-base PR").requiredOption("--from <pr#|sha[,pr#|sha...]>", "merged development PR number(s) or commit SHA(s) to cherry-pick, in pick order \u2014 one hotfix cycle carries as many fixes as you name (#4411)").option("--json", "machine-readable output").option("--out <path>", "write the result to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5983/#6068)").action(async (o) => runHotfixSub("start", () => runHotfixStart(trainApplyDeps(), { from: o.from }), o, renderHotfixStart));
44553
44384
  hotfixCmd.command("release <version>").description("after the hotfix PR is merged + checks green: tag, GitHub Release, watch deploy/publish, verify distribution (idempotent)").option("--json", "machine-readable output").option("--announce-summary-file <path>", "agent-curated 3-6 line release Slack summary; required for a NEW MMI-Hub hotfix Release (#883/#3901/#6068), optional for a product repo announcing to its project release channel (#6517)").option("--carries <pr#|sha[,pr#|sha...]>", "declared fix target(s) this hotfix must carry; each must be proven present before tagging (#3056)").option("--out <path>", "write the result to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5983/#6068)").action(async (version, o) => runHotfixSub("release", async () => {
44554
44385
  const result = await runHotfixRelease(trainApplyDeps(), version, { announceSummaryFile: o.announceSummaryFile, carries: o.carries ? [o.carries] : [] });
44555
- const postReleaseJervDoctor = await runPostReleaseJervDoctor(result.repo);
44556
44386
  const projectInfoSync = await runProjectInfoSyncLeg(runProjectInfoSyncCallback, result.repo);
44557
- return { ...result, projectInfoSync, ...postReleaseJervDoctor ? { postReleaseJervDoctor } : {} };
44387
+ return { ...result, projectInfoSync };
44558
44388
  }, o, renderHotfixRelease));
44559
44389
  function hotfixStatusDeps() {
44560
44390
  const STATUS_GH_MS = 8e3;
@@ -44592,12 +44422,12 @@ ${r.stderr ?? ""}`).catch(() => "");
44592
44422
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
44593
44423
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
44594
44424
  function envHealLockPath(home) {
44595
- return (0, import_node_path47.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
44425
+ return (0, import_node_path46.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
44596
44426
  }
44597
44427
  async function withEnvHealLock(what, run) {
44598
44428
  try {
44599
44429
  return await withFileLock(
44600
- envHealLockPath((0, import_node_os22.homedir)()),
44430
+ envHealLockPath((0, import_node_os21.homedir)()),
44601
44431
  { staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
44602
44432
  run
44603
44433
  );
@@ -44693,7 +44523,7 @@ function mmiDoctorDeps(opts = {}) {
44693
44523
  const configRoot = surfaceConfigRoot(surface);
44694
44524
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
44695
44525
  const plan = buildPluginCachePlan(
44696
- (0, import_node_os22.homedir)(),
44526
+ (0, import_node_os21.homedir)(),
44697
44527
  running,
44698
44528
  pluginCacheFsDeps(configRoot, () => 0),
44699
44529
  { configRoot, includeStaging: surface !== "codex" }
@@ -44721,14 +44551,14 @@ function mmiDoctorDeps(opts = {}) {
44721
44551
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
44722
44552
  const installed = installedActivePluginVersion(surface);
44723
44553
  const plan = buildPluginCachePlan(
44724
- (0, import_node_os22.homedir)(),
44554
+ (0, import_node_os21.homedir)(),
44725
44555
  running,
44726
44556
  pluginCacheFsDeps(configRoot, () => 0),
44727
44557
  { configRoot, includeStaging: surface !== "codex", installedVersion: installed }
44728
44558
  );
44729
44559
  const result = applyPluginCachePlan(
44730
44560
  plan,
44731
- (p) => (0, import_node_fs50.rmSync)(p, { recursive: true }),
44561
+ (p) => (0, import_node_fs48.rmSync)(p, { recursive: true }),
44732
44562
  stagingApplyFsGuard(configRoot)
44733
44563
  );
44734
44564
  return {
@@ -44763,7 +44593,7 @@ function mmiDoctorDeps(opts = {}) {
44763
44593
  // has no generated routing index would
44764
44594
  // get a permanent — demanding an artifact it never asked for.
44765
44595
  docsIndexState: (root) => {
44766
- if (!(0, import_node_fs50.existsSync)((0, import_node_path47.join)(root, DOCS_INDEX_PATH))) return void 0;
44596
+ if (!(0, import_node_fs48.existsSync)((0, import_node_path46.join)(root, DOCS_INDEX_PATH))) return void 0;
44767
44597
  const real = createDocsIndexDeps(root);
44768
44598
  let docs;
44769
44599
  const listDocs = () => docs ??= real.listDocs();
@@ -44772,7 +44602,7 @@ function mmiDoctorDeps(opts = {}) {
44772
44602
  },
44773
44603
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
44774
44604
  healDocsIndex: (root) => {
44775
- if (!(0, import_node_fs50.existsSync)((0, import_node_path47.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
44605
+ if (!(0, import_node_fs48.existsSync)((0, import_node_path46.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
44776
44606
  const real = createDocsIndexDeps(root);
44777
44607
  let docs;
44778
44608
  const listDocs = () => docs ??= real.listDocs();
@@ -45398,7 +45228,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
45398
45228
  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`);
45399
45229
  if (o.secretsFile) {
45400
45230
  try {
45401
- vars.push(`secrets=${(0, import_node_fs50.readFileSync)(o.secretsFile, "utf8")}`);
45231
+ vars.push(`secrets=${(0, import_node_fs48.readFileSync)(o.secretsFile, "utf8")}`);
45402
45232
  } catch (e) {
45403
45233
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
45404
45234
  }
@@ -45720,16 +45550,16 @@ function ciAuditDeps2() {
45720
45550
  // gate re-seed step is skipped gracefully rather than failing mid-run.
45721
45551
  readSeedFile: (path2) => {
45722
45552
  if (!root) return null;
45723
- const fullPath = (0, import_node_path47.join)(root, path2);
45724
- return (0, import_node_fs50.existsSync)(fullPath) ? (0, import_node_fs50.readFileSync)(fullPath, "utf8") : null;
45553
+ const fullPath = (0, import_node_path46.join)(root, path2);
45554
+ return (0, import_node_fs48.existsSync)(fullPath) ? (0, import_node_fs48.readFileSync)(fullPath, "utf8") : null;
45725
45555
  }
45726
45556
  };
45727
45557
  }
45728
45558
  function hubRoot2() {
45729
- const fromPkg = (0, import_node_path47.join)(__dirname, "..", "..");
45559
+ const fromPkg = (0, import_node_path46.join)(__dirname, "..", "..");
45730
45560
  const marker = "skills/bootstrap/seeds/manifest.json";
45731
- if ((0, import_node_fs50.existsSync)((0, import_node_path47.join)(fromPkg, marker))) return fromPkg;
45732
- if ((0, import_node_fs50.existsSync)((0, import_node_path47.join)(process.cwd(), marker))) return process.cwd();
45561
+ if ((0, import_node_fs48.existsSync)((0, import_node_path46.join)(fromPkg, marker))) return fromPkg;
45562
+ if ((0, import_node_fs48.existsSync)((0, import_node_path46.join)(process.cwd(), marker))) return process.cwd();
45733
45563
  return null;
45734
45564
  }
45735
45565
  registerQueryCommands(program2);
@@ -45829,10 +45659,10 @@ access.command("audit").description("audit collaborator roles + train-branch pus
45829
45659
  targets = resolution.targets;
45830
45660
  }
45831
45661
  const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
45832
- const fileMatrix = (0, import_node_fs50.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs50.readFileSync)("access-matrix.json", "utf8")) : {};
45662
+ const fileMatrix = (0, import_node_fs48.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs48.readFileSync)("access-matrix.json", "utf8")) : {};
45833
45663
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
45834
45664
  const dataAccess = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
45835
- const sanctioned = (0, import_node_fs50.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs50.readFileSync)("access-matrix.json", "utf8")) : {};
45665
+ const sanctioned = (0, import_node_fs48.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs48.readFileSync)("access-matrix.json", "utf8")) : {};
45836
45666
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
45837
45667
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
45838
45668
  if (!report.ok) process.exitCode = 1;
@@ -45863,16 +45693,16 @@ function directoryBytes(path2) {
45863
45693
  let total = 0;
45864
45694
  let entries;
45865
45695
  try {
45866
- entries = (0, import_node_fs50.readdirSync)(path2, { withFileTypes: true });
45696
+ entries = (0, import_node_fs48.readdirSync)(path2, { withFileTypes: true });
45867
45697
  } catch {
45868
45698
  return 0;
45869
45699
  }
45870
45700
  for (const entry of entries) {
45871
- const child2 = (0, import_node_path47.join)(path2, entry.name);
45701
+ const child2 = (0, import_node_path46.join)(path2, entry.name);
45872
45702
  if (entry.isDirectory()) total += directoryBytes(child2);
45873
45703
  else {
45874
45704
  try {
45875
- total += (0, import_node_fs50.statSync)(child2).size;
45705
+ total += (0, import_node_fs48.statSync)(child2).size;
45876
45706
  } catch {
45877
45707
  }
45878
45708
  }
@@ -45880,25 +45710,25 @@ function directoryBytes(path2) {
45880
45710
  return total;
45881
45711
  }
45882
45712
  function listDirEntries(dir) {
45883
- return (0, import_node_fs50.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
45713
+ return (0, import_node_fs48.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
45884
45714
  }
45885
45715
  function readInstalledPluginRefs(configRoot) {
45886
45716
  const p = installedPluginsPathForConfig(configRoot);
45887
- if (!(0, import_node_fs50.existsSync)(p)) return [];
45717
+ if (!(0, import_node_fs48.existsSync)(p)) return [];
45888
45718
  try {
45889
- return installedPluginPaths((0, import_node_fs50.readFileSync)(p, "utf8"));
45719
+ return installedPluginPaths((0, import_node_fs48.readFileSync)(p, "utf8"));
45890
45720
  } catch {
45891
45721
  return null;
45892
45722
  }
45893
45723
  }
45894
45724
  function pluginCacheFsDeps(configRoot, dirBytes) {
45895
45725
  return {
45896
- exists: (p) => (0, import_node_fs50.existsSync)(p),
45897
- listVersionDirs: (root) => (0, import_node_fs50.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
45726
+ exists: (p) => (0, import_node_fs48.existsSync)(p),
45727
+ listVersionDirs: (root) => (0, import_node_fs48.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
45898
45728
  dirBytes,
45899
- listStagingDirs: (root) => (0, import_node_fs50.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
45729
+ listStagingDirs: (root) => (0, import_node_fs48.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
45900
45730
  try {
45901
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path47.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs50.statSync)(p).mtimeMs) };
45731
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path46.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs48.statSync)(p).mtimeMs) };
45902
45732
  } catch {
45903
45733
  return { name: d.name, mtimeMs: Date.now() };
45904
45734
  }
@@ -45912,10 +45742,10 @@ function stagingApplyFsGuard(configRoot) {
45912
45742
  return {
45913
45743
  referencedPaths: () => readInstalledPluginRefs(configRoot),
45914
45744
  mtimeMs: (name) => {
45915
- const p = (0, import_node_path47.join)(stagingRoot, name);
45916
- if (!(0, import_node_fs50.existsSync)(p)) return null;
45745
+ const p = (0, import_node_path46.join)(stagingRoot, name);
45746
+ if (!(0, import_node_fs48.existsSync)(p)) return null;
45917
45747
  try {
45918
- return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs50.statSync)(q).mtimeMs);
45748
+ return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs48.statSync)(q).mtimeMs);
45919
45749
  } catch {
45920
45750
  return null;
45921
45751
  }
@@ -45935,13 +45765,13 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
45935
45765
  return;
45936
45766
  }
45937
45767
  const plan = buildPluginCachePlan(
45938
- (0, import_node_os22.homedir)(),
45768
+ (0, import_node_os21.homedir)(),
45939
45769
  running,
45940
45770
  pluginCacheFsDeps(configRoot, directoryBytes),
45941
45771
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
45942
45772
  );
45943
45773
  const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
45944
- const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs50.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
45774
+ const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs48.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
45945
45775
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
45946
45776
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
45947
45777
  else console.log(renderPluginCachePlan(plan, result));