@mutmutco/cli 4.3.29 → 4.3.31

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 +49 -14
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -15584,10 +15584,10 @@ var rollout_plan_default = {
15584
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)."
15585
15585
  },
15586
15586
  baseline: {
15587
- version: "4.3.29",
15588
- tag: "v4.3.29",
15589
- commit: "5a5b64c2d604",
15590
- npm: "@mutmutco/cli@4.3.29"
15587
+ version: "4.3.31",
15588
+ tag: "v4.3.31",
15589
+ commit: "d171389927fd",
15590
+ npm: "@mutmutco/cli@4.3.31"
15591
15591
  },
15592
15592
  exitCriterion: "fleet-n-of-n",
15593
15593
  hubOnlyShortcut: "forbidden",
@@ -15604,14 +15604,14 @@ var rollout_plan_default = {
15604
15604
  repo: "mutmutco/mmi-hub",
15605
15605
  role: "canary",
15606
15606
  schedule: "train",
15607
- v3Target: "v4.3.29"
15607
+ v3Target: "v4.3.31"
15608
15608
  }
15609
15609
  ],
15610
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.",
15611
15611
  rollback: {
15612
15612
  independent: true,
15613
- mechanism: "npm dist-tag latest -> 4.3.29 and redeploy the Hub Lambda from tag v4.3.29 (5a5b64c2d604); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15614
- v3Target: "v4.3.29 (@mutmutco/cli@4.3.29, tag commit 5a5b64c2d604 \u2014 last known-good release carrying the repo-index v4-only contract)"
15613
+ mechanism: "npm dist-tag latest -> 4.3.31 and redeploy the Hub Lambda from tag v4.3.31 (d171389927fd); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
15614
+ v3Target: "v4.3.31 (@mutmutco/cli@4.3.31, tag commit d171389927fd \u2014 last known-good release carrying the repo-index v4-only contract)"
15615
15615
  }
15616
15616
  },
15617
15617
  {
@@ -16476,6 +16476,13 @@ function validateEnum(flag, allowed, value, command) {
16476
16476
  }
16477
16477
  return v;
16478
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
+ }
16479
16486
  var ISSUE_STATES = ["open", "closed", "all"];
16480
16487
  var PR_STATES = ["open", "all"];
16481
16488
  async function resolveBoardProjectId(repoOption) {
@@ -16591,7 +16598,7 @@ function registerQueryCommands(program3) {
16591
16598
  const project2 = program3.commands.find((c) => c.name() === "project");
16592
16599
  if (!issue || !pr) return;
16593
16600
  const deps = queryDeps();
16594
- 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").choices(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) => {
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) => {
16595
16602
  try {
16596
16603
  const state = validateEnum("--state", ISSUE_STATES, o.state, "issue list");
16597
16604
  const rows = await runIssueList(deps, { label: o.label, search: o.search, state, assignee: o.assignee, limit: o.limit, repo: o.repo });
@@ -16623,7 +16630,7 @@ function registerQueryCommands(program3) {
16623
16630
  queryFail("issue frontier", e);
16624
16631
  }
16625
16632
  });
16626
- 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").choices(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) => {
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) => {
16627
16634
  try {
16628
16635
  const state = validateEnum("--state", PR_STATES, o.state, "pr list");
16629
16636
  const rows = await runPrList(deps, { mine: o.mine, state, limit: o.limit, repo: o.repo });
@@ -21293,6 +21300,10 @@ async function selfConvergeTrainCli(input) {
21293
21300
  // src/train-doctor.ts
21294
21301
  var TRAIN_LANES = ["release", "rcand", "hotfix"];
21295
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
+ }
21296
21307
  var SCRATCH_BRANCH_GLOBS = ["train/check/*", "hotfix-fold/*--port-*"];
21297
21308
  var COMPOSE_GUARD_HARD_FAIL = /^secrets preflight: .*noEnvFile is (not )?true.*$/m;
21298
21309
  function readOriginWorkflowsDefault(root, ref) {
@@ -21396,7 +21407,7 @@ async function runTrainDoctor(input) {
21396
21407
  const findings = [];
21397
21408
  let originUnverified = false;
21398
21409
  const add = (f) => {
21399
- findings.push({ ...f, anchor: `${TROUBLESHOOTING_GUIDE}#${f.code}` });
21410
+ findings.push({ ...f, anchor: troubleshootingAnchor(f.code) });
21400
21411
  };
21401
21412
  const unverified = (what, e) => {
21402
21413
  originUnverified = true;
@@ -22594,6 +22605,29 @@ async function latestRemoteRcTag(deps) {
22594
22605
  const tag = [...tags.keys()].sort(compareRcTagsNewestFirst)[0];
22595
22606
  return tag ? { tag, sha: tags.get(tag) } : void 0;
22596
22607
  }
22608
+ async function activeRcandLedgerCandidate(deps, cwd) {
22609
+ let path2;
22610
+ try {
22611
+ path2 = releaseLedgerPath(cwd);
22612
+ } catch {
22613
+ return void 0;
22614
+ }
22615
+ let prior;
22616
+ try {
22617
+ prior = parseReleaseLedger((0, import_node_fs24.readFileSync)(path2, "utf8"));
22618
+ } catch {
22619
+ return void 0;
22620
+ }
22621
+ if (prior.lane !== "rcand") return void 0;
22622
+ let liveSha = "";
22623
+ try {
22624
+ liveSha = clean2(await runGitRemoteRead(deps, ["ls-remote", "origin", `refs/tags/${prior.tag}`])).split(/\s+/)[0] ?? "";
22625
+ } catch {
22626
+ return void 0;
22627
+ }
22628
+ if (liveSha.toLowerCase() !== prior.tagSha.toLowerCase()) return void 0;
22629
+ return { tag: prior.tag, sha: prior.tagSha };
22630
+ }
22597
22631
  async function probeAncestor(deps, ancestor, descendant, label) {
22598
22632
  try {
22599
22633
  await deps.run("git", ["merge-base", "--is-ancestor", ancestor, descendant]);
@@ -22617,7 +22651,7 @@ async function runRcandResume(deps, options = {}) {
22617
22651
  throw new Error("rcand --resume: origin/rc does not exist \u2014 there is no candidate branch to resume");
22618
22652
  }
22619
22653
  const deployModel = await preflight(deps, ctx, "rc", meta);
22620
- const candidate = await latestRemoteRcTag(deps);
22654
+ const candidate = await activeRcandLedgerCandidate(deps, process.cwd()) ?? await latestRemoteRcTag(deps);
22621
22655
  if (!candidate) {
22622
22656
  throw new Error("rcand --resume: no public v*-rc.* tag found on origin \u2014 there is no tagged candidate to resume");
22623
22657
  }
@@ -27607,7 +27641,7 @@ function registerBootstrapCommands(program3) {
27607
27641
  source: "origin",
27608
27642
  title: `bootstrap verify could not run train doctor: ${e.message}`,
27609
27643
  remedy: `run mmi-cli devops train doctor --lane ${lane} --repo ${repo} --json`,
27610
- anchor: "docs/Guides/train-troubleshooting.md#origin-unverified"
27644
+ anchor: troubleshootingAnchor("origin-unverified")
27611
27645
  }]
27612
27646
  });
27613
27647
  }
@@ -40054,7 +40088,8 @@ ${list}`);
40054
40088
  "--head and --base default to the current branch and the repo default; only pass them to override.",
40055
40089
  "Use --body-file for multiline PR bodies instead of shell-escaped inline markdown.",
40056
40090
  "Write that file under .jerv/ inside the host workspace (#4405); host policy governs untracked files.",
40057
- '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).'
40091
+ '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).',
40092
+ '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).'
40058
40093
  ]);
40059
40094
  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) => {
40060
40095
  let parsed;
@@ -43307,7 +43342,7 @@ function readRepoVersion() {
43307
43342
  }
43308
43343
  function registerTrainCommands(program3, trainDeps) {
43309
43344
  const train = program3.command("train").description("release-train observability \u2014 track position, version lag, and the shared preflight-and-heal doctor (#2688, #6067)");
43310
- 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) => {
43345
+ 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) => {
43311
43346
  try {
43312
43347
  if (o.dev && o.lane && o.lane !== "release") {
43313
43348
  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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.3.29",
3
+ "version": "4.3.31",
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",