@mutmutco/cli 4.3.12 → 4.3.13

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 +42 -13
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -11867,7 +11867,7 @@ async function checkLaneContest(client, item, actor = describeSessionIdentity(),
11867
11867
  };
11868
11868
  }
11869
11869
  function laneContestMessage(ref, contest, verb) {
11870
- const holder = contest.marker ? `lane ${describeClaimMarker(contest.marker)}` : "another lane";
11870
+ const holder = contest.marker ? `lane ${describeClaimMarker(contest.marker)}` : contest.unverifiable.includes("comments") ? "an unreadable lane (its claim-marker comments could not be read, so no holder can be named)" : "another lane";
11871
11871
  const seen = contest.live.join("; ");
11872
11872
  const unreadable = contest.unverifiable.length ? `liveness could not be fully verified (failed to read: ${contest.unverifiable.join(", ")})` : "";
11873
11873
  const why = [seen, unreadable].filter(Boolean).join("; ");
@@ -15476,10 +15476,10 @@ var rollout_plan_default = {
15476
15476
  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)."
15477
15477
  },
15478
15478
  baseline: {
15479
- version: "4.3.12",
15480
- tag: "v4.3.12",
15481
- commit: "355e861fa08f",
15482
- npm: "@mutmutco/cli@4.3.12"
15479
+ version: "4.3.13",
15480
+ tag: "v4.3.13",
15481
+ commit: "8442cc0ac255",
15482
+ npm: "@mutmutco/cli@4.3.13"
15483
15483
  },
15484
15484
  exitCriterion: "fleet-n-of-n",
15485
15485
  hubOnlyShortcut: "forbidden",
@@ -15496,14 +15496,14 @@ var rollout_plan_default = {
15496
15496
  repo: "mutmutco/mmi-hub",
15497
15497
  role: "canary",
15498
15498
  schedule: "train",
15499
- v3Target: "v4.3.12"
15499
+ v3Target: "v4.3.13"
15500
15500
  }
15501
15501
  ],
15502
15502
  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.",
15503
15503
  rollback: {
15504
15504
  independent: true,
15505
- mechanism: "npm dist-tag latest -> 4.3.12 and redeploy the Hub Lambda from tag v4.3.12 (355e861fa08f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15506
- v3Target: "v4.3.12 (@mutmutco/cli@4.3.12, tag commit 355e861fa08f \u2014 last known-good release carrying the repo-index v4-only contract)"
15505
+ mechanism: "npm dist-tag latest -> 4.3.13 and redeploy the Hub Lambda from tag v4.3.13 (8442cc0ac255); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15506
+ v3Target: "v4.3.13 (@mutmutco/cli@4.3.13, tag commit 8442cc0ac255 \u2014 last known-good release carrying the repo-index v4-only contract)"
15507
15507
  }
15508
15508
  },
15509
15509
  {
@@ -24173,6 +24173,10 @@ async function finalizeCiReconcile(repo, deps, result, before, pendingReason) {
24173
24173
  result.errors.push(`post-apply audit failed \u2014 remaining: ${remaining.join(", ")}`);
24174
24174
  return result;
24175
24175
  }
24176
+ const unowned = after.checks.filter((c) => !c.ok && !remaining.includes(c.label)).map((c) => c.label);
24177
+ if (unowned.length > 0) {
24178
+ result.skipped.push(`audit still failing on rows reconcile does not own (${unowned.join("; ")}) \u2014 follow each row's remediation; re-running reconcile cannot fix them`);
24179
+ }
24176
24180
  const repaired = reconcileOwnedFailures(before).length > 0;
24177
24181
  result.postApply = { state: repaired ? "repaired" : "clean", audit: after, remaining: [] };
24178
24182
  (repaired ? result.applied : result.skipped).push(
@@ -37032,7 +37036,7 @@ var PR_MERGE_BASE_RACE_RETRY_DELAY_MS = 3e3;
37032
37036
  function assertRemoteBranchPreservedOnMerge(repo, deleteBranchOnMerge) {
37033
37037
  if (deleteBranchOnMerge === false) return;
37034
37038
  throw new Error(
37035
- `pr merge: ${repo} does not prove delete_branch_on_merge=false. Automatic deletion can irreversibly close stacked PRs. Run \`mmi-cli devops ci reconcile --repo ${repo} --apply\`, then retry; remote branch cleanup is delayed.`
37039
+ `pr merge: ${repo} does not prove delete_branch_on_merge=false. Automatic deletion can irreversibly close stacked PRs. Run \`mmi-cli devops ci reconcile --repo ${repo} --apply\`, then retry; when that proof cannot be settled (or an active batch must merge now), rerun with --preserve-worktree \u2014 the designed settings-proof bypass (#6210). Remote branch cleanup is delayed either way.`
37036
37040
  );
37037
37041
  }
37038
37042
  function mergeMethodFromParentCount(parentCount) {
@@ -37692,11 +37696,35 @@ async function checkDocsIndexAtHead(opts, deps) {
37692
37696
  }
37693
37697
 
37694
37698
  // src/pr-create-claim-guard.ts
37699
+ var CLAIM_GUARD_RATE_LIMIT_WAIT_CAP_MS = 3e4;
37700
+ function withRateLimitRetry(client, seams = {}) {
37701
+ const throttledPaths = /* @__PURE__ */ new Set();
37702
+ const retry = (path2, op) => runWithRateLimitBackoff(op, {
37703
+ context: `pr create claim guard: GET ${path2}`,
37704
+ retryCommand: "re-run `mmi-cli devops pr create` after the rate limit resets",
37705
+ capMs: seams.rateLimitWaitCapMs ?? CLAIM_GUARD_RATE_LIMIT_WAIT_CAP_MS,
37706
+ now: seams.now,
37707
+ sleep: seams.sleep,
37708
+ log: seams.log
37709
+ }).catch((e) => {
37710
+ if (isRateLimitedError(e)) throttledPaths.add(path2);
37711
+ throw e;
37712
+ });
37713
+ return {
37714
+ // The guard path issues only REST reads; graphql passes through untouched.
37715
+ client: {
37716
+ rest: (method, path2, init) => retry(path2, () => client.rest(method, path2, init)),
37717
+ restPaginate: (path2, init) => retry(path2, () => client.restPaginate(path2, init)),
37718
+ graphql: (query, variables, init) => client.graphql(query, variables, init)
37719
+ },
37720
+ throttledPaths
37721
+ };
37722
+ }
37695
37723
  async function prCreateClaimRefusal(body, repoOption, deps = {}) {
37696
37724
  const issues = [...new Set(findClosingMentions(body).map((mention) => mention.issue))];
37697
37725
  if (!issues.length) return void 0;
37698
37726
  const repo = await requireRepo(repoOption);
37699
- const client = deps.client ?? defaultGitHubClient();
37727
+ const { client, throttledPaths } = withRateLimitRetry(deps.client ?? defaultGitHubClient(), deps);
37700
37728
  const actor = deps.actor ?? describeSessionIdentity();
37701
37729
  const checkContest = deps.checkContest ?? checkLaneContest;
37702
37730
  for (const number of issues) {
@@ -37705,7 +37733,8 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
37705
37733
  const contest = await checkContest(client, { repository: repo, number }, actor);
37706
37734
  if (!contest.contested) continue;
37707
37735
  const ref = `${repo}#${number}`;
37708
- const holder = contest.marker ? `lane ${describeClaimMarker(contest.marker)}` : "another lane";
37736
+ const commentsPath = `repos/${repo}/issues/${number}/comments`;
37737
+ const holder = contest.marker ? `lane ${describeClaimMarker(contest.marker)}` : contest.unverifiable.includes("comments") ? `an unreadable lane (its claim-marker comments could not be read${throttledPaths.has(commentsPath) ? " \u2014 GitHub rate-limited the read (HTTP 403) and the bounded reset-aware retry could not clear it" : ""}; the holder may be this very lane)` : "another lane";
37709
37738
  return `pr create: REFUSED \u2014 ${ref} is held by ${holder} with live or unreadable work evidence; run \`mmi-cli oracle board claim ${ref} --force\` (move it to In Progress first if it sits In Review) or drop the closing line before creating this PR`;
37710
37739
  }
37711
37740
  return void 0;
@@ -39657,7 +39686,7 @@ ${list}`);
39657
39686
  else printLine(`pr land: ${result.status}${result.error ? ` \u2014 ${result.error}` : ""}`);
39658
39687
  if (result.status === "failed") process.exitCode = 1;
39659
39688
  });
39660
- jsonParity(pr.command("merge <number>").description("merge a PR (squash by default); archives gitignored tmp/** before worktree teardown; on no-ci repos run pr ci-policy / checks-wait first (#1432, #5679)").option("--squash", "squash merge (default)").option("--merge", "create a merge commit").option("--rebase", "rebase merge").option("--repo <owner/repo>", "target repo (defaults to the current repo); from a foreign checkout the remote probe/delete address this repo and local cleanup runs only in the verified sibling checkout ../<repo>, else localBranch reports skipped-foreign-cwd and the receipt carries foreignCwd: true (#6148)").option("--auto", "enable auto-merge \u2014 merge once the base-branch policy is satisfied (use for policy-gated repos)").addOption(new Option("--disable-auto", "disable a queued auto-merge without merging").conflicts(["auto", "wait", "squash", "merge", "rebase", "preserveWorktree", "gc", "squashBodyFile", "force"])).option("--wait", `wait for checks to reach a terminal passing verdict before merging (default budget ${PR_CHECKS_TIMEOUT_MS / 6e4}m) \u2014 run as a background/monitor task or under a shell timeout above that budget; a short foreground timeout (e.g. 120s) kills it after checks pass and leaves the PR open (#6027)`).option("--preserve-worktree", "after merge, keep the local PR worktree/branch for an active batch (#1888)").option("--gc", "acknowledge deleting unarchived gitignored tmp/** evidence newer than the branch base (#5679)").option("--squash-body-file <path>", "squash commit body (overrides GitHub COMMIT_MESSAGES); use when a pushed commit mentions close/fix/resolve + #N that must not close (#5723)").option("--force", "acknowledge and merge past a remaining prunable/severe scratch housekeeping block (advisory kept plans/ never blocks, #3012) or a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal")).action(async (number, o) => {
39689
+ jsonParity(pr.command("merge <number>").description("merge a PR (squash by default); archives gitignored tmp/** before worktree teardown; on no-ci repos run pr ci-policy / checks-wait first (#1432, #5679)").option("--squash", "squash merge (default)").option("--merge", "create a merge commit").option("--rebase", "rebase merge").option("--repo <owner/repo>", "target repo (defaults to the current repo); from a foreign checkout the remote probe/delete address this repo and local cleanup runs only in the verified sibling checkout ../<repo>, else localBranch reports skipped-foreign-cwd and the receipt carries foreignCwd: true (#6148)").option("--auto", "enable auto-merge \u2014 merge once the base-branch policy is satisfied (use for policy-gated repos)").addOption(new Option("--disable-auto", "disable a queued auto-merge without merging").conflicts(["auto", "wait", "squash", "merge", "rebase", "preserveWorktree", "gc", "squashBodyFile", "force"])).option("--wait", `wait for checks to reach a terminal passing verdict before merging (default budget ${PR_CHECKS_TIMEOUT_MS / 6e4}m) \u2014 run as a background/monitor task or under a shell timeout above that budget; a short foreground timeout (e.g. 120s) kills it after checks pass and leaves the PR open (#6027)`).option("--preserve-worktree", "after merge, keep the local PR worktree/branch for an active batch (#1888); also the merge settings-proof bypass when delete_branch_on_merge cannot be proven (#6210)").option("--gc", "acknowledge deleting unarchived gitignored tmp/** evidence newer than the branch base (#5679)").option("--squash-body-file <path>", "squash commit body (overrides GitHub COMMIT_MESSAGES); use when a pushed commit mentions close/fix/resolve + #N that must not close (#5723)").option("--force", "acknowledge and merge past a remaining prunable/severe scratch housekeeping block (advisory kept plans/ never blocks, #3012) or a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal")).action(async (number, o) => {
39661
39690
  const method = o.rebase ? "--rebase" : o.merge ? "--merge" : "--squash";
39662
39691
  const repoArgs = o.repo ? ["--repo", o.repo] : [];
39663
39692
  if (o.disableAuto) {
@@ -39713,7 +39742,7 @@ ${list}`);
39713
39742
  if (!repoForPostCleanup) throw new Error("pr merge: repository is unreadable; cannot prove remote branch preservation");
39714
39743
  const repoSettings = await fetchRestRepoMergeSettings(repoForPostCleanup);
39715
39744
  if (!repoSettings.proven) {
39716
- throw new Error(`pr merge: ${repoForPostCleanup} cannot prove delete_branch_on_merge=false \u2014 ${repoSettings.reason}. Automatic deletion can irreversibly close stacked PRs (#5789).`);
39745
+ throw new Error(`pr merge: ${repoForPostCleanup} cannot prove delete_branch_on_merge=false \u2014 ${repoSettings.reason}. Automatic deletion can irreversibly close stacked PRs (#5789). When the proof cannot be settled (or an active batch must merge now), rerun with --preserve-worktree \u2014 the designed settings-proof bypass (#6210).`);
39717
39746
  }
39718
39747
  assertRemoteBranchPreservedOnMerge(repoForPostCleanup, repoSettings.deleteBranchOnMerge);
39719
39748
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.3.12",
3
+ "version": "4.3.13",
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",