@mutmutco/cli 4.5.196 → 4.5.198
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 +89 -20
- package/dist/runbook-sweep.cjs +1 -0
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -7798,7 +7798,7 @@ function waitReadFailureMessage(e) {
|
|
|
7798
7798
|
}
|
|
7799
7799
|
var PR_CHECKS_POLL_MS = 6e4;
|
|
7800
7800
|
function pollIntervalMs(elapsedMs) {
|
|
7801
|
-
return Math.min(4 * PR_CHECKS_POLL_MS, PR_CHECKS_POLL_MS * 2 ** Math.floor(Math.max(0, elapsedMs) /
|
|
7801
|
+
return Math.min(4 * PR_CHECKS_POLL_MS, PR_CHECKS_POLL_MS * 2 ** Math.floor(Math.max(0, elapsedMs) / 9e5));
|
|
7802
7802
|
}
|
|
7803
7803
|
var PR_CHECKS_TIMEOUT_MS = 30 * 6e4;
|
|
7804
7804
|
var PR_CHECKS_SUCCESS_CONFIRMATIONS = 2;
|
|
@@ -19279,10 +19279,10 @@ var rollout_plan_default = {
|
|
|
19279
19279
|
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)."
|
|
19280
19280
|
},
|
|
19281
19281
|
baseline: {
|
|
19282
|
-
version: "4.5.
|
|
19283
|
-
tag: "v4.5.
|
|
19284
|
-
commit: "
|
|
19285
|
-
npm: "@mutmutco/cli@4.5.
|
|
19282
|
+
version: "4.5.198",
|
|
19283
|
+
tag: "v4.5.198",
|
|
19284
|
+
commit: "6d3c999e17f5",
|
|
19285
|
+
npm: "@mutmutco/cli@4.5.198"
|
|
19286
19286
|
},
|
|
19287
19287
|
exitCriterion: "fleet-n-of-n",
|
|
19288
19288
|
hubOnlyShortcut: "forbidden",
|
|
@@ -19299,14 +19299,14 @@ var rollout_plan_default = {
|
|
|
19299
19299
|
repo: "mutmutco/mmi-hub",
|
|
19300
19300
|
role: "canary",
|
|
19301
19301
|
schedule: "train",
|
|
19302
|
-
v3Target: "v4.5.
|
|
19302
|
+
v3Target: "v4.5.198"
|
|
19303
19303
|
}
|
|
19304
19304
|
],
|
|
19305
19305
|
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.",
|
|
19306
19306
|
rollback: {
|
|
19307
19307
|
independent: true,
|
|
19308
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
19309
|
-
v3Target: "v4.5.
|
|
19308
|
+
mechanism: "npm dist-tag latest -> 4.5.198 and redeploy the Hub Lambda from tag v4.5.198 (6d3c999e17f5); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
19309
|
+
v3Target: "v4.5.198 (@mutmutco/cli@4.5.198, tag commit 6d3c999e17f5 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
19310
19310
|
}
|
|
19311
19311
|
},
|
|
19312
19312
|
{
|
|
@@ -30269,6 +30269,69 @@ function auditRunnerFallbacks(repo, files) {
|
|
|
30269
30269
|
}
|
|
30270
30270
|
return checks;
|
|
30271
30271
|
}
|
|
30272
|
+
var PENDING_LANDING_LABEL = "pending PRs landing (#8783)";
|
|
30273
|
+
var PENDING_LANDING_LIST_CAP = 50;
|
|
30274
|
+
var PENDING_LANDING_STALL_MS = 15 * 60 * 1e3;
|
|
30275
|
+
function summarizePendingLanding(nodes, base, capped, now) {
|
|
30276
|
+
const prs = nodes.filter((n) => !n.isDraft);
|
|
30277
|
+
const s = {
|
|
30278
|
+
base,
|
|
30279
|
+
considered: prs.length,
|
|
30280
|
+
capped,
|
|
30281
|
+
autoMergeRequested: 0,
|
|
30282
|
+
autoMergeNotRequested: 0,
|
|
30283
|
+
inMergeQueue: 0,
|
|
30284
|
+
blockers: { DIRTY: 0, BLOCKED: 0, BEHIND: 0, UNKNOWN: 0, CLEAN_NOT_QUEUED: 0 },
|
|
30285
|
+
stalled: []
|
|
30286
|
+
};
|
|
30287
|
+
for (const pr of prs) {
|
|
30288
|
+
const requested = Boolean(pr.autoMergeRequest);
|
|
30289
|
+
const queued = pr.isInMergeQueue === true;
|
|
30290
|
+
if (requested) s.autoMergeRequested++;
|
|
30291
|
+
else s.autoMergeNotRequested++;
|
|
30292
|
+
if (queued) s.inMergeQueue++;
|
|
30293
|
+
const state = pr.mergeStateStatus ?? "UNKNOWN";
|
|
30294
|
+
if (state === "DIRTY") s.blockers.DIRTY++;
|
|
30295
|
+
else if (state === "BLOCKED") s.blockers.BLOCKED++;
|
|
30296
|
+
else if (state === "BEHIND") s.blockers.BEHIND++;
|
|
30297
|
+
else if (state === "CLEAN") {
|
|
30298
|
+
if (!requested && !queued) {
|
|
30299
|
+
s.blockers.CLEAN_NOT_QUEUED++;
|
|
30300
|
+
const updated = Date.parse(pr.updatedAt ?? "");
|
|
30301
|
+
if (Number.isFinite(updated) && now - updated > PENDING_LANDING_STALL_MS) s.stalled.push(pr.number);
|
|
30302
|
+
}
|
|
30303
|
+
} else if (state !== "HAS_HOOKS" && state !== "UNSTABLE") s.blockers.UNKNOWN++;
|
|
30304
|
+
}
|
|
30305
|
+
return s;
|
|
30306
|
+
}
|
|
30307
|
+
function pendingLandingCheck(summary, base) {
|
|
30308
|
+
if (!summary) {
|
|
30309
|
+
return { ok: true, severity: "info", label: PENDING_LANDING_LABEL, detail: `UNAVAILABLE: open-PR read for ${base} failed \u2014 counts unknown, not zero` };
|
|
30310
|
+
}
|
|
30311
|
+
const b = summary.blockers;
|
|
30312
|
+
const detail = `${summary.considered} open non-draft PR(s) into ${base}${summary.capped ? ` (capped: first ${PENDING_LANDING_LIST_CAP} by most recent update; more exist)` : ""}; auto-merge REQUESTED on ${summary.autoMergeRequested}, not requested on ${summary.autoMergeNotRequested} (per-PR requests, not the repo allow_auto_merge permission); in merge queue ${summary.inMergeQueue}; blockers: DIRTY ${b.DIRTY}, BLOCKED ${b.BLOCKED}, BEHIND ${b.BEHIND}, UNKNOWN ${b.UNKNOWN}, CLEAN-not-queued ${b.CLEAN_NOT_QUEUED}` + (summary.stalled.length ? `; STALLED (CLEAN, no auto-merge request or queue entry, idle >15 min): ${summary.stalled.map((n) => `#${n}`).join(", ")}` : "");
|
|
30313
|
+
return {
|
|
30314
|
+
ok: true,
|
|
30315
|
+
severity: summary.stalled.length ? "warn" : "info",
|
|
30316
|
+
label: PENDING_LANDING_LABEL,
|
|
30317
|
+
detail,
|
|
30318
|
+
remediation: summary.stalled.length ? "mmi-cli pr land <n> --repo <repo> for each stalled PR" : void 0
|
|
30319
|
+
};
|
|
30320
|
+
}
|
|
30321
|
+
async function auditPendingLanding(repo, base, deps) {
|
|
30322
|
+
try {
|
|
30323
|
+
const [owner, name] = repo.split("/");
|
|
30324
|
+
const data = await deps.client.graphql(
|
|
30325
|
+
"query($owner:String!,$name:String!,$base:String!,$n:Int!){repository(owner:$owner,name:$name){pullRequests(states:OPEN,baseRefName:$base,first:$n,orderBy:{field:UPDATED_AT,direction:DESC}){totalCount nodes{number isDraft updatedAt mergeStateStatus isInMergeQueue autoMergeRequest{enabledAt}}}}}",
|
|
30326
|
+
{ owner, name, base, n: PENDING_LANDING_LIST_CAP }
|
|
30327
|
+
);
|
|
30328
|
+
const prs = data?.repository?.pullRequests;
|
|
30329
|
+
if (!prs?.nodes) return pendingLandingCheck(void 0, base);
|
|
30330
|
+
return pendingLandingCheck(summarizePendingLanding(prs.nodes, base, (prs.totalCount ?? 0) > prs.nodes.length, (deps.now ?? Date.now)()), base);
|
|
30331
|
+
} catch {
|
|
30332
|
+
return pendingLandingCheck(void 0, base);
|
|
30333
|
+
}
|
|
30334
|
+
}
|
|
30272
30335
|
function slugFromRepo(repo) {
|
|
30273
30336
|
return (repo.includes("/") ? repo.split("/")[1] : repo).toLowerCase();
|
|
30274
30337
|
}
|
|
@@ -30973,6 +31036,7 @@ async function auditRepoCi(repo, callerDeps) {
|
|
|
30973
31036
|
const fresh = await auditDevStageFreshness(repo, deps);
|
|
30974
31037
|
if (fresh) checks.push(fresh);
|
|
30975
31038
|
}
|
|
31039
|
+
checks.push(await auditPendingLanding(repo, baseBranch, deps));
|
|
30976
31040
|
const failure = unauditedReason();
|
|
30977
31041
|
if (failure) {
|
|
30978
31042
|
return { repo, class: repoClass, mergePolicy: policy, ok: false, checks: [], explicitNoCi, unauditedReason: failure };
|
|
@@ -31021,6 +31085,8 @@ function renderCiAuditMarkdown(report) {
|
|
|
31021
31085
|
const gap = r.unauditedReason ? `CANNOT AUDIT \u2014 ${r.unauditedReason}` : r.checks.find((c) => !c.ok)?.label ?? "\u2014";
|
|
31022
31086
|
lines2.push(`| ${r.repo} | ${r.class} | ${r.mergePolicy} | ${r.ok ? "yes" : "no"} | ${gap} |`);
|
|
31023
31087
|
}
|
|
31088
|
+
const advisories = report.repos.flatMap((r) => r.checks.filter((c) => c.severity && c.label === PENDING_LANDING_LABEL).map((c) => `- ${c.severity === "warn" ? "WARN" : "INFO"} ${r.repo}: ${c.label} \u2014 ${c.detail ?? ""}`));
|
|
31089
|
+
if (advisories.length) lines2.push("", ...advisories);
|
|
31024
31090
|
return lines2.join("\n");
|
|
31025
31091
|
}
|
|
31026
31092
|
function renderCiAuditText(report) {
|
|
@@ -31037,7 +31103,7 @@ ${r.repo} (${r.class}, policy=${r.mergePolicy}) ${verdict}`);
|
|
|
31037
31103
|
continue;
|
|
31038
31104
|
}
|
|
31039
31105
|
for (const c of r.checks) {
|
|
31040
|
-
lines2.push(` ${c.ok ? "
|
|
31106
|
+
lines2.push(` ${!c.ok ? "FAIL" : c.severity === "warn" ? "WARN" : c.severity === "info" ? "INFO" : "OK"} ${c.label}${c.detail ? ` \u2014 ${c.detail}` : ""}`);
|
|
31041
31107
|
}
|
|
31042
31108
|
}
|
|
31043
31109
|
return lines2.join("\n");
|
|
@@ -42913,19 +42979,18 @@ function evaluatePrMergeHousekeeping(report, context, force = false) {
|
|
|
42913
42979
|
const failed2 = scratch?.status === "failed";
|
|
42914
42980
|
const prunable = scratch?.safeAuto ?? 0;
|
|
42915
42981
|
const unprunable = scratch?.skipped ?? 0;
|
|
42916
|
-
if (!(failed2 || prunable > 0 || unprunable > 0)) return {
|
|
42917
|
-
if (force) return { blocked: false };
|
|
42982
|
+
if (!(failed2 || prunable > 0 || unprunable > 0) || force) return {};
|
|
42918
42983
|
const detail = failed2 ? `scratch housekeeping failed${scratch?.error ? `: ${scratch.error}` : ""}` : `${prunable} prunable + ${unprunable} un-prunable scratch item(s) remain after cleanup`;
|
|
42919
42984
|
return {
|
|
42920
|
-
|
|
42921
|
-
reason: `${context} housekeeping blocked merge: ${detail}. Run \`mmi-cli doctor --apply\` to prune aged repo-root scratch (or \`mmi-cli doctor --verbose\` to inspect what could not be removed), then retry \u2014 or re-run \`mmi-cli devops ${context} --force\` to acknowledge an unresolved scratch block without cleaning it and proceed anyway. (Kept advisory plans/ scratch never blocks: it is gitignored and can never reach origin.)`
|
|
42985
|
+
warning: `${context} housekeeping warning (not blocking): ${detail}. Run \`mmi-cli doctor --apply\` to prune aged repo-root scratch (or \`mmi-cli doctor --verbose\` to inspect what could not be removed). Local scratch never reaches origin, so the merge proceeds.`
|
|
42922
42986
|
};
|
|
42923
42987
|
}
|
|
42924
|
-
function
|
|
42988
|
+
function reportPrMergeHousekeeping(startingPath, context, options = {}) {
|
|
42925
42989
|
const build = options.buildHousekeeping ?? ((repoRoot2) => buildPrMergeScratchHousekeeping(repoRoot2));
|
|
42926
42990
|
const housekeeping = build(startingPath || process.cwd());
|
|
42927
42991
|
const verdict = evaluatePrMergeHousekeeping(housekeeping, context, options.force);
|
|
42928
|
-
if (verdict.
|
|
42992
|
+
if (verdict.warning) process.stderr.write(`${verdict.warning}
|
|
42993
|
+
`);
|
|
42929
42994
|
return housekeeping;
|
|
42930
42995
|
}
|
|
42931
42996
|
async function pollGhPrChecks(prNumber, repoArgs) {
|
|
@@ -48696,7 +48761,7 @@ ${list}`);
|
|
|
48696
48761
|
}
|
|
48697
48762
|
class PrHeadBehindBaseError extends Error {
|
|
48698
48763
|
}
|
|
48699
|
-
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("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "
|
|
48764
|
+
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("--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 the queue's own check timeout is 60)`).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) => {
|
|
48700
48765
|
const timeoutMinutes = opts.timeout === void 0 ? void 0 : Number(opts.timeout);
|
|
48701
48766
|
if (timeoutMinutes !== void 0 && !(timeoutMinutes > 0)) return fail("pr land: --timeout must be a positive number of minutes");
|
|
48702
48767
|
if (opts.expectHead !== void 0) {
|
|
@@ -48721,7 +48786,7 @@ ${list}`);
|
|
|
48721
48786
|
}
|
|
48722
48787
|
const repoArgs = o.repo ? ["--repo", o.repo] : [];
|
|
48723
48788
|
const startingPath = (await execFileP("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
|
|
48724
|
-
|
|
48789
|
+
reportPrMergeHousekeeping(startingPath || process.cwd(), "pr land", { force: o.force });
|
|
48725
48790
|
const landRepoForGuard = await resolveRepo(o.repo).catch(() => void 0) ?? o.repo;
|
|
48726
48791
|
const landClosingGuardInput = await withAlreadyClosedCommitTargets(
|
|
48727
48792
|
await readClosingGuardInput(number, repoArgs, landRepoForGuard, "pr land"),
|
|
@@ -48816,7 +48881,11 @@ ${list}`);
|
|
|
48816
48881
|
log: (message2) => console.warn(message2),
|
|
48817
48882
|
// `pr land` inherits the same (raised) checks budget, so it needs the same liveness — otherwise the
|
|
48818
48883
|
// 30m wait is SILENT and reads exactly like the hang #2940 was filed about, only three times longer.
|
|
48819
|
-
progress: ({ state, elapsedMs, remainingMs }) =>
|
|
48884
|
+
progress: ({ state, elapsedMs, remainingMs }) => (
|
|
48885
|
+
// #8797: the wait counts only required checks; an aggregator like `gate` appears only after its
|
|
48886
|
+
// needs finish, so "no-checks-reported" there means CI is still running, not that nothing ran.
|
|
48887
|
+
console.warn(`pr land: waiting on checks \u2014 ${state === "no-checks-reported" ? "required check not created yet (CI running)" : state}, ${Math.round(elapsedMs / 1e3)}s elapsed, ${Math.round(remainingMs / 6e4)}m left`)
|
|
48888
|
+
)
|
|
48820
48889
|
});
|
|
48821
48890
|
},
|
|
48822
48891
|
// #2425: re-probe used ONLY to decide whether a failed `gh pr merge --auto` is worth retrying — a
|
|
@@ -48950,7 +49019,7 @@ ${list}`);
|
|
|
48950
49019
|
}
|
|
48951
49020
|
if (entries.some((e) => e.outcome !== "merged" && e.outcome !== "queued")) process.exitCode = 1;
|
|
48952
49021
|
});
|
|
48953
|
-
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); on a merge-queue base use `pr land <n> [<n>...]` instead (#8322) \u2014 this verb is refused there except for train PRs").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", "
|
|
49022
|
+
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); on a merge-queue base use `pr land <n> [<n>...]` instead (#8322) \u2014 this verb is refused there except for train PRs").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", "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")).action(async (number, o) => {
|
|
48954
49023
|
const method = o.rebase ? "--rebase" : o.merge ? "--merge" : "--squash";
|
|
48955
49024
|
const repoArgs = o.repo ? ["--repo", o.repo] : [];
|
|
48956
49025
|
if (o.disableAuto) {
|
|
@@ -49010,7 +49079,7 @@ ${list}`);
|
|
|
49010
49079
|
assertRemoteBranchPreservedOnMerge(repoForPostCleanup, repoSettings.deleteBranchOnMerge);
|
|
49011
49080
|
}
|
|
49012
49081
|
const startingPath = (await execFileP("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
|
|
49013
|
-
const housekeeping =
|
|
49082
|
+
const housekeeping = reportPrMergeHousekeeping(startingPath || process.cwd(), "pr merge", { force: o.force });
|
|
49014
49083
|
const beforeWorktreesRead = await execFileP("git", ["worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => ({ state: "ok", stdout: r.stdout })).catch((e) => ({ state: "failed", error: e.message || "git worktree list failed" }));
|
|
49015
49084
|
let beforeWorktrees = beforeWorktreesRead.state === "ok" ? parseGitWorktreePorcelain(beforeWorktreesRead.stdout) : [];
|
|
49016
49085
|
const cwdRepo = repoFromRemoteUrl(await gitOut(["remote", "get-url", "origin"]).catch(() => ""));
|
package/dist/runbook-sweep.cjs
CHANGED
|
@@ -5827,6 +5827,7 @@ function registryRepoKey(repo) {
|
|
|
5827
5827
|
// src/ci-audit.ts
|
|
5828
5828
|
var HUB_REPO4 = "mutmutco/MMI-Hub";
|
|
5829
5829
|
var DEV_STAGE_STALE_TOLERANCE_MS = 30 * 60 * 1e3;
|
|
5830
|
+
var PENDING_LANDING_STALL_MS = 15 * 60 * 1e3;
|
|
5830
5831
|
function collectRegistryRepos(projects) {
|
|
5831
5832
|
const seen = /* @__PURE__ */ new Map();
|
|
5832
5833
|
for (const project of projects) {
|
package/package.json
CHANGED