@mutmutco/cli 4.3.3 → 4.3.4

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 +65 -20
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -15375,10 +15375,10 @@ var rollout_plan_default = {
15375
15375
  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)."
15376
15376
  },
15377
15377
  baseline: {
15378
- version: "4.3.3",
15379
- tag: "v4.3.3",
15380
- commit: "851ec4c56e34",
15381
- npm: "@mutmutco/cli@4.3.3"
15378
+ version: "4.3.4",
15379
+ tag: "v4.3.4",
15380
+ commit: "cd7d0dd9cc3a",
15381
+ npm: "@mutmutco/cli@4.3.4"
15382
15382
  },
15383
15383
  exitCriterion: "fleet-n-of-n",
15384
15384
  hubOnlyShortcut: "forbidden",
@@ -15395,14 +15395,14 @@ var rollout_plan_default = {
15395
15395
  repo: "mutmutco/mmi-hub",
15396
15396
  role: "canary",
15397
15397
  schedule: "train",
15398
- v3Target: "v4.3.3"
15398
+ v3Target: "v4.3.4"
15399
15399
  }
15400
15400
  ],
15401
15401
  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.",
15402
15402
  rollback: {
15403
15403
  independent: true,
15404
- mechanism: "npm dist-tag latest -> 4.3.3 and redeploy the Hub Lambda from tag v4.3.3 (851ec4c56e34); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15405
- v3Target: "v4.3.3 (@mutmutco/cli@4.3.3, tag commit 851ec4c56e34 \u2014 last known-good release carrying the repo-index v4-only contract)"
15404
+ mechanism: "npm dist-tag latest -> 4.3.4 and redeploy the Hub Lambda from tag v4.3.4 (cd7d0dd9cc3a); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15405
+ v3Target: "v4.3.4 (@mutmutco/cli@4.3.4, tag commit cd7d0dd9cc3a \u2014 last known-good release carrying the repo-index v4-only contract)"
15406
15406
  }
15407
15407
  },
15408
15408
  {
@@ -35429,6 +35429,10 @@ function ghPrMergeLocalBranchDeleteWarning(message) {
35429
35429
  function mergeAutoRejectedPrAlreadyClean(message) {
35430
35430
  return /clean status \(enablePullRequestAutoMerge\)|is in clean status/i.test(message);
35431
35431
  }
35432
+ function mergeRejectedBaseBranchModified(message) {
35433
+ return /base branch was modified\. review and try the merge again/i.test(message);
35434
+ }
35435
+ var PR_MERGE_BASE_RACE_RETRY_DELAY_MS = 3e3;
35432
35436
  function assertRemoteBranchPreservedOnMerge(repo, deleteBranchOnMerge) {
35433
35437
  if (deleteBranchOnMerge === false) return;
35434
35438
  throw new Error(
@@ -35709,14 +35713,16 @@ async function deleteMergedRemoteBranch(options) {
35709
35713
  if (options.existedBefore === false) {
35710
35714
  const exists2 = await options.branchExists(options.branch);
35711
35715
  if (exists2 === false) return { branch: options.branch, existedBefore: false, attempted: false, status: "already-gone" };
35712
- return {
35713
- branch: options.branch,
35714
- existedBefore: false,
35715
- attempted: false,
35716
- status: "failed",
35717
- error: exists2 ? `origin reports ${options.branch} after merge` : `could not verify absence of origin/${options.branch}`,
35718
- remediation
35719
- };
35716
+ if (exists2 !== true) {
35717
+ return {
35718
+ branch: options.branch,
35719
+ existedBefore: false,
35720
+ attempted: false,
35721
+ status: "failed",
35722
+ error: `could not verify absence of origin/${options.branch}`,
35723
+ remediation
35724
+ };
35725
+ }
35720
35726
  }
35721
35727
  try {
35722
35728
  await options.execGit(["push", "origin", "--delete", options.branch]);
@@ -36389,6 +36395,22 @@ function samePath(a, b) {
36389
36395
  const nb = normPath2(b);
36390
36396
  return process.platform === "win32" ? na.toLowerCase() === nb.toLowerCase() : na === nb;
36391
36397
  }
36398
+ function isPathAtOrWithin(path2, worktreePath) {
36399
+ if (!path2) return false;
36400
+ const candidate = normPath2(path2);
36401
+ const target = normPath2(worktreePath);
36402
+ const normalize = (value) => process.platform === "win32" ? value.toLowerCase() : value;
36403
+ const normalizedCandidate = normalize(candidate);
36404
+ const normalizedTarget = normalize(target);
36405
+ return normalizedCandidate === normalizedTarget || normalizedCandidate.startsWith(`${normalizedTarget}/`);
36406
+ }
36407
+ function isWindowsCwdLockResidueError(error) {
36408
+ return process.platform === "win32" && /\bEPERM\b|access(?: is)? denied/i.test(error);
36409
+ }
36410
+ function deferredCwdLockRemediation(primaryRoot, wtPath) {
36411
+ const quote = (path2) => path2.replace(/'/g, "''");
36412
+ return `After this command exits: Set-Location -LiteralPath '${quote(primaryRoot)}'; Remove-Item -LiteralPath '${quote(wtPath)}' -Recurse -Force`;
36413
+ }
36392
36414
  function selectPrMergeCleanupWorktree(branch, before, after, startingPath) {
36393
36415
  if (!branch) return void 0;
36394
36416
  const current = after.find((w) => w.branch === branch)?.path;
@@ -36559,7 +36581,7 @@ async function removeWorktreeWithReconcile(wtPath, git3, listWorktrees, pathExis
36559
36581
  }
36560
36582
  function isPrMergeWorktreePartial(cleanup) {
36561
36583
  const worktree = cleanup?.worktree;
36562
- return Boolean(worktree?.path && worktree.status !== "removed" && worktree.status !== "preserved");
36584
+ return Boolean(worktree?.path && worktree.status !== "removed" && worktree.status !== "preserved" && worktree.status !== "retained-locked");
36563
36585
  }
36564
36586
  function prMergeLocalCleanupExitCode(cleanup) {
36565
36587
  return cleanup?.worktree?.status === "failed" || cleanup?.localBranch?.status === "failed" ? 1 : void 0;
@@ -36731,11 +36753,17 @@ async function cleanupPrMergeLocalBranch(branch, options) {
36731
36753
  if (residue.ok) {
36732
36754
  report.worktree.residue = "swept";
36733
36755
  } else {
36734
- report.worktree.status = "failed";
36735
- report.worktree.reason = "residue-remains";
36736
36756
  report.worktree.residue = "left";
36737
36757
  report.worktree.residueError = residue.error;
36738
- report.worktree.remediation = `Remove-Item -LiteralPath '${wtPath.replace(/'/g, "''")}' -Force`;
36758
+ if (isWindowsCwdLockResidueError(residue.error) && isPathAtOrWithin(options.startingPath, wtPath)) {
36759
+ report.worktree.status = "retained-locked";
36760
+ report.worktree.reason = "parent-cwd-lock";
36761
+ report.worktree.remediation = deferredCwdLockRemediation(options.primaryRoot, wtPath);
36762
+ } else {
36763
+ report.worktree.status = "failed";
36764
+ report.worktree.reason = "residue-remains";
36765
+ report.worktree.remediation = `Remove-Item -LiteralPath '${wtPath.replace(/'/g, "''")}' -Force`;
36766
+ }
36739
36767
  }
36740
36768
  }
36741
36769
  try {
@@ -36764,8 +36792,10 @@ function renderPrMergeCleanupLines(cleanup) {
36764
36792
  lines.push(`pr merge: worktree ${wt.path} removal failed${wt.error ? ` \u2014 ${wt.error}` : ""}`);
36765
36793
  } else if (wt.status === "preserved") {
36766
36794
  lines.push(`pr merge: preserved worktree ${wt.path} (--preserve-worktree)`);
36795
+ } else if (wt.status === "retained-locked") {
36796
+ lines.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"}`);
36767
36797
  }
36768
- if (wt.residue === "left") {
36798
+ if (wt.residue === "left" && wt.status !== "retained-locked") {
36769
36799
  lines.push(`pr merge: worktree ${wt.path} registration is gone but residue remains \u2014 ${wt.residueError ?? wt.path}; remediate: ${wt.remediation ?? wt.path}`);
36770
36800
  }
36771
36801
  if (wt.artifactsArchive?.status === "archived" && wt.artifactsArchive.path) {
@@ -37979,6 +38009,21 @@ ${list}`);
37979
38009
  });
37980
38010
  return;
37981
38011
  }
38012
+ if (!o.auto && mergeRejectedBaseBranchModified(message)) {
38013
+ console.warn(`pr merge: the base branch was modified by a concurrent merge \u2014 waiting ${PR_MERGE_BASE_RACE_RETRY_DELAY_MS / 1e3}s and retrying PR #${number}'s merge once (#6052).`);
38014
+ await new Promise((resolve7) => setTimeout(resolve7, PR_MERGE_BASE_RACE_RETRY_DELAY_MS));
38015
+ await execFileP("gh", buildPrMergeArgs({ number, repoArgs, method, auto: false, deleteBranch: false, bodyFile }), { timeout: GH_MUTATION_TIMEOUT_MS }).catch((e2) => {
38016
+ const m2 = String(e2.message || "");
38017
+ if (/already been merged/i.test(m2)) {
38018
+ remoteNotAttemptedReason = "pr-already-merged";
38019
+ return;
38020
+ }
38021
+ const note2 = timeoutKillNote(e2, GH_MUTATION_TIMEOUT_MS);
38022
+ if (note2) throw new Error(`gh pr merge ${number}: ${note2}`);
38023
+ if (!ghPrMergeLocalBranchDeleteWarning(m2)) throw e2;
38024
+ });
38025
+ return;
38026
+ }
37982
38027
  if (o.auto && mergeAutoRejectedPrAlreadyClean(message)) {
37983
38028
  await execFileP("gh", buildPrMergeArgs({ number, repoArgs, method, auto: false, deleteBranch: false, bodyFile }), { timeout: GH_MUTATION_TIMEOUT_MS }).catch((e2) => {
37984
38029
  const m2 = String(e2.message || "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.3.3",
3
+ "version": "4.3.4",
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",