@adia-ai/adia-ui-forge 0.8.15 → 0.8.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adia-forge",
3
- "version": "0.8.15",
3
+ "version": "0.8.16",
4
4
  "description": "Maintain the adia-ui (@adia-ai) framework itself \u2014 author primitives and shells, run the A2UI generation pipeline and its corpus, review gen-UI quality, sweep QA, cut releases, deploy. The maintainer counterpart to adia-factory (the consumer/app-author plugin).",
5
5
  "author": {
6
6
  "name": "Kim",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog — adia-forge
2
2
 
3
+ ## [0.8.16] — 2026-07-26
4
+
5
+ ### Fixed
6
+ - **The cut's harvest preamble now names `.examples.html` and the two generators it feeds** (`skills/adia-release/references/cut-procedure.md` §3.0; gh#421) — the trigger list covered component yaml, `.a2ui.json`, `*.contents.html`, and `data-chunk-*`-annotated pages, so an `.examples.html` edit read as out of scope. It isn't: it feeds `.examples.md`, the `site-a2ui` converted rows, **and** the chunk harvest's source hashes. The v0.8.14 cut edited two components' `.examples.html`, ran every freshness gate the doc named, saw them clean, and still lost a CI round-trip to `🔴 stale /site/components/{menu,popover}` plus two changed-since-harvest sources. The regen block now lists `generate-examples-md.mjs`, `site-a2ui.mjs --stale`, and `check-token-semantics-sync.mjs --fix`, and the trigger list adds `styles/colors/*`.
7
+
8
+ ### Changed
9
+ - **The pre-cut gate roster grows 18 → 22** (`skills/adia-release/scripts/gate-roster.mjs`) — `check:examples-md-fresh`, `verify:site-a2ui`, `verify:contrast`, and `check:token-semantics-sync` all shipped in the `npm run check` aggregate but were never in the release roster, so a gate added to CI silently never reached a cut. `verify:contrast` matters most: gh#427 widened it from 42 to 90 pairs, and without it in the roster a sub-AA token could ship past a green pre-flight. `cut-procedure.md` §3.1's transcribed table and the SKILL/gates-catalog counts moved with it — verified programmatically that the doc table and the module list are entry-for-entry identical.
10
+
11
+ ### Maintenance
12
+ - **`.claude-plugin/plugin.json` version bump** — moves in lockstep with package.json (the `/plugin update` cache key).
13
+
3
14
  ## [0.8.15] — 2026-07-26
4
15
 
5
16
  ### Maintenance
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adia-ai/adia-ui-forge",
3
- "version": "0.8.15",
3
+ "version": "0.8.16",
4
4
  "description": "Maintain the adia-ui (@adia-ai) framework itself \u2014 author primitives and shells, run the A2UI generation pipeline and its corpus, review gen-UI quality, sweep QA, cut releases, deploy. The maintainer counterpart to adia-factory (the consumer/app-author plugin).",
5
5
  "keywords": [
6
6
  "adia-ui",
@@ -93,7 +93,7 @@ assumed pass, or "published" without the actual `npm view` output.
93
93
 
94
94
  ## Mechanization (bundled `scripts/`, stdlib Node, all support `--dry`)
95
95
 
96
- `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 of the 11 packages 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 17-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.
96
+ `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 of the 11 packages 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 22-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.
97
97
 
98
98
  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` (12 tags, `--delete` to move), `dispatch-publish.mjs` (publish workflows; `--verify-triggered` re-dispatches only missing runs; `--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
99
 
@@ -61,16 +61,29 @@ Keep the stash held through the site deploy (Step 10) — the tarball builds fro
61
61
 
62
62
  ### 3.0 Harvest preamble (only when source content changed in the window)
63
63
 
64
- If `git diff <prev-tag>..HEAD --name-only` touches component yaml / `.a2ui.json` sources, `*.contents.html`, catalog/site pages with `data-chunk-*` annotations — regenerate downstream artifacts proactively (otherwise the freshness gates force a tag-move recovery later):
64
+ If `git diff <prev-tag>..HEAD --name-only` touches component yaml / `.a2ui.json` sources, **`*.examples.html`**, `*.contents.html`, **any file under `site/`, `apps/`, `playgrounds/`, or `catalog/`** — annotated with `data-chunk-*` or not or any `styles/colors/*` token source, regenerate downstream artifacts proactively (otherwise the freshness gates force a tag-move recovery later):
65
65
 
66
66
  ```bash
67
- node scripts/build/components.mjs # catalog + per-component sidecars
68
- npm run harvest:chunks # chunk corpus from site/apps/playgrounds/catalog
69
- npm run build:embeddings:chunks # embedding index (needs OPENAI_API_KEY)
70
- npm run build -w @adia-ai/llm # tsc artifact build:bundle-js resolves
71
- npm run build:bundles # dist CSS+JS bundles
67
+ node scripts/build/components.mjs # catalog + per-component sidecars
68
+ node scripts/build/generate-examples-md.mjs # .examples.md from .examples.html
69
+ node scripts/build/site-a2ui.mjs --stale # /site/components/* converted rows
70
+ npm run harvest:chunks # chunk corpus from site/apps/playgrounds/catalog
71
+ npm run check:embeddings-fresh # run this FIRST; if it passes, SKIP the rebuild below
72
+ npm run build:embeddings:chunks # ONLY if the line above failed (needs OPENAI_API_KEY)
73
+ node scripts/release/check-token-semantics-sync.mjs --fix # adia-tokens role-roster + alias-layer
74
+ npm run build -w @adia-ai/llm # tsc artifact build:bundle-js resolves
75
+ npm run build:bundles # dist CSS+JS bundles
72
76
  ```
73
77
 
78
+ **The `data-chunk-*` qualifier was the trap** (gh#421). Two separate cuts lost a CI round-trip to it:
79
+
80
+ - **v0.8.14** edited two components' `*.examples.html` — not yaml, not `.contents.html`, no annotation — so it read as out of scope. It isn't: `.examples.html` feeds **three** generators (`.examples.md`, the `site-a2ui` converted rows, and the chunk harvest's source hashes). Every freshness gate this doc named came back clean, and CI still failed on `🔴 stale /site/components/{menu,popover}` plus `2 source file(s) changed since harvest`.
81
+ - **The 0.8.16 cycle** then added a brand-new `site/pages/guides/theming.html` with *no* annotations, ran `site-a2ui`, `check:links`, `verify:llms`, and `verify:patterns-index` — all clean — and CI failed anyway: `1 source file(s) NEW since harvest`.
82
+
83
+ Root cause of both: `check-chunks-fresh` hashes **every** source file under the harvest globs and compares the set against the corpus record, so a new or changed file trips it whether or not the harvester extracts a chunk from it. The annotation governs what gets *harvested*, never what gets *hashed*. Hence the trigger list above names the directories, not the annotation.
84
+
85
+ When only source *hashes* move and chunk content does not, `check:embeddings-fresh` stays green on its content hash — no embedding rebuild, no `OPENAI_API_KEY` needed. Both incidents above were that case, which is why the block above runs that check *before* `build:embeddings:chunks` and skips the rebuild when it passes: an unconditional rebuild makes an ordinary `.examples.html` or new-page edit fail pre-flight on any machine without the key, for no reason. Only a change that alters chunk **content** needs the rebuild.
86
+
74
87
  **Regen output supersedes working-tree state.** These outputs land in the release commit unconditionally, even when the same paths are also dirty from a peer — the fresh regen is authoritative; divergent uncommitted work rebases on top afterwards.
75
88
 
76
89
  ### 3.1 The full roster — every gate runs; a subset = pre-flight failure
@@ -93,7 +106,11 @@ npm run check:embeddings-fresh # 14 embeddings vs chunk index
93
106
  npm run check:links # 15 intra-repo links
94
107
  npm run eval:diff -- --engine zettel # 16 eval floors
95
108
  npm run dogfood:status # 17 P0/P1 dogfood floor
96
- node scripts/release/check-cut-hygiene.mjs --version <mode-dependent> # 18 README CDN-pin + version currency — CUT modes pre-flight at the PREVIOUS version (the README claim is exact-match and only moves at the Step-4 bump; Step 4g re-proves at the cut version), HANDOFF pre-flights at the CUT version (post-merge, the claim already moved)
109
+ npm run check:examples-md-fresh # 18 .examples.md vs .examples.html
110
+ npm run verify:site-a2ui # 19 site-a2ui rows vs source fragments
111
+ npm run verify:contrast # 20 WCAG AA — canvas-text AND text-on-fill
112
+ npm run check:token-semantics-sync # 21 adia-tokens generated refs vs token sources
113
+ node scripts/release/check-cut-hygiene.mjs --version <mode-dependent> # 22 README CDN-pin + version currency — CUT modes pre-flight at the PREVIOUS version (the README claim is exact-match and only moves at the Step-4 bump; Step 4g re-proves at the cut version), HANDOFF pre-flights at the CUT version (post-merge, the claim already moved)
97
114
  ```
98
115
 
99
116
  Any red → route via [`gates-catalog.md`](gates-catalog.md); fix at the source, re-run the narrowest gate, then re-run the full sequence. The canonical miss: a cut that ran 7 of the gates shipped a stale-embeddings defect that surfaced a day later and cost a tag-move recovery.
@@ -202,7 +202,7 @@ npm run check:demo-shells
202
202
 
203
203
  Add `verify:corpus` + `check:embeddings-fresh` if chunks were touched; `check:lightningcss-build` if CSS was touched; F-N1 if unpushed release tags exist.
204
204
 
205
- **Full pre-cut sweep** — the 17-gate roster in [`cut-procedure.md`](cut-procedure.md) §Step 3, sourced from `` `${CLAUDE_PLUGIN_ROOT}/skills/adia-release/scripts/gate-roster.mjs` `` (the ONE list; `release-pack.mjs` imports and runs it in full — a subset run is impossible without editing that file). ~90s wall time.
205
+ **Full pre-cut sweep** — the 22-gate roster in [`cut-procedure.md`](cut-procedure.md) §Step 3, sourced from `` `${CLAUDE_PLUGIN_ROOT}/skills/adia-release/scripts/gate-roster.mjs` `` (the ONE list; `release-pack.mjs` imports and runs it in full — a subset run is impossible without editing that file). ~90s wall time.
206
206
 
207
207
  **Omnibus** — `npm run check` invokes everything. Heavy; use when re-baselining a stale checkout.
208
208
 
@@ -40,11 +40,21 @@ export const GATE_ROSTER = [
40
40
  { n: 15, cmd: 'npm run check:links', what: 'intra-repo links' },
41
41
  { n: 16, cmd: 'npm run eval:diff -- --engine zettel', what: 'eval floors' },
42
42
  { n: 17, cmd: 'npm run dogfood:status', what: 'P0/P1 dogfood floor' },
43
+ // gh#421: these four live in the `npm run check` aggregate but were never
44
+ // in the pre-cut roster, so a gate added to CI silently never reached a
45
+ // cut. examples-md + site-a2ui are the two generators an `.examples.html`
46
+ // edit invalidates (the v0.8.14 cut lost a CI round-trip to exactly that);
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.
49
+ { n: 18, cmd: 'npm run check:examples-md-fresh', what: '.examples.md vs .examples.html' },
50
+ { n: 19, cmd: 'npm run verify:site-a2ui', what: 'site-a2ui converted rows vs source fragments' },
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' },
43
53
  // versionArg: the runner appends ` --version X.Y.Z` (release-pack knows the
44
54
  // cut version; the roster stays a static list). Objective half of the
45
55
  // v0.7.13-retro hygiene checker — README CDN pins / "Current version"
46
56
  // claims vs the cut version; branch/worktree limbo prints as warns (H2).
47
- { n: 18, cmd: 'node scripts/release/check-cut-hygiene.mjs', what: 'README CDN-pin + version currency', versionArg: true },
57
+ { n: 22, cmd: 'node scripts/release/check-cut-hygiene.mjs', what: 'README CDN-pin + version currency', versionArg: true },
48
58
  ];
49
59
 
50
60
  // -- CLI ------------------------------------------------------------------
@@ -709,7 +709,7 @@ async function main() {
709
709
  // Plan-assembly selftest — spawns THIS script as a real subprocess with
710
710
  // --mode cut --dry (fully mutation-free per every step's own dry-guard) and
711
711
  // asserts the assembled plan carries the expected markers: the full
712
- // 17-gate roster (H3 — a subset run must be impossible without editing
712
+ // 22-gate roster (H3 — a subset run must be impossible without editing
713
713
  // gate-roster.mjs), and the invariant-3 stop-before-PR message (cut mode
714
714
  // must never proceed to tag/push/publish on its own). A fixture temp dir
715
715
  // supplies the operator-authored content files (--commit-message-file /