@mutmutco/cli 4.6.46 → 4.6.48
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 +39 -18
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -28556,10 +28556,10 @@ var rollout_plan_default = {
|
|
|
28556
28556
|
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)."
|
|
28557
28557
|
},
|
|
28558
28558
|
baseline: {
|
|
28559
|
-
version: "4.6.
|
|
28560
|
-
tag: "v4.6.
|
|
28561
|
-
commit: "
|
|
28562
|
-
npm: "@mutmutco/cli@4.6.
|
|
28559
|
+
version: "4.6.48",
|
|
28560
|
+
tag: "v4.6.48",
|
|
28561
|
+
commit: "9f3e651d8643",
|
|
28562
|
+
npm: "@mutmutco/cli@4.6.48"
|
|
28563
28563
|
},
|
|
28564
28564
|
exitCriterion: "fleet-n-of-n",
|
|
28565
28565
|
hubOnlyShortcut: "forbidden",
|
|
@@ -28576,14 +28576,14 @@ var rollout_plan_default = {
|
|
|
28576
28576
|
repo: "mutmutco/mmi-hub",
|
|
28577
28577
|
role: "canary",
|
|
28578
28578
|
schedule: "train",
|
|
28579
|
-
v3Target: "v4.6.
|
|
28579
|
+
v3Target: "v4.6.48"
|
|
28580
28580
|
}
|
|
28581
28581
|
],
|
|
28582
28582
|
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.",
|
|
28583
28583
|
rollback: {
|
|
28584
28584
|
independent: true,
|
|
28585
|
-
mechanism: "npm dist-tag latest -> 4.6.
|
|
28586
|
-
v3Target: "v4.6.
|
|
28585
|
+
mechanism: "npm dist-tag latest -> 4.6.48 and redeploy the Hub Lambda from tag v4.6.48 (9f3e651d8643); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
28586
|
+
v3Target: "v4.6.48 (@mutmutco/cli@4.6.48, tag commit 9f3e651d8643 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
28587
28587
|
}
|
|
28588
28588
|
},
|
|
28589
28589
|
{
|
|
@@ -42864,7 +42864,11 @@ async function runPrLandOnce(prNumber, options, deps) {
|
|
|
42864
42864
|
};
|
|
42865
42865
|
base.checksWait = await deps.waitForChecks(prNumber, repo);
|
|
42866
42866
|
const waitError = await checksWaitError(base.checksWait);
|
|
42867
|
-
if (waitError)
|
|
42867
|
+
if (waitError) {
|
|
42868
|
+
if (!hasQueue || base.checksWait.status === "conflicting") return { ...base, error: waitError };
|
|
42869
|
+
const noQueueEntry = /no-checks-reported/.test(base.checksWait.detail ?? "") ? `no merge-queue entry was created: workflow runs exist on the head but published no check-runs \u2014 inspect them with \`mmi-cli devops read run list --repo ${repo} --commit ${pinned ?? "<full head SHA>"}\`, then re-run \`mmi-cli devops pr land ${prNumber} --repo ${repo}\` once the required check exists` : "no merge-queue entry was created (the land stopped before enqueue)";
|
|
42870
|
+
return { ...base, error: `${waitError} \u2014 ${noQueueEntry}` };
|
|
42871
|
+
}
|
|
42868
42872
|
const driftAfterChecks = await headDrift("after checks");
|
|
42869
42873
|
if (driftAfterChecks) return driftAfterChecks;
|
|
42870
42874
|
prState = prState ?? await readPrState();
|
|
@@ -42883,7 +42887,7 @@ async function runPrLandOnce(prNumber, options, deps) {
|
|
|
42883
42887
|
}
|
|
42884
42888
|
base.checksWait = await deps.waitForChecks(prNumber, repo);
|
|
42885
42889
|
const reWaitError = await checksWaitError(base.checksWait);
|
|
42886
|
-
if (reWaitError) return { ...base, error:
|
|
42890
|
+
if (reWaitError) return { ...base, error: reWaitError };
|
|
42887
42891
|
prState = await readPrState();
|
|
42888
42892
|
}
|
|
42889
42893
|
if (isConflicting(prState)) return { ...base, error: conflictError() };
|
|
@@ -44185,8 +44189,8 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
|
|
|
44185
44189
|
error: `queue submission outcome unknown: ${reason}. Never hand-edit files under the mmi-cli queue-admissions receipt store (%LOCALAPPDATA%/MMI Future/mmi-cli/queue-admissions); read the queue entry with \`mmi-cli devops read pr queue ${pr} --repo ${repo} --json\`; once the PR is verifiably OPEN at the submitted head and absent from the queue, abandon the stuck admission with \`mmi-cli devops pr land ${pr} --repo ${repo} --abandon-admission\` so a new intent needs no new head \u2014 no new request was sent after this uncertainty.`
|
|
44186
44190
|
});
|
|
44187
44191
|
const rejected = (reason) => markReenqueued(admissionRejected(reason, repo, pr));
|
|
44188
|
-
const reconcile = async (reason, recordEntry = false, resumingSaved = false) => {
|
|
44189
|
-
const maxReads = options.enqueueOnly ? 3 : 1;
|
|
44192
|
+
const reconcile = async (reason, recordEntry = false, resumingSaved = false, minReads = 1) => {
|
|
44193
|
+
const maxReads = Math.max(options.enqueueOnly ? 3 : 1, minReads);
|
|
44190
44194
|
const sleep3 = options.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
44191
44195
|
for (let readAttempt = 0; readAttempt < maxReads; readAttempt++) {
|
|
44192
44196
|
if (readAttempt) await sleep3(readAttempt * 1e3);
|
|
@@ -44317,7 +44321,7 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
|
|
|
44317
44321
|
try {
|
|
44318
44322
|
response = admissionResponse(output);
|
|
44319
44323
|
} catch {
|
|
44320
|
-
return reconcile("the send response was lost or malformed");
|
|
44324
|
+
return reconcile("the send response was lost or malformed, and queue membership at the submitted head was re-read and not confirmed", true, false, 3);
|
|
44321
44325
|
}
|
|
44322
44326
|
const { code, body } = response;
|
|
44323
44327
|
if (code === 200 && ["enqueued", "merged"].includes(body.status ?? "")) {
|
|
@@ -48241,7 +48245,11 @@ function tenantTaskWriteRefusal(existing, patch) {
|
|
|
48241
48245
|
const sent = patch.tenantTasks;
|
|
48242
48246
|
if (sent === null || sent === void 0) return null;
|
|
48243
48247
|
const merged = /* @__PURE__ */ new Set([...Object.keys(stored), ...Object.keys(sent)]);
|
|
48244
|
-
if (merged.size > 20)
|
|
48248
|
+
if (merged.size > 20) {
|
|
48249
|
+
const repo = existing?.repos?.[0] || "<owner/repo>";
|
|
48250
|
+
const names = Object.keys(stored).sort();
|
|
48251
|
+
return `org project set: ${slug} would hold ${merged.size} tenantTasks (${names.length} declared today); the cap is 20 \u2014 retire one first with \`mmi-cli oracle org project set ${repo} --unset-task <name>\`. Declared: ${names.join(", ") || "(none)"}`;
|
|
48252
|
+
}
|
|
48245
48253
|
return null;
|
|
48246
48254
|
}
|
|
48247
48255
|
function secretRemovalRefusal(existing, patch) {
|
|
@@ -63092,6 +63100,14 @@ function isPathAtOrWithin(path2, worktreePath) {
|
|
|
63092
63100
|
function isWindowsCwdLockResidueError(error) {
|
|
63093
63101
|
return process.platform === "win32" && /\bEPERM\b|access(?: is)? denied/i.test(error);
|
|
63094
63102
|
}
|
|
63103
|
+
function isNodeModulesLockError(error) {
|
|
63104
|
+
return /^(?:EPERM|EACCES|EBUSY)\b/.test(error);
|
|
63105
|
+
}
|
|
63106
|
+
function deferredNodeModulesLockRemediation(wtPath, branch, prNumber, repo) {
|
|
63107
|
+
const quote = (value) => value.replace(/'/g, "''");
|
|
63108
|
+
const rerun = `mmi-cli devops pr merge ${prNumber ?? "<pr>"}${repo ? ` --repo ${repo}` : ""}`;
|
|
63109
|
+
return `Close the handle on the locked file under '${quote((0, import_node_path49.join)(wtPath, "node_modules"))}', then from the primary checkout re-run cleanup for branch '${quote(branch)}': ${rerun}`;
|
|
63110
|
+
}
|
|
63095
63111
|
function deferredCwdLockRemediation(wtPath) {
|
|
63096
63112
|
const quote = (path2) => path2.replace(/'/g, "''");
|
|
63097
63113
|
return `After leaving the directory and closing its handles, remove it only if empty: [System.IO.Directory]::Delete('${quote(wtPath)}', $false)`;
|
|
@@ -63408,7 +63424,7 @@ async function removeWorktreeWithReconcile(wtPath, git3, listWorktrees, pathExis
|
|
|
63408
63424
|
}
|
|
63409
63425
|
function isPrMergeWorktreePartial(cleanup) {
|
|
63410
63426
|
const worktree = cleanup?.worktree;
|
|
63411
|
-
return Boolean(worktree?.path && worktree.status !== "removed" && worktree.status !== "preserved" && worktree.status !== "retained-locked" && worktree.status !== "switched-primary");
|
|
63427
|
+
return Boolean(worktree?.path && worktree.status !== "removed" && worktree.status !== "preserved" && worktree.status !== "retained-locked" && worktree.status !== "switched-primary" && worktree.status !== "deferred");
|
|
63412
63428
|
}
|
|
63413
63429
|
function prMergeLocalCleanupExitCode(cleanup) {
|
|
63414
63430
|
return cleanup?.worktree?.status === "failed" || cleanup?.localBranch?.status === "failed" ? 1 : void 0;
|
|
@@ -63567,18 +63583,19 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
63567
63583
|
if (pathExists((0, import_node_path49.join)(wtPath, "node_modules"))) {
|
|
63568
63584
|
const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
|
|
63569
63585
|
if (!nmRemoved.ok) {
|
|
63586
|
+
const deferred = isNodeModulesLockError(nmRemoved.error) && pathExists(wtPath);
|
|
63570
63587
|
report.worktree = {
|
|
63571
63588
|
path: wtPath,
|
|
63572
|
-
status: "failed",
|
|
63573
|
-
reason: "pre-clean-failed",
|
|
63589
|
+
status: deferred ? "deferred" : "failed",
|
|
63590
|
+
reason: deferred ? "node-modules-locked" : "pre-clean-failed",
|
|
63574
63591
|
error: `real-node_modules cleanup failed before worktree removal: ${nmRemoved.error}`,
|
|
63575
63592
|
artifactsArchive,
|
|
63576
63593
|
stageTeardown,
|
|
63577
63594
|
tmpEvidenceCount: tmpEvidence.length,
|
|
63578
63595
|
...unlinkedReparsePoints.length ? { unlinkedReparsePoints } : {},
|
|
63579
|
-
remediation: `Close handles to '${wtPath.replace(/'/g, "''")}' and retry MMI PR landing from the primary checkout`
|
|
63596
|
+
remediation: deferred ? deferredNodeModulesLockRemediation(wtPath, branch, options.prNumber, options.repo) : `Close handles to '${wtPath.replace(/'/g, "''")}' and retry MMI PR landing from the primary checkout`
|
|
63580
63597
|
};
|
|
63581
|
-
report.localBranch = { name: branch, status: "not-attempted", reason: "worktree-pre-clean-failed" };
|
|
63598
|
+
report.localBranch = { name: branch, status: "not-attempted", reason: deferred ? "worktree-cleanup-deferred" : "worktree-pre-clean-failed" };
|
|
63582
63599
|
return report;
|
|
63583
63600
|
}
|
|
63584
63601
|
}
|
|
@@ -63677,6 +63694,8 @@ function renderPrMergeCleanupLines(cleanup) {
|
|
|
63677
63694
|
lines2.push(`pr merge: preserved worktree ${wt.path} (--preserve-worktree)`);
|
|
63678
63695
|
} else if (wt.status === "retained-locked") {
|
|
63679
63696
|
lines2.push(`pr merge: worktree ${wt.path} cleanup deferred \u2014 its Windows parent shell still holds the cwd; ${wt.remediation ?? "exit the shell and remove the residue from the primary checkout"}`);
|
|
63697
|
+
} else if (wt.status === "deferred") {
|
|
63698
|
+
lines2.push(`pr merge: worktree ${wt.path} cleanup deferred \u2014 a node_modules file is locked${wt.error ? ` (${wt.error})` : ""}; ${wt.remediation ?? "close the handle and re-run pr merge for this PR"}`);
|
|
63680
63699
|
} else if (wt.status === "switched-primary") {
|
|
63681
63700
|
const now = wt.switchedTo ? `to ${wt.switchedTo}` : "to the base branch";
|
|
63682
63701
|
lines2.push(wt.error ? `pr merge: primary checkout ${wt.path} switched ${now} but deleting the merged branch failed \u2014 ${wt.error}; remediate: ${wt.remediation ?? "delete the merged branch manually"}` : `pr merge: primary checkout ${wt.path} held the merged branch \u2014 switched it back ${now} and deleted the branch`);
|
|
@@ -65629,6 +65648,8 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
|
|
|
65629
65648
|
preserveWorktree: o.preserveWorktree,
|
|
65630
65649
|
gcAcknowledged: o.gc,
|
|
65631
65650
|
expectedHeadOid: headRefOid,
|
|
65651
|
+
prNumber: number,
|
|
65652
|
+
repo: repoForPostCleanup,
|
|
65632
65653
|
pathExists: (p) => (0, import_node_fs54.existsSync)(p),
|
|
65633
65654
|
// #5899: pin cleanup git calls to the main checkout — the task worktree this process may be
|
|
65634
65655
|
// standing in is removed mid-cleanup, so a cwd-relative invocation fails with
|
package/package.json
CHANGED