@mutmutco/cli 4.3.10 → 4.3.12
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 +77 -13
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -10515,7 +10515,14 @@ var SESSION_ID_ENV_VARS = [
|
|
|
10515
10515
|
"CODEX_THREAD_ID",
|
|
10516
10516
|
"CURSOR_SESSION_ID",
|
|
10517
10517
|
"HERMES_SESSION_ID",
|
|
10518
|
-
"PI_SESSION_ID"
|
|
10518
|
+
"PI_SESSION_ID",
|
|
10519
|
+
// #6193: lane runners spawn the CLI through the host's extension shell operations, which strip
|
|
10520
|
+
// the PI_* session variables; the JervCode launcher's durable lane id (JERV_SESSION_ID) is what
|
|
10521
|
+
// survives in that env. Read it LAST so interactive invocations keep their own PI_SESSION_ID and
|
|
10522
|
+
// a stripped spawn still resolves to its owning lane — otherwise the actor degrades to a
|
|
10523
|
+
// synth/shell identity and the claim guard contests the caller's OWN lane (the #3414/#3438
|
|
10524
|
+
// refusals of jerv_worktree_land's `devops pr create` from the claimed task worktree).
|
|
10525
|
+
"JERV_SESSION_ID"
|
|
10519
10526
|
];
|
|
10520
10527
|
var SYNTH_SESSION_PREFIX = "synth-";
|
|
10521
10528
|
function isHostSessionId(session) {
|
|
@@ -12048,6 +12055,14 @@ async function postIssueComment(client, input) {
|
|
|
12048
12055
|
|
|
12049
12056
|
// src/board-claim-move.ts
|
|
12050
12057
|
var CLAIM_CONCURRENCY = 5;
|
|
12058
|
+
function withPowerShellChainHint(message2, platform2 = process.platform) {
|
|
12059
|
+
if (platform2 !== "win32") return message2;
|
|
12060
|
+
return `${message2}
|
|
12061
|
+
note: in PowerShell a ';' chain runs every statement regardless of the previous exit code, so the chain ran past this refusal \u2014 rerun the refused write solo or chain gated writes with '&&'`;
|
|
12062
|
+
}
|
|
12063
|
+
function isArchivedItemRefusal(message2) {
|
|
12064
|
+
return /The item is archived and cannot be updated/i.test(message2);
|
|
12065
|
+
}
|
|
12051
12066
|
async function moveBoardItem(options, deps = {}) {
|
|
12052
12067
|
if (!BOARD_STATUSES.includes(options.status)) {
|
|
12053
12068
|
throw new Error(`unknown status '${options.status}'; expected one of ${BOARD_STATUSES.join(", ")}`);
|
|
@@ -12065,6 +12080,17 @@ async function moveBoardItem(options, deps = {}) {
|
|
|
12065
12080
|
try {
|
|
12066
12081
|
await updateItemSingleSelect(client, cfg.projectId, item.itemId, cfg.statusFieldId, optionId);
|
|
12067
12082
|
} catch (e) {
|
|
12083
|
+
if (options.status === "Done" && isArchivedItemRefusal(ghError(e))) {
|
|
12084
|
+
return {
|
|
12085
|
+
item,
|
|
12086
|
+
viewer: lookup.viewer,
|
|
12087
|
+
repo: currentRepo,
|
|
12088
|
+
status: item.status,
|
|
12089
|
+
partial: false,
|
|
12090
|
+
archived: true,
|
|
12091
|
+
warning: `${item.ref} is archived (already terminal \u2014 its close archived the card); no ${options.status} move was performed`
|
|
12092
|
+
};
|
|
12093
|
+
}
|
|
12068
12094
|
const warning = `partial move: ${item.ref} status was not changed to ${options.status} (${ghError(e)})`;
|
|
12069
12095
|
if (!options.allowPartial) throw new Error(warning);
|
|
12070
12096
|
return { item, viewer: lookup.viewer, repo: currentRepo, status: item.status, partial: true, warning };
|
|
@@ -12209,7 +12235,7 @@ async function claimOneBoardItem(ctx, selector, options) {
|
|
|
12209
12235
|
}
|
|
12210
12236
|
return;
|
|
12211
12237
|
}
|
|
12212
|
-
if (!options.force) throw new Error(laneContestMessage(item.ref, contest, "claim"));
|
|
12238
|
+
if (!options.force) throw new Error(withPowerShellChainHint(laneContestMessage(item.ref, contest, "claim")));
|
|
12213
12239
|
previousHolder = displaced();
|
|
12214
12240
|
};
|
|
12215
12241
|
await refuseIfContested();
|
|
@@ -12392,7 +12418,7 @@ async function unclaimBoardIssue(options, deps = {}) {
|
|
|
12392
12418
|
const toStatus = options.toStatus ?? "Todo";
|
|
12393
12419
|
if (!options.force && item.contentType === "Issue") {
|
|
12394
12420
|
const contest = await checkLaneContest(client, item);
|
|
12395
|
-
if (contest.contested) throw new Error(laneContestMessage(item.ref, contest, "unclaim"));
|
|
12421
|
+
if (contest.contested) throw new Error(withPowerShellChainHint(laneContestMessage(item.ref, contest, "unclaim")));
|
|
12396
12422
|
}
|
|
12397
12423
|
try {
|
|
12398
12424
|
await client.rest("DELETE", `repos/${item.repository}/issues/${item.number}/assignees`, {
|
|
@@ -15450,10 +15476,10 @@ var rollout_plan_default = {
|
|
|
15450
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)."
|
|
15451
15477
|
},
|
|
15452
15478
|
baseline: {
|
|
15453
|
-
version: "4.3.
|
|
15454
|
-
tag: "v4.3.
|
|
15455
|
-
commit: "
|
|
15456
|
-
npm: "@mutmutco/cli@4.3.
|
|
15479
|
+
version: "4.3.12",
|
|
15480
|
+
tag: "v4.3.12",
|
|
15481
|
+
commit: "355e861fa08f",
|
|
15482
|
+
npm: "@mutmutco/cli@4.3.12"
|
|
15457
15483
|
},
|
|
15458
15484
|
exitCriterion: "fleet-n-of-n",
|
|
15459
15485
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15470,14 +15496,14 @@ var rollout_plan_default = {
|
|
|
15470
15496
|
repo: "mutmutco/mmi-hub",
|
|
15471
15497
|
role: "canary",
|
|
15472
15498
|
schedule: "train",
|
|
15473
|
-
v3Target: "v4.3.
|
|
15499
|
+
v3Target: "v4.3.12"
|
|
15474
15500
|
}
|
|
15475
15501
|
],
|
|
15476
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.",
|
|
15477
15503
|
rollback: {
|
|
15478
15504
|
independent: true,
|
|
15479
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15480
|
-
v3Target: "v4.3.
|
|
15505
|
+
mechanism: "npm dist-tag latest -> 4.3.12 and redeploy the Hub Lambda from tag v4.3.12 (355e861fa08f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15506
|
+
v3Target: "v4.3.12 (@mutmutco/cli@4.3.12, tag commit 355e861fa08f \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15481
15507
|
}
|
|
15482
15508
|
},
|
|
15483
15509
|
{
|
|
@@ -25520,7 +25546,7 @@ function registerBoardCommands(program3) {
|
|
|
25520
25546
|
const result = await moveBoardItem({ config: await loadConfigForBoardSelector2(issueRefs[0], o.repo), selector: issueRefs[0], status: canonicalStatus, repo: o.repo, allowPartial: o.allowPartial });
|
|
25521
25547
|
invalidateStatuslineBoardCache();
|
|
25522
25548
|
if (o.json) return console.log(JSON.stringify(result));
|
|
25523
|
-
console.log(result.partial ? `Partially moved ${result.item.ref}: ${result.warning}` : `Moved ${result.item.ref} -> ${result.status}`);
|
|
25549
|
+
console.log(result.archived ? `Already terminal ${result.item.ref}: ${result.warning}` : result.partial ? `Partially moved ${result.item.ref}: ${result.warning}` : `Moved ${result.item.ref} -> ${result.status}`);
|
|
25524
25550
|
} catch (e) {
|
|
25525
25551
|
return failGraceful(`board move failed: ${e.message}`);
|
|
25526
25552
|
}
|
|
@@ -33482,6 +33508,36 @@ async function fetchBranchTipSha(repo, ref, gh = defaultGhApi) {
|
|
|
33482
33508
|
async function fetchRestPrSnapshot(prNumber, repo, gh = defaultGhApi) {
|
|
33483
33509
|
return parseRestPrSnapshot(JSON.parse(await gh([`repos/${repo}/pulls/${prNumber}`])));
|
|
33484
33510
|
}
|
|
33511
|
+
async function readRepoMergeSettingsOnce(repo, gh) {
|
|
33512
|
+
let raw;
|
|
33513
|
+
try {
|
|
33514
|
+
raw = await gh([`repos/${repo}`]);
|
|
33515
|
+
} catch (e) {
|
|
33516
|
+
return { proven: false, reason: `read failed: ${e.message}` };
|
|
33517
|
+
}
|
|
33518
|
+
let payload;
|
|
33519
|
+
try {
|
|
33520
|
+
payload = JSON.parse(raw);
|
|
33521
|
+
} catch {
|
|
33522
|
+
return { proven: false, reason: "payload was not JSON" };
|
|
33523
|
+
}
|
|
33524
|
+
if (typeof payload.delete_branch_on_merge === "boolean") {
|
|
33525
|
+
return { proven: true, deleteBranchOnMerge: payload.delete_branch_on_merge };
|
|
33526
|
+
}
|
|
33527
|
+
const apiMessage = typeof payload.message === "string" ? ` (${payload.message})` : "";
|
|
33528
|
+
return { proven: false, reason: `payload carried no delete_branch_on_merge${apiMessage}` };
|
|
33529
|
+
}
|
|
33530
|
+
async function ambientGhApi(args) {
|
|
33531
|
+
const { stdout } = await execFileP("gh", ["api", ...args], { timeout: REST_GH_TIMEOUT_MS });
|
|
33532
|
+
return stdout;
|
|
33533
|
+
}
|
|
33534
|
+
async function fetchRestRepoMergeSettings(repo, gh = defaultGhApi, ambientGh = ambientGhApi) {
|
|
33535
|
+
const primary = await readRepoMergeSettingsOnce(repo, gh);
|
|
33536
|
+
if (primary.proven) return primary;
|
|
33537
|
+
const fallback = await readRepoMergeSettingsOnce(repo, ambientGh);
|
|
33538
|
+
if (fallback.proven) return fallback;
|
|
33539
|
+
return { proven: false, reason: `${primary.reason}; ambient fallback: ${fallback.reason}` };
|
|
33540
|
+
}
|
|
33485
33541
|
var PR_SNAPSHOT_READ_RETRIES = 3;
|
|
33486
33542
|
var PR_SNAPSHOT_READ_DELAY_MS = 2e3;
|
|
33487
33543
|
async function readRestPrSnapshotWithRetry(prNumber, repo, gh = defaultGhApi, options) {
|
|
@@ -36108,6 +36164,10 @@ async function advanceClosedIssuesToDone(deps) {
|
|
|
36108
36164
|
const issue = `#${ref.number}`;
|
|
36109
36165
|
try {
|
|
36110
36166
|
const outcome = await deps.moveIssueToDone(issue);
|
|
36167
|
+
if (outcome.archived) {
|
|
36168
|
+
entries.push({ issue, moved: true, status: "archived-terminal" });
|
|
36169
|
+
continue;
|
|
36170
|
+
}
|
|
36111
36171
|
if (!outcome.moved) {
|
|
36112
36172
|
entries.push({ issue, moved: false, status: "failed", error: outcome.error });
|
|
36113
36173
|
continue;
|
|
@@ -37015,6 +37075,7 @@ async function resolveBoardAdvanceForPr(prNumber, repoOption) {
|
|
|
37015
37075
|
},
|
|
37016
37076
|
moveIssueToDone: async (ref) => {
|
|
37017
37077
|
const moved = await moveBoardItem({ config: await loadConfigForBoardSelector2(ref, repoOption), selector: ref, status: "Done", repo: repoOption, allowPartial: true });
|
|
37078
|
+
if (moved.archived) return { moved: true, archived: true };
|
|
37018
37079
|
return moved.partial ? { moved: false, error: moved.warning } : { moved: true };
|
|
37019
37080
|
},
|
|
37020
37081
|
// #5317: after a successful move, re-read the board to verify Done actually holds — a move the API
|
|
@@ -39650,8 +39711,11 @@ ${list}`);
|
|
|
39650
39711
|
if (closingGuardVerdict.message) console.warn(closingGuardVerdict.message);
|
|
39651
39712
|
if (prMeta.state !== "MERGED" && !o.preserveWorktree) {
|
|
39652
39713
|
if (!repoForPostCleanup) throw new Error("pr merge: repository is unreadable; cannot prove remote branch preservation");
|
|
39653
|
-
const repoSettings = await
|
|
39654
|
-
|
|
39714
|
+
const repoSettings = await fetchRestRepoMergeSettings(repoForPostCleanup);
|
|
39715
|
+
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).`);
|
|
39717
|
+
}
|
|
39718
|
+
assertRemoteBranchPreservedOnMerge(repoForPostCleanup, repoSettings.deleteBranchOnMerge);
|
|
39655
39719
|
}
|
|
39656
39720
|
const startingPath = (await execFileP("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
|
|
39657
39721
|
const housekeeping = assertPrMergeHousekeepingClean(startingPath || process.cwd(), "pr merge", { force: o.force });
|
package/package.json
CHANGED