@mutmutco/claude-plugin 4.5.115 → 4.5.117

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mmi",
3
3
  "displayName": "MMI",
4
- "version": "4.5.115",
4
+ "version": "4.5.117",
5
5
  "mmiCompat": "4.x",
6
6
  "description": "MMI workflow skills and org gates delivery.",
7
7
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -17939,10 +17939,10 @@ var rollout_plan_default = {
17939
17939
  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)."
17940
17940
  },
17941
17941
  baseline: {
17942
- version: "4.5.115",
17943
- tag: "v4.5.115",
17944
- commit: "8d0add650762",
17945
- npm: "@mutmutco/cli@4.5.115"
17942
+ version: "4.5.117",
17943
+ tag: "v4.5.117",
17944
+ commit: "8ec1a0aa6b67",
17945
+ npm: "@mutmutco/cli@4.5.117"
17946
17946
  },
17947
17947
  exitCriterion: "fleet-n-of-n",
17948
17948
  hubOnlyShortcut: "forbidden",
@@ -17959,14 +17959,14 @@ var rollout_plan_default = {
17959
17959
  repo: "mutmutco/mmi-hub",
17960
17960
  role: "canary",
17961
17961
  schedule: "train",
17962
- v3Target: "v4.5.115"
17962
+ v3Target: "v4.5.117"
17963
17963
  }
17964
17964
  ],
17965
17965
  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.",
17966
17966
  rollback: {
17967
17967
  independent: true,
17968
- mechanism: "npm dist-tag latest -> 4.5.115 and redeploy the Hub Lambda from tag v4.5.115 (8d0add650762); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17969
- v3Target: "v4.5.115 (@mutmutco/cli@4.5.115, tag commit 8d0add650762 \u2014 last known-good release carrying the repo-index v4-only contract)"
17968
+ mechanism: "npm dist-tag latest -> 4.5.117 and redeploy the Hub Lambda from tag v4.5.117 (8ec1a0aa6b67); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
17969
+ v3Target: "v4.5.117 (@mutmutco/cli@4.5.117, tag commit 8ec1a0aa6b67 \u2014 last known-good release carrying the repo-index v4-only contract)"
17970
17970
  }
17971
17971
  },
17972
17972
  {
@@ -36506,12 +36506,13 @@ function suiteMembers(raw) {
36506
36506
  for (const item of raw) {
36507
36507
  if (!item || typeof item !== "object") throw new Error("invalid MM-Work module registry row");
36508
36508
  const row = item;
36509
- const repo = typeof row.id === "string" ? REPOS[row.id] : void 0;
36509
+ const repo = typeof row.repository === "string" && /^[\w.-]+\/[\w.-]+$/.test(row.repository) ? row.repository : typeof row.id === "string" ? REPOS[row.id] : void 0;
36510
36510
  if (!repo || !row.bundles || typeof row.bundles !== "object") throw new Error(`unknown MM-Work module registry id: ${String(row.id)}`);
36511
36511
  members.push({ repo, id: row.id, bundles: row.bundles });
36512
36512
  }
36513
36513
  return members;
36514
36514
  }
36515
+ var trainModules = (members) => members.filter((m) => m.repo !== SUITE_REPO && (REPOS[m.id] || m.bundles.rc || m.bundles.main));
36515
36516
  function bundleTag(url) {
36516
36517
  if (typeof url !== "string") return void 0;
36517
36518
  try {
@@ -36935,7 +36936,7 @@ async function pendingBackend(deps, m, dev) {
36935
36936
  async function suiteRcand(deps, opts) {
36936
36937
  if (!opts.ownerGo && !opts.dryRun) throw new Error("suite rcand requires --owner-go (rc uses live data); nothing was written");
36937
36938
  const members = suiteMembers(await deps.registry());
36938
- const modules = members.filter((m) => m.repo !== SUITE_REPO);
36939
+ const modules = trainModules(members);
36939
36940
  const { active, held } = await holdSplit(deps, modules);
36940
36941
  const heldById = new Map(held.map((h) => [h.id, h]));
36941
36942
  const plan = [
@@ -37109,7 +37110,7 @@ async function suiteRelease(deps, ownerGo, big = false) {
37109
37110
  if (!ownerGo) throw new Error("suite release requires --owner-go; nothing was written");
37110
37111
  const record = readSuiteCut(deps.recordPath);
37111
37112
  if (!record?.pinMerged || !record.leadRcTag) throw new Error("no completed suite rc cut and merged pin PR; release refused");
37112
- const members = suiteMembers(await deps.registry()).filter((m) => m.repo !== SUITE_REPO);
37113
+ const members = trainModules(suiteMembers(await deps.registry()));
37113
37114
  const { active, held } = await holdSplit(deps, members);
37114
37115
  if (!heldMatches(record.heldMembers ?? [], held)) throw new Error("suite hold changed after the cut; release refused");
37115
37116
  if (active.length !== record.members.length || active.some((m) => !record.members.some((r) => r.repo === m.repo && r.id === m.id))) throw new Error("suite roster changed after the cut; release refused");
@@ -41007,7 +41008,7 @@ async function openSuiteCutPinPr(deps, input) {
41007
41008
  let scratch = "";
41008
41009
  try {
41009
41010
  const rows = await registry2();
41010
- const members = suiteMembers(rows).filter((m) => m.repo !== SUITE_REPO);
41011
+ const members = trainModules(suiteMembers(rows));
41011
41012
  if (members.length !== covered.length || members.some((m) => !covered.includes(m.id))) throw new Error("cut pins do not match the complete MM-Work roster");
41012
41013
  for (const pin of input.pins) {
41013
41014
  for (const url of [pin.rc, pin.main]) {
@@ -48339,7 +48340,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
48339
48340
  }
48340
48341
  },
48341
48342
  suiteMapping: async (leadTag) => {
48342
- const rows = suiteMembers(await registry2(leadTag)).filter((m) => m.repo !== SUITE_REPO);
48343
+ const rows = trainModules(suiteMembers(await registry2(leadTag)));
48343
48344
  return Object.fromEntries(rows.map((m) => {
48344
48345
  const v = bundleTag(m.bundles.main);
48345
48346
  if (!v) throw new Error(`${m.id}: MM-Work ${leadTag} has no versioned main pin; mapping not recorded`);
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.5.115",
3
+ "version": "4.5.117",
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/claude-plugin",
3
- "version": "4.5.115",
3
+ "version": "4.5.117",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",
@@ -81,18 +81,18 @@ Read the saved result, never the exit code (exit `1` = a follow-up failed after
81
81
  - `releaseVerdict.releaseStatus` + `followUpStatus` — `succeeded` + `pending` is shipped with the follow-up unresolved: neither failed nor done. A `--resume` receipt carries the same `releaseVerdict` (`command: release-resume`), plus its own `mode` and `state`.
82
82
  - `deployStatus` — `pending` is never terminal; `promoted: true` holds even when a deploy failed.
83
83
  - `served-channel(<product>)` row — the release's proof that new installs get it: the public `/release/version` pointer of the releasing repo's OWN channel (the Hub's `mmi`, or the product its registry `installer` declaration names; no declaration → no row), read after deploy and publish are green. `success` names the version read. `failure` is either a channel still on the previous version or a stale served process (the route answers 401/404): the note names what moves that channel and the exact remedy; run it, then re-read the pointer. `pending` means not probed (legs not green) or unreadable, never proof. The row is receipt evidence only, never a ledger leg, so it never blocks the next train.
84
- - `workflowRuns` — every run on the release SHA (deploy-model runs, any `push: main` deploy, the repo's own `gate`). Watch each non-success entry to conclusion: `gh run watch <run-id> --repo {owner}/{repo} --exit-status --interval 30`. Name which run is red: `deploy.yml` / `publish.yml` / `tenant-deploy.yml` / `jerv-gateway` is a deploy or publish verdict; a `gate` push run is ordinary CI sharing the SHA.
84
+ - `workflowRuns` — every run on the release SHA (deploy-model runs, any `push: main` deploy, the repo's own `gate`). On this host, discover them with the bounded run-list read below; filter locally by the exact receipt SHA. If the list hits its 100-row cap or returns no matching SHA, treat the run set as unverified and stop rather than infer completeness. Watch each matching non-success entry to conclusion: `gh run watch <run-id> --repo {owner}/{repo} --exit-status --interval 30`. Name which run is red: `deploy.yml` / `publish.yml` / `tenant-deploy.yml` / `jerv-gateway` is a deploy or publish verdict; a `gate` push run is ordinary CI sharing the SHA.
85
85
  - With `--watch` the train waits for its own alignment PR to land (true merge) and folds the ledger in the same run, so the receipt ends `succeeded` / `complete`. An external `gh run watch` never folds anything: if the receipt still shows a `pending` leg (no `--watch`, the alignment PR outlived the bounded wait, or a release-event `publish.yml` run on a registry-publish repo had not been correlated by the time the receipt was written — `--watch` waits for the alignment PR, not for that run, so a `publish` leg `pending` with no run URL after `--watch` is the expected direct-track shape, not a failure), fold it live before declaring the cut done or starting any new train: `mmi-cli devops release --resume --watch --json --out <fresh-receipt>`; the NEXT train's doctor otherwise refuses with `ledger-pending`.
86
86
  - `announceNote` — `announced` (to the alerts channel for the Hub, to the project release channel for a product repo), `skipped`, `not announced` (deploy or publish not green; the note says whether a `--resume` carrying the same `--announce-summary-file` will post it), or the failure note. The channel id itself is never printed.
87
87
  - `devRollForward` / `rcAlignment` — `pushed`, or `pr-pending` with the alignment PR to land by true merge (Merge floor). An enqueued auto-merge is not evidence of the method; before reporting, read the enqueued method back — `gh pr view <n> --json autoMergeRequest --jq .autoMergeRequest.mergeMethod` — and prove it is `MERGE`. An enqueued `SQUASH` is a stop under the Merge floor, not something to wait out.
88
88
  - `versionFold`, `rcRetirement`, `checkout` — `returned`, or the named reason you are still on `main`.
89
89
  - A `private` npm surface (`surfaces.json`): the doctor's `npm-token-rejected` finding comes first. A 401 from `npm whoami` through the `_org` `npm/NPM_TOKEN` vault hop means the token is rejected, and every authenticated `npm view` then 404s exactly like an absent package — rotate the token; only after a login is a restricted 404 "unverifiable from here", never "not published" (`publish-private-package`). On a repo whose workflows publish through Trusted Publishing and name no registry token, that row is `info`, not a warning: no lane consumes the org token, so it constrains your manual read only.
90
90
 
91
- Then the bounded Latest Release read; its `tagName` must equal the resolved tag:
91
+ Then verify Latest with this bounded one-row read; require `isLatest: true` and `tagName` equal to the resolved tag: `gh release list --repo {owner}/{repo} --limit 1 --json tagName,isLatest,publishedAt`.
92
92
 
93
- ```bash
94
- gh api repos/{owner}/{repo}/releases/latest --jq '{tagName:.tag_name,targetCommitish:.target_commitish,publishedAt:.published_at,url:.html_url}'
95
- ```
93
+ For the independent run recheck, run `gh run list --repo {owner}/{repo} --limit 100 --json databaseId,headSha,workflowName,status,conclusion,url > .jerv/tmp/release-runs.json`, then filter locally by the exact SHA from the saved receipt with `node -e 'const rows = require("./.jerv/tmp/release-runs.json"); const sha = process.argv[1]; const matches = rows.filter((run) => run.headSha === sha); if (rows.length >= 100 || !matches.length) throw new Error("release run set is incomplete or absent"); console.log(JSON.stringify(matches, null, 2));' "<release-sha>"`.
94
+
95
+ Do not use the raw `releases/latest` API route, a `--jq` formatter, or `gh run list --commit`; if the bounded list reaches 100 rows or has no SHA match, the run set is unverified and must not be called green.
96
96
 
97
97
  Four facts close the verdict: the `origin/main..origin/development` count, the tag on origin, Latest, and green runs on the release SHA.
98
98