@mutmutco/cli 4.5.58 → 4.5.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.cjs +155 -34
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -5825,11 +5825,14 @@ function waitReadFailureMessage(e) {
5825
5825
  return (stderr || err?.message || String(e)).replace(/\s+/g, " ").slice(0, 300);
5826
5826
  }
5827
5827
  var PR_CHECKS_POLL_MS = 3e4;
5828
+ function pollIntervalMs(elapsedMs) {
5829
+ return Math.min(4 * PR_CHECKS_POLL_MS, PR_CHECKS_POLL_MS * 2 ** Math.floor(Math.max(0, elapsedMs) / 3e5));
5830
+ }
5828
5831
  var PR_CHECKS_TIMEOUT_MS = 30 * 6e4;
5829
5832
  var PR_CHECKS_SUCCESS_CONFIRMATIONS = 2;
5830
5833
  var PR_CHECKS_CONFIRM_MS = 5e3;
5831
5834
  var PR_CHECKS_FAILURE_CONFIRMATIONS = 2;
5832
- var PR_CHECKS_RATELIMIT_FLOOR = 50;
5835
+ var PR_CHECKS_RATELIMIT_FLOOR = 1e3;
5833
5836
  var PR_CHECKS_RATELIMIT_JITTER_MAX_MS = 5e3;
5834
5837
  var NO_CI_LIVE_CHECKS_CONTRADICTION_REASON = "ci:none contradicted by live check runs on PR head";
5835
5838
  var PR_CHECKS_ZERO_RUNS_GRACE_MS = 2 * 6e4;
@@ -5965,7 +5968,7 @@ async function waitForPrChecks(deps) {
5965
5968
  }
5966
5969
  if (state === "failing") {
5967
5970
  lastDetail = "failing (a check failed; others still running)";
5968
- await deps.sleep(PR_CHECKS_POLL_MS);
5971
+ await deps.sleep(pollIntervalMs(now() - started));
5969
5972
  continue;
5970
5973
  }
5971
5974
  if (state === "success") {
@@ -6003,11 +6006,11 @@ async function waitForPrChecks(deps) {
6003
6006
  } else {
6004
6007
  zeroRunsStreak = 0;
6005
6008
  }
6006
- await deps.sleep(PR_CHECKS_POLL_MS);
6009
+ await deps.sleep(pollIntervalMs(now() - started));
6007
6010
  continue;
6008
6011
  }
6009
6012
  lastDetail = state;
6010
- await deps.sleep(PR_CHECKS_POLL_MS);
6013
+ await deps.sleep(pollIntervalMs(now() - started));
6011
6014
  }
6012
6015
  return { policy, status: "timeout", reason, detail: lastDetail, waitedMs: now() - started };
6013
6016
  }
@@ -6044,15 +6047,38 @@ async function pollToken() {
6044
6047
  pollTokenOnce ??= pollTokenProvider().catch(() => void 0);
6045
6048
  return pollTokenOnce;
6046
6049
  }
6047
- async function defaultGhApi(args) {
6048
- const token = await pollToken();
6049
- const { stdout } = await execFileP("gh", ["api", ...args], {
6050
- timeout: REST_GH_TIMEOUT_MS,
6051
- // Only when a token was actually minted: passing `env` at all would otherwise replace the
6052
- // inherited environment wholesale, and `gh` needs the rest of it (PATH, GH_HOST, config home).
6053
- ...token ? { env: { ...process.env, GH_TOKEN: token } } : {}
6050
+ var INCLUDED_HEADER_BLOCK = /^(?:\r?\n)?HTTP\/\d(?:\.\d)? (\d{3})[^\n]*\n(?:[^\n]+\n)*?\r?\n/gm;
6051
+ function parseIncludedOutput(out) {
6052
+ let status;
6053
+ let etag;
6054
+ let pages = 0;
6055
+ const body = out.replace(INCLUDED_HEADER_BLOCK, (block, code) => {
6056
+ if (pages++ === 0) {
6057
+ status = Number(code);
6058
+ etag = /^etag:\s*(.+?)\s*$/im.exec(block)?.[1];
6059
+ }
6060
+ return "";
6054
6061
  });
6055
- return stdout;
6062
+ return { body, status, etag, pages };
6063
+ }
6064
+ var etagCache = /* @__PURE__ */ new Map();
6065
+ async function defaultGhApi(args) {
6066
+ const key = args.join("\0");
6067
+ const cached = etagCache.get(key);
6068
+ let stdout;
6069
+ try {
6070
+ ({ stdout } = await execFileP("gh", ["api", "--include", ...cached ? ["-H", `If-None-Match: ${cached.etag}`] : [], ...args], {
6071
+ timeout: REST_GH_TIMEOUT_MS
6072
+ }));
6073
+ } catch (e) {
6074
+ const out = e.stdout;
6075
+ if (cached && typeof out === "string" && parseIncludedOutput(out).status === 304) return cached.body;
6076
+ throw e;
6077
+ }
6078
+ const { body, etag, pages } = parseIncludedOutput(stdout);
6079
+ if (etag && pages === 1) etagCache.set(key, { etag, body });
6080
+ else etagCache.delete(key);
6081
+ return body;
6056
6082
  }
6057
6083
  function classifyCheckRun(run) {
6058
6084
  if (run.status !== "completed") return "pending";
@@ -8475,6 +8501,9 @@ function isValidSecretKey(key) {
8475
8501
  if (key.includes("..") || key.startsWith("/") || key.includes("*")) return false;
8476
8502
  return KEY_RE.test(key);
8477
8503
  }
8504
+ function stripTrailingCRLF(value) {
8505
+ return value.replace(/\r\n$|\r$|\n$/, "");
8506
+ }
8478
8507
  function classifyTier(_slug, key) {
8479
8508
  const slash2 = key.indexOf("/");
8480
8509
  if (slash2 === -1) return "project";
@@ -8637,7 +8666,7 @@ async function fetchSecretValue(deps, key, opts, diagnose = false) {
8637
8666
  if (!res.ok) {
8638
8667
  if (diagnose) {
8639
8668
  const body = await readJsonBody(res);
8640
- const reason = res.status === 403 ? "authority refused" : res.status === 429 ? "rate limited" : "Hub route refused";
8669
+ const reason = res.status === 403 ? "authority refused" : res.status === 429 ? "rate limited" : body.code === "github-rate-limited" ? "Hub GitHub App allowance used up, not a denial" : "Hub route refused";
8641
8670
  throw new Error(`${reason} (HTTP ${res.status}${typeof body.error === "string" && /^(forbidden|unauthorized|rate limit|too many requests|master-admin only)$/i.test(body.error) ? `: ${body.error}` : ""})`);
8642
8671
  }
8643
8672
  return null;
@@ -9918,6 +9947,10 @@ async function secretsVerify(deps, key, opts) {
9918
9947
  }
9919
9948
  const hasProviderVerifier = Boolean(providerForSecretKey(key));
9920
9949
  const value = await fetchSecretValue(deps, key, opts);
9950
+ if (value && value !== stripTrailingCRLF(value)) {
9951
+ deps.err(`${key}: stored value ends in a CR or LF character \u2014 likely corrupted by a piped write; re-set it with \`mmi-cli vault secrets set ${key}\``);
9952
+ return false;
9953
+ }
9921
9954
  if (!hasProviderVerifier) {
9922
9955
  if (!value) {
9923
9956
  deps.err(`${key}: ABSENT or unreachable at this coordinate \u2014 no value could be read`);
@@ -10105,6 +10138,40 @@ async function secretsDeclare(deps, key, opts) {
10105
10138
  deps.log(`declared ${key} (project tier, ${slug}) \u2014 catalog metadata only; ask master (secrets request) to wire it into requiredRuntimeSecrets`);
10106
10139
  return true;
10107
10140
  }
10141
+ async function secretsUndeclare(deps, key, opts) {
10142
+ if (!DECLARE_KEY_RE.test(key.split("@")[0] ?? "")) {
10143
+ deps.err(`secrets undeclare: invalid key ${JSON.stringify(key)} \u2014 must be an env-style name (UPPER_SNAKE convention), optionally @dev|rc|main`);
10144
+ return false;
10145
+ }
10146
+ const repo = await targetRepo(deps, opts);
10147
+ const slug = await vaultSlug(deps, opts);
10148
+ let res;
10149
+ try {
10150
+ res = await deps.fetch(`${deps.apiUrl}/projects/${slug}/secrets/undeclare`, {
10151
+ method: "POST",
10152
+ headers: await deps.headers({ "content-type": "application/json" }),
10153
+ body: JSON.stringify({ repo, key }),
10154
+ signal: AbortSignal.timeout(TIMEOUT_MS)
10155
+ });
10156
+ } catch (e) {
10157
+ deps.err(`secrets undeclare: ${e.message}`);
10158
+ return false;
10159
+ }
10160
+ const body = await readJsonBody(res);
10161
+ if (!res.ok) {
10162
+ deps.err(await upgradeMessage(res, body) ?? `secrets undeclare failed: HTTP ${res.status}${errorDetail(body)}`);
10163
+ return false;
10164
+ }
10165
+ const undeclared = body?.undeclared !== false;
10166
+ if (opts.json) {
10167
+ deps.log(JSON.stringify({ ok: true, key, undeclared }));
10168
+ return true;
10169
+ }
10170
+ deps.log(
10171
+ undeclared ? `undeclared ${key} (project tier, ${slug}) \u2014 catalog entry removed; the vault value was already absent` : `${key} was not declared in ${slug}'s catalog \u2014 nothing to undeclare`
10172
+ );
10173
+ return true;
10174
+ }
10108
10175
  function parseRailsCredentialMapping(raw, stage) {
10109
10176
  const eq = raw.indexOf("=");
10110
10177
  if (eq <= 0 || eq === raw.length - 1) return null;
@@ -16302,6 +16369,17 @@ function isHubControlRepo(repo) {
16302
16369
  function isJervHubRepo(repo) {
16303
16370
  return repo.toLowerCase() === JERV_HUB_REPO.toLowerCase();
16304
16371
  }
16372
+ var WINDOWS_GIT_BASH_MSYSTEM = /^(?:MINGW(?:32|64)|UCRT64|CLANG(?:64|ARM64))$/u;
16373
+ function isWindowsGitBash(msystem) {
16374
+ return WINDOWS_GIT_BASH_MSYSTEM.test(msystem ?? "");
16375
+ }
16376
+ function assertGitBashOnWindowsForJervHubRelease(repo, platform2 = process.platform, env = process.env) {
16377
+ if (platform2 !== "win32" || !isJervHubRepo(repo)) return;
16378
+ if (isWindowsGitBash(env.MSYSTEM)) return;
16379
+ throw new Error(
16380
+ `${repo}: Windows Git Bash required \u2014 the release train's Jerv Gateway deploy leg refuses outside it, and the current shell is not Git Bash (MSYSTEM=${env.MSYSTEM ?? "(unset)"}). Run the release from Git Bash instead, e.g.: "C:/Program Files/Git/bin/bash.exe" -lc "mmi-cli devops release --apply"`
16381
+ );
16382
+ }
16305
16383
 
16306
16384
  // src/train-apply-correlation.ts
16307
16385
  var import_node_fs18 = require("node:fs");
@@ -17070,10 +17148,10 @@ var rollout_plan_default = {
17070
17148
  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)."
17071
17149
  },
17072
17150
  baseline: {
17073
- version: "4.5.58",
17074
- tag: "v4.5.58",
17075
- commit: "05d087d1fcb7",
17076
- npm: "@mutmutco/cli@4.5.58"
17151
+ version: "4.5.59",
17152
+ tag: "v4.5.59",
17153
+ commit: "ea079366d96e",
17154
+ npm: "@mutmutco/cli@4.5.59"
17077
17155
  },
17078
17156
  exitCriterion: "fleet-n-of-n",
17079
17157
  hubOnlyShortcut: "forbidden",
@@ -17090,14 +17168,14 @@ var rollout_plan_default = {
17090
17168
  repo: "mutmutco/mmi-hub",
17091
17169
  role: "canary",
17092
17170
  schedule: "train",
17093
- v3Target: "v4.5.58"
17171
+ v3Target: "v4.5.59"
17094
17172
  }
17095
17173
  ],
17096
17174
  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.",
17097
17175
  rollback: {
17098
17176
  independent: true,
17099
- mechanism: "npm dist-tag latest -> 4.5.58 and redeploy the Hub Lambda from tag v4.5.58 (05d087d1fcb7); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17100
- v3Target: "v4.5.58 (@mutmutco/cli@4.5.58, tag commit 05d087d1fcb7 \u2014 last known-good release carrying the repo-index v4-only contract)"
17177
+ mechanism: "npm dist-tag latest -> 4.5.59 and redeploy the Hub Lambda from tag v4.5.59 (ea079366d96e); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17178
+ v3Target: "v4.5.59 (@mutmutco/cli@4.5.59, tag commit ea079366d96e \u2014 last known-good release carrying the repo-index v4-only contract)"
17101
17179
  }
17102
17180
  },
17103
17181
  {
@@ -25157,6 +25235,7 @@ function enforceGateBudget(deps, repo) {
25157
25235
  }
25158
25236
  }
25159
25237
  async function preflight(deps, ctx, stage, meta, lane) {
25238
+ assertGitBashOnWindowsForJervHubRelease(ctx.repo);
25160
25239
  deps.warn?.("Release: Checking release prerequisites");
25161
25240
  if (deps.suiteCut && !authorisedSuiteCut(ctx.repo, meta, deps.suiteCut))
25162
25241
  throw new Error(`${ctx.repo}: suite cut context does not match registry META; no deployment or tag was changed`);
@@ -27467,15 +27546,16 @@ async function branchPresence(deps, repo, branch) {
27467
27546
  }
27468
27547
  }
27469
27548
  function collectRegistryRepos(projects) {
27470
- const seen = /* @__PURE__ */ new Set();
27549
+ const seen = /* @__PURE__ */ new Map();
27471
27550
  for (const project2 of projects) {
27472
27551
  for (const raw of project2.repos ?? []) {
27473
27552
  const repo = raw.includes("/") ? raw : `mutmutco/${raw}`;
27474
- seen.add(repo);
27553
+ const key = repo.toLowerCase();
27554
+ if (!seen.has(key)) seen.set(key, repo);
27475
27555
  }
27476
27556
  }
27477
- if (![...seen].some((r) => r.toLowerCase() === HUB_REPO4.toLowerCase())) seen.add(HUB_REPO4);
27478
- return [...seen].sort((a, b) => a.localeCompare(b));
27557
+ if (!seen.has(HUB_REPO4.toLowerCase())) seen.set(HUB_REPO4.toLowerCase(), HUB_REPO4);
27558
+ return [...seen.values()].sort((a, b) => a.localeCompare(b));
27479
27559
  }
27480
27560
  async function prTriggeredWorkflowsOnRef(deps, repo, branch, repoClass) {
27481
27561
  const hasGate = repoClass === "hub" ? true : await contentExists(deps, repo, branch, PRODUCT_GATE_PATH);
@@ -27522,7 +27602,29 @@ async function filterPullRequestTriggered(deps, repo, branch, paths) {
27522
27602
  }
27523
27603
  return kept;
27524
27604
  }
27525
- async function auditRepoCi(repo, deps) {
27605
+ function trackUnauditableReads(deps) {
27606
+ let reason;
27607
+ const record = (e) => {
27608
+ if (reason) return;
27609
+ const err = e;
27610
+ if (err?.rateLimited) reason = `GitHub App rate-limited: ${err.message ?? "rate limit exceeded"}`;
27611
+ else if (err?.status === 403 || err?.status === 429) reason = `HTTP ${err.status}${err.message ? `: ${err.message}` : ""}`;
27612
+ };
27613
+ const client = {
27614
+ ...deps.client,
27615
+ rest: async (method, path2, init) => {
27616
+ try {
27617
+ return await deps.client.rest(method, path2, init);
27618
+ } catch (e) {
27619
+ record(e);
27620
+ throw e;
27621
+ }
27622
+ }
27623
+ };
27624
+ return { deps: { ...deps, client }, reason: () => reason };
27625
+ }
27626
+ async function auditRepoCi(repo, callerDeps) {
27627
+ const { deps, reason: unauditedReason } = trackUnauditableReads(callerDeps);
27526
27628
  const meta = await deps.getProjectMeta(slugFromRepo(repo));
27527
27629
  const repoClass = classifyRepo(repo, meta);
27528
27630
  const checks = [];
@@ -27817,6 +27919,10 @@ async function auditRepoCi(repo, deps) {
27817
27919
  const workflows = await getBranchWorkflows();
27818
27920
  if (workflows) checks.push(...await auditSharedActionPins(workflows, deps));
27819
27921
  }
27922
+ const failure = unauditedReason();
27923
+ if (failure) {
27924
+ return { repo, class: repoClass, mergePolicy: policy, ok: false, checks: [], explicitNoCi, unauditedReason: failure };
27925
+ }
27820
27926
  const ok = checks.every((c) => c.ok);
27821
27927
  return { repo, class: repoClass, mergePolicy: policy, ok, checks, explicitNoCi };
27822
27928
  }
@@ -27858,8 +27964,8 @@ function renderCiAuditMarkdown(report) {
27858
27964
  "|------|-------|--------|----|---------|"
27859
27965
  ];
27860
27966
  for (const r of report.repos) {
27861
- const gap = r.checks.find((c) => !c.ok);
27862
- lines2.push(`| ${r.repo} | ${r.class} | ${r.mergePolicy} | ${r.ok ? "yes" : "no"} | ${gap?.label ?? "\u2014"} |`);
27967
+ const gap = r.unauditedReason ? `CANNOT AUDIT \u2014 ${r.unauditedReason}` : r.checks.find((c) => !c.ok)?.label ?? "\u2014";
27968
+ lines2.push(`| ${r.repo} | ${r.class} | ${r.mergePolicy} | ${r.ok ? "yes" : "no"} | ${gap} |`);
27863
27969
  }
27864
27970
  return lines2.join("\n");
27865
27971
  }
@@ -27869,8 +27975,13 @@ function renderCiAuditText(report) {
27869
27975
  renderCiAuditScopeLine(report)
27870
27976
  ];
27871
27977
  for (const r of report.repos) {
27978
+ const verdict = r.unauditedReason ? "CANNOT AUDIT" : r.ok ? "OK" : "GAP";
27872
27979
  lines2.push(`
27873
- ${r.repo} (${r.class}, policy=${r.mergePolicy}) ${r.ok ? "OK" : "GAP"}`);
27980
+ ${r.repo} (${r.class}, policy=${r.mergePolicy}) ${verdict}`);
27981
+ if (r.unauditedReason) {
27982
+ lines2.push(` UNAUDITED \u2014 ${r.unauditedReason}`);
27983
+ continue;
27984
+ }
27874
27985
  for (const c of r.checks) {
27875
27986
  lines2.push(` ${c.ok ? "OK" : "FAIL"} ${c.label}${c.detail ? ` \u2014 ${c.detail}` : ""}`);
27876
27987
  }
@@ -31356,7 +31467,7 @@ async function readSecretStdin() {
31356
31467
  }
31357
31468
  const chunks = [];
31358
31469
  for await (const chunk of process.stdin) chunks.push(chunk);
31359
- return Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
31470
+ return stripTrailingCRLF(Buffer.concat(chunks).toString("utf8"));
31360
31471
  }
31361
31472
  function makeSecretsDeps(cfg) {
31362
31473
  return {
@@ -31508,6 +31619,10 @@ function registerSecretsCommands(program3) {
31508
31619
  });
31509
31620
  if (!ok) process.exitCode = 1;
31510
31621
  }));
31622
+ secrets.command("undeclare <key>").description("project-admin self-undeclare: retire a secrets-catalog entry for your own repo (catalog metadata only \u2014 never a value); declare's exact inverse (MMI-Hub#7524). Refuses (409) while a live vault value still exists for the key at any declared stage \u2014 delete the value first (`secrets rm`), then undeclare. A key that is not declared is a no-op, not an error.").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json", "machine-readable output").action((key, o) => withSecrets(async (d) => {
31623
+ const ok = await secretsUndeclare(d, key, { repo: o.repo, json: o.json });
31624
+ if (!ok) process.exitCode = 1;
31625
+ }));
31511
31626
  secrets.command("verify <key>").description("validate a known provider secret without printing its value; a key with no configured provider verifier falls back to a value-free PRESENT/ABSENT reachability check (#3436)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--slug <slug>", "org-infra namespace (e.g. _org) for a granted org secret").action((key, o) => withSecrets(async (d) => {
31512
31627
  const ok = await secretsVerify(d, key, o);
31513
31628
  if (!ok) process.exitCode = 1;
@@ -33370,9 +33485,13 @@ function applyWaivers(checks, waivers) {
33370
33485
  const set = new Set(waivers);
33371
33486
  return checks.map((c) => !c.ok && set.has(c.label) ? { ...c, waived: true } : c);
33372
33487
  }
33488
+ var laneReasons = (doctor) => doctor.findings.filter((f) => (f.severity === "blocker" || f.code === "origin-unverified") && f.code !== SUITE_GUARD_CODE);
33489
+ function onlySuiteLeadOwned(doctor) {
33490
+ return !doctor.ready && laneReasons(doctor).length === 0 && doctor.findings.some((f) => f.code === SUITE_GUARD_CODE);
33491
+ }
33373
33492
  function laneNotEvaluatedFromThisBranch(doctor) {
33374
33493
  if (doctor.ready) return void 0;
33375
- const reasons = doctor.findings.filter((f) => f.severity === "blocker" || f.code === "origin-unverified");
33494
+ const reasons = laneReasons(doctor);
33376
33495
  const only = reasons.length === 1 ? reasons[0] : void 0;
33377
33496
  return only?.code === "branch-mismatch" ? only.title : void 0;
33378
33497
  }
@@ -33383,7 +33502,7 @@ function attachTrainDoctorVerdicts(report, trainDoctors) {
33383
33502
  });
33384
33503
  return {
33385
33504
  ...report,
33386
- ok: report.ok && marked.every((doctor) => doctor.ready || doctor.notEvaluatedFromThisBranch !== void 0),
33505
+ ok: report.ok && marked.every((doctor) => doctor.ready || doctor.notEvaluatedFromThisBranch !== void 0 || onlySuiteLeadOwned(doctor)),
33387
33506
  ...marked.length ? { trainDoctors: marked } : {}
33388
33507
  };
33389
33508
  }
@@ -33397,6 +33516,8 @@ function renderBootstrapVerifyReport(report) {
33397
33516
  lines2.push("", formatTrainDoctor(doctor));
33398
33517
  if (doctor.notEvaluatedFromThisBranch) {
33399
33518
  lines2.push(` NOT EVALUATED from this branch \u2014 ${doctor.notEvaluatedFromThisBranch}; one checkout stands on one branch, so this lane does not fail the verify (#6677). Run \`mmi-cli devops train doctor --lane ${doctor.lane}\` from that branch for its own verdict.`);
33519
+ } else if (onlySuiteLeadOwned(doctor)) {
33520
+ lines2.push(" SUITE MEMBER: this lane is run from the suite lead (mmi-cli devops suite rcand|release), so suite-member-solo does not fail the verify (#7511).");
33400
33521
  }
33401
33522
  }
33402
33523
  return lines2.join("\n");
@@ -42112,6 +42233,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
42112
42233
  try {
42113
42234
  entries = (0, import_node_fs40.readdirSync)(dir, { withFileTypes: true });
42114
42235
  } catch (e) {
42236
+ if (e.code === "ENOENT") continue;
42115
42237
  return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
42116
42238
  }
42117
42239
  for (const entry of entries) {
@@ -43930,7 +44052,7 @@ ${list}`);
43930
44052
  console.error(line);
43931
44053
  }
43932
44054
  }
43933
- const credential = await pollToken().catch(() => void 0) ? "app_installation" : "user";
44055
+ const credential = "user";
43934
44056
  if (o.json) printLine(JSON.stringify({ ...result, credential }));
43935
44057
  else printLine(
43936
44058
  `pr land: ${result.status}${result.error ? ` \u2014 ${result.error}` : ""} (credential: ${credential})` + (result.branchFinality ? ` \u2014 ${result.branchFinality}` : "")
@@ -44445,9 +44567,8 @@ function trainApplyDeps() {
44445
44567
  trainWriter: (verb, cwd) => acquireTrainWriterLock(cwd, `mmi-cli devops ${verb}`),
44446
44568
  run: async (file, args) => {
44447
44569
  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;
44448
- const watchToken = file === "gh" && args[0] === "run" && args[1] === "watch" ? await pollToken() : void 0;
44449
44570
  try {
44450
- return isWin3 && file === "npm" ? (await execFileP("cmd.exe", ["/c", "npm", ...args], { timeout })).stdout : (await execFileP(file, file === "git" ? trainGitArgs(args) : args, { timeout, ...watchToken ? { env: { ...process.env, GH_TOKEN: watchToken } } : {} })).stdout;
44571
+ return isWin3 && file === "npm" ? (await execFileP("cmd.exe", ["/c", "npm", ...args], { timeout })).stdout : (await execFileP(file, file === "git" ? trainGitArgs(args) : args, { timeout })).stdout;
44451
44572
  } catch (e) {
44452
44573
  throw surfaceTrainSubprocessFailure(e, file, args);
44453
44574
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.58",
3
+ "version": "4.5.59",
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",