@mutmutco/codex-plugin 4.5.111 → 4.5.113

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mmi",
3
- "version": "4.5.111",
3
+ "version": "4.5.113",
4
4
  "mmiCompat": "4.x",
5
5
  "description": "MMI workflow skills and org gates delivery.",
6
6
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -5851,42 +5851,11 @@ async function mintInstallationToken(deps) {
5851
5851
  async function pollTokenOrUndefined(deps) {
5852
5852
  try {
5853
5853
  return (await mintInstallationToken(deps)).token;
5854
- } catch {
5854
+ } catch (e) {
5855
+ if (e instanceof AppActorError && e.code === "mint-failed") throw e;
5855
5856
  return void 0;
5856
5857
  }
5857
5858
  }
5858
- var APP_POLL_HEADROOM_FRACTION = 0.4;
5859
- var APP_POLL_RESET_DEFAULT_MS = 36e5;
5860
- var appPollGuardState = {};
5861
- function appPollGuardSnapshot() {
5862
- return { ...appPollGuardState };
5863
- }
5864
- function appPollAllowsApp(nowMs) {
5865
- if (appPollGuardState.fallbackUntilMs !== void 0) {
5866
- if (nowMs < appPollGuardState.fallbackUntilMs) return false;
5867
- appPollGuardState = {};
5868
- }
5869
- const { remaining, limit } = appPollGuardState;
5870
- if (remaining === void 0 || limit === void 0 || limit <= 0) return true;
5871
- return remaining / limit >= APP_POLL_HEADROOM_FRACTION;
5872
- }
5873
- function latchAppPollFallback(nowMs) {
5874
- appPollGuardState.fallbackUntilMs = appPollGuardState.resetAtMs ?? nowMs + APP_POLL_RESET_DEFAULT_MS;
5875
- }
5876
- function noteAppPollResponse(headers, rateLimited, nowMs) {
5877
- if (headers.remaining !== void 0) appPollGuardState.remaining = headers.remaining;
5878
- if (headers.limit !== void 0) appPollGuardState.limit = headers.limit;
5879
- if (headers.resetSec !== void 0 && headers.resetSec > 0) appPollGuardState.resetAtMs = headers.resetSec * 1e3;
5880
- const { remaining, limit } = appPollGuardState;
5881
- const belowFloor = !rateLimited && remaining !== void 0 && limit !== void 0 && limit > 0 && remaining / limit < APP_POLL_HEADROOM_FRACTION;
5882
- const headroomUnverifiable = !rateLimited && (headers.remaining === void 0 || headers.limit === void 0);
5883
- if (rateLimited || belowFloor || headroomUnverifiable && appPollGuardState.resetAtMs !== void 0) {
5884
- latchAppPollFallback(nowMs);
5885
- }
5886
- }
5887
- function resetAppPollGuard() {
5888
- appPollGuardState = {};
5889
- }
5890
5859
  var notedIneligibleCommand = false;
5891
5860
  async function activateAppActor(commandPath3, env, mint, note = (line) => process.stderr.write(`${line}
5892
5861
  `)) {
@@ -6020,7 +5989,7 @@ function pollStateFromParsed(parsed) {
6020
5989
  return parsed === "error" ? "failure" : parsed;
6021
5990
  }
6022
5991
  var PR_MERGEABLE_UNKNOWN_POLL_RETRIES = 4;
6023
- var PR_MERGEABLE_UNKNOWN_POLL_MS = 3e3;
5992
+ var PR_MERGEABLE_UNKNOWN_POLL_MS = 15e3;
6024
5993
  async function resolveSettledMergeableState(pollMergeable, sleep2) {
6025
5994
  for (let attempt = 1; attempt <= PR_MERGEABLE_UNKNOWN_POLL_RETRIES; attempt++) {
6026
5995
  const state = await pollMergeable();
@@ -6078,7 +6047,7 @@ function pollIntervalMs(elapsedMs) {
6078
6047
  }
6079
6048
  var PR_CHECKS_TIMEOUT_MS = 30 * 6e4;
6080
6049
  var PR_CHECKS_SUCCESS_CONFIRMATIONS = 2;
6081
- var PR_CHECKS_CONFIRM_MS = 5e3;
6050
+ var PR_CHECKS_CONFIRM_MS = 3e4;
6082
6051
  var PR_CHECKS_FAILURE_CONFIRMATIONS = 2;
6083
6052
  var PR_CHECKS_RATELIMIT_FLOOR = 1e3;
6084
6053
  var PR_CHECKS_RATELIMIT_JITTER_MAX_MS = 5e3;
@@ -6324,15 +6293,21 @@ function lastRestPollSource() {
6324
6293
  function setPollTokenProvider(provider) {
6325
6294
  pollTokenProvider = provider;
6326
6295
  pollTokenOnce = void 0;
6327
- resetAppPollGuard();
6328
6296
  lastPollSource = void 0;
6329
6297
  observedPool.clear();
6330
6298
  }
6331
6299
  async function pollToken() {
6332
6300
  if (!pollTokenProvider) return void 0;
6333
- pollTokenOnce ??= pollTokenProvider().catch(() => void 0);
6301
+ pollTokenOnce ??= pollTokenProvider().catch((e) => {
6302
+ if (e instanceof AppActorError && e.code === "mint-failed") throw e;
6303
+ return void 0;
6304
+ });
6334
6305
  return pollTokenOnce;
6335
6306
  }
6307
+ async function ghReadEnv() {
6308
+ const appToken = await pollToken();
6309
+ return appToken ? { ...process.env, GH_TOKEN: appToken } : void 0;
6310
+ }
6336
6311
  var INCLUDED_HEADER_BLOCK = /^(?:\r?\n)?HTTP\/\d(?:\.\d)? (\d{3})[^\n]*\n(?:[^\n]+\n)*?\r?\n/gm;
6337
6312
  function parseIncludedOutput(out) {
6338
6313
  let status;
@@ -6373,11 +6348,6 @@ function describeRefusal(out) {
6373
6348
  return [parts.join(" "), text ? `"${text}"` : ""].filter(Boolean).join(" ") || "no rate-limit headers or message";
6374
6349
  }
6375
6350
  var etagCache = /* @__PURE__ */ new Map();
6376
- function appPoolDetail() {
6377
- const guard = appPollGuardSnapshot();
6378
- const counts = guard.remaining !== void 0 && guard.limit !== void 0 ? `App pool at ${guard.remaining}/${guard.limit}` : "App pool headroom unverified";
6379
- return guard.resetAtMs !== void 0 ? `${counts}, resets ${new Date(guard.resetAtMs).toISOString()}` : counts;
6380
- }
6381
6351
  var observedPool = /* @__PURE__ */ new Map();
6382
6352
  var OBSERVED_POOL_MAX_AGE_MS = 3 * 6e4;
6383
6353
  function notePoolHeaders(source, out, nowMs) {
@@ -6393,59 +6363,46 @@ function observedCorePool(source, nowMs) {
6393
6363
  }
6394
6364
  async function defaultGhApi(args) {
6395
6365
  const appToken = await pollToken();
6396
- let source = appToken && appPollAllowsApp(Date.now()) ? "app" : "user";
6397
- if (lastPollSource !== void 0 && lastPollSource !== source) {
6398
- console.warn(source === "user" ? `poll credential: ${appPoolDetail()} \u2014 below the ${APP_POLL_HEADROOM_FRACTION * 100}% App-poll headroom floor (#7843); REST poll reads switch to the ambient user token until the App pool resets` : "poll credential: App pool reset passed \u2014 REST poll reads return to the App installation token (#7843)");
6399
- }
6400
- for (; ; ) {
6401
- const key = `${source}\0${args.join("\0")}`;
6402
- const cached = etagCache.get(key);
6403
- let stdout;
6404
- try {
6405
- ({ stdout } = await execFileP("gh", ["api", "--include", ...cached ? ["-H", `If-None-Match: ${cached.etag}`] : [], ...args], {
6406
- timeout: REST_GH_TIMEOUT_MS,
6407
- // Only on the App source: passing `env` at all replaces the inherited environment wholesale,
6408
- // and `gh` needs the rest of it (PATH, GH_HOST, config home). Ambient rides the inherited env.
6409
- ...source === "app" && appToken ? { env: { ...process.env, GH_TOKEN: appToken } } : {}
6410
- }));
6411
- } catch (e) {
6412
- const out = e.stdout;
6413
- const errOut = typeof out === "string" ? out : void 0;
6414
- const status = errOut !== void 0 ? parseIncludedOutput(errOut).status : void 0;
6415
- if (errOut !== void 0) notePoolHeaders(source, errOut, Date.now());
6416
- if (cached && status === 304) {
6417
- lastPollSource = source;
6418
- return cached.body;
6419
- }
6420
- if (source === "app" && appToken && status === 403 && /Resource not accessible by integration/i.test(describeRefusal(errOut))) {
6421
- console.warn(`poll credential: App token lacks permission for this read (HTTP 403, response: ${describeRefusal(errOut)}) \u2014 this read uses the ambient user token; the App pool stays in use (#7978)`);
6422
- try {
6423
- const { stdout: userOut } = await execFileP("gh", ["api", "--include", ...args], { timeout: REST_GH_TIMEOUT_MS });
6424
- notePoolHeaders("user", userOut, Date.now());
6425
- return parseIncludedOutput(userOut).body;
6426
- } catch (userErr) {
6427
- const uo = userErr.stdout;
6428
- if (typeof uo === "string") notePoolHeaders("user", uo, Date.now());
6429
- throw userErr;
6430
- }
6431
- }
6432
- if (source === "app" && appToken && (status === 403 || status === 429)) {
6433
- noteAppPollResponse(parseRateLimitHeaders(errOut), true, Date.now());
6434
- console.warn(`poll credential: App pool refused the read (HTTP ${status}, ${appPoolDetail()}; response: ${describeRefusal(errOut)}) \u2014 REST poll reads switch to the ambient user token until the App pool resets (#7843)`);
6435
- lastPollSource = "user";
6436
- source = "user";
6437
- continue;
6366
+ const source = appToken ? "app" : "user";
6367
+ const key = `${source}\0${args.join("\0")}`;
6368
+ const cached = etagCache.get(key);
6369
+ let stdout;
6370
+ try {
6371
+ ({ stdout } = await execFileP("gh", ["api", "--include", ...cached ? ["-H", `If-None-Match: ${cached.etag}`] : [], ...args], {
6372
+ timeout: REST_GH_TIMEOUT_MS,
6373
+ // Only on the App source: passing `env` at all replaces the inherited environment wholesale,
6374
+ // and `gh` needs the rest of it (PATH, GH_HOST, config home). Ambient rides the inherited env.
6375
+ ...source === "app" && appToken ? { env: { ...process.env, GH_TOKEN: appToken } } : {}
6376
+ }));
6377
+ } catch (e) {
6378
+ const out = e.stdout;
6379
+ const errOut = typeof out === "string" ? out : void 0;
6380
+ const status = errOut !== void 0 ? parseIncludedOutput(errOut).status : void 0;
6381
+ if (errOut !== void 0) notePoolHeaders(source, errOut, Date.now());
6382
+ if (cached && status === 304) {
6383
+ lastPollSource = source;
6384
+ return cached.body;
6385
+ }
6386
+ if (status === 403 || status === 429) {
6387
+ const path2 = args.filter((a) => !a.startsWith("-")).join(" ") || args.join(" ");
6388
+ const refusal = errOut !== void 0 ? describeRefusal(errOut) : "no rate-limit headers or message";
6389
+ if (status === 403 && /Resource not accessible by integration/i.test(refusal)) {
6390
+ throw new Error(
6391
+ `poll read refused: App token lacks permission for ${path2} (HTTP 403, response: ${refusal}) \u2014 reads never fall back to the owner's token (#8030); add the permission to APP_POLL_PERMISSIONS / the App installation`
6392
+ );
6438
6393
  }
6439
- throw e;
6394
+ throw Object.assign(new Error(
6395
+ `poll read refused on the ${source} pool (HTTP ${status}, response: ${refusal}) \u2014 reads stay on the ${source === "app" ? "App" : "ambient identity"} (#8030); the wait re-arms after reset`
6396
+ ), { status, stdout: errOut, stderr: e.stderr });
6440
6397
  }
6441
- const { body, etag, pages } = parseIncludedOutput(stdout);
6442
- notePoolHeaders(source, stdout, Date.now());
6443
- if (source === "app") noteAppPollResponse(parseRateLimitHeaders(stdout), false, Date.now());
6444
- lastPollSource = source;
6445
- if (etag && pages === 1) etagCache.set(key, { etag, body });
6446
- else etagCache.delete(key);
6447
- return body;
6398
+ throw e;
6448
6399
  }
6400
+ const { body, etag, pages } = parseIncludedOutput(stdout);
6401
+ notePoolHeaders(source, stdout, Date.now());
6402
+ lastPollSource = source;
6403
+ if (etag && pages === 1) etagCache.set(key, { etag, body });
6404
+ else etagCache.delete(key);
6405
+ return body;
6449
6406
  }
6450
6407
  function classifyCheckRun(run) {
6451
6408
  if (run.status !== "completed") return "pending";
@@ -6607,7 +6564,7 @@ async function fetchRestRepoMergeSettings(repo, gh2 = defaultGhApi, ambientGh =
6607
6564
  }
6608
6565
  }
6609
6566
  var PR_SNAPSHOT_READ_RETRIES = 3;
6610
- var PR_SNAPSHOT_READ_DELAY_MS = 2e3;
6567
+ var PR_SNAPSHOT_READ_DELAY_MS = 15e3;
6611
6568
  async function readRestPrSnapshotWithRetry(prNumber, repo, gh2 = defaultGhApi, options) {
6612
6569
  const retries = options?.retries ?? PR_SNAPSHOT_READ_RETRIES;
6613
6570
  const untilMs = options?.retryTransientUntilMs;
@@ -6913,7 +6870,7 @@ async function fetchRequiredCheckContexts(repo, branch, gh2 = defaultGhApi) {
6913
6870
  return contexts;
6914
6871
  }
6915
6872
  async function fetchRestCorePool(gh2 = defaultGhApi, nowMs = Date.now()) {
6916
- const seen = gh2 === defaultGhApi ? observedCorePool(await pollToken() && appPollAllowsApp(nowMs) ? "app" : "user", nowMs) : void 0;
6873
+ const seen = gh2 === defaultGhApi ? observedCorePool(await pollToken() ? "app" : "user", nowMs) : void 0;
6917
6874
  if (seen) return { state: "ok", ...seen };
6918
6875
  let core;
6919
6876
  try {
@@ -6939,7 +6896,12 @@ function withAppClaimMarkerRead(client, appClient) {
6939
6896
  return await client.restPaginate(path2, init);
6940
6897
  } catch (e) {
6941
6898
  if (!commentsPath.test(path2) || !(e instanceof GitHubApiError) || e.status !== 429 && (e.status !== 403 || !isRateLimitRefusal(e))) throw e;
6942
- const token = appClient ? void 0 : await pollToken();
6899
+ let token;
6900
+ try {
6901
+ token = appClient ? void 0 : await pollToken();
6902
+ } catch {
6903
+ throw e;
6904
+ }
6943
6905
  if (!appClient && !token) throw e;
6944
6906
  return (appClient ?? createGitHubClient({ token: async () => token })).restPaginate(path2, init);
6945
6907
  }
@@ -16930,6 +16892,20 @@ var GH_RUN_WATCH_INTERVAL_S = 60;
16930
16892
  function ghRunWatchArgs(runId, repo) {
16931
16893
  return ["run", "watch", String(runId), "--repo", repo, "--exit-status", "--interval", String(GH_RUN_WATCH_INTERVAL_S)];
16932
16894
  }
16895
+ function isAppRoutableGhReadArgs(args) {
16896
+ if (args.some((a) => a === "--mine" || a === "viewer" || a.includes("@me"))) return false;
16897
+ const [cmd, sub] = args;
16898
+ if (cmd === "run" && (sub === "view" || sub === "list" || sub === "watch")) return true;
16899
+ if (cmd === "pr" && sub === "view") return true;
16900
+ if (cmd === "api") {
16901
+ const rest = args.slice(1);
16902
+ if (rest.some((a) => /^(-X|--method|-f|--field|-F|--raw-field|--input)/.test(a))) return false;
16903
+ const path2 = rest.find((a) => !a.startsWith("-"));
16904
+ if (path2 === "user" || path2?.startsWith("user/") || path2?.startsWith("user?")) return false;
16905
+ return true;
16906
+ }
16907
+ return false;
16908
+ }
16933
16909
  var JERV_HUB_REPO = "mutmutco/Jerv-Hub";
16934
16910
  function isHubControlRepo(repo) {
16935
16911
  return repo.toLowerCase() === HUB_REPO2.toLowerCase();
@@ -17716,10 +17692,10 @@ var rollout_plan_default = {
17716
17692
  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)."
17717
17693
  },
17718
17694
  baseline: {
17719
- version: "4.5.111",
17720
- tag: "v4.5.111",
17721
- commit: "7794d236f8bd",
17722
- npm: "@mutmutco/cli@4.5.111"
17695
+ version: "4.5.113",
17696
+ tag: "v4.5.113",
17697
+ commit: "c5ad425d42e2",
17698
+ npm: "@mutmutco/cli@4.5.113"
17723
17699
  },
17724
17700
  exitCriterion: "fleet-n-of-n",
17725
17701
  hubOnlyShortcut: "forbidden",
@@ -17736,14 +17712,14 @@ var rollout_plan_default = {
17736
17712
  repo: "mutmutco/mmi-hub",
17737
17713
  role: "canary",
17738
17714
  schedule: "train",
17739
- v3Target: "v4.5.111"
17715
+ v3Target: "v4.5.113"
17740
17716
  }
17741
17717
  ],
17742
17718
  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.",
17743
17719
  rollback: {
17744
17720
  independent: true,
17745
- mechanism: "npm dist-tag latest -> 4.5.111 and redeploy the Hub Lambda from tag v4.5.111 (7794d236f8bd); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17746
- v3Target: "v4.5.111 (@mutmutco/cli@4.5.111, tag commit 7794d236f8bd \u2014 last known-good release carrying the repo-index v4-only contract)"
17721
+ mechanism: "npm dist-tag latest -> 4.5.113 and redeploy the Hub Lambda from tag v4.5.113 (c5ad425d42e2); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17722
+ v3Target: "v4.5.113 (@mutmutco/cli@4.5.113, tag commit c5ad425d42e2 \u2014 last known-good release carrying the repo-index v4-only contract)"
17747
17723
  }
17748
17724
  },
17749
17725
  {
@@ -39115,7 +39091,7 @@ function protectedPrHeadRemedy(head, base) {
39115
39091
  return `PR head \`${head}\` is a train branch \u2014 updating it from \`${base}\` would merge \`${base}\` into \`${head}\`, promoting every unreleased commit. Never do that and never hand-merge on \`${head}\`. This is the pre-#6288 alignment shape: close this PR and let the train rebuild the alignment on a \`${base}\`-based branch that merges \`${head}\` into it (\`mmi-cli devops release --resume\`), then land THAT with a true merge \u2014 https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#head-behind-base`;
39116
39092
  }
39117
39093
  var PR_HEAD_UPDATE_API_READ_RETRIES = 5;
39118
- var PR_HEAD_UPDATE_API_READ_DELAY_MS = 2e3;
39094
+ var PR_HEAD_UPDATE_API_READ_DELAY_MS = 15e3;
39119
39095
  async function updatePrHeadFromBase(input) {
39120
39096
  const remedy = prHeadUpdateRemedy(input.head, input.base);
39121
39097
  if (isProtectedPrHead(input.head)) throw new Error(protectedPrHeadRemedy(input.head, input.base));
@@ -39152,8 +39128,8 @@ async function updatePrHeadFromBase(input) {
39152
39128
  var PR_LAND_POLL_MS = 6e4;
39153
39129
  var PR_LAND_ENQUEUE_TIMEOUT_MS = 10 * 6e4;
39154
39130
  var PR_LAND_STATE_READ_RETRIES = 3;
39155
- var PR_LAND_STATE_READ_DELAY_MS = 2e3;
39156
- var PR_LAND_MERGE_RETRY_DELAY_MS = 3e3;
39131
+ var PR_LAND_STATE_READ_DELAY_MS = 15e3;
39132
+ var PR_LAND_MERGE_RETRY_DELAY_MS = 3e4;
39157
39133
  async function mergeAutoWithTransientRetry(prNumber, repo, deps) {
39158
39134
  const first = await deps.mergeAuto(prNumber, repo);
39159
39135
  if (first.mergeStatus !== "failed") return first;
@@ -39166,7 +39142,7 @@ async function mergeAutoWithTransientRetry(prNumber, repo, deps) {
39166
39142
  return { mergeStatus: "failed", error: `merge retry after transient failure also failed: ${retried.error ?? first.error ?? "unknown error"}` };
39167
39143
  }
39168
39144
  var AUTO_MERGE_CONFIRM_RETRIES = 3;
39169
- var AUTO_MERGE_CONFIRM_DELAY_MS = 3e3;
39145
+ var AUTO_MERGE_CONFIRM_DELAY_MS = 15e3;
39170
39146
  async function confirmAutoMergeEnqueued(deps, options) {
39171
39147
  const retries = options?.retries ?? AUTO_MERGE_CONFIRM_RETRIES;
39172
39148
  const delayMs = options?.delayMs ?? AUTO_MERGE_CONFIRM_DELAY_MS;
@@ -46095,7 +46071,8 @@ ${list}`);
46095
46071
  }
46096
46072
  if (!repoFromGh || !base) {
46097
46073
  const args = repoOpt ? ["--repo", repoOpt] : repoArgs;
46098
- const viewed = (await execFileP("gh", ["pr", "view", prNumber, ...args, "--json", "headRepository,baseRefName", "--jq", '.headRepository.nameWithOwner + " " + .baseRefName'], { timeout: GC_GH_TIMEOUT_MS })).stdout.trim();
46074
+ const readEnv = await ghReadEnv();
46075
+ const viewed = (await execFileP("gh", ["pr", "view", prNumber, ...args, "--json", "headRepository,baseRefName", "--jq", '.headRepository.nameWithOwner + " " + .baseRefName'], { timeout: GC_GH_TIMEOUT_MS, ...readEnv ? { env: readEnv } : {} })).stdout.trim();
46099
46076
  [repoFromGh, base] = viewed.split(/\s+/);
46100
46077
  }
46101
46078
  const repo = repoOpt ?? repoFromGh;
@@ -46159,7 +46136,8 @@ ${list}`);
46159
46136
  },
46160
46137
  readPrState: async (prNumber, repo) => {
46161
46138
  const args = repo ? ["--repo", repo] : [];
46162
- const result2 = await readGhPrStateWithRetry(async () => (await execFileP("gh", ["pr", "view", prNumber, ...args, "--json", "mergeStateStatus,mergeable,state"], { timeout: GC_GH_TIMEOUT_MS })).stdout);
46139
+ const readEnv = await ghReadEnv();
46140
+ const result2 = await readGhPrStateWithRetry(async () => (await execFileP("gh", ["pr", "view", prNumber, ...args, "--json", "mergeStateStatus,mergeable,state"], { timeout: GC_GH_TIMEOUT_MS, ...readEnv ? { env: readEnv } : {} })).stdout);
46163
46141
  if (!result2.ok) {
46164
46142
  if (isGitHubRateLimitError(result2.error)) return fetchRestPrLandState(prNumber, repo);
46165
46143
  throw new Error(`could not read PR state: ${result2.error}`);
@@ -46777,8 +46755,9 @@ function trainApplyDeps() {
46777
46755
  trainWriter: (verb, cwd) => acquireTrainWriterLock(cwd, `mmi-cli devops ${verb}`),
46778
46756
  run: async (file, args) => {
46779
46757
  const timeout = file === "node" && args[1] === "prepare" ? NODE_PREPARE_TIMEOUT_MS : file === "node" && args[1] === "verify" ? NODE_VERIFY_TIMEOUT_MS : file === "npm" && (args[0] === "version" || args[0] === "ci" || args[0] === "install") ? NPM_FOLD_TIMEOUT_MS : file === "npm" ? NPM_TRAIN_TIMEOUT_MS : file === "bash" && /jerv-gateway-release-deploy\.sh$/.test(args[0] ?? "") ? JERV_GATEWAY_DEPLOY_TIMEOUT_MS : file === "git" && args[0] === "commit" ? GIT_COMMIT_TIMEOUT_MS : file !== "gh" ? GIT_TIMEOUT_MS : args[0] === "run" && args[1] === "watch" ? GH_RUN_WATCH_TIMEOUT_MS : GH_TRAIN_TIMEOUT_MS;
46758
+ const readEnv = file === "gh" && isAppRoutableGhReadArgs(args) ? await ghReadEnv() : void 0;
46780
46759
  try {
46781
- return isWin3 && file === "npm" ? (await execFileP("cmd.exe", ["/c", "npm", ...args], { timeout })).stdout : (await execFileP(file, file === "git" ? trainGitArgs(args) : args, { timeout })).stdout;
46760
+ return isWin3 && file === "npm" ? (await execFileP("cmd.exe", ["/c", "npm", ...args], { timeout })).stdout : (await execFileP(file, file === "git" ? trainGitArgs(args) : args, { timeout, ...readEnv ? { env: readEnv } : {} })).stdout;
46782
46761
  } catch (e) {
46783
46762
  throw surfaceTrainSubprocessFailure(e, file, args);
46784
46763
  }
@@ -47703,11 +47682,12 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
47703
47682
  init_github_client();
47704
47683
  var GH_TIMEOUT = 3e4;
47705
47684
  var WATCH_TIMEOUT = 25 * 6e4;
47706
- async function exec(file, args, cwd, timeout = GH_TIMEOUT) {
47707
- return (await execFileP(file, args, { ...cwd ? { cwd } : {}, timeout })).stdout.trim();
47685
+ async function exec(file, args, cwd, timeout = GH_TIMEOUT, env) {
47686
+ return (await execFileP(file, args, { ...cwd ? { cwd } : {}, timeout, ...env ? { env } : {} })).stdout.trim();
47708
47687
  }
47709
47688
  async function gh(args) {
47710
- return exec("gh", args);
47689
+ const readEnv = isAppRoutableGhReadArgs(args) ? await ghReadEnv() : void 0;
47690
+ return exec("gh", args, void 0, GH_TIMEOUT, readEnv ?? void 0);
47711
47691
  }
47712
47692
  function isMissingRef(message2) {
47713
47693
  return /404|Not Found|No commit found for SHA/.test(message2);
@@ -47931,7 +47911,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
47931
47911
  }
47932
47912
  if (!candidate) throw new Error(`workflow dispatch outcome ambiguous for "${title}"; inspect Actions before retrying`);
47933
47913
  try {
47934
- await exec("gh", ghRunWatchArgs(candidate.databaseId, "mutmutco/MMI-Hub"), void 0, WATCH_TIMEOUT);
47914
+ await exec("gh", ghRunWatchArgs(candidate.databaseId, "mutmutco/MMI-Hub"), void 0, WATCH_TIMEOUT, await ghReadEnv() ?? void 0);
47935
47915
  } catch {
47936
47916
  }
47937
47917
  const verdict = JSON.parse(await gh(["run", "view", String(candidate.databaseId), "--repo", "mutmutco/MMI-Hub", "--json", "conclusion"]));
@@ -47963,7 +47943,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
47963
47943
  };
47964
47944
  const rcRunCause = async (id) => {
47965
47945
  try {
47966
- return rcRunCauseFromLog(await exec("gh", ["run", "view", String(id), "--repo", "mutmutco/MMI-Hub", "--log-failed"]));
47946
+ return rcRunCauseFromLog(await gh(["run", "view", String(id), "--repo", "mutmutco/MMI-Hub", "--log-failed"]));
47967
47947
  } catch {
47968
47948
  return "";
47969
47949
  }
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.111",
3
+ "version": "4.5.113",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/codex-plugin",
3
- "version": "4.5.111",
3
+ "version": "4.5.113",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",