@mutmutco/claude-plugin 4.0.15 → 4.0.17

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.0.15",
4
+ "version": "4.0.17",
5
5
  "mmiCompat": "4.x",
6
6
  "description": "MMI workflow skills and org gates delivery.",
7
7
  "author": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/claude-plugin",
3
- "version": "4.0.15",
3
+ "version": "4.0.17",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",
@@ -38,6 +38,9 @@ nothing deploys before the protected `main` push accepts that checked SHA.
38
38
  branch's lineage and every tag-anchored check (coverage trailers, misalignment guard, version probes)
39
39
  re-flags or mis-reads forever after. Any merge that carries an already-tagged commit — the Step 5
40
40
  `main → development` roll-forward, any alignment PR — lands as a **true merge** (`--merge`), never squash.
41
+ `--wait` does not relax this: use `mmi-cli devops pr merge <n> --wait --merge` (or the policy-gated
42
+ `--auto --merge`). `--wait` alone still defaults the CLI merge method to squash and must not land an
43
+ alignment / tagged-commit-carrying PR.
41
44
  - **A refused train is a stop, never a license to finish by hand.** Every fail-closed halt below — authority
42
45
  probe, coverage guard, untolerated conflict, required checks, stray tag — ends the run. The recovery is
43
46
  always to fix the cause and re-run the train; it is never hand-resolving on `main`, bare-pushing a train
@@ -45,6 +48,12 @@ nothing deploys before the protected `main` push accepts that checked SHA.
45
48
  - **Version probes anchor on the latest Release tag, not a branch.** `next-version.mjs` and the fold derive
46
49
  the next version from tags; a branch manifest or a stale local tag is not a version source. (This is why a
47
50
  stray tag must be deleted locally too — a surviving local tag silently mints the *next* version, Step 3.)
51
+ - **One `/release` at a time on a repo (#5380).** Two overlapping `--apply` runs race the shared tag namespace:
52
+ the slower train can tag a SHA that never got a fold commit, while the other sees that tag mid-flight and
53
+ mints the *next* version (a skip). Publish then fails verify (`root package and lockfile versions must
54
+ equal …`) and the broken GitHub Release can briefly hold **Latest**. `mmi-cli devops release --apply`
55
+ fail-closes post-fold / pre-tag when the computed tag (or a newer release tag) appears on origin since
56
+ the plan-phase probe — stop, do not hand-finish, do not start a second train. Recovery is below (Step 3).
48
57
 
49
58
  ## Step 0 — confirm + probe
50
59
 
@@ -181,6 +190,17 @@ not a lockfile failure (#4982).** Rename `node_modules` aside once into a gitign
181
190
  the identical train command. `npm ci` extracts into the now-empty tree and performs no unlinks; do not retry
182
191
  this workaround repeatedly.
183
192
 
193
+ **A fold failure outside `npm ci` is often the repo's own npm lifecycle script, not a toolchain or lockfile
194
+ problem (#5365).** App-style folds run `npm version`, which fires `preversion` / `version` / `postversion`
195
+ (e.g. sync-workspace-version + refresh-distribution-bom); Hub folds run `release-distribution.mjs prepare`,
196
+ which likewise executes repo scripts. When those fail, the train surfaces only
197
+ `fold failed; local main was reset` — the real error is one layer down. Open the newest npm debug log
198
+ (path printed by npm, typically under the npm cache `_logs/`) and read the verbose title / argv: if it
199
+ names `npm version …` (or another non-`ci` command) and a `runScript` / lifecycle command failed, run that
200
+ script standalone (e.g. `node scripts/refresh-distribution-bom.mjs`) to get the real error in seconds.
201
+ Do this **before** suspecting npm major (#4578), cold cache (#4841), EPERM/EBUSY (#4982), or regenerating
202
+ the lockfile — those classes apply to install failures, not to a script that already had `node_modules`.
203
+
184
204
  **Then check the version yourself — do not rely on doctor having printed a row (#3674).** "Read the rows"
185
205
  resolves to "proceed" when the row is *absent*, and doctor's version row is conditional. On 2026-07-27 this
186
206
  step reported healthy with no version line while the installed CLI was 3.70.0 against a released 3.71.0;
@@ -277,7 +297,8 @@ why (a hotfix freezes a snapshot that `development` can keep rewriting).
277
297
  Alignment PRs are the exception to the org's squash default: land them with a true merge —
278
298
  `mmi-cli devops pr merge <n> --auto --merge` (not squash; a squash discards the merge parentage, so the
279
299
  misalignment guard re-flags the same divergence on the next run). `--auto` clears the checks the PR
280
- triggers, which block an immediate merge right after a release.
300
+ triggers, which block an immediate merge right after a release. When awaiting checks inline, keep
301
+ `--merge`: `mmi-cli devops pr merge <n> --wait --merge` — `--wait` alone is not enough (merge floor above).
281
302
 
282
303
  **Exception — version-manifest and `.gitignore` paths.** `mmi-cli devops release --apply` tolerates
283
304
  conflicts confined to the version-fold paths (Step 1b) and `.gitignore` (#1037 — a
@@ -309,6 +330,10 @@ What the fold bumps, by repo:
309
330
 
310
331
  Nothing to do by hand; the `--apply` result reports the fold outcome (`versionFold`).
311
332
 
333
+ When the fold fails here, classify with Step 0a's fold-failure notes before retrying or touching the
334
+ lockfile. If the failure is outside `npm ci`, read the npm debug log's verbose title/argv and run the
335
+ named lifecycle script standalone (#5365) — do not stop at `fold failed; local main was reset`.
336
+
312
337
  ## Step 2 — tag the release
313
338
 
314
339
  Full-track repos drop the `-rc.N` suffix from the open cycle. Direct-track repos use the next cycle directly
@@ -381,6 +406,16 @@ delete — mint the next version with `MMI_RELEASE_VERSION` instead. The CLI alr
381
406
  (`isStrayUnreleasedTag`, `cli/src/train-apply.ts`); this note surfaces the doctrine so a halted operator does
382
407
  not re-derive it from source.
383
408
 
409
+ **Halted by a concurrent-train refusal, or a publish verify that says package/lockfile versions ≠ the tag
410
+ (#5380)?** Same deletion class as a stray tag, plus the GitHub Release if one was created (it may still show
411
+ as **Latest** while broken). Evidence shape: two tags one patch apart from overlapping `/release` runs (e.g.
412
+ `v3.1.11` on a no-fold SHA + `v3.1.12` minted because that tag landed mid-flight), and verify text like
413
+ `root package and lockfile versions must equal 3.1.11`. Do **not** leave the skip-version tag and continue —
414
+ with the authorized human's go: delete the broken Release (`gh release delete vX.Y.Z --yes`), delete the
415
+ stray tag locally and on origin, confirm `next-version` would re-derive the *same* version (not the skip),
416
+ then re-run a **single** `mmi-cli devops release --apply`. If the newer skip-version already published
417
+ cleanly, keep it and only remove the broken older Release/tag.
418
+
384
419
  ## Step 4 — GitHub Release + start prod deploy (non-blocking)
385
420
 
386
421
  For `tenant-container` repos, publish the GitHub Release and dispatch the central tenant deploy.
@@ -498,7 +533,8 @@ mmi-cli oracle org project sync-info --apply # omit --apply for the read-only
498
533
  PR with a true merge** — `mmi-cli devops pr merge <number> --auto --merge` (never squash — a squash drops the merge
499
534
  parentage and the misalignment guard re-flags the divergence). `--auto` is what makes it land right after a
500
535
  release: the alignment PR's own `cli`/`infra`/`docs` checks are still running, so a plain immediate merge is
501
- policy-blocked — `--auto` merges once they pass. Never force.
536
+ policy-blocked — `--auto` merges once they pass. If you await with `--wait` instead, still pass `--merge`
537
+ (`mmi-cli devops pr merge <number> --wait --merge`); `--wait` alone must not land the alignment PR. Never force.
502
538
  - Full-track repos: `mmi-cli devops release --apply` already aligned `rc` to the released `main` (#1036 — the
503
539
  push runs inside the authority-gated train; the result reports it as `rcAlignment`). No manual `rc`
504
540
  push — if the result reports a failed alignment, investigate and rerun via the train, never bare-push.
@@ -551,15 +587,36 @@ don't publish by hand.
551
587
  Watch it, then confirm npm caught up:
552
588
  ```bash
553
589
  gh run watch "$(gh run list --workflow publish.yml --event release --limit 1 --json databaseId -q '.[0].databaseId')" --exit-status
554
- node scripts/release-distribution.mjs verify "vX.Y.0" # asserts registry versions, BOM identities, and published npm artifacts
590
+ node scripts/release-distribution.mjs verify "X.Y.0" # bare semver — asserts registry versions, BOM identities, and published npm artifacts
555
591
  ```
592
+ **verify takes bare semver (#5379).** Pass `X.Y.Z`, not the git-tag form `vX.Y.Z`. Checkout still
593
+ uses the tag (`git checkout "vX.Y.0"`); the distribution script's version argument is strict semver
594
+ without a leading `v`.
556
595
  Run that verify from a checkout **at the tag** (`main` right after the release merge, `git checkout
557
596
  "vX.Y.0"`, or a worktree at the tag) — verify checks the working tree and refuses any other commit once
558
597
  the tag exists, so a stale `development`/`rc` checkout can't masquerade as a broken release.
559
598
  Release-blocking for Hub tooling changes: every public artifact must match the registry version and BOM
560
- identity. Manual fallback if CI can't publish: `node scripts/release-distribution.mjs publish "vX.Y.0"`
599
+ identity. Manual fallback if CI can't publish: `node scripts/release-distribution.mjs publish "X.Y.0"`
561
600
  from a machine with npm auth.
562
601
 
602
+ **npm tarball identity is packer-sensitive (#5366 / #5251).** `verify` without `--skip-npm-view`
603
+ compares the registry's served `dist.integrity` (SSRI) against a live `npm pack` on THIS machine
604
+ (`packedIntegrityBySurface`). A tarball SSRI covers file modes and packer (npm version) behavior, so
605
+ that identity step is authoritative **only** when run in the publish environment (`publish.yml` on the
606
+ self-hosted Linux runner) — or on an operator machine with the **same OS and npm major** as that
607
+ runner. Elsewhere (Windows, a clean Linux container with a different packer, a mismatched npm major) a
608
+ `tarball identity mismatch` can false-fail even when the published bytes match the tag: three different
609
+ SSRIs (registry / Windows pack / container pack) with content-identical unpacked trees is the expected
610
+ cross-environment shape, not a substituted artifact. Off the publish environment, either:
611
+ - fall back to an **unpacked-content** proof — download the registry tarball (`npm pack <pkg>@X.Y.Z`
612
+ from the registry, or `npm view … dist.tarball`), `npm pack` from the tag checkout, unpack both, and
613
+ `diff -r` the trees (empty diff ⇒ identity OK; do not alarm on SSRI alone), or
614
+ - skip the registry identity read with
615
+ `node scripts/release-distribution.mjs verify "X.Y.0" --skip-npm-view` and verify published content
616
+ by hand the same way.
617
+ Do not treat an off-runner SSRI mismatch as a broken release, and do not change how the runner publishes
618
+ to paper over a local packer difference.
619
+
563
620
  **Private packages (#2405) — never trust a bare `npm view` to mean "not published".** An unauthenticated
564
621
  `npm view <pkg>` returns a hard 404 on any package published with `publishConfig.access=restricted`
565
622
  (private) — indistinguishable from "not published" — because npm masks private packages from anonymous
@@ -33,6 +33,15 @@ into the compose **process environment** — the compose file reads them via `en
33
33
  secret ever touches disk. A repo that still ships `.env.example` keeps the legacy `.env` bootstrap for
34
34
  back-compat until its compose migrates to passthrough; new repos should ship **no** `.env.example`.
35
35
 
36
+ **Build-time secrets (#5381).** When META declares `requiredBuildSecrets` (e.g. Katip's
37
+ `NODE_AUTH_TOKEN=@github-packages-token` for `@mutmutco/fofu-ds` on GitHub Packages), `/stage` injects those
38
+ BuildKit ids into the **`docker compose build`** process env only — not into the running container. Central
39
+ deploy mints the packages sentinel from Actions `GITHUB_TOKEN`; a laptop cannot. Resolution order: existing
40
+ process env → stageless project vault secret under the BuildKit id (a `read:packages` PAT at
41
+ `NODE_AUTH_TOKEN`). If both are missing, `/stage` fails with a teaching error before npm's opaque 401.
42
+ Setup: [`docs/Guides/tenant-runtime.md`](../../docs/Guides/tenant-runtime.md) § Local `/stage`. Never commit
43
+ or print the PAT.
44
+
36
45
  ## Step 0 — inspect the plan
37
46
 
38
47
  ```bash