@mutmutco/cli 4.5.26 → 4.5.27

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 +63 -7
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -16816,10 +16816,10 @@ var rollout_plan_default = {
16816
16816
  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)."
16817
16817
  },
16818
16818
  baseline: {
16819
- version: "4.5.26",
16820
- tag: "v4.5.26",
16821
- commit: "f5ca4e782979",
16822
- npm: "@mutmutco/cli@4.5.26"
16819
+ version: "4.5.27",
16820
+ tag: "v4.5.27",
16821
+ commit: "30f02884a0f7",
16822
+ npm: "@mutmutco/cli@4.5.27"
16823
16823
  },
16824
16824
  exitCriterion: "fleet-n-of-n",
16825
16825
  hubOnlyShortcut: "forbidden",
@@ -16836,14 +16836,14 @@ var rollout_plan_default = {
16836
16836
  repo: "mutmutco/mmi-hub",
16837
16837
  role: "canary",
16838
16838
  schedule: "train",
16839
- v3Target: "v4.5.26"
16839
+ v3Target: "v4.5.27"
16840
16840
  }
16841
16841
  ],
16842
16842
  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.",
16843
16843
  rollback: {
16844
16844
  independent: true,
16845
- mechanism: "npm dist-tag latest -> 4.5.26 and redeploy the Hub Lambda from tag v4.5.26 (f5ca4e782979); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
16846
- v3Target: "v4.5.26 (@mutmutco/cli@4.5.26, tag commit f5ca4e782979 \u2014 last known-good release carrying the repo-index v4-only contract)"
16845
+ mechanism: "npm dist-tag latest -> 4.5.27 and redeploy the Hub Lambda from tag v4.5.27 (30f02884a0f7); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
16846
+ v3Target: "v4.5.27 (@mutmutco/cli@4.5.27, tag commit 30f02884a0f7 \u2014 last known-good release carrying the repo-index v4-only contract)"
16847
16847
  }
16848
16848
  },
16849
16849
  {
@@ -28769,6 +28769,50 @@ async function attachBoardIssues(selectors, repoOption, deps = {}) {
28769
28769
  // src/board-commands.ts
28770
28770
  init_clean_exit();
28771
28771
  init_error_codes();
28772
+
28773
+ // src/board-events.ts
28774
+ init_fetch_retry();
28775
+ init_client_version();
28776
+ var BOARD_EVENTS_POLL_MS = 2e3;
28777
+ var BOARD_EVENTS_MAX_WAIT_S = 120;
28778
+ function isPage(b) {
28779
+ const p = b;
28780
+ return Boolean(p && Number.isInteger(p.cursor) && Array.isArray(p.events) && typeof p.resync === "boolean" && typeof p.more === "boolean");
28781
+ }
28782
+ async function readBoardEvents(since, deps) {
28783
+ if (!deps.baseUrl) throw new Error("no Hub API URL (set MMI_HUB_URL or use a current MMI CLI build)");
28784
+ const token = await deps.token();
28785
+ if (!token) throw new Error("no Hub session token (run `gh auth login`)");
28786
+ const query = since === void 0 ? "" : `?since=${since}`;
28787
+ const res = await fetchWithRetry(
28788
+ deps.fetch ?? fetch,
28789
+ `${deps.baseUrl.replace(/\/$/, "")}/board/events${query}`,
28790
+ { method: "GET", headers: { ...clientVersionHeaders(), Authorization: `Bearer ${token}` } },
28791
+ { attempts: 3, timeoutMs: 1e4 }
28792
+ );
28793
+ if (res.status === 426) throw new Error(upgradeRequiredError(res, await res.json().catch(() => null)));
28794
+ const body = await res.json().catch(() => null);
28795
+ if (!res.ok) {
28796
+ const detail = body?.error;
28797
+ throw new Error(`board events HTTP ${res.status}${detail ? `: ${detail}` : ""}`);
28798
+ }
28799
+ if (!isPage(body)) throw new Error("malformed board events response");
28800
+ return body;
28801
+ }
28802
+ async function waitBoardEvents(since, waitS, deps) {
28803
+ const now = deps.now ?? Date.now;
28804
+ const sleep2 = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
28805
+ const deadline = now() + Math.min(Math.max(waitS, 0), BOARD_EVENTS_MAX_WAIT_S) * 1e3;
28806
+ let cursor = since;
28807
+ for (; ; ) {
28808
+ const page = await readBoardEvents(cursor, deps);
28809
+ if (page.events.length || page.resync || page.more || now() + BOARD_EVENTS_POLL_MS > deadline) return page;
28810
+ cursor = page.cursor;
28811
+ await sleep2(BOARD_EVENTS_POLL_MS);
28812
+ }
28813
+ }
28814
+
28815
+ // src/board-commands.ts
28772
28816
  function refuseRateLimited(e, json) {
28773
28817
  if (!isRateLimitedError(e)) return false;
28774
28818
  if (json) console.log(JSON.stringify(e.receipt));
@@ -28852,6 +28896,18 @@ function registerBoardCommands(program3) {
28852
28896
  }
28853
28897
  const board = program3.command("board").description("read, claim, show, and move Project v2 work items for the current repo");
28854
28898
  board.command("read", { isDefault: true }).alias("list").description("read the board and print user-owned, claimable, and taken items").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo (defaults to git origin)").option("--direct", "bypass the Hub snapshot and read the live board through direct GitHub GraphQL").option("--snapshot-only", "fail instead of falling back to your personal GraphQL pool when the Hub snapshot is unavailable \u2014 for ambient readers such as sidebars (#7203)").option("--bundle-details", "fetch body/comments only for user-owned and claimable issues").option("--bodies", "fetch body/comments for EVERY scoped row, including taken and unowned in-flight ones \u2014 for consumers that scope by Status rather than ownership (#4861); implies --bundle-details and costs one extra read per row").option("--allow-partial", "return partial board results when later page/detail reads fail").option("--out <path>", "write the output to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802)").addHelpText("after", "\nread is always the authoritative live GitHub Project v2 board (#4926).\n--direct skips the Hub snapshot and uses the existing direct GitHub GraphQL read immediately.\n--allow-partial applies to the paginated path and detail reads.\n\nWhen using Windows PowerShell 5.1, avoid shell redirects: PowerShell 5.1's `> file.json` is Out-File,\nwhich writes UTF-16LE with a BOM, and Node reading it as 'utf8' then fails JSON.parse at position 1\n(#5802). Use --out instead \u2014 the CLI writes the file itself as UTF-8:\n mmi-cli oracle board read --json --out .jerv/tmp/board.json\n").action((o) => runBoardRead(o));
28899
+ board.command("events").description("content-free board/CI change records after a cursor, from the Hub event feed (no GitHub call) \u2014 for real-time sidebars (#7235)").option("--since <cursor>", "cursor from the previous answer; omit on first read (answers the head cursor with resync:true)").option("--wait <seconds>", "hold up to this long (max 120), polling every 2s, and return on the first event or resync", "0").option("--repo <owner/repo>", "repo whose Hub config to use (defaults to git origin)").option("--json", "machine-readable output (already the default)").addHelpText("after", "\nPrints {cursor, events, resync, more[, hidden]}. Pass the returned cursor as the next --since.\nresync:true means records were missed (retention ~1h, or a gap): re-read the board with\n`mmi-cli oracle board read --snapshot-only --json`.\n").action(async (o) => {
28900
+ try {
28901
+ if (o.since !== void 0 && !/^\d{1,15}$/.test(o.since)) throw new Error("--since must be a non-negative integer cursor");
28902
+ const wait = Number(o.wait ?? "0");
28903
+ if (!Number.isFinite(wait) || wait < 0) throw new Error("--wait must be a non-negative number of seconds");
28904
+ const config = await loadConfigForRepo(o.repo);
28905
+ const page = await waitBoardEvents(o.since === void 0 ? void 0 : Number(o.since), wait, registryClientDeps(config));
28906
+ console.log(JSON.stringify(page));
28907
+ } catch (e) {
28908
+ return failGraceful(`oracle board events failed: ${e.message}`);
28909
+ }
28910
+ });
28855
28911
  withExamples(mutating(
28856
28912
  board.command("claim <issues...>").description("claim issues: assign them and move their Project v2 Status to In Progress \u2014 idempotent, so an item already yours and In Progress succeeds unchanged (one or more refs); the board scan rides the Hub snapshot, same as board read").addHelpText("after", "\nclaim reads the board through the same Hub snapshot leg as `board read` (the App-installation\ncredential, never your personal GraphQL pool); the direct user-auth read is an emergency fallback\nand is named in a Warning line after the verdict (#6162).\n\nevery claim stamps a lane-identity marker comment on the issue (`<!-- mmi-claim: \u2026 -->`,\nsurface/session@host) so other agents can attribute the hold (#3727). The session is the\nhost-exported id when the surface provides one, otherwise a per-process `synth-` fallback \u2014\na claim is never anonymous (#5245). `board show`, doctor and unclaim read the latest marker.\n\nsame-owner resume (#6035): when the prior marker was posted by YOUR login on THIS host and its\nlocal session is verifiably dead (transcript probe), the claim proceeds as a resume without\n--force and names the evidence. A live, foreign-host, or unprobeable prior lane still refuses.\n\nreclaim from In Review (#6339): an In Review item with no holder, or one held by the claiming\nlogin, is claimable \u2014 it moves back to In Progress and the receipt names the status it came from.\nAn In Review item another login holds is refused (ask the holder, or wait for the review to land),\nand Done stays refused. The board status is the authority; no PR state is consulted.\n").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo for local issue numbers (defaults to git origin)").option("--for <login>", "assign to this login instead of @me \u2014 agent claims on behalf of the master").option("--force", "take an item already claimed by another lane that shows live evidence of active work (#3727)").option("--check", "read-only: run every claim gate and report the verdict, writing nothing \u2014 exits 1 with the same refusal a real claim would raise (#4511)").option("--allow-partial", "return success JSON if assignment succeeds but the status move fails"),
28857
28913
  (_opts, args) => ({ command: "oracle board claim", issues: args[0] ?? [] })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.26",
3
+ "version": "4.5.27",
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",