@mutmutco/cli 3.111.0 → 3.112.0
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 +51 -14
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -7686,14 +7686,27 @@ function validateDeadWorktreeDirCleanup(planned, inspected) {
|
|
|
7686
7686
|
}
|
|
7687
7687
|
return { ok: true };
|
|
7688
7688
|
}
|
|
7689
|
-
function
|
|
7689
|
+
function describeLeftoverEntries(entries) {
|
|
7690
|
+
const shown = entries.slice(0, 8);
|
|
7691
|
+
const more = entries.length > shown.length ? `, +${entries.length - shown.length} more` : "";
|
|
7692
|
+
return `${shown.join(", ")}${more}`;
|
|
7693
|
+
}
|
|
7694
|
+
function validateDeadWorktreeDirContent(planned, inspected, options = {}) {
|
|
7690
7695
|
if (!inspected.entries) return { ok: false, reason: inspected.error ?? "unable to inspect directory contents" };
|
|
7691
7696
|
const entries = inspected.entries.filter(Boolean);
|
|
7692
7697
|
if (planned.reason === "orphaned-folder") {
|
|
7693
|
-
|
|
7698
|
+
if (entries.length === 0 || options.force) return { ok: true };
|
|
7699
|
+
return {
|
|
7700
|
+
ok: false,
|
|
7701
|
+
reason: `orphaned worktree directory still contains files: ${describeLeftoverEntries(entries)} \u2014 re-run with --force to remove anyway`
|
|
7702
|
+
};
|
|
7694
7703
|
}
|
|
7695
7704
|
if (planned.reason === "dangling-gitdir") {
|
|
7696
|
-
|
|
7705
|
+
if (entries.length === 1 && entries[0] === ".git" || options.force) return { ok: true };
|
|
7706
|
+
return {
|
|
7707
|
+
ok: false,
|
|
7708
|
+
reason: `dangling worktree directory (git registration already severed) still contains files: ${describeLeftoverEntries(entries)} \u2014 re-run with --force to remove anyway`
|
|
7709
|
+
};
|
|
7697
7710
|
}
|
|
7698
7711
|
return { ok: false, reason: "unknown dead worktree cleanup kind" };
|
|
7699
7712
|
}
|
|
@@ -13252,7 +13265,10 @@ async function fetchTrainAuthority(repo, deps) {
|
|
|
13252
13265
|
headers: { Authorization: `Bearer ${token}` }
|
|
13253
13266
|
});
|
|
13254
13267
|
if (res.status === 426) return { ok: false, error: upgradeRequiredError(res, await res.json().catch(() => null)) };
|
|
13255
|
-
if (!res.ok)
|
|
13268
|
+
if (!res.ok) {
|
|
13269
|
+
const detail = (await res.json().catch(() => null))?.error;
|
|
13270
|
+
return { ok: false, error: detail ? `train-authority HTTP ${res.status}: ${detail}` : `train-authority HTTP ${res.status}` };
|
|
13271
|
+
}
|
|
13256
13272
|
const body = await res.json();
|
|
13257
13273
|
if (typeof body?.train !== "boolean" || !body.role) return { ok: false, error: "malformed train-authority response" };
|
|
13258
13274
|
return { ok: true, authority: body };
|
|
@@ -15618,10 +15634,10 @@ var rollout_plan_default = {
|
|
|
15618
15634
|
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)."
|
|
15619
15635
|
},
|
|
15620
15636
|
baseline: {
|
|
15621
|
-
version: "3.
|
|
15622
|
-
tag: "v3.
|
|
15623
|
-
commit: "
|
|
15624
|
-
npm: "@mutmutco/cli@3.
|
|
15637
|
+
version: "3.112.0",
|
|
15638
|
+
tag: "v3.112.0",
|
|
15639
|
+
commit: "e6eaa0103b25",
|
|
15640
|
+
npm: "@mutmutco/cli@3.112.0"
|
|
15625
15641
|
},
|
|
15626
15642
|
exitCriterion: "fleet-n-of-n",
|
|
15627
15643
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15638,14 +15654,14 @@ var rollout_plan_default = {
|
|
|
15638
15654
|
repo: "mutmutco/mmi-hub",
|
|
15639
15655
|
role: "canary",
|
|
15640
15656
|
schedule: "train",
|
|
15641
|
-
v3Target: "v3.
|
|
15657
|
+
v3Target: "v3.112.0"
|
|
15642
15658
|
}
|
|
15643
15659
|
],
|
|
15644
15660
|
rollbackTrigger: "Any red inside the post-cut soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a v3 client refused while the compat window must still admit it (SUPPORTED_MINOR_WINDOW=2, MIN_CLIENT_VERSION 0.0.0 \u2014 D6a), or npm consumer install/doctor failure on the v4 dist.",
|
|
15645
15661
|
rollback: {
|
|
15646
15662
|
independent: true,
|
|
15647
|
-
mechanism: "npm dist-tag latest -> 3.
|
|
15648
|
-
v3Target: "v3.
|
|
15663
|
+
mechanism: "npm dist-tag latest -> 3.112.0 and redeploy the Hub Lambda from tag v3.112.0 (e6eaa0103b25); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15664
|
+
v3Target: "v3.112.0 (@mutmutco/cli@3.112.0, tag commit e6eaa0103b25 \u2014 the preserved latest-v3 distribution, D6b)"
|
|
15649
15665
|
}
|
|
15650
15666
|
},
|
|
15651
15667
|
{
|
|
@@ -32802,7 +32818,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
|
|
|
32802
32818
|
result.failed.push(`${wt.path}: skipped dead-dir removal (${stillValid.reason})`);
|
|
32803
32819
|
continue;
|
|
32804
32820
|
}
|
|
32805
|
-
const contentSafe = validateDeadWorktreeDirContent(wt, inspectDeadWorktreeDirContent(wt.path));
|
|
32821
|
+
const contentSafe = validateDeadWorktreeDirContent(wt, inspectDeadWorktreeDirContent(wt.path), { force: opts.force });
|
|
32806
32822
|
if (!contentSafe.ok) {
|
|
32807
32823
|
result.failed.push(`${wt.path}: skipped dead-dir removal (${contentSafe.reason})`);
|
|
32808
32824
|
continue;
|
|
@@ -33780,6 +33796,17 @@ function landSteps(branch, hasWorktree, hasStage) {
|
|
|
33780
33796
|
steps.push("prune worktree metadata");
|
|
33781
33797
|
return steps;
|
|
33782
33798
|
}
|
|
33799
|
+
function describeLandUnresolvableWorktree(inspection) {
|
|
33800
|
+
if (inspection.gitType === "missing") {
|
|
33801
|
+
return "this directory has no .git at all \u2014 its worktree registration is gone";
|
|
33802
|
+
}
|
|
33803
|
+
if (inspection.gitType === "file" && inspection.gitDirExists === false) {
|
|
33804
|
+
const match = /^gitdir:\s*(.+)\s*$/im.exec(inspection.gitFileContent ?? "");
|
|
33805
|
+
const gitdir = match?.[1]?.trim();
|
|
33806
|
+
return `this directory's .git points at ${gitdir ? `'${gitdir}'` : "its admin dir"}, which no longer exists \u2014 its worktree registration was severed`;
|
|
33807
|
+
}
|
|
33808
|
+
return void 0;
|
|
33809
|
+
}
|
|
33783
33810
|
function orphanLandSteps(lostBranch, hasStage) {
|
|
33784
33811
|
const steps = [];
|
|
33785
33812
|
if (hasStage) steps.push("stop spawned dev stage");
|
|
@@ -34012,7 +34039,17 @@ function registerWorktreeCommands(program3) {
|
|
|
34012
34039
|
if (o.apply && o.dryRun) return fail("worktree land: choose either --dry-run or --apply");
|
|
34013
34040
|
const apply = Boolean(o.apply);
|
|
34014
34041
|
try {
|
|
34015
|
-
|
|
34042
|
+
let wtPath;
|
|
34043
|
+
try {
|
|
34044
|
+
wtPath = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS })).stdout.trim();
|
|
34045
|
+
} catch (e) {
|
|
34046
|
+
const reason = describeLandUnresolvableWorktree(inspectSiblingWorktreeDir(process.cwd(), ""));
|
|
34047
|
+
if (!reason) throw e;
|
|
34048
|
+
return fail(
|
|
34049
|
+
`worktree land: ${reason}. It cannot be landed from inside itself \u2014 cd to the primary checkout and run \`mmi-cli worktree gc --apply\` (add --force if this directory still holds leftover files) to clear it.`,
|
|
34050
|
+
{ code: ERROR_CODES.ERR_BAD_ENUM }
|
|
34051
|
+
);
|
|
34052
|
+
}
|
|
34016
34053
|
const headBorn = await execFileP2("git", ["-C", wtPath || ".", "rev-parse", "--verify", "--quiet", "HEAD"], { timeout: GIT_TIMEOUT_MS }).then(() => true).catch(() => false);
|
|
34017
34054
|
const symbolicBranch = (await execFileP2(
|
|
34018
34055
|
"git",
|
|
@@ -39759,7 +39796,7 @@ gcCmd.command("sweep-deferred").description("retry IDE-locked deferred worktree
|
|
|
39759
39796
|
process.exit(process.exitCode ?? 0);
|
|
39760
39797
|
});
|
|
39761
39798
|
});
|
|
39762
|
-
gcCmd.option("--dry-run", "show what would be deleted (default)").option("--apply", "delete only the listed clean merged/closed PR local+remote branches, linked worktrees, and stale tracking refs").option("--json", "machine-readable output").option("--scratch", "prune safe local scratch (#1864) instead of git branches/refs; local plans are surfaced advisory-only, never auto-pruned").option("--remote <name>", "remote name", "origin").option("--limit <n>", "PRs to read PER BRANCH ? an effort bound, not a correctness one: merge state is resolved per branch, so no branch is ever skipped for being old (#4227)", "200").option("--force", "remove worktrees even when the ownership registry shows another session created or worked in them recently (#3580)").option("--root <path>", "sweep an explicitly named worktrees root instead of the authoritative ../mmi-worktrees (#3471) ? descends into this repo container when present; ownership, dead-dir, and content guards still apply").action(async (o) => {
|
|
39799
|
+
gcCmd.option("--dry-run", "show what would be deleted (default)").option("--apply", "delete only the listed clean merged/closed PR local+remote branches, linked worktrees, and stale tracking refs").option("--json", "machine-readable output").option("--scratch", "prune safe local scratch (#1864) instead of git branches/refs; local plans are surfaced advisory-only, never auto-pruned").option("--remote <name>", "remote name", "origin").option("--limit <n>", "PRs to read PER BRANCH ? an effort bound, not a correctness one: merge state is resolved per branch, so no branch is ever skipped for being old (#4227)", "200").option("--force", "remove worktrees even when the ownership registry shows another session created or worked in them recently (#3580), or when a dead worktree directory still holds leftover files (#4779)").option("--root <path>", "sweep an explicitly named worktrees root instead of the authoritative ../mmi-worktrees (#3471) ? descends into this repo container when present; ownership, dead-dir, and content guards still apply").action(async (o) => {
|
|
39763
39800
|
if (o.apply && o.dryRun) return fail("worktree gc: choose either --dry-run or --apply");
|
|
39764
39801
|
if (o.scratch) {
|
|
39765
39802
|
try {
|
package/package.json
CHANGED