@mutmutco/cli 3.135.0 → 3.136.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.cjs +612 -390
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -3416,7 +3416,7 @@ var program = new Command();
3416
3416
 
3417
3417
  // src/index.ts
3418
3418
  var import_promises12 = require("node:fs/promises");
3419
- var import_node_fs47 = require("node:fs");
3419
+ var import_node_fs48 = require("node:fs");
3420
3420
  var import_node_child_process19 = require("node:child_process");
3421
3421
 
3422
3422
  // src/cli-shared.ts
@@ -5502,7 +5502,9 @@ function parseWorktreeOwners(text) {
5502
5502
  return parsed.entries.filter((e) => {
5503
5503
  if (!e || typeof e !== "object") return false;
5504
5504
  const entry = e;
5505
- return typeof entry.path === "string" && entry.path.length > 0 && typeof entry.branch === "string" && typeof entry.createdAt === "string" && typeof entry.lastSeenAt === "string" && isActor(entry.actor);
5505
+ const provenance = entry.provenance;
5506
+ const provenanceValid = provenance === void 0 || typeof provenance === "object" && typeof provenance.creationBaseOid === "string" && /^[0-9a-f]{40,64}$/i.test(provenance.creationBaseOid) && typeof provenance.workerBranch === "string" && provenance.workerBranch.length > 0;
5507
+ return typeof entry.path === "string" && entry.path.length > 0 && typeof entry.branch === "string" && typeof entry.createdAt === "string" && typeof entry.lastSeenAt === "string" && isActor(entry.actor) && provenanceValid;
5506
5508
  });
5507
5509
  }
5508
5510
  function serializeWorktreeOwners(entries) {
@@ -6400,6 +6402,8 @@ function buildGcPlan(inputs) {
6400
6402
  const preservedBranches2 = new Set(inputs.preservedBranches ?? []);
6401
6403
  const preservedWorktrees = new Set((inputs.worktrees ?? []).filter((w) => w.preserved).map((w) => w.branch));
6402
6404
  const mergedIntoBase = new Set((inputs.mergedIntoBase ?? []).map((b) => b.trim()).filter(Boolean));
6405
+ const exactTreeLanded = new Map((inputs.exactTreeLanded ?? []).map((p) => [p.branch.trim(), p]));
6406
+ const exactTreeRefusals = new Map((inputs.exactTreeRefusals ?? []).map((p) => [p.branch.trim(), p.detail]));
6403
6407
  const prLookupFailures = new Map((inputs.prLookupFailures ?? []).map((f) => [f.branch.trim(), f.detail]));
6404
6408
  const skipped = [];
6405
6409
  const branches = [];
@@ -6426,8 +6430,10 @@ function buildGcPlan(inputs) {
6426
6430
  skipped.push({ branch, reason: "open-pr" });
6427
6431
  continue;
6428
6432
  }
6429
- const state = closedState(prSet);
6430
- if (!state) continue;
6433
+ const exactDelivery = exactTreeLanded.get(branch);
6434
+ const exactRefusal = exactTreeRefusals.get(branch);
6435
+ const state = closedState(prSet) ?? (exactDelivery ? { state: "EXACT_TREE", numbers: [], headOids: [] } : null);
6436
+ if (!state && !exactRefusal) continue;
6431
6437
  if (branch === inputs.currentBranch) {
6432
6438
  skipped.push({ branch, reason: "current-branch" });
6433
6439
  skipTrackingBranches.add(branch);
@@ -6444,8 +6450,14 @@ function buildGcPlan(inputs) {
6444
6450
  skipTrackingBranches.add(branch);
6445
6451
  continue;
6446
6452
  }
6453
+ if (!state) {
6454
+ skipped.push({ branch, reason: "exact-tree-proof-refused", detail: exactRefusal });
6455
+ skipTrackingBranches.add(branch);
6456
+ continue;
6457
+ }
6447
6458
  const localHead = branchHeads?.get(branch);
6448
- const containedInBase = mergedIntoBase.has(branch);
6459
+ const exactHeadStillMatches = Boolean(exactDelivery && localHead === exactDelivery.headOid);
6460
+ const containedInBase = mergedIntoBase.has(branch) || exactHeadStillMatches;
6449
6461
  if (!containedInBase && (worktree2?.unpushed || branchHeads && (!localHead || !state.headOids.length || !state.headOids.includes(localHead)))) {
6450
6462
  const detail = worktree2?.unpushed ? worktree2.path : localHead && state.headOids.length ? `${localHead} != ${state.headOids.join("|")}` : "local branch head could not be verified against the PR head";
6451
6463
  skipped.push({ branch, reason: "unpushed-branch", detail });
@@ -6458,7 +6470,8 @@ function buildGcPlan(inputs) {
6458
6470
  prNumbers: state.numbers,
6459
6471
  worktreePath: worktree2?.path,
6460
6472
  ...state.headOids.length ? { reviewedHeadOids: state.headOids } : {},
6461
- ...containedInBase ? { containedInBase: true, ...localHead ? { plannedHeadOid: localHead } : {} } : {}
6473
+ ...containedInBase ? { containedInBase: true, ...localHead ? { plannedHeadOid: localHead } : {} } : {},
6474
+ ...exactHeadStillMatches ? { deliveredBy: exactDelivery.candidateOid } : {}
6462
6475
  });
6463
6476
  }
6464
6477
  const trackingRefs = [...new Set(inputs.staleTrackingRefs ?? [])].map((ref) => {
@@ -7060,7 +7073,8 @@ function formatGcPlan(plan, apply, auditClone) {
7060
7073
  for (const b of plan.branches) {
7061
7074
  const prs = b.prNumbers.length ? ` #${b.prNumbers.join(",#")}` : "";
7062
7075
  const wt = b.worktreePath ? ` (worktree: ${b.worktreePath})` : "";
7063
- lines.push(` - ${b.branch} (${b.prState}${prs})${wt}`);
7076
+ const authority = b.deliveredBy ? `${b.prState}; deliveredBy ${b.deliveredBy}` : `${b.prState}${prs}`;
7077
+ lines.push(` - ${b.branch} (${authority})${wt}`);
7064
7078
  }
7065
7079
  }
7066
7080
  const remoteBranches = plan.branches.filter((b) => (b.reviewedHeadOids?.length ?? 0) > 0);
@@ -7869,7 +7883,7 @@ function commandLadderHint() {
7869
7883
  }
7870
7884
 
7871
7885
  // src/index.ts
7872
- var import_node_path45 = require("node:path");
7886
+ var import_node_path46 = require("node:path");
7873
7887
 
7874
7888
  // src/merge-ci-policy.ts
7875
7889
  function resolveMergeCiPolicy(input) {
@@ -9752,9 +9766,9 @@ function parseVerifyBroker(stdout) {
9752
9766
  }
9753
9767
 
9754
9768
  // src/train-apply.ts
9755
- var import_node_fs22 = require("node:fs");
9769
+ var import_node_fs23 = require("node:fs");
9756
9770
  var import_promises4 = require("node:fs/promises");
9757
- var import_node_path22 = require("node:path");
9771
+ var import_node_path23 = require("node:path");
9758
9772
 
9759
9773
  // src/plugin-guard-io.ts
9760
9774
  var import_node_fs19 = require("node:fs");
@@ -11186,9 +11200,9 @@ function renderAccessReport(report) {
11186
11200
  }
11187
11201
 
11188
11202
  // src/cli-doctor-shared.ts
11189
- var import_node_fs20 = require("node:fs");
11190
- var import_node_path21 = require("node:path");
11191
11203
  var import_node_fs21 = require("node:fs");
11204
+ var import_node_path22 = require("node:path");
11205
+ var import_node_fs22 = require("node:fs");
11192
11206
 
11193
11207
  // ../infra/registry-endpoints.mjs
11194
11208
  var PROJECTS_LIST_PATH = "/projects/list";
@@ -13630,6 +13644,142 @@ async function fileReport(deps, req) {
13630
13644
  return { ok: true, body };
13631
13645
  }
13632
13646
 
13647
+ // src/worktree-delivery-proof.ts
13648
+ var import_node_fs20 = require("node:fs");
13649
+ var import_node_os9 = require("node:os");
13650
+ var import_node_path21 = require("node:path");
13651
+ var OID_RE = /^[0-9a-f]{40,64}$/i;
13652
+ var EXACT_TREE_CANDIDATE_LIMIT = 32;
13653
+ async function repointDeliveredWorktreeTransactionally(input) {
13654
+ const symbolic = (await input.git(["symbolic-ref", "--quiet", "--short", "HEAD"]).catch(() => "")).trim();
13655
+ if (symbolic !== input.branch) return { action: "refuse", reason: "wrong-branch", detail: symbolic || "detached HEAD" };
13656
+ const current = (await input.git(["rev-parse", "--verify", `refs/heads/${input.branch}`]).catch(() => "")).trim();
13657
+ if (current !== input.expectedWorkerOid) {
13658
+ return { action: "refuse", reason: "worker-moved", detail: `${current || "unreadable"} != ${input.expectedWorkerOid}` };
13659
+ }
13660
+ const status = await input.git(["status", "--porcelain"]).catch(() => "unreadable");
13661
+ if (status.trim()) return { action: "refuse", reason: "dirty-worktree", detail: "tracked or untracked files present" };
13662
+ try {
13663
+ await input.git(["checkout", "-B", input.branch, input.landedTipOid]);
13664
+ return { action: "repointed" };
13665
+ } catch (error) {
13666
+ return { action: "refuse", reason: "checkout-failed", detail: error instanceof Error ? error.message : String(error) };
13667
+ }
13668
+ }
13669
+ function supportsExactTreeProofGit(versionOutput) {
13670
+ const match = /\bgit version (\d+)\.(\d+)(?:\.\d+)?/i.exec(versionOutput.trim());
13671
+ if (!match) return false;
13672
+ const major = Number(match[1]);
13673
+ const minor = Number(match[2]);
13674
+ return major > 2 || major === 2 && minor >= 32;
13675
+ }
13676
+ function describeExactTreeRefusal(verdict) {
13677
+ return `${verdict.reason}${verdict.detail ? `: ${verdict.detail}` : ""}`;
13678
+ }
13679
+ function sameChangedPathSet(a, b) {
13680
+ const sorted = (value) => value.split("\0").filter(Boolean).sort().join("\0");
13681
+ return sorted(a) === sorted(b);
13682
+ }
13683
+ async function proveExactTreeDelivery(input, deps = {}) {
13684
+ const base = input.creationBaseOid?.trim();
13685
+ if (!base || !OID_RE.test(base)) return { action: "refuse", reason: "missing-provenance" };
13686
+ if (!input.recordedWorkerBranch || input.recordedWorkerBranch !== input.branch) {
13687
+ return { action: "refuse", reason: "worker-identity-mismatch" };
13688
+ }
13689
+ if (!OID_RE.test(input.workerOid)) return { action: "refuse", reason: "proof-failed", detail: "worker OID is invalid" };
13690
+ const run = deps.git ?? (async (args, env) => (await execFileP2("git", ["-C", input.repoRoot, ...args], {
13691
+ timeout: GIT_TIMEOUT_MS,
13692
+ ...env ? { env: { ...process.env, ...env } } : {}
13693
+ })).stdout);
13694
+ const isAncestor = (ancestor, descendant) => run(["merge-base", "--is-ancestor", ancestor, descendant]).then(() => true).catch(() => false);
13695
+ let version;
13696
+ try {
13697
+ version = await run(["version"]);
13698
+ } catch {
13699
+ return { action: "refuse", reason: "proof-failed", detail: "Git capability probe failed" };
13700
+ }
13701
+ if (!supportsExactTreeProofGit(version)) {
13702
+ return { action: "refuse", reason: "unsupported-git", detail: `requires Git >=2.32; found ${version.trim() || "unparseable version"}` };
13703
+ }
13704
+ try {
13705
+ const [baseType, workerType] = await Promise.all([
13706
+ run(["cat-file", "-t", base]).then((v) => v.trim()).catch(() => ""),
13707
+ run(["cat-file", "-t", input.workerOid]).then((v) => v.trim()).catch(() => "")
13708
+ ]);
13709
+ if (baseType !== "commit" || workerType !== "commit" || !await isAncestor(base, input.workerOid)) {
13710
+ return { action: "refuse", reason: "unverified-base" };
13711
+ }
13712
+ const candidates = /* @__PURE__ */ new Map();
13713
+ for (const tip of [...new Set(input.landedTips.map((v) => v.trim()).filter(Boolean))]) {
13714
+ if (!OID_RE.test(tip) || !await isAncestor(base, tip)) continue;
13715
+ const listed = await run([
13716
+ "rev-list",
13717
+ "--first-parent",
13718
+ "--parents",
13719
+ `--max-count=${EXACT_TREE_CANDIDATE_LIMIT + 1}`,
13720
+ `${base}..${tip}`
13721
+ ]);
13722
+ const rows = listed.split(/\r?\n/).map((v) => v.trim()).filter(Boolean);
13723
+ if (rows.length > EXACT_TREE_CANDIDATE_LIMIT) {
13724
+ return {
13725
+ action: "refuse",
13726
+ reason: "candidate-limit-exceeded",
13727
+ detail: `more than ${EXACT_TREE_CANDIDATE_LIMIT} first-parent candidates since stored base`
13728
+ };
13729
+ }
13730
+ for (const row of rows) {
13731
+ const [oid, parent] = row.split(/\s+/);
13732
+ if (oid && parent && OID_RE.test(oid) && OID_RE.test(parent)) candidates.set(oid, parent);
13733
+ }
13734
+ if (candidates.size > EXACT_TREE_CANDIDATE_LIMIT) {
13735
+ return {
13736
+ action: "refuse",
13737
+ reason: "candidate-limit-exceeded",
13738
+ detail: `more than ${EXACT_TREE_CANDIDATE_LIMIT} unique first-parent candidates across landed tips`
13739
+ };
13740
+ }
13741
+ }
13742
+ if (!candidates.size) return { action: "refuse", reason: "no-candidate" };
13743
+ const workerPaths = await run(["diff", "--name-only", "-z", "--no-renames", base, input.workerOid]);
13744
+ const pathMatches = [];
13745
+ for (const [candidate, parent] of candidates) {
13746
+ const candidatePaths = await run(["diff", "--name-only", "-z", "--no-renames", parent, candidate]);
13747
+ if (sameChangedPathSet(workerPaths, candidatePaths)) pathMatches.push([candidate, parent]);
13748
+ }
13749
+ if (!pathMatches.length) return { action: "refuse", reason: "tree-mismatch" };
13750
+ const makeTempDir = deps.makeTempDir ?? (() => (0, import_node_fs20.mkdtempSync)((0, import_node_path21.join)((0, import_node_os9.tmpdir)(), "mmi-tree-proof-")));
13751
+ const writeTextFile = deps.writeTextFile ?? ((path2, text) => (0, import_node_fs20.writeFileSync)(path2, text, "utf8"));
13752
+ const removeTempDir = deps.removeTempDir ?? ((path2) => (0, import_node_fs20.rmSync)(path2, { recursive: true, force: true }));
13753
+ const root = makeTempDir();
13754
+ try {
13755
+ const synthesize = async (name, from, to) => {
13756
+ const index = (0, import_node_path21.join)(root, `${name}.index`);
13757
+ const patch = (0, import_node_path21.join)(root, `${name}.patch`);
13758
+ const env = { GIT_INDEX_FILE: index };
13759
+ await run(["read-tree", base], env);
13760
+ const delta = await run(["diff-tree", "-p", "--binary", "--full-index", "--no-renames", "--no-ext-diff", from, to]);
13761
+ writeTextFile(patch, delta);
13762
+ if (delta.length) await run(["apply", "--cached", "--binary", "--3way", patch], env);
13763
+ return (await run(["write-tree"], env)).trim();
13764
+ };
13765
+ const workerTreeOid = await synthesize("worker", base, input.workerOid);
13766
+ const matches = [];
13767
+ let candidateNumber = 0;
13768
+ for (const [candidate, parent] of pathMatches) {
13769
+ const tree = await synthesize(`candidate-${candidateNumber++}`, parent, candidate).catch(() => void 0);
13770
+ if (tree === workerTreeOid) matches.push(candidate);
13771
+ }
13772
+ if (matches.length === 1) return { action: "settle", workerTreeOid, candidateOid: matches[0] };
13773
+ if (matches.length > 1) return { action: "refuse", reason: "ambiguous-candidate" };
13774
+ return { action: "refuse", reason: "tree-mismatch" };
13775
+ } finally {
13776
+ removeTempDir(root);
13777
+ }
13778
+ } catch (error) {
13779
+ return { action: "refuse", reason: "proof-failed", detail: error instanceof Error ? error.message : String(error) };
13780
+ }
13781
+ }
13782
+
13633
13783
  // src/cli-doctor-shared.ts
13634
13784
  var GC_GH_TIMEOUT_MS = 2e4;
13635
13785
  var RUN_LIST_TIMEOUT_MS = 2e4;
@@ -13732,7 +13882,7 @@ async function localBranchHeads() {
13732
13882
  }
13733
13883
  async function currentRepoWorktreeGitRoot(repoRoot2) {
13734
13884
  const gitCommonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
13735
- return gitCommonDir ? (0, import_node_path21.resolve)(repoRoot2, gitCommonDir, "worktrees") : "";
13885
+ return gitCommonDir ? (0, import_node_path22.resolve)(repoRoot2, gitCommonDir, "worktrees") : "";
13736
13886
  }
13737
13887
  async function worktreeBranches() {
13738
13888
  const { stdout } = await execFileP2("git", ["worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS });
@@ -13752,18 +13902,18 @@ function resolveGitdirForWorktreeFile(worktreePath, content) {
13752
13902
  const match = /^gitdir:\s*(.+)\s*$/im.exec(content);
13753
13903
  if (!match?.[1]) return void 0;
13754
13904
  const raw = match[1].trim();
13755
- return (0, import_node_path21.isAbsolute)(raw) ? raw : (0, import_node_path21.resolve)(worktreePath, raw);
13905
+ return (0, import_node_path22.isAbsolute)(raw) ? raw : (0, import_node_path22.resolve)(worktreePath, raw);
13756
13906
  }
13757
13907
  function metadataOwnsMissingWorktreeDir(worktreePath, worktreeGitRoot) {
13758
13908
  if (!worktreeGitRoot) return false;
13759
13909
  try {
13760
- const entries = (0, import_node_fs21.readdirSync)(worktreeGitRoot, { withFileTypes: true });
13910
+ const entries = (0, import_node_fs22.readdirSync)(worktreeGitRoot, { withFileTypes: true });
13761
13911
  for (const ent of entries) {
13762
13912
  if (!ent.isDirectory()) continue;
13763
13913
  try {
13764
- const gitdirPath = (0, import_node_fs20.readFileSync)((0, import_node_path21.join)(worktreeGitRoot, ent.name, "gitdir"), "utf8").trim();
13765
- const resolvedGitdir = (0, import_node_path21.isAbsolute)(gitdirPath) ? gitdirPath : (0, import_node_path21.resolve)(worktreeGitRoot, ent.name, gitdirPath);
13766
- if (sameWorktreeMetadataPath((0, import_node_path21.dirname)(resolvedGitdir), worktreePath)) return true;
13914
+ const gitdirPath = (0, import_node_fs21.readFileSync)((0, import_node_path22.join)(worktreeGitRoot, ent.name, "gitdir"), "utf8").trim();
13915
+ const resolvedGitdir = (0, import_node_path22.isAbsolute)(gitdirPath) ? gitdirPath : (0, import_node_path22.resolve)(worktreeGitRoot, ent.name, gitdirPath);
13916
+ if (sameWorktreeMetadataPath((0, import_node_path22.dirname)(resolvedGitdir), worktreePath)) return true;
13767
13917
  } catch {
13768
13918
  }
13769
13919
  }
@@ -13773,7 +13923,7 @@ function metadataOwnsMissingWorktreeDir(worktreePath, worktreeGitRoot) {
13773
13923
  }
13774
13924
  function pathExistsKnown(path2) {
13775
13925
  try {
13776
- (0, import_node_fs21.statSync)(path2);
13926
+ (0, import_node_fs22.statSync)(path2);
13777
13927
  return true;
13778
13928
  } catch (e) {
13779
13929
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
@@ -13782,10 +13932,10 @@ function pathExistsKnown(path2) {
13782
13932
  }
13783
13933
  }
13784
13934
  function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
13785
- const gitPath = (0, import_node_path21.join)(path2, ".git");
13935
+ const gitPath = (0, import_node_path22.join)(path2, ".git");
13786
13936
  let st;
13787
13937
  try {
13788
- st = (0, import_node_fs21.lstatSync)(gitPath);
13938
+ st = (0, import_node_fs22.lstatSync)(gitPath);
13789
13939
  } catch (e) {
13790
13940
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
13791
13941
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -13802,7 +13952,7 @@ function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
13802
13952
  if (st.isDirectory()) return { path: path2, gitType: "dir" };
13803
13953
  if (!st.isFile()) return { path: path2, gitType: "other" };
13804
13954
  try {
13805
- const gitFileContent = (0, import_node_fs20.readFileSync)(gitPath, "utf8");
13955
+ const gitFileContent = (0, import_node_fs21.readFileSync)(gitPath, "utf8");
13806
13956
  const gitdir = resolveGitdirForWorktreeFile(path2, gitFileContent);
13807
13957
  const gitDirExists = gitdir ? pathExistsKnown(gitdir) : false;
13808
13958
  return {
@@ -13819,7 +13969,7 @@ function inspectSiblingWorktreeDir(path2, worktreeGitRoot) {
13819
13969
  }
13820
13970
  function inspectDeadWorktreeDirContent(path2) {
13821
13971
  try {
13822
- return { entries: (0, import_node_fs21.readdirSync)(path2) };
13972
+ return { entries: (0, import_node_fs22.readdirSync)(path2) };
13823
13973
  } catch (e) {
13824
13974
  const code = typeof e === "object" && e && "code" in e ? String(e.code ?? "") : "";
13825
13975
  return { error: code ? `unable to inspect directory contents (${code})` : "unable to inspect directory contents" };
@@ -13836,11 +13986,11 @@ async function preservedBranches() {
13836
13986
  async function siblingWorktreeDirs(explicitRoot) {
13837
13987
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
13838
13988
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
13839
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path21.dirname)((0, import_node_path21.dirname)(worktreeGitRoot)) : repoRoot2;
13989
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path22.dirname)((0, import_node_path22.dirname)(worktreeGitRoot)) : repoRoot2;
13840
13990
  try {
13841
13991
  const dirs = explicitRoot ? listDirsIn(resolveExplicitScanRoot(explicitRoot, primaryRepoRoot)) : worktreeScanDirs(siblingMmiWorktreesRoot(primaryRepoRoot), primaryRepoRoot, listDirsIn, isRepoCheckoutDir);
13842
13992
  const agentDirs = listDirsIn(agentWorktreesRoot(primaryRepoRoot));
13843
- const repoLocalWorktrees = listDirsIn((0, import_node_path21.join)(primaryRepoRoot, ".worktrees"));
13993
+ const repoLocalWorktrees = listDirsIn((0, import_node_path22.join)(primaryRepoRoot, ".worktrees"));
13844
13994
  return [...dirs, ...agentDirs, ...repoLocalWorktrees].map((dir) => inspectSiblingWorktreeDir(dir, worktreeGitRoot)).filter((entry) => Boolean(entry));
13845
13995
  } catch {
13846
13996
  return [];
@@ -13848,18 +13998,18 @@ async function siblingWorktreeDirs(explicitRoot) {
13848
13998
  }
13849
13999
  function listDirsIn(dir) {
13850
14000
  try {
13851
- return (0, import_node_fs21.readdirSync)(dir, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => (0, import_node_path21.join)(dir, ent.name));
14001
+ return (0, import_node_fs22.readdirSync)(dir, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => (0, import_node_path22.join)(dir, ent.name));
13852
14002
  } catch {
13853
14003
  return [];
13854
14004
  }
13855
14005
  }
13856
14006
  function isRepoCheckoutDir(dir) {
13857
- return (0, import_node_fs21.existsSync)((0, import_node_path21.join)(dir, ".git"));
14007
+ return (0, import_node_fs22.existsSync)((0, import_node_path22.join)(dir, ".git"));
13858
14008
  }
13859
14009
  function resolveExplicitScanRoot(explicitRoot, repoRoot2) {
13860
14010
  let rootDirs;
13861
14011
  try {
13862
- rootDirs = (0, import_node_fs21.readdirSync)(explicitRoot, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => ent.name);
14012
+ rootDirs = (0, import_node_fs22.readdirSync)(explicitRoot, { withFileTypes: true }).filter((ent) => ent.isDirectory()).map((ent) => ent.name);
13863
14013
  } catch {
13864
14014
  return explicitRoot;
13865
14015
  }
@@ -13890,6 +14040,38 @@ async function gcPlan(remote, limit, opts = {}) {
13890
14040
  ])].filter((b) => !isProtectedBranch(b)),
13891
14041
  limit
13892
14042
  );
14043
+ const primaryRoot = await primaryCheckoutRootOf(gitOut);
14044
+ const owners = primaryRoot ? readWorktreeOwners(primaryRoot) : [];
14045
+ const mergedSet = new Set(mergedIntoBase);
14046
+ const preservedSet = new Set(preserved);
14047
+ const failedLookups = new Set(failures.map((failure) => failure.branch));
14048
+ const openBranches = new Set(prs.filter((pr2) => pr2.state === "OPEN").map((pr2) => pr2.headRefName));
14049
+ const proofWorktrees = worktrees.filter((wt) => !wt.dirty && wt.branch !== current.trim() && !isProtectedBranch(wt.branch) && !preservedSet.has(wt.branch) && !mergedSet.has(wt.branch) && !failedLookups.has(wt.branch) && !openBranches.has(wt.branch));
14050
+ const trainTips = [];
14051
+ if (proofWorktrees.length) {
14052
+ for (const name of ["development", "main", "master"]) {
14053
+ const oid = (await gitOut(["rev-parse", "--verify", `${remote}/${name}`]).catch(() => "")).trim();
14054
+ if (oid) trainTips.push(oid);
14055
+ }
14056
+ }
14057
+ const headByBranch = new Map(heads.map((h) => [h.branch, h.oid]));
14058
+ const exactTreeLanded = [];
14059
+ const exactTreeRefusals = [];
14060
+ for (const wt of proofWorktrees) {
14061
+ const headOid = headByBranch.get(wt.branch);
14062
+ const owner = owners.find((entry) => sameWorktreeMetadataPath(entry.path, wt.path));
14063
+ if (!headOid || !owner || !primaryRoot) continue;
14064
+ const proof = await proveExactTreeDelivery({
14065
+ repoRoot: primaryRoot,
14066
+ branch: wt.branch,
14067
+ workerOid: headOid,
14068
+ creationBaseOid: owner.provenance?.creationBaseOid,
14069
+ recordedWorkerBranch: owner.provenance?.workerBranch,
14070
+ landedTips: trainTips
14071
+ });
14072
+ if (proof.action === "settle") exactTreeLanded.push({ branch: wt.branch, headOid, candidateOid: proof.candidateOid });
14073
+ else exactTreeRefusals.push({ branch: wt.branch, detail: describeExactTreeRefusal(proof) });
14074
+ }
13893
14075
  return buildGcPlan({
13894
14076
  localBranches,
13895
14077
  prLookupFailures: failures,
@@ -13902,6 +14084,8 @@ async function gcPlan(remote, limit, opts = {}) {
13902
14084
  remote,
13903
14085
  preservedBranches: preserved,
13904
14086
  mergedIntoBase,
14087
+ exactTreeLanded,
14088
+ exactTreeRefusals,
13905
14089
  originBranches,
13906
14090
  trainOnly: opts.trainOnly
13907
14091
  });
@@ -14200,10 +14384,10 @@ var rollout_plan_default = {
14200
14384
  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)."
14201
14385
  },
14202
14386
  baseline: {
14203
- version: "3.135.0",
14204
- tag: "v3.135.0",
14205
- commit: "3d9fbd6f4628",
14206
- npm: "@mutmutco/cli@3.135.0"
14387
+ version: "3.136.0",
14388
+ tag: "v3.136.0",
14389
+ commit: "acba68c21013",
14390
+ npm: "@mutmutco/cli@3.136.0"
14207
14391
  },
14208
14392
  exitCriterion: "fleet-n-of-n",
14209
14393
  hubOnlyShortcut: "forbidden",
@@ -14220,14 +14404,14 @@ var rollout_plan_default = {
14220
14404
  repo: "mutmutco/mmi-hub",
14221
14405
  role: "canary",
14222
14406
  schedule: "train",
14223
- v3Target: "v3.135.0"
14407
+ v3Target: "v3.136.0"
14224
14408
  }
14225
14409
  ],
14226
14410
  rollbackTrigger: "Any red inside the post-cut soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a v3 client refused while the compat window must still admit it (SUPPORTED_MINOR_WINDOW=2, MIN_CLIENT_VERSION 0.0.0 \u2014 D6a), or npm consumer install/doctor failure on the v4 dist.",
14227
14411
  rollback: {
14228
14412
  independent: true,
14229
- mechanism: "npm dist-tag latest -> 3.135.0 and redeploy the Hub Lambda from tag v3.135.0 (3d9fbd6f4628); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
14230
- v3Target: "v3.135.0 (@mutmutco/cli@3.135.0, tag commit 3d9fbd6f4628 \u2014 the preserved latest-v3 distribution, D6b)"
14413
+ mechanism: "npm dist-tag latest -> 3.136.0 and redeploy the Hub Lambda from tag v3.136.0 (acba68c21013); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
14414
+ v3Target: "v3.136.0 (@mutmutco/cli@3.136.0, tag commit acba68c21013 \u2014 the preserved latest-v3 distribution, D6b)"
14231
14415
  }
14232
14416
  },
14233
14417
  {
@@ -16311,7 +16495,7 @@ function planTrainApplyRepoGuard(applyRepo, cwdRepo, rerun) {
16311
16495
  async function resolveFoldPaths(deps, model) {
16312
16496
  const helper = "scripts/release-distribution.mjs";
16313
16497
  if (model === "hub-serverless" || model === "registry-publish") {
16314
- if ((0, import_node_fs22.existsSync)(helper)) {
16498
+ if ((0, import_node_fs23.existsSync)(helper)) {
16315
16499
  let out;
16316
16500
  try {
16317
16501
  out = await deps.run("node", [helper, "changed-files"]);
@@ -16430,7 +16614,7 @@ async function restoreMainNpmPackIdentities(deps, version) {
16430
16614
  if (mainBom.version !== version) return void 0;
16431
16615
  let localBom;
16432
16616
  try {
16433
- localBom = JSON.parse((0, import_node_fs22.readFileSync)(bomPath, "utf8"));
16617
+ localBom = JSON.parse((0, import_node_fs23.readFileSync)(bomPath, "utf8"));
16434
16618
  } catch (e) {
16435
16619
  throw new Error(
16436
16620
  `version fold refused: ${bomPath} written by this fold's prepare is unreadable (${describeReadError(e)}) \u2014 cannot restore the published ${version} npm-pack identities from origin/main (#4503/#4713).`
@@ -16448,14 +16632,14 @@ async function restoreMainNpmPackIdentities(deps, version) {
16448
16632
  restored += 1;
16449
16633
  }
16450
16634
  if (restored === 0) return void 0;
16451
- (0, import_node_fs22.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
16635
+ (0, import_node_fs23.writeFileSync)(bomPath, `${JSON.stringify(localBom, null, 2)}
16452
16636
  `);
16453
16637
  return `restored ${restored} npm-pack BOM identit${restored === 1 ? "y" : "ies"} from origin/main (#4503)`;
16454
16638
  }
16455
16639
  function publishVisibilityFor(surfaceId) {
16456
16640
  let raw;
16457
16641
  try {
16458
- raw = (0, import_node_fs22.readFileSync)("surfaces.json", "utf8");
16642
+ raw = (0, import_node_fs23.readFileSync)("surfaces.json", "utf8");
16459
16643
  } catch (e) {
16460
16644
  if (e.code === "ENOENT") return "unknown";
16461
16645
  throw trainReadFailure(
@@ -16476,7 +16660,7 @@ function publishVisibilityFor(surfaceId) {
16476
16660
  }
16477
16661
  function npmPackArtifactName(packagePath) {
16478
16662
  try {
16479
- const pkg = JSON.parse((0, import_node_fs22.readFileSync)((0, import_node_path22.join)(packagePath, "package.json"), "utf8"));
16663
+ const pkg = JSON.parse((0, import_node_fs23.readFileSync)((0, import_node_path23.join)(packagePath, "package.json"), "utf8"));
16480
16664
  return pkg.name || void 0;
16481
16665
  } catch {
16482
16666
  return void 0;
@@ -16485,7 +16669,7 @@ function npmPackArtifactName(packagePath) {
16485
16669
  async function refuseDivergentPublishedNpmPack(deps, version) {
16486
16670
  let localBom;
16487
16671
  try {
16488
- localBom = JSON.parse((0, import_node_fs22.readFileSync)("distribution-bom.json", "utf8"));
16672
+ localBom = JSON.parse((0, import_node_fs23.readFileSync)("distribution-bom.json", "utf8"));
16489
16673
  } catch (e) {
16490
16674
  throw new Error(
16491
16675
  `version fold refused: distribution-bom.json written by this fold's prepare is unreadable (${e instanceof Error ? e.message.split("\n")[0] : String(e)}) \u2014 cannot compare the same-PATCH ${version} npm-pack identities against published npm (#4503/#4662).`
@@ -17647,17 +17831,17 @@ async function dispatchDeploy(deps, ctx, stage, ref, model, watch, autoRunSince,
17647
17831
  return { note: `no manual dispatch: ${model} repo deploys via its own push-triggered workflow`, deployStatus: "pending" };
17648
17832
  }
17649
17833
  function readLocalGateWorkflows() {
17650
- const dir = (0, import_node_path22.join)(".github", "workflows");
17834
+ const dir = (0, import_node_path23.join)(".github", "workflows");
17651
17835
  let names;
17652
17836
  try {
17653
- names = (0, import_node_fs22.readdirSync)(dir);
17837
+ names = (0, import_node_fs23.readdirSync)(dir);
17654
17838
  } catch {
17655
17839
  return null;
17656
17840
  }
17657
17841
  const files = [];
17658
17842
  for (const name of names.filter(isGateWorkflowPath)) {
17659
17843
  try {
17660
- files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs22.readFileSync)((0, import_node_path22.join)(dir, name), "utf8") });
17844
+ files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
17661
17845
  } catch {
17662
17846
  }
17663
17847
  }
@@ -19875,12 +20059,12 @@ async function runPrLand(prNumber, options, deps) {
19875
20059
  }
19876
20060
 
19877
20061
  // src/wave-status.ts
19878
- var import_node_fs24 = require("node:fs");
20062
+ var import_node_fs25 = require("node:fs");
19879
20063
 
19880
20064
  // src/stage-runner.ts
19881
20065
  var import_node_child_process8 = require("node:child_process");
19882
- var import_node_fs23 = require("node:fs");
19883
- var import_node_path23 = require("node:path");
20066
+ var import_node_fs24 = require("node:fs");
20067
+ var import_node_path24 = require("node:path");
19884
20068
  var import_node_net = require("node:net");
19885
20069
  var import_node_util5 = require("node:util");
19886
20070
 
@@ -20019,11 +20203,11 @@ function appendForceRecreate(up) {
20019
20203
  return `${up.trimEnd()} --force-recreate`;
20020
20204
  }
20021
20205
  function stageStatePath(cwd = process.cwd()) {
20022
- return (0, import_node_path23.join)(cwd, "tmp", "stage", "state.json");
20206
+ return (0, import_node_path24.join)(cwd, "tmp", "stage", "state.json");
20023
20207
  }
20024
20208
  function stageGlobalStatePath(cwd = process.cwd(), gitCommonDir = ".git") {
20025
- const dir = (0, import_node_path23.isAbsolute)(gitCommonDir) ? gitCommonDir : (0, import_node_path23.resolve)(cwd, gitCommonDir);
20026
- return (0, import_node_path23.join)(dir, "mmi", "stage", "state.json");
20209
+ const dir = (0, import_node_path24.isAbsolute)(gitCommonDir) ? gitCommonDir : (0, import_node_path24.resolve)(cwd, gitCommonDir);
20210
+ return (0, import_node_path24.join)(dir, "mmi", "stage", "state.json");
20027
20211
  }
20028
20212
  function normPath3(path2) {
20029
20213
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -20247,14 +20431,14 @@ function stageProcessEnv(stagePort, extraEnv) {
20247
20431
  }
20248
20432
  async function ensureStageRuntimeEnv(config, opts, cwd) {
20249
20433
  if (!config.ensureEnv) return;
20250
- const target = (0, import_node_path23.join)(cwd, config.ensureEnv.target);
20251
- const example = (0, import_node_path23.join)(cwd, config.ensureEnv.example);
20252
- if (!(0, import_node_fs23.existsSync)(target) && (0, import_node_fs23.existsSync)(example)) {
20253
- (0, import_node_fs23.copyFileSync)(example, target);
20254
- } else if ((0, import_node_fs23.existsSync)(target) && (0, import_node_fs23.existsSync)(example)) {
20255
- const stale = detectStaleEnvFile((0, import_node_fs23.readFileSync)(example, "utf8"), (0, import_node_fs23.readFileSync)(target, "utf8"), {
20256
- exampleMtimeMs: (0, import_node_fs23.statSync)(example).mtimeMs,
20257
- targetMtimeMs: (0, import_node_fs23.statSync)(target).mtimeMs
20434
+ const target = (0, import_node_path24.join)(cwd, config.ensureEnv.target);
20435
+ const example = (0, import_node_path24.join)(cwd, config.ensureEnv.example);
20436
+ if (!(0, import_node_fs24.existsSync)(target) && (0, import_node_fs24.existsSync)(example)) {
20437
+ (0, import_node_fs24.copyFileSync)(example, target);
20438
+ } else if ((0, import_node_fs24.existsSync)(target) && (0, import_node_fs24.existsSync)(example)) {
20439
+ const stale = detectStaleEnvFile((0, import_node_fs24.readFileSync)(example, "utf8"), (0, import_node_fs24.readFileSync)(target, "utf8"), {
20440
+ exampleMtimeMs: (0, import_node_fs24.statSync)(example).mtimeMs,
20441
+ targetMtimeMs: (0, import_node_fs24.statSync)(target).mtimeMs
20258
20442
  });
20259
20443
  if (stale) {
20260
20444
  const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running /stage`;
@@ -20262,8 +20446,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
20262
20446
  console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
20263
20447
  }
20264
20448
  }
20265
- if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs23.existsSync)(target)) {
20266
- (0, import_node_fs23.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs23.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
20449
+ if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs24.existsSync)(target)) {
20450
+ (0, import_node_fs24.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs24.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
20267
20451
  }
20268
20452
  }
20269
20453
  async function gitText(cwd, args) {
@@ -20293,20 +20477,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
20293
20477
  return void 0;
20294
20478
  }
20295
20479
  function readState(path2) {
20296
- if (!(0, import_node_fs23.existsSync)(path2)) return null;
20480
+ if (!(0, import_node_fs24.existsSync)(path2)) return null;
20297
20481
  try {
20298
- return JSON.parse((0, import_node_fs23.readFileSync)(path2, "utf8"));
20482
+ return JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8"));
20299
20483
  } catch {
20300
20484
  return null;
20301
20485
  }
20302
20486
  }
20303
20487
  function mkdirFor(path2) {
20304
20488
  const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
20305
- (0, import_node_fs23.mkdirSync)(dir, { recursive: true });
20489
+ (0, import_node_fs24.mkdirSync)(dir, { recursive: true });
20306
20490
  }
20307
20491
  function writeState(path2, state) {
20308
20492
  mkdirFor(path2);
20309
- (0, import_node_fs23.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
20493
+ (0, import_node_fs24.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
20310
20494
  }
20311
20495
  function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
20312
20496
  const reservation = {
@@ -20326,7 +20510,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd) {
20326
20510
  await shell(state.teardown.command.trim(), state.teardown.cwd || state.cwd || fallbackCwd, Math.max(timeoutMs, 1e4));
20327
20511
  }
20328
20512
  for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
20329
- (0, import_node_fs23.rmSync)(path2, { force: true });
20513
+ (0, import_node_fs24.rmSync)(path2, { force: true });
20330
20514
  }
20331
20515
  }
20332
20516
  async function killTree(pid) {
@@ -20484,8 +20668,8 @@ async function runStage(config = {}, opts = {}) {
20484
20668
  await ensureStageRuntimeEnv(config, opts, cwd);
20485
20669
  if (build) await shell(sub(build), cwd, timeoutMs, stageProcessEnv(stagePort, extraEnv));
20486
20670
  } catch (e) {
20487
- (0, import_node_fs23.rmSync)(statePath, { force: true });
20488
- if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs23.rmSync)(globalStatePath, { force: true });
20671
+ (0, import_node_fs24.rmSync)(statePath, { force: true });
20672
+ if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs24.rmSync)(globalStatePath, { force: true });
20489
20673
  throw e;
20490
20674
  }
20491
20675
  const started = await startStage(config, {
@@ -20506,9 +20690,9 @@ function parseNextFromHead(headText) {
20506
20690
  }
20507
20691
  function readStageSummary(worktreePath) {
20508
20692
  const statePath = stageStatePath(worktreePath);
20509
- if (!(0, import_node_fs24.existsSync)(statePath)) return void 0;
20693
+ if (!(0, import_node_fs25.existsSync)(statePath)) return void 0;
20510
20694
  try {
20511
- const state = JSON.parse((0, import_node_fs24.readFileSync)(statePath, "utf8"));
20695
+ const state = JSON.parse((0, import_node_fs25.readFileSync)(statePath, "utf8"));
20512
20696
  const port = typeof state.port === "number" ? state.port : void 0;
20513
20697
  if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
20514
20698
  return { port, url: typeof state.url === "string" ? state.url : void 0 };
@@ -20613,13 +20797,13 @@ async function executeWaveLand(plan, deps, opts = { preserveWorktree: true }) {
20613
20797
  }
20614
20798
 
20615
20799
  // src/index.ts
20616
- var import_node_os20 = require("node:os");
20800
+ var import_node_os21 = require("node:os");
20617
20801
 
20618
20802
  // src/board.ts
20619
20803
  var import_node_child_process9 = require("node:child_process");
20620
- var import_node_fs25 = require("node:fs");
20621
- var import_node_os9 = require("node:os");
20622
- var import_node_path24 = require("node:path");
20804
+ var import_node_fs26 = require("node:fs");
20805
+ var import_node_os10 = require("node:os");
20806
+ var import_node_path25 = require("node:path");
20623
20807
  var import_node_util6 = require("node:util");
20624
20808
 
20625
20809
  // src/board-dependency.ts
@@ -22229,7 +22413,7 @@ var CLAIM_SESSION_ACTIVITY_MS = 30 * 6e4;
22229
22413
  var CLAIM_SESSION_PROBE_CACHE_MS = 6e4;
22230
22414
  var claimSessionProbeCache = /* @__PURE__ */ new Map();
22231
22415
  function probeLocalClaimSession(marker, now = Date.now()) {
22232
- if (!marker.session || !marker.host || marker.host.toLowerCase() !== (0, import_node_os9.hostname)().toLowerCase()) return void 0;
22416
+ if (!marker.session || !marker.host || marker.host.toLowerCase() !== (0, import_node_os10.hostname)().toLowerCase()) return void 0;
22233
22417
  if (!marker.surface?.toLowerCase().startsWith("claude")) return void 0;
22234
22418
  const cacheKey = `${marker.host.toLowerCase()}/${marker.session}`;
22235
22419
  const cached = claimSessionProbeCache.get(cacheKey);
@@ -22238,17 +22422,17 @@ function probeLocalClaimSession(marker, now = Date.now()) {
22238
22422
  claimSessionProbeCache.set(cacheKey, { checkedAt: now, state });
22239
22423
  return state;
22240
22424
  };
22241
- const root = (0, import_node_path24.join)((0, import_node_os9.homedir)(), ".claude", "projects");
22425
+ const root = (0, import_node_path25.join)((0, import_node_os10.homedir)(), ".claude", "projects");
22242
22426
  try {
22243
22427
  const wanted = `${marker.session}.jsonl`.toLowerCase();
22244
22428
  const pending = [root];
22245
22429
  while (pending.length) {
22246
22430
  const dir = pending.pop();
22247
- for (const entry of (0, import_node_fs25.readdirSync)(dir, { withFileTypes: true })) {
22248
- const path2 = (0, import_node_path24.join)(dir, entry.name);
22431
+ for (const entry of (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true })) {
22432
+ const path2 = (0, import_node_path25.join)(dir, entry.name);
22249
22433
  if (entry.isDirectory()) pending.push(path2);
22250
22434
  else if (entry.isFile() && entry.name.toLowerCase() === wanted) {
22251
- return remember(now - (0, import_node_fs25.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
22435
+ return remember(now - (0, import_node_fs26.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
22252
22436
  }
22253
22437
  }
22254
22438
  }
@@ -22536,7 +22720,7 @@ async function resolveAutoAddBoardAttach(client, cfg, selector, priority, warn =
22536
22720
  }
22537
22721
 
22538
22722
  // src/issue-body.ts
22539
- var import_node_os10 = require("node:os");
22723
+ var import_node_os11 = require("node:os");
22540
22724
  var TextArgError = class extends Error {
22541
22725
  constructor(message, code, offendingFlag) {
22542
22726
  super(message);
@@ -22548,7 +22732,7 @@ var TextArgError = class extends Error {
22548
22732
  offendingFlag;
22549
22733
  };
22550
22734
  function emptyStdinMessage(fileFlag) {
22551
- if ((0, import_node_os10.platform)() === "win32") {
22735
+ if ((0, import_node_os11.platform)() === "win32") {
22552
22736
  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)`;
22553
22737
  }
22554
22738
  return `${fileFlag} - read empty stdin (nothing piped \u2014 pass a heredoc/pipe, or ${fileFlag} <path>)`;
@@ -22785,6 +22969,13 @@ function applyCommandTaxonomy(program3) {
22785
22969
  }
22786
22970
  program3.configureHelp({
22787
22971
  ...REQUIRED_OPTION_HELP,
22972
+ // #5014: the root help must show the CANONICAL house-prefixed term (`oracle board`, `devops pr`),
22973
+ // not the retired flat leaf name — an agent grounding on `mmi-cli help` and running the flat name
22974
+ // hits the Wave 3 refusal. `canonicalPathFor` is the identity for `core`, so core stays unprefixed.
22975
+ subcommandTerm(command) {
22976
+ const stock = Help.prototype.subcommandTerm.call(this, command);
22977
+ return `${canonicalPathFor(command.name()) ?? command.name()}${stock.slice(command.name().length)}`;
22978
+ },
22788
22979
  visibleCommands(command) {
22789
22980
  const visible = command.commands.filter((child2) => !child2._hidden);
22790
22981
  const helpCommand = command._getHelpCommand();
@@ -23149,20 +23340,20 @@ function consolidateCommandNamespaces(program3) {
23149
23340
  }
23150
23341
 
23151
23342
  // src/claude-binary-doctor.ts
23343
+ var import_node_fs28 = require("node:fs");
23344
+ var import_node_os13 = require("node:os");
23345
+ var import_node_path27 = require("node:path");
23346
+
23347
+ // src/jerv-cli-spawn.ts
23152
23348
  var import_node_fs27 = require("node:fs");
23153
23349
  var import_node_os12 = require("node:os");
23154
23350
  var import_node_path26 = require("node:path");
23155
-
23156
- // src/jerv-cli-spawn.ts
23157
- var import_node_fs26 = require("node:fs");
23158
- var import_node_os11 = require("node:os");
23159
- var import_node_path25 = require("node:path");
23160
23351
  var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
23161
23352
  var POSIX_NAMES = ["jerv-cli"];
23162
- var JERV_CLI_ENTRY = (0, import_node_path25.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
23353
+ var JERV_CLI_ENTRY = (0, import_node_path26.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
23163
23354
  function pathEnvEntries(pathEnv, platform2 = process.platform) {
23164
23355
  if (platform2 !== "win32") {
23165
- return pathEnv.split(import_node_path25.delimiter).map((e) => e.trim()).filter(Boolean);
23356
+ return pathEnv.split(import_node_path26.delimiter).map((e) => e.trim()).filter(Boolean);
23166
23357
  }
23167
23358
  if (pathEnv.includes(";")) {
23168
23359
  return pathEnv.split(";").map((e) => e.trim()).filter(Boolean);
@@ -23181,7 +23372,7 @@ function normalizeSpawnPathEntry(entry, platform2 = process.platform) {
23181
23372
  if (msys) return `${msys[1].toUpperCase()}:\\${msys[2].replace(/\//g, "\\")}`;
23182
23373
  return trimmed;
23183
23374
  }
23184
- function jervCliCandidateDirs(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform) {
23375
+ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform) {
23185
23376
  const seen = /* @__PURE__ */ new Set();
23186
23377
  const out = [];
23187
23378
  const push = (dir) => {
@@ -23195,35 +23386,35 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os11.hom
23195
23386
  push(normalizeSpawnPathEntry(entry, platform2));
23196
23387
  }
23197
23388
  if (platform2 === "win32") {
23198
- if (env.APPDATA) push((0, import_node_path25.join)(env.APPDATA, "npm"));
23199
- if (env.LOCALAPPDATA) push((0, import_node_path25.join)(env.LOCALAPPDATA, "npm"));
23389
+ if (env.APPDATA) push((0, import_node_path26.join)(env.APPDATA, "npm"));
23390
+ if (env.LOCALAPPDATA) push((0, import_node_path26.join)(env.LOCALAPPDATA, "npm"));
23200
23391
  } else {
23201
- push((0, import_node_path25.join)(home, ".local", "bin"));
23392
+ push((0, import_node_path26.join)(home, ".local", "bin"));
23202
23393
  }
23203
23394
  return out;
23204
23395
  }
23205
- function jervCliCandidatePaths(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform) {
23396
+ function jervCliCandidatePaths(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform) {
23206
23397
  const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
23207
23398
  const out = [];
23208
23399
  for (const dir of jervCliCandidateDirs(env, home, platform2)) {
23209
- for (const name of names) out.push((0, import_node_path25.join)(dir, name));
23400
+ for (const name of names) out.push((0, import_node_path26.join)(dir, name));
23210
23401
  }
23211
23402
  return out;
23212
23403
  }
23213
- function resolveJervCliPath(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform, exists = import_node_fs26.existsSync) {
23404
+ function resolveJervCliPath(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform, exists = import_node_fs27.existsSync) {
23214
23405
  for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
23215
23406
  if (exists(candidate)) return candidate;
23216
23407
  }
23217
23408
  return void 0;
23218
23409
  }
23219
- function resolveJervCliNodeEntry(shimPath, exists = import_node_fs26.existsSync) {
23220
- const entry = (0, import_node_path25.join)((0, import_node_path25.dirname)(shimPath), JERV_CLI_ENTRY);
23410
+ function resolveJervCliNodeEntry(shimPath, exists = import_node_fs27.existsSync) {
23411
+ const entry = (0, import_node_path26.join)((0, import_node_path26.dirname)(shimPath), JERV_CLI_ENTRY);
23221
23412
  return exists(entry) ? entry : void 0;
23222
23413
  }
23223
23414
  function jervCliExecFileArgs(args, opts = {}) {
23224
23415
  const platform2 = opts.platform ?? process.platform;
23225
- const exists = opts.exists ?? import_node_fs26.existsSync;
23226
- const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os11.homedir)(), platform2, exists);
23416
+ const exists = opts.exists ?? import_node_fs27.existsSync;
23417
+ const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os12.homedir)(), platform2, exists);
23227
23418
  if (resolved) {
23228
23419
  const entry = resolveJervCliNodeEntry(resolved, exists);
23229
23420
  if (entry) {
@@ -23312,26 +23503,26 @@ function globalNodeModulesRoots(host) {
23312
23503
  out.push(dir);
23313
23504
  };
23314
23505
  const prefix = env.npm_config_prefix?.trim();
23315
- if (prefix) push(platform2 === "win32" ? (0, import_node_path26.join)(prefix, "node_modules") : (0, import_node_path26.join)(prefix, "lib", "node_modules"));
23316
- for (const dir of jervCliCandidateDirs(env, host.home ?? (0, import_node_os12.homedir)(), platform2)) {
23317
- push((0, import_node_path26.join)(dir, "node_modules"));
23318
- push((0, import_node_path26.join)((0, import_node_path26.dirname)(dir), "lib", "node_modules"));
23506
+ if (prefix) push(platform2 === "win32" ? (0, import_node_path27.join)(prefix, "node_modules") : (0, import_node_path27.join)(prefix, "lib", "node_modules"));
23507
+ for (const dir of jervCliCandidateDirs(env, host.home ?? (0, import_node_os13.homedir)(), platform2)) {
23508
+ push((0, import_node_path27.join)(dir, "node_modules"));
23509
+ push((0, import_node_path27.join)((0, import_node_path27.dirname)(dir), "lib", "node_modules"));
23319
23510
  }
23320
23511
  return out;
23321
23512
  }
23322
23513
  function readHead(path2) {
23323
23514
  let fd;
23324
23515
  try {
23325
- fd = (0, import_node_fs27.openSync)(path2, "r");
23516
+ fd = (0, import_node_fs28.openSync)(path2, "r");
23326
23517
  const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
23327
- const read = (0, import_node_fs27.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
23518
+ const read = (0, import_node_fs28.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
23328
23519
  return buffer.subarray(0, read);
23329
23520
  } catch {
23330
23521
  return void 0;
23331
23522
  } finally {
23332
23523
  if (fd !== void 0) {
23333
23524
  try {
23334
- (0, import_node_fs27.closeSync)(fd);
23525
+ (0, import_node_fs28.closeSync)(fd);
23335
23526
  } catch {
23336
23527
  }
23337
23528
  }
@@ -23339,7 +23530,7 @@ function readHead(path2) {
23339
23530
  }
23340
23531
  function fileBytes(path2) {
23341
23532
  try {
23342
- return (0, import_node_fs27.statSync)(path2).size;
23533
+ return (0, import_node_fs28.statSync)(path2).size;
23343
23534
  } catch {
23344
23535
  return void 0;
23345
23536
  }
@@ -23353,17 +23544,17 @@ function readClaudeBinaryState(host = {}) {
23353
23544
  const arch = host.arch ?? process.arch;
23354
23545
  const magic = EXECUTABLE_MAGIC[platform2];
23355
23546
  if (!magic) return void 0;
23356
- const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path26.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs27.existsSync)((0, import_node_path26.join)(dir, "package.json")));
23547
+ const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path27.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs28.existsSync)((0, import_node_path27.join)(dir, "package.json")));
23357
23548
  if (!packageRoot) return void 0;
23358
23549
  const keys = platformPackageKeys(platform2, arch);
23359
23550
  const fallbackPackage = `${PACKAGE}-${keys[0]}`;
23360
23551
  let manifest;
23361
23552
  try {
23362
- manifest = JSON.parse((0, import_node_fs27.readFileSync)((0, import_node_path26.join)(packageRoot, "package.json"), "utf8"));
23553
+ manifest = JSON.parse((0, import_node_fs28.readFileSync)((0, import_node_path27.join)(packageRoot, "package.json"), "utf8"));
23363
23554
  } catch (e) {
23364
23555
  return {
23365
23556
  state: "unreadable",
23366
- binPath: (0, import_node_path26.join)(packageRoot, "package.json"),
23557
+ binPath: (0, import_node_path27.join)(packageRoot, "package.json"),
23367
23558
  expectedMagic: magic.name,
23368
23559
  platformPackage: fallbackPackage,
23369
23560
  error: `package.json could not be read \u2014 ${e.message}`
@@ -23380,17 +23571,17 @@ function readClaudeBinaryState(host = {}) {
23380
23571
  error: "package.json declares no `bin` entry \u2014 the executed file cannot be resolved"
23381
23572
  };
23382
23573
  }
23383
- const binPath = (0, import_node_path26.join)(packageRoot, binRelative);
23384
- const binName = (0, import_node_path26.basename)(binRelative);
23574
+ const binPath = (0, import_node_path27.join)(packageRoot, binRelative);
23575
+ const binName = (0, import_node_path27.basename)(binRelative);
23385
23576
  const optional = manifest.optionalDependencies;
23386
23577
  const publishes = (name) => typeof optional === "object" && optional !== null && Object.prototype.hasOwnProperty.call(optional, name);
23387
23578
  const published = keys.map((key) => `${PACKAGE}-${key}`).filter(publishes);
23388
23579
  if (published.length === 0) return void 0;
23389
23580
  const binIn = (name) => [
23390
- (0, import_node_path26.join)(packageRoot, "node_modules", ...name.split("/"), binName),
23391
- (0, import_node_path26.join)((0, import_node_path26.dirname)((0, import_node_path26.dirname)(packageRoot)), ...name.split("/"), binName)
23581
+ (0, import_node_path27.join)(packageRoot, "node_modules", ...name.split("/"), binName),
23582
+ (0, import_node_path27.join)((0, import_node_path27.dirname)((0, import_node_path27.dirname)(packageRoot)), ...name.split("/"), binName)
23392
23583
  ];
23393
- const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs27.existsSync)(file)) })).find((c) => c.path);
23584
+ const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs28.existsSync)(file)) })).find((c) => c.path);
23394
23585
  const platformPackage = found?.name ?? published[0];
23395
23586
  let source;
23396
23587
  let sourceProblem;
@@ -23401,7 +23592,7 @@ function readClaudeBinaryState(host = {}) {
23401
23592
  } else {
23402
23593
  source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
23403
23594
  }
23404
- if (!(0, import_node_fs27.existsSync)(binPath)) {
23595
+ if (!(0, import_node_fs28.existsSync)(binPath)) {
23405
23596
  return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
23406
23597
  }
23407
23598
  const head = readHead(binPath);
@@ -23444,9 +23635,9 @@ function healClaudeBinary(host = {}, onStep) {
23444
23635
  const platform2 = host.platform ?? process.platform;
23445
23636
  const aside = `${probe.binPath}.stub-${Date.now()}`;
23446
23637
  let renamed = false;
23447
- if ((0, import_node_fs27.existsSync)(probe.binPath)) {
23638
+ if ((0, import_node_fs28.existsSync)(probe.binPath)) {
23448
23639
  try {
23449
- (0, import_node_fs27.renameSync)(probe.binPath, aside);
23640
+ (0, import_node_fs28.renameSync)(probe.binPath, aside);
23450
23641
  renamed = true;
23451
23642
  onStep?.(`renamed the stub aside: ${aside}`);
23452
23643
  } catch (e) {
@@ -23455,12 +23646,12 @@ function healClaudeBinary(host = {}, onStep) {
23455
23646
  }
23456
23647
  try {
23457
23648
  onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
23458
- (0, import_node_fs27.copyFileSync)(probe.source.path, probe.binPath);
23459
- if (platform2 !== "win32") (0, import_node_fs27.chmodSync)(probe.binPath, 493);
23649
+ (0, import_node_fs28.copyFileSync)(probe.source.path, probe.binPath);
23650
+ if (platform2 !== "win32") (0, import_node_fs28.chmodSync)(probe.binPath, 493);
23460
23651
  } catch (e) {
23461
23652
  if (renamed) {
23462
23653
  try {
23463
- (0, import_node_fs27.renameSync)(aside, probe.binPath);
23654
+ (0, import_node_fs28.renameSync)(aside, probe.binPath);
23464
23655
  } catch {
23465
23656
  return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
23466
23657
  }
@@ -23474,7 +23665,7 @@ function healClaudeBinary(host = {}, onStep) {
23474
23665
  let kept = false;
23475
23666
  if (renamed) {
23476
23667
  try {
23477
- (0, import_node_fs27.rmSync)(aside);
23668
+ (0, import_node_fs28.rmSync)(aside);
23478
23669
  } catch {
23479
23670
  kept = true;
23480
23671
  }
@@ -23952,19 +24143,19 @@ function renderVerifyBroker(input) {
23952
24143
 
23953
24144
  // src/tenant-artifact.ts
23954
24145
  var import_node_crypto4 = require("node:crypto");
23955
- var import_node_fs28 = require("node:fs");
24146
+ var import_node_fs29 = require("node:fs");
23956
24147
  var import_promises5 = require("node:fs/promises");
23957
- var import_node_path27 = require("node:path");
24148
+ var import_node_path28 = require("node:path");
23958
24149
  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}$/;
23959
24150
  var MAX_BYTES = 5 * 1024 * 1024 * 1024;
23960
24151
  async function sha256File(path2) {
23961
24152
  const hash = (0, import_node_crypto4.createHash)("sha256");
23962
- for await (const chunk of (0, import_node_fs28.createReadStream)(path2)) hash.update(chunk);
24153
+ for await (const chunk of (0, import_node_fs29.createReadStream)(path2)) hash.update(chunk);
23963
24154
  return hash.digest("hex");
23964
24155
  }
23965
24156
  async function putTenantArtifact(repo, stage, inputPath, deps) {
23966
24157
  if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
23967
- const path2 = (0, import_node_path27.resolve)(inputPath);
24158
+ const path2 = (0, import_node_path28.resolve)(inputPath);
23968
24159
  const info = await (0, import_promises5.stat)(path2);
23969
24160
  if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
23970
24161
  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`);
@@ -23982,7 +24173,7 @@ async function putTenantArtifact(repo, stage, inputPath, deps) {
23982
24173
  return [key, value];
23983
24174
  }));
23984
24175
  headers["content-length"] = String(info.size);
23985
- const stream = (0, import_node_fs28.createReadStream)(path2);
24176
+ const stream = (0, import_node_fs29.createReadStream)(path2);
23986
24177
  let uploaded;
23987
24178
  try {
23988
24179
  uploaded = await fetch(body.uploadUrl, {
@@ -25100,8 +25291,8 @@ async function announceRelease(deps, args) {
25100
25291
  // src/repo-index.ts
25101
25292
  var import_node_crypto5 = require("node:crypto");
25102
25293
  var import_node_child_process12 = require("node:child_process");
25103
- var import_node_fs29 = require("node:fs");
25104
- var import_node_path28 = require("node:path");
25294
+ var import_node_fs30 = require("node:fs");
25295
+ var import_node_path29 = require("node:path");
25105
25296
  var REPO_INDEX_SCHEMA = 1;
25106
25297
  var HARD_DENY = [
25107
25298
  /(^|\/)\.env(\.|$)/i,
@@ -25226,11 +25417,11 @@ function loadReadmeHints(cwd, candidatePaths) {
25226
25417
  }
25227
25418
  for (const rel of readmes) {
25228
25419
  if (isHardDeniedPath(rel)) continue;
25229
- const abs = (0, import_node_path28.join)(cwd, ...rel.split("/"));
25230
- if (!(0, import_node_fs29.existsSync)(abs)) continue;
25420
+ const abs = (0, import_node_path29.join)(cwd, ...rel.split("/"));
25421
+ if (!(0, import_node_fs30.existsSync)(abs)) continue;
25231
25422
  let text;
25232
25423
  try {
25233
- text = (0, import_node_fs29.readFileSync)(abs, "utf8");
25424
+ text = (0, import_node_fs30.readFileSync)(abs, "utf8");
25234
25425
  } catch {
25235
25426
  continue;
25236
25427
  }
@@ -25243,7 +25434,7 @@ function loadReadmeHints(cwd, candidatePaths) {
25243
25434
  return hints;
25244
25435
  }
25245
25436
  function toPosix(p) {
25246
- return p.split(import_node_path28.sep).join("/");
25437
+ return p.split(import_node_path29.sep).join("/");
25247
25438
  }
25248
25439
  function listCandidatePaths(cwd, exec = import_node_child_process12.execFileSync) {
25249
25440
  try {
@@ -25265,11 +25456,11 @@ function rebuildRepoIndex(cwd, repoSlug2) {
25265
25456
  for (const rel of candidates) {
25266
25457
  if (ignored.has(rel)) continue;
25267
25458
  if (isHardDeniedPath(rel)) continue;
25268
- const abs = (0, import_node_path28.join)(cwd, ...rel.split("/"));
25269
- if (!(0, import_node_fs29.existsSync)(abs)) continue;
25459
+ const abs = (0, import_node_path29.join)(cwd, ...rel.split("/"));
25460
+ if (!(0, import_node_fs30.existsSync)(abs)) continue;
25270
25461
  let text;
25271
25462
  try {
25272
- text = (0, import_node_fs29.readFileSync)(abs, "utf8");
25463
+ text = (0, import_node_fs30.readFileSync)(abs, "utf8");
25273
25464
  } catch {
25274
25465
  continue;
25275
25466
  }
@@ -25294,16 +25485,16 @@ function rebuildRepoIndex(cwd, repoSlug2) {
25294
25485
  entries
25295
25486
  };
25296
25487
  const store = repoIndexStorePath(cwd);
25297
- (0, import_node_fs29.mkdirSync)((0, import_node_path28.dirname)(store), { recursive: true });
25298
- (0, import_node_fs29.writeFileSync)(store, `${JSON.stringify(projection, null, 2)}
25488
+ (0, import_node_fs30.mkdirSync)((0, import_node_path29.dirname)(store), { recursive: true });
25489
+ (0, import_node_fs30.writeFileSync)(store, `${JSON.stringify(projection, null, 2)}
25299
25490
  `, "utf8");
25300
25491
  return projection;
25301
25492
  }
25302
25493
  function loadRepoIndex(cwd) {
25303
25494
  const store = repoIndexStorePath(cwd);
25304
- if (!(0, import_node_fs29.existsSync)(store)) return null;
25495
+ if (!(0, import_node_fs30.existsSync)(store)) return null;
25305
25496
  try {
25306
- const raw = JSON.parse((0, import_node_fs29.readFileSync)(store, "utf8"));
25497
+ const raw = JSON.parse((0, import_node_fs30.readFileSync)(store, "utf8"));
25307
25498
  if (raw?.schema !== REPO_INDEX_SCHEMA || !Array.isArray(raw.entries)) return null;
25308
25499
  return raw;
25309
25500
  } catch {
@@ -25375,7 +25566,7 @@ function inferRepoSlug(cwd, exec = import_node_child_process12.execFileSync) {
25375
25566
  if (m?.[1]) return m[1].toLowerCase();
25376
25567
  } catch {
25377
25568
  }
25378
- return ((0, import_node_path28.basename)(cwd) || "local").toLowerCase();
25569
+ return ((0, import_node_path29.basename)(cwd) || "local").toLowerCase();
25379
25570
  }
25380
25571
 
25381
25572
  // src/repo-index-cloud-client.ts
@@ -25515,9 +25706,9 @@ async function gcRepoIndexCloud(deps) {
25515
25706
  }
25516
25707
 
25517
25708
  // src/repo-index-sync.ts
25518
- var import_node_fs30 = require("node:fs");
25519
- var import_node_os13 = require("node:os");
25520
- var import_node_path29 = require("node:path");
25709
+ var import_node_fs31 = require("node:fs");
25710
+ var import_node_os14 = require("node:os");
25711
+ var import_node_path30 = require("node:path");
25521
25712
  var import_node_child_process13 = require("node:child_process");
25522
25713
  var MAX_EMBED_BACKFILL_ROUNDS = 40;
25523
25714
  function normalizeRepo(raw) {
@@ -25561,7 +25752,7 @@ async function syncEstateRepoIndex(opts) {
25561
25752
  const failed = [];
25562
25753
  const skipped = [];
25563
25754
  for (const repo of repos) {
25564
- const dir = (0, import_node_fs30.mkdtempSync)((0, import_node_path29.join)((0, import_node_os13.tmpdir)(), "mmi-repo-index-"));
25755
+ const dir = (0, import_node_fs31.mkdtempSync)((0, import_node_path30.join)((0, import_node_os14.tmpdir)(), "mmi-repo-index-"));
25565
25756
  try {
25566
25757
  shallowClone(repo, dir, opts.githubToken);
25567
25758
  const built = rebuildRepoIndex(dir, repo);
@@ -25611,7 +25802,7 @@ async function syncEstateRepoIndex(opts) {
25611
25802
  failed.push({ repo, error: e.message });
25612
25803
  } finally {
25613
25804
  try {
25614
- (0, import_node_fs30.rmSync)(dir, { recursive: true, force: true });
25805
+ (0, import_node_fs31.rmSync)(dir, { recursive: true, force: true });
25615
25806
  } catch {
25616
25807
  }
25617
25808
  }
@@ -25620,7 +25811,7 @@ async function syncEstateRepoIndex(opts) {
25620
25811
  }
25621
25812
 
25622
25813
  // src/repo-index-health.ts
25623
- var import_node_fs31 = require("node:fs");
25814
+ var import_node_fs32 = require("node:fs");
25624
25815
 
25625
25816
  // testdata/repo-index-golden-queries.json
25626
25817
  var repo_index_golden_queries_default = {
@@ -25662,7 +25853,7 @@ function assertGoldenSuite(raw, source) {
25662
25853
  function loadGoldenSuite(path2) {
25663
25854
  let text;
25664
25855
  try {
25665
- text = (0, import_node_fs31.readFileSync)(path2, "utf8");
25856
+ text = (0, import_node_fs32.readFileSync)(path2, "utf8");
25666
25857
  } catch (e) {
25667
25858
  throw new Error(`golden suite unreadable at ${path2}: ${e.message}`);
25668
25859
  }
@@ -25816,8 +26007,8 @@ async function runRepoIndexHealth(opts) {
25816
26007
 
25817
26008
  // src/spawn-policy-core.ts
25818
26009
  var import_node_child_process14 = require("node:child_process");
25819
- var import_node_fs32 = require("node:fs");
25820
- var import_node_path30 = require("node:path");
26010
+ var import_node_fs33 = require("node:fs");
26011
+ var import_node_path31 = require("node:path");
25821
26012
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
25822
26013
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
25823
26014
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -25903,7 +26094,7 @@ function runSpawnPolicy(root) {
25903
26094
  for (const file of files) {
25904
26095
  let raw;
25905
26096
  try {
25906
- raw = (0, import_node_fs32.readFileSync)((0, import_node_path30.join)(root, file), "utf8");
26097
+ raw = (0, import_node_fs33.readFileSync)((0, import_node_path31.join)(root, file), "utf8");
25907
26098
  } catch {
25908
26099
  continue;
25909
26100
  }
@@ -25921,8 +26112,8 @@ function runSpawnPolicy(root) {
25921
26112
 
25922
26113
  // src/test-policy-core.ts
25923
26114
  var import_node_child_process15 = require("node:child_process");
25924
- var import_node_fs33 = require("node:fs");
25925
- var import_node_path31 = require("node:path");
26115
+ var import_node_fs34 = require("node:fs");
26116
+ var import_node_path32 = require("node:path");
25926
26117
  var POLICY_FILE = "test-policy.json";
25927
26118
  var TEST_RE = /\.(?:test|spec)\.[cm]?[jt]sx?$/;
25928
26119
  var PY_TEST_RE = /(?:^|\/)test_[^/]*\.py$|_test\.py$/;
@@ -25975,7 +26166,7 @@ function isTestPath(path2) {
25975
26166
  return TEST_RE.test(path2) || PY_TEST_RE.test(path2);
25976
26167
  }
25977
26168
  function loadPolicy(root, readFile9 = readFileOrNull2) {
25978
- const raw = readFile9((0, import_node_path31.join)(root, POLICY_FILE));
26169
+ const raw = readFile9((0, import_node_path32.join)(root, POLICY_FILE));
25979
26170
  if (raw == null) return { mandatory: [], declared: false };
25980
26171
  try {
25981
26172
  return { ...JSON.parse(raw), declared: true };
@@ -25985,7 +26176,7 @@ function loadPolicy(root, readFile9 = readFileOrNull2) {
25985
26176
  }
25986
26177
  function readFileOrNull2(path2) {
25987
26178
  try {
25988
- return (0, import_node_fs33.readFileSync)(path2, "utf8");
26179
+ return (0, import_node_fs34.readFileSync)(path2, "utf8");
25989
26180
  } catch {
25990
26181
  return null;
25991
26182
  }
@@ -26012,12 +26203,12 @@ function classify(changed, policy, present = () => false) {
26012
26203
  const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
26013
26204
  return { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected };
26014
26205
  }
26015
- function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs33.existsSync)(path2)) {
26016
- return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path31.join)(root, p)));
26206
+ function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs34.existsSync)(path2)) {
26207
+ return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path32.join)(root, p)));
26017
26208
  }
26018
- function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs33.existsSync)(path2)) {
26209
+ function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs34.existsSync)(path2)) {
26019
26210
  const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
26020
- return [...new Set(declared)].filter((p) => !exists((0, import_node_path31.join)(root, p)));
26211
+ return [...new Set(declared)].filter((p) => !exists((0, import_node_path32.join)(root, p)));
26021
26212
  }
26022
26213
  function evaluate(changed, policy, present = () => false) {
26023
26214
  const { mandatoryHits, untestedHits, testChanges, addedTests, removedProtected } = classify(changed, policy, present);
@@ -26199,13 +26390,13 @@ function changedFilesSince(base, cwd) {
26199
26390
  }
26200
26391
  function runTestPolicy(root, deps = {}) {
26201
26392
  const policy = deps.policy ?? loadPolicy(root);
26202
- const exists = deps.exists ?? ((path2) => (0, import_node_fs33.existsSync)(path2));
26393
+ const exists = deps.exists ?? ((path2) => (0, import_node_fs34.existsSync)(path2));
26203
26394
  const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
26204
26395
  const base = deps.changed ? "(injected)" : resolveBase(root, deps.base);
26205
26396
  const refusal = deps.changed ? null : untrustworthyRange(root, base);
26206
26397
  const changed = deps.changed ?? (refusal ? [] : changedFilesSince(base, root));
26207
26398
  const lookup = deps.override !== void 0 ? { override: deps.override, refusals: [] } : !deps.changed && !refusal ? readOverride(base, root) : { override: null, refusals: [] };
26208
- const present = (path2) => exists((0, import_node_path31.join)(root, path2));
26399
+ const present = (path2) => exists((0, import_node_path32.join)(root, path2));
26209
26400
  const removedByThisDiff = removedPaths(changed);
26210
26401
  const staleFindings = [];
26211
26402
  const unresolved = unresolvedProtectedEntries(policy, root, exists).filter((p) => !removedByThisDiff.has(p));
@@ -26243,8 +26434,8 @@ function runTestPolicy(root, deps = {}) {
26243
26434
  }
26244
26435
 
26245
26436
  // src/project-info-sync.ts
26246
- var import_node_fs34 = require("node:fs");
26247
- var import_node_path32 = require("node:path");
26437
+ var import_node_fs35 = require("node:fs");
26438
+ var import_node_path33 = require("node:path");
26248
26439
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
26249
26440
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
26250
26441
  projectV2 { id }
@@ -26289,14 +26480,14 @@ function sharedName(entries, fallback) {
26289
26480
  }
26290
26481
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
26291
26482
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
26292
- const readmePath = (0, import_node_path32.join)(repoRoot2, "README.md");
26293
- if (!(0, import_node_fs34.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
26483
+ const readmePath = (0, import_node_path33.join)(repoRoot2, "README.md");
26484
+ if (!(0, import_node_fs35.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
26294
26485
  const entries = entriesFor(project2, projects);
26295
26486
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
26296
26487
  const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
26297
26488
  if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
26298
26489
  const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
26299
- const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs34.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
26490
+ const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs35.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
26300
26491
  const lines = [
26301
26492
  `# ${projectName}`,
26302
26493
  "",
@@ -26315,8 +26506,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
26315
26506
  const targetBase = `https://github.com/${targetRepo2}`;
26316
26507
  const targetBranch = branchFor(targetRepo2, projects);
26317
26508
  const orgDocs = [
26318
- (0, import_node_fs34.existsSync)((0, import_node_path32.join)(repoRoot2, "docs", "org-readme.md")) ? `- [Org identity](${targetBase}/blob/${targetBranch}/docs/org-readme.md)` : "",
26319
- (0, import_node_fs34.existsSync)((0, import_node_path32.join)(repoRoot2, "docs", "org-architecture.md")) ? `- [Org architecture](${targetBase}/blob/${targetBranch}/docs/org-architecture.md)` : ""
26509
+ (0, import_node_fs35.existsSync)((0, import_node_path33.join)(repoRoot2, "docs", "org-readme.md")) ? `- [Org identity](${targetBase}/blob/${targetBranch}/docs/org-readme.md)` : "",
26510
+ (0, import_node_fs35.existsSync)((0, import_node_path33.join)(repoRoot2, "docs", "org-architecture.md")) ? `- [Org architecture](${targetBase}/blob/${targetBranch}/docs/org-architecture.md)` : ""
26320
26511
  ].filter(Boolean);
26321
26512
  if (orgDocs.length) lines.push("", "## Organisation docs", "", ...orgDocs);
26322
26513
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines.join("\n")}
@@ -27142,9 +27333,9 @@ function writeError(res) {
27142
27333
  }
27143
27334
 
27144
27335
  // src/secrets-commands.ts
27145
- var import_node_fs35 = require("node:fs");
27146
- var import_node_path33 = require("node:path");
27147
- var import_node_os14 = require("node:os");
27336
+ var import_node_fs36 = require("node:fs");
27337
+ var import_node_path34 = require("node:path");
27338
+ var import_node_os15 = require("node:os");
27148
27339
 
27149
27340
  // src/secrets-diff.ts
27150
27341
  var TIMEOUT_MS2 = 8e3;
@@ -27246,18 +27437,18 @@ function collectMap(value, previous = []) {
27246
27437
  return [...previous, value];
27247
27438
  }
27248
27439
  async function decryptRailsCredentials(input) {
27249
- const appDir = (0, import_node_path33.resolve)(input.appDir ?? process.cwd());
27440
+ const appDir = (0, import_node_path34.resolve)(input.appDir ?? process.cwd());
27250
27441
  const credentialsFile = input.credentialsFile ?? DEFAULT_RAILS_CREDENTIALS_FILE;
27251
27442
  const masterKeyFile = input.masterKeyFile ?? DEFAULT_RAILS_MASTER_KEY_FILE;
27252
- const credentialsPath = (0, import_node_path33.resolve)(appDir, credentialsFile);
27253
- const masterKeyPath = (0, import_node_path33.resolve)(appDir, masterKeyFile);
27443
+ const credentialsPath = (0, import_node_path34.resolve)(appDir, credentialsFile);
27444
+ const masterKeyPath = (0, import_node_path34.resolve)(appDir, masterKeyFile);
27254
27445
  const env = {
27255
27446
  ...process.env,
27256
27447
  MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
27257
27448
  MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
27258
27449
  };
27259
- if ((0, import_node_fs35.existsSync)(masterKeyPath)) {
27260
- env.RAILS_MASTER_KEY = (0, import_node_fs35.readFileSync)(masterKeyPath, "utf8").trim();
27450
+ if ((0, import_node_fs36.existsSync)(masterKeyPath)) {
27451
+ env.RAILS_MASTER_KEY = (0, import_node_fs36.readFileSync)(masterKeyPath, "utf8").trim();
27261
27452
  }
27262
27453
  const script = [
27263
27454
  'require "json"',
@@ -27267,9 +27458,9 @@ async function decryptRailsCredentials(input) {
27267
27458
  'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
27268
27459
  "puts JSON.generate(config.config)"
27269
27460
  ].join("\n");
27270
- const scriptDir = (0, import_node_fs35.mkdtempSync)((0, import_node_path33.join)((0, import_node_os14.tmpdir)(), "mmi-rails-decrypt-"));
27271
- const scriptPath = (0, import_node_path33.join)(scriptDir, "decrypt.rb");
27272
- (0, import_node_fs35.writeFileSync)(scriptPath, script, "utf8");
27461
+ const scriptDir = (0, import_node_fs36.mkdtempSync)((0, import_node_path34.join)((0, import_node_os15.tmpdir)(), "mmi-rails-decrypt-"));
27462
+ const scriptPath = (0, import_node_path34.join)(scriptDir, "decrypt.rb");
27463
+ (0, import_node_fs36.writeFileSync)(scriptPath, script, "utf8");
27273
27464
  try {
27274
27465
  const args = ["exec", "ruby", scriptPath];
27275
27466
  const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
@@ -27281,7 +27472,7 @@ async function decryptRailsCredentials(input) {
27281
27472
  });
27282
27473
  return JSON.parse(stdout);
27283
27474
  } finally {
27284
- (0, import_node_fs35.rmSync)(scriptDir, { recursive: true, force: true });
27475
+ (0, import_node_fs36.rmSync)(scriptDir, { recursive: true, force: true });
27285
27476
  }
27286
27477
  }
27287
27478
  async function readSecretStdin() {
@@ -27371,7 +27562,7 @@ function registerSecretsCommands(program3) {
27371
27562
  let body;
27372
27563
  if (o.file) {
27373
27564
  try {
27374
- body = (0, import_node_fs35.readFileSync)((0, import_node_path33.resolve)(o.file), "utf8");
27565
+ body = (0, import_node_fs36.readFileSync)((0, import_node_path34.resolve)(o.file), "utf8");
27375
27566
  } catch (e) {
27376
27567
  return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
27377
27568
  }
@@ -27476,7 +27667,7 @@ function registerSecretsCommands(program3) {
27476
27667
  {
27477
27668
  ...d,
27478
27669
  decryptRailsCredentials,
27479
- removeFile: (path2) => (0, import_node_fs35.unlinkSync)((0, import_node_path33.resolve)(o.appDir ?? process.cwd(), path2))
27670
+ removeFile: (path2) => (0, import_node_fs36.unlinkSync)((0, import_node_path34.resolve)(o.appDir ?? process.cwd(), path2))
27480
27671
  },
27481
27672
  {
27482
27673
  repo: o.repo,
@@ -27681,7 +27872,7 @@ function emitCliCallTelemetry(command) {
27681
27872
  }
27682
27873
 
27683
27874
  // src/box-commands.ts
27684
- var import_node_fs36 = require("node:fs");
27875
+ var import_node_fs37 = require("node:fs");
27685
27876
 
27686
27877
  // src/box.ts
27687
27878
  var BOX_KEYS = {
@@ -27884,7 +28075,7 @@ function registerBoxCommands(program3) {
27884
28075
  }
27885
28076
  if (o.json) console.log(JSON.stringify({ box: found, incomplete }, null, 2));
27886
28077
  else if (o.ssh && o.script) {
27887
- (0, import_node_fs36.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
28078
+ (0, import_node_fs37.writeFileSync)(o.script, sshRecipeScript(found), "utf8");
27888
28079
  console.log(`wrote ${o.script} \u2014 run: bash "${o.script}"`);
27889
28080
  } else if (o.ssh) console.log(`${formatSshRecipe(found)}
27890
28081
  ${SSH_RECIPE_AGENT_NOTE}`);
@@ -28203,7 +28394,7 @@ function registerSchedulesCommands(program3) {
28203
28394
 
28204
28395
  // src/schedules-lift-command.ts
28205
28396
  var import_promises7 = require("node:fs/promises");
28206
- var import_node_path34 = require("node:path");
28397
+ var import_node_path35 = require("node:path");
28207
28398
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
28208
28399
  var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
28209
28400
  var SchedulesLiftUsageError = class extends Error {
@@ -28230,7 +28421,7 @@ async function readWorkflowFiles(dir) {
28230
28421
  const files = [];
28231
28422
  for (const name of names.sort()) {
28232
28423
  if (!/\.ya?ml$/.test(name)) continue;
28233
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises7.readFile)((0, import_node_path34.join)(dir, name), "utf8") });
28424
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises7.readFile)((0, import_node_path35.join)(dir, name), "utf8") });
28234
28425
  }
28235
28426
  return files;
28236
28427
  }
@@ -28378,9 +28569,9 @@ function registerEdgeCommands(program3) {
28378
28569
  }
28379
28570
 
28380
28571
  // src/bootstrap-commands.ts
28381
- var import_node_fs37 = require("node:fs");
28382
- var import_node_os15 = require("node:os");
28383
- var import_node_path35 = require("node:path");
28572
+ var import_node_fs38 = require("node:fs");
28573
+ var import_node_os16 = require("node:os");
28574
+ var import_node_path36 = require("node:path");
28384
28575
 
28385
28576
  // src/bootstrap-drift.ts
28386
28577
  var import_node_crypto7 = require("node:crypto");
@@ -29260,13 +29451,13 @@ function registerBootstrapCommands(program3) {
29260
29451
  client: defaultGitHubClient(),
29261
29452
  projectMeta: meta,
29262
29453
  deployModel: typeof meta?.deployModel === "string" ? meta.deployModel : void 0,
29263
- readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs37.existsSync)(path2) ? (0, import_node_fs37.readFileSync)(path2, "utf8") : null,
29454
+ readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs38.existsSync)(path2) ? (0, import_node_fs38.readFileSync)(path2, "utf8") : null,
29264
29455
  // requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
29265
29456
  // comma-string — accept either so the seeded value verifies regardless of how it was written.
29266
29457
  // #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
29267
29458
  // permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
29268
29459
  // sanction, which is the pre-#3664 behaviour.
29269
- sanctionedAdmins: (0, import_node_fs37.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs37.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
29460
+ sanctionedAdmins: (0, import_node_fs38.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs38.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
29270
29461
  requiredGcpApis: (() => {
29271
29462
  const v = meta?.requiredGcpApis;
29272
29463
  if (Array.isArray(v)) return v;
@@ -29319,14 +29510,14 @@ function registerBootstrapCommands(program3) {
29319
29510
  bootstrap.command("drift").description("#3818: compare every org-owned whole-file seed against MMI-Hub's copy across the registry roster; read-only").option("--repo <owner/repo>", "audit one repo instead of the roster (never a fleet verdict)").option("--json", "machine-readable output").action(async () => {
29320
29511
  const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
29321
29512
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
29322
- if (!(0, import_node_fs37.existsSync)(manifestPath)) return fail(`bootstrap drift: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the reference this compares against`);
29513
+ if (!(0, import_node_fs38.existsSync)(manifestPath)) return fail(`bootstrap drift: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the reference this compares against`);
29323
29514
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
29324
29515
  if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
29325
- const manifest = loadBootstrapSeeds((0, import_node_fs37.readFileSync)(manifestPath, "utf8"));
29516
+ const manifest = loadBootstrapSeeds((0, import_node_fs38.readFileSync)(manifestPath, "utf8"));
29326
29517
  const hubContents = /* @__PURE__ */ new Map();
29327
29518
  for (const s of manifest.seeds) {
29328
29519
  if (s.ownership !== "org" || s.source !== "self") continue;
29329
- hubContents.set(s.target, (0, import_node_fs37.existsSync)(s.target) ? (0, import_node_fs37.readFileSync)(s.target, "utf8") : null);
29520
+ hubContents.set(s.target, (0, import_node_fs38.existsSync)(s.target) ? (0, import_node_fs38.readFileSync)(s.target, "utf8") : null);
29330
29521
  }
29331
29522
  let targets;
29332
29523
  let classOf = (_repo) => "deployable";
@@ -29405,10 +29596,10 @@ function registerBootstrapCommands(program3) {
29405
29596
  return fail(`bootstrap apply: ${e.message}`);
29406
29597
  }
29407
29598
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
29408
- if (!(0, import_node_fs37.existsSync)(manifestPath)) return fail(`bootstrap apply: ${manifestPath} not found; bootstrap runs from the MMI-Hub repo root by design \u2014 it stamps org-level resources (Project, Ruleset, secrets, access) through the GitHub App, which is only authorized from the Hub checkout`);
29599
+ if (!(0, import_node_fs38.existsSync)(manifestPath)) return fail(`bootstrap apply: ${manifestPath} not found; bootstrap runs from the MMI-Hub repo root by design \u2014 it stamps org-level resources (Project, Ruleset, secrets, access) through the GitHub App, which is only authorized from the Hub checkout`);
29409
29600
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
29410
29601
  if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
29411
- const manifest = loadBootstrapSeeds((0, import_node_fs37.readFileSync)(manifestPath, "utf8"));
29602
+ const manifest = loadBootstrapSeeds((0, import_node_fs38.readFileSync)(manifestPath, "utf8"));
29412
29603
  const baseBranch = o.class === "content" ? "main" : "development";
29413
29604
  const slug = parsedRepo.slug;
29414
29605
  const onlyTarget = o.only.trim();
@@ -29419,16 +29610,16 @@ function registerBootstrapCommands(program3) {
29419
29610
  ${known}`);
29420
29611
  }
29421
29612
  const gh = async (args) => execFileP2("gh", args, { timeout: 2e4 });
29422
- const readFile9 = (p) => (0, import_node_fs37.existsSync)(p) ? (0, import_node_fs37.readFileSync)(p, "utf8") : null;
29613
+ const readFile9 = (p) => (0, import_node_fs38.existsSync)(p) ? (0, import_node_fs38.readFileSync)(p, "utf8") : null;
29423
29614
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
29424
29615
  const putSeed = async (target, content, ref, sha) => {
29425
- const tmp = (0, import_node_path35.join)((0, import_node_os15.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
29426
- (0, import_node_fs37.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
29616
+ const tmp = (0, import_node_path36.join)((0, import_node_os16.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
29617
+ (0, import_node_fs38.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
29427
29618
  try {
29428
29619
  await gh(contentPutInputArgs(repo, target, tmp));
29429
29620
  } finally {
29430
29621
  try {
29431
- (0, import_node_fs37.unlinkSync)(tmp);
29622
+ (0, import_node_fs38.unlinkSync)(tmp);
29432
29623
  } catch {
29433
29624
  }
29434
29625
  }
@@ -29693,10 +29884,10 @@ LIVE apply to ${repo}:
29693
29884
  bootstrap.command("propagate").description("#4238: re-entrant canary\u2192wave tick \u2014 plan (or, with --execute, open) per-repo PRs fanning an org-owned seed out to the fleet").option("--target <path>", "the manifest target to propagate (an ownership:org + source:self seed, e.g. .github/workflows/agent-pr.yml)").option("--execute", "LIVE tick via gh (master-gated) \u2014 opens/reuses per-repo seed-propagate PRs; dry-run prints the plan only").option("--json", "machine-readable output").action(async () => {
29694
29885
  const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
29695
29886
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
29696
- if (!(0, import_node_fs37.existsSync)(manifestPath)) return fail(`bootstrap propagate: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the desired state this tick propagates`);
29887
+ if (!(0, import_node_fs38.existsSync)(manifestPath)) return fail(`bootstrap propagate: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the desired state this tick propagates`);
29697
29888
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
29698
29889
  if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
29699
- const manifest = loadBootstrapSeeds((0, import_node_fs37.readFileSync)(manifestPath, "utf8"));
29890
+ const manifest = loadBootstrapSeeds((0, import_node_fs38.readFileSync)(manifestPath, "utf8"));
29700
29891
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
29701
29892
  if (!o.target) {
29702
29893
  return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
@@ -29705,8 +29896,8 @@ LIVE apply to ${repo}:
29705
29896
  const seed = propagatable.find((s) => s.target === o.target);
29706
29897
  if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no ownership:org + source:self seed in ${manifestPath}. Propagatable targets:
29707
29898
  ${propagatable.map((s) => s.target).join("\n ")}`);
29708
- if (!(0, import_node_fs37.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
29709
- const hubContent = (0, import_node_fs37.readFileSync)(seed.target, "utf8");
29899
+ if (!(0, import_node_fs38.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
29900
+ const hubContent = (0, import_node_fs38.readFileSync)(seed.target, "utf8");
29710
29901
  const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
29711
29902
  const cfg = await loadConfig();
29712
29903
  const projects = await fetchProjectsList(registryClientDeps(cfg));
@@ -29715,9 +29906,9 @@ LIVE apply to ${repo}:
29715
29906
  }
29716
29907
  const rosterRepos2 = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
29717
29908
  let independentCount = rosterRepos2.length;
29718
- if ((0, import_node_fs37.existsSync)("projects.json")) {
29909
+ if ((0, import_node_fs38.existsSync)("projects.json")) {
29719
29910
  try {
29720
- const local = JSON.parse((0, import_node_fs37.readFileSync)("projects.json", "utf8"));
29911
+ const local = JSON.parse((0, import_node_fs38.readFileSync)("projects.json", "utf8"));
29721
29912
  const localRepos = /* @__PURE__ */ new Set();
29722
29913
  for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
29723
29914
  const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
@@ -29833,13 +30024,13 @@ LIVE apply to ${repo}:
29833
30024
  } catch {
29834
30025
  existingSha = void 0;
29835
30026
  }
29836
- const tmp = (0, import_node_path35.join)((0, import_node_os15.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
29837
- (0, import_node_fs37.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, hubContent, branch, existingSha)), "utf8");
30027
+ const tmp = (0, import_node_path36.join)((0, import_node_os16.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
30028
+ (0, import_node_fs38.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, hubContent, branch, existingSha)), "utf8");
29838
30029
  try {
29839
30030
  await gh(contentPutInputArgs(rec.repo, seed.target, tmp));
29840
30031
  } finally {
29841
30032
  try {
29842
- (0, import_node_fs37.unlinkSync)(tmp);
30033
+ (0, import_node_fs38.unlinkSync)(tmp);
29843
30034
  } catch {
29844
30035
  }
29845
30036
  }
@@ -29897,10 +30088,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
29897
30088
  return fail(`bootstrap rollback: ${e.message}`);
29898
30089
  }
29899
30090
  const manifestPath = "skills/bootstrap/seeds/manifest.json";
29900
- if (!(0, import_node_fs37.existsSync)(manifestPath)) return fail(`bootstrap rollback: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the manifest names which targets are org-owned and therefore propagated (and rollback-able)`);
30091
+ if (!(0, import_node_fs38.existsSync)(manifestPath)) return fail(`bootstrap rollback: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the manifest names which targets are org-owned and therefore propagated (and rollback-able)`);
29901
30092
  const seedSource = await resolveHubSeedSource(execGitForSeedSource);
29902
30093
  if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
29903
- const manifest = loadBootstrapSeeds((0, import_node_fs37.readFileSync)(manifestPath, "utf8"));
30094
+ const manifest = loadBootstrapSeeds((0, import_node_fs38.readFileSync)(manifestPath, "utf8"));
29904
30095
  const propagatable = manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self");
29905
30096
  if (!o.target) {
29906
30097
  return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
@@ -29917,10 +30108,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
29917
30108
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
29918
30109
  let candidates;
29919
30110
  if (o.record) {
29920
- if (!(0, import_node_fs37.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
30111
+ if (!(0, import_node_fs38.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
29921
30112
  let parsed;
29922
30113
  try {
29923
- parsed = JSON.parse((0, import_node_fs37.readFileSync)(o.record, "utf8"));
30114
+ parsed = JSON.parse((0, import_node_fs38.readFileSync)(o.record, "utf8"));
29924
30115
  } catch (e) {
29925
30116
  return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
29926
30117
  }
@@ -29989,13 +30180,13 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
29989
30180
  } catch {
29990
30181
  existingSha = void 0;
29991
30182
  }
29992
- const tmp = (0, import_node_path35.join)((0, import_node_os15.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
29993
- (0, import_node_fs37.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
30183
+ const tmp = (0, import_node_path36.join)((0, import_node_os16.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
30184
+ (0, import_node_fs38.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
29994
30185
  try {
29995
30186
  await gh(contentPutInputArgs(repo, seed.target, tmp));
29996
30187
  } finally {
29997
30188
  try {
29998
- (0, import_node_fs37.unlinkSync)(tmp);
30189
+ (0, import_node_fs38.unlinkSync)(tmp);
29999
30190
  } catch {
30000
30191
  }
30001
30192
  }
@@ -30017,12 +30208,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
30017
30208
  }
30018
30209
 
30019
30210
  // src/stage-commands.ts
30020
- var import_node_fs39 = require("node:fs");
30021
- var import_node_path37 = require("node:path");
30211
+ var import_node_fs40 = require("node:fs");
30212
+ var import_node_path38 = require("node:path");
30022
30213
 
30023
30214
  // src/port-registry.ts
30024
- var import_node_fs38 = require("node:fs");
30025
- var import_node_path36 = require("node:path");
30215
+ var import_node_fs39 = require("node:fs");
30216
+ var import_node_path37 = require("node:path");
30026
30217
 
30027
30218
  // ../infra/port-geometry.mjs
30028
30219
  var PORT_BLOCK = 100;
@@ -30036,8 +30227,8 @@ function nextPortBlock(registry2) {
30036
30227
  return [base, base + PORT_SPAN];
30037
30228
  }
30038
30229
  function loadPortRegistry(path2) {
30039
- if (!(0, import_node_fs38.existsSync)(path2)) return {};
30040
- const raw = JSON.parse((0, import_node_fs38.readFileSync)(path2, "utf8"));
30230
+ if (!(0, import_node_fs39.existsSync)(path2)) return {};
30231
+ const raw = JSON.parse((0, import_node_fs39.readFileSync)(path2, "utf8"));
30041
30232
  const out = {};
30042
30233
  for (const [key, value] of Object.entries(raw)) {
30043
30234
  if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
@@ -30051,9 +30242,9 @@ function ensurePortRange(repo, path2) {
30051
30242
  const existing = registry2[repo];
30052
30243
  if (existing) return existing;
30053
30244
  const range = nextPortBlock(registry2);
30054
- const raw = (0, import_node_fs38.existsSync)(path2) ? JSON.parse((0, import_node_fs38.readFileSync)(path2, "utf8")) : {};
30245
+ const raw = (0, import_node_fs39.existsSync)(path2) ? JSON.parse((0, import_node_fs39.readFileSync)(path2, "utf8")) : {};
30055
30246
  raw[repo] = range;
30056
- (0, import_node_fs38.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
30247
+ (0, import_node_fs39.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
30057
30248
  return range;
30058
30249
  }
30059
30250
  function portCursorSeed(registry2) {
@@ -30075,22 +30266,22 @@ function existingPortRange(repo, registry2) {
30075
30266
  return registry2[repo] ?? null;
30076
30267
  }
30077
30268
  function portRangeInfraAt(root, source) {
30078
- const registryPath = (0, import_node_path36.join)(root, "infra", "port-ranges.json");
30079
- const ddbScriptPath = (0, import_node_path36.join)(root, "infra", "port-ddb.mjs");
30080
- if (!(0, import_node_fs38.existsSync)(registryPath) || !(0, import_node_fs38.existsSync)(ddbScriptPath)) return null;
30269
+ const registryPath = (0, import_node_path37.join)(root, "infra", "port-ranges.json");
30270
+ const ddbScriptPath = (0, import_node_path37.join)(root, "infra", "port-ddb.mjs");
30271
+ if (!(0, import_node_fs39.existsSync)(registryPath) || !(0, import_node_fs39.existsSync)(ddbScriptPath)) return null;
30081
30272
  return { root, source, registryPath, ddbScriptPath };
30082
30273
  }
30083
30274
  function resolvePortRangeInfra(cwd, packageDir) {
30084
30275
  const direct = portRangeInfraAt(cwd, "cwd");
30085
30276
  if (direct) return direct;
30086
- for (let dir = cwd; ; dir = (0, import_node_path36.dirname)(dir)) {
30087
- const sibling = portRangeInfraAt((0, import_node_path36.join)(dir, "MMI-Hub"), "sibling-hub");
30277
+ for (let dir = cwd; ; dir = (0, import_node_path37.dirname)(dir)) {
30278
+ const sibling = portRangeInfraAt((0, import_node_path37.join)(dir, "MMI-Hub"), "sibling-hub");
30088
30279
  if (sibling) return sibling;
30089
- const parent = (0, import_node_path36.dirname)(dir);
30280
+ const parent = (0, import_node_path37.dirname)(dir);
30090
30281
  if (parent === dir) break;
30091
30282
  }
30092
30283
  if (packageDir) {
30093
- const pkgRoot = (0, import_node_path36.join)(packageDir, "..", "..");
30284
+ const pkgRoot = (0, import_node_path37.join)(packageDir, "..", "..");
30094
30285
  const pkgFrom = portRangeInfraAt(pkgRoot, "pkg-root");
30095
30286
  if (pkgFrom) return pkgFrom;
30096
30287
  }
@@ -30284,8 +30475,8 @@ function registerStageCommands(program3) {
30284
30475
  const portRange = portRangeMeta && typeof portRangeMeta.start === "number" && typeof portRangeMeta.end === "number" ? [portRangeMeta.start, portRangeMeta.end] : void 0;
30285
30476
  return decideStage({
30286
30477
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
30287
- hasCompose: (0, import_node_fs39.existsSync)((0, import_node_path37.join)(process.cwd(), "docker-compose.yml")),
30288
- hasEnvExample: (0, import_node_fs39.existsSync)((0, import_node_path37.join)(process.cwd(), ".env.example"))
30478
+ hasCompose: (0, import_node_fs40.existsSync)((0, import_node_path38.join)(process.cwd(), "docker-compose.yml")),
30479
+ hasEnvExample: (0, import_node_fs40.existsSync)((0, import_node_path38.join)(process.cwd(), ".env.example"))
30289
30480
  });
30290
30481
  }
30291
30482
  async function fetchStageVaultEnvMerge() {
@@ -30776,10 +30967,10 @@ function registerBoardCommands(program3) {
30776
30967
  }
30777
30968
 
30778
30969
  // src/merge-cleanup.ts
30779
- var import_node_fs40 = require("node:fs");
30970
+ var import_node_fs41 = require("node:fs");
30780
30971
  var import_promises9 = require("node:fs/promises");
30781
- var import_node_path39 = require("node:path");
30782
- var import_node_os16 = require("node:os");
30972
+ var import_node_path40 = require("node:path");
30973
+ var import_node_os17 = require("node:os");
30783
30974
  var import_node_child_process17 = require("node:child_process");
30784
30975
 
30785
30976
  // src/board-advance.ts
@@ -30866,7 +31057,7 @@ function boardAdvanceFailureMessage(result) {
30866
31057
 
30867
31058
  // src/deferred-registry-store.ts
30868
31059
  var import_promises8 = require("node:fs/promises");
30869
- var import_node_path38 = require("node:path");
31060
+ var import_node_path39 = require("node:path");
30870
31061
  var sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
30871
31062
  async function atomicWrite(target, contents) {
30872
31063
  const tmp = `${target}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
@@ -30917,12 +31108,12 @@ function makeDeferredWorktreeStore(registryPath, lockOpts = {}) {
30917
31108
  },
30918
31109
  // Standalone atomic write — THROWS on failure (no best-effort swallow, #2846).
30919
31110
  write: async (entries) => {
30920
- await (0, import_promises8.mkdir)((0, import_node_path38.dirname)(registryPath), { recursive: true });
31111
+ await (0, import_promises8.mkdir)((0, import_node_path39.dirname)(registryPath), { recursive: true });
30921
31112
  await atomicWrite(registryPath, serializeDeferredWorktrees(entries));
30922
31113
  },
30923
31114
  // Serialized read-modify-write under the repo-wide lock (#2846).
30924
31115
  update: async (mutate) => {
30925
- await (0, import_promises8.mkdir)((0, import_node_path38.dirname)(registryPath), { recursive: true });
31116
+ await (0, import_promises8.mkdir)((0, import_node_path39.dirname)(registryPath), { recursive: true });
30926
31117
  const deadline = Date.now() + opts.maxWaitMs;
30927
31118
  for (; ; ) {
30928
31119
  const guard = await acquireLock(lockPath, opts, deadline);
@@ -31086,17 +31277,17 @@ ${err.stderr ?? ""}`;
31086
31277
  return { step, status: `failed: ${msg}` };
31087
31278
  }
31088
31279
  }
31089
- async function bestEffortCloseMissingWorktreeLeases(leaseDir = (0, import_node_path39.join)((0, import_node_os16.homedir)(), ".jerv", "leases"), exists = import_node_fs40.existsSync) {
31280
+ async function bestEffortCloseMissingWorktreeLeases(leaseDir = (0, import_node_path40.join)((0, import_node_os17.homedir)(), ".jerv", "leases"), exists = import_node_fs41.existsSync) {
31090
31281
  let names = [];
31091
31282
  try {
31092
- names = (0, import_node_fs40.readdirSync)(leaseDir);
31283
+ names = (0, import_node_fs41.readdirSync)(leaseDir);
31093
31284
  } catch {
31094
31285
  return;
31095
31286
  }
31096
31287
  for (const name of names) {
31097
31288
  if (!name.endsWith(".json")) continue;
31098
31289
  try {
31099
- const rec = JSON.parse((0, import_node_fs40.readFileSync)((0, import_node_path39.join)(leaseDir, name), "utf8"));
31290
+ const rec = JSON.parse((0, import_node_fs41.readFileSync)((0, import_node_path40.join)(leaseDir, name), "utf8"));
31100
31291
  if (rec.kind !== "worktree" || rec.state === "closed" || typeof rec.ref !== "string" || !rec.ref.trim()) continue;
31101
31292
  if (!exists(rec.ref)) await bestEffortLeaseClose(rec.ref);
31102
31293
  } catch {
@@ -31110,7 +31301,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
31110
31301
  );
31111
31302
  const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
31112
31303
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
31113
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path39.dirname)((0, import_node_path39.dirname)(worktreeGitRoot)) : repoRoot2;
31304
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path40.dirname)((0, import_node_path40.dirname)(worktreeGitRoot)) : repoRoot2;
31114
31305
  const gcActor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
31115
31306
  const owners = readWorktreeOwners(primaryRepoRoot);
31116
31307
  const removalNow = Date.now();
@@ -31169,7 +31360,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
31169
31360
  const cleanup = await cleanupPrMergeLocalBranch(branch.branch, {
31170
31361
  beforeWorktrees,
31171
31362
  startingPath: branch.worktreePath,
31172
- pathExists: (p) => (0, import_node_fs40.existsSync)(p),
31363
+ pathExists: (p) => (0, import_node_fs41.existsSync)(p),
31173
31364
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
31174
31365
  teardownWorktreeStage,
31175
31366
  deferredStore,
@@ -31208,7 +31399,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
31208
31399
  let removalAttempted = false;
31209
31400
  try {
31210
31401
  const cleanupTarget = resolveSafeSiblingWorktreeCleanupTarget(wt.path, cleanupRoots, {
31211
- realpath: (path2) => (0, import_node_fs40.realpathSync)(path2)
31402
+ realpath: (path2) => (0, import_node_fs41.realpathSync)(path2)
31212
31403
  });
31213
31404
  if (!cleanupTarget.ok) {
31214
31405
  result.failed.push(`${wt.path}: ${cleanupTarget.reason}`);
@@ -31310,13 +31501,13 @@ async function composeOverrideBodyFile(prNumber, repoArgs, gh) {
31310
31501
  const commits = JSON.parse(raw).commits ?? [];
31311
31502
  const body = squashBodyWithOverride(commits.map((c) => ({ headline: c.messageHeadline ?? "", body: c.messageBody ?? "" })), process.cwd());
31312
31503
  if (!body) return void 0;
31313
- const dir = (0, import_node_fs40.mkdtempSync)((0, import_node_path39.join)((0, import_node_os16.tmpdir)(), "mmi-squash-body-"));
31314
- const path2 = (0, import_node_path39.join)(dir, "body.txt");
31315
- (0, import_node_fs40.writeFileSync)(path2, `${body}
31504
+ const dir = (0, import_node_fs41.mkdtempSync)((0, import_node_path40.join)((0, import_node_os17.tmpdir)(), "mmi-squash-body-"));
31505
+ const path2 = (0, import_node_path40.join)(dir, "body.txt");
31506
+ (0, import_node_fs41.writeFileSync)(path2, `${body}
31316
31507
  `, "utf8");
31317
31508
  return { path: path2, cleanup: () => {
31318
31509
  try {
31319
- (0, import_node_fs40.rmSync)(dir, { recursive: true, force: true });
31510
+ (0, import_node_fs41.rmSync)(dir, { recursive: true, force: true });
31320
31511
  } catch {
31321
31512
  }
31322
31513
  } };
@@ -31439,13 +31630,13 @@ var realWorktreeDirRemover = {
31439
31630
  const target = win32LongPath(p);
31440
31631
  let st;
31441
31632
  try {
31442
- st = (0, import_node_fs40.lstatSync)(target);
31633
+ st = (0, import_node_fs41.lstatSync)(target);
31443
31634
  } catch {
31444
31635
  return null;
31445
31636
  }
31446
31637
  if (st.isSymbolicLink()) return "link";
31447
31638
  try {
31448
- (0, import_node_fs40.readlinkSync)(target);
31639
+ (0, import_node_fs41.readlinkSync)(target);
31449
31640
  return "link";
31450
31641
  } catch {
31451
31642
  }
@@ -31453,7 +31644,7 @@ var realWorktreeDirRemover = {
31453
31644
  },
31454
31645
  readdir: (p) => {
31455
31646
  try {
31456
- return (0, import_node_fs40.readdirSync)(win32LongPath(p));
31647
+ return (0, import_node_fs41.readdirSync)(win32LongPath(p));
31457
31648
  } catch {
31458
31649
  return [];
31459
31650
  }
@@ -31463,9 +31654,9 @@ var realWorktreeDirRemover = {
31463
31654
  detachLink: (p) => {
31464
31655
  const target = win32LongPath(p);
31465
31656
  try {
31466
- (0, import_node_fs40.rmdirSync)(target);
31657
+ (0, import_node_fs41.rmdirSync)(target);
31467
31658
  } catch {
31468
- (0, import_node_fs40.unlinkSync)(target);
31659
+ (0, import_node_fs41.unlinkSync)(target);
31469
31660
  }
31470
31661
  },
31471
31662
  // #4904: Windows MAX_PATH aborts git worktree remove; the fallback must use \\?\ so the dir
@@ -31488,7 +31679,7 @@ function worktreeRemoveDeps(execGit) {
31488
31679
  detachReparsePoints: (worktreePath) => detachReparsePoints(worktreePath, realWorktreeDirRemover),
31489
31680
  removeWorktreeDir: async (worktreePath) => removeWorktreeTree(worktreePath, await resolvePrimaryCheckout(execGit), realWorktreeDirRemover),
31490
31681
  // #4850: verify the directory is actually gone before any caller reports completion.
31491
- pathExists: (worktreePath) => (0, import_node_fs40.existsSync)(worktreePath)
31682
+ pathExists: (worktreePath) => (0, import_node_fs41.existsSync)(worktreePath)
31492
31683
  };
31493
31684
  }
31494
31685
  async function worktreeHasStageState(worktreePath) {
@@ -31502,9 +31693,9 @@ async function worktreeHasStageState(worktreePath) {
31502
31693
  }
31503
31694
  }
31504
31695
  function stageStateFileBelongsToWorktree(statePath, worktreePath) {
31505
- if (!(0, import_node_fs40.existsSync)(statePath)) return false;
31696
+ if (!(0, import_node_fs41.existsSync)(statePath)) return false;
31506
31697
  try {
31507
- const state = JSON.parse((0, import_node_fs40.readFileSync)(statePath, "utf8"));
31698
+ const state = JSON.parse((0, import_node_fs41.readFileSync)(statePath, "utf8"));
31508
31699
  const recordedCwd = typeof state.identity?.cwd === "string" ? state.identity.cwd : typeof state.cwd === "string" ? state.cwd : "";
31509
31700
  return Boolean(recordedCwd && isPathUnderDirectory2(recordedCwd, worktreePath));
31510
31701
  } catch {
@@ -31939,15 +32130,15 @@ async function checkDocsIndexAtHead(opts, deps) {
31939
32130
  }
31940
32131
 
31941
32132
  // src/worktree-lifecycle-commands.ts
31942
- var import_node_fs42 = require("node:fs");
32133
+ var import_node_fs43 = require("node:fs");
31943
32134
  var import_promises10 = require("node:fs/promises");
31944
- var import_node_os17 = require("node:os");
31945
- var import_node_path41 = require("node:path");
32135
+ var import_node_os18 = require("node:os");
32136
+ var import_node_path42 = require("node:path");
31946
32137
 
31947
32138
  // src/worktree-install-cache.ts
31948
32139
  var import_node_crypto8 = require("node:crypto");
31949
- var import_node_fs41 = require("node:fs");
31950
- var import_node_path40 = require("node:path");
32140
+ var import_node_fs42 = require("node:fs");
32141
+ var import_node_path41 = require("node:path");
31951
32142
  var CACHE_DIR = "worktree-install-cache";
31952
32143
  var MANIFEST = "manifest.json";
31953
32144
  var NODE_MODULES2 = "node_modules";
@@ -31960,16 +32151,16 @@ var LOCKFILE_NAMES = [
31960
32151
  "package-lock.json"
31961
32152
  ];
31962
32153
  var realWorktreeInstallCacheFs = {
31963
- exists: import_node_fs41.existsSync,
31964
- readFile: (path2) => (0, import_node_fs41.readFileSync)(path2, "utf8"),
31965
- lstat: (path2) => (0, import_node_fs41.lstatSync)(path2),
31966
- copyDir: (from, to) => (0, import_node_fs41.cpSync)(from, to, { recursive: true, force: true }),
32154
+ exists: import_node_fs42.existsSync,
32155
+ readFile: (path2) => (0, import_node_fs42.readFileSync)(path2, "utf8"),
32156
+ lstat: (path2) => (0, import_node_fs42.lstatSync)(path2),
32157
+ copyDir: (from, to) => (0, import_node_fs42.cpSync)(from, to, { recursive: true, force: true }),
31967
32158
  mkdirp: (path2) => {
31968
- (0, import_node_fs41.mkdirSync)(path2, { recursive: true });
32159
+ (0, import_node_fs42.mkdirSync)(path2, { recursive: true });
31969
32160
  },
31970
- writeFile: (path2, contents) => (0, import_node_fs41.writeFileSync)(path2, contents, "utf8"),
32161
+ writeFile: (path2, contents) => (0, import_node_fs42.writeFileSync)(path2, contents, "utf8"),
31971
32162
  rm: (path2) => {
31972
- (0, import_node_fs41.rmSync)(path2, { recursive: true, force: true });
32163
+ (0, import_node_fs42.rmSync)(path2, { recursive: true, force: true });
31973
32164
  }
31974
32165
  };
31975
32166
  function hashLockfileBytes(contents) {
@@ -31977,7 +32168,7 @@ function hashLockfileBytes(contents) {
31977
32168
  }
31978
32169
  function resolveWorktreeInstallLockfile(packageDir, fs2 = realWorktreeInstallCacheFs) {
31979
32170
  for (const name of LOCKFILE_NAMES) {
31980
- const path2 = (0, import_node_path40.join)(packageDir, name);
32171
+ const path2 = (0, import_node_path41.join)(packageDir, name);
31981
32172
  if (!fs2.exists(path2)) continue;
31982
32173
  try {
31983
32174
  const hash = hashLockfileBytes(fs2.readFile(path2));
@@ -31992,8 +32183,8 @@ function worktreeInstallCacheEntry(primaryRoot, lockfileHash) {
31992
32183
  const root = repoRuntimeStatePath(primaryRoot, CACHE_DIR, lockfileHash);
31993
32184
  return {
31994
32185
  root,
31995
- manifestPath: (0, import_node_path40.join)(root, MANIFEST),
31996
- nodeModulesPath: (0, import_node_path40.join)(root, NODE_MODULES2)
32186
+ manifestPath: (0, import_node_path41.join)(root, MANIFEST),
32187
+ nodeModulesPath: (0, import_node_path41.join)(root, NODE_MODULES2)
31997
32188
  };
31998
32189
  }
31999
32190
  function readWorktreeInstallCacheManifest(manifestPath, fs2 = realWorktreeInstallCacheFs) {
@@ -32033,7 +32224,7 @@ function invalidateWorktreeInstallCacheEntry(entry, fs2 = realWorktreeInstallCac
32033
32224
  }
32034
32225
  }
32035
32226
  function removeMaterializedTree(packageDir, fs2) {
32036
- const dest = (0, import_node_path40.join)(packageDir, NODE_MODULES2);
32227
+ const dest = (0, import_node_path41.join)(packageDir, NODE_MODULES2);
32037
32228
  if (!fs2.exists(dest)) return;
32038
32229
  fs2.rm(dest);
32039
32230
  if (fs2.exists(dest)) {
@@ -32041,7 +32232,7 @@ function removeMaterializedTree(packageDir, fs2) {
32041
32232
  }
32042
32233
  }
32043
32234
  function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeInstallCacheFs) {
32044
- const dest = (0, import_node_path40.join)(destPackageDir, NODE_MODULES2);
32235
+ const dest = (0, import_node_path41.join)(destPackageDir, NODE_MODULES2);
32045
32236
  try {
32046
32237
  if (fs2.exists(dest)) fs2.rm(dest);
32047
32238
  fs2.mkdirp(destPackageDir);
@@ -32056,7 +32247,7 @@ function materializeCachedNodeModules(entry, destPackageDir, fs2 = realWorktreeI
32056
32247
  }
32057
32248
  }
32058
32249
  async function storeWorktreeInstallCacheEntry(primaryRoot, lockfile, command, sourcePackageDir, fs2 = realWorktreeInstallCacheFs, now = Date.now()) {
32059
- const source = (0, import_node_path40.join)(sourcePackageDir, NODE_MODULES2);
32250
+ const source = (0, import_node_path41.join)(sourcePackageDir, NODE_MODULES2);
32060
32251
  if (!isMaterializableNodeModulesDir(source, fs2)) return;
32061
32252
  const entry = worktreeInstallCacheEntry(primaryRoot, lockfile.hash);
32062
32253
  const manifest = {
@@ -32340,7 +32531,7 @@ function classifyStaleLeaks(input) {
32340
32531
  var defaultOrphanDirScanDeps = {
32341
32532
  listDirs: (root) => {
32342
32533
  try {
32343
- return (0, import_node_fs42.readdirSync)(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path41.join)(root, e.name));
32534
+ return (0, import_node_fs43.readdirSync)(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path42.join)(root, e.name));
32344
32535
  } catch {
32345
32536
  return [];
32346
32537
  }
@@ -32530,13 +32721,13 @@ function registerWorktreeCommands(program3) {
32530
32721
  const detached = headBorn && !symbolicBranch;
32531
32722
  const branch = symbolicBranch || (detached ? "HEAD" : "");
32532
32723
  if (!wtPath || !branch) return fail("worktree land: not inside a git worktree");
32533
- const gitFile = (0, import_node_path41.join)(wtPath, ".git");
32534
- const isLinked = (0, import_node_fs42.existsSync)(gitFile) && (0, import_node_fs42.statSync)(gitFile).isFile();
32724
+ const gitFile = (0, import_node_path42.join)(wtPath, ".git");
32725
+ const isLinked = (0, import_node_fs43.existsSync)(gitFile) && (0, import_node_fs43.statSync)(gitFile).isFile();
32535
32726
  if (apply && !isLinked) {
32536
32727
  return fail("worktree land: run from inside the linked worktree you want to land (this is the primary checkout)");
32537
32728
  }
32538
32729
  const commonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
32539
- const primaryCheckout = commonDir ? (0, import_node_path41.dirname)(commonDir) : wtPath;
32730
+ const primaryCheckout = commonDir ? (0, import_node_path42.dirname)(commonDir) : wtPath;
32540
32731
  const localBranchNames = await execFileP2("git", ["-C", primaryCheckout, "for-each-ref", "--format=%(refname:short)", "refs/heads"], { timeout: GIT_TIMEOUT_MS }).then(({ stdout }) => new Set((stdout || "").split("\n").map((l) => l.trim()).filter(Boolean))).catch(() => void 0);
32541
32732
  const orphan = classifyOrphanedWorktree({
32542
32733
  branch,
@@ -32796,7 +32987,7 @@ async function gatherWorktreeContext() {
32796
32987
  const porcelain = (await execFileP2("git", ["worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
32797
32988
  const parsed = parseWorktreePorcelain(porcelain);
32798
32989
  const primaryPath = parsed[0]?.path ?? repoRoot2;
32799
- const worktrees = parsed.map((w) => ({ path: (0, import_node_path41.resolve)(toNativePath(w.path)), branch: w.branch, primary: w.path === primaryPath }));
32990
+ const worktrees = parsed.map((w) => ({ path: (0, import_node_path42.resolve)(toNativePath(w.path)), branch: w.branch, primary: w.path === primaryPath }));
32800
32991
  const branchOut = (await execFileP2("git", ["branch", "--format=%(refname:short)"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
32801
32992
  const localBranches = branchOut.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
32802
32993
  const currentBranch2 = (await execFileP2("git", ["rev-parse", "--abbrev-ref", "HEAD"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || void 0;
@@ -32834,17 +33025,17 @@ async function gatherWorktreeContext() {
32834
33025
  if (s) stages.push({ path: wt.path, port: s.port });
32835
33026
  }
32836
33027
  const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
32837
- const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path41.dirname)((0, import_node_path41.dirname)(worktreeGitRoot)) : repoRoot2;
33028
+ const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path42.dirname)((0, import_node_path42.dirname)(worktreeGitRoot)) : repoRoot2;
32838
33029
  const wtRoot = siblingMmiWorktreesRoot(primaryRepoRoot);
32839
33030
  let orphanDirs = [];
32840
- if ((0, import_node_fs42.existsSync)(wtRoot)) {
33031
+ if ((0, import_node_fs43.existsSync)(wtRoot)) {
32841
33032
  orphanDirs = scanOrphanDirs(wtRoot, worktreeGitRoot, {
32842
33033
  ...defaultOrphanDirScanDeps,
32843
33034
  listDirs: (root) => worktreeScanDirs(root, primaryRepoRoot, defaultOrphanDirScanDeps.listDirs, isRepoCheckoutDir)
32844
33035
  });
32845
33036
  }
32846
33037
  const repoContainer = worktreesRootOf(primaryRepoRoot);
32847
- if ((0, import_node_fs42.existsSync)(repoContainer)) {
33038
+ if ((0, import_node_fs43.existsSync)(repoContainer)) {
32848
33039
  for (const dir of defaultOrphanDirScanDeps.listDirs(repoContainer)) {
32849
33040
  if (orphanDirs.some((o) => o.path === dir)) continue;
32850
33041
  const inspected = inspectSiblingWorktreeDir(dir, worktreeGitRoot);
@@ -32868,7 +33059,7 @@ async function gatherWorktreeContext() {
32868
33059
  });
32869
33060
  const helperWorktrees = scanHelperWorktrees(primaryRepoRoot, worktreeGitRoot);
32870
33061
  const leaseRefs = readJervWorktreeLeaseRefs();
32871
- const missingLeaseRefs = leaseRefs.filter((ref) => !(0, import_node_fs42.existsSync)(ref));
33062
+ const missingLeaseRefs = leaseRefs.filter((ref) => !(0, import_node_fs43.existsSync)(ref));
32872
33063
  const remoteUrls = await gitRemoteUrls();
32873
33064
  const otherCheckouts = discoverOtherPrimaries(primaryRepoRoot).map((path2) => ({
32874
33065
  path: path2,
@@ -32898,16 +33089,16 @@ async function gatherWorktreeContext() {
32898
33089
  };
32899
33090
  }
32900
33091
  function gitConfigRemoteUrls(checkout) {
32901
- const gitPath = (0, import_node_path41.join)(checkout, ".git");
32902
- let configPath = (0, import_node_path41.join)(checkout, ".git", "config");
33092
+ const gitPath = (0, import_node_path42.join)(checkout, ".git");
33093
+ let configPath = (0, import_node_path42.join)(checkout, ".git", "config");
32903
33094
  try {
32904
- const st = (0, import_node_fs42.statSync)(gitPath);
33095
+ const st = (0, import_node_fs43.statSync)(gitPath);
32905
33096
  if (st.isFile()) return [];
32906
33097
  } catch {
32907
33098
  return [];
32908
33099
  }
32909
33100
  try {
32910
- const text = (0, import_node_fs42.readFileSync)(configPath, "utf8");
33101
+ const text = (0, import_node_fs43.readFileSync)(configPath, "utf8");
32911
33102
  return [...text.matchAll(/^\s*url\s*=\s*(.+)$/gm)].map((m) => m[1].trim());
32912
33103
  } catch {
32913
33104
  return [];
@@ -32921,26 +33112,26 @@ async function gitRemoteUrls() {
32921
33112
  }
32922
33113
  function discoverOtherPrimaries(primaryRepoRoot) {
32923
33114
  const found = /* @__PURE__ */ new Set();
32924
- const parent = (0, import_node_path41.dirname)(primaryRepoRoot);
33115
+ const parent = (0, import_node_path42.dirname)(primaryRepoRoot);
32925
33116
  try {
32926
- for (const name of (0, import_node_fs42.readdirSync)(parent)) {
32927
- const path2 = (0, import_node_path41.join)(parent, name);
33117
+ for (const name of (0, import_node_fs43.readdirSync)(parent)) {
33118
+ const path2 = (0, import_node_path42.join)(parent, name);
32928
33119
  if (path2 === primaryRepoRoot) continue;
32929
- if ((0, import_node_fs42.existsSync)((0, import_node_path41.join)(path2, ".git"))) found.add(path2);
33120
+ if ((0, import_node_fs43.existsSync)((0, import_node_path42.join)(path2, ".git"))) found.add(path2);
32930
33121
  }
32931
33122
  } catch {
32932
33123
  }
32933
- const mirror = (0, import_node_path41.join)((0, import_node_os17.homedir)(), "Projects", (0, import_node_path41.basename)(primaryRepoRoot));
32934
- if (mirror !== primaryRepoRoot && (0, import_node_fs42.existsSync)((0, import_node_path41.join)(mirror, ".git"))) found.add(mirror);
33124
+ const mirror = (0, import_node_path42.join)((0, import_node_os18.homedir)(), "Projects", (0, import_node_path42.basename)(primaryRepoRoot));
33125
+ if (mirror !== primaryRepoRoot && (0, import_node_fs43.existsSync)((0, import_node_path42.join)(mirror, ".git"))) found.add(mirror);
32935
33126
  return [...found];
32936
33127
  }
32937
- function readJervWorktreeLeaseRefs(leaseDir = (0, import_node_path41.join)((0, import_node_os17.homedir)(), ".jerv", "leases")) {
33128
+ function readJervWorktreeLeaseRefs(leaseDir = (0, import_node_path42.join)((0, import_node_os18.homedir)(), ".jerv", "leases")) {
32938
33129
  try {
32939
33130
  const refs = [];
32940
- for (const name of (0, import_node_fs42.readdirSync)(leaseDir)) {
33131
+ for (const name of (0, import_node_fs43.readdirSync)(leaseDir)) {
32941
33132
  if (!name.endsWith(".json")) continue;
32942
33133
  try {
32943
- const rec = JSON.parse((0, import_node_fs42.readFileSync)((0, import_node_path41.join)(leaseDir, name), "utf8"));
33134
+ const rec = JSON.parse((0, import_node_fs43.readFileSync)((0, import_node_path42.join)(leaseDir, name), "utf8"));
32944
33135
  if (rec.kind === "worktree" && rec.state !== "closed" && typeof rec.ref === "string" && rec.ref.trim()) {
32945
33136
  refs.push(rec.ref);
32946
33137
  }
@@ -32956,9 +33147,9 @@ function scanHelperWorktrees(thisPrimary, thisWorktreeGitRoot) {
32956
33147
  const primaries = [thisPrimary, ...discoverOtherPrimaries(thisPrimary)];
32957
33148
  const out = [];
32958
33149
  for (const primary of primaries) {
32959
- const gitRoot = primary === thisPrimary ? thisWorktreeGitRoot : (0, import_node_path41.join)(primary, ".git", "worktrees");
33150
+ const gitRoot = primary === thisPrimary ? thisWorktreeGitRoot : (0, import_node_path42.join)(primary, ".git", "worktrees");
32960
33151
  for (const root of helperWorktreeRoots(primary)) {
32961
- if (!(0, import_node_fs42.existsSync)(root)) continue;
33152
+ if (!(0, import_node_fs43.existsSync)(root)) continue;
32962
33153
  for (const dir of defaultOrphanDirScanDeps.listDirs(root)) {
32963
33154
  const inspected = inspectSiblingWorktreeDir(dir, gitRoot);
32964
33155
  const classified = classifySiblingWorktreeDir(inspected);
@@ -32998,7 +33189,7 @@ ${err.stderr ?? ""}`;
32998
33189
  }
32999
33190
 
33000
33191
  // src/issue-commands.ts
33001
- var import_node_fs43 = require("node:fs");
33192
+ var import_node_fs44 = require("node:fs");
33002
33193
  var import_node_crypto9 = require("node:crypto");
33003
33194
  var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
33004
33195
  var ReparentConflictError = class extends Error {
@@ -33016,7 +33207,7 @@ async function editIssue(client, options, deps = {}) {
33016
33207
  const url = `https://github.com/${repo}/issues/${parsed.number}`;
33017
33208
  const patch = {};
33018
33209
  let bodyChanged = false;
33019
- const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs43.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
33210
+ const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs44.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
33020
33211
  if (options.titleFile !== void 0) {
33021
33212
  patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
33022
33213
  } else if (options.title !== void 0) {
@@ -33621,7 +33812,7 @@ function extendCreateCommand(issue2, batchAttach) {
33621
33812
  if (opts.batch) {
33622
33813
  let specs;
33623
33814
  try {
33624
- const raw = (0, import_node_fs43.readFileSync)(opts.batch, "utf8");
33815
+ const raw = (0, import_node_fs44.readFileSync)(opts.batch, "utf8");
33625
33816
  specs = JSON.parse(raw);
33626
33817
  if (!Array.isArray(specs)) throw new Error("batch file must contain a JSON array");
33627
33818
  } catch (e) {
@@ -33696,8 +33887,8 @@ ${lines}`, {
33696
33887
  }
33697
33888
 
33698
33889
  // src/train-commands.ts
33699
- var import_node_fs44 = require("node:fs");
33700
- var import_node_path42 = require("node:path");
33890
+ var import_node_fs45 = require("node:fs");
33891
+ var import_node_path43 = require("node:path");
33701
33892
  var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
33702
33893
  function resolveReleaseBumpIntent(raw) {
33703
33894
  const intent = typeof raw === "string" ? raw.trim() : "";
@@ -33708,7 +33899,7 @@ function resolveReleaseBumpIntent(raw) {
33708
33899
  }
33709
33900
  function readRepoVersion() {
33710
33901
  try {
33711
- return JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path42.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
33902
+ return JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path43.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
33712
33903
  } catch {
33713
33904
  return void 0;
33714
33905
  }
@@ -33865,9 +34056,9 @@ function registerDeployCommands(program3) {
33865
34056
  }
33866
34057
 
33867
34058
  // src/discovery-commands.ts
33868
- var import_node_fs45 = require("node:fs");
33869
- var import_node_os18 = require("node:os");
33870
- var import_node_path43 = require("node:path");
34059
+ var import_node_fs46 = require("node:fs");
34060
+ var import_node_os19 = require("node:os");
34061
+ var import_node_path44 = require("node:path");
33871
34062
  var GC_GH_TIMEOUT_MS3 = 2e4;
33872
34063
  async function collectStatus() {
33873
34064
  const repo = await resolveRepo();
@@ -34051,10 +34242,10 @@ async function collectOnboardStatus(opts = {}) {
34051
34242
  else if (top) nextCommand = `mmi-cli oracle board claim ${top.number} # ${top.title}`;
34052
34243
  else nextCommand = "mmi-cli oracle board read \u2014 no claimable items found";
34053
34244
  }
34054
- const home = (0, import_node_os18.homedir)();
34245
+ const home = (0, import_node_os19.homedir)();
34055
34246
  const plugin = onboardPluginGate({
34056
- readKnown: () => readFileSyncSafe((0, import_node_path43.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs45.readFileSync),
34057
- readSettings: () => readFileSyncSafe((0, import_node_path43.join)(home, ".claude", "settings.json"), import_node_fs45.readFileSync)
34247
+ readKnown: () => readFileSyncSafe((0, import_node_path44.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs46.readFileSync),
34248
+ readSettings: () => readFileSyncSafe((0, import_node_path44.join)(home, ".claude", "settings.json"), import_node_fs46.readFileSync)
34058
34249
  });
34059
34250
  return { track, board, registry: registry2, secrets, plugin, estateCli, doors: opts.doors ?? [], nextCommand };
34060
34251
  }
@@ -37835,17 +38026,17 @@ function parseOriginRepo(remoteUrl) {
37835
38026
  }
37836
38027
  function ghHostsConfigPath(env, platform2) {
37837
38028
  const sep3 = platform2 === "win32" ? "\\" : "/";
37838
- const join40 = (...parts) => parts.join(sep3);
38029
+ const join41 = (...parts) => parts.join(sep3);
37839
38030
  const explicit = env.GH_CONFIG_DIR?.trim();
37840
- if (explicit) return join40(explicit, "hosts.yml");
38031
+ if (explicit) return join41(explicit, "hosts.yml");
37841
38032
  if (platform2 === "win32") {
37842
38033
  const appData = (env.AppData ?? env.APPDATA)?.trim();
37843
- return appData ? join40(appData, "GitHub CLI", "hosts.yml") : void 0;
38034
+ return appData ? join41(appData, "GitHub CLI", "hosts.yml") : void 0;
37844
38035
  }
37845
38036
  const xdg = env.XDG_CONFIG_HOME?.trim();
37846
- if (xdg) return join40(xdg, "gh", "hosts.yml");
38037
+ if (xdg) return join41(xdg, "gh", "hosts.yml");
37847
38038
  const home = env.HOME?.trim();
37848
- return home ? join40(home, ".config", "gh", "hosts.yml") : void 0;
38039
+ return home ? join41(home, ".config", "gh", "hosts.yml") : void 0;
37849
38040
  }
37850
38041
  function parseGhHostsAccounts(yaml, host = "github.com") {
37851
38042
  let hostIndent = null;
@@ -37895,9 +38086,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
37895
38086
  }
37896
38087
 
37897
38088
  // src/doctor-io.ts
37898
- var import_node_fs46 = require("node:fs");
37899
- var import_node_os19 = require("node:os");
37900
- var import_node_path44 = require("node:path");
38089
+ var import_node_fs47 = require("node:fs");
38090
+ var import_node_os20 = require("node:os");
38091
+ var import_node_path45 = require("node:path");
37901
38092
  var import_node_child_process18 = require("node:child_process");
37902
38093
  var import_node_util8 = require("node:util");
37903
38094
  var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process18.execFile);
@@ -37905,7 +38096,7 @@ var MMI_PLUGIN_ID2 = "mmi@mutmutco";
37905
38096
  function installedClaudePluginVersion() {
37906
38097
  try {
37907
38098
  const file = JSON.parse(
37908
- (0, import_node_fs46.readFileSync)((0, import_node_path44.join)((0, import_node_os19.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
38099
+ (0, import_node_fs47.readFileSync)((0, import_node_path45.join)((0, import_node_os20.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
37909
38100
  );
37910
38101
  const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
37911
38102
  if (versions.length === 0) return void 0;
@@ -37916,7 +38107,7 @@ function installedClaudePluginVersion() {
37916
38107
  }
37917
38108
  function manifestVersion(path2) {
37918
38109
  try {
37919
- const manifest = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
38110
+ const manifest = JSON.parse((0, import_node_fs47.readFileSync)(path2, "utf8"));
37920
38111
  return typeof manifest.version === "string" && manifest.version.trim() ? manifest.version.trim() : void 0;
37921
38112
  } catch {
37922
38113
  return void 0;
@@ -37926,20 +38117,20 @@ function installedSurfacePluginVersion(surface) {
37926
38117
  const token = surfaceToken(surface);
37927
38118
  if (token === "kilo") {
37928
38119
  try {
37929
- const stamp = (0, import_node_fs46.readFileSync)((0, import_node_path44.join)((0, import_node_os19.homedir)(), ".kilo", ".mmi-kilo-version"), "utf8").trim();
38120
+ const stamp = (0, import_node_fs47.readFileSync)((0, import_node_path45.join)((0, import_node_os20.homedir)(), ".kilo", ".mmi-kilo-version"), "utf8").trim();
37930
38121
  return stamp || void 0;
37931
38122
  } catch {
37932
38123
  return void 0;
37933
38124
  }
37934
38125
  }
37935
38126
  if (token === "cursor") {
37936
- return manifestVersion((0, import_node_path44.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
38127
+ return manifestVersion((0, import_node_path45.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
37937
38128
  }
37938
38129
  if (token === "jervcode") {
37939
38130
  return installedJervCodePackageVersion();
37940
38131
  }
37941
38132
  if (token === "kimi") {
37942
- return manifestVersion((0, import_node_path44.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
38133
+ return manifestVersion((0, import_node_path45.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
37943
38134
  }
37944
38135
  if (token === "claude") return installedClaudePluginVersion();
37945
38136
  if (token !== "codex") return void 0;
@@ -37977,13 +38168,13 @@ function worktreeRootSync() {
37977
38168
  }
37978
38169
  var gitignorePath = () => {
37979
38170
  const root = worktreeRootSync();
37980
- return root === null ? null : (0, import_node_path44.join)(root, ".gitignore");
38171
+ return root === null ? null : (0, import_node_path45.join)(root, ".gitignore");
37981
38172
  };
37982
38173
  function readGitignore() {
37983
38174
  const path2 = gitignorePath();
37984
38175
  if (path2 === null) return null;
37985
38176
  try {
37986
- return (0, import_node_fs46.readFileSync)(path2, "utf8");
38177
+ return (0, import_node_fs47.readFileSync)(path2, "utf8");
37987
38178
  } catch {
37988
38179
  return null;
37989
38180
  }
@@ -37992,7 +38183,7 @@ function writeGitignore(content) {
37992
38183
  const path2 = gitignorePath();
37993
38184
  if (path2 === null) return false;
37994
38185
  try {
37995
- (0, import_node_fs46.writeFileSync)(path2, content, "utf8");
38186
+ (0, import_node_fs47.writeFileSync)(path2, content, "utf8");
37996
38187
  return true;
37997
38188
  } catch {
37998
38189
  return false;
@@ -38011,7 +38202,7 @@ async function repoRoot() {
38011
38202
  }
38012
38203
  function hasRepoLocalWorktrees() {
38013
38204
  const root = worktreeRootSync();
38014
- return root !== null && ((0, import_node_fs46.existsSync)((0, import_node_path44.join)(root, ".worktrees")) || (0, import_node_fs46.existsSync)((0, import_node_path44.join)(root, ".claude", "worktrees")));
38205
+ return root !== null && ((0, import_node_fs47.existsSync)((0, import_node_path45.join)(root, ".worktrees")) || (0, import_node_fs47.existsSync)((0, import_node_path45.join)(root, ".claude", "worktrees")));
38015
38206
  }
38016
38207
 
38017
38208
  // src/cross-repo-filing-issue.ts
@@ -38117,8 +38308,8 @@ ${r.stderr ?? ""}`).catch(() => "");
38117
38308
  function ghMultiAccountCaveat(announcedLogin) {
38118
38309
  try {
38119
38310
  const hostsPath = ghHostsConfigPath(process.env, process.platform);
38120
- if (!hostsPath || !(0, import_node_fs47.existsSync)(hostsPath)) return void 0;
38121
- return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0, import_node_fs47.readFileSync)(hostsPath, "utf8")));
38311
+ if (!hostsPath || !(0, import_node_fs48.existsSync)(hostsPath)) return void 0;
38312
+ return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0, import_node_fs48.readFileSync)(hostsPath, "utf8")));
38122
38313
  } catch {
38123
38314
  return void 0;
38124
38315
  }
@@ -38126,12 +38317,12 @@ function ghMultiAccountCaveat(announcedLogin) {
38126
38317
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
38127
38318
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
38128
38319
  function envHealLockPath(home) {
38129
- return (0, import_node_path45.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
38320
+ return (0, import_node_path46.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
38130
38321
  }
38131
38322
  async function withEnvHealLock(what, run) {
38132
38323
  try {
38133
38324
  return await withFileLock(
38134
- envHealLockPath((0, import_node_os20.homedir)()),
38325
+ envHealLockPath((0, import_node_os21.homedir)()),
38135
38326
  { staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
38136
38327
  run
38137
38328
  );
@@ -38226,7 +38417,7 @@ function mmiDoctorDeps(opts = {}) {
38226
38417
  const configRoot = surfaceConfigRoot(surface);
38227
38418
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
38228
38419
  const plan = buildPluginCachePlan(
38229
- (0, import_node_os20.homedir)(),
38420
+ (0, import_node_os21.homedir)(),
38230
38421
  running,
38231
38422
  pluginCacheFsDeps(configRoot, () => 0),
38232
38423
  { configRoot, includeStaging: surface !== "codex" }
@@ -38250,14 +38441,14 @@ function mmiDoctorDeps(opts = {}) {
38250
38441
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
38251
38442
  const installed = installedActivePluginVersion(surface);
38252
38443
  const plan = buildPluginCachePlan(
38253
- (0, import_node_os20.homedir)(),
38444
+ (0, import_node_os21.homedir)(),
38254
38445
  running,
38255
38446
  pluginCacheFsDeps(configRoot, () => 0),
38256
38447
  { configRoot, includeStaging: surface !== "codex", installedVersion: installed }
38257
38448
  );
38258
38449
  const result = applyPluginCachePlan(
38259
38450
  plan,
38260
- (p) => (0, import_node_fs47.rmSync)(p, { recursive: true }),
38451
+ (p) => (0, import_node_fs48.rmSync)(p, { recursive: true }),
38261
38452
  stagingApplyFsGuard(configRoot)
38262
38453
  );
38263
38454
  return {
@@ -38295,7 +38486,7 @@ function mmiDoctorDeps(opts = {}) {
38295
38486
  // adopted the generated routing index (MMG-Unlive: `docs/Archive/**` only, no index, no gate.yml) would
38296
38487
  // get a permanent — demanding an artifact it never asked for.
38297
38488
  docsIndexState: (root) => {
38298
- if (!(0, import_node_fs47.existsSync)((0, import_node_path45.join)(root, DOCS_INDEX_PATH))) return void 0;
38489
+ if (!(0, import_node_fs48.existsSync)((0, import_node_path46.join)(root, DOCS_INDEX_PATH))) return void 0;
38299
38490
  const real = createDocsIndexDeps(root);
38300
38491
  let docs2;
38301
38492
  const listDocs = () => docs2 ??= real.listDocs();
@@ -38304,7 +38495,7 @@ function mmiDoctorDeps(opts = {}) {
38304
38495
  },
38305
38496
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
38306
38497
  healDocsIndex: (root) => {
38307
- if (!(0, import_node_fs47.existsSync)((0, import_node_path45.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
38498
+ if (!(0, import_node_fs48.existsSync)((0, import_node_path46.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
38308
38499
  const real = createDocsIndexDeps(root);
38309
38500
  let docs2;
38310
38501
  const listDocs = () => docs2 ??= real.listDocs();
@@ -38670,19 +38861,19 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
38670
38861
  });
38671
38862
  var rules = program2.command("rules").description("org-managed .gitignore delivery");
38672
38863
  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) => {
38673
- const path2 = (0, import_node_path45.join)(process.cwd(), ".gitignore");
38674
- const current = (0, import_node_fs47.existsSync)(path2) ? (0, import_node_fs47.readFileSync)(path2, "utf8") : null;
38864
+ const path2 = (0, import_node_path46.join)(process.cwd(), ".gitignore");
38865
+ const current = (0, import_node_fs48.existsSync)(path2) ? (0, import_node_fs48.readFileSync)(path2, "utf8") : null;
38675
38866
  const plan = planManagedGitignore(current);
38676
38867
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
38677
38868
  if (opts.json) {
38678
- if (opts.write && plan.changed) (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
38869
+ if (opts.write && plan.changed) (0, import_node_fs48.writeFileSync)(path2, plan.content, "utf8");
38679
38870
  console.log(JSON.stringify(plan, null, 2));
38680
38871
  if (!opts.write && plan.changed) process.exitCode = 1;
38681
38872
  return;
38682
38873
  }
38683
38874
  if (opts.write) {
38684
38875
  if (plan.changed) {
38685
- (0, import_node_fs47.writeFileSync)(path2, plan.content, "utf8");
38876
+ (0, import_node_fs48.writeFileSync)(path2, plan.content, "utf8");
38686
38877
  console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
38687
38878
  } else {
38688
38879
  console.log("mmi-cli devops org rules gitignore: up to date");
@@ -38841,8 +39032,8 @@ gcCmd.option("--dry-run", "show what would be deleted (default)").option("--appl
38841
39032
  if (!Number.isFinite(limit) || limit < 1) return fail("worktree gc: --limit must be a positive integer");
38842
39033
  let root;
38843
39034
  if (o.root !== void 0) {
38844
- root = (0, import_node_path45.resolve)(o.root);
38845
- if (!(0, import_node_fs47.existsSync)(root) || !(0, import_node_fs47.statSync)(root).isDirectory()) return fail(`worktree gc: --root ${o.root} is not a directory`);
39035
+ root = (0, import_node_path46.resolve)(o.root);
39036
+ if (!(0, import_node_fs48.existsSync)(root) || !(0, import_node_fs48.statSync)(root).isDirectory()) return fail(`worktree gc: --root ${o.root} is not a directory`);
38846
39037
  const gcRepoRoot = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
38847
39038
  if (isPathUnderDirectory2(gcRepoRoot, root)) {
38848
39039
  return fail(`worktree gc: --root ${root} contains this checkout \u2014 name a worktrees root, not the repo or an ancestor of it`);
@@ -38941,7 +39132,7 @@ async function currentWorktreeRemovalContext(command, force) {
38941
39132
  };
38942
39133
  }
38943
39134
  async function unprovenWorktreeReason(wtPath, repoRoot2) {
38944
- if (!(0, import_node_fs47.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
39135
+ if (!(0, import_node_fs48.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
38945
39136
  const porcelain = (await execFileP2("git", ["-C", repoRoot2, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
38946
39137
  const registered = parseWorktreePorcelainEntries(porcelain);
38947
39138
  if (!registered.length) {
@@ -38971,26 +39162,26 @@ function makeProvisionDeps(worktreeRoot, quiet, log) {
38971
39162
  function acquireWorktreeSetupLock(worktreeRoot) {
38972
39163
  const lockPath = repoRuntimeStatePath(worktreeRoot, "worktree-setup.lock");
38973
39164
  const take = () => {
38974
- const fd = (0, import_node_fs47.openSync)(lockPath, "wx");
39165
+ const fd = (0, import_node_fs48.openSync)(lockPath, "wx");
38975
39166
  try {
38976
- (0, import_node_fs47.writeSync)(fd, String(Date.now()));
39167
+ (0, import_node_fs48.writeSync)(fd, String(Date.now()));
38977
39168
  } finally {
38978
- (0, import_node_fs47.closeSync)(fd);
39169
+ (0, import_node_fs48.closeSync)(fd);
38979
39170
  }
38980
39171
  return () => {
38981
39172
  try {
38982
- (0, import_node_fs47.rmSync)(lockPath, { force: true });
39173
+ (0, import_node_fs48.rmSync)(lockPath, { force: true });
38983
39174
  } catch {
38984
39175
  }
38985
39176
  };
38986
39177
  };
38987
39178
  try {
38988
- (0, import_node_fs47.mkdirSync)((0, import_node_path45.dirname)(lockPath), { recursive: true });
39179
+ (0, import_node_fs48.mkdirSync)((0, import_node_path46.dirname)(lockPath), { recursive: true });
38989
39180
  return take();
38990
39181
  } catch {
38991
39182
  try {
38992
- if (Date.now() - (0, import_node_fs47.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
38993
- (0, import_node_fs47.rmSync)(lockPath, { force: true });
39183
+ if (Date.now() - (0, import_node_fs48.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
39184
+ (0, import_node_fs48.rmSync)(lockPath, { force: true });
38994
39185
  return take();
38995
39186
  }
38996
39187
  } catch {
@@ -39070,8 +39261,10 @@ withExamples(mutating(
39070
39261
  }
39071
39262
  };
39072
39263
  if (preferRemote && await revParseRef(preferRemote)) base = preferRemote;
39264
+ const resolvedBaseOid = await revParseRef(base);
39265
+ if (!resolvedBaseOid) return fail(`worktree create: could not resolve creation base '${base}' to an immutable commit`);
39073
39266
  if (!o.json) {
39074
- const baseSha = (await revParseRef(base))?.slice(0, 12) ?? "unresolved";
39267
+ const baseSha = resolvedBaseOid.slice(0, 12);
39075
39268
  const localOnly = preferRemote && base !== preferRemote ? ` (no ${preferRemote} ? local ref)` : "";
39076
39269
  console.error(` base ${base} ${baseSha}${localOnly}`);
39077
39270
  }
@@ -39090,23 +39283,45 @@ withExamples(mutating(
39090
39283
  const status = (await execFileP2("git", ["-C", wtPath, "status", "--porcelain"], { timeout: GIT_TIMEOUT_MS })).stdout.trim();
39091
39284
  if (status) return fail(`worktree create: refusing to resume ${wtPath} \u2014 it has uncommitted changes`);
39092
39285
  const head = await revParseRef(`refs/heads/${branch}`);
39093
- const baseOid = await revParseRef(base);
39094
- if (!head || !baseOid) return fail(`worktree create: could not prove '${branch}' and '${base}' before resume`);
39286
+ const baseOid = resolvedBaseOid;
39287
+ if (!head) return fail(`worktree create: could not prove '${branch}' and '${base}' before resume`);
39095
39288
  const canFastForward = await execFileP2(
39096
39289
  "git",
39097
39290
  ["-C", repoRoot2, "merge-base", "--is-ancestor", head, baseOid],
39098
39291
  { timeout: GIT_TIMEOUT_MS }
39099
39292
  // io-census-allow: an unprovable ancestor probe conservatively refuses the resume below rather than fast-forwarding onto unproven history
39100
39293
  ).then(() => true).catch(() => false);
39101
- if (!canFastForward) {
39102
- return fail(`worktree create: refusing to resume '${branch}' \u2014 it has local commits or diverges from ${base}`);
39294
+ if (canFastForward) {
39295
+ await execFileP2("git", ["-C", wtPath, "merge", "--ff-only", base], { timeout: GIT_TIMEOUT_MS });
39296
+ resumed = true;
39297
+ } else {
39298
+ const owner2 = lookupWorktreeOwner(repoRoot2, wtPath);
39299
+ const delivered = await proveExactTreeDelivery({
39300
+ repoRoot: repoRoot2,
39301
+ branch,
39302
+ workerOid: head,
39303
+ creationBaseOid: owner2?.provenance?.creationBaseOid,
39304
+ recordedWorkerBranch: owner2?.provenance?.workerBranch,
39305
+ landedTips: [baseOid]
39306
+ });
39307
+ if (delivered.action !== "settle") {
39308
+ return fail(`worktree create: refusing to resume '${branch}' \u2014 it has local commits or diverges from ${base}; exact-tree delivery proof refused (${describeExactTreeRefusal(delivered)})`);
39309
+ }
39310
+ const repoint = await repointDeliveredWorktreeTransactionally({
39311
+ branch,
39312
+ expectedWorkerOid: head,
39313
+ landedTipOid: baseOid,
39314
+ git: async (args) => (await execFileP2("git", ["-C", wtPath, ...args], { timeout: GIT_TIMEOUT_MS })).stdout
39315
+ });
39316
+ if (repoint.action !== "repointed") {
39317
+ return fail(`worktree create: exact-tree delivery was proven by ${delivered.candidateOid}, but transactional resume refused (${repoint.reason}${repoint.detail ? `: ${repoint.detail}` : ""})`);
39318
+ }
39319
+ resumed = true;
39103
39320
  }
39104
- await execFileP2("git", ["-C", wtPath, "merge", "--ff-only", base], { timeout: GIT_TIMEOUT_MS });
39105
- resumed = true;
39106
39321
  }
39107
39322
  if (!resumed) {
39108
39323
  step = `git worktree add ${wtPath}`;
39109
- const wtPathPreExisted = (0, import_node_fs47.existsSync)(wtPath);
39324
+ const wtPathPreExisted = (0, import_node_fs48.existsSync)(wtPath);
39110
39325
  const partialRemove = worktreeRemoveDeps(async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout);
39111
39326
  await withWorktreeAddLock(repoRoot2, () => addWorktreeRobust(wtPath, branch, base, {
39112
39327
  // #4834: `-c core.longpaths=true` rides the add command itself — a Windows worktree path
@@ -39122,7 +39337,7 @@ withExamples(mutating(
39122
39337
  },
39123
39338
  deleteBranch: (b) => execFileP2("git", ["branch", "-D", b], { timeout: GIT_TIMEOUT_MS }).then(() => void 0),
39124
39339
  cleanupPartial: async () => {
39125
- if (wtPathPreExisted || !(0, import_node_fs47.existsSync)(wtPath)) return;
39340
+ if (wtPathPreExisted || !(0, import_node_fs48.existsSync)(wtPath)) return;
39126
39341
  partialRemove.detachReparsePoints(wtPath);
39127
39342
  await execFileP2("git", ["worktree", "remove", "--force", wtPath], { timeout: GIT_TIMEOUT_MS }).catch(() => partialRemove.removeWorktreeDir(wtPath).then(() => void 0));
39128
39343
  await execFileP2("git", ["worktree", "prune"], { timeout: GIT_TIMEOUT_MS }).catch(() => {
@@ -39166,7 +39381,14 @@ withExamples(mutating(
39166
39381
  }
39167
39382
  const createActor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
39168
39383
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
39169
- const owner = { path: wtPath, branch, createdAt, lastSeenAt: createdAt, actor: createActor };
39384
+ const owner = {
39385
+ path: wtPath,
39386
+ branch,
39387
+ provenance: { creationBaseOid: resolvedBaseOid, workerBranch: branch },
39388
+ createdAt,
39389
+ lastSeenAt: createdAt,
39390
+ actor: createActor
39391
+ };
39170
39392
  recordWorktreeOwner(repoRoot2, owner);
39171
39393
  appendWorktreeEvent(repoRoot2, { action: "created", command: "worktree create", target: wtPath, branch, actor: owner.actor });
39172
39394
  let lease;
@@ -39903,7 +40125,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
39903
40125
  if (dupe) return fail(`org project set: KEY "${dupe}" was passed to both --var and --set; --set is an alias of --var, so pass each KEY once`);
39904
40126
  if (o.secretsFile) {
39905
40127
  try {
39906
- vars.push(`secrets=${(0, import_node_fs47.readFileSync)(o.secretsFile, "utf8")}`);
40128
+ vars.push(`secrets=${(0, import_node_fs48.readFileSync)(o.secretsFile, "utf8")}`);
39907
40129
  } catch (e) {
39908
40130
  return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
39909
40131
  }
@@ -40671,11 +40893,11 @@ pr.command("view <number>").description("read a PR as structured JSON (merged st
40671
40893
  }
40672
40894
  });
40673
40895
  async function listCiWorkflowPaths(cwd = process.cwd()) {
40674
- const wfDir = (0, import_node_path45.join)(cwd, ".github", "workflows");
40675
- if (!(0, import_node_fs47.existsSync)(wfDir)) return [];
40676
- return (0, import_node_fs47.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
40896
+ const wfDir = (0, import_node_path46.join)(cwd, ".github", "workflows");
40897
+ if (!(0, import_node_fs48.existsSync)(wfDir)) return [];
40898
+ return (0, import_node_fs48.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
40677
40899
  try {
40678
- return workflowReportsPrChecks((0, import_node_fs47.readFileSync)((0, import_node_path45.join)(wfDir, name), "utf8"));
40900
+ return workflowReportsPrChecks((0, import_node_fs48.readFileSync)((0, import_node_path46.join)(wfDir, name), "utf8"));
40679
40901
  } catch {
40680
40902
  return true;
40681
40903
  }
@@ -40727,16 +40949,16 @@ function ciAuditDeps() {
40727
40949
  // gate re-seed step is skipped gracefully rather than failing mid-run.
40728
40950
  readSeedFile: (path2) => {
40729
40951
  if (!root) return null;
40730
- const fullPath = (0, import_node_path45.join)(root, path2);
40731
- return (0, import_node_fs47.existsSync)(fullPath) ? (0, import_node_fs47.readFileSync)(fullPath, "utf8") : null;
40952
+ const fullPath = (0, import_node_path46.join)(root, path2);
40953
+ return (0, import_node_fs48.existsSync)(fullPath) ? (0, import_node_fs48.readFileSync)(fullPath, "utf8") : null;
40732
40954
  }
40733
40955
  };
40734
40956
  }
40735
40957
  function hubRoot() {
40736
- const fromPkg = (0, import_node_path45.join)(__dirname, "..", "..");
40958
+ const fromPkg = (0, import_node_path46.join)(__dirname, "..", "..");
40737
40959
  const marker = "skills/bootstrap/seeds/manifest.json";
40738
- if ((0, import_node_fs47.existsSync)((0, import_node_path45.join)(fromPkg, marker))) return fromPkg;
40739
- if ((0, import_node_fs47.existsSync)((0, import_node_path45.join)(process.cwd(), marker))) return process.cwd();
40960
+ if ((0, import_node_fs48.existsSync)((0, import_node_path46.join)(fromPkg, marker))) return fromPkg;
40961
+ if ((0, import_node_fs48.existsSync)((0, import_node_path46.join)(process.cwd(), marker))) return process.cwd();
40740
40962
  return null;
40741
40963
  }
40742
40964
  async function waitLoopCorePool(label) {
@@ -41067,7 +41289,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
41067
41289
  }
41068
41290
  if (!repoForPostCleanup) throw e;
41069
41291
  console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
41070
- const commitMessage = bodyFile ? (0, import_node_fs47.readFileSync)(bodyFile, "utf8") : void 0;
41292
+ const commitMessage = bodyFile ? (0, import_node_fs48.readFileSync)(bodyFile, "utf8") : void 0;
41071
41293
  await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
41072
41294
  body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
41073
41295
  timeoutMs: GH_MUTATION_TIMEOUT_MS
@@ -41163,7 +41385,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
41163
41385
  localCleanup = await cleanupPrMergeLocalBranch(headRef, {
41164
41386
  beforeWorktrees,
41165
41387
  startingPath,
41166
- pathExists: (p) => (0, import_node_fs47.existsSync)(p),
41388
+ pathExists: (p) => (0, import_node_fs48.existsSync)(p),
41167
41389
  execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
41168
41390
  teardownWorktreeStage,
41169
41391
  deferredStore,
@@ -41767,12 +41989,12 @@ access.command("audit").description("audit collaborator roles + train-branch pus
41767
41989
  targets = resolution.targets;
41768
41990
  }
41769
41991
  const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
41770
- const fileMatrix = (0, import_node_fs47.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs47.readFileSync)("access-matrix.json", "utf8")) : {};
41992
+ const fileMatrix = (0, import_node_fs48.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs48.readFileSync)("access-matrix.json", "utf8")) : {};
41771
41993
  const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
41772
41994
  const derivedContracts = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
41773
- const fileContracts = (0, import_node_fs47.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs47.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
41995
+ const fileContracts = (0, import_node_fs48.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs48.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
41774
41996
  const dataAccess = mergeDataAccessContracts(fileContracts, derivedContracts);
41775
- const sanctioned = (0, import_node_fs47.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs47.readFileSync)("access-matrix.json", "utf8")) : {};
41997
+ const sanctioned = (0, import_node_fs48.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs48.readFileSync)("access-matrix.json", "utf8")) : {};
41776
41998
  const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
41777
41999
  console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
41778
42000
  if (!report.ok) process.exitCode = 1;
@@ -41804,16 +42026,16 @@ function directoryBytes(path2) {
41804
42026
  let total = 0;
41805
42027
  let entries;
41806
42028
  try {
41807
- entries = (0, import_node_fs47.readdirSync)(path2, { withFileTypes: true });
42029
+ entries = (0, import_node_fs48.readdirSync)(path2, { withFileTypes: true });
41808
42030
  } catch {
41809
42031
  return 0;
41810
42032
  }
41811
42033
  for (const entry of entries) {
41812
- const child2 = (0, import_node_path45.join)(path2, entry.name);
42034
+ const child2 = (0, import_node_path46.join)(path2, entry.name);
41813
42035
  if (entry.isDirectory()) total += directoryBytes(child2);
41814
42036
  else {
41815
42037
  try {
41816
- total += (0, import_node_fs47.statSync)(child2).size;
42038
+ total += (0, import_node_fs48.statSync)(child2).size;
41817
42039
  } catch {
41818
42040
  }
41819
42041
  }
@@ -41821,25 +42043,25 @@ function directoryBytes(path2) {
41821
42043
  return total;
41822
42044
  }
41823
42045
  function listDirEntries(dir) {
41824
- return (0, import_node_fs47.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
42046
+ return (0, import_node_fs48.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
41825
42047
  }
41826
42048
  function readInstalledPluginRefs(configRoot) {
41827
42049
  const p = installedPluginsPathForConfig(configRoot);
41828
- if (!(0, import_node_fs47.existsSync)(p)) return [];
42050
+ if (!(0, import_node_fs48.existsSync)(p)) return [];
41829
42051
  try {
41830
- return installedPluginPaths((0, import_node_fs47.readFileSync)(p, "utf8"));
42052
+ return installedPluginPaths((0, import_node_fs48.readFileSync)(p, "utf8"));
41831
42053
  } catch {
41832
42054
  return null;
41833
42055
  }
41834
42056
  }
41835
42057
  function pluginCacheFsDeps(configRoot, dirBytes) {
41836
42058
  return {
41837
- exists: (p) => (0, import_node_fs47.existsSync)(p),
41838
- listVersionDirs: (root) => (0, import_node_fs47.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
42059
+ exists: (p) => (0, import_node_fs48.existsSync)(p),
42060
+ listVersionDirs: (root) => (0, import_node_fs48.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
41839
42061
  dirBytes,
41840
- listStagingDirs: (root) => (0, import_node_fs47.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
42062
+ listStagingDirs: (root) => (0, import_node_fs48.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
41841
42063
  try {
41842
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path45.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs47.statSync)(p).mtimeMs) };
42064
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path46.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs48.statSync)(p).mtimeMs) };
41843
42065
  } catch {
41844
42066
  return { name: d.name, mtimeMs: Date.now() };
41845
42067
  }
@@ -41853,10 +42075,10 @@ function stagingApplyFsGuard(configRoot) {
41853
42075
  return {
41854
42076
  referencedPaths: () => readInstalledPluginRefs(configRoot),
41855
42077
  mtimeMs: (name) => {
41856
- const p = (0, import_node_path45.join)(stagingRoot, name);
41857
- if (!(0, import_node_fs47.existsSync)(p)) return null;
42078
+ const p = (0, import_node_path46.join)(stagingRoot, name);
42079
+ if (!(0, import_node_fs48.existsSync)(p)) return null;
41858
42080
  try {
41859
- return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs47.statSync)(q).mtimeMs);
42081
+ return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs48.statSync)(q).mtimeMs);
41860
42082
  } catch {
41861
42083
  return null;
41862
42084
  }
@@ -41876,13 +42098,13 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
41876
42098
  return;
41877
42099
  }
41878
42100
  const plan = buildPluginCachePlan(
41879
- (0, import_node_os20.homedir)(),
42101
+ (0, import_node_os21.homedir)(),
41880
42102
  running,
41881
42103
  pluginCacheFsDeps(configRoot, directoryBytes),
41882
42104
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
41883
42105
  );
41884
42106
  const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
41885
- const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs47.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
42107
+ const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs48.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
41886
42108
  const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
41887
42109
  if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
41888
42110
  else console.log(renderPluginCachePlan(plan, result));