@adia-ai/adia-ui-forge 0.8.37 → 0.8.39

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 (46) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +23 -0
  3. package/README.md +6 -2
  4. package/agents/a2ui-planner-agent.md +52 -0
  5. package/agents/framework-alignment-agent.md +60 -0
  6. package/agents/framework-planner-agent.md +49 -0
  7. package/package.json +1 -1
  8. package/references/contracts/a2ui-mcp-surface.md +7 -7
  9. package/skills/a2ui-maintenance/SKILL.md +5 -5
  10. package/skills/a2ui-maintenance/references/anti-patterns.md +2 -2
  11. package/skills/a2ui-maintenance/references/chunk-authoring.md +2 -2
  12. package/skills/a2ui-maintenance/references/eval-diagnostics.md +3 -3
  13. package/skills/a2ui-maintenance/references/format-extension-decisions.md +1 -1
  14. package/skills/a2ui-maintenance/references/mcp-pipeline-ops.md +5 -5
  15. package/skills/a2ui-maintenance/references/mcp-tool-reference.md +4 -4
  16. package/skills/a2ui-maintenance/references/pipeline-overview.md +18 -18
  17. package/skills/a2ui-maintenance/references/semantic-fail-lifting.md +2 -2
  18. package/skills/a2ui-maintenance/references/strategy-engines.md +2 -2
  19. package/skills/a2ui-maintenance/references/zettel-calibration.md +2 -2
  20. package/skills/gen-ui-review/references/corpus-html-patterns.md +1 -1
  21. package/skills/gen-ui-review/references/loop-protocol.md +1 -1
  22. package/skills/llm-client-maintenance/SKILL.md +4 -4
  23. package/skills/llm-client-maintenance/references/adapter-contract.md +3 -3
  24. package/skills/llm-client-maintenance/references/add-a-provider.md +5 -5
  25. package/skills/llm-client-maintenance/references/bridge-facade.md +2 -2
  26. package/skills/llm-client-maintenance/references/browser-proxy-boundary.md +2 -2
  27. package/skills/llm-client-maintenance/references/model-registry.md +2 -2
  28. package/skills/llm-client-maintenance/references/streaming-sse.md +2 -2
  29. package/skills/package-release/SKILL.md +8 -8
  30. package/skills/package-release/references/cut-procedure.md +6 -91
  31. package/skills/package-release/references/gates-catalog.md +4 -4
  32. package/skills/package-release/references/independent-package-release.md +2 -2
  33. package/skills/package-release/references/recovery-paths.md +2 -2
  34. package/skills/package-release/scripts/bump.mjs +31 -28
  35. package/skills/package-release/scripts/insert-stub.mjs +1 -1
  36. package/skills/package-release/scripts/package-paths.mjs +34 -50
  37. package/skills/package-release/scripts/release-pack.mjs +12 -5
  38. package/skills/package-release/scripts/tag-lockstep.mjs +1 -1
  39. package/skills/primitive-authoring/references/common-gotchas.md +1 -1
  40. package/skills/primitive-authoring/references/css-patterns.md +1 -1
  41. package/skills/primitive-authoring/references/llm-bridge.md +12 -12
  42. package/skills/primitive-authoring/references/module-promotion.md +2 -2
  43. package/skills/primitive-authoring/references/token-contract.md +20 -1
  44. package/skills/site-deployment/SKILL.md +2 -2
  45. package/skills/site-deployment/references/deploy-playbooks.md +8 -8
  46. package/skills/site-docs-authoring/intent.md +1 -1
@@ -1,10 +1,10 @@
1
1
  # Adapter contract
2
2
 
3
- The single shape every provider adapter implements. Source: `packages/llm/src/adapters/anthropic.ts` (the canonical adapter — `openai.ts` and `gemini.ts` import their shared types from it), the facade `packages/llm/src/adapters/index.ts`, and the shared parser `packages/llm/src/adapters/sse.ts`.
3
+ The single shape every provider adapter implements. Source: `packages/llm/core/src/adapters/anthropic.ts` (the canonical adapter — `openai.ts` and `gemini.ts` import their shared types from it), the facade `packages/llm/core/src/adapters/index.ts`, and the shared parser `packages/llm/core/src/adapters/sse.ts`.
4
4
 
5
5
  This reference is about the adapter object — its three methods, the request it builds, and the response/usage/`stopReason` it parses. The SSE-byte mechanics live in `streaming-sse.md`; the facade that dispatches to an adapter lives in `bridge-facade.md`.
6
6
 
7
- Field tables below are a snapshot verified against `packages/llm/src/` on 2026-07-10 — on any conflict, the source wins; re-grep before relying on an exact field name.
7
+ Field tables below are a snapshot verified against `packages/llm/core/src/` on 2026-07-10 — on any conflict, the source wins; re-grep before relying on an exact field name.
8
8
 
9
9
  ---
10
10
 
@@ -98,4 +98,4 @@ Symptom: cache hit-rate telemetry reads `0` for Anthropic even though the API re
98
98
  - [bridge-facade.md](bridge-facade.md) — how `chat()` / `streamChat()` resolve and call an adapter; the `ChatResult` wrapper
99
99
  - [browser-proxy-boundary.md](browser-proxy-boundary.md) — why `buildRequest()` must stay proxy-agnostic
100
100
  - [add-a-provider.md](add-a-provider.md) — the end-to-end recipe that uses this contract
101
- - Source: `packages/llm/src/adapters/anthropic.ts` (canonical types + adapter), `openai.ts`, `gemini.ts`
101
+ - Source: `packages/llm/core/src/adapters/anthropic.ts` (canonical types + adapter), `openai.ts`, `gemini.ts`
@@ -1,6 +1,6 @@
1
1
  # Add a provider
2
2
 
3
- The end-to-end recipe for a 4th provider adapter (DeepSeek, Mistral, Cohere, an OpenAI-compatible gateway, …). Grounded in the existing three adapters under `packages/llm/src/adapters/` and the facade `packages/llm/src/adapters/index.ts`. Read `adapter-contract.md` first — this recipe wires the contract it defines.
3
+ The end-to-end recipe for a 4th provider adapter (DeepSeek, Mistral, Cohere, an OpenAI-compatible gateway, …). Grounded in the existing three adapters under `packages/llm/core/src/adapters/` and the facade `packages/llm/core/src/adapters/index.ts`. Read `adapter-contract.md` first — this recipe wires the contract it defines.
4
4
 
5
5
  Adding a provider is **additive** to the public surface (a new adapter, a new `MODELS` group, a new `detectProvider` branch). It does not break existing consumers if you follow the contract.
6
6
 
@@ -12,7 +12,7 @@ Many providers (Groq, Together, Mistral, any OpenAI-compatible gateway) speak th
12
12
 
13
13
  ## Step 1 — write the adapter
14
14
 
15
- Create `packages/llm/src/adapters/<name>.ts` exporting one `const` matching the contract (model on `anthropic.ts`):
15
+ Create `packages/llm/core/src/adapters/<name>.ts` exporting one `const` matching the contract (model on `anthropic.ts`):
16
16
 
17
17
  - `name: '<name>' as const`.
18
18
  - `buildRequest(opts: BuildRequestOpts): AdapterRequest` — return `{ url, headers, body }`. Set the auth header the provider expects. Map `opts.system`, `opts.messages`, `opts.maxTokens` (default to the package's `32768` unless the provider's ceiling is lower), `opts.temperature`, and the `stream` flag into the provider's body shape.
@@ -23,7 +23,7 @@ Create `packages/llm/src/adapters/<name>.ts` exporting one `const` matching the
23
23
 
24
24
  ## Step 2 — register in the facade
25
25
 
26
- Edit `packages/llm/src/adapters/index.ts`:
26
+ Edit `packages/llm/core/src/adapters/index.ts`:
27
27
 
28
28
  ```text
29
29
  import { myprovider } from './myprovider.js';
@@ -44,7 +44,7 @@ Support both conventions — a substring (`m.includes(...)`) and a `provider/mod
44
44
 
45
45
  ## Step 4 — add to the model registry
46
46
 
47
- Edit `packages/llm/src/models.ts` — add a `ModelGroup`:
47
+ Edit `packages/llm/core/src/models.ts` — add a `ModelGroup`:
48
48
 
49
49
  ```text
50
50
  { label: 'MyProvider', options: [ { value: '<model-id>', label: '<display name>' } ] }
@@ -54,7 +54,7 @@ Keep the `[{ label, options: [{ value, label }] }]` shape exactly (the `<chat-in
54
54
 
55
55
  ## Step 5 — wire the bridge default + browser route (if browser-routable)
56
56
 
57
- Edit `packages/llm/src/llm-bridge.ts`:
57
+ Edit `packages/llm/core/src/llm-bridge.ts`:
58
58
 
59
59
  - Add `myprovider: '<default-model-id>'` to `DEFAULT_MODELS` (the per-provider fallback `createAdapter()` uses when no model is supplied — distinct from `models.ts`'s `DEFAULT_MODEL`; see `model-registry.md`).
60
60
  - **INVARIANT: every keyed map in the bridge (`DEFAULT_MODELS`, `resolveBaseUrl`'s proxyMap, `detectProvider`'s return) uses the SAME key as the adapters registry** (`providers` in `adapters/index.ts`). A mismatched key compiles fine and throws at runtime (`Unknown provider`) — the gh#268 L-1 bug class. If a marketing name differs from the registry key (Google/Gemini), normalize the alias at the top of `createAdapter()` and use the registry key everywhere below.
@@ -1,6 +1,6 @@
1
1
  # Bridge + facade + stub
2
2
 
3
- The three public entry layers above the adapters. Source: the facade `packages/llm/src/adapters/index.ts` (`chat` / `streamChat` / `createClient` + types), the bridge `packages/llm/src/llm-bridge.ts` (`createAdapter` → `AdiaUILLMBridge`), the stub `packages/llm/src/llm-stub.ts` (`StubLLMAdapter`), and the barrel `packages/llm/src/index.ts`.
3
+ The three public entry layers above the adapters. Source: the facade `packages/llm/core/src/adapters/index.ts` (`chat` / `streamChat` / `createClient` + types), the bridge `packages/llm/core/src/llm-bridge.ts` (`createAdapter` → `AdiaUILLMBridge`), the stub `packages/llm/core/src/llm-stub.ts` (`StubLLMAdapter`), and the barrel `packages/llm/core/src/index.ts`.
4
4
 
5
5
  This reference covers the facade/bridge contract and the stub. The proxy-flavor mechanics are in `browser-proxy-boundary.md`.
6
6
 
@@ -98,4 +98,4 @@ The stub's `complete()` result shape (`{ content, usage: { inputTokens, outputTo
98
98
  - [browser-proxy-boundary.md](browser-proxy-boundary.md) — the `proxyUrl` dispatch and the production-host stub path
99
99
  - [model-registry.md](model-registry.md) — `DEFAULT_MODEL` vs the bridge's `DEFAULT_MODELS`
100
100
  - [streaming-sse.md](streaming-sse.md) — the `StreamChunk` union the bridge re-shapes
101
- - Source: `packages/llm/src/adapters/index.ts`, `packages/llm/src/llm-bridge.ts`, `packages/llm/src/llm-stub.ts`, `packages/llm/src/index.ts`
101
+ - Source: `packages/llm/core/src/adapters/index.ts`, `packages/llm/core/src/llm-bridge.ts`, `packages/llm/core/src/llm-stub.ts`, `packages/llm/core/src/index.ts`
@@ -1,6 +1,6 @@
1
1
  # Browser / proxy boundary
2
2
 
3
- The browser+Node duality and the two proxy flavors. Source: the dispatch in `packages/llm/src/adapters/index.ts` (`isPassthroughProxy`, `proxyRequest`, `passthroughRequest`) and the browser logic in `packages/llm/src/llm-bridge.ts` (`resolveBaseUrl`, `isProductionHost`, `createBrowserProxyBridge`, the key-in-browser warning).
3
+ The browser+Node duality and the two proxy flavors. Source: the dispatch in `packages/llm/core/src/adapters/index.ts` (`isPassthroughProxy`, `proxyRequest`, `passthroughRequest`) and the browser logic in `packages/llm/core/src/llm-bridge.ts` (`resolveBaseUrl`, `isProductionHost`, `createBrowserProxyBridge`, the key-in-browser warning).
4
4
 
5
5
  This is the single most error-prone area of the package: `proxyUrl` is overloaded, and getting it wrong produces silent 401s in the browser even when the local server works fine.
6
6
 
@@ -88,4 +88,4 @@ Keep the warning and the dedup flag when touching `createAdapter()`.
88
88
  - [adapter-contract.md](adapter-contract.md) — `buildRequest()` as the single upstream-shape source
89
89
  - [bridge-facade.md](bridge-facade.md) — `createAdapter()` and the stub fallback
90
90
  - [streaming-sse.md](streaming-sse.md) — SSE-through-a-proxy buffering symptoms
91
- - Source: `isPassthroughProxy` / `proxyRequest` / `passthroughRequest` in `packages/llm/src/adapters/index.ts`; `resolveBaseUrl` / `isProductionHost` / `createBrowserProxyBridge` in `packages/llm/src/llm-bridge.ts`
91
+ - Source: `isPassthroughProxy` / `proxyRequest` / `passthroughRequest` in `packages/llm/core/src/adapters/index.ts`; `resolveBaseUrl` / `isProductionHost` / `createBrowserProxyBridge` in `packages/llm/core/src/llm-bridge.ts`
@@ -1,6 +1,6 @@
1
1
  # Model registry
2
2
 
3
- The shared model catalog and provider detection. Source: `packages/llm/src/models.ts` (the `MODELS` catalog + `DEFAULT_MODEL`) and the `detectProvider()` function in `packages/llm/src/adapters/index.ts`.
3
+ The shared model catalog and provider detection. Source: `packages/llm/core/src/models.ts` (the `MODELS` catalog + `DEFAULT_MODEL`) and the `detectProvider()` function in `packages/llm/core/src/adapters/index.ts`.
4
4
 
5
5
  Concrete ids/groups below are a snapshot verified against the source on 2026-07-10 — on any conflict, the source wins.
6
6
 
@@ -74,4 +74,4 @@ Add a new Anthropic model to the chat-input dropdown.
74
74
 
75
75
  - [bridge-facade.md](bridge-facade.md) — `createAdapter()` and its per-provider `DEFAULT_MODELS`
76
76
  - [add-a-provider.md](add-a-provider.md) — the recipe that adds a `MODELS` group + a `detectProvider` branch together
77
- - Source: `packages/llm/src/models.ts`, `detectProvider()` in `packages/llm/src/adapters/index.ts`, `DEFAULT_MODELS` in `packages/llm/src/llm-bridge.ts`
77
+ - Source: `packages/llm/core/src/models.ts`, `detectProvider()` in `packages/llm/core/src/adapters/index.ts`, `DEFAULT_MODELS` in `packages/llm/core/src/llm-bridge.ts`
@@ -1,6 +1,6 @@
1
1
  # Streaming + SSE
2
2
 
3
- The streaming protocol and the shared SSE parser. Source: `packages/llm/src/adapters/sse.ts` (the parser) and the `parseStream` method of each adapter in `packages/llm/src/adapters/anthropic.ts` / `openai.ts` / `gemini.ts`. The `StreamChunk` union is declared in `anthropic.ts`.
3
+ The streaming protocol and the shared SSE parser. Source: `packages/llm/core/src/adapters/sse.ts` (the parser) and the `parseStream` method of each adapter in `packages/llm/core/src/adapters/anthropic.ts` / `openai.ts` / `gemini.ts`. The `StreamChunk` union is declared in `anthropic.ts`.
4
4
 
5
5
  ---
6
6
 
@@ -92,4 +92,4 @@ A new `StreamChunk` variant (e.g. `{ type: 'tool_call'; ... }`):
92
92
  - [adapter-contract.md](adapter-contract.md) — the adapter object, `parseResponse`, and the `usage` / `stopReason` mapping
93
93
  - [bridge-facade.md](bridge-facade.md) — how the bridge re-shapes `StreamChunk` for the adia-ui pipeline
94
94
  - [browser-proxy-boundary.md](browser-proxy-boundary.md) — SSE through a proxy (buffering pitfalls)
95
- - Source: `packages/llm/src/adapters/sse.ts`, and the `parseStream` of `anthropic.ts` / `openai.ts` / `gemini.ts`
95
+ - Source: `packages/llm/core/src/adapters/sse.ts`, and the `parseStream` of `anthropic.ts` / `openai.ts` / `gemini.ts`
@@ -3,8 +3,8 @@ name: package-release
3
3
  description: >-
4
4
  Release engineering for the @adia-ai lockstep monorepo. Use when asked to
5
5
  cut and ship a release, promote [Unreleased] CHANGELOG entries, tag and push the
6
- lockstep packages to origin, publish a 16-package release (14
7
- npm libraries + 2 Claude Code plugins, as of gh#1240's MCP fold — see
6
+ lockstep packages to origin, publish a 10-package release (8
7
+ npm libraries + 2 Claude Code plugins, as of gh#1282's shim retirement — see
8
8
  scripts/package-paths.mjs), batch-push piled-up release commits,
9
9
  recover a cut that landed wrong or whose publish workflows didn't fire,
10
10
  fix a check:lockstep bump failure or an F-N1 CHANGELOG-coverage warning,
@@ -18,7 +18,7 @@ user-invocable: true
18
18
 
19
19
  # package-release
20
20
 
21
- Release engineering for an @adia-ai-style lockstep monorepo: the `@adia-ai/*` packages on the roster (`scripts/package-paths.mjs`, the single source — 16 lockstep as of gh#1240's MCP-distribution fold (ADR-0048 P5, amended): 14 npm libraries plus the 2 Claude Code plugins under `packages/plugins/*`; 6 of those libraries are the old-name shims marked `shim: true`, which ride the 0.8.37 cut once and are deleted in the P7 follow-up, taking the count to 10) version and publish together (class A; the plugins joined the lockstep 2026-07-15 after class-B independence let npm drift a full harness-reset behind the repo). Class B (independent versioning) has one member — `@adia-ai/adia-plugins` (gh#1133/gh#1160, ADR-0045), the npm-sourced marketplace manifest package, marked `lockstep: false` on the roster; it cuts on its own version line and its own tag, never the umbrella ([`references/independent-package-release.md`](references/independent-package-release.md)). The substrate — `scripts/release/*`, the `check:*` gates, the tag-triggered publish workflows — encodes the invariants; this skill routes, sequences, and stops at the judgment calls.
21
+ Release engineering for an @adia-ai-style lockstep monorepo: the `@adia-ai/*` packages on the roster (`scripts/package-paths.mjs`, the single source — 10 lockstep as of gh#1282's shim retirement (ADR-0048 P7 follow-up: the six `shim: true` old-name rows rode the 0.8.37 cut once and are deleted): 8 npm libraries plus the 2 Claude Code plugins under `packages/plugins/*`) version and publish together (class A; the plugins joined the lockstep 2026-07-15 after class-B independence let npm drift a full harness-reset behind the repo). Class B (independent versioning) has one member — `@adia-ai/adia-plugins` (gh#1133/gh#1160, ADR-0045), the npm-sourced marketplace manifest package, marked `lockstep: false` on the roster; it cuts on its own version line and its own tag, never the umbrella ([`references/independent-package-release.md`](references/independent-package-release.md)). The substrate — `scripts/release/*`, the `check:*` gates, the tag-triggered publish workflows — encodes the invariants; this skill routes, sequences, and stops at the judgment calls.
22
22
 
23
23
  ## Authorization — one go, gates do the rest (operator ruling 2026-07-17)
24
24
 
@@ -35,11 +35,11 @@ Mechanics: `release-pack.mjs --go` auto-confirms all checkpoints (it equals `--y
35
35
  1. **Lockstep coherence** — every roster package bumps together (`check:lockstep`). **The roster is `scripts/package-paths.mjs`'s `PACKAGE_ROSTER` — read it, never a copy.** This line used to enumerate the names inline and went stale the first time the roster moved (ADR-0048 P4 added a package while the list still read the pre-split six); a name list here has no gate behind it, so it can only decay. Each plugin's `.claude-plugin/plugin.json` version moves with its package.json — `bump.mjs` handles both; `verify:plugins` gates the sync.
36
36
  2. **PATCH-cut asymmetry** — internal `@adia-ai/*` ranges hold at `^X.Y.0` during PATCH cuts; only MINOR bumps the floor. `^0.0.x` is forbidden (pre-1.0 caret locks exact — shipped a real stale-sibling bug).
37
37
  3. **Release commits land via PR, never a direct push to `main`** (repo policy, operator ruling 2026-07-12): commit on `release/vX.Y.Z` → PR → CI → merge — THEN tag at `main`'s post-merge HEAD, not at the bump commit; post-bump fixes merge before tagging and belong in the tarball. Exception: batch push tags each version at its own release-merge SHA.
38
- 4. **One umbrella + one per-package tag per cut** (`vX.Y.Z` + 16 × `<pkg>-vX.Y.Z`, one per lockstep-roster package — `scripts/package-paths.mjs`); publish workflows key off the per-package tags. Push tags **one per `git push`** — a batched multi-tag push drops the trigger event.
38
+ 4. **One umbrella + one per-package tag per cut** (`vX.Y.Z` + 10 × `<pkg>-vX.Y.Z`, one per lockstep-roster package — `scripts/package-paths.mjs`); publish workflows key off the per-package tags. Push tags **one per `git push`** — a batched multi-tag push drops the trigger event.
39
39
  5. **F-N1 (`check:release --all-pending`) per-package clean** — the umbrella-tag mismatch error is expected noise. Coverage is mechanized at cut time: Step 4f (`check-release.mjs --pending-version X.Y.Z --fix`) runs the SAME matcher pre-PR and auto-appends verified Maintenance bullets, so a post-tag warn means something novel — stop and investigate, don't loop enrichment PRs.
40
40
  6. **`npm dist-tag latest` is set by publish order** — batch pushes publish oldest first and WAIT for settle.
41
41
  7. **A breaking (MINOR) cut MUST ship its MIGRATION GUIDE section in the same cycle** — MINOR is reserved for removed/renamed API symbols; everything else, including visible behavior changes, stays PATCH.
42
- 8. **The adia-factory plugin's `.mcp.json` pins the generation MCP exactly** — bump the pin in `packages/plugins/adia-ui-factory/.mcp.json` in the same cut (the consumer never floats; with the plugins in-lockstep this lands in the release commit itself, not a follow-up). The pinned NAME is still `@adia-ai/a2ui-mcp` and flips to `@adia-ai/gen-ui-mcp` in the ADR-0048 P7 release commit never before it, because invariant 8 forces the pin to the current lockstep version and the new name has no `0.8.x` on npm (`references/cut-procedure.md` §the P7 cut).
42
+ 8. **The adia-factory plugin's `.mcp.json` pins the generation MCP exactly** — bump the pin in `packages/plugins/adia-ui-factory/.mcp.json` in the same cut (the consumer never floats; with the plugins in-lockstep this lands in the release commit itself, not a follow-up). The pinned NAME is `@adia-ai/mcp` with the `gen-ui` subcommand (`npx -y @adia-ai/mcp@<exact> gen-ui`) the single live name since the ADR-0048 P7 cut (v0.8.37) per the gh#1240 one-package amendment; `@adia-ai/a2ui-mcp` is retired and the P2-planned `@adia-ai/gen-ui-mcp` never published. `check:lockstep`'s mcp-pin guard and `bump.mjs` both enforce this pin.
43
43
 
44
44
  The release is done only when reality confirms it: **the npm registry, the GH release page, and the deployed endpoint — a workflow's green check or any self-report is never the verify target.**
45
45
 
@@ -59,7 +59,7 @@ The release is done only when reality confirms it: **the npm registry, the GH re
59
59
 
60
60
  | Task shape | Done when |
61
61
  | --- | --- |
62
- | Lockstep cut / handoff | `npm view @adia-ai/<pkg> version` = X.Y.Z for all 16 lockstep packages AND `dist-tags.latest` = X.Y.Z AND a deployed content file (not an SPA route) serves real bytes |
62
+ | Lockstep cut / handoff | `npm view @adia-ai/<pkg> version` = X.Y.Z for all 10 lockstep packages AND `dist-tags.latest` = X.Y.Z AND a deployed content file (not an SPA route) serves real bytes |
63
63
  | Batch push | every batched tag on `git ls-remote --tags origin` + every version on the registry, `latest` on the newest |
64
64
  | Verify-only | the failing gate re-runs green |
65
65
  | Recovery | the trip-wire that surfaced the issue passes |
@@ -75,7 +75,7 @@ Every cut reports, whether it ran inline or via `package-release-agent`:
75
75
  | --- | --- |
76
76
  | Version | X.Y.Z — all roster packages at this version (`check:lockstep`) |
77
77
  | Commit / PR | release commit SHA, PR # (merged) |
78
- | Tags | umbrella `vX.Y.Z` + 16 per-package tags pushed (or: which are still pending, and why) |
78
+ | Tags | umbrella `vX.Y.Z` + 10 per-package tags pushed (or: which are still pending, and why) |
79
79
  | Registry | `npm view @adia-ai/<pkg> version` per package, cited (not "publish workflow green") |
80
80
  | `dist-tags.latest` | confirmed = X.Y.Z |
81
81
  | Deploy | dispatched (`deploy-site.yml` run URL) / N/A this cut |
@@ -96,7 +96,7 @@ assumed pass, or "published" without the actual `npm view` output.
96
96
 
97
97
  `release-pack.mjs` walks the cycle in two phases per invariant 3 — `--mode cut` / `--mode from-scratch` promote `[Unreleased]` (BOTH modes now — a peer's hand-authored section must be promoted whichever mode cut it, and a loud guard blocks the bump if any roster package still carries non-empty `[Unreleased]` content after promotion), run Step 4f (pre-tag coverage `--fix` with the authoritative F-N1 matcher), and stop at the release commit (PR → merge); `--mode handoff` tags/publishes/deploys from post-merge main. **`--go` is the standard invocation for an operator-initiated release** — the single authorization covers the cycle; evidence blocks print as a log; granular `--yes`/`--push`/`--publish` remain for cautious manual runs (`--push` still refuses to auto-fire past any F-N1 finding). `--mode batch` is not implemented — it hard-rejects with a pointer to [`recovery-paths.md`](references/recovery-paths.md) §Scenario 2 rather than silently misbehaving; a real batch tags each version at its own release-merge SHA, which this single-version orchestrator has no model for. Pre-flight (Step 3) runs the full 29-gate roster from the single shared list in `scripts/gate-roster.mjs` — the same list [`cut-procedure.md`](references/cut-procedure.md) §3.1 transcribes, so a subset run requires editing that one file, not two.
98
98
 
99
- The pieces are callable alone: `bump.mjs` (version fields + the factory `.mcp.json` a2ui-mcp pin, invariant 8), `promote-unreleased.mjs` / `insert-stub.mjs` (CHANGELOG blocks), `tag-lockstep.mjs` (umbrella + one tag per lockstep roster package — the set is derived from `PACKAGE_ROSTER`, never a number written here: it went stale at 14 while the roster said 17, 17 went stale in turn when gh#1240 folded two planned MCP rows into one (now 16), and 16 goes stale again the day the ADR-0048 shims retire; run `--dry` to see the live list, `--delete` to move), `dispatch-publish.mjs` (publish workflows; `--verify-triggered` re-dispatches missing AND dead — cancelled/failed/timed-out — runs, each gated behind an npm-registry check so an already-published version is never re-dispatched (gh#763); `--after` enforces batch ordering — dispatch output states what WAS done, never a to-do phrased as if it hadn't fired), and `pr-bridge.mjs` (the two-phase bridge: pushes the release branch, opens the PR, waits out CI, and merges ONLY on all-non-fail-soft-checks-green + zero unresolved threads + no changes-requested; any other state stops with evidence — §5.7 mechanized, `--dry` to preview the decision). All fail fast outside a monorepo root (`assert-monorepo-root.mjs`); fork-configurable via `--host` / `--scope`. All 6 CLI scripts (plus `scripts/release/check-release.mjs`) have a `selftest` mode wired into CI's Plugin bin selftests step; the 3 helper modules (`assert-monorepo-root`, `gate-roster`, `package-paths`) are exercised through the CLIs' selftests, not their own.
99
+ The pieces are callable alone: `bump.mjs` (version fields + the factory `.mcp.json` `@adia-ai/mcp` pin, invariant 8), `promote-unreleased.mjs` / `insert-stub.mjs` (CHANGELOG blocks), `tag-lockstep.mjs` (umbrella + one tag per lockstep roster package — the set is derived from `PACKAGE_ROSTER`, never a number written here: it went stale at 14 while the roster said 17, 17 went stale in turn when gh#1240 folded two planned MCP rows into one (now 16), and 16 goes stale again the day the ADR-0048 shims retire; run `--dry` to see the live list, `--delete` to move), `dispatch-publish.mjs` (publish workflows; `--verify-triggered` re-dispatches missing AND dead — cancelled/failed/timed-out — runs, each gated behind an npm-registry check so an already-published version is never re-dispatched (gh#763); `--after` enforces batch ordering — dispatch output states what WAS done, never a to-do phrased as if it hadn't fired), and `pr-bridge.mjs` (the two-phase bridge: pushes the release branch, opens the PR, waits out CI, and merges ONLY on all-non-fail-soft-checks-green + zero unresolved threads + no changes-requested; any other state stops with evidence — §5.7 mechanized, `--dry` to preview the decision). All fail fast outside a monorepo root (`assert-monorepo-root.mjs`); fork-configurable via `--host` / `--scope`. All 6 CLI scripts (plus `scripts/release/check-release.mjs`) have a `selftest` mode wired into CI's Plugin bin selftests step; the 3 helper modules (`assert-monorepo-root`, `gate-roster`, `package-paths`) are exercised through the CLIs' selftests, not their own.
100
100
 
101
101
  Site deploy (Step 10 of the handoff) dispatches `deploy-site.yml` (its own pre-flight verify → snapshot → hardened rsync → post-deploy verify → auto-rollback), never a raw local `rsync` — H1 (forge-campaign gh#268 audit): the script had drifted into bypassing that pipeline even though this doc already taught the workflow-dispatch path. The dispatch rides the cycle's single authorization (`--go`, or `--publish` on a manual run); the workflow's own GitHub environment gate is the human stop for the deploy itself.
102
102
 
@@ -92,7 +92,7 @@ When only source *hashes* move and chunk content does not, `check:embeddings-fre
92
92
  ```bash
93
93
  node scripts/build/components.mjs --verify # 1 yaml ↔ sidecar ↔ .d.ts
94
94
  npm run verify:traits # 2 trait coverage
95
- npm run check:lockstep # 3 version coherence (+ factory .mcp.json a2ui-mcp pin, invariant 8)
95
+ npm run check:lockstep # 3 version coherence (+ factory .mcp.json @adia-ai/mcp pin, invariant 8)
96
96
  npm run test:unit:serial # 4 vitest, serial — the source of truth (§Cat 8; parallel flakes under load)
97
97
  npm run typecheck # 5 tsc --noEmit
98
98
  npm run check:demo-shells # 6 demo imports cover composes:
@@ -223,7 +223,7 @@ allowlist (never `git add -A`; if peers may have pre-staged files,
223
223
  git -C "$REPO" checkout -b "release/vX.Y.Z"
224
224
  git -C "$REPO" reset HEAD >/dev/null 2>&1
225
225
  git -C "$REPO" add package-lock.json packages/*/package.json packages/*/CHANGELOG.md \
226
- packages/a2ui/*/package.json packages/a2ui/*/CHANGELOG.md \
226
+ packages/gen-ui/a2ui/*/package.json packages/gen-ui/a2ui/*/CHANGELOG.md \
227
227
  packages/genui/adia-catalog/base.json packages/genui/adia-catalog/adia-pack.json \
228
228
  docs/releases/vX.Y.Z.md # + in-scope source + Step-3.0 regen outputs
229
229
  git -C "$REPO" diff --cached --stat | tail -3 # count must match the allowlist
@@ -276,7 +276,7 @@ The operator's initiating instruction covers the whole cycle — no per-step re-
276
276
 
277
277
  | Evidence logged before | Content | Why it's still printed |
278
278
  | --- | --- | --- |
279
- | Tagging (Step 6) | The planned tag list (umbrella + 16 per-package) | The log line a recovery diagnoses from |
279
+ | Tagging (Step 6) | The planned tag list (umbrella + 10 per-package) | The log line a recovery diagnoses from |
280
280
  | Pushing (Step 8) | The Step 7 F-N1 output + tag list + `origin/main..HEAD` count | F-N1's first real evidence — and its ERROR path still hard-stops unconditionally |
281
281
  | Publishing (Step 9) | The current registry snapshot (versions + `dist-tags.latest`) | Ordering is verified against what's LIVE, mechanically |
282
282
  | Deploying (Step 10) | The `deploy-site.yml` dispatch (never a raw rsync) | The workflow carries its own GitHub-environment human gate |
@@ -299,7 +299,7 @@ Log the planned tag list (evidence table above), then tag **at `main`'s post-mer
299
299
 
300
300
  ```bash
301
301
  node "${CLAUDE_PLUGIN_ROOT}/skills/package-release/scripts/tag-lockstep.mjs" \
302
- --version X.Y.Z # umbrella vX.Y.Z + 16 <pkg>-vX.Y.Z (14 npm + 2 plugins)
302
+ --version X.Y.Z # umbrella vX.Y.Z + 10 <pkg>-vX.Y.Z (8 npm + 2 plugins)
303
303
  ```
304
304
 
305
305
  ## §Step 7 — F-N1 release trip-wire
@@ -395,98 +395,13 @@ Any Step-2 stashes: `git stash pop`; flag conflicts to the operator.
395
395
 
396
396
  Always author notes at end-of-cycle without being asked — context is freshest now. Single version → [`notes-authoring.md`](notes-authoring.md); ≥2 versions since the last broadcast → its §Rollup section. Surface the draft inline for copy-paste; the operator owns posting. Skip only on an explicit "no notes".
397
397
 
398
- ## §The 0.8.37 estate-split cut (ADR-0048 P7 — ONE cut, then delete this section)
399
-
400
- Extra steps for the single cut that ships the a2ui/gen-ui split. They ride the
401
- normal procedure above; nothing here replaces a step.
402
-
403
- **It is a PATCH cut, by operator ruling (2026-08-13, gh#1192)** — `0.8.37`, not
404
- the `0.9.0` MINOR the ADR originally proposed. Two consequences to hold in mind
405
- before Step 4:
406
-
407
- - **Invariant 2 (PATCH asymmetry) applies UNCHANGED — no exception.** Internal
408
- `@adia-ai/*` dep ranges stay `^0.8.0` on a patch cut, and that is exactly
409
- right here: `targetCaret("0.8.37")` is `^0.8.0`, the three new names
410
- (`a2ui`, `gen-ui`, `mcp` — retargeted gh#1240, 2026-08-14: this row named
411
- `gen-ui-mcp` before the MCP-distribution fold; that name never published,
412
- `mcp` is its real successor) publish `0.8.37` as their FIRST version, and
413
- `^0.8.0` resolves to it. The shims' deps on their successors are already
414
- `^0.8.0` and need no edit; web-modules' EXACT peer pin moves to `0.8.37` by
415
- the normal peer rule (gh#489), which `bump.mjs` does. So nothing in the split
416
- needs a hand-written range — if `check:lockstep` asks for one, something else
417
- is wrong; do not hand-pin.
418
- - **A patch-shaped number does NOT relax the MIGRATION GUIDE obligation**
419
- (invariant 7). Six published names are being replaced; the guide is owed
420
- regardless of what the version looks like. This is the one failure mode the
421
- small number invites.
422
-
423
- **In the release commit (Step 4/5), not before and not after:**
424
-
425
- 1. **Flip the factory `.mcp.json` pin NAME** — `@adia-ai/a2ui-mcp` →
426
- `@adia-ai/mcp` (retargeted gh#1240, 2026-08-14: this step named
427
- `@adia-ai/gen-ui-mcp` before the MCP-distribution fold folded that planned
428
- name — and `@adia-ai/a2ui-protocol-mcp` — into `@adia-ai/mcp` before either
429
- ever published; the flip target moved, the flip's own timing did not), in
430
- `packages/plugins/adia-ui-factory/.mcp.json` AND its README prose echo
431
- (invariant 8 covers both files; `bump.mjs` moves the VERSION on either
432
- name, so only the name is hand-edited). The pinned args also grow a
433
- subcommand: `["-y", "@adia-ai/mcp@0.8.37", "gen-ui"]` — the fold's bin
434
- dispatches `adia-mcp gen-ui`/`adia-mcp protocol`, not a bare invocation.
435
- **Why here and not at P5:** invariant 8 forces the pin to the CURRENT
436
- lockstep version. Before this cut that is `0.8.36`, and `@adia-ai/mcp`
437
- has no `0.8.36` on npm — flipping early pins every local-marketplace install
438
- to `npx -y @adia-ai/mcp@0.8.36`, i.e. a registry 404. In this commit
439
- the version becomes `0.8.37`, which this cut publishes. (The reasoning is
440
- unchanged by the 0.9.0 → 0.8.37 ruling, and unchanged again by the
441
- gen-ui-mcp → mcp retarget; only the numbers and the name moved.)
442
- `check:lockstep` accepts any name this pin has carried (`MCP_PIN_RE`), so
443
- the flip is gate-clean regardless of which name is live when this runs.
444
-
445
- **Config-KEY standardization rides the same flip (operator ruling
446
- 2026-08-14):** the `mcpServers` key names move with the pin so a tool
447
- call's prefix always names which server answered. Factory `.mcp.json`:
448
- key `a2ui` → `adia-gen-ui`. Repo root `.mcp.json`: key `adia-ui` →
449
- `adia-gen-ui`. New entries added later use `adia-protocol` /
450
- `adia-factory` for the other subcommands. Key renames change consumers'
451
- tool prefixes (`mcp__a2ui__*` → `mcp__adia-gen-ui__*`) — that is the
452
- point, and it ships in the same breaking-named cut as everything else.
453
-
454
- **After Step 9 (publish), once `npm view <old-name> version` shows the shim on
455
- the registry — never before:**
456
-
457
- 2. **Deprecate the six retired names.** The list is projected from the shim
458
- generator's SPEC, so it cannot drift from what actually shipped:
459
-
460
- ```bash
461
- node scripts/build/generate-shims.mjs --deprecate-commands
462
- ```
463
-
464
- It prints the `npm deprecate` lines plus an `npm info <pkg> deprecated`
465
- verify line per package. Print-only by design — read them, then run them.
466
- **Verify by reading the field back**; a zero exit code is not proof.
467
- Deprecating before the shim publishes leaves consumers at a dead end (the
468
- pointer text names a package version that isn't there yet).
469
-
470
- 3. **Verify a shim tarball's CONTENTS, not just the publish exit code** — e.g.
471
- `npm pack @adia-ai/a2ui-runtime@0.8.37 && tar -tzf *.tgz`, then import one
472
- subpath from a scratch dir and confirm it resolves through to
473
- `@adia-ai/a2ui`.
474
-
475
- **Follow-up PR (not this cut):** delete `packages/shims/`, the roster rows
476
- marked `shim: true`, their six `publish-a2ui-*.yml` workflows,
477
- `resolvePackageDir`'s `shims/` fallback, `scripts/build/generate-shims.mjs`,
478
- `scripts/verify/check-shim-bridges.mjs`, the `check:shims` gate, and this
479
- section. Then narrow `MCP_PIN_RE` + `bump.mjs`'s pin pattern back to the single
480
- new name.
481
-
482
- ---
483
-
484
398
  ## §The 0.8.38 cut (the clean-world cut — delete this section after it lands)
485
399
 
486
400
  The first cut AFTER the estate-split bridge. Pre-conditions, all verifiable
487
401
  before Step 1:
488
402
 
489
- 1. **The shim-deletion follow-up PR has MERGED** (the §0.8.37 follow-up above:
403
+ 1. **The shim-deletion follow-up PR has MERGED** (the §0.8.37 follow-up — that
404
+ section deleted itself with the same PR, as designed:
490
405
  `packages/shims/` gone, roster shim rows gone, the six `publish-a2ui-*.yml`
491
406
  workflows gone, `check:shims`/`check-shim-bridges` retired). The roster file
492
407
  is the member count — never transcribe it.
@@ -14,7 +14,7 @@ Row layout per gate: **What** · **Typical failure** · **Recovery**.
14
14
 
15
15
  ### `npm run check:lockstep`
16
16
 
17
- - **What:** all 16 lockstep `@adia-ai/*` packages declare the same `version` (the class-B `adia-plugins` package is excluded — `lockstep: false`, `scripts/package-paths.mjs`); internal `@adia-ai/*` dep ranges match policy (`^X.Y.0` during PATCH cycles, bumped at MINOR).
17
+ - **What:** all 10 lockstep `@adia-ai/*` packages declare the same `version` (the class-B `adia-plugins` package is excluded — `lockstep: false`, `scripts/package-paths.mjs`); internal `@adia-ai/*` dep ranges match policy (`^X.Y.0` during PATCH cycles, bumped at MINOR).
18
18
  - **Typical failure:** one package forgot to bump; a peer edited an internal range mid-PATCH; a `^0.0.x` range slipped in.
19
19
  - **Recovery:** version drift → `` `${CLAUDE_PLUGIN_ROOT}/skills/package-release/scripts/bump.mjs` ``; range drift → `npm run check:lockstep:fix` auto-aligns, then re-run.
20
20
  - **Why `^0.0.x` is forbidden:** npm pre-1.0 semver only widens the caret when major+minor aren't both zero — `^0.0.6` resolves to `>=0.0.6 <0.0.7`, locked to exactly 0.0.6. An internal dep pinned that way silently installs a *stale* sibling on every fresh `npm i` (this shipped a real ~4-day-latent bug before the lockstep policy). The `^X.Y.0` floor (Y≥1) widens correctly across patches; trust the gate, don't reason about caret semantics by hand. Moot at 1.0.0.
@@ -96,8 +96,8 @@ Also: `check:no-self-import-css` (no transitively self-importing barrel) · `che
96
96
 
97
97
  ### `npm run check:browser-safe`
98
98
 
99
- - **What:** no top-level `import 'node:*'` in browser-reachable modules (`packages/a2ui/{compose,retrieval,validator}`, `web-components/`, `web-modules/`, `apps/*/app/*.contents.js`).
100
- - **Recovery:** dual-mode pattern (`IS_NODE` + dynamic `await import(/* @vite-ignore */ 'node:*')` + `import.meta.glob` browser branch); canonical impl: `packages/a2ui/retrieval/component-catalog.js`.
99
+ - **What:** no top-level `import 'node:*'` in browser-reachable modules (`packages/gen-ui/a2ui/{compose,retrieval,validator}`, `web-components/`, `web-modules/`, `apps/*/app/*.contents.js`).
100
+ - **Recovery:** dual-mode pattern (`IS_NODE` + dynamic `await import(/* @vite-ignore */ 'node:*')` + `import.meta.glob` browser branch); canonical impl: `packages/gen-ui/a2ui/retrieval/component-catalog.js`.
101
101
 
102
102
  Siblings: `check:absolute-imports` (no leading-`/` imports — rewrite relative) · `check:template-interp` (template `${expr}` contract) · `check:yaml-events` (yaml `events:` match runtime `dispatchEvent` calls) · `check:yaml-impl-coverage` (every yaml prop implemented in the JS class).
103
103
 
@@ -121,7 +121,7 @@ The two `audit:*` probes are soft-fail pre-cut (exit-1 only on criticals); findi
121
121
 
122
122
  ### `npm run verify:corpus`
123
123
 
124
- - **What:** every chunk in `packages/a2ui/corpus/chunks/*.json` is reachable and well-formed.
124
+ - **What:** every chunk in `packages/gen-ui/a2ui/corpus/chunks/*.json` is reachable and well-formed.
125
125
  - **Recovery:** corpus remediation routes to the A2UI-pipeline skill, not this one.
126
126
 
127
127
  ### `npm run check:chunks-fresh`
@@ -19,7 +19,7 @@
19
19
  | | Class A — lockstep cut | Class B — independent package |
20
20
  | --- | --- | --- |
21
21
  | Versioning | whole set bumps together | own version line per package |
22
- | Lockstep gate | enforced (`check:lockstep` 16/16) | **excluded** — a class-B package is not listed in `check-lockstep.mjs`'s `PACKAGES` (`adia-plugins`, the current member, is filtered out via `lockstep: false` — `scripts/package-paths.mjs`) |
22
+ | Lockstep gate | enforced (`check:lockstep` 10/10) | **excluded** — a class-B package is not listed in `check-lockstep.mjs`'s `PACKAGES` (`adia-plugins`, the current member, is filtered out via `lockstep: false` — `scripts/package-paths.mjs`) |
23
23
  | Umbrella tag | `vX.Y.Z` + per-package | **none** — per-package tags only (versions differ) |
24
24
  | `dist-tag` ordering | cross-package publish order matters | N/A |
25
25
  | Demo-site deploy | yes | **none** |
@@ -47,7 +47,7 @@ Substrate fixes (release scripts / lockfile / CHANGELOG), landed once as a norma
47
47
 
48
48
  ## §Verify target
49
49
 
50
- The published package(s) on the **npm registry** at their independent versions, plus the npm-published `@adia-ai/adia-plugins` manifest referencing the new versions (ADR-0045). NOT "all 16 lockstep packages + the demo site" — that's class A.
50
+ The published package(s) on the **npm registry** at their independent versions, plus the npm-published `@adia-ai/adia-plugins` manifest referencing the new versions (ADR-0045). NOT "all 10 lockstep packages + the demo site" — that's class A.
51
51
 
52
52
  ## §Gotchas (from the first independent cut, factory v0.2.2 + forge v0.1.2)
53
53
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  1. Verify the skip: `npm view <pkg> versions --json | tail` (no X+1 on npm) + `git tag --list 'vX.Y.*'` (no tags). Run pre-flight at the peer's commit to confirm it's shippable.
19
19
  2. Correct the version via a **new commit on top** (not amend — the peer's commit stays for history).
20
- 3. Sweep every occurrence of the wrong version: 16 × package.json, 16 × CHANGELOG (headers + body refs — the lockstep roster, `scripts/package-paths.mjs`), any doc/CSS-comment refs, then regenerate the lockfile. Preserve filename references that intentionally encode the original label.
20
+ 3. Sweep every occurrence of the wrong version: 10 × package.json, 10 × CHANGELOG (headers + body refs — the lockstep roster, `scripts/package-paths.mjs`), any doc/CSS-comment refs, then regenerate the lockfile. Preserve filename references that intentionally encode the original label.
21
21
  4. Commit as `fix(release): correct vX.Y.Z+1 version-skip → vX.Y.Z` documenting the discovery, then resume [`cut-procedure.md`](cut-procedure.md) at Step 5.
22
22
 
23
23
  ## §Scenario 2 — Batch push
@@ -63,7 +63,7 @@
63
63
 
64
64
  ## §Scenario 7 — Tags pushed, ZERO publish workflows fired
65
65
 
66
- **Shape:** all 17 tags exist on origin (umbrella + one per lockstep-roster package — `scripts/package-paths.mjs`), but no `publish-<pkg>.yml` run exists for them; npm latest unchanged; nothing errored.
66
+ **Shape:** all 11 tags exist on origin (umbrella + one per lockstep-roster package — `scripts/package-paths.mjs`), but no `publish-<pkg>.yml` run exists for them; npm latest unchanged; nothing errored.
67
67
 
68
68
  **Root cause:** pushing many tags in **one** `git push` fires a single batched create event that GitHub Actions routinely drops. Re-pushing is a no-op (the tags already exist remotely).
69
69
 
@@ -41,36 +41,34 @@ const SIBLING_MANIFESTS = Object.fromEntries(
41
41
 
42
42
  // Cross-package EXACT pins bumped in the same pass — a different shape from a
43
43
  // package.json "version" field, so SIBLING_MANIFESTS' regex can't reach them.
44
- // The factory plugin's .mcp.json pins @adia-ai/a2ui-mcp to the exact lockstep
44
+ // The factory plugin's .mcp.json pins @adia-ai/mcp to the exact lockstep
45
45
  // version (SKILL invariant 8 — the consumer never floats). bump.mjs left this
46
46
  // untouched through the 0.8.6 + 0.8.7 cuts, forcing a manual edit + amend each
47
47
  // time; check-lockstep's mcp-pin guard now catches a drift, this moves it.
48
48
  //
49
49
  // Each package maps to an ARRAY of pin configs — the factory README's own
50
- // prose echo of the same pin (`server pinned: @adia-ai/a2ui-mcp@X`) is a
50
+ // prose echo of the same pin (`server pinned: @adia-ai/mcp@X`) is a
51
51
  // SECOND file invariant 8 covers, and check:plugin-count-claims' "factory
52
- // README a2ui-mcp pin" EQUALITY check enforces the two agree. Left out of
53
- // this array through the 0.8.35 + 0.8.36 cuts, it needed the same manual
52
+ // README generation-MCP pin" EQUALITY check enforces the two agree. Left out
53
+ // of this array through the 0.8.35 + 0.8.36 cuts, it needed the same manual
54
54
  // hand-commit .mcp.json used to (gh#1198) — same file set, invariant 8's own
55
55
  // scope, so it moves alongside .mcp.json rather than getting its own key.
56
56
  //
57
- // ANY NAME THIS PIN HAS CARRIED (ADR-0048 P5, retargeted gh#1240 2026-08-14):
58
- // the generation MCP is `@adia-ai/mcp` (its `gen-ui` surface) since the
59
- // MCP-distribution fold P2 had planned `@adia-ai/gen-ui-mcp`, which never
60
- // published but the pin keeps naming the old package until the P7 cut
61
- // flips it in the release commit itself (see lockstep-checks.mjs MCP_PIN_RE
62
- // for why an early flip pins consumers to a 404). Matching every name means
63
- // the version bump works before AND after either flip, with no cut-day edit
64
- // to this file.
57
+ // `@adia-ai/mcp` is the single live name since the 0.8.37 estate-split cut
58
+ // flipped the pin in its release commit (ADR-0048 P7). The bridge-window
59
+ // alternation over the retired names (`a2ui-mcp`, the never-published
60
+ // `gen-ui-mcp`) was narrowed back by the shim-deletion follow-up PR, matching
61
+ // lockstep-checks.mjs's MCP_PIN_RE — a retired name in the pin must now fail
62
+ // loudly instead of being bumped along.
65
63
  const A2UI_MCP_PIN = {
66
- label: 'generation-MCP pin (@adia-ai/{a2ui-mcp,gen-ui-mcp,mcp})',
67
- // `@adia-ai/{a2ui-mcp,gen-ui-mcp,mcp}@<from>` (not a prefix of a longer version) → `@<to>`
64
+ label: 'generation-MCP pin (@adia-ai/mcp)',
65
+ // `@adia-ai/mcp@<from>` (not a prefix of a longer version) → `@<to>`
68
66
  // Escape EVERY regex metacharacter in `from`, not just dots: a prerelease or
69
67
  // build-metadata version (`0.9.0-rc+1`) would otherwise inject `+` as a
70
68
  // quantifier and silently match the wrong text. Same class as the truncating
71
69
  // MCP_PIN_RE suffix CodeRabbit found on PR #1229.
72
70
  pattern: (from) =>
73
- new RegExp(`(@adia-ai/(?:(?:a2ui|gen-ui)-mcp|mcp)@)${from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\d.])`),
71
+ new RegExp(`(@adia-ai/mcp@)${from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\d.])`),
74
72
  replace: (to) => `$1${to}`,
75
73
  };
76
74
  const PINNED_REFS = {
@@ -298,38 +296,43 @@ function selftest() {
298
296
  console.error('selftest FAIL: corrupted package.json (no version match) not caught'); process.exit(1);
299
297
  }
300
298
 
301
- // PINNED_REFS — the .mcp.json a2ui-mcp pin (invariant 8) moves in lockstep.
299
+ // PINNED_REFS — the .mcp.json @adia-ai/mcp pin (invariant 8) moves in lockstep.
302
300
  const [pinCfg, readmePinCfg] = PINNED_REFS['packages/plugins/adia-ui-factory'];
303
- const pinBefore = '{"args":["-y","@adia-ai/a2ui-mcp@0.8.6"]}';
301
+ const pinBefore = '{"args":["-y","@adia-ai/mcp@0.8.6","gen-ui"]}';
304
302
  const pinAfter = bumpPinnedRef(pinBefore, pinCfg, '0.8.6', '0.8.7');
305
- if (!pinAfter.includes('@adia-ai/a2ui-mcp@0.8.7') || pinAfter.includes('@0.8.6')) {
306
- console.error('selftest FAIL: PINNED_REFS did not bump the .mcp.json a2ui-mcp pin'); process.exit(1);
303
+ if (!pinAfter.includes('@adia-ai/mcp@0.8.7') || pinAfter.includes('@0.8.6')) {
304
+ console.error('selftest FAIL: PINNED_REFS did not bump the .mcp.json generation-MCP pin'); process.exit(1);
307
305
  }
308
306
  // Must NOT prefix-match a longer version (0.8.6 inside 0.8.60).
309
- if (bumpPinnedRef('@adia-ai/a2ui-mcp@0.8.60', pinCfg, '0.8.6', '0.8.7') !== '@adia-ai/a2ui-mcp@0.8.60') {
307
+ if (bumpPinnedRef('@adia-ai/mcp@0.8.60', pinCfg, '0.8.6', '0.8.7') !== '@adia-ai/mcp@0.8.60') {
310
308
  console.error('selftest FAIL: PINNED_REFS pattern prefix-matched a longer version'); process.exit(1);
311
309
  }
310
+ // A retired bridge name must NOT be bumped along — it should fail the later
311
+ // check-lockstep gate loudly, not be silently kept alive by this pass.
312
+ if (bumpPinnedRef('@adia-ai/a2ui-mcp@0.8.6', pinCfg, '0.8.6', '0.8.7') !== '@adia-ai/a2ui-mcp@0.8.6') {
313
+ console.error('selftest FAIL: pin pattern matched a retired generation-MCP name'); process.exit(1);
314
+ }
312
315
 
313
316
  // gh#1198 — the factory README's OWN prose echo of the same pin
314
- // (`server pinned: @adia-ai/a2ui-mcp@X`) must move alongside .mcp.json;
315
- // check:plugin-count-claims' "factory README a2ui-mcp pin" EQUALITY check
316
- // is what caught this drift on the v0.8.35 + v0.8.36 cuts.
317
+ // (`server pinned: @adia-ai/mcp@X`) must move alongside .mcp.json;
318
+ // check:plugin-count-claims' "factory README generation-MCP pin" EQUALITY
319
+ // check is what caught this drift on the v0.8.35 + v0.8.36 cuts.
317
320
  if (readmePinCfg.file !== 'README.md') {
318
321
  console.error('selftest FAIL: expected the second factory pin config to target README.md'); process.exit(1);
319
322
  }
320
- const readmeBefore = '`a2ui` server pinned: `@adia-ai/a2ui-mcp@0.8.6` (tool SoT: `packages/mcp/TOOLS.md`)';
323
+ const readmeBefore = '`adia-gen-ui` server pinned: `@adia-ai/mcp@0.8.6` (tool SoT: `packages/gen-ui/mcp/TOOLS.md`)';
321
324
  const readmeAfter = bumpPinnedRef(readmeBefore, readmePinCfg, '0.8.6', '0.8.7');
322
- if (!readmeAfter.includes('@adia-ai/a2ui-mcp@0.8.7') || readmeAfter.includes('@0.8.6')) {
323
- console.error('selftest FAIL: PINNED_REFS did not bump the README a2ui-mcp prose pin'); process.exit(1);
325
+ if (!readmeAfter.includes('@adia-ai/mcp@0.8.7') || readmeAfter.includes('@0.8.6')) {
326
+ console.error('selftest FAIL: PINNED_REFS did not bump the README generation-MCP prose pin'); process.exit(1);
324
327
  }
325
- if (bumpPinnedRef('@adia-ai/a2ui-mcp@0.8.60', readmePinCfg, '0.8.6', '0.8.7') !== '@adia-ai/a2ui-mcp@0.8.60') {
328
+ if (bumpPinnedRef('@adia-ai/mcp@0.8.60', readmePinCfg, '0.8.6', '0.8.7') !== '@adia-ai/mcp@0.8.60') {
326
329
  console.error('selftest FAIL: README pin pattern prefix-matched a longer version'); process.exit(1);
327
330
  }
328
331
 
329
332
  // web-modules exact peer pins (gh#489) — all three move in one pass; a
330
333
  // longer version must not prefix-match.
331
334
  const [peerCfg] = PINNED_REFS['packages/web-modules'];
332
- const peersBefore = '{"peerDependencies":{"@adia-ai/web-components": "0.8.22","@adia-ai/a2ui-runtime": "0.8.22","@adia-ai/llm": "0.8.22"}}';
335
+ const peersBefore = '{"peerDependencies":{"@adia-ai/web-components": "0.8.22","@adia-ai/a2ui": "0.8.22","@adia-ai/llm": "0.8.22"}}';
333
336
  const peersAfter = bumpPinnedRef(peersBefore, peerCfg, '0.8.22', '0.8.23');
334
337
  if ((peersAfter.match(/0\.8\.23/g) || []).length !== 3 || peersAfter.includes('0.8.22')) {
335
338
  console.error('selftest FAIL: web-modules peer pins did not all move'); process.exit(1);
@@ -144,7 +144,7 @@ function main() {
144
144
  function selftest() {
145
145
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'insert-stub-selftest-'));
146
146
  try {
147
- const dir = path.join(tmp, 'packages', 'llm');
147
+ const dir = path.join(tmp, 'packages', 'llm', 'core');
148
148
  fs.mkdirSync(dir, { recursive: true });
149
149
  const clPath = path.join(dir, 'CHANGELOG.md');
150
150
  const anchor = '## [0.1.0] — 2026-01-01';