@adia-ai/adia-ui-forge 0.8.36 → 0.8.38

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 (126) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +53 -18
  3. package/README.md +17 -17
  4. package/agents/{a2ui-builder.corpus.json → a2ui-maintenance-agent.corpus.json} +1 -1
  5. package/agents/{a2ui-builder.md → a2ui-maintenance-agent.md} +6 -6
  6. package/agents/framework-reviewer.md +6 -6
  7. package/agents/{release-builder.corpus.json → package-release-agent.corpus.json} +3 -3
  8. package/agents/{release-builder.md → package-release-agent.md} +7 -7
  9. package/agents/{component-author.corpus.json → primitive-authoring-agent.corpus.json} +2 -2
  10. package/agents/{component-author.md → primitive-authoring-agent.md} +7 -7
  11. package/agents/routing-corpus.json +40 -40
  12. package/commands/{dogfood.md → demo-audit.md} +2 -1
  13. package/commands/{gen-review.md → gen-ui-review.md} +3 -2
  14. package/commands/{release.md → package-release.md} +3 -2
  15. package/commands/{deploy.md → site-deployment.md} +2 -1
  16. package/package.json +1 -1
  17. package/references/contracts/a2ui-mcp-surface.md +16 -8
  18. package/references/contracts/migration-guide-format.md +4 -4
  19. package/scripts/demo-postwrite-pattern-gate +2 -2
  20. package/scripts/release-pretag-docs-gate +2 -2
  21. package/scripts/sidecar-prewrite-guard +3 -3
  22. package/skills/{adia-a2ui → a2ui-maintenance}/SKILL.md +10 -9
  23. package/skills/{adia-a2ui → a2ui-maintenance}/evals/evals.json +8 -8
  24. package/skills/{adia-a2ui → a2ui-maintenance}/evals/routing-corpus.json +51 -51
  25. package/skills/{adia-a2ui → a2ui-maintenance}/references/anti-patterns.md +2 -2
  26. package/skills/{adia-a2ui → a2ui-maintenance}/references/chunk-authoring.md +2 -2
  27. package/skills/{adia-a2ui → a2ui-maintenance}/references/eval-diagnostics.md +3 -3
  28. package/skills/{adia-a2ui → a2ui-maintenance}/references/format-extension-decisions.md +2 -2
  29. package/skills/{adia-a2ui → a2ui-maintenance}/references/mcp-pipeline-ops.md +5 -5
  30. package/skills/{adia-a2ui → a2ui-maintenance}/references/mcp-tool-reference.md +5 -4
  31. package/skills/{adia-a2ui → a2ui-maintenance}/references/pipeline-overview.md +18 -18
  32. package/skills/{adia-a2ui → a2ui-maintenance}/references/semantic-fail-lifting.md +2 -2
  33. package/skills/{adia-a2ui → a2ui-maintenance}/references/strategy-engines.md +2 -2
  34. package/skills/{adia-a2ui → a2ui-maintenance}/references/zettel-calibration.md +2 -2
  35. package/skills/{adia-dogfood → demo-audit}/SKILL.md +8 -8
  36. package/skills/{adia-dogfood → demo-audit}/evals/evals.json +7 -7
  37. package/skills/{adia-dogfood → demo-audit}/evals/routing-corpus.json +43 -43
  38. package/skills/{adia-dogfood → demo-audit}/references/visual-probe-triage.md +1 -1
  39. package/skills/{adia-dogfood → demo-audit}/scripts/analyze.mjs +2 -2
  40. package/skills/{adia-gen-review → gen-ui-review}/SKILL.md +13 -13
  41. package/skills/{adia-gen-review → gen-ui-review}/evals/evals.json +7 -7
  42. package/skills/{adia-gen-review → gen-ui-review}/evals/routing-corpus.json +43 -43
  43. package/skills/{adia-gen-review → gen-ui-review}/references/corpus-html-patterns.md +4 -4
  44. package/skills/{adia-gen-review → gen-ui-review}/references/loop-protocol.md +11 -11
  45. package/skills/{adia-gen-review → gen-ui-review}/references/scores.schema.json +1 -1
  46. package/skills/{adia-gen-review → gen-ui-review}/scripts/gen-review-coverage-audit.mjs +4 -4
  47. package/skills/{adia-gen-review → gen-ui-review}/scripts/gen-review-decompose.mjs +6 -6
  48. package/skills/{adia-gen-review → gen-ui-review}/scripts/gen-review-status.mjs +5 -5
  49. package/skills/{adia-gen-review → gen-ui-review}/scripts/validate-cycle-scores.mjs +5 -5
  50. package/skills/{adia-llm-internals → llm-client-maintenance}/SKILL.md +7 -7
  51. package/skills/{adia-llm-internals → llm-client-maintenance}/evals/evals.json +7 -7
  52. package/skills/{adia-llm-internals → llm-client-maintenance}/evals/routing-corpus.json +49 -49
  53. package/skills/{adia-llm-internals → llm-client-maintenance}/references/adapter-contract.md +3 -3
  54. package/skills/{adia-llm-internals → llm-client-maintenance}/references/add-a-provider.md +5 -5
  55. package/skills/{adia-llm-internals → llm-client-maintenance}/references/bridge-facade.md +2 -2
  56. package/skills/{adia-llm-internals → llm-client-maintenance}/references/browser-proxy-boundary.md +2 -2
  57. package/skills/{adia-llm-internals → llm-client-maintenance}/references/model-registry.md +2 -2
  58. package/skills/{adia-llm-internals → llm-client-maintenance}/references/streaming-sse.md +2 -2
  59. package/skills/{adia-release → package-release}/SKILL.md +16 -16
  60. package/skills/{adia-release → package-release}/evals/evals.json +7 -7
  61. package/skills/{adia-release → package-release}/evals/routing-corpus.json +45 -45
  62. package/skills/{adia-release → package-release}/references/changelog-discipline.md +4 -4
  63. package/skills/{adia-release → package-release}/references/cut-procedure.md +84 -30
  64. package/skills/{adia-release → package-release}/references/gates-catalog.md +7 -6
  65. package/skills/{adia-release → package-release}/references/independent-package-release.md +2 -2
  66. package/skills/{adia-release → package-release}/references/migration-guide-authoring.md +12 -3
  67. package/skills/{adia-release → package-release}/references/recovery-paths.md +5 -5
  68. package/skills/{adia-release → package-release}/scripts/bump.mjs +87 -37
  69. package/skills/{adia-release → package-release}/scripts/dispatch-publish.mjs +1 -1
  70. package/skills/{adia-release → package-release}/scripts/gate-roster.mjs +17 -6
  71. package/skills/{adia-release → package-release}/scripts/insert-stub.mjs +30 -8
  72. package/skills/{adia-release → package-release}/scripts/package-paths.mjs +47 -18
  73. package/skills/{adia-release → package-release}/scripts/pr-bridge.mjs +1 -1
  74. package/skills/{adia-release → package-release}/scripts/promote-unreleased.mjs +1 -1
  75. package/skills/{adia-release → package-release}/scripts/release-pack.mjs +29 -8
  76. package/skills/{adia-release → package-release}/scripts/tag-lockstep.mjs +2 -2
  77. package/skills/{adia-author → primitive-authoring}/SKILL.md +7 -7
  78. package/skills/{adia-author → primitive-authoring}/evals/evals.json +7 -7
  79. package/skills/{adia-author → primitive-authoring}/evals/routing-corpus.json +61 -61
  80. package/skills/{adia-author → primitive-authoring}/references/INDEX.md +2 -2
  81. package/skills/{adia-author → primitive-authoring}/references/authoring-cycle.md +1 -1
  82. package/skills/{adia-author → primitive-authoring}/references/code-style.md +5 -5
  83. package/skills/{adia-author → primitive-authoring}/references/common-gotchas.md +1 -1
  84. package/skills/{adia-author → primitive-authoring}/references/llm-bridge.md +17 -17
  85. package/skills/{adia-author → primitive-authoring}/references/module-promotion.md +5 -5
  86. package/skills/{adia-author → primitive-authoring}/references/shell-patterns.md +2 -2
  87. package/skills/{adia-author → primitive-authoring}/references/trait-pages.md +1 -1
  88. package/skills/{adia-author → primitive-authoring}/scripts/build-canonical-pattern-index.mjs +1 -1
  89. package/skills/{adia-deploy → site-deployment}/SKILL.md +6 -6
  90. package/skills/{adia-deploy → site-deployment}/evals/evals.json +8 -8
  91. package/skills/{adia-deploy → site-deployment}/evals/routing-corpus.json +49 -49
  92. package/skills/{adia-deploy → site-deployment}/references/deploy-playbooks.md +10 -10
  93. package/skills/{adia-site-docs → site-docs-authoring}/SKILL.md +4 -4
  94. package/skills/{adia-site-docs → site-docs-authoring}/evals/evals.json +7 -7
  95. package/skills/{adia-site-docs → site-docs-authoring}/evals/routing-corpus.json +51 -51
  96. package/skills/{adia-site-docs → site-docs-authoring}/intent.md +8 -8
  97. package/skills/{adia-ssr → ssr-compatibility}/SKILL.md +8 -8
  98. package/skills/{adia-ssr → ssr-compatibility}/evals/evals.json +7 -7
  99. package/skills/{adia-ssr → ssr-compatibility}/evals/routing-corpus.json +43 -43
  100. package/skills/{adia-ssr → ssr-compatibility}/references/failure-shapes.md +1 -1
  101. package/skills/{adia-ssr → ssr-compatibility}/references/guard-patterns.md +1 -1
  102. /package/skills/{adia-a2ui → a2ui-maintenance}/references/corpus-discipline.md +0 -0
  103. /package/skills/{adia-a2ui → a2ui-maintenance}/references/leverage-rules.md +0 -0
  104. /package/skills/{adia-dogfood → demo-audit}/references/admin-shell-anatomy.md +0 -0
  105. /package/skills/{adia-dogfood → demo-audit}/references/app-shell-pitfalls.md +0 -0
  106. /package/skills/{adia-dogfood → demo-audit}/references/card-anatomy-sweep.md +0 -0
  107. /package/skills/{adia-dogfood → demo-audit}/references/html-attr-sweep.md +0 -0
  108. /package/skills/{adia-dogfood → demo-audit}/references/native-leak-annotations.md +0 -0
  109. /package/skills/{adia-gen-review → gen-ui-review}/references/rubric-cosmetic.md +0 -0
  110. /package/skills/{adia-gen-review → gen-ui-review}/references/rubric-decompose.md +0 -0
  111. /package/skills/{adia-gen-review → gen-ui-review}/references/rubric-score.md +0 -0
  112. /package/skills/{adia-release → package-release}/references/notes-authoring.md +0 -0
  113. /package/skills/{adia-release → package-release}/scripts/assert-monorepo-root.mjs +0 -0
  114. /package/skills/{adia-author → primitive-authoring}/references/anti-patterns.md +0 -0
  115. /package/skills/{adia-author → primitive-authoring}/references/api-contract.md +0 -0
  116. /package/skills/{adia-author → primitive-authoring}/references/canonical-pattern-index.md +0 -0
  117. /package/skills/{adia-author → primitive-authoring}/references/composite-demo-protocol.md +0 -0
  118. /package/skills/{adia-author → primitive-authoring}/references/css-patterns.md +0 -0
  119. /package/skills/{adia-author → primitive-authoring}/references/lifecycle-patterns.md +0 -0
  120. /package/skills/{adia-author → primitive-authoring}/references/primitive-audit.md +0 -0
  121. /package/skills/{adia-author → primitive-authoring}/references/token-contract.md +0 -0
  122. /package/skills/{adia-author → primitive-authoring}/references/worked-example.md +0 -0
  123. /package/skills/{adia-author → primitive-authoring}/references/yaml-contract.md +0 -0
  124. /package/skills/{adia-ssr → ssr-compatibility}/references/consumer-workarounds.md +0 -0
  125. /package/skills/{adia-ssr → ssr-compatibility}/references/status-ledger.md +0 -0
  126. /package/skills/{adia-ssr → ssr-compatibility}/references/test-without-linkedom.md +0 -0
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
- // bump.mjs — bump the 11 lockstep @adia-ai/* package.json from --from to --to.
2
+ // bump.mjs — bump every lockstep @adia-ai/* package.json from --from to --to.
3
+ // The set is PACKAGE_ROSTER (package-paths.mjs) filtered to `lockstep !== false`,
4
+ // never a count written here — that number went stale twice.
3
5
  //
4
6
  // Idempotent. Stops on the first mismatch (a package not at --from) so
5
7
  // you can investigate before any mutation lands.
@@ -8,11 +10,11 @@
8
10
  // node bump.mjs --from 0.6.20 --to 0.6.21
9
11
  // node bump.mjs --from 0.6.20 --to 0.6.21 --dry
10
12
  //
11
- // Part of the adia-release skill. Replaces the /tmp/vXXX-prep.mjs
13
+ // Part of the package-release skill. Replaces the /tmp/vXXX-prep.mjs
12
14
  // improvisation pattern from the v0.6.13 → v0.6.21 cycles.
13
15
  //
14
16
  // Exits:
15
- // 0 — all 11 bumped successfully (or --dry succeeded)
17
+ // 0 — every lockstep package bumped successfully (or --dry succeeded)
16
18
  // 1 — at least one package not at --from (no mutation)
17
19
  // 2 — bad args / file I/O error
18
20
  // 3 — partial mutation (shouldn't happen if --from validation passes)
@@ -39,30 +41,53 @@ const SIBLING_MANIFESTS = Object.fromEntries(
39
41
 
40
42
  // Cross-package EXACT pins bumped in the same pass — a different shape from a
41
43
  // package.json "version" field, so SIBLING_MANIFESTS' regex can't reach them.
42
- // 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
43
45
  // version (SKILL invariant 8 — the consumer never floats). bump.mjs left this
44
46
  // untouched through the 0.8.6 + 0.8.7 cuts, forcing a manual edit + amend each
45
47
  // time; check-lockstep's mcp-pin guard now catches a drift, this moves it.
48
+ //
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/mcp@X`) is a
51
+ // SECOND file invariant 8 covers, and check:plugin-count-claims' "factory
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
+ // hand-commit .mcp.json used to (gh#1198) — same file set, invariant 8's own
55
+ // scope, so it moves alongside .mcp.json rather than getting its own key.
56
+ //
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.
63
+ const A2UI_MCP_PIN = {
64
+ label: 'generation-MCP pin (@adia-ai/mcp)',
65
+ // `@adia-ai/mcp@<from>` (not a prefix of a longer version) → `@<to>`
66
+ // Escape EVERY regex metacharacter in `from`, not just dots: a prerelease or
67
+ // build-metadata version (`0.9.0-rc+1`) would otherwise inject `+` as a
68
+ // quantifier and silently match the wrong text. Same class as the truncating
69
+ // MCP_PIN_RE suffix CodeRabbit found on PR #1229.
70
+ pattern: (from) =>
71
+ new RegExp(`(@adia-ai/mcp@)${from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\d.])`),
72
+ replace: (to) => `$1${to}`,
73
+ };
46
74
  const PINNED_REFS = {
47
- 'packages/plugins/adia-ui-factory': {
48
- file: '.mcp.json',
49
- label: '@adia-ai/a2ui-mcp pin',
50
- // `@adia-ai/a2ui-mcp@<from>` (not a prefix of a longer version) → `@<to>`
51
- pattern: (from) => new RegExp(`(@adia-ai/a2ui-mcp@)${from.replace(/\./g, '\\.')}(?![\\d.])`),
52
- replace: (to) => `$1${to}`,
53
- },
75
+ 'packages/plugins/adia-ui-factory': [
76
+ { ...A2UI_MCP_PIN, file: '.mcp.json' },
77
+ { ...A2UI_MCP_PIN, file: 'README.md', label: 'generation-MCP pin (README prose)' },
78
+ ],
54
79
  // web-modules' internal peers pin the EXACT lockstep version (gh#489 —
55
80
  // a caret peer never moves on a lockstep bump; adia-v2 sat on llm 0.8.19
56
81
  // under web-modules 0.8.22). Same file bumpAll already rewrote for
57
82
  // "version", so this pass re-reads it from disk before matching. The
58
83
  // check:lockstep peer-exact-mismatch guard catches a pin left behind.
59
- 'packages/web-modules': {
84
+ 'packages/web-modules': [{
60
85
  file: 'package.json',
61
86
  label: '@adia-ai/* exact peer pins',
62
87
  pattern: (from) =>
63
88
  new RegExp(`("@adia-ai/[a-z0-9-]+":\\s*")${from.replace(/\./g, '\\.')}(?![\\d.])`, 'g'),
64
89
  replace: (to) => `$1${to}`,
65
- },
90
+ }],
66
91
  };
67
92
 
68
93
  // Repo-level version references (path relative to REPO ROOT, not a package) —
@@ -131,13 +156,15 @@ function loadPackageJsons(repo) {
131
156
  // half-bumped tree whose re-run then failed validateAllAtFrom.)
132
157
  function loadPinnedRefs(repo) {
133
158
  const out = [];
134
- for (const [pkg, cfg] of Object.entries(PINNED_REFS)) {
135
- const p = path.join(repo, pkg, cfg.file);
136
- if (!fs.existsSync(p)) {
137
- console.error(`error: missing ${p}`);
138
- process.exit(2);
159
+ for (const [pkg, cfgs] of Object.entries(PINNED_REFS)) {
160
+ for (const cfg of cfgs) {
161
+ const p = path.join(repo, pkg, cfg.file);
162
+ if (!fs.existsSync(p)) {
163
+ console.error(`error: missing ${p}`);
164
+ process.exit(2);
165
+ }
166
+ out.push({ pkg, cfg, path: p, txt: fs.readFileSync(p, 'utf8') });
139
167
  }
140
- out.push({ pkg, cfg, path: p, txt: fs.readFileSync(p, 'utf8') });
141
168
  }
142
169
  for (const cfg of REPO_PINNED_REFS) {
143
170
  const p = path.join(repo, cfg.file);
@@ -206,17 +233,19 @@ function bumpAll(packages, from, to, dry) {
206
233
  if (!dry) fs.writeFileSync(sibPath, sibOut);
207
234
  console.log(` ${dry ? '[dry] ' : ''}bumped ${p.pkg}/${sibling}: ${from} → ${to}`);
208
235
  }
209
- const pin = PINNED_REFS[p.pkg];
210
- if (pin) {
211
- const pinPath = path.join(path.dirname(p.path), pin.file);
212
- const pinTxt = fs.readFileSync(pinPath, 'utf8');
213
- const pinOut = bumpPinnedRef(pinTxt, pin, from, to);
214
- if (pinOut === pinTxt) {
215
- console.error(`error: ${p.pkg}/${pin.file} — ${pin.label} '@${from}' not found (invariant 8 drift? set the pin to @${from} and re-run, or use \`npm run check:lockstep:fix\`)`);
216
- return -1;
236
+ const pins = PINNED_REFS[p.pkg];
237
+ if (pins) {
238
+ for (const pin of pins) {
239
+ const pinPath = path.join(path.dirname(p.path), pin.file);
240
+ const pinTxt = fs.readFileSync(pinPath, 'utf8');
241
+ const pinOut = bumpPinnedRef(pinTxt, pin, from, to);
242
+ if (pinOut === pinTxt) {
243
+ console.error(`error: ${p.pkg}/${pin.file} — ${pin.label} '@${from}' not found (invariant 8 drift? set the pin to @${from} and re-run, or use \`npm run check:lockstep:fix\`)`);
244
+ return -1;
245
+ }
246
+ if (!dry) fs.writeFileSync(pinPath, pinOut);
247
+ console.log(` ${dry ? '[dry] ' : ''}bumped ${p.pkg}/${pin.file} ${pin.label}: @${from} → @${to}`);
217
248
  }
218
- if (!dry) fs.writeFileSync(pinPath, pinOut);
219
- console.log(` ${dry ? '[dry] ' : ''}bumped ${p.pkg}/${pin.file} ${pin.label}: @${from} → @${to}`);
220
249
  }
221
250
  }
222
251
  return bumped;
@@ -267,22 +296,43 @@ function selftest() {
267
296
  console.error('selftest FAIL: corrupted package.json (no version match) not caught'); process.exit(1);
268
297
  }
269
298
 
270
- // PINNED_REFS — the .mcp.json a2ui-mcp pin (invariant 8) moves in lockstep.
271
- const pinCfg = PINNED_REFS['packages/plugins/adia-ui-factory'];
272
- const pinBefore = '{"args":["-y","@adia-ai/a2ui-mcp@0.8.6"]}';
299
+ // PINNED_REFS — the .mcp.json @adia-ai/mcp pin (invariant 8) moves in lockstep.
300
+ const [pinCfg, readmePinCfg] = PINNED_REFS['packages/plugins/adia-ui-factory'];
301
+ const pinBefore = '{"args":["-y","@adia-ai/mcp@0.8.6","gen-ui"]}';
273
302
  const pinAfter = bumpPinnedRef(pinBefore, pinCfg, '0.8.6', '0.8.7');
274
- if (!pinAfter.includes('@adia-ai/a2ui-mcp@0.8.7') || pinAfter.includes('@0.8.6')) {
275
- 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);
276
305
  }
277
306
  // Must NOT prefix-match a longer version (0.8.6 inside 0.8.60).
278
- 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') {
279
308
  console.error('selftest FAIL: PINNED_REFS pattern prefix-matched a longer version'); process.exit(1);
280
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
+ }
315
+
316
+ // gh#1198 — the factory README's OWN prose echo of the same pin
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.
320
+ if (readmePinCfg.file !== 'README.md') {
321
+ console.error('selftest FAIL: expected the second factory pin config to target README.md'); process.exit(1);
322
+ }
323
+ const readmeBefore = '`adia-gen-ui` server pinned: `@adia-ai/mcp@0.8.6` (tool SoT: `packages/gen-ui/mcp/TOOLS.md`)';
324
+ const readmeAfter = bumpPinnedRef(readmeBefore, readmePinCfg, '0.8.6', '0.8.7');
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);
327
+ }
328
+ if (bumpPinnedRef('@adia-ai/mcp@0.8.60', readmePinCfg, '0.8.6', '0.8.7') !== '@adia-ai/mcp@0.8.60') {
329
+ console.error('selftest FAIL: README pin pattern prefix-matched a longer version'); process.exit(1);
330
+ }
281
331
 
282
332
  // web-modules exact peer pins (gh#489) — all three move in one pass; a
283
333
  // longer version must not prefix-match.
284
- const peerCfg = PINNED_REFS['packages/web-modules'];
285
- const peersBefore = '{"peerDependencies":{"@adia-ai/web-components": "0.8.22","@adia-ai/a2ui-runtime": "0.8.22","@adia-ai/llm": "0.8.22"}}';
334
+ const [peerCfg] = PINNED_REFS['packages/web-modules'];
335
+ const peersBefore = '{"peerDependencies":{"@adia-ai/web-components": "0.8.22","@adia-ai/a2ui": "0.8.22","@adia-ai/llm": "0.8.22"}}';
286
336
  const peersAfter = bumpPinnedRef(peersBefore, peerCfg, '0.8.22', '0.8.23');
287
337
  if ((peersAfter.match(/0\.8\.23/g) || []).length !== 3 || peersAfter.includes('0.8.22')) {
288
338
  console.error('selftest FAIL: web-modules peer pins did not all move'); process.exit(1);
@@ -14,7 +14,7 @@
14
14
  // # Dry mode:
15
15
  // node dispatch-publish.mjs --version 0.6.22 --dry
16
16
  //
17
- // Part of the adia-release skill. Mechanizes the dispatch loop
17
+ // Part of the package-release skill. Mechanizes the dispatch loop
18
18
  // + handles the npm-latest ordering rule for batch pushes.
19
19
 
20
20
  import { execFileSync } from 'node:child_process';
@@ -45,11 +45,11 @@ export const GATE_ROSTER = [
45
45
  // cut. examples-md + site-a2ui are the two generators an `.examples.html`
46
46
  // edit invalidates (the v0.8.14 cut lost a CI round-trip to exactly that);
47
47
  // contrast is the AA gate that gh#427 widened from 42 to 90 pairs;
48
- // token-semantics-sync keeps the adia-tokens pack's generated half honest.
48
+ // token-semantics-sync keeps the token-selection pack's generated half honest.
49
49
  { n: 18, cmd: 'npm run check:examples-md-fresh', what: '.examples.md vs .examples.html' },
50
50
  { n: 19, cmd: 'npm run verify:site-a2ui', what: 'site-a2ui converted rows vs source fragments' },
51
51
  { n: 20, cmd: 'npm run verify:contrast', what: 'WCAG AA — canvas-text + text-on-fill pairs' },
52
- { n: 21, cmd: 'npm run check:token-semantics-sync', what: 'adia-tokens generated references vs token sources' },
52
+ { n: 21, cmd: 'npm run check:token-semantics-sync', what: 'token-selection generated references vs token sources' },
53
53
  // Operator directive 2026-07-27: demo surfaces must be discoverable —
54
54
  // components/modules with .examples.html need a /site/components route,
55
55
  // catalog patterns need their Pattern Library sitemap entry.
@@ -73,12 +73,12 @@ export const GATE_ROSTER = [
73
73
  { n: 25, cmd: 'python3 packages/plugins/adia-ui-factory/scripts/adia-scaffold selftest', what: 'scaffold specifiers resolve in packed tarballs' },
74
74
  // gh#1137 (factory-dx-ws6-measurement SPEC, REQ-05) — FLAGGED FOR
75
75
  // CONFIRMATION: this entry was authored by the WS-6 build without a live
76
- // adia-release sign-off (no operator was available mid-build to confirm
76
+ // package-release sign-off (no operator was available mid-build to confirm
77
77
  // the exact freshness window / regression semantics). Asserts a
78
78
  // qa/dx/sweeps/ record exists dated within this cut's window AND its
79
79
  // verdict is not a regression-RED (a plain floors<=1 baseline RED does
80
80
  // NOT block a cut — only a floor that DROPPED since the prior sweep
81
- // does). CONFIRMED by adia-release on the first live cut (v0.8.35,
81
+ // does). CONFIRMED by package-release on the first live cut (v0.8.35,
82
82
  // 2026-08-13): semantics hold, with one correction — the previous-cut
83
83
  // comparison excludes the in-flight target version (self-reference fired
84
84
  // on the handoff re-run, since the promoted heading was already on main).
@@ -93,14 +93,25 @@ export const GATE_ROSTER = [
93
93
  // concern this is not) — hence `targetVersionArg` rather than
94
94
  // `versionArg`, a distinct flag release-pack.mjs's step3PreFlight reads.
95
95
  { n: 28, cmd: 'node scripts/release/write-eval-health.mjs', what: 'evals/health/<version>.json committed, AC-01/AC-02 run for real', targetVersionArg: true },
96
+ // ADR-0048 (gh#1192) estate-split latch. Between P1 (mint @adia-ai/gen-ui)
97
+ // and P5 (shims + roster) the tree is correct in-repo but deliberately
98
+ // NOT publishable: the old package dirs are `private: true` stubs the
99
+ // roster still points at, and a2ui-mcp depends on @adia-ai/gen-ui, which
100
+ // is not on npm until P7. Prose in this doc does not stop a 2am cut; this
101
+ // gate does. It is a tree property (private / unrostered dep edges), not a
102
+ // phase number, so it clears itself when P5 lands — and then stays as a
103
+ // permanent no-cost invariant against any future private-dep edge.
104
+ // Appended rather than inserted: gate numbers are cited as identities in
105
+ // shipped release notes, so renumbering would falsify them.
106
+ { n: 29, cmd: 'node scripts/release/check-estate-split-latch.mjs', what: 'no lockstep cut mid estate-split (ADR-0048)' },
96
107
  ];
97
108
 
98
109
  // -- CLI ------------------------------------------------------------------
99
110
  // Only runs when invoked directly (not when imported by release-pack.mjs).
100
111
  // realpathSync BOTH sides (CodeRabbit, PR #289): a naive string/URL compare
101
112
  // breaks under a symlinked invocation — this skill is normally reached
102
- // through `.claude/skills/adia-release` -> `packages/plugins/adia-ui-forge/
103
- // skills/adia-release`, and Node resolves `import.meta.url` through that
113
+ // through `.claude/skills/package-release` -> `packages/plugins/adia-ui-forge/
114
+ // skills/package-release`, and Node resolves `import.meta.url` through that
104
115
  // symlink to the real file while `process.argv[1]` keeps the as-invoked
105
116
  // path, so an unresolved compare never matches even when this IS the entry
106
117
  // point. Verified directly (see embeddings-chunks.mjs's identical guard).
@@ -9,9 +9,9 @@
9
9
  // --substantive "<one-line summary>" \
10
10
  // --xref "packages/web-modules/CHANGELOG.md#0622--2026-05-22" \
11
11
  // --previous-version 0.6.21 \
12
- // --packages llm,a2ui/compose,a2ui/mcp,a2ui/retrieval,a2ui/runtime,a2ui/validator
12
+ // --packages llm,a2ui-compose,a2ui-mcp,a2ui-retrieval,a2ui-runtime,a2ui-validator
13
13
  //
14
- // Part of the adia-release skill. Replaces the inline stub-
14
+ // Part of the package-release skill. Replaces the inline stub-
15
15
  // insertion pattern used across v0.6.18 / v0.6.19 / v0.6.20 / v0.6.21
16
16
  // cycles.
17
17
 
@@ -82,8 +82,20 @@ function insertStub(repo, pkg, anchor, stubBlock, version, dry) {
82
82
  }
83
83
  const txt = fs.readFileSync(p, 'utf8');
84
84
  if (txt.includes(`## [${version}]`)) {
85
- console.error(` ERROR ${pkg} already has [${version}] heading`);
86
- return 'already-present';
85
+ // TRUE idempotency across partial runs (the gh#976 lesson, learned
86
+ // here on the v0.8.36 cut's r4): an earlier aborted run already
87
+ // inserted this stub — that's the DONE state, not an error. The
88
+ // BOTH-headings danger promote-unreleased guards (real [Unreleased]
89
+ // content that would miss the release) applies here too: a stub
90
+ // package whose [Unreleased] still carries content means it was
91
+ // wrongly classified as a stub — loud stop.
92
+ const un = txt.match(/^## \[Unreleased\][^\n]*\n([\s\S]*?)(?=^## \[|(?![\s\S]))/m);
93
+ if (un && un[1].trim().length > 0) {
94
+ console.error(` ERROR ${pkg} — has [${version}] heading AND non-empty [Unreleased] content: this package is substantive, not a stub — move it to --substantive-packages`);
95
+ return 'already-present';
96
+ }
97
+ console.log(` ok ${pkg} — stub already present (idempotent skip)`);
98
+ return 'inserted';
87
99
  }
88
100
  if (!txt.includes(anchor)) {
89
101
  console.error(` ERROR ${pkg} — anchor '${anchor}' not found`);
@@ -132,7 +144,7 @@ function main() {
132
144
  function selftest() {
133
145
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'insert-stub-selftest-'));
134
146
  try {
135
- const dir = path.join(tmp, 'packages', 'llm');
147
+ const dir = path.join(tmp, 'packages', 'llm', 'core');
136
148
  fs.mkdirSync(dir, { recursive: true });
137
149
  const clPath = path.join(dir, 'CHANGELOG.md');
138
150
  const anchor = '## [0.1.0] — 2026-01-01';
@@ -147,10 +159,20 @@ function selftest() {
147
159
  console.error('selftest FAIL: stub must land ABOVE the previous-version anchor, not below'); process.exit(1);
148
160
  }
149
161
 
150
- // Idempotency: re-inserting against an already-stubbed target must fail
151
- // loudly, not create a duplicate [0.2.0] block.
162
+ // TRUE idempotency across partial runs (gh#976 lesson, v0.8.36 r4): a
163
+ // re-run against an already-stubbed target is the DONE state — ok skip,
164
+ // file untouched, never a duplicate block.
165
+ const beforeRerun = fs.readFileSync(clPath, 'utf8');
152
166
  const r2 = insertStub(tmp, 'llm', anchor, stub, '0.2.0', false);
153
- if (r2 !== 'already-present') { console.error(`selftest FAIL: expected 'already-present' on re-run, got '${r2}'`); process.exit(1); }
167
+ if (r2 !== 'inserted') { console.error(`selftest FAIL: expected idempotent 'inserted' on re-run, got '${r2}'`); process.exit(1); }
168
+ if (fs.readFileSync(clPath, 'utf8') !== beforeRerun) { console.error('selftest FAIL: idempotent re-run must not modify the file'); process.exit(1); }
169
+ if ((fs.readFileSync(clPath, 'utf8').match(/## \[0\.2\.0\]/g) || []).length !== 1) { console.error('selftest FAIL: duplicate stub block'); process.exit(1); }
170
+
171
+ // The one loud stop left: stub heading present BUT non-empty [Unreleased]
172
+ // — a substantive package misclassified as a stub.
173
+ fs.writeFileSync(clPath, `# C\n\n## [Unreleased]\n\n### Fixed\n- real content\n\n## [0.2.0] — 2026-02-02\n\n- stub\n\n${anchor}\n\n- prior\n`);
174
+ const r3 = insertStub(tmp, 'llm', anchor, stub, '0.2.0', false);
175
+ if (r3 !== 'already-present') { console.error(`selftest FAIL: expected 'already-present' for misclassified stub, got '${r3}'`); process.exit(1); }
154
176
 
155
177
  console.log('selftest OK');
156
178
  } finally {
@@ -2,21 +2,21 @@
2
2
  // standalone CHANGELOG helpers.
3
3
  //
4
4
  // THE PROBLEM (bit all 6 a2ui packages at the v0.7.14 cut):
5
- // The 6 a2ui packages live on disk under `packages/a2ui/<x>/` but carry the
5
+ // The 6 a2ui packages live on disk under `packages/gen-ui/a2ui/<x>/` but carry the
6
6
  // flat npm-name `a2ui-<x>` everywhere else in the tooling (release-pack.mjs,
7
7
  // dispatch-publish.mjs, tag-lockstep.mjs all use the NAME form). The two
8
8
  // standalone helpers (promote-unreleased.mjs, insert-stub.mjs) joined
9
9
  // `packages/<arg>/CHANGELOG.md` with the raw arg, so calling them with the
10
10
  // name form silently 404'd: `CHANGELOG.md not found at packages/a2ui-corpus/`.
11
- // release-pack.mjs maps internally (`a2ui-corpus` → `packages/a2ui/corpus`),
11
+ // release-pack.mjs maps internally (`a2ui-corpus` → `packages/gen-ui/a2ui/corpus`),
12
12
  // so the two forms diverged: name-form failed standalone, path-form failed
13
13
  // when handed to the orchestrator-style callers.
14
14
  //
15
15
  // THE FIX:
16
16
  // Accept BOTH forms. Try `packages/<arg>` first (path form, backward-compat).
17
17
  // If that directory is absent AND the arg matches `a2ui-<x>`, fall back to
18
- // `packages/a2ui/<x>`. So `a2ui-corpus` (name) and `a2ui/corpus` (path) both
19
- // resolve to `packages/a2ui/corpus/`.
18
+ // `packages/gen-ui/a2ui/<x>`. So `a2ui-corpus` (name) and `a2ui/corpus` (path) both
19
+ // resolve to `packages/gen-ui/a2ui/corpus/`.
20
20
  //
21
21
  // Pure Node, stdlib only — keeps the scripts free of runtime deps.
22
22
 
@@ -55,6 +55,12 @@ import path from 'node:path';
55
55
  // trip-wire (check-release.mjs's per-tag `checkTag` lookup) reads the FULL
56
56
  // roster unfiltered — every pushed tag, lockstep or not, still needs its
57
57
  // package.json/CHANGELOG validated, so it must recognize a class-B tag too.
58
+ //
59
+ // `shim: true` (ADR-0048 P5) marked the six retired a2ui-* names for their
60
+ // single 0.8.37 bridge cut; the P7 follow-up PR deleted those rows together
61
+ // with packages/shims/. No row carries the flag anymore, and none may — a
62
+ // future one-cut bridge re-introduces the marker with its own retirement PR.
63
+ //
58
64
  // Every lockstep-scoped consumer must filter `p.lockstep !== false` itself
59
65
  // (this module intentionally does NOT pre-filter PACKAGE_NAMES/PACKAGE_DIRS —
60
66
  // they stay full-roster projections so a consumer's own filter is visible at
@@ -62,15 +68,33 @@ import path from 'node:path';
62
68
  export const PACKAGE_ROSTER = [
63
69
  { name: 'web-components', dir: 'packages/web-components', lockstep: true },
64
70
  { name: 'web-modules', dir: 'packages/web-modules', lockstep: true },
65
- { name: 'llm', dir: 'packages/llm', lockstep: true },
66
- { name: 'agent', dir: 'packages/agent', lockstep: true },
67
- { name: 'persona', dir: 'packages/persona', lockstep: true },
68
- { name: 'a2ui-runtime', dir: 'packages/a2ui/runtime', lockstep: true },
69
- { name: 'a2ui-compose', dir: 'packages/a2ui/compose', lockstep: true },
70
- { name: 'a2ui-corpus', dir: 'packages/a2ui/corpus', lockstep: true },
71
- { name: 'a2ui-mcp', dir: 'packages/a2ui/mcp', lockstep: true },
72
- { name: 'a2ui-retrieval', dir: 'packages/a2ui/retrieval', lockstep: true },
73
- { name: 'a2ui-validator', dir: 'packages/a2ui/validator', lockstep: true },
71
+ { name: 'llm', dir: 'packages/llm/core', lockstep: true },
72
+ { name: 'agent', dir: 'packages/llm/agent', lockstep: true },
73
+ { name: 'persona', dir: 'packages/llm/persona', lockstep: true },
74
+ // ── ADR-0048 P5 — the estate split's published names ────────────────────
75
+ //
76
+ // The successors of the six old a2ui-* names. `a2ui`/`gen-ui` join here,
77
+ // which is what turns gate 29 (check-estate-split-latch) green: every
78
+ // workspace dependency edge — web-components a2ui, mcp/gen-ui → gen-ui,
79
+ // the shims → their successors — now points at a name some cut actually
80
+ // publishes.
81
+ //
82
+ // `mcp` (gh#1240, operator ruling 2026-08-14, roster 17 → 16): folds what
83
+ // were TWO planned rows — `gen-ui-mcp` (P2 rename target) and
84
+ // `a2ui-protocol-mcp` (minted fresh at P4) — into ONE published name,
85
+ // `@adia-ai/mcp`, at `packages/gen-ui/mcp/`. Neither predecessor name ever
86
+ // published a 0.8.x, so this fold has no npm deprecation cycle to run —
87
+ // unlike the SIX old a2ui-* names, which really did publish and got one
88
+ // (shim rows retired below). The two-SERVER decision (ADR-0048 §3) is
89
+ // unchanged; only the npm-distribution row count dropped by one.
90
+ { name: 'a2ui', dir: 'packages/gen-ui/a2ui', lockstep: true },
91
+ { name: 'gen-ui', dir: 'packages/gen-ui/engine', lockstep: true },
92
+ { name: 'mcp', dir: 'packages/gen-ui/mcp', lockstep: true },
93
+ // The six retired a2ui-* names (a2ui-runtime/-compose/-corpus/-mcp/
94
+ // -retrieval/-validator) rode EXACTLY the 0.8.37 cut here as `shim: true`
95
+ // rows under packages/shims/, then the P7 follow-up PR deleted them
96
+ // (cut-procedure.md §0.8.38 precondition 1). Their npm names are
97
+ // deprecated pointers; nothing may re-add them.
74
98
  // Plugins joined the lockstep 2026-07-15 (check-lockstep.mjs POLICY note);
75
99
  // each carries a .claude-plugin/plugin.json that bumps with package.json.
76
100
  { name: 'adia-ui-factory', dir: 'packages/plugins/adia-ui-factory', lockstep: true, plugin: true },
@@ -97,12 +121,17 @@ export const PACKAGE_DIRS = PACKAGE_ROSTER.map((p) => p.dir);
97
121
  // require the directory to exist (so callers can render a legible not-found
98
122
  // error against the resolved path).
99
123
  export function resolvePackageDir(repo, pkg) {
124
+ // Roster name-form first (ADR-0049): `llm` must resolve to the roster's
125
+ // `packages/llm/core`, never to the bare `packages/llm/` FAMILY GROUPING
126
+ // dir that now exists on disk (no package.json, no CHANGELOG) — an
127
+ // existsSync-first probe would hit the grouping dir and silently target
128
+ // a non-package. Same for `gen-ui` → `packages/gen-ui/engine`.
129
+ const row = PACKAGE_ROSTER.find((p) => p.name === pkg);
130
+ if (row) return path.relative('packages', row.dir);
100
131
  if (fs.existsSync(path.join(repo, 'packages', pkg))) return pkg;
101
- const m = /^a2ui-(.+)$/.exec(pkg);
102
- if (m) {
103
- const nested = path.join('a2ui', m[1]);
104
- if (fs.existsSync(path.join(repo, 'packages', nested))) return nested;
105
- }
132
+ // (The historical a2ui-* fallbacks — packages/shims/<old-name> and the
133
+ // pre-split packages/gen-ui/a2ui/<x> nesting — died with the shim-deletion
134
+ // follow-up PR after the 0.8.37 cut; a2ui-gen-ui-split.md ruled both dead.)
106
135
  // Plugins live under packages/plugins/<name> but carry the flat name form
107
136
  // (adia-ui-forge) in the release tooling — same name-vs-path split as a2ui.
108
137
  if (/^adia-ui-/.test(pkg)) {
@@ -37,7 +37,7 @@
37
37
  //
38
38
  // Exit: 0 merged + main re-baselined · 1 stopped (evidence printed) · 2 bad args.
39
39
  //
40
- // Part of the adia-release skill. Registered in CI's "Plugin bin selftests".
40
+ // Part of the package-release skill. Registered in CI's "Plugin bin selftests".
41
41
 
42
42
  import { execSync, execFileSync } from 'node:child_process';
43
43
  import fs from 'node:fs';
@@ -14,7 +14,7 @@
14
14
  // node promote-unreleased.mjs --version 0.6.22 --date 2026-05-22 \
15
15
  // --packages web-components,web-modules --dry
16
16
  //
17
- // Part of the adia-release skill. Replaces the inline heading-swap
17
+ // Part of the package-release skill. Replaces the inline heading-swap
18
18
  // pattern used across v0.6.18 / v0.6.19 / v0.6.20 / v0.6.21 cycles.
19
19
  //
20
20
  // Exits:
@@ -55,7 +55,7 @@
55
55
  // --skip-gates : (DEBUG ONLY) skip pre-flight (don't ship anything!)
56
56
  // --skip-site : skip the EXE deploy step (rare; for offline cycles)
57
57
  //
58
- // Part of the adia-release skill. Mechanizes the cut procedure from
58
+ // Part of the package-release skill. Mechanizes the cut procedure from
59
59
  // references/cut-procedure.md. Every confirmation boundary prints its evidence
60
60
  // block BEFORE the prompt (H5) — never a bare y/N — whether it waits for input
61
61
  // (manual flags) or auto-confirms (--go).
@@ -222,8 +222,8 @@ function help() {
222
222
  --gh-notes-file /tmp/release-v$X.Y.Z.md \\
223
223
  --substantive "<one-line>" \\
224
224
  --xref "packages/web-modules/CHANGELOG.md#0$X$Y$Z--YYYY-MM-DD" \\
225
- --substantive-packages web-components,web-modules,a2ui/corpus \\
226
- --stub-packages llm,a2ui/compose,a2ui/mcp,a2ui/retrieval,a2ui/runtime,a2ui/validator
225
+ --substantive-packages web-components,web-modules,gen-ui \\
226
+ --stub-packages llm,agent,persona,a2ui,mcp,adia-ui-factory,adia-ui-forge
227
227
 
228
228
  Flags: --go (single-authorization: the operator's cut-start go covers the
229
229
  whole cycle — auto-confirms ALL checkpoints; stops only on
@@ -691,11 +691,22 @@ function step5Commit(args) {
691
691
  'packages/genui/adia-catalog/base.json',
692
692
  'packages/genui/adia-catalog/adia-pack.json',
693
693
  'packages/genui/adia-catalog/catalog-data.js',
694
+ // gh#1197: gate 28 (write-eval-health.mjs, Step 3) writes this
695
+ // COMMITTED per-cut health record — WS-4 REQ-06's contract — but it
696
+ // never rode the release commit: v0.8.35's and v0.8.36's records both
697
+ // sat untracked until a session close-out swept them by hand (PR
698
+ // #1196). Named after args.version (gate 28 is a targetVersionArg gate,
699
+ // so it always writes at the CUT version, never previous — see Step 3's
700
+ // targetVersionArg comment above). Under --skip-gates the record was
701
+ // never written (Step 3 returned early), so staging it would make the
702
+ // whole `git add` fail on a missing pathspec (PR #1204 review).
703
+ ...(args.skipGates ? [] : [`evals/health/${args.version}.json`]),
694
704
  ...LOCKSTEP_ROSTER.flatMap(({ name, dir, plugin }) => {
695
705
  // Roster-driven (H3): each package stages its manifest + CHANGELOG;
696
706
  // plugins also stage .claude-plugin/plugin.json (the /plugin-update
697
- // cache key, moved by bump.mjs); factory additionally pins a2ui-mcp in
698
- // .mcp.json (SKILL invariant 8 — bump.mjs moves the pin too).
707
+ // cache key, moved by bump.mjs); factory additionally pins the
708
+ // generation MCP (@adia-ai/mcp) in .mcp.json (SKILL invariant 8 —
709
+ // bump.mjs moves the pin too).
699
710
  const files = [`${dir}/package.json`, `${dir}/CHANGELOG.md`];
700
711
  if (plugin) files.push(`${dir}/.claude-plugin/plugin.json`);
701
712
  if (name === 'adia-ui-factory') files.push(`${dir}/.mcp.json`);
@@ -1009,13 +1020,13 @@ async function main() {
1009
1020
  const args = parseArgs(process.argv.slice(2));
1010
1021
  // Fail-fast guard: refuse to git/npm/gh/curl against a non-monorepo directory.
1011
1022
  assertMonorepoRoot(REPO);
1012
- console.log(`adia-release release-pack — v${args.version} (${args.mode})${args.dry ? ' [DRY]' : ''}`);
1023
+ console.log(`package-release release-pack — v${args.version} (${args.mode})${args.dry ? ' [DRY]' : ''}`);
1013
1024
  // Stale-plugin-cache self-check (v0.8.32 cut, first failure): the INSTALLED
1014
1025
  // plugin cache only refreshes on a version bump, so running this script from
1015
1026
  // the cache mid-cycle can execute a version that predates its own guards
1016
1027
  // (SKILL.md §Plugin cache). If the repo carries its own copy and the bytes
1017
1028
  // differ, warn loudly — the repo copy is almost always the newer one.
1018
- const repoCopy = path.join(REPO, 'packages/plugins/adia-ui-forge/skills/adia-release/scripts/release-pack.mjs');
1029
+ const repoCopy = path.join(REPO, 'packages/plugins/adia-ui-forge/skills/package-release/scripts/release-pack.mjs');
1019
1030
  const selfPath = new URL(import.meta.url).pathname;
1020
1031
  if (fs.existsSync(repoCopy) && path.resolve(selfPath) !== path.resolve(repoCopy)) {
1021
1032
  const self = fs.readFileSync(selfPath, 'utf8');
@@ -1115,6 +1126,10 @@ function selftest() {
1115
1126
  'STOPPING per invariant 3',
1116
1127
  // gh#358 — the release branch must actually be created, not just documented.
1117
1128
  'git checkout -b release/v9.9.9',
1129
+ // gh#1197 — Step 5's staging pathspec must carry gate 28's committed
1130
+ // health record, or it rides untracked past the release commit
1131
+ // (v0.8.35/v0.8.36 both did, PR #1196 swept them by hand).
1132
+ 'evals/health/9.9.9.json',
1118
1133
  ];
1119
1134
  for (const marker of need) {
1120
1135
  if (!out.includes(marker)) {
@@ -1153,7 +1168,13 @@ function selftest() {
1153
1168
  guardFailed = true;
1154
1169
  guardOut = (e.stdout || '') + (e.stderr || '');
1155
1170
  }
1156
- if (!guardFailed || !guardOut.includes('ride-along') || !guardOut.includes('a2ui-validator')) {
1171
+ // The expected ride-alongs are DERIVED from the roster (everything but
1172
+ // the one --substantive-packages entry above), never transcribed — a
1173
+ // hard-coded name here went stale when the shim-deletion follow-up PR
1174
+ // shrank the roster 16 → 10 (the same never-transcribe rule the cut
1175
+ // docs enforce on every other roster projection).
1176
+ const expectedRideAlongs = PACKAGES.filter((p) => p !== 'web-components');
1177
+ if (!guardFailed || !guardOut.includes('ride-along') || !expectedRideAlongs.every((p) => guardOut.includes(p))) {
1157
1178
  console.error('selftest FAIL: from-scratch without --stub-packages must hard-reject at parse time, naming the ride-alongs');
1158
1179
  process.exit(1);
1159
1180
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // tag-lockstep.mjs — create the lockstep tag set (umbrella vX.Y.Z + one
3
3
  // per-package <pkg>-vX.Y.Z per roster entry — package-paths.mjs is the
4
- // live census; 14 tags as of gh#607) at HEAD or at a specified SHA.
4
+ // live census; 11 tags as of gh#1282) at HEAD or at a specified SHA.
5
5
  //
6
6
  // Usage:
7
7
  // node tag-lockstep.mjs --version 0.6.22
@@ -9,7 +9,7 @@
9
9
  // node tag-lockstep.mjs --version 0.6.22 --delete # delete existing tags
10
10
  // node tag-lockstep.mjs --version 0.6.22 --dry # print commands without running
11
11
  //
12
- // Part of the adia-release skill. Mechanizes the tag loop used
12
+ // Part of the package-release skill. Mechanizes the tag loop used
13
13
  // every cycle.
14
14
 
15
15
  import { execSync } from 'node:child_process';
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: adia-author
2
+ name: primitive-authoring
3
3
  description: >-
4
4
  Author or modify AdiaUI framework source inside the monorepo — primitives
5
5
  (packages/web-components), shells/composites (packages/web-modules), yaml
@@ -10,19 +10,19 @@ description: >-
10
10
  module, audit a component's four-axis contract/token usage/lifecycle
11
11
  (connected/disconnected symmetry) for drift, or author/write a demo or
12
12
  examples.html for a component or composite. NOT for composing app screens
13
- from primitives (adia-compose), A2UI pipeline internals (adia-a2ui),
14
- @adia-ai/llm adapter/streaming/bridge internals (adia-llm-internals), or
15
- site/pages docs pages (adia-site-docs).
13
+ from primitives (screen-composition), A2UI pipeline internals (a2ui-maintenance),
14
+ @adia-ai/llm adapter/streaming/bridge internals (llm-client-maintenance), or
15
+ site/pages docs pages (site-docs-authoring).
16
16
  disable-model-invocation: false
17
17
  user-invocable: true
18
18
  ---
19
19
 
20
- # adia-author
20
+ # primitive-authoring
21
21
 
22
22
  Guard rails for code that lands INSIDE the adia-ui monorepo: primitives
23
23
  (`packages/web-components/`), shells and composites (`packages/web-modules/`),
24
24
  their `<name>.yaml` SoTs, and composite demos. `@adia-ai/llm` internals
25
- (adapters, streaming, the bridge) are `adia-llm-internals`'s charter, not
25
+ (adapters, streaming, the bridge) are `llm-client-maintenance`'s charter, not
26
26
  this skill's — route there.
27
27
  Light-DOM is load-bearing: `slot=` attributes are decorative metadata,
28
28
  positioning is CSS by tag + ancestor + DOM order — never `::slotted()`,
@@ -41,7 +41,7 @@ wins any tie with this skill. Monorepo source read while authoring (yaml, CSS,
41
41
  | Contract / token / lifecycle drift audit on an existing component | [token-contract.md](references/token-contract.md) + [anti-patterns.md](references/anti-patterns.md) |
42
42
  | Demo for a composite/module — any `packages/web-modules/**/*.{examples,contents}.html` | [composite-demo-protocol.md](references/composite-demo-protocol.md) — NOT the primitive or promotion paths; they lack the canonical-survey discipline |
43
43
  | Convention question ("is this idiomatic?") | [code-style.md](references/code-style.md) — cite the rule, don't expand it inline |
44
- | Trait detail page (`site/pages/traits/<name>/`) | [trait-pages.md](references/trait-pages.md) — the ADR-0019 required-section template (traits are this skill's charter; adia-site-docs does not own `traits/`) |
44
+ | Trait detail page (`site/pages/traits/<name>/`) | [trait-pages.md](references/trait-pages.md) — the ADR-0019 required-section template (traits are this skill's charter; site-docs-authoring does not own `traits/`) |
45
45
 
46
46
  Full retrieval map — one line per reference file, grouped by axis:
47
47
  [references/INDEX.md](references/INDEX.md). Depth references (api-contract,