@mutmutco/cli 4.5.32 → 4.5.34
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 +40 -12
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -5485,7 +5485,7 @@ function isSnapshotShape(body) {
|
|
|
5485
5485
|
const staleValid = b?.stale === void 0 || typeof b.stale === "object" && b.stale !== null && Number.isFinite(b.stale.ageMs) && b.stale.ageMs >= 0;
|
|
5486
5486
|
const githubValid = b?.github === void 0 || b.github.credential === "app_installation" && (rate === void 0 || Number.isFinite(rate?.limit) && Number.isFinite(rate?.remaining) && Number.isFinite(rate?.cost) && typeof rate?.resetAt === "string");
|
|
5487
5487
|
return Boolean(
|
|
5488
|
-
b && typeof b === "object" && typeof b.project?.id === "string" && typeof b.project?.title === "string" && typeof b.viewer === "string" && b.viewer.length > 0 && Array.isArray(b.nodes) && Array.isArray(b.writableRepos) && Array.isArray(b.unreadableRepos) && Array.isArray(b.pullRequests) && Array.isArray(b.warnings) && typeof b.partial === "boolean" && githubValid && staleValid
|
|
5488
|
+
b && typeof b === "object" && typeof b.project?.id === "string" && typeof b.project?.title === "string" && typeof b.viewer === "string" && b.viewer.length > 0 && Array.isArray(b.nodes) && Array.isArray(b.writableRepos) && Array.isArray(b.unreadableRepos) && Array.isArray(b.pullRequests) && Array.isArray(b.warnings) && typeof b.partial === "boolean" && (b.eventCursor === void 0 || Number.isInteger(b.eventCursor) && b.eventCursor >= 0) && githubValid && staleValid
|
|
5489
5489
|
);
|
|
5490
5490
|
}
|
|
5491
5491
|
async function fetchHubBoardSnapshot(request, deps) {
|
|
@@ -12541,6 +12541,7 @@ async function readBoard(options, deps = {}) {
|
|
|
12541
12541
|
const { collected, snapshot } = await collectBoardPreferringSnapshot(cfg, options, deps);
|
|
12542
12542
|
let writable;
|
|
12543
12543
|
let pullRequests;
|
|
12544
|
+
let eventCursor;
|
|
12544
12545
|
let github;
|
|
12545
12546
|
if (snapshot) {
|
|
12546
12547
|
for (const unreadable of snapshot.unreadableRepos) {
|
|
@@ -12552,6 +12553,7 @@ async function readBoard(options, deps = {}) {
|
|
|
12552
12553
|
unknown: new Set(snapshot.unreadableRepos.map((entry) => entry.repo.toLowerCase()))
|
|
12553
12554
|
};
|
|
12554
12555
|
pullRequests = snapshot.pullRequests;
|
|
12556
|
+
eventCursor = snapshot.eventCursor;
|
|
12555
12557
|
github = snapshot.github && { ...snapshot.github, ...snapshot.quotaResetAt ? { quotaResetAt: snapshot.quotaResetAt } : {} };
|
|
12556
12558
|
} else {
|
|
12557
12559
|
const probed = await resolveWritableReposForClaimables(collected.items, client);
|
|
@@ -12569,6 +12571,7 @@ async function readBoard(options, deps = {}) {
|
|
|
12569
12571
|
partial: collected.partial,
|
|
12570
12572
|
source: "live",
|
|
12571
12573
|
...pullRequests ? { pullRequests } : {},
|
|
12574
|
+
...eventCursor !== void 0 ? { eventCursor } : {},
|
|
12572
12575
|
...github ? { github } : {}
|
|
12573
12576
|
};
|
|
12574
12577
|
if (options.includeBundleDetails || options.includeAllBodies) {
|
|
@@ -16837,10 +16840,10 @@ var rollout_plan_default = {
|
|
|
16837
16840
|
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)."
|
|
16838
16841
|
},
|
|
16839
16842
|
baseline: {
|
|
16840
|
-
version: "4.5.
|
|
16841
|
-
tag: "v4.5.
|
|
16842
|
-
commit: "
|
|
16843
|
-
npm: "@mutmutco/cli@4.5.
|
|
16843
|
+
version: "4.5.34",
|
|
16844
|
+
tag: "v4.5.34",
|
|
16845
|
+
commit: "fe244fb48abc",
|
|
16846
|
+
npm: "@mutmutco/cli@4.5.34"
|
|
16844
16847
|
},
|
|
16845
16848
|
exitCriterion: "fleet-n-of-n",
|
|
16846
16849
|
hubOnlyShortcut: "forbidden",
|
|
@@ -16857,14 +16860,14 @@ var rollout_plan_default = {
|
|
|
16857
16860
|
repo: "mutmutco/mmi-hub",
|
|
16858
16861
|
role: "canary",
|
|
16859
16862
|
schedule: "train",
|
|
16860
|
-
v3Target: "v4.5.
|
|
16863
|
+
v3Target: "v4.5.34"
|
|
16861
16864
|
}
|
|
16862
16865
|
],
|
|
16863
16866
|
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.",
|
|
16864
16867
|
rollback: {
|
|
16865
16868
|
independent: true,
|
|
16866
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
16867
|
-
v3Target: "v4.5.
|
|
16869
|
+
mechanism: "npm dist-tag latest -> 4.5.34 and redeploy the Hub Lambda from tag v4.5.34 (fe244fb48abc); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
16870
|
+
v3Target: "v4.5.34 (@mutmutco/cli@4.5.34, tag commit fe244fb48abc \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
16868
16871
|
}
|
|
16869
16872
|
},
|
|
16870
16873
|
{
|
|
@@ -19354,8 +19357,21 @@ async function pushAlignmentBranch(deps, target, tag) {
|
|
|
19354
19357
|
if (!commit) throw new Error(`git commit-tree wrote no commit for the ${target} alignment of ${tag} (#6288)`);
|
|
19355
19358
|
await deps.run("git", ["push", "origin", "--delete", branch]).catch(() => void 0);
|
|
19356
19359
|
await runGitPush(deps, ["push", "origin", `${commit}:refs/heads/${branch}`]);
|
|
19360
|
+
await sweepLandedAlignmentBranches(deps, target, branch);
|
|
19357
19361
|
return branch;
|
|
19358
19362
|
}
|
|
19363
|
+
async function sweepLandedAlignmentBranches(deps, target, keep) {
|
|
19364
|
+
const prefix = `refs/heads/release-align/${target}/`;
|
|
19365
|
+
const listed = await deps.run("git", ["ls-remote", "--heads", "origin", `${prefix}*`]).catch(() => "");
|
|
19366
|
+
for (const line of clean2(listed).split("\n")) {
|
|
19367
|
+
const [sha, ref] = line.split(" ");
|
|
19368
|
+
if (!sha || !ref?.startsWith(prefix)) continue;
|
|
19369
|
+
const name = ref.slice("refs/heads/".length);
|
|
19370
|
+
if (name === keep) continue;
|
|
19371
|
+
const landed = await deps.run("git", ["merge-base", "--is-ancestor", sha, `origin/${target}`]).then(() => true, () => false);
|
|
19372
|
+
if (landed) await deps.run("git", ["push", "origin", "--delete", name]).catch(() => void 0);
|
|
19373
|
+
}
|
|
19374
|
+
}
|
|
19359
19375
|
async function findAlignmentPr(deps, ctx, target, head) {
|
|
19360
19376
|
const out = clean2(await deps.run("gh", ["pr", "list", "--repo", ctx.repo, "--base", target, "--head", head, "--state", "all", "--json", "number,url,state"]));
|
|
19361
19377
|
if (!out) return void 0;
|
|
@@ -23531,7 +23547,8 @@ async function supersedeContentCausedDeployLeg(deps, cwd) {
|
|
|
23531
23547
|
`release --supersede-deploy: origin reports ${prior.tag} at ${liveSha.slice(0, 12) || "no tag"} but the ledger anchors ${prior.tagSha.slice(0, 12)} \u2014 an absent or divergent release is NOT supersedeable (release --abort --apply is the unpublished candidate's own exit); nothing was written (#6553)`
|
|
23532
23548
|
);
|
|
23533
23549
|
}
|
|
23534
|
-
const
|
|
23550
|
+
const failed = prior.phases.deploy.state === "failed";
|
|
23551
|
+
const note = failed ? `superseded: content-caused deploy failure on the immutable promoted ${prior.tag} \u2014 the cause fix rides the next patch train (master-approved closure, #6553)` : `superseded: ${prior.tag} deploy outcome uncorrelatable from the release SHA (no failure recorded) \u2014 closed on the owner's evidence (master-approved closure, #6553, #7327)`;
|
|
23535
23552
|
await fence(() => atomicWriteJson(path2, {
|
|
23536
23553
|
...prior,
|
|
23537
23554
|
phases: {
|
|
@@ -23545,7 +23562,7 @@ async function supersedeContentCausedDeployLeg(deps, cwd) {
|
|
|
23545
23562
|
repo: prior.repo,
|
|
23546
23563
|
tag: prior.tag,
|
|
23547
23564
|
tagSha: prior.tagSha,
|
|
23548
|
-
note: `closed the ${prior.tag} deploy leg as superseded (skipped) \u2014 the ledger is phases-green; rerun the train doctor to confirm, then run the next patch train (hotfix or release) to carry the cause fix`
|
|
23565
|
+
note: failed ? `closed the ${prior.tag} deploy leg as superseded (skipped) \u2014 the ledger is phases-green; rerun the train doctor to confirm, then run the next patch train (hotfix or release) to carry the cause fix` : `closed the ${prior.tag} uncorrelatable deploy leg as superseded (skipped) \u2014 the ledger is phases-green; rerun the train doctor to confirm`
|
|
23549
23566
|
};
|
|
23550
23567
|
});
|
|
23551
23568
|
}
|
|
@@ -25916,6 +25933,14 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
25916
25933
|
}
|
|
25917
25934
|
if (persisted?.phases.deploy.superseded === true) phaseInputs.deploy = persisted.phases.deploy;
|
|
25918
25935
|
if (persisted?.phases.publish.superseded === true) phaseInputs.publish = persisted.phases.publish;
|
|
25936
|
+
for (const leg of ["deploy", "publish"]) {
|
|
25937
|
+
const kept = persisted?.phases[leg];
|
|
25938
|
+
if (kept?.state === "complete" && kept.runId != null && phaseInputs[leg].state === "pending") phaseInputs[leg] = kept;
|
|
25939
|
+
}
|
|
25940
|
+
if (!companion && phaseInputs.deploy.state === "complete" && (phaseInputs.publish.state === "complete" || phaseInputs.publish.state === "skipped")) {
|
|
25941
|
+
dispatch2.deployStatus = "success";
|
|
25942
|
+
dispatch2.note = `historical ${deployModel} deploy/publish status: success (re-verified by the recorded run)`;
|
|
25943
|
+
}
|
|
25919
25944
|
if (persisted) {
|
|
25920
25945
|
if (persisted.phases.deploy.superseded !== true) {
|
|
25921
25946
|
await recordPhase(ledger, deps, anchors, "deploy", phaseEntry(phaseInputs.deploy), { strict: true, landed: "the verified GitHub Release and origin/main at the immutable tag SHA" });
|
|
@@ -37572,8 +37597,11 @@ function readRepoVersion() {
|
|
|
37572
37597
|
}
|
|
37573
37598
|
function registerTrainCommands(program3, trainDeps) {
|
|
37574
37599
|
const train = program3.command("train").description("release-train observability \u2014 track position, version lag, and the shared preflight-and-heal doctor (#2688, #6067)");
|
|
37575
|
-
train.command("doctor").description("one shared preflight-and-heal verdict for the release, rcand and hotfix lanes; read-only unless --heal (#6067)").addOption(new Option("--lane <lane>", "train lane to check (defaults from the release track: direct \u2192 release)").choices([...TRAIN_LANES])).option("--dev", "judge the `release --dev` lane (development -> main, skipping rc): the lane starts from development and is read on development's workflows (#6318)").option("--heal", "repair safe local reconstructible state (scratch gitignore, churn, stray local tags, ff-only branch lag, finished scratch branches, stale alignment ledger leg); it never clears a ledger-pending, ledger-failed or branch-mismatch blocker (#6404, #6401, #6399) \u2014 those need `mmi-cli devops release --resume` (or, with fresh approval, `--abort --apply`) and `git checkout <start branch>`, so exit 1 after --heal is the gate working, not a failed heal").option("--repo <owner/repo>", "target repo (defaults to the current checkout)").option("--json", "machine-readable output").option("--out <path>", "write the verdict to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802/#6563); pair with --json for a machine-readable file (e.g. `--json --out .jerv/tmp/train-doctor.json`); the file is written even when the verdict is NOT READY").addHelpText("after", "\nExit codes:\n 0 ready \u2014 no blocker and origin verified\n 1 a blocker remains, or origin could not be verified (never green on an unread origin)\n\nEvery finding carries code, severity (blocker|warning|healed|info), source (local|origin), remedy and a\ndocs/Guides/train-troubleshooting.md#<code> anchor. `release --apply` and `rcand --apply` run this at step 0 with --heal.\n").action(async (o) => {
|
|
37600
|
+
train.command("doctor").description("one shared preflight-and-heal verdict for the release, rcand and hotfix lanes; read-only unless --heal (#6067)").addOption(new Option("--lane <lane>", "train lane to check (defaults from the release track: direct \u2192 release)").choices([...TRAIN_LANES])).option("--dev", "judge the `release --dev` lane (development -> main, skipping rc): the lane starts from development and is read on development's workflows (#6318)").option("--heal", "repair safe local reconstructible state (scratch gitignore, churn, stray local tags, ff-only branch lag, finished scratch branches, stale alignment ledger leg); it never clears a ledger-pending, ledger-failed or branch-mismatch blocker (#6404, #6401, #6399) \u2014 those need `mmi-cli devops release --resume` (or, with fresh approval, `--abort --apply`) and `git checkout <start branch>`, so exit 1 after --heal is the gate working, not a failed heal").option("--repo <owner/repo>", "target repo (defaults to the current checkout)").option("--suite-solo", "judge an owner-approved solo release of one suite module, as `release --suite-solo --owner-go` does (requires --owner-go; never on rcand, #7327)").option("--owner-go", "explicit owner approval for the suite-solo lane (requires --suite-solo)").option("--json", "machine-readable output").option("--out <path>", "write the verdict to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802/#6563); pair with --json for a machine-readable file (e.g. `--json --out .jerv/tmp/train-doctor.json`); the file is written even when the verdict is NOT READY").addHelpText("after", "\nExit codes:\n 0 ready \u2014 no blocker and origin verified\n 1 a blocker remains, or origin could not be verified (never green on an unread origin)\n\nEvery finding carries code, severity (blocker|warning|healed|info), source (local|origin), remedy and a\ndocs/Guides/train-troubleshooting.md#<code> anchor. `release --apply` and `rcand --apply` run this at step 0 with --heal.\n").action(async (o) => {
|
|
37576
37601
|
try {
|
|
37602
|
+
if (o.suiteSolo !== o.ownerGo || o.lane === "rcand" && o.suiteSolo) {
|
|
37603
|
+
return failGraceful("train doctor: a suite-solo verdict needs BOTH --suite-solo --owner-go, and never on the rcand lane");
|
|
37604
|
+
}
|
|
37577
37605
|
if (o.dev && o.lane && o.lane !== "release") {
|
|
37578
37606
|
return failGraceful(`train doctor: --dev applies only to the release lane \u2014 it names the development -> main variant that skips rc, which the ${o.lane} lane does not have`);
|
|
37579
37607
|
}
|
|
@@ -37594,7 +37622,7 @@ function registerTrainCommands(program3, trainDeps) {
|
|
|
37594
37622
|
}
|
|
37595
37623
|
}
|
|
37596
37624
|
};
|
|
37597
|
-
const verdict = await runTrainDoctor({ lane: o.lane, dev: o.dev === true, heal: o.heal === true, train: deps, repo: o.repo, cwd: root, argv: INVOKED_ARGV });
|
|
37625
|
+
const verdict = await runTrainDoctor({ lane: o.lane, dev: o.dev === true, heal: o.heal === true, train: deps, repo: o.repo, cwd: root, argv: INVOKED_ARGV, suiteSolo: o.suiteSolo === true });
|
|
37598
37626
|
if (verdict.reexecCode !== void 0) return process.exit(verdict.reexecCode);
|
|
37599
37627
|
const output = o.json ? JSON.stringify(verdict, null, 2) : formatTrainDoctor(verdict);
|
|
37600
37628
|
if (!o.out) console.log(output);
|
package/package.json
CHANGED