@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.
- package/dist/main.cjs +42 -13
- 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.
|
|
15480
|
-
tag: "v4.3.
|
|
15481
|
-
commit: "
|
|
15482
|
-
npm: "@mutmutco/cli@4.3.
|
|
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.
|
|
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.
|
|
15506
|
-
v3Target: "v4.3.
|
|
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;
|
|
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
|
|
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