@mutmutco/cli 4.5.42 → 4.5.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.cjs +379 -189
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -5496,8 +5496,8 @@ function resolveVerbAliasShim(argv) {
5496
5496
  }
5497
5497
 
5498
5498
  // src/command-composition.ts
5499
- var import_node_os22 = require("node:os");
5500
- var import_node_path51 = require("node:path");
5499
+ var import_node_os23 = require("node:os");
5500
+ var import_node_path52 = require("node:path");
5501
5501
 
5502
5502
  // src/board-read.ts
5503
5503
  var import_node_fs13 = require("node:fs");
@@ -16871,10 +16871,10 @@ var rollout_plan_default = {
16871
16871
  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)."
16872
16872
  },
16873
16873
  baseline: {
16874
- version: "4.5.42",
16875
- tag: "v4.5.42",
16876
- commit: "448720f2bc43",
16877
- npm: "@mutmutco/cli@4.5.42"
16874
+ version: "4.5.43",
16875
+ tag: "v4.5.43",
16876
+ commit: "daaa2fa607cd",
16877
+ npm: "@mutmutco/cli@4.5.43"
16878
16878
  },
16879
16879
  exitCriterion: "fleet-n-of-n",
16880
16880
  hubOnlyShortcut: "forbidden",
@@ -16891,14 +16891,14 @@ var rollout_plan_default = {
16891
16891
  repo: "mutmutco/mmi-hub",
16892
16892
  role: "canary",
16893
16893
  schedule: "train",
16894
- v3Target: "v4.5.42"
16894
+ v3Target: "v4.5.43"
16895
16895
  }
16896
16896
  ],
16897
16897
  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.",
16898
16898
  rollback: {
16899
16899
  independent: true,
16900
- mechanism: "npm dist-tag latest -> 4.5.42 and redeploy the Hub Lambda from tag v4.5.42 (448720f2bc43); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
16901
- v3Target: "v4.5.42 (@mutmutco/cli@4.5.42, tag commit 448720f2bc43 \u2014 last known-good release carrying the repo-index v4-only contract)"
16900
+ mechanism: "npm dist-tag latest -> 4.5.43 and redeploy the Hub Lambda from tag v4.5.43 (daaa2fa607cd); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
16901
+ v3Target: "v4.5.43 (@mutmutco/cli@4.5.43, tag commit daaa2fa607cd \u2014 last known-good release carrying the repo-index v4-only contract)"
16902
16902
  }
16903
16903
  },
16904
16904
  {
@@ -29577,8 +29577,8 @@ function registerBoardCommands(program3) {
29577
29577
 
29578
29578
  // src/bootstrap-commands.ts
29579
29579
  var import_node_fs28 = require("node:fs");
29580
- var import_node_os16 = require("node:os");
29581
- var import_node_path27 = require("node:path");
29580
+ var import_node_os17 = require("node:os");
29581
+ var import_node_path28 = require("node:path");
29582
29582
  init_cli_shared();
29583
29583
  init_clean_exit();
29584
29584
 
@@ -29890,6 +29890,122 @@ async function assignPersistedPortRange(repo, slug, reg, opts) {
29890
29890
 
29891
29891
  // src/box-commands.ts
29892
29892
  var import_node_fs27 = require("node:fs");
29893
+ var import_node_child_process10 = require("node:child_process");
29894
+ var import_node_os16 = require("node:os");
29895
+ var import_node_path27 = require("node:path");
29896
+
29897
+ // src/box-control.ts
29898
+ var import_node_crypto8 = require("node:crypto");
29899
+ var MANIFEST_PATH = "infra/box-control/manifest.json";
29900
+ var ALLOWED_POST = /* @__PURE__ */ new Set(["systemctl daemon-reload"]);
29901
+ function parseManifest(text) {
29902
+ const raw = JSON.parse(text);
29903
+ if (!Array.isArray(raw.files)) throw new Error('box control manifest: "files" must be an array');
29904
+ const seen = /* @__PURE__ */ new Set();
29905
+ return raw.files.map((f, i) => {
29906
+ const where = `box control manifest: files[${i}]`;
29907
+ if (typeof f.src !== "string" || !f.src || f.src.startsWith("/") || f.src.includes("..")) throw new Error(`${where}: src must be a repo-relative path`);
29908
+ if (f.mode !== "0644" && f.mode !== "0755") throw new Error(`${where} (${f.src}): mode must be "0644" or "0755"`);
29909
+ if (f.post !== void 0 && (typeof f.post !== "string" || !ALLOWED_POST.has(f.post))) {
29910
+ throw new Error(`${where} (${f.src}): post must be one of ${[...ALLOWED_POST].join(", ")}`);
29911
+ }
29912
+ const targets = [];
29913
+ if (Array.isArray(f.targets)) targets.push(...f.targets);
29914
+ if (f.lanes !== void 0) targets.push(...expandLanes(f.lanes, where));
29915
+ if (!targets.length) throw new Error(`${where} (${f.src}): needs targets or lanes`);
29916
+ for (const t of targets) {
29917
+ if (typeof t.box !== "string" || !/^[a-z0-9-]+$/.test(t.box)) throw new Error(`${where} (${f.src}): bad box name`);
29918
+ if (typeof t.dest !== "string" || !/^\/[A-Za-z0-9._\/-]+$/.test(t.dest) || t.dest.includes("..")) {
29919
+ throw new Error(`${where} (${f.src}): dest must be an absolute path of plain characters`);
29920
+ }
29921
+ if (t.dest.startsWith("/opt/mmi-control/secrets") || t.dest.endsWith(".env")) {
29922
+ throw new Error(`${where} (${f.src}): ${t.dest} is vault-owned and cannot be a manifest destination`);
29923
+ }
29924
+ const key = `${t.box}:${t.dest}`;
29925
+ if (seen.has(key)) throw new Error(`${where} (${f.src}): duplicate destination ${key}`);
29926
+ seen.add(key);
29927
+ }
29928
+ return { src: f.src, mode: f.mode, ...f.post ? { post: f.post } : {}, targets };
29929
+ });
29930
+ }
29931
+ function expandLanes(l, where) {
29932
+ if (!l || typeof l.box !== "string" || !Number.isInteger(l.from) || !Number.isInteger(l.to) || l.from < 1 || l.to < l.from || typeof l.dest !== "string" || !l.dest.includes("{N}")) {
29933
+ throw new Error(`${where}: lanes needs box, integer from <= to, and a dest containing {N}`);
29934
+ }
29935
+ const out = [];
29936
+ for (let n = l.from; n <= l.to; n += 1) out.push({ box: l.box, dest: l.dest.replace("{N}", String(n)) });
29937
+ return out;
29938
+ }
29939
+ function filesForBox(files, box) {
29940
+ return files.flatMap((file) => file.targets.filter((t) => t.box === box).map((t) => ({ file, dest: t.dest })));
29941
+ }
29942
+ function md5(content) {
29943
+ return (0, import_node_crypto8.createHash)("md5").update(content).digest("hex");
29944
+ }
29945
+ function planRemoteScript(dests) {
29946
+ const lines2 = ["set -u"];
29947
+ for (const d of dests) {
29948
+ lines2.push(`if [ -f '${d}' ]; then printf '%s %s %s\\n' "$(md5sum < '${d}' | cut -d' ' -f1)" "$(stat -c %a '${d}')" '${d}'; else printf 'MISSING - %s\\n' '${d}'; fi`);
29949
+ }
29950
+ return `${lines2.join("\n")}
29951
+ `;
29952
+ }
29953
+ function parsePlanOutput(output, rows) {
29954
+ const seen = /* @__PURE__ */ new Map();
29955
+ for (const line of output.split("\n")) {
29956
+ const m = /^([0-9a-f]{32}|MISSING) (\d{3,4}|-) (\/\S+)$/.exec(line.trim());
29957
+ if (m) seen.set(m[3], { md5: m[1], mode: m[2] });
29958
+ }
29959
+ return rows.map(({ file, dest, expectedMd5 }) => {
29960
+ const expectedMode = file.mode.replace(/^0/, "");
29961
+ const got = seen.get(dest);
29962
+ const base = { src: file.src, dest, expectedMd5, expectedMode: file.mode };
29963
+ if (!got) return { ...base, status: "unread", installedMd5: null, installedMode: null };
29964
+ if (got.md5 === "MISSING") return { ...base, status: "missing", installedMd5: null, installedMode: null };
29965
+ const status = got.md5 !== expectedMd5 ? "drift" : got.mode !== expectedMode ? "mode-drift" : "in-sync";
29966
+ return { ...base, status, installedMd5: got.md5, installedMode: `0${got.mode}` };
29967
+ });
29968
+ }
29969
+ function selectApplyRows(rows, sel) {
29970
+ const unknown = sel.only.filter((s) => !rows.some((r) => r.file.src === s));
29971
+ if (unknown.length) return `not a manifest src for this box: ${unknown.join(", ")}`;
29972
+ const chosen = rows.filter((r) => sel.only.includes(r.file.src));
29973
+ const strayDest = sel.dest.filter((d) => !chosen.some((r) => r.dest === d));
29974
+ if (strayDest.length) return `--dest is not a destination of the chosen --only source(s): ${strayDest.join(", ")}`;
29975
+ const out = [];
29976
+ for (const src of sel.only) {
29977
+ const targets = chosen.filter((r) => r.file.src === src);
29978
+ if (targets.length === 1 || sel.allTargets) {
29979
+ out.push(...targets);
29980
+ continue;
29981
+ }
29982
+ const named = targets.filter((r) => sel.dest.includes(r.dest));
29983
+ if (!named.length) {
29984
+ return `${src} has ${targets.length} destinations on this box; name each with --dest <path>, or pass --all-targets`;
29985
+ }
29986
+ out.push(...named);
29987
+ }
29988
+ return out;
29989
+ }
29990
+ function backupPath(dest, date) {
29991
+ if (dest.startsWith("/etc/cron.d/")) return `/root/${dest.slice("/etc/cron.d/".length)}.cron.bak-${date}`;
29992
+ return `${dest}.bak-${date}`;
29993
+ }
29994
+ function applyRemoteScript(items, date) {
29995
+ const lines2 = ["set -eu", "tmp=$(mktemp)", `trap 'rm -f "$tmp"' EXIT`];
29996
+ for (const it of items) {
29997
+ const b64 = Buffer.from(it.content).toString("base64");
29998
+ lines2.push(`if [ -f '${it.dest}' ]; then cp -p '${it.dest}' '${backupPath(it.dest, date)}'; fi`);
29999
+ lines2.push(`printf '%s' '${b64}' | base64 -d > "$tmp"`);
30000
+ lines2.push(`install -D -m ${it.mode} "$tmp" '${it.dest}'`);
30001
+ }
30002
+ for (const post of [...new Set(items.map((i) => i.post).filter((p) => !!p))]) lines2.push(post);
30003
+ lines2.push(planRemoteScript(items.map((i) => i.dest)).replace(/^set -u\n/, ""));
30004
+ return `${lines2.join("\n")}
30005
+ `;
30006
+ }
30007
+
30008
+ // src/box-commands.ts
29893
30009
  init_clean_exit();
29894
30010
 
29895
30011
  // src/secrets-commands.ts
@@ -31479,6 +31595,80 @@ ${SSH_RECIPE_AGENT_NOTE}`);
31479
31595
  await failGraceful(e.message);
31480
31596
  }
31481
31597
  });
31598
+ box.command("control <name>").description("box-side control files (#7402): --plan (default, read-only) reports drift from the repo; --apply --only <src> installs with backups").option("--plan", "read-only drift report (the default)").option("--apply", "install the files named by --only on this box, backing up each previous copy").option("--only <src>", "with --apply: a manifest src to install (repeatable; approval is file by file)", (v, acc) => [...acc, v], []).option("--dest <path>", "with --apply: a destination of a multi-target --only source to install (repeatable, #7409)", (v, acc) => [...acc, v], []).option("--all-targets", "with --apply: install a multi-target --only source to every one of its destinations on this box").option("--ref <ref>", "git ref the repo content is read from", "origin/development").option("--json", "machine-readable output").action(async (name, o) => {
31599
+ try {
31600
+ if (o.apply && o.plan) throw new UsageError("box control: --plan and --apply are exclusive");
31601
+ if (o.apply && !o.only.length) throw new UsageError("box control: --apply needs --only <src> for each file to install; approval is file by file");
31602
+ if (!o.apply && (o.only.length || o.dest.length || o.allTargets)) throw new UsageError("box control: --only, --dest and --all-targets apply to --apply");
31603
+ const show = hubGitShow(o.ref);
31604
+ const files = parseManifest(show(MANIFEST_PATH).toString("utf8"));
31605
+ const { boxes, incomplete } = await fetchInventory();
31606
+ const found = lookupBox(name, boxes, incomplete);
31607
+ if (found.kind !== "found") {
31608
+ const why = found.kind === "unknown" ? `the inventory is incomplete (${found.reasons.join("; ")})` : `no box named '${name}'`;
31609
+ throw new UnreadableError(`box control: ${why}`);
31610
+ }
31611
+ const rows = filesForBox(files, found.box.name).map(({ file, dest }) => {
31612
+ const content = show(file.src);
31613
+ return { file, dest, content, expectedMd5: md5(content) };
31614
+ });
31615
+ if (!rows.length) throw new UsageError(`box control: ${MANIFEST_PATH} lists no files for ${found.box.name}`);
31616
+ let probeRows = rows;
31617
+ if (o.apply) {
31618
+ const picked = selectApplyRows(rows, { only: o.only, dest: o.dest, allTargets: !!o.allTargets });
31619
+ if (typeof picked === "string") throw new UsageError(`box control: ${picked}`);
31620
+ probeRows = picked;
31621
+ }
31622
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
31623
+ const script = o.apply ? applyRemoteScript(probeRows.map((r) => ({ dest: r.dest, mode: r.file.mode, content: r.content, post: r.file.post })), date) : planRemoteScript(probeRows.map((r) => r.dest));
31624
+ const output = runOnBox(found.box, script);
31625
+ const results = parsePlanOutput(output, probeRows);
31626
+ const drift = results.filter((r) => r.status !== "in-sync").length;
31627
+ const unread = results.some((r) => r.status === "unread");
31628
+ const payload = { box: found.box.name, ref: o.ref, mode: o.apply ? "apply" : "plan", files: results, drift, ok: drift === 0 };
31629
+ if (o.json) console.log(JSON.stringify(payload, null, 2));
31630
+ else console.log(formatControl(payload.mode, found.box.name, results));
31631
+ process.exitCode = unread ? 2 : drift ? 1 : 0;
31632
+ } catch (e) {
31633
+ if (o.json) console.log(JSON.stringify({ box: name, ref: o.ref, ok: false, error: e.message }, null, 2));
31634
+ else console.error(e.message);
31635
+ process.exitCode = 2;
31636
+ }
31637
+ });
31638
+ }
31639
+ var UsageError = class extends Error {
31640
+ };
31641
+ var UnreadableError = class extends Error {
31642
+ };
31643
+ function hubGitShow(ref) {
31644
+ const git3 = (args) => (0, import_node_child_process10.execFileSync)("git", args, { maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
31645
+ try {
31646
+ git3(["cat-file", "-e", `HEAD:${MANIFEST_PATH}`]);
31647
+ } catch {
31648
+ throw new UsageError(`box control: run this from an MMI-Hub checkout (no ${MANIFEST_PATH} here)`);
31649
+ }
31650
+ if (ref.startsWith("origin/")) git3(["fetch", "--quiet", "origin"]);
31651
+ return (path2) => git3(["show", `${ref}:${path2}`]);
31652
+ }
31653
+ function runOnBox(found, script) {
31654
+ const dir = (0, import_node_fs27.mkdtempSync)((0, import_node_path27.join)((0, import_node_os16.tmpdir)(), "mmi-box-control-"));
31655
+ try {
31656
+ const recipe = (0, import_node_path27.join)(dir, "recipe.sh");
31657
+ (0, import_node_fs27.writeFileSync)(recipe, sshRecipeScript(found, "sh -s"), "utf8");
31658
+ const r = (0, import_node_child_process10.spawnSync)("bash", [recipe], { input: script, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 18e4, windowsHide: true });
31659
+ if (r.status !== 0) {
31660
+ throw new UnreadableError(`box control: the ssh session to ${found.name} failed (exit ${r.status ?? r.signal}): ${(r.stderr || "").trim().split("\n").slice(-3).join(" | ")}`);
31661
+ }
31662
+ return r.stdout;
31663
+ } finally {
31664
+ (0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
31665
+ }
31666
+ }
31667
+ function formatControl(mode, box, rows) {
31668
+ const lines2 = rows.map((r) => `${r.status.padEnd(10)} ${r.dest} <- ${r.src}`);
31669
+ const bad = rows.filter((r) => r.status !== "in-sync").length;
31670
+ lines2.push(`${box}: ${mode} \u2014 ${rows.length} file(s), ${bad} not in sync`);
31671
+ return lines2.join("\n");
31482
31672
  }
31483
31673
 
31484
31674
  // src/bootstrap-box-ports.ts
@@ -31599,7 +31789,7 @@ function renderDeployPortDoctor(report) {
31599
31789
  }
31600
31790
 
31601
31791
  // src/bootstrap-drift.ts
31602
- var import_node_crypto8 = require("node:crypto");
31792
+ var import_node_crypto9 = require("node:crypto");
31603
31793
  function byteComparableSeeds(manifest, cls) {
31604
31794
  return manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self" && s.classes.includes(cls));
31605
31795
  }
@@ -31619,7 +31809,7 @@ function compareSeedBytes(hubContent, repoContent) {
31619
31809
  return normalize(hubContent) === normalize(repoContent) ? "match" : "drift";
31620
31810
  }
31621
31811
  function seedContentHash(content) {
31622
- return (0, import_node_crypto8.createHash)("sha256").update(content.replace(/\r\n/g, "\n"), "utf8").digest("hex");
31812
+ return (0, import_node_crypto9.createHash)("sha256").update(content.replace(/\r\n/g, "\n"), "utf8").digest("hex");
31623
31813
  }
31624
31814
  function auditRepoSeedDrift(repo, seeds, hubContents, repoReads) {
31625
31815
  const byTarget = new Map(repoReads.map((r) => [r.target, r.content]));
@@ -31781,7 +31971,7 @@ function renderPropagationReport(plan) {
31781
31971
  }
31782
31972
 
31783
31973
  // src/bootstrap-propagation-identity.ts
31784
- var import_node_crypto9 = require("node:crypto");
31974
+ var import_node_crypto10 = require("node:crypto");
31785
31975
  var PROPAGATION_BRANCH_PREFIX = "seed-propagate-";
31786
31976
  var TARGET_MARKER_NAME = "mmi-bootstrap-propagation-target";
31787
31977
  function safeBranchPart(value, maxLength, fallback) {
@@ -31794,7 +31984,7 @@ function repoSlug2(repo) {
31794
31984
  function propagationBranch(repo, target) {
31795
31985
  const repoPart = safeBranchPart(repoSlug2(repo), 32, "repo");
31796
31986
  const targetPart = safeBranchPart(target, 48, "target");
31797
- const hash = (0, import_node_crypto9.createHash)("sha256").update(repo.trim().toLowerCase()).update("\0").update(target).digest("hex").slice(0, 12);
31987
+ const hash = (0, import_node_crypto10.createHash)("sha256").update(repo.trim().toLowerCase()).update("\0").update(target).digest("hex").slice(0, 12);
31798
31988
  return `${PROPAGATION_BRANCH_PREFIX}${repoPart}-${targetPart}-${hash}`;
31799
31989
  }
31800
31990
  function legacyPropagationBranch(repo) {
@@ -32950,7 +33140,7 @@ function renderBootstrapVerifyReport(report) {
32950
33140
  }
32951
33141
 
32952
33142
  // src/bootstrap-seed-delivery.ts
32953
- var import_node_crypto10 = require("node:crypto");
33143
+ var import_node_crypto11 = require("node:crypto");
32954
33144
  init_github_client();
32955
33145
  var SHA = /^[a-f0-9]{40}$/;
32956
33146
  async function readSeedFile(repo, target, ref, client) {
@@ -32983,7 +33173,7 @@ async function targetedSeedPlan(repo, slug, target, baseBranch, sourceSha, clien
32983
33173
  }
32984
33174
  const baseSha = base?.object?.sha;
32985
33175
  if (!baseSha || !SHA.test(baseSha) || !SHA.test(sourceSha)) throw new Error("bootstrap apply: seed identity is unreadable");
32986
- const identity = (0, import_node_crypto10.createHash)("sha256").update(JSON.stringify([repo.toLowerCase(), target, baseSha, sourceSha])).digest("hex").slice(0, 24);
33176
+ const identity = (0, import_node_crypto11.createHash)("sha256").update(JSON.stringify([repo.toLowerCase(), target, baseSha, sourceSha])).digest("hex").slice(0, 24);
32987
33177
  return { ...planSeedDelivery(rules, slug, baseBranch, `bootstrap-seed-${identity}`), baseSha, baseBranch };
32988
33178
  }
32989
33179
  async function verifyTargetedSeedBranch(repo, plan, target, client, allowMissing = false) {
@@ -33378,7 +33568,7 @@ function registerBootstrapCommands(program3) {
33378
33568
  const readFile9 = (p) => (0, import_node_fs28.existsSync)(p) ? (0, import_node_fs28.readFileSync)(p, "utf8") : null;
33379
33569
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
33380
33570
  const putSeed = async (target, content, ref, sha) => {
33381
- const tmp = (0, import_node_path27.join)((0, import_node_os16.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
33571
+ const tmp = (0, import_node_path28.join)((0, import_node_os17.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
33382
33572
  (0, import_node_fs28.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
33383
33573
  try {
33384
33574
  await gh2(contentPutInputArgs(repo, target, tmp));
@@ -34125,7 +34315,7 @@ LIVE apply to ${repo}:
34125
34315
  } catch {
34126
34316
  existingSha = void 0;
34127
34317
  }
34128
- const tmp = (0, import_node_path27.join)((0, import_node_os16.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
34318
+ const tmp = (0, import_node_path28.join)((0, import_node_os17.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
34129
34319
  const desiredContent = desiredByRepo.get(rec.repo);
34130
34320
  if (desiredContent == null) return fail(`bootstrap propagate: no resolved content for ${rec.repo} ${seed.target} \u2014 refusing to write`);
34131
34321
  (0, import_node_fs28.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha)), "utf8");
@@ -34300,7 +34490,7 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
34300
34490
  } catch {
34301
34491
  existingSha = void 0;
34302
34492
  }
34303
- const tmp = (0, import_node_path27.join)((0, import_node_os16.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
34493
+ const tmp = (0, import_node_path28.join)((0, import_node_os17.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
34304
34494
  (0, import_node_fs28.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
34305
34495
  try {
34306
34496
  await gh2(contentPutInputArgs(repo, seed.target, tmp));
@@ -34586,8 +34776,8 @@ function formatSuiteStatus(report) {
34586
34776
 
34587
34777
  // src/suite-train.ts
34588
34778
  var import_node_fs29 = require("node:fs");
34589
- var import_node_path28 = require("node:path");
34590
- var import_node_crypto11 = require("node:crypto");
34779
+ var import_node_path29 = require("node:path");
34780
+ var import_node_crypto12 = require("node:crypto");
34591
34781
  var SCHEMA = "mmi-suite-cut/v1";
34592
34782
  var SHA2 = /^[a-f0-9]{40}$/i;
34593
34783
  var RC_TAG = /^v\d+\.\d+\.\d+-rc\.\d+$/;
@@ -34622,8 +34812,8 @@ function readSuiteCut(path2) {
34622
34812
  return record;
34623
34813
  }
34624
34814
  function writeSuiteCut(path2, record) {
34625
- (0, import_node_fs29.mkdirSync)((0, import_node_path28.dirname)(path2), { recursive: true });
34626
- const temp = `${path2}.${(0, import_node_crypto11.randomBytes)(8).toString("hex")}.tmp`;
34815
+ (0, import_node_fs29.mkdirSync)((0, import_node_path29.dirname)(path2), { recursive: true });
34816
+ const temp = `${path2}.${(0, import_node_crypto12.randomBytes)(8).toString("hex")}.tmp`;
34627
34817
  try {
34628
34818
  (0, import_node_fs29.writeFileSync)(temp, JSON.stringify(record, null, 2), { flag: "wx" });
34629
34819
  (0, import_node_fs29.renameSync)(temp, path2);
@@ -34828,7 +35018,7 @@ async function suiteRelease(deps, ownerGo) {
34828
35018
 
34829
35019
  // src/suite-train-io.ts
34830
35020
  var import_node_fs43 = require("node:fs");
34831
- var import_node_path42 = require("node:path");
35021
+ var import_node_path43 = require("node:path");
34832
35022
  init_cli_shared();
34833
35023
 
34834
35024
  // src/command-register-train-operations.ts
@@ -35108,9 +35298,9 @@ A hotfix branch is cut from origin/main and carries ONLY the fixes --from names,
35108
35298
  async function preflightHotfixBatchPicks(deps, sources, pickTolerated) {
35109
35299
  if (sources.length === 0) return { failures: [], skipped: [] };
35110
35300
  const { mkdtemp: mkdtemp2, rm: rm2 } = await import("node:fs/promises");
35111
- const { tmpdir: tmpdir10 } = await import("node:os");
35112
- const { join: join44 } = await import("node:path");
35113
- const dir = await mkdtemp2(join44(tmpdir10(), "mmi-hotfix-preflight-"));
35301
+ const { tmpdir: tmpdir11 } = await import("node:os");
35302
+ const { join: join45 } = await import("node:path");
35303
+ const dir = await mkdtemp2(join45(tmpdir11(), "mmi-hotfix-preflight-"));
35114
35304
  const wt = { run: (file, args) => deps.run(file, file === "git" ? ["-C", dir, ...args] : args) };
35115
35305
  const failures = [];
35116
35306
  const skipped = [];
@@ -36309,13 +36499,13 @@ async function findInFlightHotfixVersion(deps, ctx, latestMainTag, workflows = H
36309
36499
  }
36310
36500
 
36311
36501
  // src/hotfix-coverage.ts
36312
- var import_node_child_process10 = require("node:child_process");
36502
+ var import_node_child_process11 = require("node:child_process");
36313
36503
  var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
36314
36504
  var GIT_MAX_BUFFER = 512 * 1024 * 1024;
36315
36505
  function checkHotfixCoverage(options = {}) {
36316
36506
  const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
36317
36507
  const ack = (options.ack ?? []).filter(Boolean);
36318
- const git3 = options.git ?? ((args, opts) => (0, import_node_child_process10.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
36508
+ const git3 = options.git ?? ((args, opts) => (0, import_node_child_process11.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
36319
36509
  const revList = (range) => {
36320
36510
  const out = git3(["rev-list", "--no-merges", range]).trim();
36321
36511
  return out ? out.split("\n") : [];
@@ -36383,7 +36573,7 @@ function checkHotfixCoverage(options = {}) {
36383
36573
  }
36384
36574
  function checkHotfixCarries(options) {
36385
36575
  const { cwd = process.cwd(), branch, baseRef, targets } = options;
36386
- const git3 = options.git ?? ((args, opts) => (0, import_node_child_process10.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
36576
+ const git3 = options.git ?? ((args, opts) => (0, import_node_child_process11.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
36387
36577
  const isAncestor = (sha, ref) => {
36388
36578
  try {
36389
36579
  git3(["merge-base", "--is-ancestor", sha, ref]);
@@ -36416,8 +36606,8 @@ function checkHotfixCarries(options) {
36416
36606
 
36417
36607
  // src/merge-cleanup.ts
36418
36608
  var import_node_fs31 = require("node:fs");
36419
- var import_node_path30 = require("node:path");
36420
- var import_node_os17 = require("node:os");
36609
+ var import_node_path31 = require("node:path");
36610
+ var import_node_os18 = require("node:os");
36421
36611
  init_cli_shared();
36422
36612
  init_github_client();
36423
36613
 
@@ -36706,12 +36896,12 @@ async function runPrLand(prNumber, options, deps) {
36706
36896
  }
36707
36897
 
36708
36898
  // src/test-policy-core.ts
36709
- var import_node_child_process12 = require("node:child_process");
36899
+ var import_node_child_process13 = require("node:child_process");
36710
36900
  var import_node_fs30 = require("node:fs");
36711
- var import_node_path29 = require("node:path");
36901
+ var import_node_path30 = require("node:path");
36712
36902
 
36713
36903
  // src/test-command-policy-shared.mjs
36714
- var import_node_child_process11 = require("node:child_process");
36904
+ var import_node_child_process12 = require("node:child_process");
36715
36905
  var TEST_COMMAND_CLASS = "test";
36716
36906
  var TRAILER_KEY = "Test-Policy-Override";
36717
36907
  var OVERRIDE_RE = /^Test-Policy-Override:\s*(.+)$/im;
@@ -36828,7 +37018,7 @@ function evaluateTestCommandPolicy({ paths, mandatory, regulated = true, overrid
36828
37018
  };
36829
37019
  }
36830
37020
  function git(args, cwd) {
36831
- return (0, import_node_child_process11.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37021
+ return (0, import_node_child_process12.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
36832
37022
  }
36833
37023
  function parseScope(value) {
36834
37024
  const scoped = /^\[([^\]]*)\]\s*([\s\S]*)$/.exec(value);
@@ -37184,7 +37374,7 @@ function isMeaningfulRow(file) {
37184
37374
  return file.meaningful !== false;
37185
37375
  }
37186
37376
  function loadPolicy(root, readFile9 = readFileOrNull2) {
37187
- const raw = readFile9((0, import_node_path29.join)(root, POLICY_FILE));
37377
+ const raw = readFile9((0, import_node_path30.join)(root, POLICY_FILE));
37188
37378
  if (raw == null) return { mandatory: [], declared: false };
37189
37379
  return parsePolicy(raw, POLICY_FILE);
37190
37380
  }
@@ -37290,11 +37480,11 @@ function classify(changed, policy, present = () => false) {
37290
37480
  return { mandatoryHits, untestedHits, testChanges, meaningfulTestChanges, addedTests, removedProtected };
37291
37481
  }
37292
37482
  function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs30.existsSync)(path2)) {
37293
- return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path29.join)(root, p)));
37483
+ return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path30.join)(root, p)));
37294
37484
  }
37295
37485
  function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs30.existsSync)(path2)) {
37296
37486
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
37297
- return [...new Set(declared)].filter((p) => !exists((0, import_node_path29.join)(root, p)));
37487
+ return [...new Set(declared)].filter((p) => !exists((0, import_node_path30.join)(root, p)));
37298
37488
  }
37299
37489
  function evaluate(changed, policy, present = () => false) {
37300
37490
  const { mandatoryHits, untestedHits, meaningfulTestChanges, addedTests, removedProtected } = classify(changed, policy, present);
@@ -37327,14 +37517,14 @@ function evaluate(changed, policy, present = () => false) {
37327
37517
  return findings;
37328
37518
  }
37329
37519
  function git2(args, cwd) {
37330
- return (0, import_node_child_process12.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37520
+ return (0, import_node_child_process13.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
37331
37521
  }
37332
37522
  var COAUTHOR_KEY = "Co-authored-by";
37333
37523
  var GH_MESSAGE_SEPARATOR = /^-{5,}$/;
37334
37524
  var LIFTED_KEYS = new RegExp(`^(?:${TRAILER_KEY}|${COAUTHOR_KEY}):`, "i");
37335
37525
  function parseTrailers(message2, cwd) {
37336
37526
  try {
37337
- return (0, import_node_child_process12.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
37527
+ return (0, import_node_child_process13.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
37338
37528
  windowsHide: true,
37339
37529
  cwd,
37340
37530
  input: message2,
@@ -37440,7 +37630,7 @@ function runTestPolicy(root, deps = {}) {
37440
37630
  const raw = deps.changed ?? (refusal ? [] : changedFilesSince(base, root));
37441
37631
  const changed = deps.changed ? raw : annotateChangeMeaning(raw, policy, (path2) => ({
37442
37632
  before: blobAt(base, path2, root),
37443
- after: readFileOrNull2((0, import_node_path29.join)(root, path2))
37633
+ after: readFileOrNull2((0, import_node_path30.join)(root, path2))
37444
37634
  }));
37445
37635
  const lookup = deps.override !== void 0 ? { override: deps.override, refusals: [] } : !deps.changed && !refusal ? readOverride2(base, root) : { override: null, refusals: [] };
37446
37636
  const policyRefusals = policy.declared === false ? [{
@@ -37450,8 +37640,8 @@ function runTestPolicy(root, deps = {}) {
37450
37640
  A gate with no policy cannot decide which test commands are required or permitted.
37451
37641
  ` + (deps.base === HOTFIX_DIFF_BASE ? ` Hotfix lane (--base ${HOTFIX_DIFF_BASE}): pass --policy-ref <exact-${HOTFIX_POLICY_REF}-commit> so the current policy is read from ${HOTFIX_POLICY_REF}.` : ` Restore ${POLICY_FILE} on this branch; the policy file belongs on every non-hotfix lane.`)
37452
37642
  }] : [];
37453
- const present = (path2) => exists((0, import_node_path29.join)(root, path2));
37454
- const policyTree = policySource.sha ? new Set(git2(["ls-tree", "-r", "-z", "--name-only", policySource.sha], root).split("\0").filter(Boolean).map((p) => (0, import_node_path29.join)(root, p))) : null;
37643
+ const present = (path2) => exists((0, import_node_path30.join)(root, path2));
37644
+ const policyTree = policySource.sha ? new Set(git2(["ls-tree", "-r", "-z", "--name-only", policySource.sha], root).split("\0").filter(Boolean).map((p) => (0, import_node_path30.join)(root, p))) : null;
37455
37645
  const policyTreeExists = policyTree ? (abs) => policyTree.has(abs) : exists;
37456
37646
  const where = policySource.sha ? `${policySource.ref}@${policySource.sha}` : "this worktree";
37457
37647
  const removedByThisDiff = removedPaths(changed);
@@ -37696,8 +37886,8 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
37696
37886
  return rewritten === base ? null : rewritten;
37697
37887
  }
37698
37888
  function writeSquashBodyFile(body) {
37699
- const dir = (0, import_node_fs31.mkdtempSync)((0, import_node_path30.join)((0, import_node_os17.tmpdir)(), "mmi-squash-body-"));
37700
- const path2 = (0, import_node_path30.join)(dir, "body.txt");
37889
+ const dir = (0, import_node_fs31.mkdtempSync)((0, import_node_path31.join)((0, import_node_os18.tmpdir)(), "mmi-squash-body-"));
37890
+ const path2 = (0, import_node_path31.join)(dir, "body.txt");
37701
37891
  (0, import_node_fs31.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
37702
37892
  `, "utf8");
37703
37893
  return { path: path2, cleanup: () => {
@@ -37910,7 +38100,7 @@ async function deleteMergedRemoteBranch(options) {
37910
38100
 
37911
38101
  // src/project-info-sync.ts
37912
38102
  var import_node_fs32 = require("node:fs");
37913
- var import_node_path31 = require("node:path");
38103
+ var import_node_path32 = require("node:path");
37914
38104
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
37915
38105
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
37916
38106
  projectV2 { id }
@@ -37957,7 +38147,7 @@ function sharedName(entries, fallback) {
37957
38147
  }
37958
38148
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
37959
38149
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
37960
- const readmePath = (0, import_node_path31.join)(repoRoot2, "README.md");
38150
+ const readmePath = (0, import_node_path32.join)(repoRoot2, "README.md");
37961
38151
  if (!(0, import_node_fs32.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
37962
38152
  const entries = entriesFor(project2, projects);
37963
38153
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
@@ -37983,8 +38173,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
37983
38173
  const targetBase = `https://github.com/${targetRepo2}`;
37984
38174
  const targetBranch = branchFor(targetRepo2, projects);
37985
38175
  const orgDocs = [
37986
- (0, import_node_fs32.existsSync)((0, import_node_path31.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
37987
- (0, import_node_fs32.existsSync)((0, import_node_path31.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
38176
+ (0, import_node_fs32.existsSync)((0, import_node_path32.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
38177
+ (0, import_node_fs32.existsSync)((0, import_node_path32.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
37988
38178
  ].filter(Boolean);
37989
38179
  if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
37990
38180
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
@@ -38007,7 +38197,7 @@ async function syncProjectInfo(plan, client, apply) {
38007
38197
 
38008
38198
  // src/train-commands.ts
38009
38199
  var import_node_fs33 = require("node:fs");
38010
- var import_node_path32 = require("node:path");
38200
+ var import_node_path33 = require("node:path");
38011
38201
  init_cli_shared();
38012
38202
  init_clean_exit();
38013
38203
  init_client_version();
@@ -38022,7 +38212,7 @@ function resolveReleaseBumpIntent(raw) {
38022
38212
  }
38023
38213
  function readRepoVersion() {
38024
38214
  try {
38025
- return JSON.parse((0, import_node_fs33.readFileSync)((0, import_node_path32.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
38215
+ return JSON.parse((0, import_node_fs33.readFileSync)((0, import_node_path33.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
38026
38216
  } catch {
38027
38217
  return void 0;
38028
38218
  }
@@ -38133,7 +38323,7 @@ function releaseProgressVerdict(status, subject = "Release") {
38133
38323
 
38134
38324
  // src/suite-pin.ts
38135
38325
  var import_promises5 = require("node:fs/promises");
38136
- var import_node_path33 = require("node:path");
38326
+ var import_node_path34 = require("node:path");
38137
38327
  async function openSuiteCutPinPr(deps, input) {
38138
38328
  if (!/^[a-f0-9]{40}$/.test(input.cut) || !input.pins.length) throw new Error("suite pin PR needs an anchored cut and at least one module");
38139
38329
  const ids = input.pins.map((p) => p.module);
@@ -38169,15 +38359,15 @@ async function openSuiteCutPinPr(deps, input) {
38169
38359
  const row = rows.find((r) => r.id === p.module);
38170
38360
  return row?.bundles.rc === p.rc && row?.bundles.main === p.main;
38171
38361
  })) throw new Error("pins already match without a merged cut PR \u2014 provenance unverified");
38172
- await (0, import_promises5.mkdir)((0, import_node_path33.join)(deps.root, "tmp"), { recursive: true });
38173
- scratch = await (0, import_promises5.mkdtemp)((0, import_node_path33.join)(deps.root, "tmp", "suite-pin-"));
38362
+ await (0, import_promises5.mkdir)((0, import_node_path34.join)(deps.root, "tmp"), { recursive: true });
38363
+ scratch = await (0, import_promises5.mkdtemp)((0, import_node_path34.join)(deps.root, "tmp", "suite-pin-"));
38174
38364
  const run = (file, args) => deps.run(file, args, scratch);
38175
38365
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
38176
38366
  if ((await run("git", ["rev-parse", "HEAD"])).trim().toLowerCase() !== input.cut.toLowerCase())
38177
38367
  throw new Error("MM-Work development moved after the suite snapshot; no pin PR opened");
38178
38368
  await run("git", ["switch", "-c", branch]);
38179
38369
  for (const stage of ["rc", "main"]) {
38180
- const path2 = (0, import_node_path33.join)(scratch, `${stage}-pins.json`);
38370
+ const path2 = (0, import_node_path34.join)(scratch, `${stage}-pins.json`);
38181
38371
  await (0, import_promises5.writeFile)(path2, JSON.stringify(input.pins.map((p) => ({ module: p.module, url: p[stage] }))));
38182
38372
  await run("node", ["scripts/pin-modules.mjs", "--stage", stage, "--pins", path2]);
38183
38373
  }
@@ -38223,8 +38413,8 @@ async function openSuitePinPr(deps, input) {
38223
38413
  url.searchParams.set("v", tag);
38224
38414
  const pin = url.toString();
38225
38415
  const branch = `suite-pin/${stage}-${member.id}-${tag}`;
38226
- await (0, import_promises5.mkdir)((0, import_node_path33.join)(deps.root, "tmp"), { recursive: true });
38227
- scratch = await (0, import_promises5.mkdtemp)((0, import_node_path33.join)(deps.root, "tmp", "suite-pin-"));
38416
+ await (0, import_promises5.mkdir)((0, import_node_path34.join)(deps.root, "tmp"), { recursive: true });
38417
+ scratch = await (0, import_promises5.mkdtemp)((0, import_node_path34.join)(deps.root, "tmp", "suite-pin-"));
38228
38418
  const run = (file, args) => deps.run(file, args, scratch);
38229
38419
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
38230
38420
  const existing = JSON.parse(await run("gh", ["pr", "list", "--repo", SUITE_REPO, "--head", branch, "--state", "all", "--json", "url,state"]));
@@ -38267,7 +38457,7 @@ async function openSuitePinPr(deps, input) {
38267
38457
  }
38268
38458
 
38269
38459
  // src/command-register-collaboration.ts
38270
- var import_node_child_process16 = require("node:child_process");
38460
+ var import_node_child_process17 = require("node:child_process");
38271
38461
  var import_node_fs42 = require("node:fs");
38272
38462
  var import_promises7 = require("node:fs/promises");
38273
38463
  init_clean_exit();
@@ -38292,11 +38482,11 @@ function spawnDetachedSelf(args, deps, opts = {}) {
38292
38482
  }
38293
38483
 
38294
38484
  // src/command-register-collaboration.ts
38295
- var import_node_path41 = require("node:path");
38485
+ var import_node_path42 = require("node:path");
38296
38486
  init_house_map();
38297
38487
 
38298
38488
  // src/issue-body.ts
38299
- var import_node_os18 = require("node:os");
38489
+ var import_node_os19 = require("node:os");
38300
38490
  init_error_codes();
38301
38491
  var TextArgError = class extends Error {
38302
38492
  constructor(message2, code, offendingFlag) {
@@ -38309,7 +38499,7 @@ var TextArgError = class extends Error {
38309
38499
  offendingFlag;
38310
38500
  };
38311
38501
  function emptyStdinMessage(fileFlag) {
38312
- if ((0, import_node_os18.platform)() === "win32") {
38502
+ if ((0, import_node_os19.platform)() === "win32") {
38313
38503
  return `${fileFlag} - read empty stdin (on Windows, ${fileFlag} - is unreliable through the npm .cmd shim \u2014 use ${fileFlag} <path>, or pipe to \`node cli/dist/index.cjs\` directly)`;
38314
38504
  }
38315
38505
  return `${fileFlag} - read empty stdin (nothing piped \u2014 pass a heredoc/pipe, or ${fileFlag} <path>)`;
@@ -38402,7 +38592,7 @@ init_github_client();
38402
38592
 
38403
38593
  // src/issue-commands.ts
38404
38594
  var import_node_fs34 = require("node:fs");
38405
- var import_node_crypto12 = require("node:crypto");
38595
+ var import_node_crypto13 = require("node:crypto");
38406
38596
  init_cli_shared();
38407
38597
  init_clean_exit();
38408
38598
  init_error_codes();
@@ -38875,7 +39065,7 @@ function rowIdempotencyKey(batchKey, spec) {
38875
39065
  const identity = `${spec.type}
38876
39066
  ${spec.title.trim()}
38877
39067
  ${spec.body ?? ""}`;
38878
- const hash = (0, import_node_crypto12.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
39068
+ const hash = (0, import_node_crypto13.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
38879
39069
  return `${batchKey}:${hash}`;
38880
39070
  }
38881
39071
  var BATCH_SPEC_KEYS = /* @__PURE__ */ new Set(["type", "title", "body", "priority", "labels", "label", "parent", "repo", "surface"]);
@@ -39335,7 +39525,7 @@ ${lines2}`, {
39335
39525
 
39336
39526
  // src/post-merge-recon.ts
39337
39527
  var import_node_fs35 = require("node:fs");
39338
- var import_node_path34 = require("node:path");
39528
+ var import_node_path35 = require("node:path");
39339
39529
 
39340
39530
  // src/cross-repo-filing-issue.ts
39341
39531
  init_github_client();
@@ -39502,7 +39692,7 @@ function buildPostMergeReconRecovery(input) {
39502
39692
  }
39503
39693
  function writePostMergeReconRecovery(cwd, recovery) {
39504
39694
  const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
39505
- (0, import_node_fs35.mkdirSync)((0, import_node_path34.dirname)(path2), { recursive: true });
39695
+ (0, import_node_fs35.mkdirSync)((0, import_node_path35.dirname)(path2), { recursive: true });
39506
39696
  (0, import_node_fs35.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
39507
39697
  `, "utf8");
39508
39698
  return path2;
@@ -39937,10 +40127,10 @@ function registerPrLifecycleCommands(program3) {
39937
40127
  }
39938
40128
 
39939
40129
  // src/review-verdict.ts
39940
- var import_node_child_process13 = require("node:child_process");
40130
+ var import_node_child_process14 = require("node:child_process");
39941
40131
  var import_node_fs36 = require("node:fs");
39942
- var import_node_os19 = require("node:os");
39943
- var import_node_path35 = require("node:path");
40132
+ var import_node_os20 = require("node:os");
40133
+ var import_node_path36 = require("node:path");
39944
40134
  init_cli_shared();
39945
40135
  var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
39946
40136
  var REVIEW_VERDICTS = ["PROCEED", "CORRECT", "ESCALATE"];
@@ -40037,8 +40227,8 @@ async function checkPrReview(number, repo, head, deps = {
40037
40227
  }
40038
40228
  function computePrPatchId(number, repo) {
40039
40229
  return new Promise((resolve7, reject) => {
40040
- const gh2 = (0, import_node_child_process13.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
40041
- const git3 = (0, import_node_child_process13.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
40230
+ const gh2 = (0, import_node_child_process14.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
40231
+ const git3 = (0, import_node_child_process14.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
40042
40232
  let out = "";
40043
40233
  let ghErr = "";
40044
40234
  let gitErr = "";
@@ -40105,8 +40295,8 @@ async function readPrIssueComments(number, repo) {
40105
40295
  return comments;
40106
40296
  }
40107
40297
  async function postPrCommentFromFile(number, repo, body) {
40108
- const dir = (0, import_node_fs36.mkdtempSync)((0, import_node_path35.join)((0, import_node_os19.tmpdir)(), "mmi-review-verdict-"));
40109
- const path2 = (0, import_node_path35.join)(dir, "body.md");
40298
+ const dir = (0, import_node_fs36.mkdtempSync)((0, import_node_path36.join)((0, import_node_os20.tmpdir)(), "mmi-review-verdict-"));
40299
+ const path2 = (0, import_node_path36.join)(dir, "body.md");
40110
40300
  try {
40111
40301
  (0, import_node_fs36.writeFileSync)(path2, body, "utf8");
40112
40302
  const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
@@ -40120,7 +40310,7 @@ async function postPrCommentFromFile(number, repo, body) {
40120
40310
  }
40121
40311
 
40122
40312
  // src/pr-create-docs-check.ts
40123
- var import_node_child_process14 = require("node:child_process");
40313
+ var import_node_child_process15 = require("node:child_process");
40124
40314
  init_cli_shared();
40125
40315
  var GIT_TIMEOUT_MS2 = 15e3;
40126
40316
  function catFileBatch(root, ref, paths) {
@@ -40128,7 +40318,7 @@ function catFileBatch(root, ref, paths) {
40128
40318
  return new Promise((resolve7) => {
40129
40319
  const chunks = [];
40130
40320
  let settled = false;
40131
- const child2 = (0, import_node_child_process14.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
40321
+ const child2 = (0, import_node_child_process15.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
40132
40322
  const finish = () => {
40133
40323
  if (settled) return;
40134
40324
  settled = true;
@@ -40340,17 +40530,17 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
40340
40530
 
40341
40531
  // src/worktree-residue-sweep.ts
40342
40532
  var import_node_fs41 = require("node:fs");
40343
- var import_node_path40 = require("node:path");
40533
+ var import_node_path41 = require("node:path");
40344
40534
 
40345
40535
  // src/worktree-merge-cleanup.ts
40346
40536
  var import_node_fs40 = require("node:fs");
40347
- var import_node_path39 = require("node:path");
40537
+ var import_node_path40 = require("node:path");
40348
40538
  init_cli_shared();
40349
40539
 
40350
40540
  // src/stage-runner.ts
40351
- var import_node_child_process15 = require("node:child_process");
40541
+ var import_node_child_process16 = require("node:child_process");
40352
40542
  var import_node_fs38 = require("node:fs");
40353
- var import_node_path37 = require("node:path");
40543
+ var import_node_path38 = require("node:path");
40354
40544
  var import_node_net = require("node:net");
40355
40545
  var import_node_util5 = require("node:util");
40356
40546
 
@@ -40361,7 +40551,7 @@ function normalizeEol2(s) {
40361
40551
 
40362
40552
  // src/env-detection.ts
40363
40553
  var import_node_fs37 = require("node:fs");
40364
- var import_node_path36 = require("node:path");
40554
+ var import_node_path37 = require("node:path");
40365
40555
  var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
40366
40556
  function isEnvBaseName(name) {
40367
40557
  return name.toLowerCase() === ".env";
@@ -40379,13 +40569,13 @@ function findEnvFiles(root) {
40379
40569
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
40380
40570
  if (entry.isDirectory()) {
40381
40571
  if (SKIPPED_DIRS.has(entry.name)) continue;
40382
- walk2((0, import_node_path36.join)(dir, entry.name), relPath);
40572
+ walk2((0, import_node_path37.join)(dir, entry.name), relPath);
40383
40573
  continue;
40384
40574
  }
40385
40575
  if (isEnvBaseName(entry.name)) {
40386
40576
  let isDir = false;
40387
40577
  try {
40388
- isDir = (0, import_node_fs37.lstatSync)((0, import_node_path36.join)(dir, entry.name)).isDirectory();
40578
+ isDir = (0, import_node_fs37.lstatSync)((0, import_node_path37.join)(dir, entry.name)).isDirectory();
40389
40579
  } catch {
40390
40580
  }
40391
40581
  if (!isDir) found.push(relPath);
@@ -40442,15 +40632,15 @@ function stageComposeFileEnv(files) {
40442
40632
  }
40443
40633
 
40444
40634
  // src/stage-runner.ts
40445
- var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process15.execFile);
40635
+ var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process16.execFile);
40446
40636
  var DOCKER_TIMEOUT_MS = 15e3;
40447
40637
  function stageBash() {
40448
40638
  if (process.platform !== "win32") return "bash";
40449
40639
  const configured = process.env.SHELL;
40450
- if (configured && (0, import_node_path37.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs38.existsSync)(configured)) return configured;
40640
+ if (configured && (0, import_node_path38.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs38.existsSync)(configured)) return configured;
40451
40641
  const candidates = [
40452
- (0, import_node_path37.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
40453
- ...process.env.LOCALAPPDATA ? [(0, import_node_path37.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
40642
+ (0, import_node_path38.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
40643
+ ...process.env.LOCALAPPDATA ? [(0, import_node_path38.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
40454
40644
  ];
40455
40645
  const bash = candidates.find((path2) => (0, import_node_fs38.existsSync)(path2));
40456
40646
  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.");
@@ -40583,7 +40773,7 @@ function appendForceRecreate(up) {
40583
40773
  return `${up.trimEnd()} --force-recreate`;
40584
40774
  }
40585
40775
  function stageStatePath(cwd = process.cwd()) {
40586
- return (0, import_node_path37.join)(cwd, "tmp", "stage", "state.json");
40776
+ return (0, import_node_path38.join)(cwd, "tmp", "stage", "state.json");
40587
40777
  }
40588
40778
  function normPath(path2) {
40589
40779
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -40800,7 +40990,7 @@ function stageProcessEnv(stagePort, extraEnv) {
40800
40990
  }
40801
40991
  function composeResolvesPort(cwd) {
40802
40992
  if (process.env.PORT) return true;
40803
- const envFile = (0, import_node_path37.join)(cwd, ".env");
40993
+ const envFile = (0, import_node_path38.join)(cwd, ".env");
40804
40994
  return (0, import_node_fs38.existsSync)(envFile) && envFileKeys((0, import_node_fs38.readFileSync)(envFile, "utf8")).has("PORT");
40805
40995
  }
40806
40996
  function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
@@ -40814,13 +41004,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
40814
41004
  function stageComposeFiles(cwd) {
40815
41005
  const files = ["docker-compose.yml"];
40816
41006
  for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
40817
- if ((0, import_node_fs38.existsSync)((0, import_node_path37.join)(cwd, conventional))) files.push(conventional);
41007
+ if ((0, import_node_fs38.existsSync)((0, import_node_path38.join)(cwd, conventional))) files.push(conventional);
40818
41008
  }
40819
41009
  return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
40820
41010
  }
40821
41011
  async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
40822
41012
  const keys = Object.keys(vaultEnvMerge ?? {});
40823
- if (!keys.length || !(0, import_node_fs38.existsSync)((0, import_node_path37.join)(cwd, "docker-compose.yml"))) return {};
41013
+ if (!keys.length || !(0, import_node_fs38.existsSync)((0, import_node_path38.join)(cwd, "docker-compose.yml"))) return {};
40824
41014
  let configJson;
40825
41015
  try {
40826
41016
  const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
@@ -40836,15 +41026,15 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
40836
41026
  }
40837
41027
  const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys);
40838
41028
  if (!body) return {};
40839
- const overridePath = (0, import_node_path37.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
40840
- (0, import_node_fs38.mkdirSync)((0, import_node_path37.join)(cwd, "tmp", "stage"), { recursive: true });
41029
+ const overridePath = (0, import_node_path38.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
41030
+ (0, import_node_fs38.mkdirSync)((0, import_node_path38.join)(cwd, "tmp", "stage"), { recursive: true });
40841
41031
  (0, import_node_fs38.writeFileSync)(overridePath, body, "utf8");
40842
41032
  return stageComposeFileEnv(stageComposeFiles(cwd));
40843
41033
  }
40844
41034
  async function ensureStageRuntimeEnv(config, opts, cwd) {
40845
41035
  if (!config.ensureEnv) return;
40846
- const target = (0, import_node_path37.join)(cwd, config.ensureEnv.target);
40847
- const example = (0, import_node_path37.join)(cwd, config.ensureEnv.example);
41036
+ const target = (0, import_node_path38.join)(cwd, config.ensureEnv.target);
41037
+ const example = (0, import_node_path38.join)(cwd, config.ensureEnv.example);
40848
41038
  if (!(0, import_node_fs38.existsSync)(target) && (0, import_node_fs38.existsSync)(example)) {
40849
41039
  (0, import_node_fs38.copyFileSync)(example, target);
40850
41040
  } else if ((0, import_node_fs38.existsSync)(target) && (0, import_node_fs38.existsSync)(example)) {
@@ -41025,7 +41215,7 @@ async function startStage(config = {}, opts = {}) {
41025
41215
  let up = sub(config.up.trim());
41026
41216
  if (opts.forceRecreate) up = appendForceRecreate(up);
41027
41217
  const identity = await resolveStageIdentity(cwd);
41028
- const child2 = (0, import_node_child_process15.spawn)(bash, ["-c", up], {
41218
+ const child2 = (0, import_node_child_process16.spawn)(bash, ["-c", up], {
41029
41219
  cwd,
41030
41220
  // POSIX-only: the process group exists for the group-kill in stopStage. On win32 teardown is
41031
41221
  // `taskkill /T /F` (no group needed), and detached+shell defeats windowsHide — every spawn would
@@ -41135,7 +41325,7 @@ async function runStage(config = {}, opts = {}) {
41135
41325
 
41136
41326
  // src/worktree-evidence-archive.ts
41137
41327
  var import_node_fs39 = require("node:fs");
41138
- var import_node_path38 = require("node:path");
41328
+ var import_node_path39 = require("node:path");
41139
41329
  var JERV_ARTIFACT_RUN_SCOPE_ENV_VARS = ["JERV_RUN_ID", ...SESSION_ID_ENV_VARS];
41140
41330
  function sanitizeArchiveSegment(value, max = 80) {
41141
41331
  const scrubbed = value.replace(/[^A-Za-z0-9._@+-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -41167,7 +41357,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
41167
41357
  const resolveRoot = deps.resolveArchiveRoot ?? repoRuntimeStatePath;
41168
41358
  if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
41169
41359
  if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
41170
- const source = (0, import_node_path38.join)(args.worktreePath, ".jerv");
41360
+ const source = (0, import_node_path39.join)(args.worktreePath, ".jerv");
41171
41361
  if (!exists(source)) return { status: "absent" };
41172
41362
  if (!isDirectory(source)) return { status: "skipped", reason: "jerv-not-a-directory" };
41173
41363
  const runScope = resolveArtifactRunScope(env);
@@ -41175,7 +41365,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
41175
41365
  const stamp = now().toISOString().replace(/[:.]/g, "-");
41176
41366
  const dest = resolveRoot(args.primaryRoot, "jerv-artifacts", runScope, branchSlug, stamp, ".jerv");
41177
41367
  try {
41178
- mkdirp((0, import_node_path38.dirname)(dest));
41368
+ mkdirp((0, import_node_path39.dirname)(dest));
41179
41369
  copyDir(source, dest);
41180
41370
  if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
41181
41371
  return { status: "archived", path: dest, runScope };
@@ -41191,7 +41381,7 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
41191
41381
  const exists = deps.exists ?? import_node_fs39.existsSync;
41192
41382
  const stat4 = deps.stat ?? defaultStat;
41193
41383
  const readdir2 = deps.readdir ?? import_node_fs39.readdirSync;
41194
- const tmpRoot = (0, import_node_path38.join)(worktreePath, "tmp");
41384
+ const tmpRoot = (0, import_node_path39.join)(worktreePath, "tmp");
41195
41385
  if (!exists(tmpRoot)) return [];
41196
41386
  const entries = [];
41197
41387
  const walk2 = (dir) => {
@@ -41202,14 +41392,14 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
41202
41392
  return;
41203
41393
  }
41204
41394
  for (const name of names) {
41205
- const full = (0, import_node_path38.join)(dir, name);
41395
+ const full = (0, import_node_path39.join)(dir, name);
41206
41396
  let st;
41207
41397
  try {
41208
41398
  st = stat4(full);
41209
41399
  } catch {
41210
41400
  continue;
41211
41401
  }
41212
- const relPath = (0, import_node_path38.relative)(worktreePath, full).replace(/\\/g, "/");
41402
+ const relPath = (0, import_node_path39.relative)(worktreePath, full).replace(/\\/g, "/");
41213
41403
  if (st.isDirectory()) {
41214
41404
  if (st.mtimeMs > newerThanMs) entries.push({ relPath, bytes: 0, mtimeMs: st.mtimeMs });
41215
41405
  walk2(full);
@@ -41234,7 +41424,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
41234
41424
  if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
41235
41425
  if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
41236
41426
  const scanned = scanWorktreeTmpEvidence(args.worktreePath, args.newerThanMs, deps);
41237
- const source = (0, import_node_path38.join)(args.worktreePath, "tmp");
41427
+ const source = (0, import_node_path39.join)(args.worktreePath, "tmp");
41238
41428
  if (!scanned.length) return { status: "absent" };
41239
41429
  if (!exists(source)) return { status: "absent" };
41240
41430
  const runScope = resolveArtifactRunScope(env);
@@ -41242,7 +41432,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
41242
41432
  const stamp = now().toISOString().replace(/[:.]/g, "-");
41243
41433
  const dest = resolveRoot(args.primaryRoot, "worktree-artifacts", runScope, branchSlug, stamp, "tmp");
41244
41434
  try {
41245
- mkdirp((0, import_node_path38.dirname)(dest));
41435
+ mkdirp((0, import_node_path39.dirname)(dest));
41246
41436
  copyDir(source, dest);
41247
41437
  if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
41248
41438
  const bytes = scanned.reduce((sum, e) => sum + e.bytes, 0);
@@ -41311,7 +41501,7 @@ function normPath2(p) {
41311
41501
  return p.replace(/\\/g, "/").replace(/\/+$/, "");
41312
41502
  }
41313
41503
  function unlinkNodeModulesJunction(wtPath) {
41314
- const nm = (0, import_node_path39.join)(wtPath, "node_modules");
41504
+ const nm = (0, import_node_path40.join)(wtPath, "node_modules");
41315
41505
  try {
41316
41506
  if ((0, import_node_fs40.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs40.rmdirSync)(nm);
41317
41507
  return { ok: true };
@@ -41448,7 +41638,7 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
41448
41638
  }
41449
41639
  async function listNestedIgnoredNodeModules(wtPath, execGit) {
41450
41640
  const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
41451
- 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)));
41641
+ return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path40.join)(wtPath, line.slice(0, -1)));
41452
41642
  }
41453
41643
  function safeRemoveTree(path2) {
41454
41644
  const stat4 = (0, import_node_fs40.lstatSync)(path2);
@@ -41461,7 +41651,7 @@ function safeRemoveTree(path2) {
41461
41651
  return;
41462
41652
  }
41463
41653
  if (stat4.isDirectory()) {
41464
- for (const entry of (0, import_node_fs40.readdirSync)(path2)) safeRemoveTree((0, import_node_path39.join)(path2, entry));
41654
+ for (const entry of (0, import_node_fs40.readdirSync)(path2)) safeRemoveTree((0, import_node_path40.join)(path2, entry));
41465
41655
  (0, import_node_fs40.rmdirSync)(path2);
41466
41656
  return;
41467
41657
  }
@@ -41469,7 +41659,7 @@ function safeRemoveTree(path2) {
41469
41659
  }
41470
41660
  async function removeWorktreeNodeModules(wtPath) {
41471
41661
  try {
41472
- safeRemoveTree((0, import_node_path39.join)(wtPath, "node_modules"));
41662
+ safeRemoveTree((0, import_node_path40.join)(wtPath, "node_modules"));
41473
41663
  return { ok: true };
41474
41664
  } catch (e) {
41475
41665
  if (e.code === "ENOENT") return { ok: true };
@@ -41513,7 +41703,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
41513
41703
  return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
41514
41704
  }
41515
41705
  for (const entry of entries) {
41516
- const child2 = (0, import_node_path39.join)(dir, entry.name);
41706
+ const child2 = (0, import_node_path40.join)(dir, entry.name);
41517
41707
  if (entry.isSymbolicLink()) {
41518
41708
  let target = "";
41519
41709
  try {
@@ -41840,7 +42030,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
41840
42030
  const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
41841
42031
  if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
41842
42032
  unlinkedReparsePoints.push(...preHelperGuard.unlinked);
41843
- if (pathExists((0, import_node_path39.join)(wtPath, "node_modules"))) {
42033
+ if (pathExists((0, import_node_path40.join)(wtPath, "node_modules"))) {
41844
42034
  const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
41845
42035
  if (!nmRemoved.ok) {
41846
42036
  report.worktree = {
@@ -41980,7 +42170,7 @@ function norm(p) {
41980
42170
  return process.platform === "win32" ? s.toLowerCase() : s;
41981
42171
  }
41982
42172
  function residueLedgerPath(gitCommonDir) {
41983
- return (0, import_node_path40.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
42173
+ return (0, import_node_path41.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
41984
42174
  }
41985
42175
  function readPaths(file, deps) {
41986
42176
  try {
@@ -41993,7 +42183,7 @@ function readPaths(file, deps) {
41993
42183
  function writePaths(file, paths, deps) {
41994
42184
  try {
41995
42185
  const write = deps.writeLedger ?? ((f, t) => {
41996
- (0, import_node_fs41.mkdirSync)((0, import_node_path40.dirname)(f), { recursive: true });
42186
+ (0, import_node_fs41.mkdirSync)((0, import_node_path41.dirname)(f), { recursive: true });
41997
42187
  (0, import_node_fs41.writeFileSync)(f, t, "utf8");
41998
42188
  });
41999
42189
  write(file, `${JSON.stringify([...new Set(paths)], null, 1)}
@@ -42044,7 +42234,7 @@ async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
42044
42234
  }
42045
42235
  if (recorded.length) writePaths(file, remaining, deps);
42046
42236
  const roots = /* @__PURE__ */ new Set();
42047
- for (const p of [...registered.slice(1), ...recorded]) roots.add((0, import_node_path40.dirname)(p));
42237
+ for (const p of [...registered.slice(1), ...recorded]) roots.add((0, import_node_path41.dirname)(p));
42048
42238
  const keptKeys = new Set(remaining.map(norm));
42049
42239
  for (const root of roots) {
42050
42240
  if (!isDir(root) || live.has(norm(root)) || norm(root) === primary) continue;
@@ -42055,7 +42245,7 @@ async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
42055
42245
  continue;
42056
42246
  }
42057
42247
  for (const name of children) {
42058
- const child2 = (0, import_node_path40.join)(root, name);
42248
+ const child2 = (0, import_node_path41.join)(root, name);
42059
42249
  const key = norm(child2);
42060
42250
  if (live.has(key) || key === primary || keptKeys.has(key) || !isDir(child2)) continue;
42061
42251
  let entries;
@@ -42123,10 +42313,10 @@ function argvWantsJson2() {
42123
42313
  return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
42124
42314
  }
42125
42315
  function hubRoot() {
42126
- const fromPkg = (0, import_node_path41.join)(__dirname, "..", "..");
42316
+ const fromPkg = (0, import_node_path42.join)(__dirname, "..", "..");
42127
42317
  const marker = "skills/bootstrap/seeds/manifest.json";
42128
- if ((0, import_node_fs42.existsSync)((0, import_node_path41.join)(fromPkg, marker))) return fromPkg;
42129
- if ((0, import_node_fs42.existsSync)((0, import_node_path41.join)(process.cwd(), marker))) return process.cwd();
42318
+ if ((0, import_node_fs42.existsSync)((0, import_node_path42.join)(fromPkg, marker))) return fromPkg;
42319
+ if ((0, import_node_fs42.existsSync)((0, import_node_path42.join)(process.cwd(), marker))) return process.cwd();
42130
42320
  return null;
42131
42321
  }
42132
42322
  function ciAuditDeps() {
@@ -42138,7 +42328,7 @@ function ciAuditDeps() {
42138
42328
  getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
42139
42329
  readSeedFile: (path2) => {
42140
42330
  if (!root) return null;
42141
- const fullPath = (0, import_node_path41.join)(root, path2);
42331
+ const fullPath = (0, import_node_path42.join)(root, path2);
42142
42332
  return (0, import_node_fs42.existsSync)(fullPath) ? (0, import_node_fs42.readFileSync)(fullPath, "utf8") : null;
42143
42333
  }
42144
42334
  };
@@ -42246,7 +42436,7 @@ function scheduleRelatedDiscovery(o) {
42246
42436
  try {
42247
42437
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
42248
42438
  if (o.repo) args.push("--repo", o.repo);
42249
- spawnDetachedSelf(args, { spawn: import_node_child_process16.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
42439
+ spawnDetachedSelf(args, { spawn: import_node_child_process17.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
42250
42440
  } catch {
42251
42441
  }
42252
42442
  }
@@ -42897,11 +43087,11 @@ ${list}`);
42897
43087
  }
42898
43088
  });
42899
43089
  async function listCiWorkflowPaths(cwd = process.cwd()) {
42900
- const wfDir = (0, import_node_path41.join)(cwd, ".github", "workflows");
43090
+ const wfDir = (0, import_node_path42.join)(cwd, ".github", "workflows");
42901
43091
  if (!(0, import_node_fs42.existsSync)(wfDir)) return [];
42902
43092
  return (0, import_node_fs42.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
42903
43093
  try {
42904
- return workflowReportsPrChecks((0, import_node_fs42.readFileSync)((0, import_node_path41.join)(wfDir, name), "utf8"));
43094
+ return workflowReportsPrChecks((0, import_node_fs42.readFileSync)((0, import_node_path42.join)(wfDir, name), "utf8"));
42905
43095
  } catch {
42906
43096
  return true;
42907
43097
  }
@@ -43406,7 +43596,7 @@ ${list}`);
43406
43596
  const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
43407
43597
  let foreignCheckout;
43408
43598
  if (foreignCwd) {
43409
- const sibling = (0, import_node_path41.join)((0, import_node_path41.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
43599
+ const sibling = (0, import_node_path42.join)((0, import_node_path42.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
43410
43600
  const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
43411
43601
  if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
43412
43602
  const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
@@ -43615,7 +43805,7 @@ ${list}`);
43615
43805
  let residueSweep;
43616
43806
  if (!(foreignCwd && !foreignCheckout)) {
43617
43807
  try {
43618
- gitCommonDir = (0, import_node_path41.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
43808
+ gitCommonDir = (0, import_node_path42.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
43619
43809
  residueSweep = await sweepWorktreeResidue(gitCommonDir, beforeWorktrees.map((w) => w.path));
43620
43810
  } catch {
43621
43811
  }
@@ -44709,15 +44899,15 @@ function rcRunCauseFromLog(log) {
44709
44899
  }
44710
44900
  function suiteTrainIo(root, summaryFile) {
44711
44901
  const recordPath = repoRuntimeStatePath(root, "suite", "cut.json");
44712
- const base = (0, import_node_path42.join)(repoRuntimeStatePath(root, "suite"), "checkouts");
44902
+ const base = (0, import_node_path43.join)(repoRuntimeStatePath(root, "suite"), "checkouts");
44713
44903
  const checkout = async (repo) => {
44714
44904
  if (repo === SUITE_REPO) return root;
44715
- const target = (0, import_node_path42.join)(base, repo.split("/")[1]);
44905
+ const target = (0, import_node_path43.join)(base, repo.split("/")[1]);
44716
44906
  if (!(0, import_node_fs43.existsSync)(target)) {
44717
44907
  (0, import_node_fs43.mkdirSync)(base, { recursive: true });
44718
44908
  await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
44719
44909
  }
44720
- if (!(0, import_node_fs43.existsSync)((0, import_node_path42.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
44910
+ if (!(0, import_node_fs43.existsSync)((0, import_node_path43.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
44721
44911
  const origin = await exec("git", ["remote", "get-url", "origin"], target);
44722
44912
  if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
44723
44913
  throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
@@ -45106,8 +45296,8 @@ async function collectWaveStatus(deps) {
45106
45296
  init_github_client();
45107
45297
  init_cli_shared();
45108
45298
  var import_node_fs46 = require("node:fs");
45109
- var import_node_os20 = require("node:os");
45110
- var import_node_path43 = require("node:path");
45299
+ var import_node_os21 = require("node:os");
45300
+ var import_node_path44 = require("node:path");
45111
45301
  var GC_GH_TIMEOUT_MS3 = 2e4;
45112
45302
  async function collectStatus() {
45113
45303
  const repo = await resolveRepo();
@@ -45296,10 +45486,10 @@ async function collectOnboardStatus(opts = {}) {
45296
45486
  else if (top) nextCommand = `mmi-cli oracle board claim ${top.number} # ${top.title}`;
45297
45487
  else nextCommand = "mmi-cli oracle board read \u2014 no claimable items found";
45298
45488
  }
45299
- const home = (0, import_node_os20.homedir)();
45489
+ const home = (0, import_node_os21.homedir)();
45300
45490
  const plugin = onboardPluginGate({
45301
- readKnown: () => readFileSyncSafe((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
45302
- readSettings: () => readFileSyncSafe((0, import_node_path43.join)(home, ".claude", "settings.json"), import_node_fs46.readFileSync)
45491
+ readKnown: () => readFileSyncSafe((0, import_node_path44.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
45492
+ readSettings: () => readFileSyncSafe((0, import_node_path44.join)(home, ".claude", "settings.json"), import_node_fs46.readFileSync)
45303
45493
  });
45304
45494
  return {
45305
45495
  guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
@@ -48413,7 +48603,7 @@ function registerSessionReport(program3) {
48413
48603
 
48414
48604
  // src/stage-commands.ts
48415
48605
  var import_node_fs47 = require("node:fs");
48416
- var import_node_path44 = require("node:path");
48606
+ var import_node_path45 = require("node:path");
48417
48607
  init_cli_shared();
48418
48608
  init_clean_exit();
48419
48609
 
@@ -48659,8 +48849,8 @@ function registerStageCommands(program3) {
48659
48849
  return {
48660
48850
  resolution: decideStage({
48661
48851
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
48662
- hasCompose: (0, import_node_fs47.existsSync)((0, import_node_path44.join)(process.cwd(), "docker-compose.yml")),
48663
- hasEnvExample: (0, import_node_fs47.existsSync)((0, import_node_path44.join)(process.cwd(), ".env.example")),
48852
+ hasCompose: (0, import_node_fs47.existsSync)((0, import_node_path45.join)(process.cwd(), "docker-compose.yml")),
48853
+ hasEnvExample: (0, import_node_fs47.existsSync)((0, import_node_path45.join)(process.cwd(), ".env.example")),
48664
48854
  repo
48665
48855
  }),
48666
48856
  project: project2,
@@ -48944,20 +49134,20 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
48944
49134
  }
48945
49135
 
48946
49136
  // src/tenant-artifact.ts
48947
- var import_node_crypto13 = require("node:crypto");
49137
+ var import_node_crypto14 = require("node:crypto");
48948
49138
  var import_node_fs48 = require("node:fs");
48949
49139
  var import_promises10 = require("node:fs/promises");
48950
- var import_node_path45 = require("node:path");
49140
+ var import_node_path46 = require("node:path");
48951
49141
  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}$/;
48952
49142
  var MAX_BYTES = 5 * 1024 * 1024 * 1024;
48953
49143
  async function sha256File(path2) {
48954
- const hash = (0, import_node_crypto13.createHash)("sha256");
49144
+ const hash = (0, import_node_crypto14.createHash)("sha256");
48955
49145
  for await (const chunk of (0, import_node_fs48.createReadStream)(path2)) hash.update(chunk);
48956
49146
  return hash.digest("hex");
48957
49147
  }
48958
49148
  async function putTenantArtifact(repo, stage, inputPath, deps) {
48959
49149
  if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
48960
- const path2 = (0, import_node_path45.resolve)(inputPath);
49150
+ const path2 = (0, import_node_path46.resolve)(inputPath);
48961
49151
  const info = await (0, import_promises10.stat)(path2);
48962
49152
  if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
48963
49153
  if (!Number.isSafeInteger(info.size) || info.size < 1 || info.size > MAX_BYTES) throw new Error(`tenant artifact put: file must be 1..${MAX_BYTES} bytes`);
@@ -49147,7 +49337,7 @@ async function resolveWhoami(deps) {
49147
49337
  }
49148
49338
 
49149
49339
  // src/command-register-developer.ts
49150
- var import_node_path50 = require("node:path");
49340
+ var import_node_path51 = require("node:path");
49151
49341
  init_house_map();
49152
49342
  init_hub_url();
49153
49343
 
@@ -49180,27 +49370,27 @@ async function executeWaveLand(plan, deps) {
49180
49370
  }
49181
49371
 
49182
49372
  // src/dist-drift.ts
49183
- var import_node_child_process17 = require("node:child_process");
49184
- var import_node_crypto15 = require("node:crypto");
49373
+ var import_node_child_process18 = require("node:child_process");
49374
+ var import_node_crypto16 = require("node:crypto");
49185
49375
  var import_node_fs50 = require("node:fs");
49186
- var import_node_os21 = require("node:os");
49187
- var import_node_path47 = require("node:path");
49376
+ var import_node_os22 = require("node:os");
49377
+ var import_node_path48 = require("node:path");
49188
49378
 
49189
49379
  // ../scripts/distribution-digest.mjs
49190
- var import_node_crypto14 = require("node:crypto");
49380
+ var import_node_crypto15 = require("node:crypto");
49191
49381
  var import_node_fs49 = require("node:fs");
49192
- var import_node_path46 = require("node:path");
49382
+ var import_node_path47 = require("node:path");
49193
49383
  var slash = (value) => value.replaceAll("\\", "/");
49194
49384
  function repoPath(root, declaredPath, label) {
49195
- const absoluteRoot = (0, import_node_path46.resolve)(root);
49196
- const target = (0, import_node_path46.resolve)(root, declaredPath);
49197
- if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path46.sep}`)) {
49385
+ const absoluteRoot = (0, import_node_path47.resolve)(root);
49386
+ const target = (0, import_node_path47.resolve)(root, declaredPath);
49387
+ if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path47.sep}`)) {
49198
49388
  throw new Error(`${label} ${declaredPath} escapes the repository root`);
49199
49389
  }
49200
49390
  return target;
49201
49391
  }
49202
49392
  function digestFiles(files) {
49203
- const hash = (0, import_node_crypto14.createHash)("sha256");
49393
+ const hash = (0, import_node_crypto15.createHash)("sha256");
49204
49394
  for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
49205
49395
  const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs49.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs49.readFileSync)(file.absolute);
49206
49396
  hash.update(file.relative, "utf8");
@@ -49230,7 +49420,7 @@ var DIST_ARTIFACTS = [
49230
49420
  ];
49231
49421
  var BOM_DIST_TREE_ID = "mmi-cli-dist";
49232
49422
  var ABSENT = "absent";
49233
- var sha256 = (bytes) => `sha256:${(0, import_node_crypto15.createHash)("sha256").update(bytes).digest("hex")}`;
49423
+ var sha256 = (bytes) => `sha256:${(0, import_node_crypto16.createHash)("sha256").update(bytes).digest("hex")}`;
49234
49424
  function artifactDrift(path2, committedBytes, rebuiltBytes) {
49235
49425
  const committed = committedBytes ? sha256(committedBytes) : ABSENT;
49236
49426
  const rebuiltExpected = rebuiltBytes ? sha256(rebuiltBytes) : ABSENT;
@@ -49308,7 +49498,7 @@ function walkFiles(root) {
49308
49498
  const files = [];
49309
49499
  const walk2 = (directory) => {
49310
49500
  for (const entry of (0, import_node_fs50.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
49311
- const child2 = (0, import_node_path47.join)(directory, entry.name);
49501
+ const child2 = (0, import_node_path48.join)(directory, entry.name);
49312
49502
  if (entry.isDirectory()) walk2(child2);
49313
49503
  else files.push(child2);
49314
49504
  }
@@ -49318,14 +49508,14 @@ function walkFiles(root) {
49318
49508
  }
49319
49509
  function bomPathFor(root) {
49320
49510
  try {
49321
- const registry2 = JSON.parse((0, import_node_fs50.readFileSync)((0, import_node_path47.join)(root, "surfaces.json"), "utf8"));
49322
- return (0, import_node_path47.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
49511
+ const registry2 = JSON.parse((0, import_node_fs50.readFileSync)((0, import_node_path48.join)(root, "surfaces.json"), "utf8"));
49512
+ return (0, import_node_path48.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
49323
49513
  } catch {
49324
- return (0, import_node_path47.join)(root, "distribution-bom.json");
49514
+ return (0, import_node_path48.join)(root, "distribution-bom.json");
49325
49515
  }
49326
49516
  }
49327
49517
  function rebuildTo(packageRoot, outDir) {
49328
- (0, import_node_child_process17.execFileSync)(process.execPath, ["build.mjs"], {
49518
+ (0, import_node_child_process18.execFileSync)(process.execPath, ["build.mjs"], {
49329
49519
  cwd: packageRoot,
49330
49520
  env: { ...process.env, MMI_DIST_OUTDIR: outDir },
49331
49521
  windowsHide: true,
@@ -49334,28 +49524,28 @@ function rebuildTo(packageRoot, outDir) {
49334
49524
  });
49335
49525
  }
49336
49526
  function runDistStatus(root) {
49337
- const stage = (0, import_node_fs50.mkdtempSync)((0, import_node_path47.join)((0, import_node_os21.tmpdir)(), "mmi-dist-drift-"));
49527
+ const stage = (0, import_node_fs50.mkdtempSync)((0, import_node_path48.join)((0, import_node_os22.tmpdir)(), "mmi-dist-drift-"));
49338
49528
  let overlayCount = 0;
49339
49529
  try {
49340
- const cliOut = (0, import_node_path47.join)(stage, "cli-dist");
49341
- const hubOut = (0, import_node_path47.join)(stage, "hub-dist");
49342
- rebuildTo((0, import_node_path47.join)(root, "cli"), cliOut);
49343
- rebuildTo((0, import_node_path47.join)(root, "updater"), hubOut);
49530
+ const cliOut = (0, import_node_path48.join)(stage, "cli-dist");
49531
+ const hubOut = (0, import_node_path48.join)(stage, "hub-dist");
49532
+ rebuildTo((0, import_node_path48.join)(root, "cli"), cliOut);
49533
+ rebuildTo((0, import_node_path48.join)(root, "updater"), hubOut);
49344
49534
  const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
49345
49535
  const rebuilt = (path2) => {
49346
49536
  const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
49347
- return spec ? readOrNull((0, import_node_path47.join)(outDirFor(spec.packageDir), spec.output)) : null;
49537
+ return spec ? readOrNull((0, import_node_path48.join)(outDirFor(spec.packageDir), spec.output)) : null;
49348
49538
  };
49349
- const committed = (path2) => readOrNull((0, import_node_path47.join)(root, path2));
49350
- const tree = (path2) => readOrNull((0, import_node_path47.join)(root, path2));
49351
- const distRoot = (0, import_node_path47.join)(root, "cli", "dist");
49352
- const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path47.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
49539
+ const committed = (path2) => readOrNull((0, import_node_path48.join)(root, path2));
49540
+ const tree = (path2) => readOrNull((0, import_node_path48.join)(root, path2));
49541
+ const distRoot = (0, import_node_path48.join)(root, "cli", "dist");
49542
+ const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path48.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
49353
49543
  const bom = JSON.parse((0, import_node_fs50.readFileSync)(bomPathFor(root), "utf8"));
49354
49544
  const digest = (entries) => {
49355
- const overlay = (0, import_node_path47.join)(stage, `overlay-${overlayCount++}`);
49545
+ const overlay = (0, import_node_path48.join)(stage, `overlay-${overlayCount++}`);
49356
49546
  for (const entry of entries) {
49357
- const target = (0, import_node_path47.join)(overlay, entry.path);
49358
- (0, import_node_fs50.mkdirSync)((0, import_node_path47.dirname)(target), { recursive: true });
49547
+ const target = (0, import_node_path48.join)(overlay, entry.path);
49548
+ (0, import_node_fs50.mkdirSync)((0, import_node_path48.dirname)(target), { recursive: true });
49359
49549
  (0, import_node_fs50.writeFileSync)(target, entry.bytes);
49360
49550
  }
49361
49551
  return digestPackedFiles(overlay, entries.map((entry) => entry.path));
@@ -49441,7 +49631,7 @@ init_hub_auth();
49441
49631
 
49442
49632
  // src/schedules-lift-command.ts
49443
49633
  var import_promises11 = require("node:fs/promises");
49444
- var import_node_path48 = require("node:path");
49634
+ var import_node_path49 = require("node:path");
49445
49635
  init_clean_exit();
49446
49636
  init_cli_shared();
49447
49637
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
@@ -49470,7 +49660,7 @@ async function readWorkflowFiles(dir) {
49470
49660
  const files = [];
49471
49661
  for (const name of names.sort()) {
49472
49662
  if (!/\.ya?ml$/.test(name)) continue;
49473
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises11.readFile)((0, import_node_path48.join)(dir, name), "utf8") });
49663
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises11.readFile)((0, import_node_path49.join)(dir, name), "utf8") });
49474
49664
  }
49475
49665
  return files;
49476
49666
  }
@@ -49552,9 +49742,9 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
49552
49742
  }
49553
49743
 
49554
49744
  // src/spawn-policy-core.ts
49555
- var import_node_child_process18 = require("node:child_process");
49745
+ var import_node_child_process19 = require("node:child_process");
49556
49746
  var import_node_fs51 = require("node:fs");
49557
- var import_node_path49 = require("node:path");
49747
+ var import_node_path50 = require("node:path");
49558
49748
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
49559
49749
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
49560
49750
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -49623,7 +49813,7 @@ function findViolationsInSource(raw) {
49623
49813
  return found;
49624
49814
  }
49625
49815
  function policedFiles(root) {
49626
- const r = (0, import_node_child_process18.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
49816
+ const r = (0, import_node_child_process19.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
49627
49817
  cwd: root,
49628
49818
  encoding: "utf8",
49629
49819
  windowsHide: true,
@@ -49640,7 +49830,7 @@ function runSpawnPolicy(root) {
49640
49830
  for (const file of files) {
49641
49831
  let raw;
49642
49832
  try {
49643
- raw = (0, import_node_fs51.readFileSync)((0, import_node_path49.join)(root, file), "utf8");
49833
+ raw = (0, import_node_fs51.readFileSync)((0, import_node_path50.join)(root, file), "utf8");
49644
49834
  } catch {
49645
49835
  continue;
49646
49836
  }
@@ -49660,7 +49850,7 @@ function runSpawnPolicy(root) {
49660
49850
  function registerDeveloperCommands(program3) {
49661
49851
  const rules = program3.command("rules").description("org-managed .gitignore delivery");
49662
49852
  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) => {
49663
- const path2 = (0, import_node_path50.join)(process.cwd(), ".gitignore");
49853
+ const path2 = (0, import_node_path51.join)(process.cwd(), ".gitignore");
49664
49854
  const current = (0, import_node_fs52.existsSync)(path2) ? (0, import_node_fs52.readFileSync)(path2, "utf8") : null;
49665
49855
  const plan = planManagedGitignore(current);
49666
49856
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
@@ -49935,12 +50125,12 @@ ${r.stderr ?? ""}`).catch(() => "");
49935
50125
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
49936
50126
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
49937
50127
  function envHealLockPath(home) {
49938
- return (0, import_node_path51.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
50128
+ return (0, import_node_path52.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
49939
50129
  }
49940
50130
  async function withEnvHealLock(what, run) {
49941
50131
  try {
49942
50132
  return await withFileLock(
49943
- envHealLockPath((0, import_node_os22.homedir)()),
50133
+ envHealLockPath((0, import_node_os23.homedir)()),
49944
50134
  { staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
49945
50135
  run
49946
50136
  );
@@ -50037,7 +50227,7 @@ function mmiDoctorDeps(opts = {}) {
50037
50227
  const configRoot = surfaceConfigRoot(surface);
50038
50228
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
50039
50229
  const plan = buildPluginCachePlan(
50040
- (0, import_node_os22.homedir)(),
50230
+ (0, import_node_os23.homedir)(),
50041
50231
  running,
50042
50232
  pluginCacheFsDeps(configRoot, () => 0),
50043
50233
  { configRoot, includeStaging: surface !== "codex" }
@@ -50065,7 +50255,7 @@ function mmiDoctorDeps(opts = {}) {
50065
50255
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
50066
50256
  const installed = installedActivePluginVersion(surface);
50067
50257
  const plan = buildPluginCachePlan(
50068
- (0, import_node_os22.homedir)(),
50258
+ (0, import_node_os23.homedir)(),
50069
50259
  running,
50070
50260
  pluginCacheFsDeps(configRoot, () => 0),
50071
50261
  { configRoot, includeStaging: surface !== "codex", installedVersion: installed }
@@ -50107,7 +50297,7 @@ function mmiDoctorDeps(opts = {}) {
50107
50297
  // has no generated routing index would
50108
50298
  // get a permanent — demanding an artifact it never asked for.
50109
50299
  docsIndexState: (root) => {
50110
- if (!(0, import_node_fs53.existsSync)((0, import_node_path51.join)(root, DOCS_INDEX_PATH))) return void 0;
50300
+ if (!(0, import_node_fs53.existsSync)((0, import_node_path52.join)(root, DOCS_INDEX_PATH))) return void 0;
50111
50301
  const real = createDocsIndexDeps(root);
50112
50302
  let docs;
50113
50303
  const listDocs = () => docs ??= real.listDocs();
@@ -50116,7 +50306,7 @@ function mmiDoctorDeps(opts = {}) {
50116
50306
  },
50117
50307
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
50118
50308
  healDocsIndex: (root) => {
50119
- if (!(0, import_node_fs53.existsSync)((0, import_node_path51.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
50309
+ if (!(0, import_node_fs53.existsSync)((0, import_node_path52.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
50120
50310
  const real = createDocsIndexDeps(root);
50121
50311
  let docs;
50122
50312
  const listDocs = () => docs ??= real.listDocs();
@@ -51203,16 +51393,16 @@ function ciAuditDeps2() {
51203
51393
  // gate re-seed step is skipped gracefully rather than failing mid-run.
51204
51394
  readSeedFile: (path2) => {
51205
51395
  if (!root) return null;
51206
- const fullPath = (0, import_node_path51.join)(root, path2);
51396
+ const fullPath = (0, import_node_path52.join)(root, path2);
51207
51397
  return (0, import_node_fs53.existsSync)(fullPath) ? (0, import_node_fs53.readFileSync)(fullPath, "utf8") : null;
51208
51398
  }
51209
51399
  };
51210
51400
  }
51211
51401
  function hubRoot2() {
51212
- const fromPkg = (0, import_node_path51.join)(__dirname, "..", "..");
51402
+ const fromPkg = (0, import_node_path52.join)(__dirname, "..", "..");
51213
51403
  const marker = "skills/bootstrap/seeds/manifest.json";
51214
- if ((0, import_node_fs53.existsSync)((0, import_node_path51.join)(fromPkg, marker))) return fromPkg;
51215
- if ((0, import_node_fs53.existsSync)((0, import_node_path51.join)(process.cwd(), marker))) return process.cwd();
51404
+ if ((0, import_node_fs53.existsSync)((0, import_node_path52.join)(fromPkg, marker))) return fromPkg;
51405
+ if ((0, import_node_fs53.existsSync)((0, import_node_path52.join)(process.cwd(), marker))) return process.cwd();
51216
51406
  return null;
51217
51407
  }
51218
51408
  registerQueryCommands(program2);
@@ -51353,7 +51543,7 @@ function directoryBytes(path2) {
51353
51543
  return 0;
51354
51544
  }
51355
51545
  for (const entry of entries) {
51356
- const child2 = (0, import_node_path51.join)(path2, entry.name);
51546
+ const child2 = (0, import_node_path52.join)(path2, entry.name);
51357
51547
  if (entry.isDirectory()) total += directoryBytes(child2);
51358
51548
  else {
51359
51549
  try {
@@ -51383,7 +51573,7 @@ function pluginCacheFsDeps(configRoot, dirBytes) {
51383
51573
  dirBytes,
51384
51574
  listStagingDirs: (root) => (0, import_node_fs53.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
51385
51575
  try {
51386
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path51.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs53.statSync)(p).mtimeMs) };
51576
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path52.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs53.statSync)(p).mtimeMs) };
51387
51577
  } catch {
51388
51578
  return { name: d.name, mtimeMs: Date.now() };
51389
51579
  }
@@ -51397,7 +51587,7 @@ function stagingApplyFsGuard(configRoot) {
51397
51587
  return {
51398
51588
  referencedPaths: () => readInstalledPluginRefs(configRoot),
51399
51589
  mtimeMs: (name) => {
51400
- const p = (0, import_node_path51.join)(stagingRoot, name);
51590
+ const p = (0, import_node_path52.join)(stagingRoot, name);
51401
51591
  if (!(0, import_node_fs53.existsSync)(p)) return null;
51402
51592
  try {
51403
51593
  return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs53.statSync)(q).mtimeMs);
@@ -51420,7 +51610,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
51420
51610
  return;
51421
51611
  }
51422
51612
  const plan = buildPluginCachePlan(
51423
- (0, import_node_os22.homedir)(),
51613
+ (0, import_node_os23.homedir)(),
51424
51614
  running,
51425
51615
  pluginCacheFsDeps(configRoot, directoryBytes),
51426
51616
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }