@mutmutco/claude-plugin 4.6.36 → 4.6.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/dist/main.cjs CHANGED
@@ -1229,8 +1229,6 @@ var init_house_map = __esm({
1229
1229
  // --- harbour — declared lanes -------------------------------------------------------------------
1230
1230
  "org schedules": "harbour",
1231
1231
  // register/run/park schedule rows under the one lane contract
1232
- intercom: "harbour",
1233
- // #9184: the guest coordination lane to the MM Coordinator — a bounded lane, not a claim on org truth
1234
1232
  // --- devops — shipping --------------------------------------------------------------------------
1235
1233
  pr: "devops",
1236
1234
  read: "devops",
@@ -1279,6 +1277,11 @@ var init_house_map = __esm({
1279
1277
  pickup: "learning",
1280
1278
  // cloud-agent adoption gate (#5708)
1281
1279
  // --- core — the front door itself ---------------------------------------------------------------
1280
+ // #9993: `intercom` is the guest's own coordination door, not a declared org lane — it reads and
1281
+ // writes nothing of this org's truth (no schedules, no registry, no board), it talks to the Jerv
1282
+ // Gateway as this caller's own GitHub identity. So it is core: `mmi-cli intercom guest …`, unprefixed.
1283
+ // The old `harbour intercom guest …` spelling still runs through HOUSE_ALIASES below.
1284
+ intercom: "core",
1282
1285
  commands: "core",
1283
1286
  whoami: "core",
1284
1287
  spawn: "core",
@@ -1303,7 +1306,9 @@ var init_house_map = __esm({
1303
1306
  HOUSE_ALIASES = {
1304
1307
  issue: ["devops"],
1305
1308
  // filing/managing issues is oracle, but reads as shipping work
1306
- "issue create": ["devops"]
1309
+ "issue create": ["devops"],
1310
+ intercom: ["harbour"]
1311
+ // #9993: `intercom` moved out of harbour to core; the old spelling still routes
1307
1312
  };
1308
1313
  }
1309
1314
  });
@@ -13690,7 +13695,7 @@ function isAgentScratchPath(path2) {
13690
13695
  return /^tmp_[^/]+$/.test(normalized);
13691
13696
  }
13692
13697
  var PUSH_WALL_AGENT_CONFIG_DIRS = [".cursor/rules/", ".codex/", ".agents/"];
13693
- var LIVE_SESSION_DIRS = [".jerv/", ".pi/"];
13698
+ var LIVE_SESSION_DIRS = [".jerv/", ".pi/", "review-state/"];
13694
13699
  function pathUnderDirPrefix(path2, dir) {
13695
13700
  return path2 === dir || path2 === dir.slice(0, -1) || path2.startsWith(dir) || path2.includes(`/${dir}`);
13696
13701
  }
@@ -14549,7 +14554,7 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
14549
14554
  function archiveWorktreeTmpArtifacts(args, deps = {}) {
14550
14555
  const copyFile = deps.copyFile ?? import_node_fs12.copyFileSync;
14551
14556
  const fileSize = deps.fileSize ?? ((path2) => (0, import_node_fs12.statSync)(path2).size);
14552
- const writeFile4 = deps.writeFile ?? ((path2, text) => (0, import_node_fs12.writeFileSync)(path2, text));
14557
+ const writeFile5 = deps.writeFile ?? ((path2, text) => (0, import_node_fs12.writeFileSync)(path2, text));
14553
14558
  const mkdirp = deps.mkdirp ?? ((path2) => {
14554
14559
  (0, import_node_fs12.mkdirSync)(path2, { recursive: true });
14555
14560
  });
@@ -14576,7 +14581,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
14576
14581
  bytes += copied;
14577
14582
  }
14578
14583
  const manifest = (0, import_node_path9.join)((0, import_node_path9.dirname)(dest), "tmp-manifest.json");
14579
- writeFile4(manifest, `${JSON.stringify({ files: scan.entries.map(({ relPath, bytes: b }) => ({ relPath, bytes: b })), bytes, excluded: scan.excluded, skippedLinks: scan.links }, null, 2)}
14584
+ writeFile5(manifest, `${JSON.stringify({ files: scan.entries.map(({ relPath, bytes: b }) => ({ relPath, bytes: b })), bytes, excluded: scan.excluded, skippedLinks: scan.links }, null, 2)}
14580
14585
  `);
14581
14586
  return { status: "archived", path: dest, runScope, entries: scan.entries.length, bytes, manifest, excluded: scan.excluded, skippedLinks: scan.links };
14582
14587
  } catch (e) {
@@ -15261,8 +15266,8 @@ function resolveVerbAliasShim(argv) {
15261
15266
  }
15262
15267
 
15263
15268
  // src/command-composition.ts
15264
- var import_node_os28 = require("node:os");
15265
- var import_node_path64 = require("node:path");
15269
+ var import_node_os29 = require("node:os");
15270
+ var import_node_path65 = require("node:path");
15266
15271
 
15267
15272
  // src/board-read.ts
15268
15273
  var import_node_fs18 = require("node:fs");
@@ -25302,6 +25307,8 @@ var MANAGED_GITIGNORE_LINES = [
25302
25307
  // (measured on the v3.120.0 Hub train), with no legal resolution: committing another host's runtime
25303
25308
  // state is not an option, so the operator's only move was to park the directory outside the repo.
25304
25309
  ".pi/",
25310
+ // #10003: reviewer worktrees — never committable, regenerate during review (same runtime class as `.pi/`).
25311
+ "/review-state/",
25305
25312
  ".aws-sam/",
25306
25313
  // jerv-cli lease markers are ephemeral runtime state and never tracked. Hub#2586.
25307
25314
  ".jerv-lease.json",
@@ -25427,7 +25434,7 @@ function extractForwardRefs(markdown) {
25427
25434
  });
25428
25435
  return refs;
25429
25436
  }
25430
- function checkPins(root, readFile10, docs) {
25437
+ function checkPins(root, readFile11, docs) {
25431
25438
  const findings = [];
25432
25439
  for (const [doc, markdown] of Object.entries(docs)) {
25433
25440
  for (const pin of extractPins(markdown)) {
@@ -25435,7 +25442,7 @@ function checkPins(root, readFile10, docs) {
25435
25442
  findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
25436
25443
  continue;
25437
25444
  }
25438
- const source = readFile10((0, import_node_path16.join)(root, pin.file));
25445
+ const source = readFile11((0, import_node_path16.join)(root, pin.file));
25439
25446
  if (source == null) {
25440
25447
  findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
25441
25448
  continue;
@@ -25731,15 +25738,15 @@ function checkRunbookCoverage(docs, base, git3) {
25731
25738
  }
25732
25739
  return findings;
25733
25740
  }
25734
- function checkSeedRunbookReview(root, base, readFile10, git3) {
25735
- const manifestJson = readFile10((0, import_node_path16.join)(root, "skills/bootstrap/seeds/manifest.json"));
25741
+ function checkSeedRunbookReview(root, base, readFile11, git3) {
25742
+ const manifestJson = readFile11((0, import_node_path16.join)(root, "skills/bootstrap/seeds/manifest.json"));
25736
25743
  if (!manifestJson) return [];
25737
25744
  const changed = new Set(git3(["diff", "--name-only", `${base}...HEAD`]).split(/\r?\n/).filter(Boolean));
25738
25745
  const touched = loadBootstrapSeeds(manifestJson).seeds.filter((seed) => isPropagatableSeed(seed) && changed.has(seedSourcePath(seed)));
25739
25746
  if (!touched.length) return [];
25740
25747
  let declarations = null;
25741
25748
  try {
25742
- declarations = JSON.parse(readFile10((0, import_node_path16.join)(root, RUNBOOK_UNAFFECTED_PATH)) ?? "null");
25749
+ declarations = JSON.parse(readFile11((0, import_node_path16.join)(root, RUNBOOK_UNAFFECTED_PATH)) ?? "null");
25743
25750
  } catch {
25744
25751
  declarations = null;
25745
25752
  }
@@ -25826,12 +25833,12 @@ function defaultTrackedFiles(root, firstSegments, exec3 = import_node_child_proc
25826
25833
  throw error;
25827
25834
  }
25828
25835
  }
25829
- function mergeGroupRunbookMessages(root, deps, readFile10, warnings) {
25836
+ function mergeGroupRunbookMessages(root, deps, readFile11, warnings) {
25830
25837
  const env = deps.env ?? process.env;
25831
25838
  if (env.GITHUB_EVENT_NAME !== "merge_group") return "";
25832
25839
  let source = "merge_group event payload";
25833
25840
  try {
25834
- const event = JSON.parse(readFile10(env.GITHUB_EVENT_PATH ?? "") ?? "");
25841
+ const event = JSON.parse(readFile11(env.GITHUB_EVENT_PATH ?? "") ?? "");
25835
25842
  const match = /^refs\/heads\/gh-readonly-queue\/.+\/pr-([1-9]\d*)-[a-f0-9]+$/.exec(event.merge_group?.head_ref ?? "");
25836
25843
  const repo = env.GITHUB_REPOSITORY;
25837
25844
  if (!match || !repo || !/^[\w.-]+\/[\w.-]+$/.test(repo)) throw new Error("invalid queue source");
@@ -25854,7 +25861,7 @@ function mergeGroupRunbookMessages(root, deps, readFile10, warnings) {
25854
25861
  }
25855
25862
  }
25856
25863
  function runDocRefs(root, deps = {}) {
25857
- const readFile10 = deps.readFile ?? readFileOrNull;
25864
+ const readFile11 = deps.readFile ?? readFileOrNull;
25858
25865
  const exists = deps.exists ?? import_node_fs19.existsSync;
25859
25866
  const listDocs = deps.listDocs ?? defaultListDocs;
25860
25867
  const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
@@ -25868,11 +25875,11 @@ function runDocRefs(root, deps = {}) {
25868
25875
  const walked = listDocs(root);
25869
25876
  const ignoredDocs = walked.length ? isIgnored(walked) : /* @__PURE__ */ new Set();
25870
25877
  const docs = Object.fromEntries(
25871
- walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile10((0, import_node_path16.join)(root, rel))]).filter(([rel, body]) => body != null && (!deps.runbooksOnly || isRunbook(rel, body)))
25878
+ walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile11((0, import_node_path16.join)(root, rel))]).filter(([rel, body]) => body != null && (!deps.runbooksOnly || isRunbook(rel, body)))
25872
25879
  );
25873
25880
  const refResult = checkRefs(root, { exists, isIgnored, trackedFirstSegments }, docs);
25874
25881
  const findings = [
25875
- ...checkPins(root, readFile10, docs).findings,
25882
+ ...checkPins(root, readFile11, docs).findings,
25876
25883
  ...refResult.findings
25877
25884
  ];
25878
25885
  if (commandPaths == null) {
@@ -25886,7 +25893,7 @@ function runDocRefs(root, deps = {}) {
25886
25893
  findings.push(...checkCommands(docs, commandPaths).findings);
25887
25894
  }
25888
25895
  const runbooks = Object.fromEntries(Object.entries(docs).filter(([doc, body]) => isRunbook(doc, body)));
25889
- findings.push(...checkRunbookClaims(root, runbooks, { readFile: readFile10, exists, isIgnored, trackedFirstSegments, commandPaths, commandOptions: deps.commandOptions, commandSource: deps.commandSource }));
25896
+ findings.push(...checkRunbookClaims(root, runbooks, { readFile: readFile11, exists, isIgnored, trackedFirstSegments, commandPaths, commandOptions: deps.commandOptions, commandSource: deps.commandSource }));
25890
25897
  const warnings = [...refResult.warnings];
25891
25898
  if (deps.runbooksOnly && !Object.keys(runbooks).length) {
25892
25899
  warnings.push({ kind: "runbook-missing", doc: "docs/Guides/operator.md", line: 0, detail: "no operator runbook or <!-- runbook --> document exists" });
@@ -25894,9 +25901,9 @@ function runDocRefs(root, deps = {}) {
25894
25901
  if (deps.base) {
25895
25902
  const git3 = deps.git ?? ((args) => (0, import_node_child_process6.execFileSync)("git", args, { cwd: root, encoding: "utf8", maxBuffer: CHECK_IGNORE_MAX_BUFFER, windowsHide: true }));
25896
25903
  const stale = checkRunbookCoverage(runbooks, deps.base, git3);
25897
- const seedStale = checkSeedRunbookReview(root, deps.base, readFile10, git3);
25904
+ const seedStale = checkSeedRunbookReview(root, deps.base, readFile11, git3);
25898
25905
  const messages = git3(["log", "--format=%B", `${deps.base}..HEAD`]);
25899
- const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps, readFile10, warnings) : "";
25906
+ const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps, readFile11, warnings) : "";
25900
25907
  const allMessages = `${messages}
25901
25908
  ${sourceMessages}`;
25902
25909
  const override = /^Runbook-Unaffected:[ \t]*\S.*$/m.test(allMessages);
@@ -26855,22 +26862,22 @@ function renderBootstrapAncillaryPlan(labels, environments, exceptions = []) {
26855
26862
  ...exceptions.map(({ name, detail }) => ` OK environment ${name} (${detail})`)
26856
26863
  ].join("\n");
26857
26864
  }
26858
- function resolveSeedContent(seed, vars, readFile10) {
26859
- if (seed.source === "self") return readFile10(seed.target);
26865
+ function resolveSeedContent(seed, vars, readFile11) {
26866
+ if (seed.source === "self") return readFile11(seed.target);
26860
26867
  if (seed.source.startsWith("seed:")) {
26861
- const tmpl = readFile10(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
26868
+ const tmpl = readFile11(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
26862
26869
  return tmpl == null ? null : renderSeed(tmpl, vars);
26863
26870
  }
26864
26871
  return null;
26865
26872
  }
26866
- function resolveSeedWriteContent(seed, vars, readFile10, remoteContent) {
26873
+ function resolveSeedWriteContent(seed, vars, readFile11, remoteContent) {
26867
26874
  if (!seed.managedBlock) {
26868
- return { ok: true, content: resolveSeedContent(seed, vars, readFile10), managed: seed.source === "managed-block" };
26875
+ return { ok: true, content: resolveSeedContent(seed, vars, readFile11), managed: seed.source === "managed-block" };
26869
26876
  }
26870
- const base = remoteContent ?? resolveSeedContent(seed, vars, readFile10);
26877
+ const base = remoteContent ?? resolveSeedContent(seed, vars, readFile11);
26871
26878
  if (base == null) return { ok: true, content: null, managed: true };
26872
26879
  const blockSeed = { ...seed, source: seed.managedBlock.source, managedBlock: void 0 };
26873
- const desired = resolveSeedContent(blockSeed, vars, readFile10);
26880
+ const desired = resolveSeedContent(blockSeed, vars, readFile11);
26874
26881
  if (desired == null) return { ok: true, content: null, managed: true };
26875
26882
  const result = upsertManagedSeedBlock(base, desired, seed.managedBlock.begin, seed.managedBlock.end);
26876
26883
  return result.ok ? { ok: true, content: result.content, managed: true } : { ok: false, reason: result.reason, managed: true };
@@ -28385,10 +28392,10 @@ var rollout_plan_default = {
28385
28392
  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)."
28386
28393
  },
28387
28394
  baseline: {
28388
- version: "4.6.36",
28389
- tag: "v4.6.36",
28390
- commit: "d1c15e58d6e5",
28391
- npm: "@mutmutco/cli@4.6.36"
28395
+ version: "4.6.37",
28396
+ tag: "v4.6.37",
28397
+ commit: "94211a24e48a",
28398
+ npm: "@mutmutco/cli@4.6.37"
28392
28399
  },
28393
28400
  exitCriterion: "fleet-n-of-n",
28394
28401
  hubOnlyShortcut: "forbidden",
@@ -28405,14 +28412,14 @@ var rollout_plan_default = {
28405
28412
  repo: "mutmutco/mmi-hub",
28406
28413
  role: "canary",
28407
28414
  schedule: "train",
28408
- v3Target: "v4.6.36"
28415
+ v3Target: "v4.6.37"
28409
28416
  }
28410
28417
  ],
28411
28418
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
28412
28419
  rollback: {
28413
28420
  independent: true,
28414
- mechanism: "npm dist-tag latest -> 4.6.36 and redeploy the Hub Lambda from tag v4.6.36 (d1c15e58d6e5); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28415
- v3Target: "v4.6.36 (@mutmutco/cli@4.6.36, tag commit d1c15e58d6e5 \u2014 last known-good release carrying the repo-index v4-only contract)"
28421
+ mechanism: "npm dist-tag latest -> 4.6.37 and redeploy the Hub Lambda from tag v4.6.37 (94211a24e48a); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28422
+ v3Target: "v4.6.37 (@mutmutco/cli@4.6.37, tag commit 94211a24e48a \u2014 last known-good release carrying the repo-index v4-only contract)"
28416
28423
  }
28417
28424
  },
28418
28425
  {
@@ -43435,8 +43442,8 @@ function annotateChangeMeaning(changed, policy, read) {
43435
43442
  function isMeaningfulRow(file) {
43436
43443
  return file.meaningful !== false;
43437
43444
  }
43438
- function loadPolicy(root, readFile10 = readFileOrNull2) {
43439
- const raw = readFile10((0, import_node_path30.join)(root, POLICY_FILE));
43445
+ function loadPolicy(root, readFile11 = readFileOrNull2) {
43446
+ const raw = readFile11((0, import_node_path30.join)(root, POLICY_FILE));
43440
43447
  if (raw == null) return { mandatory: [], declared: false };
43441
43448
  return parsePolicy(raw, POLICY_FILE);
43442
43449
  }
@@ -44173,12 +44180,16 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
44173
44180
  receipt = { ...receipt, state: "pending", uuid: details.uuid };
44174
44181
  }
44175
44182
  const sleep2 = options.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
44176
- for (let attempt = 0; attempt < 3; attempt++) {
44177
- if (attempt) await sleep2(attempt * 1e3);
44183
+ const confirmDelays = [0, 1e3, 2e3, 4e3, 8e3, 15e3, 15e3, 15e3];
44184
+ let readFailure;
44185
+ for (const delay of confirmDelays) {
44186
+ if (delay) await sleep2(delay);
44187
+ readFailure = void 0;
44178
44188
  try {
44179
44189
  response = admissionResponse(await read([`repos/${repo}/pulls/${pr}/merge-async/${receipt.uuid}`, "--include", ...ASYNC_HEADERS]));
44180
44190
  } catch {
44181
- return reconcile("the saved operation cannot be read (including expired results)");
44191
+ readFailure = "the saved operation cannot be read (including expired results)";
44192
+ continue;
44182
44193
  }
44183
44194
  if (response.code !== 200) return reconcile(`the saved operation returned HTTP ${response.code}`);
44184
44195
  const { status, details } = response.body;
@@ -44220,6 +44231,7 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
44220
44231
  if (receipt.head !== head) return reconcile("the previous head completed admission; inspect current head and membership before continuing");
44221
44232
  return reconcile(`operation ${receipt.uuid} reported ${status}, but matching-head membership or merged state is unconfirmed`, status === "enqueued");
44222
44233
  }
44234
+ if (readFailure) return reconcile(readFailure);
44223
44235
  return markReenqueued({
44224
44236
  mergeStatus: "queue-admission-pending",
44225
44237
  retryable: false,
@@ -44442,8 +44454,8 @@ async function abandonQueueAdmission(pr, repo, options = {}) {
44442
44454
  }
44443
44455
  const receipt = journal.receipt;
44444
44456
  if (!receipt) return refuse("no queue-admission receipt exists for this PR; nothing to abandon");
44445
- if (!["pending", "enqueued"].includes(receipt.state)) {
44446
- return refuse(`the saved admission is '${receipt.state}', not a stuck non-terminal 'pending'/'enqueued' receipt; nothing to abandon`);
44457
+ if (!["pending", "enqueued"].includes(receipt.state) && !(receipt.state === "dispatching" && !receipt.uuid)) {
44458
+ return refuse(`the saved admission is '${receipt.state}'${receipt.uuid ? ` with operation ${receipt.uuid}` : ""}, not a stuck non-terminal 'pending'/'enqueued' receipt; nothing to abandon`);
44447
44459
  }
44448
44460
  let snapshot;
44449
44461
  try {
@@ -45777,20 +45789,20 @@ function buildPrLifecycle(state, manifest, joins) {
45777
45789
  if (member.pr !== state.number) continue;
45778
45790
  if (!member.admission_event_id) continue;
45779
45791
  const ep = episodes.find((x) => x.episode_id === member.admission_event_id);
45780
- const join54 = joins.find((j) => j.run_id === run.run_id && j.run_attempt === run.run_attempt && j.pr === member.pr && j.admission_event_id === member.admission_event_id);
45781
- if (!join54) continue;
45792
+ const join55 = joins.find((j) => j.run_id === run.run_id && j.run_attempt === run.run_attempt && j.pr === member.pr && j.admission_event_id === member.admission_event_id);
45793
+ if (!join55) continue;
45782
45794
  if (!ep) {
45783
45795
  if (state.status === "complete") {
45784
- join54.status = "unresolved";
45785
- join54.reason = "admission-event-not-in-history";
45796
+ join55.status = "unresolved";
45797
+ join55.reason = "admission-event-not-in-history";
45786
45798
  } else {
45787
- join54.status = "unresolved";
45788
- join54.reason = "history-incomplete";
45799
+ join55.status = "unresolved";
45800
+ join55.reason = "history-incomplete";
45789
45801
  }
45790
45802
  continue;
45791
45803
  }
45792
- join54.status = "joined";
45793
- delete join54.reason;
45804
+ join55.status = "joined";
45805
+ delete join55.reason;
45794
45806
  ep.runs.push({ run_id: run.run_id, run_attempt: run.run_attempt, head_sha: run.head_sha });
45795
45807
  }
45796
45808
  }
@@ -51654,7 +51666,7 @@ function registerBootstrapCommands(program3) {
51654
51666
  const slug = parsedRepo.slug;
51655
51667
  const onlyTarget = o.fromConfig && o.only.trim() === "gate.yml" ? ".github/workflows/gate.yml" : o.only.trim();
51656
51668
  const gh2 = async (args) => execFileP("gh", args, { timeout: 2e4 });
51657
- const readFile10 = (p) => (0, import_node_fs40.existsSync)(p) ? (0, import_node_fs40.readFileSync)(p, "utf8") : null;
51669
+ const readFile11 = (p) => (0, import_node_fs40.existsSync)(p) ? (0, import_node_fs40.readFileSync)(p, "utf8") : null;
51658
51670
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
51659
51671
  const putSeed = async (target, content, ref, sha) => {
51660
51672
  const tmp = (0, import_node_path37.join)((0, import_node_os21.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
@@ -51826,7 +51838,7 @@ function registerBootstrapCommands(program3) {
51826
51838
  registryMeta?.requiredCheckBranches,
51827
51839
  registryMeta?.requiredChecks
51828
51840
  );
51829
- const rendered = resolveSeedContent(gateSeed, gateVars, readFile10);
51841
+ const rendered = resolveSeedContent(gateSeed, gateVars, readFile11);
51830
51842
  if (rendered === null || missingPlaceholders(rendered).length) return failGraceful("bootstrap apply: registry gate template is unreadable or has unfilled placeholders");
51831
51843
  const base = (await readTargetedSeedFiles(repo, scopedPlan, onlyTarget, scopedPlan.baseSha, controlClient)).base?.content ?? null;
51832
51844
  configGateAction = planGateFromConfig(base, rendered);
@@ -51930,7 +51942,7 @@ function registerBootstrapCommands(program3) {
51930
51942
  ...vars,
51931
51943
  ...registryMeta?.requiredChecks?.length ? { GATE_RULESET_CONTEXTS_JSON: rulesetVars.GATE_RULESET_CONTEXTS_JSON } : {},
51932
51944
  ...registryMeta?.requiredCheckBranches?.length ? { GATE_RULESET_BRANCH_REFS_JSON: rulesetVars.GATE_RULESET_BRANCH_REFS_JSON } : {}
51933
- } : vars, readFile10, preservedContent);
51945
+ } : vars, readFile11, preservedContent);
51934
51946
  if (!writeContent.ok) {
51935
51947
  return fail(`bootstrap apply: ${resolved.target}: ${writeContent.reason} \u2014 refusing to overwrite repo-owned content`);
51936
51948
  }
@@ -52076,7 +52088,7 @@ ${onlyManagedBlock ? `Only the marker-bounded Hub-managed block inside repo-owne
52076
52088
  }
52077
52089
  const rulesetSeed = repo.toLowerCase() === "mutmutco/mmi-hub" ? void 0 : manifest.seeds.find((s) => s.target === ".github/rulesets/mmi-product-required-checks.json");
52078
52090
  if (rulesetSeed) {
52079
- const rulesetContent = resolveSeedContent({ ...rulesetSeed, target: rulesetSeed.target.replace("{{REPO_SLUG}}", slug) }, vars, readFile10);
52091
+ const rulesetContent = resolveSeedContent({ ...rulesetSeed, target: rulesetSeed.target.replace("{{REPO_SLUG}}", slug) }, vars, readFile11);
52080
52092
  if (rulesetContent) {
52081
52093
  try {
52082
52094
  const client = controlClient;
@@ -52868,32 +52880,183 @@ function registerDeployCommands(program3) {
52868
52880
  }
52869
52881
 
52870
52882
  // src/intercom-guest.ts
52883
+ var import_node_crypto19 = require("node:crypto");
52884
+ var import_promises5 = require("node:fs/promises");
52885
+ var import_node_os22 = require("node:os");
52886
+ var import_node_path38 = require("node:path");
52887
+ init_cli_shared();
52871
52888
  init_github_client();
52872
- var CANONICAL_COMMAND = "mmi-cli harbour intercom guest";
52889
+ var CANONICAL_COMMAND = "mmi-cli intercom guest";
52873
52890
  var INTERCOM_GUEST_VERBS = ["register", "read", "send", "join", "leave"];
52891
+ var DELIVERIES_LIMIT_MAX = 100;
52892
+ var DELIVERIES_LIMIT_DEFAULT = 20;
52893
+ function deliveriesLimit(limit) {
52894
+ if (limit === void 0 || !Number.isFinite(limit) || limit < 1) return DELIVERIES_LIMIT_DEFAULT;
52895
+ return Math.min(Math.floor(limit), DELIVERIES_LIMIT_MAX);
52896
+ }
52874
52897
  var INTERCOM_GUEST_CONTRACT = {
52875
- source: "mutmutco/Jerv-Hub#2522 (Jerv Gateway guest principal, GitHub-token verification, allowlist)",
52898
+ source: "mutmutco/Jerv-Hub#2727 published guest wire contract (gateway/v1: contract/operations.js, contract/authorization.json, src/http/handler.js)",
52899
+ contractVersion: "gateway/v1",
52900
+ baseUrl: "https://jerv-central.tail4ce549.ts.net",
52876
52901
  baseUrlEnv: "MMI_INTERCOM_GATEWAY_URL",
52877
- operations: null
52902
+ discovery: {
52903
+ operation: "intercom.directory",
52904
+ method: "POST",
52905
+ path: "/v1/intercom/directory",
52906
+ mutation: false,
52907
+ credential: "required",
52908
+ // Idle endpoints are included on purpose: the Coordinator is reachable while it is idle, and the
52909
+ // contract says to match its display name and take the id from the row, never to remember one.
52910
+ body: () => ({ limit: 200, includeIdle: true })
52911
+ },
52912
+ operations: {
52913
+ // #9993 — the guest's first contact. `displayName` is the gh login; the Gateway appends 8 hex of the
52914
+ // endpoint id only when the name collides. HostKind/project are optional and omitted (the Gateway
52915
+ // stores `remote`). With a stored credential this same call rotates and resumes the endpoint.
52916
+ register: {
52917
+ operation: "intercom.register",
52918
+ method: "POST",
52919
+ path: "/v1/intercom/register",
52920
+ mutation: true,
52921
+ credential: "optional",
52922
+ needsLogin: true,
52923
+ body: (_request, context) => ({ displayName: context.login ?? "" })
52924
+ },
52925
+ // #9993 — `read` is the inbox: pending deliveries. Accepting them (intercom.accept) or acking them
52926
+ // (intercom.ack) is a separate, explicit call the contract documents under `cliVerbs.read.then`.
52927
+ read: {
52928
+ operation: "intercom.deliveries",
52929
+ method: "POST",
52930
+ path: "/v1/intercom/deliveries",
52931
+ mutation: false,
52932
+ credential: "required",
52933
+ body: (request) => ({ state: "pending", limit: deliveriesLimit(request.limit) })
52934
+ },
52935
+ // #9993 — the wire field is `text`. A body field named `message` is `unknown_field` at the Gateway.
52936
+ send: {
52937
+ operation: "intercom.send",
52938
+ method: "POST",
52939
+ path: "/v1/intercom/send",
52940
+ mutation: true,
52941
+ credential: "required",
52942
+ body: (request) => ({ to: request.to, text: request.message })
52943
+ },
52944
+ // #9993 — no Gateway operation admits a guest to a suite (Jerv-Hub#2524): a join is an ordinary
52945
+ // `send` to the Coordinator carrying the suite message convention. The suite name travels inside the
52946
+ // text because the convention carries no suite field.
52947
+ join: {
52948
+ operation: "intercom.send",
52949
+ method: "POST",
52950
+ path: "/v1/intercom/send",
52951
+ mutation: true,
52952
+ credential: "required",
52953
+ needsCoordinator: true,
52954
+ body: (request, context) => ({
52955
+ to: context.coordinator,
52956
+ text: `Suite join: ${context.endpointId ?? ""}, ${context.displayName ?? context.login ?? ""} guest, repo ${context.repo}, host ${context.host}, suite ${request.suite ?? ""}`
52957
+ })
52958
+ },
52959
+ // #9993 — leaving is the same shape, and the Coordinator marks the seat left.
52960
+ leave: {
52961
+ operation: "intercom.send",
52962
+ method: "POST",
52963
+ path: "/v1/intercom/send",
52964
+ mutation: true,
52965
+ credential: "required",
52966
+ needsCoordinator: true,
52967
+ body: (_request, context) => ({
52968
+ to: context.coordinator,
52969
+ text: `Suite leave: ${context.endpointId ?? ""}`
52970
+ })
52971
+ }
52972
+ }
52878
52973
  };
52879
52974
  var INTERCOM_GUEST_CONTRACT_MISSING = "intercom-guest-contract-missing";
52880
52975
  var INTERCOM_GUEST_BASE_URL_MISSING = "intercom-guest-base-url-missing";
52881
52976
  var INTERCOM_GUEST_NO_IDENTITY = "intercom-guest-no-identity";
52977
+ var INTERCOM_GUEST_INPUT_MISSING = "intercom-guest-input-missing";
52978
+ var INTERCOM_GUEST_NO_CREDENTIAL = "intercom-guest-no-credential";
52979
+ var INTERCOM_GUEST_COORDINATOR_MISSING = "intercom-guest-coordinator-missing";
52980
+ function intercomGuestStorePath(env = process.env) {
52981
+ const home = env.MMI_INTERCOM_HOME?.trim();
52982
+ return (0, import_node_path38.join)(home && home.length > 0 ? home : (0, import_node_path38.join)((0, import_node_os22.homedir)(), ".mmi", "intercom"), "guest.json");
52983
+ }
52882
52984
  function scrubToken(text, token) {
52883
52985
  if (!token) return text;
52884
52986
  return text.split(token).join("***");
52885
52987
  }
52988
+ function scrubSecrets(text, secrets) {
52989
+ return secrets.reduce((acc, secret) => scrubToken(acc, secret), text);
52990
+ }
52886
52991
  function missingContractRefusal(verb) {
52887
52992
  return [
52888
- `${CANONICAL_COMMAND} ${verb}: not sent \u2014 the Jerv Gateway guest contract has not landed (${INTERCOM_GUEST_CONTRACT.source}).`,
52889
- `Its guest operations (${INTERCOM_GUEST_VERBS.join(", ")}) publish no method, path or field shape yet, so this client refuses`,
52890
- "instead of guessing an endpoint: a guessed call would come back 404/403 and read as a permission or allowlist answer",
52891
- "when the real answer is that the contract is missing.",
52892
- `To switch every verb on: land the guest principal operations in ${INTERCOM_GUEST_CONTRACT.source}, then fill`,
52893
- "`INTERCOM_GUEST_CONTRACT.operations` in cli/src/intercom-guest.ts \u2014 that object is the one place the wire shape lives.",
52993
+ `${CANONICAL_COMMAND} ${verb}: not sent \u2014 this CLI build carries no Jerv Gateway operation for the '${verb}' verb (${INTERCOM_GUEST_CONTRACT.source}).`,
52994
+ "The published guest contract publishes the method, path and field shape for every verb this client knows",
52995
+ `(${INTERCOM_GUEST_VERBS.join(", ")}), so an empty entry means the contract moved and this build did not follow it \u2014`,
52996
+ "this client refuses instead of guessing an endpoint: a guessed call would come back 404/403 and read as a permission",
52997
+ "or allowlist answer when the real answer is that the operation is unknown here.",
52998
+ "To fix it: check the published contract against `INTERCOM_GUEST_CONTRACT.operations` in cli/src/intercom-guest.ts",
52999
+ "\u2014 that object is the one place the wire shape lives.",
52894
53000
  "Nothing was read and nothing was sent: no token was touched and no request was made."
52895
53001
  ].join(" ");
52896
53002
  }
53003
+ function missingInput(request) {
53004
+ if (request.verb === "send") {
53005
+ if (!request.to?.trim()) return "`--to <address>` is required";
53006
+ if (!request.message?.trim()) return "`--message <text>` is required";
53007
+ }
53008
+ if (request.verb === "join" && !request.suite?.trim()) return "`--suite <name>` is required";
53009
+ return void 0;
53010
+ }
53011
+ function coordinatorEndpointId(directoryBody) {
53012
+ let parsed;
53013
+ try {
53014
+ parsed = JSON.parse(directoryBody);
53015
+ } catch {
53016
+ return void 0;
53017
+ }
53018
+ const data = parsed?.data ?? parsed;
53019
+ const items = data?.items;
53020
+ if (!Array.isArray(items)) return void 0;
53021
+ const candidates = items.filter((item) => Boolean(item) && typeof item === "object");
53022
+ const named = candidates.filter((item) => typeof item.displayName === "string" && /^Coordinator(\s|$)/.test(item.displayName) && item.self !== true);
53023
+ const exact = named.find((item) => item.displayName === "Coordinator") ?? named[0];
53024
+ return typeof exact?.endpointId === "string" && exact.endpointId.length > 0 ? exact.endpointId : void 0;
53025
+ }
53026
+ async function readStore(path2) {
53027
+ try {
53028
+ const parsed = JSON.parse(await (0, import_promises5.readFile)(path2, "utf8"));
53029
+ return parsed && typeof parsed === "object" ? parsed : void 0;
53030
+ } catch {
53031
+ return void 0;
53032
+ }
53033
+ }
53034
+ async function writeStore(path2, entry) {
53035
+ await (0, import_promises5.mkdir)((0, import_node_path38.dirname)(path2), { recursive: true, mode: 448 });
53036
+ await (0, import_promises5.writeFile)(path2, `${JSON.stringify(entry, null, 2)}
53037
+ `, { encoding: "utf8", mode: 384 });
53038
+ await (0, import_promises5.chmod)(path2, 384).catch(() => {
53039
+ });
53040
+ }
53041
+ function registrationEntry(gateway, body, previous) {
53042
+ let parsed;
53043
+ try {
53044
+ parsed = JSON.parse(body);
53045
+ } catch {
53046
+ return void 0;
53047
+ }
53048
+ const data = parsed?.data ?? parsed;
53049
+ const credential = typeof data?.credential === "string" ? data.credential : previous?.credential;
53050
+ if (!credential) return void 0;
53051
+ return {
53052
+ gateway,
53053
+ endpointId: typeof data?.endpointId === "string" ? data.endpointId : previous?.endpointId,
53054
+ deviceId: typeof data?.deviceId === "string" ? data.deviceId : previous?.deviceId,
53055
+ credential,
53056
+ displayName: typeof data?.displayName === "string" ? data.displayName : previous?.displayName,
53057
+ epoch: typeof data?.epoch === "number" ? data.epoch : previous?.epoch
53058
+ };
53059
+ }
52897
53060
  async function runIntercomGuest(request, deps = {}) {
52898
53061
  const verb = request.verb;
52899
53062
  const contract = deps.contract ?? INTERCOM_GUEST_CONTRACT;
@@ -52901,61 +53064,156 @@ async function runIntercomGuest(request, deps = {}) {
52901
53064
  if (!operation) {
52902
53065
  return { ok: false, verb, code: INTERCOM_GUEST_CONTRACT_MISSING, message: missingContractRefusal(verb), tokenRead: false };
52903
53066
  }
53067
+ const inputProblem = missingInput(request);
53068
+ if (inputProblem) {
53069
+ return {
53070
+ ok: false,
53071
+ verb,
53072
+ code: INTERCOM_GUEST_INPUT_MISSING,
53073
+ message: `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${inputProblem}. Nothing was read and no request was made.`,
53074
+ tokenRead: false
53075
+ };
53076
+ }
52904
53077
  const env = deps.env ?? process.env;
52905
- const baseUrl = env[contract.baseUrlEnv]?.trim();
53078
+ const baseUrl = (env[contract.baseUrlEnv]?.trim() || contract.baseUrl).replace(/\/+$/, "");
52906
53079
  if (!baseUrl) {
52907
53080
  return {
52908
53081
  ok: false,
52909
53082
  verb,
52910
53083
  code: INTERCOM_GUEST_BASE_URL_MISSING,
52911
- message: `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${contract.baseUrlEnv} is not set, and the Jerv Gateway base URL has no default while the contract is unlanded (${contract.source}). Nothing was read and no request was made.`,
53084
+ message: `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${contract.baseUrlEnv} is empty and the published contract names no base URL either (${contract.source}). Nothing was read and no request was made.`,
52912
53085
  tokenRead: false
52913
53086
  };
52914
53087
  }
53088
+ const storePath = deps.storePath ?? intercomGuestStorePath(env);
53089
+ const store = await readStore(storePath);
52915
53090
  const identity = await (deps.readToken ?? githubKeyringTokenRead)();
52916
53091
  if (identity.state !== "ok") {
52917
53092
  return {
52918
53093
  ok: false,
52919
53094
  verb,
52920
53095
  code: INTERCOM_GUEST_NO_IDENTITY,
52921
- message: scrubToken(
52922
- `${CANONICAL_COMMAND} ${verb}: not sent \u2014 the guest identity is the caller's own \`gh\` login and it could not be read (${identity.detail}). Run \`gh auth login\`, then retry. No request was made.`
53096
+ message: scrubSecrets(
53097
+ `${CANONICAL_COMMAND} ${verb}: not sent \u2014 the guest identity is the caller's own \`gh\` login and it could not be read (${identity.detail}). Run \`gh auth login\`, then retry. No request was made.`,
53098
+ []
52923
53099
  ),
52924
53100
  tokenRead: false
52925
53101
  };
52926
53102
  }
52927
53103
  const token = identity.token;
52928
- const fetchImpl = deps.fetchImpl ?? ((url, init2) => fetch(url, init2));
52929
- const headers = { accept: "application/json", authorization: `Bearer ${token}` };
52930
- const init = { method: operation.method, headers };
52931
- if (operation.body) {
52932
- headers["content-type"] = "application/json";
52933
- init.body = JSON.stringify(operation.body(request));
53104
+ let login;
53105
+ if (operation.needsLogin) {
53106
+ login = await (deps.readLogin ?? githubLogin)();
53107
+ if (!login) {
53108
+ return {
53109
+ ok: false,
53110
+ verb,
53111
+ code: INTERCOM_GUEST_NO_IDENTITY,
53112
+ message: scrubSecrets(
53113
+ `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${operation.operation} needs your GitHub login as \`displayName\` and \`gh api user\` returned none. Run \`gh auth login\`, then retry. No request was made.`,
53114
+ [token]
53115
+ ),
53116
+ tokenRead: true
53117
+ };
53118
+ }
52934
53119
  }
52935
- let response;
52936
- try {
52937
- response = await fetchImpl(new URL(operation.path, baseUrl).toString(), init);
52938
- } catch (error) {
52939
- const detail = error instanceof Error ? error.message : String(error);
52940
- return { ok: false, verb, code: "intercom-guest-transport-failed", message: scrubToken(`${CANONICAL_COMMAND} ${verb}: the Gateway call failed in transport (${detail}).`, token), tokenRead: true };
53120
+ const credential = store?.credential;
53121
+ if (operation.credential === "required" && !credential) {
53122
+ return {
53123
+ ok: false,
53124
+ verb,
53125
+ code: INTERCOM_GUEST_NO_CREDENTIAL,
53126
+ message: scrubSecrets(
53127
+ `${CANONICAL_COMMAND} ${verb}: not sent \u2014 no intercom credential is stored for this machine (${storePath}). ${operation.operation} requires the \`Jerv-Intercom-Credential\` the Gateway returns exactly once, so run \`${CANONICAL_COMMAND} register\` first. Nothing was read and no request was made.`,
53128
+ [token]
53129
+ ),
53130
+ tokenRead: true
53131
+ };
52941
53132
  }
52942
- const text = await response.text().catch(() => "");
52943
- if (!response.ok) {
53133
+ const fetchImpl = deps.fetchImpl ?? ((url, init) => fetch(url, init));
53134
+ const newKey = deps.newIdempotencyKey ?? (() => (0, import_node_crypto19.randomUUID)());
53135
+ const secrets = [token, credential].filter((secret) => Boolean(secret));
53136
+ const callOne = async (op, body2) => {
53137
+ const headers = {
53138
+ accept: "application/json",
53139
+ "content-type": "application/json",
53140
+ "jerv-contract-version": contract.contractVersion,
53141
+ "jerv-guest-github-token": token
53142
+ };
53143
+ if (credential && op.credential !== "never") headers["jerv-intercom-credential"] = credential;
53144
+ if (op.mutation) headers["idempotency-key"] = newKey();
53145
+ let response;
53146
+ try {
53147
+ response = await fetchImpl(new URL(op.path, baseUrl).toString(), { method: op.method, headers, body: JSON.stringify(body2) });
53148
+ } catch (error) {
53149
+ return { transport: error instanceof Error ? error.message : String(error) };
53150
+ }
53151
+ const text = await response.text().catch(() => "");
53152
+ return { status: response.status, ok: response.ok, text };
53153
+ };
53154
+ let context = {
53155
+ login,
53156
+ credential,
53157
+ endpointId: store?.endpointId,
53158
+ displayName: store?.displayName,
53159
+ repo: env.GITHUB_REPOSITORY?.trim() || "unknown",
53160
+ host: (0, import_node_os22.hostname)()
53161
+ };
53162
+ if (operation.needsCoordinator) {
53163
+ const directory = await callOne(contract.discovery, contract.discovery.body?.(request, context) ?? {});
53164
+ if ("transport" in directory) {
53165
+ return { ok: false, verb, code: "intercom-guest-transport-failed", message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: the Gateway call failed in transport (${directory.transport}).`, secrets), tokenRead: true };
53166
+ }
53167
+ if (!directory.ok) {
53168
+ return {
53169
+ ok: false,
53170
+ verb,
53171
+ code: `intercom-guest-http-${directory.status}`,
53172
+ message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: ${contract.discovery.operation} answered HTTP ${directory.status}${directory.text ? ` \u2014 ${directory.text.slice(0, 600)}` : ""}`, secrets),
53173
+ tokenRead: true
53174
+ };
53175
+ }
53176
+ const coordinator = coordinatorEndpointId(directory.text);
53177
+ if (!coordinator) {
53178
+ return {
53179
+ ok: false,
53180
+ verb,
53181
+ code: INTERCOM_GUEST_COORDINATOR_MISSING,
53182
+ message: scrubSecrets(
53183
+ `${CANONICAL_COMMAND} ${verb}: ${contract.discovery.operation} listed no live endpoint named \`Coordinator\`, so there is nobody to send to and nothing was sent. The Coordinator's endpoint id comes from that directory, never from this client.`,
53184
+ secrets
53185
+ ),
53186
+ tokenRead: true
53187
+ };
53188
+ }
53189
+ context = { ...context, coordinator };
53190
+ }
53191
+ const body = operation.body ? operation.body(request, context) : {};
53192
+ const result = await callOne(operation, body);
53193
+ if ("transport" in result) {
53194
+ return { ok: false, verb, code: "intercom-guest-transport-failed", message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: the Gateway call failed in transport (${result.transport}).`, secrets), tokenRead: true };
53195
+ }
53196
+ if (!result.ok) {
52944
53197
  return {
52945
53198
  ok: false,
52946
53199
  verb,
52947
- code: `intercom-guest-http-${response.status}`,
52948
- message: scrubToken(`${CANONICAL_COMMAND} ${verb}: the Gateway answered HTTP ${response.status}${text ? ` \u2014 ${text.slice(0, 600)}` : ""}`, token),
53200
+ code: `intercom-guest-http-${result.status}`,
53201
+ message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: the Gateway answered HTTP ${result.status}${result.text ? ` \u2014 ${result.text.slice(0, 600)}` : ""}`, secrets),
52949
53202
  tokenRead: true
52950
53203
  };
52951
53204
  }
52952
- return { ok: true, verb, status: response.status, body: scrubToken(text, token) };
53205
+ if (operation.operation === "intercom.register") {
53206
+ const entry = registrationEntry(baseUrl, result.text, store);
53207
+ if (entry) await writeStore(storePath, entry).catch(() => {
53208
+ });
53209
+ }
53210
+ return { ok: true, verb, status: result.status, body: scrubSecrets(result.text, secrets) };
52953
53211
  }
52954
53212
  function renderIntercomGuestResult(result) {
52955
53213
  return result.ok ? result.body : result.message;
52956
53214
  }
52957
53215
  function registerIntercomGuestCommands(program3, io = {}) {
52958
- const guest = program3.command("intercom").description("Coordinate with the MM Coordinator through the Jerv Gateway intercom (guest identity; Jerv-Hub#2522)").command("guest").description("Guest coordination verbs: register, read, send, join, leave \u2014 coordination only, never orders");
53216
+ const guest = program3.command("intercom").description("Coordinate with the MM Coordinator through the Jerv Gateway intercom (guest identity; Jerv-Hub#2727)").command("guest").description("Guest coordination verbs: register, read, send, join, leave \u2014 coordination only, never orders");
52959
53217
  const out = io.out ?? ((line) => process.stdout.write(`${line}
52960
53218
  `));
52961
53219
  const err = io.err ?? ((line) => process.stderr.write(`${line}
@@ -52970,19 +53228,21 @@ function registerIntercomGuestCommands(program3, io = {}) {
52970
53228
  return;
52971
53229
  }
52972
53230
  err(renderIntercomGuestResult(result));
52973
- setExitCode(result.code === INTERCOM_GUEST_CONTRACT_MISSING || result.code === INTERCOM_GUEST_BASE_URL_MISSING ? 2 : 1);
53231
+ setExitCode(
53232
+ result.code === INTERCOM_GUEST_CONTRACT_MISSING || result.code === INTERCOM_GUEST_BASE_URL_MISSING || result.code === INTERCOM_GUEST_NO_CREDENTIAL ? 2 : 1
53233
+ );
52974
53234
  };
52975
- guest.command("register").description("Register this guest endpoint with the Gateway using your `gh auth` login").action(async () => {
53235
+ guest.command("register").description("Register this guest endpoint with the Gateway, using your `gh` login as the display name").action(async () => {
52976
53236
  await run({ verb: "register" });
52977
53237
  });
52978
- guest.command("read").description("Read messages waiting for this guest (default 20)").option("--limit <n>", "how many messages to look at", "20").action(async (options) => {
52979
- const limit = Number(options.limit ?? 20);
52980
- await run({ verb: "read", limit: Number.isFinite(limit) && limit > 0 ? Math.min(limit, 200) : 20 });
53238
+ guest.command("read").description(`Read the deliveries waiting for this guest endpoint (default ${DELIVERIES_LIMIT_DEFAULT}, at most ${DELIVERIES_LIMIT_MAX})`).option("--limit <n>", `how many deliveries to look at (1-${DELIVERIES_LIMIT_MAX})`, String(DELIVERIES_LIMIT_DEFAULT)).action(async (options) => {
53239
+ const limit = Number(options.limit ?? DELIVERIES_LIMIT_DEFAULT);
53240
+ await run({ verb: "read", limit: deliveriesLimit(limit) });
52981
53241
  });
52982
- guest.command("send").description("Send a coordination message to a peer endpoint (e.g. the MM Coordinator)").requiredOption("--to <address>", "peer endpoint address").requiredOption("--message <text>", "the coordination message").action(async (options) => {
53242
+ guest.command("send").description("Send a coordination message to the MM Coordinator").requiredOption("--to <address>", "peer endpoint id or display name (the MM Coordinator)").requiredOption("--message <text>", "the coordination message").action(async (options) => {
52983
53243
  await run({ verb: "send", to: options.to, message: options.message });
52984
53244
  });
52985
- guest.command("join").description("Request to join a suite").requiredOption("--suite <name>", "suite name").action(async (options) => {
53245
+ guest.command("join").description("Request to join a suite (a message to the MM Coordinator, who grants it)").requiredOption("--suite <name>", "suite name").action(async (options) => {
52986
53246
  await run({ verb: "join", suite: options.suite });
52987
53247
  });
52988
53248
  guest.command("leave").description("Leave the suite and withdraw this guest endpoint").action(async () => {
@@ -52997,7 +53257,7 @@ init_github_client();
52997
53257
  init_cli_shared();
52998
53258
 
52999
53259
  // src/suite-status.ts
53000
- var import_node_crypto19 = require("node:crypto");
53260
+ var import_node_crypto20 = require("node:crypto");
53001
53261
  var SUITE_REPO = "mutmutco/MM-Work";
53002
53262
  var REPOS = {
53003
53263
  "mmi-scout": "mutmutco/MMI-Scout",
@@ -53025,7 +53285,7 @@ function parseSuiteMapping(body) {
53025
53285
  return void 0;
53026
53286
  }
53027
53287
  }
53028
- var sha2562 = (b) => (0, import_node_crypto19.createHash)("sha256").update(b).digest("hex");
53288
+ var sha2562 = (b) => (0, import_node_crypto20.createHash)("sha256").update(b).digest("hex");
53029
53289
  async function proveBundle(url, tag, fetchUrl) {
53030
53290
  const get = async (u) => {
53031
53291
  try {
@@ -53281,8 +53541,8 @@ async function waitSuiteDev(deps, opts) {
53281
53541
 
53282
53542
  // src/suite-train.ts
53283
53543
  var import_node_fs41 = require("node:fs");
53284
- var import_node_path38 = require("node:path");
53285
- var import_node_crypto20 = require("node:crypto");
53544
+ var import_node_path39 = require("node:path");
53545
+ var import_node_crypto21 = require("node:crypto");
53286
53546
 
53287
53547
  // src/kit-version.ts
53288
53548
  var parse = (v) => /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(typeof v === "string" ? v.trim() : "");
@@ -53383,8 +53643,8 @@ function readSuiteCut(path2) {
53383
53643
  return record2;
53384
53644
  }
53385
53645
  function writeSuiteCut(path2, record2) {
53386
- (0, import_node_fs41.mkdirSync)((0, import_node_path38.dirname)(path2), { recursive: true });
53387
- const temp = `${path2}.${(0, import_node_crypto20.randomBytes)(8).toString("hex")}.tmp`;
53646
+ (0, import_node_fs41.mkdirSync)((0, import_node_path39.dirname)(path2), { recursive: true });
53647
+ const temp = `${path2}.${(0, import_node_crypto21.randomBytes)(8).toString("hex")}.tmp`;
53388
53648
  try {
53389
53649
  (0, import_node_fs41.writeFileSync)(temp, JSON.stringify(record2, null, 2), { flag: "wx" });
53390
53650
  (0, import_node_fs41.renameSync)(temp, path2);
@@ -53443,7 +53703,7 @@ async function retireFailedLeadRcLedger(deps, ownerGo) {
53443
53703
  if (ledger.repo !== SUITE_REPO || ledger.lane !== "rcand" || ledger.phases.promotion.state === "complete" || !states.includes("failed")) return void 0;
53444
53704
  if (!ownerGo) throw new Error(`the lead's failed rcand ledger for ${ledger.tag} blocks every train; retire it with suite abandon --owner-go`);
53445
53705
  if ((await deps.rcHead())?.toLowerCase() === ledger.tagSha.toLowerCase()) throw new Error(`origin rc already points at ${ledger.tag}; it was promoted, so its ledger is not retired`);
53446
- const archive = (0, import_node_path38.join)((0, import_node_path38.dirname)(deps.ledgerPath), `phases.archive-${ledger.tag}.json`);
53706
+ const archive = (0, import_node_path39.join)((0, import_node_path39.dirname)(deps.ledgerPath), `phases.archive-${ledger.tag}.json`);
53447
53707
  if ((0, import_node_fs41.existsSync)(archive)) throw new Error(`ledger archive already exists at ${archive}; inspect before retiring again`);
53448
53708
  await deps.markAbandoned(SUITE_REPO, ledger.tag, ledger.tagSha);
53449
53709
  await fence(() => (0, import_node_fs41.renameSync)(deps.ledgerPath, archive));
@@ -53810,7 +54070,7 @@ Each member's live release must serve <data>/main/module.js at its main pin path
53810
54070
  }
53811
54071
  return record2;
53812
54072
  }
53813
- var hotfixRecordPath = (deps) => (0, import_node_path38.join)((0, import_node_path38.dirname)(deps.recordPath), "hotfix.json");
54073
+ var hotfixRecordPath = (deps) => (0, import_node_path39.join)((0, import_node_path39.dirname)(deps.recordPath), "hotfix.json");
53814
54074
  function readSuiteHotfix(path2) {
53815
54075
  let raw;
53816
54076
  try {
@@ -54125,20 +54385,20 @@ async function runRcDataSwitch(deps, opts) {
54125
54385
 
54126
54386
  // src/suite-train-io.ts
54127
54387
  var import_node_child_process19 = require("node:child_process");
54128
- var import_node_path51 = require("node:path");
54129
- var import_node_fs55 = require("node:fs");
54130
54388
  var import_node_path52 = require("node:path");
54389
+ var import_node_fs55 = require("node:fs");
54390
+ var import_node_path53 = require("node:path");
54131
54391
  init_cli_shared();
54132
54392
 
54133
54393
  // src/command-register-train-operations.ts
54134
- var import_promises9 = require("node:fs/promises");
54394
+ var import_promises10 = require("node:fs/promises");
54135
54395
  init_clean_exit();
54136
54396
  init_cli_shared();
54137
54397
  init_client_version();
54138
54398
  init_house_map();
54139
54399
 
54140
54400
  // src/hotfix-apply.ts
54141
- var import_promises5 = require("node:fs/promises");
54401
+ var import_promises6 = require("node:fs/promises");
54142
54402
 
54143
54403
  // src/release-announce.ts
54144
54404
  var ANNOUNCE_REPO = "mutmutco/MMI-Hub";
@@ -54481,8 +54741,8 @@ async function preflightHotfixBatchPicks(deps, sources, pickTolerated) {
54481
54741
  if (sources.length === 0) return { failures: [], skipped: [] };
54482
54742
  const { mkdtemp: mkdtemp2, rm: rm2 } = await import("node:fs/promises");
54483
54743
  const { tmpdir: tmpdir13 } = await import("node:os");
54484
- const { join: join54 } = await import("node:path");
54485
- const dir = await mkdtemp2(join54(tmpdir13(), "mmi-hotfix-preflight-"));
54744
+ const { join: join55 } = await import("node:path");
54745
+ const dir = await mkdtemp2(join55(tmpdir13(), "mmi-hotfix-preflight-"));
54486
54746
  const wt = { run: (file, args) => deps.run(file, file === "git" ? ["-C", dir, ...args] : args) };
54487
54747
  const failures = [];
54488
54748
  const skipped = [];
@@ -55194,7 +55454,7 @@ async function runHotfixReleaseLocked(deps, versionInput, options, doctor) {
55194
55454
  }
55195
55455
  let lines2;
55196
55456
  try {
55197
- lines2 = summaryFileLines(await (deps.readFile ?? ((p) => (0, import_promises5.readFile)(p, "utf8")))(options.announceSummaryFile));
55457
+ lines2 = summaryFileLines(await (deps.readFile ?? ((p) => (0, import_promises6.readFile)(p, "utf8")))(options.announceSummaryFile));
55198
55458
  } catch (e) {
55199
55459
  throw new Error(`could not read --announce-summary-file ${options.announceSummaryFile}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`);
55200
55460
  }
@@ -55820,8 +56080,8 @@ function checkHotfixCarries(options) {
55820
56080
 
55821
56081
  // src/merge-cleanup.ts
55822
56082
  var import_node_fs42 = require("node:fs");
55823
- var import_node_path39 = require("node:path");
55824
- var import_node_os22 = require("node:os");
56083
+ var import_node_path40 = require("node:path");
56084
+ var import_node_os23 = require("node:os");
55825
56085
  init_cli_shared();
55826
56086
  init_github_client();
55827
56087
 
@@ -56228,8 +56488,8 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
56228
56488
  return rewritten === base ? null : rewritten;
56229
56489
  }
56230
56490
  function writeSquashBodyFile(body) {
56231
- const dir = (0, import_node_fs42.mkdtempSync)((0, import_node_path39.join)((0, import_node_os22.tmpdir)(), "mmi-squash-body-"));
56232
- const path2 = (0, import_node_path39.join)(dir, "body.txt");
56491
+ const dir = (0, import_node_fs42.mkdtempSync)((0, import_node_path40.join)((0, import_node_os23.tmpdir)(), "mmi-squash-body-"));
56492
+ const path2 = (0, import_node_path40.join)(dir, "body.txt");
56233
56493
  (0, import_node_fs42.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
56234
56494
  `, "utf8");
56235
56495
  return { path: path2, cleanup: () => {
@@ -56485,9 +56745,9 @@ async function deleteMergedRemoteBranch(options) {
56485
56745
  init_github_client();
56486
56746
 
56487
56747
  // src/release-custody.ts
56488
- var import_node_crypto21 = require("node:crypto");
56748
+ var import_node_crypto22 = require("node:crypto");
56489
56749
  var import_node_fs43 = require("node:fs");
56490
- var import_node_path40 = require("node:path");
56750
+ var import_node_path41 = require("node:path");
56491
56751
  init_github_client();
56492
56752
 
56493
56753
  // src/release-custody-bootstrap.ts
@@ -56709,7 +56969,7 @@ var ReleaseCustodyError = class extends Error {
56709
56969
  this.name = "ReleaseCustodyError";
56710
56970
  }
56711
56971
  };
56712
- var custodyDigest = (value) => (0, import_node_crypto21.createHash)("sha256").update(value).digest("hex");
56972
+ var custodyDigest = (value) => (0, import_node_crypto22.createHash)("sha256").update(value).digest("hex");
56713
56973
  function parseCustody(raw, repo) {
56714
56974
  const s = JSON.parse(raw);
56715
56975
  if (s.schema !== "mmi-release-custody/v1" || s.repo !== repo || !s.precutId || !Number.isSafeInteger(s.revision) || s.revision < 1 || !s.controller || !Number.isSafeInteger(s.controller.runId) || s.controller.runId <= 0 || !Number.isSafeInteger(s.controller.runAttempt) || s.controller.runAttempt <= 0 || !s.controller.token || !(s.ledger === null || typeof s.ledger === "string") || !s.archives || !s.effects) {
@@ -56810,7 +57070,7 @@ var ReleaseCustodySession = class _ReleaseCustodySession {
56810
57070
  }
56811
57071
  }
56812
57072
  let state = {
56813
- ...found.state ?? { schema: "mmi-release-custody/v1", repo, precutId: (0, import_node_crypto21.randomUUID)(), effects: {}, ...await initialize() },
57073
+ ...found.state ?? { schema: "mmi-release-custody/v1", repo, precutId: (0, import_node_crypto22.randomUUID)(), effects: {}, ...await initialize() },
56814
57074
  revision: (found.state?.revision ?? 0) + 1,
56815
57075
  controller
56816
57076
  };
@@ -56871,7 +57131,7 @@ var ReleaseCustodySession = class _ReleaseCustodySession {
56871
57131
  proof: { kind: "ledger-lifecycle", controller: state.controller }
56872
57132
  };
56873
57133
  }
56874
- return { ...state, ledger: raw, archives, precutId: state.ledger && !raw ? (0, import_node_crypto21.randomUUID)() : state.precutId };
57134
+ return { ...state, ledger: raw, archives, precutId: state.ledger && !raw ? (0, import_node_crypto22.randomUUID)() : state.precutId };
56875
57135
  });
56876
57136
  }
56877
57137
  async preserveLocal(raw) {
@@ -56987,10 +57247,10 @@ function localRaw(path2) {
56987
57247
  function hydrateLocal(path2, raw) {
56988
57248
  const previous = localRaw(path2);
56989
57249
  if (previous === raw) return;
56990
- (0, import_node_fs43.mkdirSync)((0, import_node_path40.dirname)(path2), { recursive: true });
57250
+ (0, import_node_fs43.mkdirSync)((0, import_node_path41.dirname)(path2), { recursive: true });
56991
57251
  if (previous !== null) {
56992
57252
  const ledger = parseReleaseLedger(previous);
56993
- const archive = (0, import_node_path40.join)((0, import_node_path40.dirname)(path2), `phases.local-${ledger.tagSha}-${custodyDigest(previous)}.json`);
57253
+ const archive = (0, import_node_path41.join)((0, import_node_path41.dirname)(path2), `phases.local-${ledger.tagSha}-${custodyDigest(previous)}.json`);
56994
57254
  if (!(0, import_node_fs43.existsSync)(archive)) (0, import_node_fs43.writeFileSync)(archive, previous, { flag: "wx" });
56995
57255
  if (raw === null) (0, import_node_fs43.renameSync)(path2, `${path2}.retired-${custodyDigest(previous)}`);
56996
57256
  }
@@ -57105,7 +57365,7 @@ function withHubReleaseCustody(deps) {
57105
57365
  if (!authority.ok || !authority.train || authority.authenticatedDelegation !== true) {
57106
57366
  throw new ReleaseCustodyError("repository custody requires the server-verified owner-triggered train session");
57107
57367
  }
57108
- const controller = { ...runIdentity, token: (0, import_node_crypto21.randomUUID)(), ...process.env.GITHUB_JOB ? { job: process.env.GITHUB_JOB } : {} };
57368
+ const controller = { ...runIdentity, token: (0, import_node_crypto22.randomUUID)(), ...process.env.GITHUB_JOB ? { job: process.env.GITHUB_JOB } : {} };
57109
57369
  const raw = localRaw(path2);
57110
57370
  const requiredContexts = () => discoverRequiredCheckContexts(
57111
57371
  deps,
@@ -57186,7 +57446,7 @@ function withHubReleaseCustody(deps) {
57186
57446
 
57187
57447
  // src/project-info-sync.ts
57188
57448
  var import_node_fs44 = require("node:fs");
57189
- var import_node_path41 = require("node:path");
57449
+ var import_node_path42 = require("node:path");
57190
57450
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
57191
57451
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
57192
57452
  projectV2 { id }
@@ -57233,7 +57493,7 @@ function sharedName(entries, fallback) {
57233
57493
  }
57234
57494
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
57235
57495
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
57236
- const readmePath = (0, import_node_path41.join)(repoRoot2, "README.md");
57496
+ const readmePath = (0, import_node_path42.join)(repoRoot2, "README.md");
57237
57497
  if (!(0, import_node_fs44.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
57238
57498
  const entries = entriesFor(project2, projects);
57239
57499
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
@@ -57259,8 +57519,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
57259
57519
  const targetBase = `https://github.com/${targetRepo2}`;
57260
57520
  const targetBranch = branchFor(targetRepo2, projects);
57261
57521
  const orgDocs = [
57262
- (0, import_node_fs44.existsSync)((0, import_node_path41.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
57263
- (0, import_node_fs44.existsSync)((0, import_node_path41.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
57522
+ (0, import_node_fs44.existsSync)((0, import_node_path42.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
57523
+ (0, import_node_fs44.existsSync)((0, import_node_path42.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
57264
57524
  ].filter(Boolean);
57265
57525
  if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
57266
57526
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
@@ -57283,7 +57543,7 @@ async function syncProjectInfo(plan, client, apply) {
57283
57543
 
57284
57544
  // src/train-commands.ts
57285
57545
  var import_node_fs45 = require("node:fs");
57286
- var import_node_path42 = require("node:path");
57546
+ var import_node_path43 = require("node:path");
57287
57547
  init_cli_shared();
57288
57548
  init_clean_exit();
57289
57549
  init_client_version();
@@ -57298,7 +57558,7 @@ function resolveReleaseBumpIntent(raw) {
57298
57558
  }
57299
57559
  function readRepoVersion() {
57300
57560
  try {
57301
- return JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path42.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
57561
+ return JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path43.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
57302
57562
  } catch {
57303
57563
  return void 0;
57304
57564
  }
@@ -57408,8 +57668,8 @@ function releaseProgressVerdict(status, subject = "Release") {
57408
57668
  }
57409
57669
 
57410
57670
  // src/suite-pin.ts
57411
- var import_promises6 = require("node:fs/promises");
57412
- var import_node_path43 = require("node:path");
57671
+ var import_promises7 = require("node:fs/promises");
57672
+ var import_node_path44 = require("node:path");
57413
57673
  var SuitePinError = class _SuitePinError extends Error {
57414
57674
  diagnostic;
57415
57675
  constructor(repo, tag, error) {
@@ -57477,8 +57737,8 @@ async function openSuiteCutPinPr(deps, input) {
57477
57737
  if (input.carriedOnly) return { status: "unchanged" };
57478
57738
  throw new Error("pins already match without a merged cut PR \u2014 provenance unverified");
57479
57739
  }
57480
- await (0, import_promises6.mkdir)((0, import_node_path43.join)(deps.root, "tmp"), { recursive: true });
57481
- scratch = await (0, import_promises6.mkdtemp)((0, import_node_path43.join)(deps.root, "tmp", "suite-pin-"));
57740
+ await (0, import_promises7.mkdir)((0, import_node_path44.join)(deps.root, "tmp"), { recursive: true });
57741
+ scratch = await (0, import_promises7.mkdtemp)((0, import_node_path44.join)(deps.root, "tmp", "suite-pin-"));
57482
57742
  const run = (file, args) => deps.run(file, args, scratch);
57483
57743
  await run("git", ["clone", "--quiet", "--branch", prs.length ? branch : "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
57484
57744
  if (prs.length) {
@@ -57490,8 +57750,8 @@ async function openSuiteCutPinPr(deps, input) {
57490
57750
  await run("git", ["switch", "-c", branch]);
57491
57751
  }
57492
57752
  for (const stage of ["rc", "main"]) {
57493
- const path2 = (0, import_node_path43.join)(scratch, `${stage}-pins.json`);
57494
- await (0, import_promises6.writeFile)(path2, JSON.stringify(input.pins.map((p) => ({ module: p.module, url: p[stage] }))));
57753
+ const path2 = (0, import_node_path44.join)(scratch, `${stage}-pins.json`);
57754
+ await (0, import_promises7.writeFile)(path2, JSON.stringify(input.pins.map((p) => ({ module: p.module, url: p[stage] }))));
57495
57755
  await run("node", ["scripts/pin-modules.mjs", "--stage", stage, "--pins", path2]);
57496
57756
  }
57497
57757
  await run("git", ["add", "seed/modules.json"]);
@@ -57521,7 +57781,7 @@ async function openSuiteCutPinPr(deps, input) {
57521
57781
  } catch (e) {
57522
57782
  throw new Error(`suite cut pin PR FAILED: ${e.message}; merge/verify the single ${SUITE_REPO} development pin PR, then rerun the cut (never recut member tags)`);
57523
57783
  } finally {
57524
- if (scratch) await (0, import_promises6.rm)(scratch, { recursive: true, force: true });
57784
+ if (scratch) await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
57525
57785
  }
57526
57786
  }
57527
57787
  async function openSuiteRestorePinPr(deps, input) {
@@ -57543,13 +57803,13 @@ async function openSuiteRestorePinPr(deps, input) {
57543
57803
  }
57544
57804
  });
57545
57805
  if (!todo.length) return void 0;
57546
- await (0, import_promises6.mkdir)((0, import_node_path43.join)(deps.root, "tmp"), { recursive: true });
57547
- scratch = await (0, import_promises6.mkdtemp)((0, import_node_path43.join)(deps.root, "tmp", "suite-pin-"));
57806
+ await (0, import_promises7.mkdir)((0, import_node_path44.join)(deps.root, "tmp"), { recursive: true });
57807
+ scratch = await (0, import_promises7.mkdtemp)((0, import_node_path44.join)(deps.root, "tmp", "suite-pin-"));
57548
57808
  const run = (file, args) => deps.run(file, args, scratch);
57549
57809
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
57550
57810
  await run("git", ["switch", "-c", branch]);
57551
- const path2 = (0, import_node_path43.join)(scratch, "main-pins.json");
57552
- await (0, import_promises6.writeFile)(path2, JSON.stringify(todo.map((p) => ({ module: p.module, url: p.prior }))));
57811
+ const path2 = (0, import_node_path44.join)(scratch, "main-pins.json");
57812
+ await (0, import_promises7.writeFile)(path2, JSON.stringify(todo.map((p) => ({ module: p.module, url: p.prior }))));
57553
57813
  await run("node", ["scripts/pin-modules.mjs", "--stage", "main", "--pins", path2]);
57554
57814
  await run("git", ["add", "seed/modules.json"]);
57555
57815
  await run("git", ["commit", "-m", `Restore main pins of abandoned suite cut ${input.cut.slice(0, 12)} (#7758)`]);
@@ -57574,7 +57834,7 @@ async function openSuiteRestorePinPr(deps, input) {
57574
57834
  } catch (e) {
57575
57835
  throw new Error(`suite restore pin PR FAILED: ${e.message}; rerun suite abandon --owner-go (the record is kept until the restore PR exists)`);
57576
57836
  } finally {
57577
- if (scratch) await (0, import_promises6.rm)(scratch, { recursive: true, force: true });
57837
+ if (scratch) await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
57578
57838
  }
57579
57839
  }
57580
57840
  async function openSuitePinPr(deps, input) {
@@ -57622,8 +57882,8 @@ async function openSuitePinPr(deps, input) {
57622
57882
  if (newer.length) return { status: "superseded", pr: newer[0].url, url: pin };
57623
57883
  const open2 = onBranch.find((p) => p.state === "OPEN");
57624
57884
  if (open2 && tagOf(open2.title ?? "") === tag) return { status: "pending", pr: open2.url, url: pin };
57625
- await (0, import_promises6.mkdir)((0, import_node_path43.join)(deps.root, "tmp"), { recursive: true });
57626
- scratch = await (0, import_promises6.mkdtemp)((0, import_node_path43.join)(deps.root, "tmp", "suite-pin-"));
57885
+ await (0, import_promises7.mkdir)((0, import_node_path44.join)(deps.root, "tmp"), { recursive: true });
57886
+ scratch = await (0, import_promises7.mkdtemp)((0, import_node_path44.join)(deps.root, "tmp", "suite-pin-"));
57627
57887
  const run = (file, args) => deps.run(file, args, scratch);
57628
57888
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
57629
57889
  await run("git", ["switch", "-c", branch]);
@@ -57650,7 +57910,7 @@ async function openSuitePinPr(deps, input) {
57650
57910
  } finally {
57651
57911
  if (scratch) {
57652
57912
  try {
57653
- await (0, import_promises6.rm)(scratch, { recursive: true, force: true });
57913
+ await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
57654
57914
  } catch (e) {
57655
57915
  const cleanupFailure = failure ?? new SuitePinError(repo, tag, e);
57656
57916
  cleanupFailure.diagnostic.cleanupFailed = true;
@@ -57676,7 +57936,7 @@ function prTitleRefusal(title) {
57676
57936
  // src/command-register-collaboration.ts
57677
57937
  var import_node_child_process18 = require("node:child_process");
57678
57938
  var import_node_fs54 = require("node:fs");
57679
- var import_promises8 = require("node:fs/promises");
57939
+ var import_promises9 = require("node:fs/promises");
57680
57940
  init_clean_exit();
57681
57941
  init_cli_shared();
57682
57942
  init_error_codes();
@@ -57699,11 +57959,11 @@ function spawnDetachedSelf(args, deps, opts = {}) {
57699
57959
  }
57700
57960
 
57701
57961
  // src/command-register-collaboration.ts
57702
- var import_node_path50 = require("node:path");
57962
+ var import_node_path51 = require("node:path");
57703
57963
  init_house_map();
57704
57964
 
57705
57965
  // src/issue-body.ts
57706
- var import_node_os23 = require("node:os");
57966
+ var import_node_os24 = require("node:os");
57707
57967
  init_error_codes();
57708
57968
  var TextArgError = class extends Error {
57709
57969
  constructor(message2, code, offendingFlag) {
@@ -57716,7 +57976,7 @@ var TextArgError = class extends Error {
57716
57976
  offendingFlag;
57717
57977
  };
57718
57978
  function emptyStdinMessage(fileFlag) {
57719
- if ((0, import_node_os23.platform)() === "win32") {
57979
+ if ((0, import_node_os24.platform)() === "win32") {
57720
57980
  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)`;
57721
57981
  }
57722
57982
  return `${fileFlag} - read empty stdin (nothing piped \u2014 pass a heredoc/pipe, or ${fileFlag} <path>)`;
@@ -57817,7 +58077,7 @@ init_github_quota();
57817
58077
 
57818
58078
  // src/issue-commands.ts
57819
58079
  var import_node_fs46 = require("node:fs");
57820
- var import_node_crypto22 = require("node:crypto");
58080
+ var import_node_crypto23 = require("node:crypto");
57821
58081
  init_cli_shared();
57822
58082
  init_clean_exit();
57823
58083
  init_error_codes();
@@ -58294,7 +58554,7 @@ function rowIdempotencyKey(batchKey, spec) {
58294
58554
  const identity = `${spec.type}
58295
58555
  ${spec.title.trim()}
58296
58556
  ${spec.body ?? ""}`;
58297
- const hash = (0, import_node_crypto22.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
58557
+ const hash = (0, import_node_crypto23.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
58298
58558
  return `${batchKey}:${hash}`;
58299
58559
  }
58300
58560
  var BATCH_SPEC_KEYS = /* @__PURE__ */ new Set(["type", "title", "body", "priority", "labels", "label", "parent", "repo", "surface"]);
@@ -58754,7 +59014,7 @@ ${lines2}`, {
58754
59014
 
58755
59015
  // src/post-merge-recon.ts
58756
59016
  var import_node_fs47 = require("node:fs");
58757
- var import_node_path44 = require("node:path");
59017
+ var import_node_path45 = require("node:path");
58758
59018
 
58759
59019
  // src/cross-repo-filing-issue.ts
58760
59020
  init_github_client();
@@ -58924,7 +59184,7 @@ function buildPostMergeReconRecovery(input) {
58924
59184
  }
58925
59185
  function writePostMergeReconRecovery(cwd, recovery) {
58926
59186
  const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
58927
- (0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(path2), { recursive: true });
59187
+ (0, import_node_fs47.mkdirSync)((0, import_node_path45.dirname)(path2), { recursive: true });
58928
59188
  (0, import_node_fs47.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
58929
59189
  `, "utf8");
58930
59190
  return path2;
@@ -58964,7 +59224,7 @@ function postMergeReconWarnings(input) {
58964
59224
  }
58965
59225
 
58966
59226
  // src/pr-commands.ts
58967
- var import_promises7 = require("node:fs/promises");
59227
+ var import_promises8 = require("node:fs/promises");
58968
59228
  init_cli_shared();
58969
59229
 
58970
59230
  // src/api-read.ts
@@ -60457,10 +60717,10 @@ function registerPrLifecycleCommands(program3) {
60457
60717
  let body;
60458
60718
  try {
60459
60719
  if (o.title || o.titleFile) {
60460
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises7.readFile, readStdin });
60720
+ title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
60461
60721
  }
60462
60722
  if (o.body || o.bodyFile) {
60463
- body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises7.readFile, readStdin });
60723
+ body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
60464
60724
  }
60465
60725
  } catch (e) {
60466
60726
  return fail(`pr edit: ${e.message}`);
@@ -60491,7 +60751,7 @@ function registerPrLifecycleCommands(program3) {
60491
60751
  }
60492
60752
  let body;
60493
60753
  try {
60494
- body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises7.readFile, readStdin });
60754
+ body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
60495
60755
  } catch (e) {
60496
60756
  return fail(`pr comment: ${e.message}`);
60497
60757
  }
@@ -60776,8 +61036,8 @@ function registerPrLifecycleCommands(program3) {
60776
61036
  // src/review-verdict.ts
60777
61037
  var import_node_child_process15 = require("node:child_process");
60778
61038
  var import_node_fs49 = require("node:fs");
60779
- var import_node_os24 = require("node:os");
60780
- var import_node_path45 = require("node:path");
61039
+ var import_node_os25 = require("node:os");
61040
+ var import_node_path46 = require("node:path");
60781
61041
  init_cli_shared();
60782
61042
  var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
60783
61043
  var REVIEW_VERDICTS = ["PROCEED", "CORRECT", "ESCALATE"];
@@ -60942,8 +61202,8 @@ async function readPrIssueComments(number, repo) {
60942
61202
  return comments;
60943
61203
  }
60944
61204
  async function postPrCommentFromFile(number, repo, body) {
60945
- const dir = (0, import_node_fs49.mkdtempSync)((0, import_node_path45.join)((0, import_node_os24.tmpdir)(), "mmi-review-verdict-"));
60946
- const path2 = (0, import_node_path45.join)(dir, "body.md");
61205
+ const dir = (0, import_node_fs49.mkdtempSync)((0, import_node_path46.join)((0, import_node_os25.tmpdir)(), "mmi-review-verdict-"));
61206
+ const path2 = (0, import_node_path46.join)(dir, "body.md");
60947
61207
  try {
60948
61208
  (0, import_node_fs49.writeFileSync)(path2, body, "utf8");
60949
61209
  const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
@@ -61439,17 +61699,17 @@ function createPreparationDeps(input, io = {}) {
61439
61699
 
61440
61700
  // src/worktree-residue-sweep.ts
61441
61701
  var import_node_fs53 = require("node:fs");
61442
- var import_node_path49 = require("node:path");
61702
+ var import_node_path50 = require("node:path");
61443
61703
 
61444
61704
  // src/worktree-merge-cleanup.ts
61445
61705
  var import_node_fs52 = require("node:fs");
61446
- var import_node_path48 = require("node:path");
61706
+ var import_node_path49 = require("node:path");
61447
61707
  init_cli_shared();
61448
61708
 
61449
61709
  // src/stage-runner.ts
61450
61710
  var import_node_child_process17 = require("node:child_process");
61451
61711
  var import_node_fs51 = require("node:fs");
61452
- var import_node_path47 = require("node:path");
61712
+ var import_node_path48 = require("node:path");
61453
61713
  var import_node_net = require("node:net");
61454
61714
  var import_node_util5 = require("node:util");
61455
61715
 
@@ -61460,7 +61720,7 @@ function normalizeEol2(s) {
61460
61720
 
61461
61721
  // src/env-detection.ts
61462
61722
  var import_node_fs50 = require("node:fs");
61463
- var import_node_path46 = require("node:path");
61723
+ var import_node_path47 = require("node:path");
61464
61724
  var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
61465
61725
  function isEnvBaseName(name) {
61466
61726
  return name.toLowerCase() === ".env";
@@ -61478,13 +61738,13 @@ function findEnvFiles(root) {
61478
61738
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
61479
61739
  if (entry.isDirectory()) {
61480
61740
  if (SKIPPED_DIRS.has(entry.name)) continue;
61481
- walk2((0, import_node_path46.join)(dir, entry.name), relPath);
61741
+ walk2((0, import_node_path47.join)(dir, entry.name), relPath);
61482
61742
  continue;
61483
61743
  }
61484
61744
  if (isEnvBaseName(entry.name)) {
61485
61745
  let isDir = false;
61486
61746
  try {
61487
- isDir = (0, import_node_fs50.lstatSync)((0, import_node_path46.join)(dir, entry.name)).isDirectory();
61747
+ isDir = (0, import_node_fs50.lstatSync)((0, import_node_path47.join)(dir, entry.name)).isDirectory();
61488
61748
  } catch {
61489
61749
  }
61490
61750
  if (!isDir) found.push(relPath);
@@ -61623,10 +61883,10 @@ var DOCKER_TIMEOUT_MS = 15e3;
61623
61883
  function stageBash() {
61624
61884
  if (process.platform !== "win32") return "bash";
61625
61885
  const configured = process.env.SHELL;
61626
- if (configured && (0, import_node_path47.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs51.existsSync)(configured)) return configured;
61886
+ if (configured && (0, import_node_path48.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs51.existsSync)(configured)) return configured;
61627
61887
  const candidates = [
61628
- (0, import_node_path47.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
61629
- ...process.env.LOCALAPPDATA ? [(0, import_node_path47.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
61888
+ (0, import_node_path48.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
61889
+ ...process.env.LOCALAPPDATA ? [(0, import_node_path48.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
61630
61890
  ];
61631
61891
  const bash = candidates.find((path2) => (0, import_node_fs51.existsSync)(path2));
61632
61892
  if (!bash) throw new Error("Local stages require Git Bash on Windows. Install Git for Windows or set SHELL to its absolute bash.exe path.");
@@ -61766,7 +62026,7 @@ function appendForceRecreate(up) {
61766
62026
  return `${up.trimEnd()} --force-recreate`;
61767
62027
  }
61768
62028
  function stageStatePath(cwd = process.cwd()) {
61769
- return (0, import_node_path47.join)(cwd, "tmp", "stage", "state.json");
62029
+ return (0, import_node_path48.join)(cwd, "tmp", "stage", "state.json");
61770
62030
  }
61771
62031
  function normPath(path2) {
61772
62032
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -61983,7 +62243,7 @@ function stageProcessEnv(stagePort, extraEnv) {
61983
62243
  }
61984
62244
  function composeResolvesPort(cwd) {
61985
62245
  if (process.env.PORT) return true;
61986
- const envFile = (0, import_node_path47.join)(cwd, ".env");
62246
+ const envFile = (0, import_node_path48.join)(cwd, ".env");
61987
62247
  return (0, import_node_fs51.existsSync)(envFile) && envFileKeys((0, import_node_fs51.readFileSync)(envFile, "utf8")).has("PORT");
61988
62248
  }
61989
62249
  function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
@@ -61999,13 +62259,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
61999
62259
  function stageComposeFiles(cwd) {
62000
62260
  const files = ["docker-compose.yml"];
62001
62261
  for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
62002
- if ((0, import_node_fs51.existsSync)((0, import_node_path47.join)(cwd, conventional))) files.push(conventional);
62262
+ if ((0, import_node_fs51.existsSync)((0, import_node_path48.join)(cwd, conventional))) files.push(conventional);
62003
62263
  }
62004
62264
  return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
62005
62265
  }
62006
62266
  async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
62007
62267
  const keys = Object.keys(vaultEnvMerge ?? {});
62008
- if (!keys.length || !(0, import_node_fs51.existsSync)((0, import_node_path47.join)(cwd, "docker-compose.yml"))) return {};
62268
+ if (!keys.length || !(0, import_node_fs51.existsSync)((0, import_node_path48.join)(cwd, "docker-compose.yml"))) return {};
62009
62269
  let configJson;
62010
62270
  try {
62011
62271
  const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
@@ -62021,15 +62281,15 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
62021
62281
  }
62022
62282
  const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys, runtimeEnvExcludes(configJson), runtimeEnvSelects(configJson));
62023
62283
  if (!body) return {};
62024
- const overridePath = (0, import_node_path47.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
62025
- (0, import_node_fs51.mkdirSync)((0, import_node_path47.join)(cwd, "tmp", "stage"), { recursive: true });
62284
+ const overridePath = (0, import_node_path48.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
62285
+ (0, import_node_fs51.mkdirSync)((0, import_node_path48.join)(cwd, "tmp", "stage"), { recursive: true });
62026
62286
  (0, import_node_fs51.writeFileSync)(overridePath, body, "utf8");
62027
62287
  return stageComposeFileEnv(stageComposeFiles(cwd));
62028
62288
  }
62029
62289
  async function ensureStageRuntimeEnv(config, opts, cwd) {
62030
62290
  if (!config.ensureEnv) return;
62031
- const target = (0, import_node_path47.join)(cwd, config.ensureEnv.target);
62032
- const example = (0, import_node_path47.join)(cwd, config.ensureEnv.example);
62291
+ const target = (0, import_node_path48.join)(cwd, config.ensureEnv.target);
62292
+ const example = (0, import_node_path48.join)(cwd, config.ensureEnv.example);
62033
62293
  if (!(0, import_node_fs51.existsSync)(target) && (0, import_node_fs51.existsSync)(example)) {
62034
62294
  (0, import_node_fs51.copyFileSync)(example, target);
62035
62295
  } else if ((0, import_node_fs51.existsSync)(target) && (0, import_node_fs51.existsSync)(example)) {
@@ -62383,7 +62643,7 @@ function normPath2(p) {
62383
62643
  return p.replace(/\\/g, "/").replace(/\/+$/, "");
62384
62644
  }
62385
62645
  function unlinkNodeModulesJunction(wtPath) {
62386
- const nm = (0, import_node_path48.join)(wtPath, "node_modules");
62646
+ const nm = (0, import_node_path49.join)(wtPath, "node_modules");
62387
62647
  try {
62388
62648
  if ((0, import_node_fs52.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs52.rmdirSync)(nm);
62389
62649
  return { ok: true };
@@ -62520,7 +62780,7 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
62520
62780
  }
62521
62781
  async function listNestedIgnoredNodeModules(wtPath, execGit) {
62522
62782
  const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
62523
- return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path48.join)(wtPath, line.slice(0, -1)));
62783
+ return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path49.join)(wtPath, line.slice(0, -1)));
62524
62784
  }
62525
62785
  function safeRemoveTree(path2) {
62526
62786
  const stat4 = (0, import_node_fs52.lstatSync)(path2);
@@ -62533,7 +62793,7 @@ function safeRemoveTree(path2) {
62533
62793
  return;
62534
62794
  }
62535
62795
  if (stat4.isDirectory()) {
62536
- for (const entry of (0, import_node_fs52.readdirSync)(path2)) safeRemoveTree((0, import_node_path48.join)(path2, entry));
62796
+ for (const entry of (0, import_node_fs52.readdirSync)(path2)) safeRemoveTree((0, import_node_path49.join)(path2, entry));
62537
62797
  (0, import_node_fs52.rmdirSync)(path2);
62538
62798
  return;
62539
62799
  }
@@ -62541,7 +62801,7 @@ function safeRemoveTree(path2) {
62541
62801
  }
62542
62802
  async function removeWorktreeNodeModules(wtPath) {
62543
62803
  try {
62544
- safeRemoveTree((0, import_node_path48.join)(wtPath, "node_modules"));
62804
+ safeRemoveTree((0, import_node_path49.join)(wtPath, "node_modules"));
62545
62805
  return { ok: true };
62546
62806
  } catch (e) {
62547
62807
  if (e.code === "ENOENT") return { ok: true };
@@ -62586,7 +62846,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
62586
62846
  return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
62587
62847
  }
62588
62848
  for (const entry of entries) {
62589
- const child2 = (0, import_node_path48.join)(dir, entry.name);
62849
+ const child2 = (0, import_node_path49.join)(dir, entry.name);
62590
62850
  if (entry.isSymbolicLink()) {
62591
62851
  let target = "";
62592
62852
  try {
@@ -62913,7 +63173,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
62913
63173
  const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
62914
63174
  if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
62915
63175
  unlinkedReparsePoints.push(...preHelperGuard.unlinked);
62916
- if (pathExists((0, import_node_path48.join)(wtPath, "node_modules"))) {
63176
+ if (pathExists((0, import_node_path49.join)(wtPath, "node_modules"))) {
62917
63177
  const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
62918
63178
  if (!nmRemoved.ok) {
62919
63179
  report.worktree = {
@@ -63049,35 +63309,35 @@ function renderPrMergeCleanupLines(cleanup) {
63049
63309
  // src/worktree-residue-sweep.ts
63050
63310
  var RESIDUE_LEDGER_FILE = "mmi-worktree-residue.json";
63051
63311
  function canonicalWorktreeRoot(primary) {
63052
- return (0, import_node_path49.join)((0, import_node_path49.dirname)(primary), "mmi-worktrees", (0, import_node_path49.basename)(primary));
63312
+ return (0, import_node_path50.join)((0, import_node_path50.dirname)(primary), "mmi-worktrees", (0, import_node_path50.basename)(primary));
63053
63313
  }
63054
63314
  function lastSegment(p) {
63055
- return (0, import_node_path49.basename)(p.split(/[\\/]+/).filter(Boolean).pop() ?? p);
63315
+ return (0, import_node_path50.basename)(p.split(/[\\/]+/).filter(Boolean).pop() ?? p);
63056
63316
  }
63057
63317
  function readProvenance(folder, gitCommonDir, exists) {
63058
63318
  const found = {
63059
63319
  path: folder,
63060
63320
  gitdirPresent: false,
63061
- registrationId: (0, import_node_path49.basename)(folder),
63321
+ registrationId: (0, import_node_path50.basename)(folder),
63062
63322
  registrationPresent: false
63063
63323
  };
63064
63324
  try {
63065
- const pointer = /^\s*gitdir:\s*(.+?)\s*$/m.exec((0, import_node_fs53.readFileSync)((0, import_node_path49.join)(folder, ".git"), "utf8"));
63325
+ const pointer = /^\s*gitdir:\s*(.+?)\s*$/m.exec((0, import_node_fs53.readFileSync)((0, import_node_path50.join)(folder, ".git"), "utf8"));
63066
63326
  if (pointer) {
63067
63327
  const target = pointer[1];
63068
- found.gitdir = (0, import_node_path49.isAbsolute)(target) ? target : (0, import_node_path49.join)(folder, target);
63328
+ found.gitdir = (0, import_node_path50.isAbsolute)(target) ? target : (0, import_node_path50.join)(folder, target);
63069
63329
  found.gitdirPresent = exists(found.gitdir);
63070
63330
  found.registrationId = lastSegment(found.gitdir);
63071
63331
  }
63072
63332
  } catch {
63073
63333
  }
63074
63334
  try {
63075
- found.registrationPresent = exists((0, import_node_path49.join)(gitCommonDir, "worktrees", found.registrationId));
63335
+ found.registrationPresent = exists((0, import_node_path50.join)(gitCommonDir, "worktrees", found.registrationId));
63076
63336
  } catch {
63077
63337
  }
63078
63338
  if (found.gitdir && found.gitdirPresent) {
63079
63339
  try {
63080
- const head = (0, import_node_fs53.readFileSync)((0, import_node_path49.join)(found.gitdir, "HEAD"), "utf8").trim();
63340
+ const head = (0, import_node_fs53.readFileSync)((0, import_node_path50.join)(found.gitdir, "HEAD"), "utf8").trim();
63081
63341
  const branch = /^ref:\s*(.+?)\s*$/.exec(head);
63082
63342
  if (branch) found.head = branch[1].startsWith("refs/heads/") ? branch[1].slice("refs/heads/".length) : `ref ${branch[1]}`;
63083
63343
  else if (/^[0-9a-f]{7,64}$/i.test(head)) found.head = `detached ${head.slice(0, 12)}`;
@@ -63096,7 +63356,7 @@ function norm2(p) {
63096
63356
  return process.platform === "win32" ? s.toLowerCase() : s;
63097
63357
  }
63098
63358
  function residueLedgerPath(gitCommonDir) {
63099
- return (0, import_node_path49.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
63359
+ return (0, import_node_path50.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
63100
63360
  }
63101
63361
  function readPaths(file, deps) {
63102
63362
  try {
@@ -63109,7 +63369,7 @@ function readPaths(file, deps) {
63109
63369
  function writePaths(file, paths, deps) {
63110
63370
  try {
63111
63371
  const write = deps.writeLedger ?? ((f, t) => {
63112
- (0, import_node_fs53.mkdirSync)((0, import_node_path49.dirname)(f), { recursive: true });
63372
+ (0, import_node_fs53.mkdirSync)((0, import_node_path50.dirname)(f), { recursive: true });
63113
63373
  (0, import_node_fs53.writeFileSync)(f, t, "utf8");
63114
63374
  });
63115
63375
  write(file, `${JSON.stringify([...new Set(paths)], null, 1)}
@@ -63169,7 +63429,7 @@ async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
63169
63429
  } catch {
63170
63430
  }
63171
63431
  for (const name of children) {
63172
- const child2 = (0, import_node_path49.join)(root, name);
63432
+ const child2 = (0, import_node_path50.join)(root, name);
63173
63433
  const key = norm2(child2);
63174
63434
  if (live.has(key) || key === primary || keptKeys.has(key) || !isDir(child2)) continue;
63175
63435
  let entries;
@@ -63221,10 +63481,10 @@ function argvWantsJson2() {
63221
63481
  return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
63222
63482
  }
63223
63483
  function hubRoot() {
63224
- const fromPkg = (0, import_node_path50.join)(__dirname, "..", "..");
63484
+ const fromPkg = (0, import_node_path51.join)(__dirname, "..", "..");
63225
63485
  const marker = "skills/bootstrap/seeds/manifest.json";
63226
- if ((0, import_node_fs54.existsSync)((0, import_node_path50.join)(fromPkg, marker))) return fromPkg;
63227
- if ((0, import_node_fs54.existsSync)((0, import_node_path50.join)(process.cwd(), marker))) return process.cwd();
63486
+ if ((0, import_node_fs54.existsSync)((0, import_node_path51.join)(fromPkg, marker))) return fromPkg;
63487
+ if ((0, import_node_fs54.existsSync)((0, import_node_path51.join)(process.cwd(), marker))) return process.cwd();
63228
63488
  return null;
63229
63489
  }
63230
63490
  function ciAuditDeps() {
@@ -63236,7 +63496,7 @@ function ciAuditDeps() {
63236
63496
  getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
63237
63497
  readSeedFile: (path2) => {
63238
63498
  if (!root) return null;
63239
- const fullPath = (0, import_node_path50.join)(root, path2);
63499
+ const fullPath = (0, import_node_path51.join)(root, path2);
63240
63500
  return (0, import_node_fs54.existsSync)(fullPath) ? (0, import_node_fs54.readFileSync)(fullPath, "utf8") : null;
63241
63501
  }
63242
63502
  };
@@ -63461,7 +63721,7 @@ function registerCollaborationCommands(program3) {
63461
63721
  try {
63462
63722
  title = await resolveIssueTitle(
63463
63723
  { title: opts.title, titleFile: opts.titleFile },
63464
- { readFile: import_promises8.readFile, readStdin }
63724
+ { readFile: import_promises9.readFile, readStdin }
63465
63725
  );
63466
63726
  } catch (e) {
63467
63727
  return fail(
@@ -63515,8 +63775,8 @@ function registerCollaborationCommands(program3) {
63515
63775
  let surfaceInferred;
63516
63776
  try {
63517
63777
  issueType = resolveCreateType(o.type, "issue create", o.label);
63518
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
63519
- body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
63778
+ title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
63779
+ body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
63520
63780
  if (o.idempotencyKey) body = appendIdempotencyMarker(body, o.idempotencyKey);
63521
63781
  priority = resolveCreatePriority(o.priority, "issue create");
63522
63782
  extraLabels = [...o.label ?? []];
@@ -63831,7 +64091,7 @@ function registerCollaborationCommands(program3) {
63831
64091
  }
63832
64092
  let body;
63833
64093
  try {
63834
- body = o.edit !== void 0 ? "" : await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
64094
+ body = o.edit !== void 0 ? "" : await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
63835
64095
  } catch (e) {
63836
64096
  return fail(`issue comment: ${e.message}`);
63837
64097
  }
@@ -63910,8 +64170,8 @@ ${list}`);
63910
64170
  let title;
63911
64171
  const sourceRepo = o.repo ?? await resolveRepo(void 0);
63912
64172
  try {
63913
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
63914
- body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
64173
+ title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
64174
+ body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
63915
64175
  priority = resolveCreatePriority(o.priority, "report");
63916
64176
  if (!ISSUE_TYPES.includes(o.type)) {
63917
64177
  throw new Error(`unknown issue type "${o.type}" \u2014 expected one of: ${ISSUE_TYPES.join(", ")}`);
@@ -63965,8 +64225,8 @@ ${list}`);
63965
64225
  let args;
63966
64226
  try {
63967
64227
  skill = assertSkillName(o.skill);
63968
- rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
63969
- const rawTitle = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
64228
+ rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
64229
+ const rawTitle = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
63970
64230
  title = buildSkillLessonTitle(skill, rawTitle);
63971
64231
  priority = resolveCreatePriority(o.priority, "skill-lesson");
63972
64232
  body = buildSkillLessonBody(rawBody, sourceRepo, pluginSha);
@@ -64027,8 +64287,8 @@ ${list}`);
64027
64287
  let body;
64028
64288
  let title;
64029
64289
  try {
64030
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
64031
- body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
64290
+ title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
64291
+ body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
64032
64292
  } catch (e) {
64033
64293
  return fail(`pr create: ${e.message}`, e instanceof TextArgError ? { code: e.code, offending_flag: e.offendingFlag } : void 0);
64034
64294
  }
@@ -64122,11 +64382,11 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64122
64382
  }
64123
64383
  });
64124
64384
  async function listCiWorkflowPaths(cwd = process.cwd()) {
64125
- const wfDir = (0, import_node_path50.join)(cwd, ".github", "workflows");
64385
+ const wfDir = (0, import_node_path51.join)(cwd, ".github", "workflows");
64126
64386
  if (!(0, import_node_fs54.existsSync)(wfDir)) return [];
64127
64387
  return (0, import_node_fs54.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
64128
64388
  try {
64129
- return workflowReportsPrChecks((0, import_node_fs54.readFileSync)((0, import_node_path50.join)(wfDir, name), "utf8"));
64389
+ return workflowReportsPrChecks((0, import_node_fs54.readFileSync)((0, import_node_path51.join)(wfDir, name), "utf8"));
64130
64390
  } catch {
64131
64391
  return true;
64132
64392
  }
@@ -64381,7 +64641,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64381
64641
  }
64382
64642
  class PrHeadBehindBaseError extends Error {
64383
64643
  }
64384
- pr.command("land <numbers...>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only. Several PR numbers land together (#8322): all are enqueued, waited on together, a queue-ejected PR is updated and re-enqueued once, a queue merge is followed by worktree/branch cleanup and board Done, and one table (or --json) reports each outcome").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").option("--enqueue-only", "return once queue membership is confirmed; without a merge queue, land normally").option("--abandon-admission", "one stuck-receipt recovery, one PR per call: journal the saved non-terminal (pending/enqueued) queue-admission receipt terminal ONLY after positively observing the PR OPEN at the receipt head and absent from the queue; any unprovable observation refuses and changes nothing (#9951). The next pr land then submits a new intent with no new head").option("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "silence the leftover-scratch warning (scratch never blocks, #8785) and acknowledge a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal").option("--without-review <reason>", "compatibility option; shared merge helpers do not require a review verdict").option("--timeout <minutes>", `merge-queue wait per PR (default ${PR_LAND_QUEUE_TIMEOUT_MS / 6e4} minutes, one window per ${PR_LAND_QUEUE_BATCH_SIZE} PRs \u2014 per-repo ruleset check_response_timeout_minutes is 15 default with 30/45/60 overrides in .github/rulesets/mmi-development-merge-queue.json; agents never edit the ruleset to shorten a queue wait)`).option("--preserve-worktree", "after a queue merge keep the local worktree and branch (skips the post-merge cleanup)").option("--expect-head <sha>", "pin the PR head to this full 40-hex SHA (#8456): checked before landing, after checks and by GitHub at enqueue (--match-head-commit); never updates a BEHIND head and never retries an ejection \u2014 it stops with pinnedHead.refused instead. One PR only").action(async (numbers, opts) => {
64644
+ pr.command("land <numbers...>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only. Several PR numbers land together (#8322): all are enqueued, waited on together, a queue-ejected PR is updated and re-enqueued once, a queue merge is followed by worktree/branch cleanup and board Done, and one table (or --json) reports each outcome").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").option("--enqueue-only", "return once queue membership is confirmed; without a merge queue, land normally").option("--abandon-admission", "one stuck-receipt recovery, one PR per call: journal the saved non-terminal (pending/enqueued, or a dispatching send that saved no operation UUID after its sender died \u2014 #9995) queue-admission receipt terminal ONLY after positively observing the PR OPEN at the receipt head and absent from the queue; any unprovable observation refuses and changes nothing (#9951). The next pr land then submits a new intent with no new head").option("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "silence the leftover-scratch warning (scratch never blocks, #8785) and acknowledge a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal").option("--without-review <reason>", "compatibility option; shared merge helpers do not require a review verdict").option("--timeout <minutes>", `merge-queue wait per PR (default ${PR_LAND_QUEUE_TIMEOUT_MS / 6e4} minutes, one window per ${PR_LAND_QUEUE_BATCH_SIZE} PRs \u2014 per-repo ruleset check_response_timeout_minutes is 15 default with 30/45/60 overrides in .github/rulesets/mmi-development-merge-queue.json; agents never edit the ruleset to shorten a queue wait)`).option("--preserve-worktree", "after a queue merge keep the local worktree and branch (skips the post-merge cleanup)").option("--expect-head <sha>", "pin the PR head to this full 40-hex SHA (#8456): checked before landing, after checks and by GitHub at enqueue (--match-head-commit); never updates a BEHIND head and never retries an ejection \u2014 it stops with pinnedHead.refused instead. One PR only").action(async (numbers, opts) => {
64385
64645
  const timeoutMinutes = opts.timeout === void 0 ? void 0 : Number(opts.timeout);
64386
64646
  if (timeoutMinutes !== void 0 && !(timeoutMinutes > 0)) return fail("pr land: --timeout must be a positive number of minutes");
64387
64647
  if (opts.abandonAdmission) {
@@ -64722,7 +64982,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64722
64982
  const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
64723
64983
  let foreignCheckout;
64724
64984
  if (foreignCwd) {
64725
- const sibling = (0, import_node_path50.join)((0, import_node_path50.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
64985
+ const sibling = (0, import_node_path51.join)((0, import_node_path51.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
64726
64986
  const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
64727
64987
  if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
64728
64988
  const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
@@ -64956,7 +65216,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64956
65216
  let residueSweep;
64957
65217
  if (!(foreignCwd && !foreignCheckout)) {
64958
65218
  try {
64959
- gitCommonDir = (0, import_node_path50.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
65219
+ gitCommonDir = (0, import_node_path51.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
64960
65220
  residueSweep = await sweepWorktreeResidue(gitCommonDir, beforeWorktrees.map((w) => w.path));
64961
65221
  } catch {
64962
65222
  }
@@ -65176,7 +65436,7 @@ function trainGitArgs(args) {
65176
65436
  async function announceSummaryLineCountRefusal(path2) {
65177
65437
  let content;
65178
65438
  try {
65179
- content = await (0, import_promises9.readFile)(path2, "utf8");
65439
+ content = await (0, import_promises10.readFile)(path2, "utf8");
65180
65440
  } catch (e) {
65181
65441
  return `release: could not read --announce-summary-file ${path2}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`;
65182
65442
  }
@@ -65188,7 +65448,7 @@ async function announceSummaryLineCountRefusal(path2) {
65188
65448
  async function announceSummaryRefusal(path2, isHub = false, isWorkSuite = false) {
65189
65449
  let lines2;
65190
65450
  try {
65191
- lines2 = summaryFileLines(await (0, import_promises9.readFile)(path2, "utf8"));
65451
+ lines2 = summaryFileLines(await (0, import_promises10.readFile)(path2, "utf8"));
65192
65452
  } catch (e) {
65193
65453
  return `release: could not read --announce-summary-file ${path2}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`;
65194
65454
  }
@@ -65326,8 +65586,8 @@ function trainApplyDeps() {
65326
65586
  }
65327
65587
  return body.status;
65328
65588
  },
65329
- readFile: (path2) => (0, import_promises9.readFile)(path2, "utf8"),
65330
- removeFile: (path2) => (0, import_promises9.unlink)(path2),
65589
+ readFile: (path2) => (0, import_promises10.readFile)(path2, "utf8"),
65590
+ removeFile: (path2) => (0, import_promises10.unlink)(path2),
65331
65591
  // #6521/#6523: the project's own release channel AND releaseLanguage, read from registry META in ONE
65332
65592
  // checked read. Same shape as fetchEdgeDomains below: a FAILED read refuses by name so the announce
65333
65593
  // note reports a failed read, never a project that configured nothing.
@@ -66255,7 +66515,7 @@ function rcRunCauseFromLog(log) {
66255
66515
  function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
66256
66516
  return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
66257
66517
  }
66258
- var suiteStateDir = (root) => (0, import_node_path52.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
66518
+ var suiteStateDir = (root) => (0, import_node_path53.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
66259
66519
  async function runSuiteMemberRcand(repo, previousRc, rcWasAbsent) {
66260
66520
  const deps = trainApplyDeps();
66261
66521
  deps.suiteCut = suiteCutContext(repo, SUITE_REPO);
@@ -66302,16 +66562,16 @@ async function rcandInCheckout(repo, deps, previousRc, rcWasAbsent) {
66302
66562
  }
66303
66563
  }
66304
66564
  function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
66305
- const recordPath = (0, import_node_path52.join)(suiteStateDir(root), "cut.json");
66306
- const base = (0, import_node_path52.join)(suiteStateDir(root), "checkouts");
66565
+ const recordPath = (0, import_node_path53.join)(suiteStateDir(root), "cut.json");
66566
+ const base = (0, import_node_path53.join)(suiteStateDir(root), "checkouts");
66307
66567
  const checkout = async (repo) => {
66308
66568
  if (repo === SUITE_REPO) return root;
66309
- const target = (0, import_node_path52.join)(base, repo.split("/")[1]);
66569
+ const target = (0, import_node_path53.join)(base, repo.split("/")[1]);
66310
66570
  if (!(0, import_node_fs55.existsSync)(target)) {
66311
66571
  (0, import_node_fs55.mkdirSync)(base, { recursive: true });
66312
66572
  await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
66313
66573
  }
66314
- if (!(0, import_node_fs55.existsSync)((0, import_node_path52.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
66574
+ if (!(0, import_node_fs55.existsSync)((0, import_node_path53.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
66315
66575
  const origin = await exec("git", ["remote", "get-url", "origin"], target);
66316
66576
  if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
66317
66577
  throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
@@ -66375,7 +66635,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
66375
66635
  if (repo === SUITE_REPO) return inTrain(repo, (deps) => rcandInCheckout(repo, deps, previousRc, rcWasAbsent));
66376
66636
  const target = await checkout(repo);
66377
66637
  return new Promise((resolveResult, reject2) => {
66378
- const child2 = (0, import_node_child_process19.fork)((0, import_node_path51.resolve)(process.argv[1]), ["devops", "suite", "member-rcand-internal", repo, previousRc ?? "", ...rcWasAbsent ? ["--rc-was-absent"] : []], {
66638
+ const child2 = (0, import_node_child_process19.fork)((0, import_node_path52.resolve)(process.argv[1]), ["devops", "suite", "member-rcand-internal", repo, previousRc ?? "", ...rcWasAbsent ? ["--rc-was-absent"] : []], {
66379
66639
  cwd: target,
66380
66640
  stdio: ["ignore", "inherit", "inherit", "ipc"],
66381
66641
  execArgv: []
@@ -66619,7 +66879,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
66619
66879
  if (parseSuiteMapping(body)) return;
66620
66880
  const dir = suiteStateDir(root);
66621
66881
  (0, import_node_fs55.mkdirSync)(dir, { recursive: true });
66622
- const file = (0, import_node_path52.join)(dir, `notes-${leadTag}.md`);
66882
+ const file = (0, import_node_path53.join)(dir, `notes-${leadTag}.md`);
66623
66883
  (0, import_node_fs55.writeFileSync)(file, `${body}
66624
66884
 
66625
66885
  ${suiteMappingBlock(leadTag, mapping)}`);
@@ -66996,8 +67256,8 @@ function registerJevCommands(program3) {
66996
67256
  // src/packages-adopt-export.ts
66997
67257
  var import_node_child_process20 = require("node:child_process");
66998
67258
  var import_node_fs57 = require("node:fs");
66999
- var import_node_os25 = require("node:os");
67000
- var import_node_path53 = require("node:path");
67259
+ var import_node_os26 = require("node:os");
67260
+ var import_node_path54 = require("node:path");
67001
67261
  var import_node_util6 = require("node:util");
67002
67262
  init_cli_shared();
67003
67263
 
@@ -67617,25 +67877,25 @@ function expectedFromRun(run, opts) {
67617
67877
  }
67618
67878
  async function adoptExport(opts, deps) {
67619
67879
  if (!/^sha256:[0-9a-f]{64}$/.test(opts.digest)) throw new Error("--digest must be sha256:<64 hex>, from the export run summary");
67620
- const packagePath = (0, import_node_path53.join)(opts.dir, "package.json");
67621
- const lockPath = (0, import_node_path53.join)(opts.dir, "package-lock.json");
67880
+ const packagePath = (0, import_node_path54.join)(opts.dir, "package.json");
67881
+ const lockPath = (0, import_node_path54.join)(opts.dir, "package-lock.json");
67622
67882
  const packageText = (0, import_node_fs57.readFileSync)(packagePath, "utf8");
67623
67883
  const lockText = (0, import_node_fs57.readFileSync)(lockPath, "utf8");
67624
- const work = (0, import_node_fs57.mkdtempSync)((0, import_node_path53.join)((0, import_node_os25.tmpdir)(), "mmi-adopt-export-"));
67884
+ const work = (0, import_node_fs57.mkdtempSync)((0, import_node_path54.join)((0, import_node_os26.tmpdir)(), "mmi-adopt-export-"));
67625
67885
  try {
67626
67886
  const run = JSON.parse((await deps.ghApi(`repos/${EXPORT_REPO}/actions/runs/${opts.run}`)).toString("utf8"));
67627
- (0, import_node_fs57.writeFileSync)((0, import_node_path53.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
67628
- (0, import_node_fs57.writeFileSync)((0, import_node_path53.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
67629
- (0, import_node_fs57.writeFileSync)((0, import_node_path53.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
67630
- const script = (0, import_node_path53.join)(work, "package_export.py");
67887
+ (0, import_node_fs57.writeFileSync)((0, import_node_path54.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
67888
+ (0, import_node_fs57.writeFileSync)((0, import_node_path54.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
67889
+ (0, import_node_fs57.writeFileSync)((0, import_node_path54.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
67890
+ const script = (0, import_node_path54.join)(work, "package_export.py");
67631
67891
  (0, import_node_fs57.writeFileSync)(script, package_export_default);
67632
67892
  await deps.python(script, ["verify", work, opts.ds, opts.screens]);
67633
- const verified = (0, import_node_path53.join)(work, "verified");
67634
- const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs57.readFileSync)((0, import_node_path53.join)(verified, `${short3}.metadata.json`), "utf8"))]));
67893
+ const verified = (0, import_node_path54.join)(work, "verified");
67894
+ const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs57.readFileSync)((0, import_node_path54.join)(verified, `${short3}.metadata.json`), "utf8"))]));
67635
67895
  const plan = planAdoption(packageText, lockText, metadata);
67636
67896
  for (const { name } of plan.result.adopted) {
67637
67897
  const short3 = PACKAGES.find((p) => p.name === name).short;
67638
- await deps.npm(["cache", "add", (0, import_node_path53.join)(verified, `${short3}.tgz`)], opts.dir);
67898
+ await deps.npm(["cache", "add", (0, import_node_path54.join)(verified, `${short3}.tgz`)], opts.dir);
67639
67899
  }
67640
67900
  (0, import_node_fs57.writeFileSync)(packagePath, plan.packageText);
67641
67901
  (0, import_node_fs57.writeFileSync)(lockPath, plan.lockText);
@@ -67825,8 +68085,8 @@ async function collectWaveStatus(deps) {
67825
68085
  init_github_client();
67826
68086
  init_cli_shared();
67827
68087
  var import_node_fs59 = require("node:fs");
67828
- var import_node_os26 = require("node:os");
67829
- var import_node_path54 = require("node:path");
68088
+ var import_node_os27 = require("node:os");
68089
+ var import_node_path55 = require("node:path");
67830
68090
  var GC_GH_TIMEOUT_MS3 = 2e4;
67831
68091
  var defaultStatusDeps = {
67832
68092
  repo: resolveRepo,
@@ -68045,10 +68305,10 @@ async function collectOnboardStatus(opts = {}) {
68045
68305
  else if (top) nextCommand = `mmi-cli oracle board claim ${top.number} # ${top.title}`;
68046
68306
  else nextCommand = "mmi-cli oracle board read \u2014 no claimable items found";
68047
68307
  }
68048
- const home = (0, import_node_os26.homedir)();
68308
+ const home = (0, import_node_os27.homedir)();
68049
68309
  const plugin = onboardPluginGate({
68050
- readKnown: () => readFileSyncSafe((0, import_node_path54.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs59.readFileSync),
68051
- readSettings: () => readFileSyncSafe((0, import_node_path54.join)(home, ".claude", "settings.json"), import_node_fs59.readFileSync)
68310
+ readKnown: () => readFileSyncSafe((0, import_node_path55.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs59.readFileSync),
68311
+ readSettings: () => readFileSyncSafe((0, import_node_path55.join)(home, ".claude", "settings.json"), import_node_fs59.readFileSync)
68052
68312
  });
68053
68313
  return {
68054
68314
  guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
@@ -70685,7 +70945,7 @@ function registerConnectionsOauth(program3, deps) {
70685
70945
  }
70686
70946
 
70687
70947
  // src/schedules-commands.ts
70688
- var import_promises10 = require("node:fs/promises");
70948
+ var import_promises11 = require("node:fs/promises");
70689
70949
  init_clean_exit();
70690
70950
  init_github_client();
70691
70951
  init_cli_shared();
@@ -70865,9 +71125,9 @@ function registerSchedulesCommands(program3) {
70865
71125
  await failGraceful("org schedules --doc: refusing to regenerate the doc from an incomplete read (see warnings above).");
70866
71126
  return;
70867
71127
  }
70868
- const docText = await (0, import_promises10.readFile)(o.doc, "utf8");
71128
+ const docText = await (0, import_promises11.readFile)(o.doc, "utf8");
70869
71129
  const spliced = spliceDoc(docText, renderDocSection(entries, now.toISOString()));
70870
- await (0, import_promises10.writeFile)(o.doc, spliced, "utf8");
71130
+ await (0, import_promises11.writeFile)(o.doc, spliced, "utf8");
70871
71131
  reportParked(parkedLines);
70872
71132
  reportDrift(drift);
70873
71133
  console.log(`org schedules: wrote ${entries.length} entries into ${o.doc}`);
@@ -71180,7 +71440,7 @@ function registerSessionReport(program3) {
71180
71440
 
71181
71441
  // src/stage-commands.ts
71182
71442
  var import_node_fs60 = require("node:fs");
71183
- var import_node_path55 = require("node:path");
71443
+ var import_node_path56 = require("node:path");
71184
71444
  init_cli_shared();
71185
71445
  init_clean_exit();
71186
71446
 
@@ -71428,8 +71688,8 @@ function registerStageCommands(program3) {
71428
71688
  const repo = Array.isArray(project2?.repos) && typeof project2.repos[0] === "string" ? project2.repos[0] : slug;
71429
71689
  const resolution = decideStage({
71430
71690
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
71431
- hasCompose: (0, import_node_fs60.existsSync)((0, import_node_path55.join)(process.cwd(), "docker-compose.yml")),
71432
- hasEnvExample: (0, import_node_fs60.existsSync)((0, import_node_path55.join)(process.cwd(), ".env.example")),
71691
+ hasCompose: (0, import_node_fs60.existsSync)((0, import_node_path56.join)(process.cwd(), "docker-compose.yml")),
71692
+ hasEnvExample: (0, import_node_fs60.existsSync)((0, import_node_path56.join)(process.cwd(), ".env.example")),
71433
71693
  repo
71434
71694
  });
71435
71695
  if (resolution.source === "derived" && resolution.derived) {
@@ -71721,21 +71981,21 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
71721
71981
  }
71722
71982
 
71723
71983
  // src/tenant-artifact.ts
71724
- var import_node_crypto23 = require("node:crypto");
71984
+ var import_node_crypto24 = require("node:crypto");
71725
71985
  var import_node_fs61 = require("node:fs");
71726
- var import_promises11 = require("node:fs/promises");
71727
- var import_node_path56 = require("node:path");
71986
+ var import_promises12 = require("node:fs/promises");
71987
+ var import_node_path57 = require("node:path");
71728
71988
  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}$/;
71729
71989
  var MAX_BYTES2 = 5 * 1024 * 1024 * 1024;
71730
71990
  async function sha256File(path2) {
71731
- const hash = (0, import_node_crypto23.createHash)("sha256");
71991
+ const hash = (0, import_node_crypto24.createHash)("sha256");
71732
71992
  for await (const chunk of (0, import_node_fs61.createReadStream)(path2)) hash.update(chunk);
71733
71993
  return hash.digest("hex");
71734
71994
  }
71735
71995
  async function putTenantArtifact(repo, stage, inputPath, deps) {
71736
71996
  if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
71737
- const path2 = (0, import_node_path56.resolve)(inputPath);
71738
- const info = await (0, import_promises11.stat)(path2);
71997
+ const path2 = (0, import_node_path57.resolve)(inputPath);
71998
+ const info = await (0, import_promises12.stat)(path2);
71739
71999
  if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
71740
72000
  if (!Number.isSafeInteger(info.size) || info.size < 1 || info.size > MAX_BYTES2) throw new Error(`tenant artifact put: file must be 1..${MAX_BYTES2} bytes`);
71741
72001
  const sha2564 = await sha256File(path2);
@@ -72214,12 +72474,12 @@ async function resolveWhoami(deps) {
72214
72474
  }
72215
72475
 
72216
72476
  // src/command-register-developer.ts
72217
- var import_node_path63 = require("node:path");
72477
+ var import_node_path64 = require("node:path");
72218
72478
 
72219
72479
  // src/doc-refs-command-source.ts
72220
72480
  var import_node_child_process21 = require("node:child_process");
72221
72481
  var import_node_fs62 = require("node:fs");
72222
- var import_node_path57 = require("node:path");
72482
+ var import_node_path58 = require("node:path");
72223
72483
  var IN_PROCESS_SOURCE = "in-process";
72224
72484
  var BUNDLE_MANIFEST_TIMEOUT_MS = 12e4;
72225
72485
  var BUNDLE_MANIFEST_MAX_BUFFER = 64 * 1024 * 1024;
@@ -72241,7 +72501,7 @@ function inventoryFromManifest(manifest, source) {
72241
72501
  function readBundleManifest(bundle, exec3 = import_node_child_process21.execFileSync) {
72242
72502
  try {
72243
72503
  const text = exec3(process.execPath, [bundle, "commands", "--all", "--json"], {
72244
- cwd: (0, import_node_path57.dirname)(bundle),
72504
+ cwd: (0, import_node_path58.dirname)(bundle),
72245
72505
  encoding: "utf8",
72246
72506
  windowsHide: true,
72247
72507
  timeout: BUNDLE_MANIFEST_TIMEOUT_MS,
@@ -72257,16 +72517,16 @@ function readBundleManifest(bundle, exec3 = import_node_child_process21.execFile
72257
72517
  function isRunningBundle(bundle, argv1 = process.argv[1], platform2 = process.platform) {
72258
72518
  if (!argv1) return false;
72259
72519
  const norm3 = (path2) => {
72260
- const absolute = (0, import_node_path57.resolve)(path2);
72520
+ const absolute = (0, import_node_path58.resolve)(path2);
72261
72521
  return platform2 === "win32" ? absolute.toLowerCase() : absolute;
72262
72522
  };
72263
72523
  const running = norm3(argv1);
72264
- if (!["main.cjs", "index.cjs"].includes((0, import_node_path57.basename)(running))) return false;
72265
- return (0, import_node_path57.dirname)(running) === (0, import_node_path57.dirname)(norm3(bundle));
72524
+ if (!["main.cjs", "index.cjs"].includes((0, import_node_path58.basename)(running))) return false;
72525
+ return (0, import_node_path58.dirname)(running) === (0, import_node_path58.dirname)(norm3(bundle));
72266
72526
  }
72267
72527
  function nameUnknownCommandSources(findings, source, root) {
72268
- const checkoutBundle = (0, import_node_path57.resolve)(root, "cli", "dist", "main.cjs");
72269
- const recovery = source !== IN_PROCESS_SOURCE && (0, import_node_path57.resolve)(source) === checkoutBundle ? "; rebuild with `npm --prefix cli run build` and retry, or pass `--commands-from <bundle>`" : "";
72528
+ const checkoutBundle = (0, import_node_path58.resolve)(root, "cli", "dist", "main.cjs");
72529
+ const recovery = source !== IN_PROCESS_SOURCE && (0, import_node_path58.resolve)(source) === checkoutBundle ? "; rebuild with `npm --prefix cli run build` and retry, or pass `--commands-from <bundle>`" : "";
72270
72530
  for (const finding of findings) {
72271
72531
  if (finding.kind !== "unknown-command") continue;
72272
72532
  finding.commandSource = source;
@@ -72278,7 +72538,7 @@ function resolveCommandInventory(deps) {
72278
72538
  const read = deps.read ?? ((bundle) => readBundleManifest(bundle));
72279
72539
  const warnings = [];
72280
72540
  if (deps.from) {
72281
- const bundle = (0, import_node_path57.isAbsolute)(deps.from) ? deps.from : (0, import_node_path57.resolve)(deps.root, deps.from);
72541
+ const bundle = (0, import_node_path58.isAbsolute)(deps.from) ? deps.from : (0, import_node_path58.resolve)(deps.root, deps.from);
72282
72542
  if (!exists(bundle)) {
72283
72543
  throw new Error(`docs refs --commands-from: ${bundle} does not exist \u2014 name the CLI bundle to read commands from (usually cli/dist/main.cjs)`);
72284
72544
  }
@@ -72288,7 +72548,7 @@ function resolveCommandInventory(deps) {
72288
72548
  }
72289
72549
  return { inventory: inventory2, warnings };
72290
72550
  }
72291
- const treeBundle = (0, import_node_path57.join)(deps.root, "cli", "dist", "main.cjs");
72551
+ const treeBundle = (0, import_node_path58.join)(deps.root, "cli", "dist", "main.cjs");
72292
72552
  if (!exists(treeBundle)) {
72293
72553
  return { inventory: deps.inProcess(), warnings };
72294
72554
  }
@@ -72408,26 +72668,26 @@ async function executeWaveLand(plan, deps) {
72408
72668
 
72409
72669
  // src/dist-drift.ts
72410
72670
  var import_node_child_process22 = require("node:child_process");
72411
- var import_node_crypto25 = require("node:crypto");
72671
+ var import_node_crypto26 = require("node:crypto");
72412
72672
  var import_node_fs64 = require("node:fs");
72413
- var import_node_os27 = require("node:os");
72414
- var import_node_path59 = require("node:path");
72673
+ var import_node_os28 = require("node:os");
72674
+ var import_node_path60 = require("node:path");
72415
72675
 
72416
72676
  // ../scripts/distribution-digest.mjs
72417
- var import_node_crypto24 = require("node:crypto");
72677
+ var import_node_crypto25 = require("node:crypto");
72418
72678
  var import_node_fs63 = require("node:fs");
72419
- var import_node_path58 = require("node:path");
72679
+ var import_node_path59 = require("node:path");
72420
72680
  var slash = (value) => value.replaceAll("\\", "/");
72421
72681
  function repoPath(root, declaredPath, label) {
72422
- const absoluteRoot = (0, import_node_path58.resolve)(root);
72423
- const target = (0, import_node_path58.resolve)(root, declaredPath);
72424
- if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path58.sep}`)) {
72682
+ const absoluteRoot = (0, import_node_path59.resolve)(root);
72683
+ const target = (0, import_node_path59.resolve)(root, declaredPath);
72684
+ if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path59.sep}`)) {
72425
72685
  throw new Error(`${label} ${declaredPath} escapes the repository root`);
72426
72686
  }
72427
72687
  return target;
72428
72688
  }
72429
72689
  function digestFiles(files) {
72430
- const hash = (0, import_node_crypto24.createHash)("sha256");
72690
+ const hash = (0, import_node_crypto25.createHash)("sha256");
72431
72691
  for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
72432
72692
  const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs63.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs63.readFileSync)(file.absolute);
72433
72693
  hash.update(file.relative, "utf8");
@@ -72458,7 +72718,7 @@ var DIST_ARTIFACTS = [
72458
72718
  ];
72459
72719
  var BOM_DIST_TREE_ID = "mmi-cli-dist";
72460
72720
  var ABSENT = "absent";
72461
- var sha2563 = (bytes) => `sha256:${(0, import_node_crypto25.createHash)("sha256").update(bytes).digest("hex")}`;
72721
+ var sha2563 = (bytes) => `sha256:${(0, import_node_crypto26.createHash)("sha256").update(bytes).digest("hex")}`;
72462
72722
  function artifactDrift(path2, committedBytes, rebuiltBytes) {
72463
72723
  const committed = committedBytes ? sha2563(committedBytes) : ABSENT;
72464
72724
  const rebuiltExpected = rebuiltBytes ? sha2563(rebuiltBytes) : ABSENT;
@@ -72536,7 +72796,7 @@ function walkFiles(root) {
72536
72796
  const files = [];
72537
72797
  const walk2 = (directory) => {
72538
72798
  for (const entry of (0, import_node_fs64.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
72539
- const child2 = (0, import_node_path59.join)(directory, entry.name);
72799
+ const child2 = (0, import_node_path60.join)(directory, entry.name);
72540
72800
  if (entry.isDirectory()) walk2(child2);
72541
72801
  else files.push(child2);
72542
72802
  }
@@ -72546,10 +72806,10 @@ function walkFiles(root) {
72546
72806
  }
72547
72807
  function bomPathFor(root) {
72548
72808
  try {
72549
- const registry2 = JSON.parse((0, import_node_fs64.readFileSync)((0, import_node_path59.join)(root, "surfaces.json"), "utf8"));
72550
- return (0, import_node_path59.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
72809
+ const registry2 = JSON.parse((0, import_node_fs64.readFileSync)((0, import_node_path60.join)(root, "surfaces.json"), "utf8"));
72810
+ return (0, import_node_path60.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
72551
72811
  } catch {
72552
- return (0, import_node_path59.join)(root, "distribution-bom.json");
72812
+ return (0, import_node_path60.join)(root, "distribution-bom.json");
72553
72813
  }
72554
72814
  }
72555
72815
  function rebuildTo(packageRoot, outDir) {
@@ -72562,28 +72822,28 @@ function rebuildTo(packageRoot, outDir) {
72562
72822
  });
72563
72823
  }
72564
72824
  function runDistStatus(root) {
72565
- const stage = (0, import_node_fs64.mkdtempSync)((0, import_node_path59.join)((0, import_node_os27.tmpdir)(), "mmi-dist-drift-"));
72825
+ const stage = (0, import_node_fs64.mkdtempSync)((0, import_node_path60.join)((0, import_node_os28.tmpdir)(), "mmi-dist-drift-"));
72566
72826
  let overlayCount = 0;
72567
72827
  try {
72568
- const cliOut = (0, import_node_path59.join)(stage, "cli-dist");
72569
- const hubOut = (0, import_node_path59.join)(stage, "hub-dist");
72570
- rebuildTo((0, import_node_path59.join)(root, "cli"), cliOut);
72571
- rebuildTo((0, import_node_path59.join)(root, "updater"), hubOut);
72828
+ const cliOut = (0, import_node_path60.join)(stage, "cli-dist");
72829
+ const hubOut = (0, import_node_path60.join)(stage, "hub-dist");
72830
+ rebuildTo((0, import_node_path60.join)(root, "cli"), cliOut);
72831
+ rebuildTo((0, import_node_path60.join)(root, "updater"), hubOut);
72572
72832
  const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
72573
72833
  const rebuilt = (path2) => {
72574
72834
  const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
72575
- return spec ? readOrNull((0, import_node_path59.join)(outDirFor(spec.packageDir), spec.output)) : null;
72835
+ return spec ? readOrNull((0, import_node_path60.join)(outDirFor(spec.packageDir), spec.output)) : null;
72576
72836
  };
72577
- const committed = (path2) => readOrNull((0, import_node_path59.join)(root, path2));
72578
- const tree = (path2) => readOrNull((0, import_node_path59.join)(root, path2));
72579
- const distRoot = (0, import_node_path59.join)(root, "cli", "dist");
72580
- const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path59.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
72837
+ const committed = (path2) => readOrNull((0, import_node_path60.join)(root, path2));
72838
+ const tree = (path2) => readOrNull((0, import_node_path60.join)(root, path2));
72839
+ const distRoot = (0, import_node_path60.join)(root, "cli", "dist");
72840
+ const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path60.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
72581
72841
  const bom = JSON.parse((0, import_node_fs64.readFileSync)(bomPathFor(root), "utf8"));
72582
72842
  const digest = (entries) => {
72583
- const overlay = (0, import_node_path59.join)(stage, `overlay-${overlayCount++}`);
72843
+ const overlay = (0, import_node_path60.join)(stage, `overlay-${overlayCount++}`);
72584
72844
  for (const entry of entries) {
72585
- const target = (0, import_node_path59.join)(overlay, entry.path);
72586
- (0, import_node_fs64.mkdirSync)((0, import_node_path59.dirname)(target), { recursive: true });
72845
+ const target = (0, import_node_path60.join)(overlay, entry.path);
72846
+ (0, import_node_fs64.mkdirSync)((0, import_node_path60.dirname)(target), { recursive: true });
72587
72847
  (0, import_node_fs64.writeFileSync)(target, entry.bytes);
72588
72848
  }
72589
72849
  return digestPackedFiles(overlay, entries.map((entry) => entry.path));
@@ -72595,7 +72855,7 @@ function runDistStatus(root) {
72595
72855
  }
72596
72856
 
72597
72857
  // src/doc-refs-live.ts
72598
- var import_node_path60 = require("node:path");
72858
+ var import_node_path61 = require("node:path");
72599
72859
  var concrete = (value) => !!value && !/[<>{}$]/.test(value);
72600
72860
  var liveOption = (tokens2, flag) => {
72601
72861
  const index = tokens2.indexOf(flag);
@@ -72668,7 +72928,7 @@ async function runLiveDocRefs(root, deps, live) {
72668
72928
  const offline = runDocRefs(root, { ...deps, runbooksOnly: true });
72669
72929
  const read = deps.readFile ?? readFileOrNull;
72670
72930
  const docs = Object.fromEntries((deps.listDocs ?? defaultListDocs)(root).flatMap((doc) => {
72671
- const body = read((0, import_node_path60.join)(root, doc));
72931
+ const body = read((0, import_node_path61.join)(root, doc));
72672
72932
  return body !== null && isRunbook(doc, body) && !deps.isIgnored?.([doc]).has(doc) ? [[doc, body]] : [];
72673
72933
  }));
72674
72934
  const remote = await checkRunbookLive(docs, live);
@@ -72717,13 +72977,13 @@ init_cli_shared();
72717
72977
  // src/edge-tunnel.ts
72718
72978
  var HOSTNAME_RE = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/;
72719
72979
  var UPSTREAM_RE = /^https?:\/\/[^/\s]+(?::\d+)?(?:\/.*)?$/;
72720
- function tunnelNameFromHostname(hostname4) {
72721
- return hostname4.replace(/\./g, "-").slice(0, 63);
72980
+ function tunnelNameFromHostname(hostname5) {
72981
+ return hostname5.replace(/\./g, "-").slice(0, 63);
72722
72982
  }
72723
- function planInfraTunnel(hostname4, upstream) {
72724
- const host = hostname4.trim().toLowerCase();
72983
+ function planInfraTunnel(hostname5, upstream) {
72984
+ const host = hostname5.trim().toLowerCase();
72725
72985
  const origin = upstream.trim();
72726
- if (!HOSTNAME_RE.test(host)) throw new Error(`invalid hostname ${JSON.stringify(hostname4)}`);
72986
+ if (!HOSTNAME_RE.test(host)) throw new Error(`invalid hostname ${JSON.stringify(hostname5)}`);
72727
72987
  if (!UPSTREAM_RE.test(origin)) throw new Error(`invalid upstream ${JSON.stringify(upstream)} \u2014 expected http(s)://host:port`);
72728
72988
  const tunnelName = tunnelNameFromHostname(host);
72729
72989
  const configYaml = [
@@ -72878,8 +73138,8 @@ async function diagnoseHub(deps) {
72878
73138
  }
72879
73139
 
72880
73140
  // src/schedules-lift-command.ts
72881
- var import_promises12 = require("node:fs/promises");
72882
- var import_node_path61 = require("node:path");
73141
+ var import_promises13 = require("node:fs/promises");
73142
+ var import_node_path62 = require("node:path");
72883
73143
  init_clean_exit();
72884
73144
  init_cli_shared();
72885
73145
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
@@ -72901,14 +73161,14 @@ var RegistryUnreachableError = class extends Error {
72901
73161
  async function readWorkflowFiles(dir) {
72902
73162
  let names;
72903
73163
  try {
72904
- names = await (0, import_promises12.readdir)(dir);
73164
+ names = await (0, import_promises13.readdir)(dir);
72905
73165
  } catch {
72906
73166
  return [];
72907
73167
  }
72908
73168
  const files = [];
72909
73169
  for (const name of names.sort()) {
72910
73170
  if (!/\.ya?ml$/.test(name)) continue;
72911
- files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises12.readFile)((0, import_node_path61.join)(dir, name), "utf8") });
73171
+ files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises13.readFile)((0, import_node_path62.join)(dir, name), "utf8") });
72912
73172
  }
72913
73173
  return files;
72914
73174
  }
@@ -72992,7 +73252,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
72992
73252
  // src/spawn-policy-core.ts
72993
73253
  var import_node_child_process24 = require("node:child_process");
72994
73254
  var import_node_fs65 = require("node:fs");
72995
- var import_node_path62 = require("node:path");
73255
+ var import_node_path63 = require("node:path");
72996
73256
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
72997
73257
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
72998
73258
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -73078,7 +73338,7 @@ function runSpawnPolicy(root) {
73078
73338
  for (const file of files) {
73079
73339
  let raw;
73080
73340
  try {
73081
- raw = (0, import_node_fs65.readFileSync)((0, import_node_path62.join)(root, file), "utf8");
73341
+ raw = (0, import_node_fs65.readFileSync)((0, import_node_path63.join)(root, file), "utf8");
73082
73342
  } catch {
73083
73343
  continue;
73084
73344
  }
@@ -73098,7 +73358,7 @@ function runSpawnPolicy(root) {
73098
73358
  function registerDeveloperCommands(program3) {
73099
73359
  const rules = program3.command("rules").description("org-managed .gitignore delivery");
73100
73360
  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) => {
73101
- const path2 = (0, import_node_path63.join)(process.cwd(), ".gitignore");
73361
+ const path2 = (0, import_node_path64.join)(process.cwd(), ".gitignore");
73102
73362
  const current = (0, import_node_fs66.existsSync)(path2) ? (0, import_node_fs66.readFileSync)(path2, "utf8") : null;
73103
73363
  const plan = planManagedGitignore(current);
73104
73364
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
@@ -73428,12 +73688,12 @@ ${r.stderr ?? ""}`).catch(() => "");
73428
73688
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
73429
73689
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
73430
73690
  function envHealLockPath(home) {
73431
- return (0, import_node_path64.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
73691
+ return (0, import_node_path65.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
73432
73692
  }
73433
73693
  async function withEnvHealLock(what, run) {
73434
73694
  try {
73435
73695
  return await withFileLock(
73436
- envHealLockPath((0, import_node_os28.homedir)()),
73696
+ envHealLockPath((0, import_node_os29.homedir)()),
73437
73697
  { staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
73438
73698
  run
73439
73699
  );
@@ -73531,7 +73791,7 @@ function mmiDoctorDeps(opts = {}) {
73531
73791
  const configRoot = surfaceConfigRoot(surface);
73532
73792
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
73533
73793
  const plan = buildPluginCachePlan(
73534
- (0, import_node_os28.homedir)(),
73794
+ (0, import_node_os29.homedir)(),
73535
73795
  running,
73536
73796
  pluginCacheFsDeps(configRoot, () => 0),
73537
73797
  { configRoot, includeStaging: surface !== "codex" }
@@ -73559,7 +73819,7 @@ function mmiDoctorDeps(opts = {}) {
73559
73819
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
73560
73820
  const installed = installedActivePluginVersion(surface);
73561
73821
  const plan = buildPluginCachePlan(
73562
- (0, import_node_os28.homedir)(),
73822
+ (0, import_node_os29.homedir)(),
73563
73823
  running,
73564
73824
  pluginCacheFsDeps(configRoot, () => 0),
73565
73825
  { configRoot, includeStaging: surface !== "codex", installedVersion: installed }
@@ -73601,7 +73861,7 @@ function mmiDoctorDeps(opts = {}) {
73601
73861
  // has no generated routing index would
73602
73862
  // get a permanent — demanding an artifact it never asked for.
73603
73863
  docsIndexState: (root) => {
73604
- if (!(0, import_node_fs67.existsSync)((0, import_node_path64.join)(root, DOCS_INDEX_PATH))) return void 0;
73864
+ if (!(0, import_node_fs67.existsSync)((0, import_node_path65.join)(root, DOCS_INDEX_PATH))) return void 0;
73605
73865
  const real = createDocsIndexDeps(root);
73606
73866
  let docs;
73607
73867
  const listDocs = () => docs ??= real.listDocs();
@@ -73610,7 +73870,7 @@ function mmiDoctorDeps(opts = {}) {
73610
73870
  },
73611
73871
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
73612
73872
  healDocsIndex: (root) => {
73613
- if (!(0, import_node_fs67.existsSync)((0, import_node_path64.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
73873
+ if (!(0, import_node_fs67.existsSync)((0, import_node_path65.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
73614
73874
  const real = createDocsIndexDeps(root);
73615
73875
  let docs;
73616
73876
  const listDocs = () => docs ??= real.listDocs();
@@ -74841,16 +75101,16 @@ function ciAuditDeps2() {
74841
75101
  // gate re-seed step is skipped gracefully rather than failing mid-run.
74842
75102
  readSeedFile: (path2) => {
74843
75103
  if (!root) return null;
74844
- const fullPath = (0, import_node_path64.join)(root, path2);
75104
+ const fullPath = (0, import_node_path65.join)(root, path2);
74845
75105
  return (0, import_node_fs67.existsSync)(fullPath) ? (0, import_node_fs67.readFileSync)(fullPath, "utf8") : null;
74846
75106
  }
74847
75107
  };
74848
75108
  }
74849
75109
  function hubRoot2() {
74850
- const fromPkg = (0, import_node_path64.join)(__dirname, "..", "..");
75110
+ const fromPkg = (0, import_node_path65.join)(__dirname, "..", "..");
74851
75111
  const marker = "skills/bootstrap/seeds/manifest.json";
74852
- if ((0, import_node_fs67.existsSync)((0, import_node_path64.join)(fromPkg, marker))) return fromPkg;
74853
- if ((0, import_node_fs67.existsSync)((0, import_node_path64.join)(process.cwd(), marker))) return process.cwd();
75112
+ if ((0, import_node_fs67.existsSync)((0, import_node_path65.join)(fromPkg, marker))) return fromPkg;
75113
+ if ((0, import_node_fs67.existsSync)((0, import_node_path65.join)(process.cwd(), marker))) return process.cwd();
74854
75114
  return null;
74855
75115
  }
74856
75116
  registerQueryCommands(program2);
@@ -75064,7 +75324,7 @@ function directoryBytes(path2) {
75064
75324
  return 0;
75065
75325
  }
75066
75326
  for (const entry of entries) {
75067
- const child2 = (0, import_node_path64.join)(path2, entry.name);
75327
+ const child2 = (0, import_node_path65.join)(path2, entry.name);
75068
75328
  if (entry.isDirectory()) total += directoryBytes(child2);
75069
75329
  else {
75070
75330
  try {
@@ -75094,7 +75354,7 @@ function pluginCacheFsDeps(configRoot, dirBytes) {
75094
75354
  dirBytes,
75095
75355
  listStagingDirs: (root) => (0, import_node_fs67.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
75096
75356
  try {
75097
- return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path64.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs67.statSync)(p).mtimeMs) };
75357
+ return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path65.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs67.statSync)(p).mtimeMs) };
75098
75358
  } catch {
75099
75359
  return { name: d.name, mtimeMs: Date.now() };
75100
75360
  }
@@ -75108,7 +75368,7 @@ function stagingApplyFsGuard(configRoot) {
75108
75368
  return {
75109
75369
  referencedPaths: () => readInstalledPluginRefs(configRoot),
75110
75370
  mtimeMs: (name) => {
75111
- const p = (0, import_node_path64.join)(stagingRoot, name);
75371
+ const p = (0, import_node_path65.join)(stagingRoot, name);
75112
75372
  if (!(0, import_node_fs67.existsSync)(p)) return null;
75113
75373
  try {
75114
75374
  return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs67.statSync)(q).mtimeMs);
@@ -75131,7 +75391,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
75131
75391
  return;
75132
75392
  }
75133
75393
  const plan = buildPluginCachePlan(
75134
- (0, import_node_os28.homedir)(),
75394
+ (0, import_node_os29.homedir)(),
75135
75395
  running,
75136
75396
  pluginCacheFsDeps(configRoot, directoryBytes),
75137
75397
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
@@ -75147,7 +75407,7 @@ program2.command("archive-prune").description("inventory worktree evidence archi
75147
75407
  let primary = o.repoRoot;
75148
75408
  if (!primary) {
75149
75409
  const common = await gitOut(["rev-parse", "--path-format=absolute", "--git-common-dir"]);
75150
- primary = common ? (0, import_node_path64.dirname)(common) : "";
75410
+ primary = common ? (0, import_node_path65.dirname)(common) : "";
75151
75411
  }
75152
75412
  if (!primary) {
75153
75413
  const detail = "archive-prune: not inside a git checkout (pass --repo-root <primary checkout>)";