@mutmutco/cli 4.3.28 → 4.3.30
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 +43 -17
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -11896,7 +11896,10 @@ function laneResumeEvidence(evidence) {
|
|
|
11896
11896
|
return `prior claim by lane ${describeClaimMarker(evidence.marker)} (@${evidence.markerBy}, ${formatClaimAge(evidence.markerAgeMs)} old) is verifiably not running on this host \u2014 its local session transcript is gone or stale${artifacts.length ? `; resuming over ${artifacts.join("; ")}` : ""}`;
|
|
11897
11897
|
}
|
|
11898
11898
|
async function checkLaneContest(client, item, actor = describeSessionIdentity(), viewerLogin) {
|
|
11899
|
-
|
|
11899
|
+
let evidence = await gatherClaimLiveness(client, item.repository, item.number, openPullsFetcher(client));
|
|
11900
|
+
if (evidence.failed.some((channel) => channel !== "session")) {
|
|
11901
|
+
evidence = await gatherClaimLiveness(client, item.repository, item.number, openPullsFetcher(client));
|
|
11902
|
+
}
|
|
11900
11903
|
const ownership = laneOwnership(evidence.marker, actor);
|
|
11901
11904
|
const sameOwner = Boolean(viewerLogin && evidence.markerBy && evidence.markerBy.toLowerCase() === viewerLogin.toLowerCase());
|
|
11902
11905
|
const resume = ownership !== "mine" && sameOwner ? laneResumeEvidence(evidence) : void 0;
|
|
@@ -15581,10 +15584,10 @@ var rollout_plan_default = {
|
|
|
15581
15584
|
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)."
|
|
15582
15585
|
},
|
|
15583
15586
|
baseline: {
|
|
15584
|
-
version: "4.3.
|
|
15585
|
-
tag: "v4.3.
|
|
15586
|
-
commit: "
|
|
15587
|
-
npm: "@mutmutco/cli@4.3.
|
|
15587
|
+
version: "4.3.30",
|
|
15588
|
+
tag: "v4.3.30",
|
|
15589
|
+
commit: "a8f898264f6e",
|
|
15590
|
+
npm: "@mutmutco/cli@4.3.30"
|
|
15588
15591
|
},
|
|
15589
15592
|
exitCriterion: "fleet-n-of-n",
|
|
15590
15593
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15601,14 +15604,14 @@ var rollout_plan_default = {
|
|
|
15601
15604
|
repo: "mutmutco/mmi-hub",
|
|
15602
15605
|
role: "canary",
|
|
15603
15606
|
schedule: "train",
|
|
15604
|
-
v3Target: "v4.3.
|
|
15607
|
+
v3Target: "v4.3.30"
|
|
15605
15608
|
}
|
|
15606
15609
|
],
|
|
15607
15610
|
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.",
|
|
15608
15611
|
rollback: {
|
|
15609
15612
|
independent: true,
|
|
15610
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15611
|
-
v3Target: "v4.3.
|
|
15613
|
+
mechanism: "npm dist-tag latest -> 4.3.30 and redeploy the Hub Lambda from tag v4.3.30 (a8f898264f6e); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15614
|
+
v3Target: "v4.3.30 (@mutmutco/cli@4.3.30, tag commit a8f898264f6e \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15612
15615
|
}
|
|
15613
15616
|
},
|
|
15614
15617
|
{
|
|
@@ -16473,6 +16476,13 @@ function validateEnum(flag, allowed, value, command) {
|
|
|
16473
16476
|
}
|
|
16474
16477
|
return v;
|
|
16475
16478
|
}
|
|
16479
|
+
function caseInsensitiveChoices(option, allowed) {
|
|
16480
|
+
return option.choices(allowed).argParser((value) => {
|
|
16481
|
+
const folded = value.toLowerCase();
|
|
16482
|
+
if (!allowed.includes(folded)) throw new InvalidArgumentError(`Allowed choices are ${allowed.join(", ")}.`);
|
|
16483
|
+
return folded;
|
|
16484
|
+
});
|
|
16485
|
+
}
|
|
16476
16486
|
var ISSUE_STATES = ["open", "closed", "all"];
|
|
16477
16487
|
var PR_STATES = ["open", "all"];
|
|
16478
16488
|
async function resolveBoardProjectId(repoOption) {
|
|
@@ -16588,7 +16598,7 @@ function registerQueryCommands(program3) {
|
|
|
16588
16598
|
const project2 = program3.commands.find((c) => c.name() === "project");
|
|
16589
16599
|
if (!issue || !pr) return;
|
|
16590
16600
|
const deps = queryDeps();
|
|
16591
|
-
issue.command("list").description("bounded issue read \u2014 filter by text, label, state, or assignee; always prints JSON").option("--label <label>", "filter by label").option("--search <query>", "free-text issue search").addOption(new Option("--state <state>", "open | closed | all").default("open")
|
|
16601
|
+
issue.command("list").description("bounded issue read \u2014 filter by text, label, state, or assignee; always prints JSON").option("--label <label>", "filter by label").option("--search <query>", "free-text issue search").addOption(caseInsensitiveChoices(new Option("--state <state>", "open | closed | all").default("open"), ISSUE_STATES)).option("--assignee <login>", "filter by assignee login").option("--limit <n>", "max issues to return (capped at 100)", (v) => Number(v), DEFAULT_LIMIT).option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json", "machine-readable output (already the default \u2014 accepted for contract uniformity)").action(async (o) => {
|
|
16592
16602
|
try {
|
|
16593
16603
|
const state = validateEnum("--state", ISSUE_STATES, o.state, "issue list");
|
|
16594
16604
|
const rows = await runIssueList(deps, { label: o.label, search: o.search, state, assignee: o.assignee, limit: o.limit, repo: o.repo });
|
|
@@ -16620,7 +16630,7 @@ function registerQueryCommands(program3) {
|
|
|
16620
16630
|
queryFail("issue frontier", e);
|
|
16621
16631
|
}
|
|
16622
16632
|
});
|
|
16623
|
-
pr.command("list").description("bounded PR read \u2014 --mine scopes to the viewer's own PRs (resolves the viewer via gh); always prints JSON").option("--mine", "only the caller's own PRs (resolves the viewer via `gh api user`)").addOption(new Option("--state <state>", "open | all").default("open")
|
|
16633
|
+
pr.command("list").description("bounded PR read \u2014 --mine scopes to the viewer's own PRs (resolves the viewer via gh); always prints JSON").option("--mine", "only the caller's own PRs (resolves the viewer via `gh api user`)").addOption(caseInsensitiveChoices(new Option("--state <state>", "open | all").default("open"), PR_STATES)).option("--limit <n>", "max PRs to return (capped at 100)", (v) => Number(v), DEFAULT_LIMIT).option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json", "machine-readable output (already the default \u2014 accepted for contract uniformity)").action(async (o) => {
|
|
16624
16634
|
try {
|
|
16625
16635
|
const state = validateEnum("--state", PR_STATES, o.state, "pr list");
|
|
16626
16636
|
const rows = await runPrList(deps, { mine: o.mine, state, limit: o.limit, repo: o.repo });
|
|
@@ -21290,6 +21300,10 @@ async function selfConvergeTrainCli(input) {
|
|
|
21290
21300
|
// src/train-doctor.ts
|
|
21291
21301
|
var TRAIN_LANES = ["release", "rcand", "hotfix"];
|
|
21292
21302
|
var TROUBLESHOOTING_GUIDE = "docs/Guides/train-troubleshooting.md";
|
|
21303
|
+
var TROUBLESHOOTING_GUIDE_URL = `https://github.com/mutmutco/MMI-Hub/blob/development/${TROUBLESHOOTING_GUIDE}`;
|
|
21304
|
+
function troubleshootingAnchor(code) {
|
|
21305
|
+
return `${TROUBLESHOOTING_GUIDE_URL}#${code}`;
|
|
21306
|
+
}
|
|
21293
21307
|
var SCRATCH_BRANCH_GLOBS = ["train/check/*", "hotfix-fold/*--port-*"];
|
|
21294
21308
|
var COMPOSE_GUARD_HARD_FAIL = /^secrets preflight: .*noEnvFile is (not )?true.*$/m;
|
|
21295
21309
|
function readOriginWorkflowsDefault(root, ref) {
|
|
@@ -21393,7 +21407,7 @@ async function runTrainDoctor(input) {
|
|
|
21393
21407
|
const findings = [];
|
|
21394
21408
|
let originUnverified = false;
|
|
21395
21409
|
const add = (f) => {
|
|
21396
|
-
findings.push({ ...f, anchor:
|
|
21410
|
+
findings.push({ ...f, anchor: troubleshootingAnchor(f.code) });
|
|
21397
21411
|
};
|
|
21398
21412
|
const unverified = (what, e) => {
|
|
21399
21413
|
originUnverified = true;
|
|
@@ -23644,6 +23658,12 @@ function refPatternCovers(pattern, ref) {
|
|
|
23644
23658
|
function uncoveredTrackBranches(liveIncludes, trackBranches) {
|
|
23645
23659
|
return trackBranches.filter((branch) => !liveIncludes.some((pattern) => refPatternCovers(pattern, `refs/heads/${branch}`)));
|
|
23646
23660
|
}
|
|
23661
|
+
function unreachableTrackBranches(uncovered, requiredContexts, emittedByBranch) {
|
|
23662
|
+
return uncovered.filter((branch) => {
|
|
23663
|
+
const emitted = emittedByBranch[branch];
|
|
23664
|
+
return emitted !== void 0 && !requiredContexts.every((context) => emitted.includes(context));
|
|
23665
|
+
});
|
|
23666
|
+
}
|
|
23647
23667
|
function rulesetCoversReleaseBranches(payload, track) {
|
|
23648
23668
|
const conditions = payload.conditions;
|
|
23649
23669
|
const include = conditions?.ref_name?.include;
|
|
@@ -23945,14 +23965,19 @@ async function auditRepoCi(repo, deps) {
|
|
|
23945
23965
|
}
|
|
23946
23966
|
}
|
|
23947
23967
|
if (productRuleset != null) {
|
|
23948
|
-
const
|
|
23968
|
+
const presentTrackBranches = [];
|
|
23949
23969
|
for (const branch of uncoveredTrackBranches(liveBranchIncludes, branchesForTrack(resolveReleaseTrack(meta, void 0, repo)))) {
|
|
23950
|
-
if (await branchPresence(deps, repo, branch) === true)
|
|
23970
|
+
if (await branchPresence(deps, repo, branch) === true) presentTrackBranches.push(branch);
|
|
23951
23971
|
}
|
|
23972
|
+
const emittedByTrackBranch = {};
|
|
23973
|
+
for (const branch of presentTrackBranches) emittedByTrackBranch[branch] = await resolveEmittedPrContexts(deps, repo, branch);
|
|
23974
|
+
const toleratedTrackBranches = unreachableTrackBranches(presentTrackBranches, liveContexts, emittedByTrackBranch);
|
|
23975
|
+
const missingTrackBranches = presentTrackBranches.filter((branch) => !toleratedTrackBranches.includes(branch));
|
|
23976
|
+
const toleratedNote = toleratedTrackBranches.length ? ` (tolerated until first release: [${toleratedTrackBranches.join(", ")}] \u2014 their trees cannot emit every one of [${liveContexts.join(", ")}], #6385)` : "";
|
|
23952
23977
|
checks.push({
|
|
23953
23978
|
ok: missingTrackBranches.length === 0,
|
|
23954
23979
|
label: RULESET_TRACK_SCOPE_LABEL,
|
|
23955
|
-
detail: missingTrackBranches.length ? `live ${PRODUCT_RULESET_NAME} includes [${liveBranchIncludes.join(", ")}] but the release track also requires [${missingTrackBranches.join(", ")}] \u2014 those branches tag and merge with no required check` : void 0,
|
|
23980
|
+
detail: missingTrackBranches.length ? `live ${PRODUCT_RULESET_NAME} includes [${liveBranchIncludes.join(", ")}] but the release track also requires [${missingTrackBranches.join(", ")}] \u2014 those branches tag and merge with no required check${toleratedNote}` : toleratedNote ? toleratedNote.trim().replace(/^\(|\)$/g, "") : void 0,
|
|
23956
23981
|
remediation: missingTrackBranches.length ? `mmi-cli oracle org project set ${repo} --var requiredCheckBranches=${JSON.stringify(branchesForTrack(resolveReleaseTrack(meta, void 0, repo)))} then mmi-cli devops bootstrap apply ${repo} --execute` : void 0
|
|
23957
23982
|
});
|
|
23958
23983
|
}
|
|
@@ -27593,7 +27618,7 @@ function registerBootstrapCommands(program3) {
|
|
|
27593
27618
|
source: "origin",
|
|
27594
27619
|
title: `bootstrap verify could not run train doctor: ${e.message}`,
|
|
27595
27620
|
remedy: `run mmi-cli devops train doctor --lane ${lane} --repo ${repo} --json`,
|
|
27596
|
-
anchor: "
|
|
27621
|
+
anchor: troubleshootingAnchor("origin-unverified")
|
|
27597
27622
|
}]
|
|
27598
27623
|
});
|
|
27599
27624
|
}
|
|
@@ -40040,7 +40065,8 @@ ${list}`);
|
|
|
40040
40065
|
"--head and --base default to the current branch and the repo default; only pass them to override.",
|
|
40041
40066
|
"Use --body-file for multiline PR bodies instead of shell-escaped inline markdown.",
|
|
40042
40067
|
"Write that file under .jerv/ inside the host workspace (#4405); host policy governs untracked files.",
|
|
40043
|
-
'Keep closing keywords on a dedicated line ("Closes #N") \u2014 GitHub parses close/fix/resolve + #N even mid-sentence, so pr create rewrites such prose to "part of #N" (#6039).'
|
|
40068
|
+
'Keep closing keywords on a dedicated line ("Closes #N") \u2014 GitHub parses close/fix/resolve + #N even mid-sentence, so pr create rewrites such prose to "part of #N" (#6039).',
|
|
40069
|
+
'When acceptance is only provable AFTER deploy, link with "Part of #N", never "Closes" \u2014 a closing reference closes the issue and advances its board card to Done on merge, before the acceptance evidence exists. Close it on that evidence instead (#6407).'
|
|
40044
40070
|
]);
|
|
40045
40071
|
pr.command("view <ref>").description("read a PR as structured JSON (merged state, head/base, URL, merge commit) \u2014 the mmi-cli read path (#2347). --comments folds in every comment; --context also adds linkedIssues (the issues it closes/references, #2894)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json [fields...]", 'gh --json field list (overrides the default field set). Accepts commas, spaces, or repeated --json flags \u2014 in PowerShell an unquoted comma list is an array literal, so QUOTE it: --json "state,baseRefName,mergeCommit"').option("--comments", "include every comment (body + comments in one call) \u2014 read the whole PR before landing it (#2894)").option("--context", "full working context in one call: implies --comments and also adds linkedIssues (the issues the PR closes/references) (#2894)").action(async (ref, o) => {
|
|
40046
40072
|
let parsed;
|
|
@@ -43293,7 +43319,7 @@ function readRepoVersion() {
|
|
|
43293
43319
|
}
|
|
43294
43320
|
function registerTrainCommands(program3, trainDeps) {
|
|
43295
43321
|
const train = program3.command("train").description("release-train observability \u2014 track position, version lag, and the shared preflight-and-heal doctor (#2688, #6067)");
|
|
43296
|
-
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)").option("--repo <owner/repo>", "target repo (defaults to the current checkout)").option("--json", "machine-readable output").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) => {
|
|
43322
|
+
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").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) => {
|
|
43297
43323
|
try {
|
|
43298
43324
|
if (o.dev && o.lane && o.lane !== "release") {
|
|
43299
43325
|
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`);
|
package/package.json
CHANGED