@mutmutco/claude-plugin 4.6.35 → 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");
@@ -15366,13 +15371,6 @@ async function fetchHubBoardSnapshot(request, deps) {
15366
15371
  // src/board-read.ts
15367
15372
  init_github_quota();
15368
15373
 
15369
- // src/claim-marker-client.ts
15370
- init_github_client();
15371
- init_github_quota();
15372
-
15373
- // src/pr-checks-rest.ts
15374
- init_cli_shared();
15375
-
15376
15374
  // ../shared/github-quota-scope.ts
15377
15375
  var import_node_crypto4 = require("node:crypto");
15378
15376
  function appQuotaScope(appId, installationId, origin = "https://api.github.com", resource = "graphql") {
@@ -15737,6 +15735,13 @@ async function activateAppActor(commandPath4, env, mint, note = (line) => proces
15737
15735
  return "app";
15738
15736
  }
15739
15737
 
15738
+ // src/claim-marker-client.ts
15739
+ init_github_client();
15740
+ init_github_quota();
15741
+
15742
+ // src/pr-checks-rest.ts
15743
+ init_cli_shared();
15744
+
15740
15745
  // src/merge-ci-policy.ts
15741
15746
  function resolveMergeCiPolicy(input) {
15742
15747
  if (input.registryCi === "none") {
@@ -17174,9 +17179,11 @@ async function fetchRestCorePool(gh2 = defaultGhApi, nowMs = Date.now()) {
17174
17179
  // src/claim-marker-client.ts
17175
17180
  var claimWriteTokenProvider;
17176
17181
  var claimWriteTokenOnce;
17182
+ var notedPersonalClaimWrite = false;
17177
17183
  function setClaimWriteTokenProvider(provider) {
17178
17184
  claimWriteTokenProvider = provider;
17179
17185
  claimWriteTokenOnce = void 0;
17186
+ notedPersonalClaimWrite = false;
17180
17187
  }
17181
17188
  async function selectClaimWriteClient(client, appClient) {
17182
17189
  if (appClient) return appClient;
@@ -17187,15 +17194,26 @@ async function selectClaimWriteClient(client, appClient) {
17187
17194
  token = await claimWriteTokenOnce;
17188
17195
  } catch (e) {
17189
17196
  claimWriteTokenOnce = void 0;
17197
+ if (e instanceof AppActorError && e.code === "vault-denied" && process.env.MMI_ACTOR?.trim() !== "app") return personalClaimWrite(client);
17190
17198
  const detail = e instanceof Error ? e.message : String(e);
17191
17199
  throw new Error(`${detail} \u2014 refusing personal-token fallback for claim write (#9511)`);
17192
17200
  }
17193
17201
  if (!token) {
17194
17202
  claimWriteTokenOnce = void 0;
17195
- throw new Error("app actor: claim write token unavailable \u2014 refusing personal-token fallback for claim write (#9511)");
17203
+ if (process.env.MMI_ACTOR?.trim() === "app") {
17204
+ throw new Error("app actor: claim write token unavailable \u2014 refusing personal-token fallback for claim write (#9511)");
17205
+ }
17206
+ return personalClaimWrite(client);
17196
17207
  }
17197
17208
  return createGitHubClient({ token: async () => token });
17198
17209
  }
17210
+ function personalClaimWrite(client) {
17211
+ if (!notedPersonalClaimWrite) {
17212
+ notedPersonalClaimWrite = true;
17213
+ process.stderr.write("note: no App route on this host (no MMI-Hub vault access) \u2014 claim writes go as your own GitHub login\n");
17214
+ }
17215
+ return client;
17216
+ }
17199
17217
  async function selectLivenessClient(client, appClient) {
17200
17218
  if (appClient) return appClient;
17201
17219
  let token;
@@ -22745,6 +22763,7 @@ mutation($projectId: ID!, $itemId: ID!) {
22745
22763
  item { id }
22746
22764
  }
22747
22765
  }`;
22766
+ var BOARD_WRITE_REFUSAL_TYPES = /* @__PURE__ */ new Set(["INSUFFICIENT_SCOPES", "FORBIDDEN", "NOT_FOUND"]);
22748
22767
  async function updateItemSingleSelect(client, projectId, itemId, fieldId, optionId) {
22749
22768
  if (process.env.MMI_ACTOR?.trim() === "app") {
22750
22769
  const { writeHubBoardField: writeHubBoardField2 } = await Promise.resolve().then(() => (init_board_write(), board_write_exports));
@@ -22771,10 +22790,14 @@ async function updateItemSingleSelect(client, projectId, itemId, fieldId, option
22771
22790
  return { credential: "user" };
22772
22791
  } catch (error) {
22773
22792
  const errors = error.graphqlErrors;
22774
- if (errors?.length && errors.every((entry) => entry.type === "INSUFFICIENT_SCOPES")) {
22793
+ if (errors?.length && errors.every((entry) => entry.type !== void 0 && BOARD_WRITE_REFUSAL_TYPES.has(entry.type))) {
22775
22794
  const { writeHubBoardField: writeHubBoardField2 } = await Promise.resolve().then(() => (init_board_write(), board_write_exports));
22776
- await writeHubBoardField2({ projectId, itemId, fieldId, optionId });
22777
- return { credential: "app_installation" };
22795
+ try {
22796
+ await writeHubBoardField2({ projectId, itemId, fieldId, optionId });
22797
+ return { credential: "app_installation" };
22798
+ } catch {
22799
+ throw error;
22800
+ }
22778
22801
  }
22779
22802
  if (isGitHubRateLimitError(error)) {
22780
22803
  const { writeHubBoardField: writeHubBoardField2 } = await Promise.resolve().then(() => (init_board_write(), board_write_exports));
@@ -25284,6 +25307,8 @@ var MANAGED_GITIGNORE_LINES = [
25284
25307
  // (measured on the v3.120.0 Hub train), with no legal resolution: committing another host's runtime
25285
25308
  // state is not an option, so the operator's only move was to park the directory outside the repo.
25286
25309
  ".pi/",
25310
+ // #10003: reviewer worktrees — never committable, regenerate during review (same runtime class as `.pi/`).
25311
+ "/review-state/",
25287
25312
  ".aws-sam/",
25288
25313
  // jerv-cli lease markers are ephemeral runtime state and never tracked. Hub#2586.
25289
25314
  ".jerv-lease.json",
@@ -25409,7 +25434,7 @@ function extractForwardRefs(markdown) {
25409
25434
  });
25410
25435
  return refs;
25411
25436
  }
25412
- function checkPins(root, readFile10, docs) {
25437
+ function checkPins(root, readFile11, docs) {
25413
25438
  const findings = [];
25414
25439
  for (const [doc, markdown] of Object.entries(docs)) {
25415
25440
  for (const pin of extractPins(markdown)) {
@@ -25417,7 +25442,7 @@ function checkPins(root, readFile10, docs) {
25417
25442
  findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
25418
25443
  continue;
25419
25444
  }
25420
- const source = readFile10((0, import_node_path16.join)(root, pin.file));
25445
+ const source = readFile11((0, import_node_path16.join)(root, pin.file));
25421
25446
  if (source == null) {
25422
25447
  findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
25423
25448
  continue;
@@ -25713,15 +25738,15 @@ function checkRunbookCoverage(docs, base, git3) {
25713
25738
  }
25714
25739
  return findings;
25715
25740
  }
25716
- function checkSeedRunbookReview(root, base, readFile10, git3) {
25717
- 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"));
25718
25743
  if (!manifestJson) return [];
25719
25744
  const changed = new Set(git3(["diff", "--name-only", `${base}...HEAD`]).split(/\r?\n/).filter(Boolean));
25720
25745
  const touched = loadBootstrapSeeds(manifestJson).seeds.filter((seed) => isPropagatableSeed(seed) && changed.has(seedSourcePath(seed)));
25721
25746
  if (!touched.length) return [];
25722
25747
  let declarations = null;
25723
25748
  try {
25724
- 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");
25725
25750
  } catch {
25726
25751
  declarations = null;
25727
25752
  }
@@ -25808,12 +25833,12 @@ function defaultTrackedFiles(root, firstSegments, exec3 = import_node_child_proc
25808
25833
  throw error;
25809
25834
  }
25810
25835
  }
25811
- function mergeGroupRunbookMessages(root, deps, readFile10, warnings) {
25836
+ function mergeGroupRunbookMessages(root, deps, readFile11, warnings) {
25812
25837
  const env = deps.env ?? process.env;
25813
25838
  if (env.GITHUB_EVENT_NAME !== "merge_group") return "";
25814
25839
  let source = "merge_group event payload";
25815
25840
  try {
25816
- const event = JSON.parse(readFile10(env.GITHUB_EVENT_PATH ?? "") ?? "");
25841
+ const event = JSON.parse(readFile11(env.GITHUB_EVENT_PATH ?? "") ?? "");
25817
25842
  const match = /^refs\/heads\/gh-readonly-queue\/.+\/pr-([1-9]\d*)-[a-f0-9]+$/.exec(event.merge_group?.head_ref ?? "");
25818
25843
  const repo = env.GITHUB_REPOSITORY;
25819
25844
  if (!match || !repo || !/^[\w.-]+\/[\w.-]+$/.test(repo)) throw new Error("invalid queue source");
@@ -25836,7 +25861,7 @@ function mergeGroupRunbookMessages(root, deps, readFile10, warnings) {
25836
25861
  }
25837
25862
  }
25838
25863
  function runDocRefs(root, deps = {}) {
25839
- const readFile10 = deps.readFile ?? readFileOrNull;
25864
+ const readFile11 = deps.readFile ?? readFileOrNull;
25840
25865
  const exists = deps.exists ?? import_node_fs19.existsSync;
25841
25866
  const listDocs = deps.listDocs ?? defaultListDocs;
25842
25867
  const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
@@ -25850,11 +25875,11 @@ function runDocRefs(root, deps = {}) {
25850
25875
  const walked = listDocs(root);
25851
25876
  const ignoredDocs = walked.length ? isIgnored(walked) : /* @__PURE__ */ new Set();
25852
25877
  const docs = Object.fromEntries(
25853
- 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)))
25854
25879
  );
25855
25880
  const refResult = checkRefs(root, { exists, isIgnored, trackedFirstSegments }, docs);
25856
25881
  const findings = [
25857
- ...checkPins(root, readFile10, docs).findings,
25882
+ ...checkPins(root, readFile11, docs).findings,
25858
25883
  ...refResult.findings
25859
25884
  ];
25860
25885
  if (commandPaths == null) {
@@ -25868,7 +25893,7 @@ function runDocRefs(root, deps = {}) {
25868
25893
  findings.push(...checkCommands(docs, commandPaths).findings);
25869
25894
  }
25870
25895
  const runbooks = Object.fromEntries(Object.entries(docs).filter(([doc, body]) => isRunbook(doc, body)));
25871
- 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 }));
25872
25897
  const warnings = [...refResult.warnings];
25873
25898
  if (deps.runbooksOnly && !Object.keys(runbooks).length) {
25874
25899
  warnings.push({ kind: "runbook-missing", doc: "docs/Guides/operator.md", line: 0, detail: "no operator runbook or <!-- runbook --> document exists" });
@@ -25876,9 +25901,9 @@ function runDocRefs(root, deps = {}) {
25876
25901
  if (deps.base) {
25877
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 }));
25878
25903
  const stale = checkRunbookCoverage(runbooks, deps.base, git3);
25879
- const seedStale = checkSeedRunbookReview(root, deps.base, readFile10, git3);
25904
+ const seedStale = checkSeedRunbookReview(root, deps.base, readFile11, git3);
25880
25905
  const messages = git3(["log", "--format=%B", `${deps.base}..HEAD`]);
25881
- const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps, readFile10, warnings) : "";
25906
+ const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps, readFile11, warnings) : "";
25882
25907
  const allMessages = `${messages}
25883
25908
  ${sourceMessages}`;
25884
25909
  const override = /^Runbook-Unaffected:[ \t]*\S.*$/m.test(allMessages);
@@ -26837,22 +26862,22 @@ function renderBootstrapAncillaryPlan(labels, environments, exceptions = []) {
26837
26862
  ...exceptions.map(({ name, detail }) => ` OK environment ${name} (${detail})`)
26838
26863
  ].join("\n");
26839
26864
  }
26840
- function resolveSeedContent(seed, vars, readFile10) {
26841
- if (seed.source === "self") return readFile10(seed.target);
26865
+ function resolveSeedContent(seed, vars, readFile11) {
26866
+ if (seed.source === "self") return readFile11(seed.target);
26842
26867
  if (seed.source.startsWith("seed:")) {
26843
- const tmpl = readFile10(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
26868
+ const tmpl = readFile11(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
26844
26869
  return tmpl == null ? null : renderSeed(tmpl, vars);
26845
26870
  }
26846
26871
  return null;
26847
26872
  }
26848
- function resolveSeedWriteContent(seed, vars, readFile10, remoteContent) {
26873
+ function resolveSeedWriteContent(seed, vars, readFile11, remoteContent) {
26849
26874
  if (!seed.managedBlock) {
26850
- 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" };
26851
26876
  }
26852
- const base = remoteContent ?? resolveSeedContent(seed, vars, readFile10);
26877
+ const base = remoteContent ?? resolveSeedContent(seed, vars, readFile11);
26853
26878
  if (base == null) return { ok: true, content: null, managed: true };
26854
26879
  const blockSeed = { ...seed, source: seed.managedBlock.source, managedBlock: void 0 };
26855
- const desired = resolveSeedContent(blockSeed, vars, readFile10);
26880
+ const desired = resolveSeedContent(blockSeed, vars, readFile11);
26856
26881
  if (desired == null) return { ok: true, content: null, managed: true };
26857
26882
  const result = upsertManagedSeedBlock(base, desired, seed.managedBlock.begin, seed.managedBlock.end);
26858
26883
  return result.ok ? { ok: true, content: result.content, managed: true } : { ok: false, reason: result.reason, managed: true };
@@ -28367,10 +28392,10 @@ var rollout_plan_default = {
28367
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)."
28368
28393
  },
28369
28394
  baseline: {
28370
- version: "4.6.35",
28371
- tag: "v4.6.35",
28372
- commit: "2a54cf011975",
28373
- npm: "@mutmutco/cli@4.6.35"
28395
+ version: "4.6.37",
28396
+ tag: "v4.6.37",
28397
+ commit: "94211a24e48a",
28398
+ npm: "@mutmutco/cli@4.6.37"
28374
28399
  },
28375
28400
  exitCriterion: "fleet-n-of-n",
28376
28401
  hubOnlyShortcut: "forbidden",
@@ -28387,14 +28412,14 @@ var rollout_plan_default = {
28387
28412
  repo: "mutmutco/mmi-hub",
28388
28413
  role: "canary",
28389
28414
  schedule: "train",
28390
- v3Target: "v4.6.35"
28415
+ v3Target: "v4.6.37"
28391
28416
  }
28392
28417
  ],
28393
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.",
28394
28419
  rollback: {
28395
28420
  independent: true,
28396
- mechanism: "npm dist-tag latest -> 4.6.35 and redeploy the Hub Lambda from tag v4.6.35 (2a54cf011975); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28397
- v3Target: "v4.6.35 (@mutmutco/cli@4.6.35, tag commit 2a54cf011975 \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)"
28398
28423
  }
28399
28424
  },
28400
28425
  {
@@ -43417,8 +43442,8 @@ function annotateChangeMeaning(changed, policy, read) {
43417
43442
  function isMeaningfulRow(file) {
43418
43443
  return file.meaningful !== false;
43419
43444
  }
43420
- function loadPolicy(root, readFile10 = readFileOrNull2) {
43421
- 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));
43422
43447
  if (raw == null) return { mandatory: [], declared: false };
43423
43448
  return parsePolicy(raw, POLICY_FILE);
43424
43449
  }
@@ -44155,12 +44180,16 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
44155
44180
  receipt = { ...receipt, state: "pending", uuid: details.uuid };
44156
44181
  }
44157
44182
  const sleep2 = options.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
44158
- for (let attempt = 0; attempt < 3; attempt++) {
44159
- 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;
44160
44188
  try {
44161
44189
  response = admissionResponse(await read([`repos/${repo}/pulls/${pr}/merge-async/${receipt.uuid}`, "--include", ...ASYNC_HEADERS]));
44162
44190
  } catch {
44163
- return reconcile("the saved operation cannot be read (including expired results)");
44191
+ readFailure = "the saved operation cannot be read (including expired results)";
44192
+ continue;
44164
44193
  }
44165
44194
  if (response.code !== 200) return reconcile(`the saved operation returned HTTP ${response.code}`);
44166
44195
  const { status, details } = response.body;
@@ -44202,6 +44231,7 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
44202
44231
  if (receipt.head !== head) return reconcile("the previous head completed admission; inspect current head and membership before continuing");
44203
44232
  return reconcile(`operation ${receipt.uuid} reported ${status}, but matching-head membership or merged state is unconfirmed`, status === "enqueued");
44204
44233
  }
44234
+ if (readFailure) return reconcile(readFailure);
44205
44235
  return markReenqueued({
44206
44236
  mergeStatus: "queue-admission-pending",
44207
44237
  retryable: false,
@@ -44424,8 +44454,8 @@ async function abandonQueueAdmission(pr, repo, options = {}) {
44424
44454
  }
44425
44455
  const receipt = journal.receipt;
44426
44456
  if (!receipt) return refuse("no queue-admission receipt exists for this PR; nothing to abandon");
44427
- if (!["pending", "enqueued"].includes(receipt.state)) {
44428
- 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`);
44429
44459
  }
44430
44460
  let snapshot;
44431
44461
  try {
@@ -45759,20 +45789,20 @@ function buildPrLifecycle(state, manifest, joins) {
45759
45789
  if (member.pr !== state.number) continue;
45760
45790
  if (!member.admission_event_id) continue;
45761
45791
  const ep = episodes.find((x) => x.episode_id === member.admission_event_id);
45762
- 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);
45763
- 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;
45764
45794
  if (!ep) {
45765
45795
  if (state.status === "complete") {
45766
- join54.status = "unresolved";
45767
- join54.reason = "admission-event-not-in-history";
45796
+ join55.status = "unresolved";
45797
+ join55.reason = "admission-event-not-in-history";
45768
45798
  } else {
45769
- join54.status = "unresolved";
45770
- join54.reason = "history-incomplete";
45799
+ join55.status = "unresolved";
45800
+ join55.reason = "history-incomplete";
45771
45801
  }
45772
45802
  continue;
45773
45803
  }
45774
- join54.status = "joined";
45775
- delete join54.reason;
45804
+ join55.status = "joined";
45805
+ delete join55.reason;
45776
45806
  ep.runs.push({ run_id: run.run_id, run_attempt: run.run_attempt, head_sha: run.head_sha });
45777
45807
  }
45778
45808
  }
@@ -46149,6 +46179,15 @@ async function attachOnIntegrationRefusal(detail, cfg, contentNodeId, attach = a
46149
46179
  return { warning: `board attach refused: the gh login is an App installation token without Projects access (${detail}) and the Hub App leg failed (${e.message}). If the Hub reports the same refusal, ${PROJECTS_PERMISSION_HINT}` };
46150
46180
  }
46151
46181
  }
46182
+ var ATTACH_AUTHORITY_REFUSAL = /FORBIDDEN|NOT_FOUND|Resource not accessible|missing required scopes|insufficient (?:permissions?|scope)|Could not resolve to a node|does not have (?:access|permission)/i;
46183
+ async function attachOnAuthorityRefusal(detail, cfg, contentNodeId, attach = attachViaHubApp) {
46184
+ if (!ATTACH_AUTHORITY_REFUSAL.test(detail)) return void 0;
46185
+ try {
46186
+ return { projectItemId: await attach(cfg, contentNodeId) };
46187
+ } catch (e) {
46188
+ return { warning: `${detail}; the Hub attach also refused (${e.message}) \u2014 attach needs org-owner, repo-admin or repository write authority on the board's repository` };
46189
+ }
46190
+ }
46152
46191
  async function issueNodeIdForAttach(repo, number, ghView, client) {
46153
46192
  try {
46154
46193
  return (await ghView()).trim();
@@ -51627,7 +51666,7 @@ function registerBootstrapCommands(program3) {
51627
51666
  const slug = parsedRepo.slug;
51628
51667
  const onlyTarget = o.fromConfig && o.only.trim() === "gate.yml" ? ".github/workflows/gate.yml" : o.only.trim();
51629
51668
  const gh2 = async (args) => execFileP("gh", args, { timeout: 2e4 });
51630
- 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;
51631
51670
  const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
51632
51671
  const putSeed = async (target, content, ref, sha) => {
51633
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`);
@@ -51799,7 +51838,7 @@ function registerBootstrapCommands(program3) {
51799
51838
  registryMeta?.requiredCheckBranches,
51800
51839
  registryMeta?.requiredChecks
51801
51840
  );
51802
- const rendered = resolveSeedContent(gateSeed, gateVars, readFile10);
51841
+ const rendered = resolveSeedContent(gateSeed, gateVars, readFile11);
51803
51842
  if (rendered === null || missingPlaceholders(rendered).length) return failGraceful("bootstrap apply: registry gate template is unreadable or has unfilled placeholders");
51804
51843
  const base = (await readTargetedSeedFiles(repo, scopedPlan, onlyTarget, scopedPlan.baseSha, controlClient)).base?.content ?? null;
51805
51844
  configGateAction = planGateFromConfig(base, rendered);
@@ -51903,7 +51942,7 @@ function registerBootstrapCommands(program3) {
51903
51942
  ...vars,
51904
51943
  ...registryMeta?.requiredChecks?.length ? { GATE_RULESET_CONTEXTS_JSON: rulesetVars.GATE_RULESET_CONTEXTS_JSON } : {},
51905
51944
  ...registryMeta?.requiredCheckBranches?.length ? { GATE_RULESET_BRANCH_REFS_JSON: rulesetVars.GATE_RULESET_BRANCH_REFS_JSON } : {}
51906
- } : vars, readFile10, preservedContent);
51945
+ } : vars, readFile11, preservedContent);
51907
51946
  if (!writeContent.ok) {
51908
51947
  return fail(`bootstrap apply: ${resolved.target}: ${writeContent.reason} \u2014 refusing to overwrite repo-owned content`);
51909
51948
  }
@@ -52049,7 +52088,7 @@ ${onlyManagedBlock ? `Only the marker-bounded Hub-managed block inside repo-owne
52049
52088
  }
52050
52089
  const rulesetSeed = repo.toLowerCase() === "mutmutco/mmi-hub" ? void 0 : manifest.seeds.find((s) => s.target === ".github/rulesets/mmi-product-required-checks.json");
52051
52090
  if (rulesetSeed) {
52052
- 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);
52053
52092
  if (rulesetContent) {
52054
52093
  try {
52055
52094
  const client = controlClient;
@@ -52841,32 +52880,183 @@ function registerDeployCommands(program3) {
52841
52880
  }
52842
52881
 
52843
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();
52844
52888
  init_github_client();
52845
- var CANONICAL_COMMAND = "mmi-cli harbour intercom guest";
52889
+ var CANONICAL_COMMAND = "mmi-cli intercom guest";
52846
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
+ }
52847
52897
  var INTERCOM_GUEST_CONTRACT = {
52848
- 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",
52849
52901
  baseUrlEnv: "MMI_INTERCOM_GATEWAY_URL",
52850
- 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
+ }
52851
52973
  };
52852
52974
  var INTERCOM_GUEST_CONTRACT_MISSING = "intercom-guest-contract-missing";
52853
52975
  var INTERCOM_GUEST_BASE_URL_MISSING = "intercom-guest-base-url-missing";
52854
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
+ }
52855
52984
  function scrubToken(text, token) {
52856
52985
  if (!token) return text;
52857
52986
  return text.split(token).join("***");
52858
52987
  }
52988
+ function scrubSecrets(text, secrets) {
52989
+ return secrets.reduce((acc, secret) => scrubToken(acc, secret), text);
52990
+ }
52859
52991
  function missingContractRefusal(verb) {
52860
52992
  return [
52861
- `${CANONICAL_COMMAND} ${verb}: not sent \u2014 the Jerv Gateway guest contract has not landed (${INTERCOM_GUEST_CONTRACT.source}).`,
52862
- `Its guest operations (${INTERCOM_GUEST_VERBS.join(", ")}) publish no method, path or field shape yet, so this client refuses`,
52863
- "instead of guessing an endpoint: a guessed call would come back 404/403 and read as a permission or allowlist answer",
52864
- "when the real answer is that the contract is missing.",
52865
- `To switch every verb on: land the guest principal operations in ${INTERCOM_GUEST_CONTRACT.source}, then fill`,
52866
- "`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.",
52867
53000
  "Nothing was read and nothing was sent: no token was touched and no request was made."
52868
53001
  ].join(" ");
52869
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
+ }
52870
53060
  async function runIntercomGuest(request, deps = {}) {
52871
53061
  const verb = request.verb;
52872
53062
  const contract = deps.contract ?? INTERCOM_GUEST_CONTRACT;
@@ -52874,61 +53064,156 @@ async function runIntercomGuest(request, deps = {}) {
52874
53064
  if (!operation) {
52875
53065
  return { ok: false, verb, code: INTERCOM_GUEST_CONTRACT_MISSING, message: missingContractRefusal(verb), tokenRead: false };
52876
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
+ }
52877
53077
  const env = deps.env ?? process.env;
52878
- const baseUrl = env[contract.baseUrlEnv]?.trim();
53078
+ const baseUrl = (env[contract.baseUrlEnv]?.trim() || contract.baseUrl).replace(/\/+$/, "");
52879
53079
  if (!baseUrl) {
52880
53080
  return {
52881
53081
  ok: false,
52882
53082
  verb,
52883
53083
  code: INTERCOM_GUEST_BASE_URL_MISSING,
52884
- 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.`,
52885
53085
  tokenRead: false
52886
53086
  };
52887
53087
  }
53088
+ const storePath = deps.storePath ?? intercomGuestStorePath(env);
53089
+ const store = await readStore(storePath);
52888
53090
  const identity = await (deps.readToken ?? githubKeyringTokenRead)();
52889
53091
  if (identity.state !== "ok") {
52890
53092
  return {
52891
53093
  ok: false,
52892
53094
  verb,
52893
53095
  code: INTERCOM_GUEST_NO_IDENTITY,
52894
- message: scrubToken(
52895
- `${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
+ []
52896
53099
  ),
52897
53100
  tokenRead: false
52898
53101
  };
52899
53102
  }
52900
53103
  const token = identity.token;
52901
- const fetchImpl = deps.fetchImpl ?? ((url, init2) => fetch(url, init2));
52902
- const headers = { accept: "application/json", authorization: `Bearer ${token}` };
52903
- const init = { method: operation.method, headers };
52904
- if (operation.body) {
52905
- headers["content-type"] = "application/json";
52906
- 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
+ }
52907
53119
  }
52908
- let response;
52909
- try {
52910
- response = await fetchImpl(new URL(operation.path, baseUrl).toString(), init);
52911
- } catch (error) {
52912
- const detail = error instanceof Error ? error.message : String(error);
52913
- 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
+ };
52914
53132
  }
52915
- const text = await response.text().catch(() => "");
52916
- 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) {
52917
53197
  return {
52918
53198
  ok: false,
52919
53199
  verb,
52920
- code: `intercom-guest-http-${response.status}`,
52921
- 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),
52922
53202
  tokenRead: true
52923
53203
  };
52924
53204
  }
52925
- 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) };
52926
53211
  }
52927
53212
  function renderIntercomGuestResult(result) {
52928
53213
  return result.ok ? result.body : result.message;
52929
53214
  }
52930
53215
  function registerIntercomGuestCommands(program3, io = {}) {
52931
- 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");
52932
53217
  const out = io.out ?? ((line) => process.stdout.write(`${line}
52933
53218
  `));
52934
53219
  const err = io.err ?? ((line) => process.stderr.write(`${line}
@@ -52943,19 +53228,21 @@ function registerIntercomGuestCommands(program3, io = {}) {
52943
53228
  return;
52944
53229
  }
52945
53230
  err(renderIntercomGuestResult(result));
52946
- 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
+ );
52947
53234
  };
52948
- 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 () => {
52949
53236
  await run({ verb: "register" });
52950
53237
  });
52951
- 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) => {
52952
- const limit = Number(options.limit ?? 20);
52953
- 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) });
52954
53241
  });
52955
- 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) => {
52956
53243
  await run({ verb: "send", to: options.to, message: options.message });
52957
53244
  });
52958
- 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) => {
52959
53246
  await run({ verb: "join", suite: options.suite });
52960
53247
  });
52961
53248
  guest.command("leave").description("Leave the suite and withdraw this guest endpoint").action(async () => {
@@ -52970,7 +53257,7 @@ init_github_client();
52970
53257
  init_cli_shared();
52971
53258
 
52972
53259
  // src/suite-status.ts
52973
- var import_node_crypto19 = require("node:crypto");
53260
+ var import_node_crypto20 = require("node:crypto");
52974
53261
  var SUITE_REPO = "mutmutco/MM-Work";
52975
53262
  var REPOS = {
52976
53263
  "mmi-scout": "mutmutco/MMI-Scout",
@@ -52998,7 +53285,7 @@ function parseSuiteMapping(body) {
52998
53285
  return void 0;
52999
53286
  }
53000
53287
  }
53001
- 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");
53002
53289
  async function proveBundle(url, tag, fetchUrl) {
53003
53290
  const get = async (u) => {
53004
53291
  try {
@@ -53254,8 +53541,8 @@ async function waitSuiteDev(deps, opts) {
53254
53541
 
53255
53542
  // src/suite-train.ts
53256
53543
  var import_node_fs41 = require("node:fs");
53257
- var import_node_path38 = require("node:path");
53258
- var import_node_crypto20 = require("node:crypto");
53544
+ var import_node_path39 = require("node:path");
53545
+ var import_node_crypto21 = require("node:crypto");
53259
53546
 
53260
53547
  // src/kit-version.ts
53261
53548
  var parse = (v) => /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(typeof v === "string" ? v.trim() : "");
@@ -53356,8 +53643,8 @@ function readSuiteCut(path2) {
53356
53643
  return record2;
53357
53644
  }
53358
53645
  function writeSuiteCut(path2, record2) {
53359
- (0, import_node_fs41.mkdirSync)((0, import_node_path38.dirname)(path2), { recursive: true });
53360
- 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`;
53361
53648
  try {
53362
53649
  (0, import_node_fs41.writeFileSync)(temp, JSON.stringify(record2, null, 2), { flag: "wx" });
53363
53650
  (0, import_node_fs41.renameSync)(temp, path2);
@@ -53416,7 +53703,7 @@ async function retireFailedLeadRcLedger(deps, ownerGo) {
53416
53703
  if (ledger.repo !== SUITE_REPO || ledger.lane !== "rcand" || ledger.phases.promotion.state === "complete" || !states.includes("failed")) return void 0;
53417
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`);
53418
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`);
53419
- 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`);
53420
53707
  if ((0, import_node_fs41.existsSync)(archive)) throw new Error(`ledger archive already exists at ${archive}; inspect before retiring again`);
53421
53708
  await deps.markAbandoned(SUITE_REPO, ledger.tag, ledger.tagSha);
53422
53709
  await fence(() => (0, import_node_fs41.renameSync)(deps.ledgerPath, archive));
@@ -53783,7 +54070,7 @@ Each member's live release must serve <data>/main/module.js at its main pin path
53783
54070
  }
53784
54071
  return record2;
53785
54072
  }
53786
- 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");
53787
54074
  function readSuiteHotfix(path2) {
53788
54075
  let raw;
53789
54076
  try {
@@ -54098,20 +54385,20 @@ async function runRcDataSwitch(deps, opts) {
54098
54385
 
54099
54386
  // src/suite-train-io.ts
54100
54387
  var import_node_child_process19 = require("node:child_process");
54101
- var import_node_path51 = require("node:path");
54102
- var import_node_fs55 = require("node:fs");
54103
54388
  var import_node_path52 = require("node:path");
54389
+ var import_node_fs55 = require("node:fs");
54390
+ var import_node_path53 = require("node:path");
54104
54391
  init_cli_shared();
54105
54392
 
54106
54393
  // src/command-register-train-operations.ts
54107
- var import_promises9 = require("node:fs/promises");
54394
+ var import_promises10 = require("node:fs/promises");
54108
54395
  init_clean_exit();
54109
54396
  init_cli_shared();
54110
54397
  init_client_version();
54111
54398
  init_house_map();
54112
54399
 
54113
54400
  // src/hotfix-apply.ts
54114
- var import_promises5 = require("node:fs/promises");
54401
+ var import_promises6 = require("node:fs/promises");
54115
54402
 
54116
54403
  // src/release-announce.ts
54117
54404
  var ANNOUNCE_REPO = "mutmutco/MMI-Hub";
@@ -54454,8 +54741,8 @@ async function preflightHotfixBatchPicks(deps, sources, pickTolerated) {
54454
54741
  if (sources.length === 0) return { failures: [], skipped: [] };
54455
54742
  const { mkdtemp: mkdtemp2, rm: rm2 } = await import("node:fs/promises");
54456
54743
  const { tmpdir: tmpdir13 } = await import("node:os");
54457
- const { join: join54 } = await import("node:path");
54458
- 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-"));
54459
54746
  const wt = { run: (file, args) => deps.run(file, file === "git" ? ["-C", dir, ...args] : args) };
54460
54747
  const failures = [];
54461
54748
  const skipped = [];
@@ -55167,7 +55454,7 @@ async function runHotfixReleaseLocked(deps, versionInput, options, doctor) {
55167
55454
  }
55168
55455
  let lines2;
55169
55456
  try {
55170
- 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));
55171
55458
  } catch (e) {
55172
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`);
55173
55460
  }
@@ -55793,8 +56080,8 @@ function checkHotfixCarries(options) {
55793
56080
 
55794
56081
  // src/merge-cleanup.ts
55795
56082
  var import_node_fs42 = require("node:fs");
55796
- var import_node_path39 = require("node:path");
55797
- var import_node_os22 = require("node:os");
56083
+ var import_node_path40 = require("node:path");
56084
+ var import_node_os23 = require("node:os");
55798
56085
  init_cli_shared();
55799
56086
  init_github_client();
55800
56087
 
@@ -56201,8 +56488,8 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
56201
56488
  return rewritten === base ? null : rewritten;
56202
56489
  }
56203
56490
  function writeSquashBodyFile(body) {
56204
- const dir = (0, import_node_fs42.mkdtempSync)((0, import_node_path39.join)((0, import_node_os22.tmpdir)(), "mmi-squash-body-"));
56205
- 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");
56206
56493
  (0, import_node_fs42.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
56207
56494
  `, "utf8");
56208
56495
  return { path: path2, cleanup: () => {
@@ -56458,9 +56745,9 @@ async function deleteMergedRemoteBranch(options) {
56458
56745
  init_github_client();
56459
56746
 
56460
56747
  // src/release-custody.ts
56461
- var import_node_crypto21 = require("node:crypto");
56748
+ var import_node_crypto22 = require("node:crypto");
56462
56749
  var import_node_fs43 = require("node:fs");
56463
- var import_node_path40 = require("node:path");
56750
+ var import_node_path41 = require("node:path");
56464
56751
  init_github_client();
56465
56752
 
56466
56753
  // src/release-custody-bootstrap.ts
@@ -56682,7 +56969,7 @@ var ReleaseCustodyError = class extends Error {
56682
56969
  this.name = "ReleaseCustodyError";
56683
56970
  }
56684
56971
  };
56685
- 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");
56686
56973
  function parseCustody(raw, repo) {
56687
56974
  const s = JSON.parse(raw);
56688
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) {
@@ -56783,7 +57070,7 @@ var ReleaseCustodySession = class _ReleaseCustodySession {
56783
57070
  }
56784
57071
  }
56785
57072
  let state = {
56786
- ...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() },
56787
57074
  revision: (found.state?.revision ?? 0) + 1,
56788
57075
  controller
56789
57076
  };
@@ -56844,7 +57131,7 @@ var ReleaseCustodySession = class _ReleaseCustodySession {
56844
57131
  proof: { kind: "ledger-lifecycle", controller: state.controller }
56845
57132
  };
56846
57133
  }
56847
- 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 };
56848
57135
  });
56849
57136
  }
56850
57137
  async preserveLocal(raw) {
@@ -56960,10 +57247,10 @@ function localRaw(path2) {
56960
57247
  function hydrateLocal(path2, raw) {
56961
57248
  const previous = localRaw(path2);
56962
57249
  if (previous === raw) return;
56963
- (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 });
56964
57251
  if (previous !== null) {
56965
57252
  const ledger = parseReleaseLedger(previous);
56966
- 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`);
56967
57254
  if (!(0, import_node_fs43.existsSync)(archive)) (0, import_node_fs43.writeFileSync)(archive, previous, { flag: "wx" });
56968
57255
  if (raw === null) (0, import_node_fs43.renameSync)(path2, `${path2}.retired-${custodyDigest(previous)}`);
56969
57256
  }
@@ -57078,7 +57365,7 @@ function withHubReleaseCustody(deps) {
57078
57365
  if (!authority.ok || !authority.train || authority.authenticatedDelegation !== true) {
57079
57366
  throw new ReleaseCustodyError("repository custody requires the server-verified owner-triggered train session");
57080
57367
  }
57081
- 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 } : {} };
57082
57369
  const raw = localRaw(path2);
57083
57370
  const requiredContexts = () => discoverRequiredCheckContexts(
57084
57371
  deps,
@@ -57159,7 +57446,7 @@ function withHubReleaseCustody(deps) {
57159
57446
 
57160
57447
  // src/project-info-sync.ts
57161
57448
  var import_node_fs44 = require("node:fs");
57162
- var import_node_path41 = require("node:path");
57449
+ var import_node_path42 = require("node:path");
57163
57450
  var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
57164
57451
  updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
57165
57452
  projectV2 { id }
@@ -57206,7 +57493,7 @@ function sharedName(entries, fallback) {
57206
57493
  }
57207
57494
  function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
57208
57495
  if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
57209
- const readmePath = (0, import_node_path41.join)(repoRoot2, "README.md");
57496
+ const readmePath = (0, import_node_path42.join)(repoRoot2, "README.md");
57210
57497
  if (!(0, import_node_fs44.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
57211
57498
  const entries = entriesFor(project2, projects);
57212
57499
  const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
@@ -57232,8 +57519,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
57232
57519
  const targetBase = `https://github.com/${targetRepo2}`;
57233
57520
  const targetBranch = branchFor(targetRepo2, projects);
57234
57521
  const orgDocs = [
57235
- (0, import_node_fs44.existsSync)((0, import_node_path41.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
57236
- (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)` : ""
57237
57524
  ].filter(Boolean);
57238
57525
  if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
57239
57526
  return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
@@ -57256,7 +57543,7 @@ async function syncProjectInfo(plan, client, apply) {
57256
57543
 
57257
57544
  // src/train-commands.ts
57258
57545
  var import_node_fs45 = require("node:fs");
57259
- var import_node_path42 = require("node:path");
57546
+ var import_node_path43 = require("node:path");
57260
57547
  init_cli_shared();
57261
57548
  init_clean_exit();
57262
57549
  init_client_version();
@@ -57271,7 +57558,7 @@ function resolveReleaseBumpIntent(raw) {
57271
57558
  }
57272
57559
  function readRepoVersion() {
57273
57560
  try {
57274
- 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;
57275
57562
  } catch {
57276
57563
  return void 0;
57277
57564
  }
@@ -57381,8 +57668,8 @@ function releaseProgressVerdict(status, subject = "Release") {
57381
57668
  }
57382
57669
 
57383
57670
  // src/suite-pin.ts
57384
- var import_promises6 = require("node:fs/promises");
57385
- var import_node_path43 = require("node:path");
57671
+ var import_promises7 = require("node:fs/promises");
57672
+ var import_node_path44 = require("node:path");
57386
57673
  var SuitePinError = class _SuitePinError extends Error {
57387
57674
  diagnostic;
57388
57675
  constructor(repo, tag, error) {
@@ -57450,8 +57737,8 @@ async function openSuiteCutPinPr(deps, input) {
57450
57737
  if (input.carriedOnly) return { status: "unchanged" };
57451
57738
  throw new Error("pins already match without a merged cut PR \u2014 provenance unverified");
57452
57739
  }
57453
- await (0, import_promises6.mkdir)((0, import_node_path43.join)(deps.root, "tmp"), { recursive: true });
57454
- 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-"));
57455
57742
  const run = (file, args) => deps.run(file, args, scratch);
57456
57743
  await run("git", ["clone", "--quiet", "--branch", prs.length ? branch : "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
57457
57744
  if (prs.length) {
@@ -57463,8 +57750,8 @@ async function openSuiteCutPinPr(deps, input) {
57463
57750
  await run("git", ["switch", "-c", branch]);
57464
57751
  }
57465
57752
  for (const stage of ["rc", "main"]) {
57466
- const path2 = (0, import_node_path43.join)(scratch, `${stage}-pins.json`);
57467
- 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] }))));
57468
57755
  await run("node", ["scripts/pin-modules.mjs", "--stage", stage, "--pins", path2]);
57469
57756
  }
57470
57757
  await run("git", ["add", "seed/modules.json"]);
@@ -57494,7 +57781,7 @@ async function openSuiteCutPinPr(deps, input) {
57494
57781
  } catch (e) {
57495
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)`);
57496
57783
  } finally {
57497
- 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 });
57498
57785
  }
57499
57786
  }
57500
57787
  async function openSuiteRestorePinPr(deps, input) {
@@ -57516,13 +57803,13 @@ async function openSuiteRestorePinPr(deps, input) {
57516
57803
  }
57517
57804
  });
57518
57805
  if (!todo.length) return void 0;
57519
- await (0, import_promises6.mkdir)((0, import_node_path43.join)(deps.root, "tmp"), { recursive: true });
57520
- 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-"));
57521
57808
  const run = (file, args) => deps.run(file, args, scratch);
57522
57809
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
57523
57810
  await run("git", ["switch", "-c", branch]);
57524
- const path2 = (0, import_node_path43.join)(scratch, "main-pins.json");
57525
- 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 }))));
57526
57813
  await run("node", ["scripts/pin-modules.mjs", "--stage", "main", "--pins", path2]);
57527
57814
  await run("git", ["add", "seed/modules.json"]);
57528
57815
  await run("git", ["commit", "-m", `Restore main pins of abandoned suite cut ${input.cut.slice(0, 12)} (#7758)`]);
@@ -57547,7 +57834,7 @@ async function openSuiteRestorePinPr(deps, input) {
57547
57834
  } catch (e) {
57548
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)`);
57549
57836
  } finally {
57550
- 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 });
57551
57838
  }
57552
57839
  }
57553
57840
  async function openSuitePinPr(deps, input) {
@@ -57595,8 +57882,8 @@ async function openSuitePinPr(deps, input) {
57595
57882
  if (newer.length) return { status: "superseded", pr: newer[0].url, url: pin };
57596
57883
  const open2 = onBranch.find((p) => p.state === "OPEN");
57597
57884
  if (open2 && tagOf(open2.title ?? "") === tag) return { status: "pending", pr: open2.url, url: pin };
57598
- await (0, import_promises6.mkdir)((0, import_node_path43.join)(deps.root, "tmp"), { recursive: true });
57599
- 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-"));
57600
57887
  const run = (file, args) => deps.run(file, args, scratch);
57601
57888
  await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
57602
57889
  await run("git", ["switch", "-c", branch]);
@@ -57623,7 +57910,7 @@ async function openSuitePinPr(deps, input) {
57623
57910
  } finally {
57624
57911
  if (scratch) {
57625
57912
  try {
57626
- await (0, import_promises6.rm)(scratch, { recursive: true, force: true });
57913
+ await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
57627
57914
  } catch (e) {
57628
57915
  const cleanupFailure = failure ?? new SuitePinError(repo, tag, e);
57629
57916
  cleanupFailure.diagnostic.cleanupFailed = true;
@@ -57649,7 +57936,7 @@ function prTitleRefusal(title) {
57649
57936
  // src/command-register-collaboration.ts
57650
57937
  var import_node_child_process18 = require("node:child_process");
57651
57938
  var import_node_fs54 = require("node:fs");
57652
- var import_promises8 = require("node:fs/promises");
57939
+ var import_promises9 = require("node:fs/promises");
57653
57940
  init_clean_exit();
57654
57941
  init_cli_shared();
57655
57942
  init_error_codes();
@@ -57672,11 +57959,11 @@ function spawnDetachedSelf(args, deps, opts = {}) {
57672
57959
  }
57673
57960
 
57674
57961
  // src/command-register-collaboration.ts
57675
- var import_node_path50 = require("node:path");
57962
+ var import_node_path51 = require("node:path");
57676
57963
  init_house_map();
57677
57964
 
57678
57965
  // src/issue-body.ts
57679
- var import_node_os23 = require("node:os");
57966
+ var import_node_os24 = require("node:os");
57680
57967
  init_error_codes();
57681
57968
  var TextArgError = class extends Error {
57682
57969
  constructor(message2, code, offendingFlag) {
@@ -57689,7 +57976,7 @@ var TextArgError = class extends Error {
57689
57976
  offendingFlag;
57690
57977
  };
57691
57978
  function emptyStdinMessage(fileFlag) {
57692
- if ((0, import_node_os23.platform)() === "win32") {
57979
+ if ((0, import_node_os24.platform)() === "win32") {
57693
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)`;
57694
57981
  }
57695
57982
  return `${fileFlag} - read empty stdin (nothing piped \u2014 pass a heredoc/pipe, or ${fileFlag} <path>)`;
@@ -57790,7 +58077,7 @@ init_github_quota();
57790
58077
 
57791
58078
  // src/issue-commands.ts
57792
58079
  var import_node_fs46 = require("node:fs");
57793
- var import_node_crypto22 = require("node:crypto");
58080
+ var import_node_crypto23 = require("node:crypto");
57794
58081
  init_cli_shared();
57795
58082
  init_clean_exit();
57796
58083
  init_error_codes();
@@ -58267,7 +58554,7 @@ function rowIdempotencyKey(batchKey, spec) {
58267
58554
  const identity = `${spec.type}
58268
58555
  ${spec.title.trim()}
58269
58556
  ${spec.body ?? ""}`;
58270
- 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);
58271
58558
  return `${batchKey}:${hash}`;
58272
58559
  }
58273
58560
  var BATCH_SPEC_KEYS = /* @__PURE__ */ new Set(["type", "title", "body", "priority", "labels", "label", "parent", "repo", "surface"]);
@@ -58727,7 +59014,7 @@ ${lines2}`, {
58727
59014
 
58728
59015
  // src/post-merge-recon.ts
58729
59016
  var import_node_fs47 = require("node:fs");
58730
- var import_node_path44 = require("node:path");
59017
+ var import_node_path45 = require("node:path");
58731
59018
 
58732
59019
  // src/cross-repo-filing-issue.ts
58733
59020
  init_github_client();
@@ -58897,7 +59184,7 @@ function buildPostMergeReconRecovery(input) {
58897
59184
  }
58898
59185
  function writePostMergeReconRecovery(cwd, recovery) {
58899
59186
  const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
58900
- (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 });
58901
59188
  (0, import_node_fs47.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
58902
59189
  `, "utf8");
58903
59190
  return path2;
@@ -58937,7 +59224,7 @@ function postMergeReconWarnings(input) {
58937
59224
  }
58938
59225
 
58939
59226
  // src/pr-commands.ts
58940
- var import_promises7 = require("node:fs/promises");
59227
+ var import_promises8 = require("node:fs/promises");
58941
59228
  init_cli_shared();
58942
59229
 
58943
59230
  // src/api-read.ts
@@ -60430,10 +60717,10 @@ function registerPrLifecycleCommands(program3) {
60430
60717
  let body;
60431
60718
  try {
60432
60719
  if (o.title || o.titleFile) {
60433
- 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 });
60434
60721
  }
60435
60722
  if (o.body || o.bodyFile) {
60436
- 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 });
60437
60724
  }
60438
60725
  } catch (e) {
60439
60726
  return fail(`pr edit: ${e.message}`);
@@ -60464,7 +60751,7 @@ function registerPrLifecycleCommands(program3) {
60464
60751
  }
60465
60752
  let body;
60466
60753
  try {
60467
- 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 });
60468
60755
  } catch (e) {
60469
60756
  return fail(`pr comment: ${e.message}`);
60470
60757
  }
@@ -60749,8 +61036,8 @@ function registerPrLifecycleCommands(program3) {
60749
61036
  // src/review-verdict.ts
60750
61037
  var import_node_child_process15 = require("node:child_process");
60751
61038
  var import_node_fs49 = require("node:fs");
60752
- var import_node_os24 = require("node:os");
60753
- var import_node_path45 = require("node:path");
61039
+ var import_node_os25 = require("node:os");
61040
+ var import_node_path46 = require("node:path");
60754
61041
  init_cli_shared();
60755
61042
  var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
60756
61043
  var REVIEW_VERDICTS = ["PROCEED", "CORRECT", "ESCALATE"];
@@ -60915,8 +61202,8 @@ async function readPrIssueComments(number, repo) {
60915
61202
  return comments;
60916
61203
  }
60917
61204
  async function postPrCommentFromFile(number, repo, body) {
60918
- const dir = (0, import_node_fs49.mkdtempSync)((0, import_node_path45.join)((0, import_node_os24.tmpdir)(), "mmi-review-verdict-"));
60919
- 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");
60920
61207
  try {
60921
61208
  (0, import_node_fs49.writeFileSync)(path2, body, "utf8");
60922
61209
  const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
@@ -61412,17 +61699,17 @@ function createPreparationDeps(input, io = {}) {
61412
61699
 
61413
61700
  // src/worktree-residue-sweep.ts
61414
61701
  var import_node_fs53 = require("node:fs");
61415
- var import_node_path49 = require("node:path");
61702
+ var import_node_path50 = require("node:path");
61416
61703
 
61417
61704
  // src/worktree-merge-cleanup.ts
61418
61705
  var import_node_fs52 = require("node:fs");
61419
- var import_node_path48 = require("node:path");
61706
+ var import_node_path49 = require("node:path");
61420
61707
  init_cli_shared();
61421
61708
 
61422
61709
  // src/stage-runner.ts
61423
61710
  var import_node_child_process17 = require("node:child_process");
61424
61711
  var import_node_fs51 = require("node:fs");
61425
- var import_node_path47 = require("node:path");
61712
+ var import_node_path48 = require("node:path");
61426
61713
  var import_node_net = require("node:net");
61427
61714
  var import_node_util5 = require("node:util");
61428
61715
 
@@ -61433,7 +61720,7 @@ function normalizeEol2(s) {
61433
61720
 
61434
61721
  // src/env-detection.ts
61435
61722
  var import_node_fs50 = require("node:fs");
61436
- var import_node_path46 = require("node:path");
61723
+ var import_node_path47 = require("node:path");
61437
61724
  var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
61438
61725
  function isEnvBaseName(name) {
61439
61726
  return name.toLowerCase() === ".env";
@@ -61451,13 +61738,13 @@ function findEnvFiles(root) {
61451
61738
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
61452
61739
  if (entry.isDirectory()) {
61453
61740
  if (SKIPPED_DIRS.has(entry.name)) continue;
61454
- walk2((0, import_node_path46.join)(dir, entry.name), relPath);
61741
+ walk2((0, import_node_path47.join)(dir, entry.name), relPath);
61455
61742
  continue;
61456
61743
  }
61457
61744
  if (isEnvBaseName(entry.name)) {
61458
61745
  let isDir = false;
61459
61746
  try {
61460
- 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();
61461
61748
  } catch {
61462
61749
  }
61463
61750
  if (!isDir) found.push(relPath);
@@ -61596,10 +61883,10 @@ var DOCKER_TIMEOUT_MS = 15e3;
61596
61883
  function stageBash() {
61597
61884
  if (process.platform !== "win32") return "bash";
61598
61885
  const configured = process.env.SHELL;
61599
- 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;
61600
61887
  const candidates = [
61601
- (0, import_node_path47.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
61602
- ...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")] : []
61603
61890
  ];
61604
61891
  const bash = candidates.find((path2) => (0, import_node_fs51.existsSync)(path2));
61605
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.");
@@ -61739,7 +62026,7 @@ function appendForceRecreate(up) {
61739
62026
  return `${up.trimEnd()} --force-recreate`;
61740
62027
  }
61741
62028
  function stageStatePath(cwd = process.cwd()) {
61742
- return (0, import_node_path47.join)(cwd, "tmp", "stage", "state.json");
62029
+ return (0, import_node_path48.join)(cwd, "tmp", "stage", "state.json");
61743
62030
  }
61744
62031
  function normPath(path2) {
61745
62032
  return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
@@ -61956,7 +62243,7 @@ function stageProcessEnv(stagePort, extraEnv) {
61956
62243
  }
61957
62244
  function composeResolvesPort(cwd) {
61958
62245
  if (process.env.PORT) return true;
61959
- const envFile = (0, import_node_path47.join)(cwd, ".env");
62246
+ const envFile = (0, import_node_path48.join)(cwd, ".env");
61960
62247
  return (0, import_node_fs51.existsSync)(envFile) && envFileKeys((0, import_node_fs51.readFileSync)(envFile, "utf8")).has("PORT");
61961
62248
  }
61962
62249
  function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
@@ -61972,13 +62259,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
61972
62259
  function stageComposeFiles(cwd) {
61973
62260
  const files = ["docker-compose.yml"];
61974
62261
  for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
61975
- 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);
61976
62263
  }
61977
62264
  return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
61978
62265
  }
61979
62266
  async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
61980
62267
  const keys = Object.keys(vaultEnvMerge ?? {});
61981
- 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 {};
61982
62269
  let configJson;
61983
62270
  try {
61984
62271
  const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
@@ -61994,15 +62281,15 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
61994
62281
  }
61995
62282
  const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys, runtimeEnvExcludes(configJson), runtimeEnvSelects(configJson));
61996
62283
  if (!body) return {};
61997
- const overridePath = (0, import_node_path47.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
61998
- (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 });
61999
62286
  (0, import_node_fs51.writeFileSync)(overridePath, body, "utf8");
62000
62287
  return stageComposeFileEnv(stageComposeFiles(cwd));
62001
62288
  }
62002
62289
  async function ensureStageRuntimeEnv(config, opts, cwd) {
62003
62290
  if (!config.ensureEnv) return;
62004
- const target = (0, import_node_path47.join)(cwd, config.ensureEnv.target);
62005
- 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);
62006
62293
  if (!(0, import_node_fs51.existsSync)(target) && (0, import_node_fs51.existsSync)(example)) {
62007
62294
  (0, import_node_fs51.copyFileSync)(example, target);
62008
62295
  } else if ((0, import_node_fs51.existsSync)(target) && (0, import_node_fs51.existsSync)(example)) {
@@ -62356,7 +62643,7 @@ function normPath2(p) {
62356
62643
  return p.replace(/\\/g, "/").replace(/\/+$/, "");
62357
62644
  }
62358
62645
  function unlinkNodeModulesJunction(wtPath) {
62359
- const nm = (0, import_node_path48.join)(wtPath, "node_modules");
62646
+ const nm = (0, import_node_path49.join)(wtPath, "node_modules");
62360
62647
  try {
62361
62648
  if ((0, import_node_fs52.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs52.rmdirSync)(nm);
62362
62649
  return { ok: true };
@@ -62493,7 +62780,7 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
62493
62780
  }
62494
62781
  async function listNestedIgnoredNodeModules(wtPath, execGit) {
62495
62782
  const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
62496
- 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)));
62497
62784
  }
62498
62785
  function safeRemoveTree(path2) {
62499
62786
  const stat4 = (0, import_node_fs52.lstatSync)(path2);
@@ -62506,7 +62793,7 @@ function safeRemoveTree(path2) {
62506
62793
  return;
62507
62794
  }
62508
62795
  if (stat4.isDirectory()) {
62509
- 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));
62510
62797
  (0, import_node_fs52.rmdirSync)(path2);
62511
62798
  return;
62512
62799
  }
@@ -62514,7 +62801,7 @@ function safeRemoveTree(path2) {
62514
62801
  }
62515
62802
  async function removeWorktreeNodeModules(wtPath) {
62516
62803
  try {
62517
- safeRemoveTree((0, import_node_path48.join)(wtPath, "node_modules"));
62804
+ safeRemoveTree((0, import_node_path49.join)(wtPath, "node_modules"));
62518
62805
  return { ok: true };
62519
62806
  } catch (e) {
62520
62807
  if (e.code === "ENOENT") return { ok: true };
@@ -62559,7 +62846,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
62559
62846
  return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
62560
62847
  }
62561
62848
  for (const entry of entries) {
62562
- const child2 = (0, import_node_path48.join)(dir, entry.name);
62849
+ const child2 = (0, import_node_path49.join)(dir, entry.name);
62563
62850
  if (entry.isSymbolicLink()) {
62564
62851
  let target = "";
62565
62852
  try {
@@ -62886,7 +63173,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
62886
63173
  const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
62887
63174
  if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
62888
63175
  unlinkedReparsePoints.push(...preHelperGuard.unlinked);
62889
- if (pathExists((0, import_node_path48.join)(wtPath, "node_modules"))) {
63176
+ if (pathExists((0, import_node_path49.join)(wtPath, "node_modules"))) {
62890
63177
  const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
62891
63178
  if (!nmRemoved.ok) {
62892
63179
  report.worktree = {
@@ -63022,35 +63309,35 @@ function renderPrMergeCleanupLines(cleanup) {
63022
63309
  // src/worktree-residue-sweep.ts
63023
63310
  var RESIDUE_LEDGER_FILE = "mmi-worktree-residue.json";
63024
63311
  function canonicalWorktreeRoot(primary) {
63025
- 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));
63026
63313
  }
63027
63314
  function lastSegment(p) {
63028
- 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);
63029
63316
  }
63030
63317
  function readProvenance(folder, gitCommonDir, exists) {
63031
63318
  const found = {
63032
63319
  path: folder,
63033
63320
  gitdirPresent: false,
63034
- registrationId: (0, import_node_path49.basename)(folder),
63321
+ registrationId: (0, import_node_path50.basename)(folder),
63035
63322
  registrationPresent: false
63036
63323
  };
63037
63324
  try {
63038
- 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"));
63039
63326
  if (pointer) {
63040
63327
  const target = pointer[1];
63041
- 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);
63042
63329
  found.gitdirPresent = exists(found.gitdir);
63043
63330
  found.registrationId = lastSegment(found.gitdir);
63044
63331
  }
63045
63332
  } catch {
63046
63333
  }
63047
63334
  try {
63048
- 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));
63049
63336
  } catch {
63050
63337
  }
63051
63338
  if (found.gitdir && found.gitdirPresent) {
63052
63339
  try {
63053
- 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();
63054
63341
  const branch = /^ref:\s*(.+?)\s*$/.exec(head);
63055
63342
  if (branch) found.head = branch[1].startsWith("refs/heads/") ? branch[1].slice("refs/heads/".length) : `ref ${branch[1]}`;
63056
63343
  else if (/^[0-9a-f]{7,64}$/i.test(head)) found.head = `detached ${head.slice(0, 12)}`;
@@ -63069,7 +63356,7 @@ function norm2(p) {
63069
63356
  return process.platform === "win32" ? s.toLowerCase() : s;
63070
63357
  }
63071
63358
  function residueLedgerPath(gitCommonDir) {
63072
- return (0, import_node_path49.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
63359
+ return (0, import_node_path50.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
63073
63360
  }
63074
63361
  function readPaths(file, deps) {
63075
63362
  try {
@@ -63082,7 +63369,7 @@ function readPaths(file, deps) {
63082
63369
  function writePaths(file, paths, deps) {
63083
63370
  try {
63084
63371
  const write = deps.writeLedger ?? ((f, t) => {
63085
- (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 });
63086
63373
  (0, import_node_fs53.writeFileSync)(f, t, "utf8");
63087
63374
  });
63088
63375
  write(file, `${JSON.stringify([...new Set(paths)], null, 1)}
@@ -63142,7 +63429,7 @@ async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
63142
63429
  } catch {
63143
63430
  }
63144
63431
  for (const name of children) {
63145
- const child2 = (0, import_node_path49.join)(root, name);
63432
+ const child2 = (0, import_node_path50.join)(root, name);
63146
63433
  const key = norm2(child2);
63147
63434
  if (live.has(key) || key === primary || keptKeys.has(key) || !isDir(child2)) continue;
63148
63435
  let entries;
@@ -63194,10 +63481,10 @@ function argvWantsJson2() {
63194
63481
  return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
63195
63482
  }
63196
63483
  function hubRoot() {
63197
- const fromPkg = (0, import_node_path50.join)(__dirname, "..", "..");
63484
+ const fromPkg = (0, import_node_path51.join)(__dirname, "..", "..");
63198
63485
  const marker = "skills/bootstrap/seeds/manifest.json";
63199
- if ((0, import_node_fs54.existsSync)((0, import_node_path50.join)(fromPkg, marker))) return fromPkg;
63200
- 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();
63201
63488
  return null;
63202
63489
  }
63203
63490
  function ciAuditDeps() {
@@ -63209,7 +63496,7 @@ function ciAuditDeps() {
63209
63496
  getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
63210
63497
  readSeedFile: (path2) => {
63211
63498
  if (!root) return null;
63212
- const fullPath = (0, import_node_path50.join)(root, path2);
63499
+ const fullPath = (0, import_node_path51.join)(root, path2);
63213
63500
  return (0, import_node_fs54.existsSync)(fullPath) ? (0, import_node_fs54.readFileSync)(fullPath, "utf8") : null;
63214
63501
  }
63215
63502
  };
@@ -63338,6 +63625,24 @@ async function attachToProject(issueNumber, repo, priority) {
63338
63625
  }
63339
63626
  return boardAttachRateLimitedReceipt(resetEpochSeconds);
63340
63627
  }
63628
+ const authority = contentId ? await attachOnAuthorityRefusal(detail, cfg, contentId) : void 0;
63629
+ if (authority && "projectItemId" in authority) {
63630
+ if (priority) {
63631
+ try {
63632
+ await setBoardItemPriority(defaultGitHubClient(), cfg, authority.projectItemId, priority);
63633
+ } catch (pe) {
63634
+ const perr = pe;
63635
+ process.stderr.write(`warning: issue #${issueNumber} board Priority not set: ${(perr.stderr || perr.message || String(pe)).trim()}
63636
+ `);
63637
+ }
63638
+ }
63639
+ return { projectItemId: authority.projectItemId, onBoard: true, credential: "app_installation" };
63640
+ }
63641
+ if (authority) {
63642
+ process.stderr.write(`warning: issue #${issueNumber} created but NOT added to the project board: ${authority.warning}
63643
+ `);
63644
+ return { onBoard: false };
63645
+ }
63341
63646
  process.stderr.write(`warning: issue #${issueNumber} created but NOT added to the project board: ${detail}
63342
63647
  `);
63343
63648
  return { onBoard: false };
@@ -63416,7 +63721,7 @@ function registerCollaborationCommands(program3) {
63416
63721
  try {
63417
63722
  title = await resolveIssueTitle(
63418
63723
  { title: opts.title, titleFile: opts.titleFile },
63419
- { readFile: import_promises8.readFile, readStdin }
63724
+ { readFile: import_promises9.readFile, readStdin }
63420
63725
  );
63421
63726
  } catch (e) {
63422
63727
  return fail(
@@ -63470,8 +63775,8 @@ function registerCollaborationCommands(program3) {
63470
63775
  let surfaceInferred;
63471
63776
  try {
63472
63777
  issueType = resolveCreateType(o.type, "issue create", o.label);
63473
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
63474
- 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 });
63475
63780
  if (o.idempotencyKey) body = appendIdempotencyMarker(body, o.idempotencyKey);
63476
63781
  priority = resolveCreatePriority(o.priority, "issue create");
63477
63782
  extraLabels = [...o.label ?? []];
@@ -63786,7 +64091,7 @@ function registerCollaborationCommands(program3) {
63786
64091
  }
63787
64092
  let body;
63788
64093
  try {
63789
- 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 });
63790
64095
  } catch (e) {
63791
64096
  return fail(`issue comment: ${e.message}`);
63792
64097
  }
@@ -63865,8 +64170,8 @@ ${list}`);
63865
64170
  let title;
63866
64171
  const sourceRepo = o.repo ?? await resolveRepo(void 0);
63867
64172
  try {
63868
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
63869
- 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 });
63870
64175
  priority = resolveCreatePriority(o.priority, "report");
63871
64176
  if (!ISSUE_TYPES.includes(o.type)) {
63872
64177
  throw new Error(`unknown issue type "${o.type}" \u2014 expected one of: ${ISSUE_TYPES.join(", ")}`);
@@ -63920,8 +64225,8 @@ ${list}`);
63920
64225
  let args;
63921
64226
  try {
63922
64227
  skill = assertSkillName(o.skill);
63923
- rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
63924
- 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 });
63925
64230
  title = buildSkillLessonTitle(skill, rawTitle);
63926
64231
  priority = resolveCreatePriority(o.priority, "skill-lesson");
63927
64232
  body = buildSkillLessonBody(rawBody, sourceRepo, pluginSha);
@@ -63982,8 +64287,8 @@ ${list}`);
63982
64287
  let body;
63983
64288
  let title;
63984
64289
  try {
63985
- title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
63986
- 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 });
63987
64292
  } catch (e) {
63988
64293
  return fail(`pr create: ${e.message}`, e instanceof TextArgError ? { code: e.code, offending_flag: e.offendingFlag } : void 0);
63989
64294
  }
@@ -64077,11 +64382,11 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64077
64382
  }
64078
64383
  });
64079
64384
  async function listCiWorkflowPaths(cwd = process.cwd()) {
64080
- const wfDir = (0, import_node_path50.join)(cwd, ".github", "workflows");
64385
+ const wfDir = (0, import_node_path51.join)(cwd, ".github", "workflows");
64081
64386
  if (!(0, import_node_fs54.existsSync)(wfDir)) return [];
64082
64387
  return (0, import_node_fs54.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
64083
64388
  try {
64084
- 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"));
64085
64390
  } catch {
64086
64391
  return true;
64087
64392
  }
@@ -64336,7 +64641,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64336
64641
  }
64337
64642
  class PrHeadBehindBaseError extends Error {
64338
64643
  }
64339
- 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) => {
64340
64645
  const timeoutMinutes = opts.timeout === void 0 ? void 0 : Number(opts.timeout);
64341
64646
  if (timeoutMinutes !== void 0 && !(timeoutMinutes > 0)) return fail("pr land: --timeout must be a positive number of minutes");
64342
64647
  if (opts.abandonAdmission) {
@@ -64677,7 +64982,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64677
64982
  const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
64678
64983
  let foreignCheckout;
64679
64984
  if (foreignCwd) {
64680
- 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]);
64681
64986
  const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
64682
64987
  if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
64683
64988
  const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
@@ -64911,7 +65216,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
64911
65216
  let residueSweep;
64912
65217
  if (!(foreignCwd && !foreignCheckout)) {
64913
65218
  try {
64914
- 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());
64915
65220
  residueSweep = await sweepWorktreeResidue(gitCommonDir, beforeWorktrees.map((w) => w.path));
64916
65221
  } catch {
64917
65222
  }
@@ -65131,7 +65436,7 @@ function trainGitArgs(args) {
65131
65436
  async function announceSummaryLineCountRefusal(path2) {
65132
65437
  let content;
65133
65438
  try {
65134
- content = await (0, import_promises9.readFile)(path2, "utf8");
65439
+ content = await (0, import_promises10.readFile)(path2, "utf8");
65135
65440
  } catch (e) {
65136
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`;
65137
65442
  }
@@ -65143,7 +65448,7 @@ async function announceSummaryLineCountRefusal(path2) {
65143
65448
  async function announceSummaryRefusal(path2, isHub = false, isWorkSuite = false) {
65144
65449
  let lines2;
65145
65450
  try {
65146
- lines2 = summaryFileLines(await (0, import_promises9.readFile)(path2, "utf8"));
65451
+ lines2 = summaryFileLines(await (0, import_promises10.readFile)(path2, "utf8"));
65147
65452
  } catch (e) {
65148
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`;
65149
65454
  }
@@ -65281,8 +65586,8 @@ function trainApplyDeps() {
65281
65586
  }
65282
65587
  return body.status;
65283
65588
  },
65284
- readFile: (path2) => (0, import_promises9.readFile)(path2, "utf8"),
65285
- removeFile: (path2) => (0, import_promises9.unlink)(path2),
65589
+ readFile: (path2) => (0, import_promises10.readFile)(path2, "utf8"),
65590
+ removeFile: (path2) => (0, import_promises10.unlink)(path2),
65286
65591
  // #6521/#6523: the project's own release channel AND releaseLanguage, read from registry META in ONE
65287
65592
  // checked read. Same shape as fetchEdgeDomains below: a FAILED read refuses by name so the announce
65288
65593
  // note reports a failed read, never a project that configured nothing.
@@ -66210,7 +66515,7 @@ function rcRunCauseFromLog(log) {
66210
66515
  function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
66211
66516
  return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
66212
66517
  }
66213
- 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");
66214
66519
  async function runSuiteMemberRcand(repo, previousRc, rcWasAbsent) {
66215
66520
  const deps = trainApplyDeps();
66216
66521
  deps.suiteCut = suiteCutContext(repo, SUITE_REPO);
@@ -66257,16 +66562,16 @@ async function rcandInCheckout(repo, deps, previousRc, rcWasAbsent) {
66257
66562
  }
66258
66563
  }
66259
66564
  function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
66260
- const recordPath = (0, import_node_path52.join)(suiteStateDir(root), "cut.json");
66261
- 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");
66262
66567
  const checkout = async (repo) => {
66263
66568
  if (repo === SUITE_REPO) return root;
66264
- const target = (0, import_node_path52.join)(base, repo.split("/")[1]);
66569
+ const target = (0, import_node_path53.join)(base, repo.split("/")[1]);
66265
66570
  if (!(0, import_node_fs55.existsSync)(target)) {
66266
66571
  (0, import_node_fs55.mkdirSync)(base, { recursive: true });
66267
66572
  await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
66268
66573
  }
66269
- 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`);
66270
66575
  const origin = await exec("git", ["remote", "get-url", "origin"], target);
66271
66576
  if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
66272
66577
  throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
@@ -66330,7 +66635,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
66330
66635
  if (repo === SUITE_REPO) return inTrain(repo, (deps) => rcandInCheckout(repo, deps, previousRc, rcWasAbsent));
66331
66636
  const target = await checkout(repo);
66332
66637
  return new Promise((resolveResult, reject2) => {
66333
- 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"] : []], {
66334
66639
  cwd: target,
66335
66640
  stdio: ["ignore", "inherit", "inherit", "ipc"],
66336
66641
  execArgv: []
@@ -66574,7 +66879,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
66574
66879
  if (parseSuiteMapping(body)) return;
66575
66880
  const dir = suiteStateDir(root);
66576
66881
  (0, import_node_fs55.mkdirSync)(dir, { recursive: true });
66577
- const file = (0, import_node_path52.join)(dir, `notes-${leadTag}.md`);
66882
+ const file = (0, import_node_path53.join)(dir, `notes-${leadTag}.md`);
66578
66883
  (0, import_node_fs55.writeFileSync)(file, `${body}
66579
66884
 
66580
66885
  ${suiteMappingBlock(leadTag, mapping)}`);
@@ -66951,8 +67256,8 @@ function registerJevCommands(program3) {
66951
67256
  // src/packages-adopt-export.ts
66952
67257
  var import_node_child_process20 = require("node:child_process");
66953
67258
  var import_node_fs57 = require("node:fs");
66954
- var import_node_os25 = require("node:os");
66955
- var import_node_path53 = require("node:path");
67259
+ var import_node_os26 = require("node:os");
67260
+ var import_node_path54 = require("node:path");
66956
67261
  var import_node_util6 = require("node:util");
66957
67262
  init_cli_shared();
66958
67263
 
@@ -67572,25 +67877,25 @@ function expectedFromRun(run, opts) {
67572
67877
  }
67573
67878
  async function adoptExport(opts, deps) {
67574
67879
  if (!/^sha256:[0-9a-f]{64}$/.test(opts.digest)) throw new Error("--digest must be sha256:<64 hex>, from the export run summary");
67575
- const packagePath = (0, import_node_path53.join)(opts.dir, "package.json");
67576
- 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");
67577
67882
  const packageText = (0, import_node_fs57.readFileSync)(packagePath, "utf8");
67578
67883
  const lockText = (0, import_node_fs57.readFileSync)(lockPath, "utf8");
67579
- 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-"));
67580
67885
  try {
67581
67886
  const run = JSON.parse((await deps.ghApi(`repos/${EXPORT_REPO}/actions/runs/${opts.run}`)).toString("utf8"));
67582
- (0, import_node_fs57.writeFileSync)((0, import_node_path53.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
67583
- (0, import_node_fs57.writeFileSync)((0, import_node_path53.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
67584
- (0, import_node_fs57.writeFileSync)((0, import_node_path53.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
67585
- 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");
67586
67891
  (0, import_node_fs57.writeFileSync)(script, package_export_default);
67587
67892
  await deps.python(script, ["verify", work, opts.ds, opts.screens]);
67588
- const verified = (0, import_node_path53.join)(work, "verified");
67589
- 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"))]));
67590
67895
  const plan = planAdoption(packageText, lockText, metadata);
67591
67896
  for (const { name } of plan.result.adopted) {
67592
67897
  const short3 = PACKAGES.find((p) => p.name === name).short;
67593
- 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);
67594
67899
  }
67595
67900
  (0, import_node_fs57.writeFileSync)(packagePath, plan.packageText);
67596
67901
  (0, import_node_fs57.writeFileSync)(lockPath, plan.lockText);
@@ -67780,8 +68085,8 @@ async function collectWaveStatus(deps) {
67780
68085
  init_github_client();
67781
68086
  init_cli_shared();
67782
68087
  var import_node_fs59 = require("node:fs");
67783
- var import_node_os26 = require("node:os");
67784
- var import_node_path54 = require("node:path");
68088
+ var import_node_os27 = require("node:os");
68089
+ var import_node_path55 = require("node:path");
67785
68090
  var GC_GH_TIMEOUT_MS3 = 2e4;
67786
68091
  var defaultStatusDeps = {
67787
68092
  repo: resolveRepo,
@@ -68000,10 +68305,10 @@ async function collectOnboardStatus(opts = {}) {
68000
68305
  else if (top) nextCommand = `mmi-cli oracle board claim ${top.number} # ${top.title}`;
68001
68306
  else nextCommand = "mmi-cli oracle board read \u2014 no claimable items found";
68002
68307
  }
68003
- const home = (0, import_node_os26.homedir)();
68308
+ const home = (0, import_node_os27.homedir)();
68004
68309
  const plugin = onboardPluginGate({
68005
- readKnown: () => readFileSyncSafe((0, import_node_path54.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs59.readFileSync),
68006
- 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)
68007
68312
  });
68008
68313
  return {
68009
68314
  guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
@@ -70640,7 +70945,7 @@ function registerConnectionsOauth(program3, deps) {
70640
70945
  }
70641
70946
 
70642
70947
  // src/schedules-commands.ts
70643
- var import_promises10 = require("node:fs/promises");
70948
+ var import_promises11 = require("node:fs/promises");
70644
70949
  init_clean_exit();
70645
70950
  init_github_client();
70646
70951
  init_cli_shared();
@@ -70820,9 +71125,9 @@ function registerSchedulesCommands(program3) {
70820
71125
  await failGraceful("org schedules --doc: refusing to regenerate the doc from an incomplete read (see warnings above).");
70821
71126
  return;
70822
71127
  }
70823
- const docText = await (0, import_promises10.readFile)(o.doc, "utf8");
71128
+ const docText = await (0, import_promises11.readFile)(o.doc, "utf8");
70824
71129
  const spliced = spliceDoc(docText, renderDocSection(entries, now.toISOString()));
70825
- await (0, import_promises10.writeFile)(o.doc, spliced, "utf8");
71130
+ await (0, import_promises11.writeFile)(o.doc, spliced, "utf8");
70826
71131
  reportParked(parkedLines);
70827
71132
  reportDrift(drift);
70828
71133
  console.log(`org schedules: wrote ${entries.length} entries into ${o.doc}`);
@@ -71135,7 +71440,7 @@ function registerSessionReport(program3) {
71135
71440
 
71136
71441
  // src/stage-commands.ts
71137
71442
  var import_node_fs60 = require("node:fs");
71138
- var import_node_path55 = require("node:path");
71443
+ var import_node_path56 = require("node:path");
71139
71444
  init_cli_shared();
71140
71445
  init_clean_exit();
71141
71446
 
@@ -71383,8 +71688,8 @@ function registerStageCommands(program3) {
71383
71688
  const repo = Array.isArray(project2?.repos) && typeof project2.repos[0] === "string" ? project2.repos[0] : slug;
71384
71689
  const resolution = decideStage({
71385
71690
  registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
71386
- hasCompose: (0, import_node_fs60.existsSync)((0, import_node_path55.join)(process.cwd(), "docker-compose.yml")),
71387
- 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")),
71388
71693
  repo
71389
71694
  });
71390
71695
  if (resolution.source === "derived" && resolution.derived) {
@@ -71676,21 +71981,21 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
71676
71981
  }
71677
71982
 
71678
71983
  // src/tenant-artifact.ts
71679
- var import_node_crypto23 = require("node:crypto");
71984
+ var import_node_crypto24 = require("node:crypto");
71680
71985
  var import_node_fs61 = require("node:fs");
71681
- var import_promises11 = require("node:fs/promises");
71682
- var import_node_path56 = require("node:path");
71986
+ var import_promises12 = require("node:fs/promises");
71987
+ var import_node_path57 = require("node:path");
71683
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}$/;
71684
71989
  var MAX_BYTES2 = 5 * 1024 * 1024 * 1024;
71685
71990
  async function sha256File(path2) {
71686
- const hash = (0, import_node_crypto23.createHash)("sha256");
71991
+ const hash = (0, import_node_crypto24.createHash)("sha256");
71687
71992
  for await (const chunk of (0, import_node_fs61.createReadStream)(path2)) hash.update(chunk);
71688
71993
  return hash.digest("hex");
71689
71994
  }
71690
71995
  async function putTenantArtifact(repo, stage, inputPath, deps) {
71691
71996
  if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
71692
- const path2 = (0, import_node_path56.resolve)(inputPath);
71693
- 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);
71694
71999
  if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
71695
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`);
71696
72001
  const sha2564 = await sha256File(path2);
@@ -72169,12 +72474,12 @@ async function resolveWhoami(deps) {
72169
72474
  }
72170
72475
 
72171
72476
  // src/command-register-developer.ts
72172
- var import_node_path63 = require("node:path");
72477
+ var import_node_path64 = require("node:path");
72173
72478
 
72174
72479
  // src/doc-refs-command-source.ts
72175
72480
  var import_node_child_process21 = require("node:child_process");
72176
72481
  var import_node_fs62 = require("node:fs");
72177
- var import_node_path57 = require("node:path");
72482
+ var import_node_path58 = require("node:path");
72178
72483
  var IN_PROCESS_SOURCE = "in-process";
72179
72484
  var BUNDLE_MANIFEST_TIMEOUT_MS = 12e4;
72180
72485
  var BUNDLE_MANIFEST_MAX_BUFFER = 64 * 1024 * 1024;
@@ -72196,7 +72501,7 @@ function inventoryFromManifest(manifest, source) {
72196
72501
  function readBundleManifest(bundle, exec3 = import_node_child_process21.execFileSync) {
72197
72502
  try {
72198
72503
  const text = exec3(process.execPath, [bundle, "commands", "--all", "--json"], {
72199
- cwd: (0, import_node_path57.dirname)(bundle),
72504
+ cwd: (0, import_node_path58.dirname)(bundle),
72200
72505
  encoding: "utf8",
72201
72506
  windowsHide: true,
72202
72507
  timeout: BUNDLE_MANIFEST_TIMEOUT_MS,
@@ -72212,16 +72517,16 @@ function readBundleManifest(bundle, exec3 = import_node_child_process21.execFile
72212
72517
  function isRunningBundle(bundle, argv1 = process.argv[1], platform2 = process.platform) {
72213
72518
  if (!argv1) return false;
72214
72519
  const norm3 = (path2) => {
72215
- const absolute = (0, import_node_path57.resolve)(path2);
72520
+ const absolute = (0, import_node_path58.resolve)(path2);
72216
72521
  return platform2 === "win32" ? absolute.toLowerCase() : absolute;
72217
72522
  };
72218
72523
  const running = norm3(argv1);
72219
- if (!["main.cjs", "index.cjs"].includes((0, import_node_path57.basename)(running))) return false;
72220
- 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));
72221
72526
  }
72222
72527
  function nameUnknownCommandSources(findings, source, root) {
72223
- const checkoutBundle = (0, import_node_path57.resolve)(root, "cli", "dist", "main.cjs");
72224
- 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>`" : "";
72225
72530
  for (const finding of findings) {
72226
72531
  if (finding.kind !== "unknown-command") continue;
72227
72532
  finding.commandSource = source;
@@ -72233,7 +72538,7 @@ function resolveCommandInventory(deps) {
72233
72538
  const read = deps.read ?? ((bundle) => readBundleManifest(bundle));
72234
72539
  const warnings = [];
72235
72540
  if (deps.from) {
72236
- 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);
72237
72542
  if (!exists(bundle)) {
72238
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)`);
72239
72544
  }
@@ -72243,7 +72548,7 @@ function resolveCommandInventory(deps) {
72243
72548
  }
72244
72549
  return { inventory: inventory2, warnings };
72245
72550
  }
72246
- 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");
72247
72552
  if (!exists(treeBundle)) {
72248
72553
  return { inventory: deps.inProcess(), warnings };
72249
72554
  }
@@ -72363,26 +72668,26 @@ async function executeWaveLand(plan, deps) {
72363
72668
 
72364
72669
  // src/dist-drift.ts
72365
72670
  var import_node_child_process22 = require("node:child_process");
72366
- var import_node_crypto25 = require("node:crypto");
72671
+ var import_node_crypto26 = require("node:crypto");
72367
72672
  var import_node_fs64 = require("node:fs");
72368
- var import_node_os27 = require("node:os");
72369
- var import_node_path59 = require("node:path");
72673
+ var import_node_os28 = require("node:os");
72674
+ var import_node_path60 = require("node:path");
72370
72675
 
72371
72676
  // ../scripts/distribution-digest.mjs
72372
- var import_node_crypto24 = require("node:crypto");
72677
+ var import_node_crypto25 = require("node:crypto");
72373
72678
  var import_node_fs63 = require("node:fs");
72374
- var import_node_path58 = require("node:path");
72679
+ var import_node_path59 = require("node:path");
72375
72680
  var slash = (value) => value.replaceAll("\\", "/");
72376
72681
  function repoPath(root, declaredPath, label) {
72377
- const absoluteRoot = (0, import_node_path58.resolve)(root);
72378
- const target = (0, import_node_path58.resolve)(root, declaredPath);
72379
- 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}`)) {
72380
72685
  throw new Error(`${label} ${declaredPath} escapes the repository root`);
72381
72686
  }
72382
72687
  return target;
72383
72688
  }
72384
72689
  function digestFiles(files) {
72385
- const hash = (0, import_node_crypto24.createHash)("sha256");
72690
+ const hash = (0, import_node_crypto25.createHash)("sha256");
72386
72691
  for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
72387
72692
  const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs63.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs63.readFileSync)(file.absolute);
72388
72693
  hash.update(file.relative, "utf8");
@@ -72413,7 +72718,7 @@ var DIST_ARTIFACTS = [
72413
72718
  ];
72414
72719
  var BOM_DIST_TREE_ID = "mmi-cli-dist";
72415
72720
  var ABSENT = "absent";
72416
- 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")}`;
72417
72722
  function artifactDrift(path2, committedBytes, rebuiltBytes) {
72418
72723
  const committed = committedBytes ? sha2563(committedBytes) : ABSENT;
72419
72724
  const rebuiltExpected = rebuiltBytes ? sha2563(rebuiltBytes) : ABSENT;
@@ -72491,7 +72796,7 @@ function walkFiles(root) {
72491
72796
  const files = [];
72492
72797
  const walk2 = (directory) => {
72493
72798
  for (const entry of (0, import_node_fs64.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
72494
- const child2 = (0, import_node_path59.join)(directory, entry.name);
72799
+ const child2 = (0, import_node_path60.join)(directory, entry.name);
72495
72800
  if (entry.isDirectory()) walk2(child2);
72496
72801
  else files.push(child2);
72497
72802
  }
@@ -72501,10 +72806,10 @@ function walkFiles(root) {
72501
72806
  }
72502
72807
  function bomPathFor(root) {
72503
72808
  try {
72504
- const registry2 = JSON.parse((0, import_node_fs64.readFileSync)((0, import_node_path59.join)(root, "surfaces.json"), "utf8"));
72505
- 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");
72506
72811
  } catch {
72507
- return (0, import_node_path59.join)(root, "distribution-bom.json");
72812
+ return (0, import_node_path60.join)(root, "distribution-bom.json");
72508
72813
  }
72509
72814
  }
72510
72815
  function rebuildTo(packageRoot, outDir) {
@@ -72517,28 +72822,28 @@ function rebuildTo(packageRoot, outDir) {
72517
72822
  });
72518
72823
  }
72519
72824
  function runDistStatus(root) {
72520
- 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-"));
72521
72826
  let overlayCount = 0;
72522
72827
  try {
72523
- const cliOut = (0, import_node_path59.join)(stage, "cli-dist");
72524
- const hubOut = (0, import_node_path59.join)(stage, "hub-dist");
72525
- rebuildTo((0, import_node_path59.join)(root, "cli"), cliOut);
72526
- 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);
72527
72832
  const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
72528
72833
  const rebuilt = (path2) => {
72529
72834
  const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
72530
- 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;
72531
72836
  };
72532
- const committed = (path2) => readOrNull((0, import_node_path59.join)(root, path2));
72533
- const tree = (path2) => readOrNull((0, import_node_path59.join)(root, path2));
72534
- const distRoot = (0, import_node_path59.join)(root, "cli", "dist");
72535
- 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("\\", "/")}`);
72536
72841
  const bom = JSON.parse((0, import_node_fs64.readFileSync)(bomPathFor(root), "utf8"));
72537
72842
  const digest = (entries) => {
72538
- const overlay = (0, import_node_path59.join)(stage, `overlay-${overlayCount++}`);
72843
+ const overlay = (0, import_node_path60.join)(stage, `overlay-${overlayCount++}`);
72539
72844
  for (const entry of entries) {
72540
- const target = (0, import_node_path59.join)(overlay, entry.path);
72541
- (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 });
72542
72847
  (0, import_node_fs64.writeFileSync)(target, entry.bytes);
72543
72848
  }
72544
72849
  return digestPackedFiles(overlay, entries.map((entry) => entry.path));
@@ -72550,7 +72855,7 @@ function runDistStatus(root) {
72550
72855
  }
72551
72856
 
72552
72857
  // src/doc-refs-live.ts
72553
- var import_node_path60 = require("node:path");
72858
+ var import_node_path61 = require("node:path");
72554
72859
  var concrete = (value) => !!value && !/[<>{}$]/.test(value);
72555
72860
  var liveOption = (tokens2, flag) => {
72556
72861
  const index = tokens2.indexOf(flag);
@@ -72623,7 +72928,7 @@ async function runLiveDocRefs(root, deps, live) {
72623
72928
  const offline = runDocRefs(root, { ...deps, runbooksOnly: true });
72624
72929
  const read = deps.readFile ?? readFileOrNull;
72625
72930
  const docs = Object.fromEntries((deps.listDocs ?? defaultListDocs)(root).flatMap((doc) => {
72626
- const body = read((0, import_node_path60.join)(root, doc));
72931
+ const body = read((0, import_node_path61.join)(root, doc));
72627
72932
  return body !== null && isRunbook(doc, body) && !deps.isIgnored?.([doc]).has(doc) ? [[doc, body]] : [];
72628
72933
  }));
72629
72934
  const remote = await checkRunbookLive(docs, live);
@@ -72672,13 +72977,13 @@ init_cli_shared();
72672
72977
  // src/edge-tunnel.ts
72673
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])?)+$/;
72674
72979
  var UPSTREAM_RE = /^https?:\/\/[^/\s]+(?::\d+)?(?:\/.*)?$/;
72675
- function tunnelNameFromHostname(hostname4) {
72676
- return hostname4.replace(/\./g, "-").slice(0, 63);
72980
+ function tunnelNameFromHostname(hostname5) {
72981
+ return hostname5.replace(/\./g, "-").slice(0, 63);
72677
72982
  }
72678
- function planInfraTunnel(hostname4, upstream) {
72679
- const host = hostname4.trim().toLowerCase();
72983
+ function planInfraTunnel(hostname5, upstream) {
72984
+ const host = hostname5.trim().toLowerCase();
72680
72985
  const origin = upstream.trim();
72681
- 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)}`);
72682
72987
  if (!UPSTREAM_RE.test(origin)) throw new Error(`invalid upstream ${JSON.stringify(upstream)} \u2014 expected http(s)://host:port`);
72683
72988
  const tunnelName = tunnelNameFromHostname(host);
72684
72989
  const configYaml = [
@@ -72833,8 +73138,8 @@ async function diagnoseHub(deps) {
72833
73138
  }
72834
73139
 
72835
73140
  // src/schedules-lift-command.ts
72836
- var import_promises12 = require("node:fs/promises");
72837
- var import_node_path61 = require("node:path");
73141
+ var import_promises13 = require("node:fs/promises");
73142
+ var import_node_path62 = require("node:path");
72838
73143
  init_clean_exit();
72839
73144
  init_cli_shared();
72840
73145
  var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
@@ -72856,14 +73161,14 @@ var RegistryUnreachableError = class extends Error {
72856
73161
  async function readWorkflowFiles(dir) {
72857
73162
  let names;
72858
73163
  try {
72859
- names = await (0, import_promises12.readdir)(dir);
73164
+ names = await (0, import_promises13.readdir)(dir);
72860
73165
  } catch {
72861
73166
  return [];
72862
73167
  }
72863
73168
  const files = [];
72864
73169
  for (const name of names.sort()) {
72865
73170
  if (!/\.ya?ml$/.test(name)) continue;
72866
- 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") });
72867
73172
  }
72868
73173
  return files;
72869
73174
  }
@@ -72947,7 +73252,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
72947
73252
  // src/spawn-policy-core.ts
72948
73253
  var import_node_child_process24 = require("node:child_process");
72949
73254
  var import_node_fs65 = require("node:fs");
72950
- var import_node_path62 = require("node:path");
73255
+ var import_node_path63 = require("node:path");
72951
73256
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
72952
73257
  var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
72953
73258
  var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
@@ -73033,7 +73338,7 @@ function runSpawnPolicy(root) {
73033
73338
  for (const file of files) {
73034
73339
  let raw;
73035
73340
  try {
73036
- 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");
73037
73342
  } catch {
73038
73343
  continue;
73039
73344
  }
@@ -73053,7 +73358,7 @@ function runSpawnPolicy(root) {
73053
73358
  function registerDeveloperCommands(program3) {
73054
73359
  const rules = program3.command("rules").description("org-managed .gitignore delivery");
73055
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) => {
73056
- const path2 = (0, import_node_path63.join)(process.cwd(), ".gitignore");
73361
+ const path2 = (0, import_node_path64.join)(process.cwd(), ".gitignore");
73057
73362
  const current = (0, import_node_fs66.existsSync)(path2) ? (0, import_node_fs66.readFileSync)(path2, "utf8") : null;
73058
73363
  const plan = planManagedGitignore(current);
73059
73364
  const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
@@ -73383,12 +73688,12 @@ ${r.stderr ?? ""}`).catch(() => "");
73383
73688
  var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
73384
73689
  var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
73385
73690
  function envHealLockPath(home) {
73386
- 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");
73387
73692
  }
73388
73693
  async function withEnvHealLock(what, run) {
73389
73694
  try {
73390
73695
  return await withFileLock(
73391
- envHealLockPath((0, import_node_os28.homedir)()),
73696
+ envHealLockPath((0, import_node_os29.homedir)()),
73392
73697
  { staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
73393
73698
  run
73394
73699
  );
@@ -73486,7 +73791,7 @@ function mmiDoctorDeps(opts = {}) {
73486
73791
  const configRoot = surfaceConfigRoot(surface);
73487
73792
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
73488
73793
  const plan = buildPluginCachePlan(
73489
- (0, import_node_os28.homedir)(),
73794
+ (0, import_node_os29.homedir)(),
73490
73795
  running,
73491
73796
  pluginCacheFsDeps(configRoot, () => 0),
73492
73797
  { configRoot, includeStaging: surface !== "codex" }
@@ -73514,7 +73819,7 @@ function mmiDoctorDeps(opts = {}) {
73514
73819
  const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
73515
73820
  const installed = installedActivePluginVersion(surface);
73516
73821
  const plan = buildPluginCachePlan(
73517
- (0, import_node_os28.homedir)(),
73822
+ (0, import_node_os29.homedir)(),
73518
73823
  running,
73519
73824
  pluginCacheFsDeps(configRoot, () => 0),
73520
73825
  { configRoot, includeStaging: surface !== "codex", installedVersion: installed }
@@ -73556,7 +73861,7 @@ function mmiDoctorDeps(opts = {}) {
73556
73861
  // has no generated routing index would
73557
73862
  // get a permanent — demanding an artifact it never asked for.
73558
73863
  docsIndexState: (root) => {
73559
- 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;
73560
73865
  const real = createDocsIndexDeps(root);
73561
73866
  let docs;
73562
73867
  const listDocs = () => docs ??= real.listDocs();
@@ -73565,7 +73870,7 @@ function mmiDoctorDeps(opts = {}) {
73565
73870
  },
73566
73871
  // #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
73567
73872
  healDocsIndex: (root) => {
73568
- 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 };
73569
73874
  const real = createDocsIndexDeps(root);
73570
73875
  let docs;
73571
73876
  const listDocs = () => docs ??= real.listDocs();
@@ -73948,7 +74253,16 @@ setGhWriteTokenProvider(() => {
73948
74253
  throw e;
73949
74254
  });
73950
74255
  });
73951
- setClaimWriteTokenProvider(() => mintFilingWriteToken(appActorDeps()).then((t) => t.token));
74256
+ var claimWriteToken;
74257
+ setClaimWriteTokenProvider(() => {
74258
+ if (process.env.MMI_ACTOR?.trim() === "app") {
74259
+ return mintFilingWriteToken(appActorDeps()).then((t) => t.token);
74260
+ }
74261
+ return claimWriteToken ??= mintFilingWriteToken(appActorDeps()).then((t) => t.token, (e) => {
74262
+ if (e instanceof AppActorError && e.code === "vault-denied") return void 0;
74263
+ throw e;
74264
+ });
74265
+ });
73952
74266
  setStatusWriteTokenProvider(() => mintStatusWriteToken(appActorDeps()));
73953
74267
  var registerPreAction = Reflect.get(program2, ["h", "ook"].join(""));
73954
74268
  registerPreAction.call(program2, "preAction", async (_thisCommand, actionCommand) => {
@@ -74787,16 +75101,16 @@ function ciAuditDeps2() {
74787
75101
  // gate re-seed step is skipped gracefully rather than failing mid-run.
74788
75102
  readSeedFile: (path2) => {
74789
75103
  if (!root) return null;
74790
- const fullPath = (0, import_node_path64.join)(root, path2);
75104
+ const fullPath = (0, import_node_path65.join)(root, path2);
74791
75105
  return (0, import_node_fs67.existsSync)(fullPath) ? (0, import_node_fs67.readFileSync)(fullPath, "utf8") : null;
74792
75106
  }
74793
75107
  };
74794
75108
  }
74795
75109
  function hubRoot2() {
74796
- const fromPkg = (0, import_node_path64.join)(__dirname, "..", "..");
75110
+ const fromPkg = (0, import_node_path65.join)(__dirname, "..", "..");
74797
75111
  const marker = "skills/bootstrap/seeds/manifest.json";
74798
- if ((0, import_node_fs67.existsSync)((0, import_node_path64.join)(fromPkg, marker))) return fromPkg;
74799
- 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();
74800
75114
  return null;
74801
75115
  }
74802
75116
  registerQueryCommands(program2);
@@ -75010,7 +75324,7 @@ function directoryBytes(path2) {
75010
75324
  return 0;
75011
75325
  }
75012
75326
  for (const entry of entries) {
75013
- const child2 = (0, import_node_path64.join)(path2, entry.name);
75327
+ const child2 = (0, import_node_path65.join)(path2, entry.name);
75014
75328
  if (entry.isDirectory()) total += directoryBytes(child2);
75015
75329
  else {
75016
75330
  try {
@@ -75040,7 +75354,7 @@ function pluginCacheFsDeps(configRoot, dirBytes) {
75040
75354
  dirBytes,
75041
75355
  listStagingDirs: (root) => (0, import_node_fs67.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
75042
75356
  try {
75043
- 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) };
75044
75358
  } catch {
75045
75359
  return { name: d.name, mtimeMs: Date.now() };
75046
75360
  }
@@ -75054,7 +75368,7 @@ function stagingApplyFsGuard(configRoot) {
75054
75368
  return {
75055
75369
  referencedPaths: () => readInstalledPluginRefs(configRoot),
75056
75370
  mtimeMs: (name) => {
75057
- const p = (0, import_node_path64.join)(stagingRoot, name);
75371
+ const p = (0, import_node_path65.join)(stagingRoot, name);
75058
75372
  if (!(0, import_node_fs67.existsSync)(p)) return null;
75059
75373
  try {
75060
75374
  return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs67.statSync)(q).mtimeMs);
@@ -75077,7 +75391,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
75077
75391
  return;
75078
75392
  }
75079
75393
  const plan = buildPluginCachePlan(
75080
- (0, import_node_os28.homedir)(),
75394
+ (0, import_node_os29.homedir)(),
75081
75395
  running,
75082
75396
  pluginCacheFsDeps(configRoot, directoryBytes),
75083
75397
  { withBytes: true, configRoot, includeStaging: surface !== "codex" }
@@ -75093,7 +75407,7 @@ program2.command("archive-prune").description("inventory worktree evidence archi
75093
75407
  let primary = o.repoRoot;
75094
75408
  if (!primary) {
75095
75409
  const common = await gitOut(["rev-parse", "--path-format=absolute", "--git-common-dir"]);
75096
- primary = common ? (0, import_node_path64.dirname)(common) : "";
75410
+ primary = common ? (0, import_node_path65.dirname)(common) : "";
75097
75411
  }
75098
75412
  if (!primary) {
75099
75413
  const detail = "archive-prune: not inside a git checkout (pass --repo-root <primary checkout>)";