@adia-ai/a2ui 0.8.38 → 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.
@@ -15,6 +15,18 @@ the ladder's one law: **every tier-N entry is a declared composition of
15
15
  tier-(N−1) entries.** An entry that composes nothing, or that names something
16
16
  absent from the rung below, fails the build.
17
17
 
18
+ Where an entry carries a `template`, the law is enforced one level deeper:
19
+ `composes` must be **exactly** the set of rung-below entries the template
20
+ actually uses — no undeclared uses, no unused declarations. Templates spell
21
+ components with A2UI standard TYPE names (`Column`, `CheckBox`,
22
+ `ChoicePicker`) while L0 is keyed by catalog COMPONENT names (`Col`, `Check`,
23
+ `Select`); the derivation joins them through `registry.js` (type → tag) and
24
+ the catalog's `x-adiaui.tag` (tag → name), so authors write whichever
25
+ vocabulary the template uses and declare `composes` in catalog names. A type
26
+ that resolves to neither — a native element (`FormContainer`,
27
+ `DescriptionTerm`), a sub-descriptor (`ColDef`), or an upper-rung unit
28
+ (`AdminShell`) — has no L0 entry and fails the build.
29
+
18
30
  ## File shape
19
31
 
20
32
  ```jsonc
@@ -27,7 +39,7 @@ absent from the rung below, fails the build.
27
39
  "template": [ /* A2UI nodes referencing L0 types only */ ],
28
40
  "wiring": { /* controller/handler contract, wiring-registry vocabulary */ },
29
41
  "keywords": ["stats", "kpi", "dashboard"],
30
- "preview": "previews/stat-summary-row.html" // derived artifact, never hand-written
42
+ // "preview": "previews/stat-summary-row.html" // RESERVED, unbuilt — see below
31
43
  }
32
44
  }
33
45
  }
@@ -37,9 +49,46 @@ Only `composes` is interpreted by the derivation; every other key is carried
37
49
  into the index untouched, so this directory stays the single authoring
38
50
  surface and the index stays a pure aggregation.
39
51
 
52
+ `preview` is **reserved and unbuilt** — no entry carries one, and no generator
53
+ exists. Rendering an AdiaUI widget needs a browser (built bundles, icon
54
+ registry, custom-element upgrade), and every rendering path in this repo is
55
+ ephemeral review tooling against a running dev server. The scope-out rationale
56
+ and the re-entry checklist are in `.claude/docs/specs/tiered-catalogs.md`
57
+ ## Previews (gh#1291 phase 2). Until then, `source.page` is the pointer at a
58
+ live demo page where the widget renders in situ.
59
+
40
60
  ## Status
41
61
 
42
- Empty by design as of phase 1 (the L0 home-move). L1 curation — promoting the
43
- best of the zettel compositions and patterns into named, versioned widget
44
- entriesis its own sized phase; see `.claude/docs/specs/tiered-catalogs.md`
45
- ## Follow-up phases.
62
+ | Rung | State |
63
+ |---|---|
64
+ | `l1-widgets.json` | **populated** 44 curated widgets across 17 domains (gh#1291 phase 1) |
65
+ | `l2-*.json` | reserved — unblocked now that L1 exists |
66
+ | `l3-*.json` · `l4-*.json` | reserved |
67
+
68
+ ## The L1 curation record
69
+
70
+ `curation/l1-widgets.curation.json` is the **authored judgment**: the criteria
71
+ (five mechanical gates + three selection rules) and the allow-list of admitted
72
+ chunk names, with the rationale for each. `l1-widgets.json` is its
73
+ transcription, materialized by
74
+
75
+ node scripts/build/curate-l1-widgets.mjs --apply # write
76
+ node scripts/build/curate-l1-widgets.mjs --verify # report divergence
77
+
78
+ That script is a **one-shot curation tool, not a build step** — deliberately
79
+ absent from `npm run check` and from every freshness gate. ADR-0050 Decision
80
+ §1 rules that the corpus derives from catalogs and never the reverse; wiring
81
+ the transcription into the build would make the chunk corpus a standing input
82
+ to the catalog and close a derivation cycle. `curation/` is not matched by the
83
+ `l1-*.json` glob, so the tier derivation never reads it.
84
+
85
+ An entry's `template` is a **snapshot frozen at curation time**, not a live
86
+ view of its source chunk — a widget entry is a versioned contract that holds
87
+ still while demo HTML evolves. `--verify` reporting divergence is information,
88
+ not breakage; re-syncing means bumping the affected entries' `version` and
89
+ re-running `--apply`.
90
+
91
+ Entry names are their source chunk's name unchanged, which keeps the
92
+ provenance join an identity and keeps naming out of the judgment budget.
93
+ Each entry carries `source: { chunk, page }`; the reverse linkage (a chunk
94
+ naming its catalog entry) is gh#1291 phase 5.
@@ -0,0 +1,153 @@
1
+ {
2
+ "$comment": "AUTHORED curation record for the L1 widget rung (ADR-0050, gh#1291 phase 1). This file is the CURATION — the judgment act. `../l1-widgets.json` is its transcription, materialized by `node scripts/build/curate-l1-widgets.mjs --apply` (a one-shot curation tool, deliberately NOT a gate and NOT in `npm run check`: the corpus must never become a standing input to the catalog build — ADR-0050 Decision §1, 'the corpus derives from catalogs, never the reverse'). Not matched by the tier glob (`l1-*.json` in the parent dir), so the derivation never reads it.",
3
+ "curationId": "l1-widgets@1",
4
+ "date": "2026-08-15",
5
+ "issue": "https://github.com/adiahealth/gen-ui-kit/issues/1291",
6
+ "rationale": {
7
+ "proposalAsWritten": "The design note's open question 1 proposed ranking by zettel-engine usage frequency from eval traces. That signal is not available to this curation: eval runs land in `evals/mcp/runs/` which is not committed, and the corpus chunk index reports `instances: 1` for every one of the 431 ladder-clean block chunks, so there is no in-repo frequency to rank by. The criteria below substitute repo-resident, deterministic signals for the same intent — 'what recurs on shipped surfaces', not 'what exists'.",
8
+ "intent": "L1 is the CURATED-COMMON tier: the chat-scale functional units an agent enumerates and asks for by name. Breadth over depth — one canonical entry per composition shape, capped per domain — so the first slice is a usable vocabulary rather than a census of the 516 templates.",
9
+ "namingRule": "An entry's name is its source chunk's name, unchanged. Renaming would buy prettier names at the cost of traceability and would make every name an arbitrary judgment call; chunk names are already kebab-case, unique, and descriptive. This also makes the phase-5 chunk<->entry linkage an identity join.",
10
+ "frozenSnapshot": "An entry's `template` is a snapshot taken at curation time, not a live view of the chunk. That is the point of curation: a widget entry is a versioned contract that holds still while demo HTML evolves. Re-syncing is an authored act (bump `version`, re-run the tool), never an automatic build step."
11
+ },
12
+ "criteria": {
13
+ "gates": [
14
+ {
15
+ "id": "G1",
16
+ "name": "tier fit",
17
+ "rule": "chunk.kind === 'block'",
18
+ "why": "L1's entry unit is a chat-scale functional unit. `page` chunks are whole routes and `panel` chunks are shell regions — both are L2/L3 material, and admitting them would let L1 absorb the rungs above it."
19
+ },
20
+ {
21
+ "id": "G2",
22
+ "name": "ladder-clean",
23
+ "rule": "every template node's `component` canonicalizes to an L0 catalog entry",
24
+ "why": "The composability law. Canonicalization goes A2UI type -> tag (packages/gen-ui/a2ui/registry.js) -> catalog component name, because templates emit A2UI standard type names (Column, CheckBox, ChoicePicker) while L0 is keyed by catalog names (Col, Check, Select). Excludes templates using FormContainer / DescriptionTerm / DescriptionDetail / ColDef (native elements and sub-descriptors with no L0 entry) and AdminShell (an L3 unit — correctly not composable at L1)."
25
+ },
26
+ {
27
+ "id": "G3",
28
+ "name": "chat-scale",
29
+ "rule": "6 <= template.length <= 30 nodes",
30
+ "why": "Below 6 nodes an entry is a decorated primitive, not a widget — it adds a name without adding composition. Above 30 it is a section or a page, which is L2's unit."
31
+ },
32
+ {
33
+ "id": "G4",
34
+ "name": "self-contained",
35
+ "rule": "chunk.nested.length === 0",
36
+ "why": "A chunk that contains another chunk is a composition of compositions — L2 by the ladder's own definition."
37
+ },
38
+ {
39
+ "id": "G5",
40
+ "name": "retrieval-ready",
41
+ "rule": "metadata.domain && metadata.description && metadata.keywords.length >= 6",
42
+ "why": "An entry a chat agent cannot find is not a served entry. Domain, description, and keywords are what the protocol MCP will enumerate on (phase 3)."
43
+ }
44
+ ],
45
+ "selection": [
46
+ {
47
+ "id": "S1",
48
+ "name": "one entry per composition shape",
49
+ "rule": "Within a group of gated candidates sharing an identical canonical `composes` set, admit at most one — the most generically-named, most complete representative.",
50
+ "why": "Curated, not census. `banner-announcement-beta` and `banner-announcement-promo` are the same widget with different copy; shipping both spends the vocabulary budget on duplicates."
51
+ },
52
+ {
53
+ "id": "S2",
54
+ "name": "domain cap",
55
+ "rule": "At most 3 entries per metadata.domain.",
56
+ "why": "Breadth is the first slice's job. Uncapped, `data` / `forms` / `settings` alone would take half the tier and leave billing, overlay, and content unrepresented."
57
+ },
58
+ {
59
+ "id": "S3",
60
+ "name": "the named-thing test",
61
+ "rule": "Judgment: would an agent ask for this by name? Prefer canonical shapes over page-specific instances.",
62
+ "why": "The one criterion that cannot be mechanized, and the reason this file is authored rather than derived."
63
+ }
64
+ ]
65
+ },
66
+ "census": {
67
+ "corpusTemplates": 516,
68
+ "afterG1G2": 431,
69
+ "afterAllGates": 273,
70
+ "curated": 44,
71
+ "note": "44 of 273 gated (16%), 8.5% of the 516 templates. The remaining 229 gated candidates are the backlog for the next curation pass, not rejects."
72
+ },
73
+ "entries": {
74
+ "agent": [
75
+ "agent-tool-call-accordion",
76
+ "agent-reasoning-collapsed",
77
+ "agent-memory-list"
78
+ ],
79
+ "auth": [
80
+ "access-denied-with-request",
81
+ "auth-signin-card-otp",
82
+ "verification-stepper"
83
+ ],
84
+ "billing": [
85
+ "checkout-order-summary-card",
86
+ "usage-quota-meter-card"
87
+ ],
88
+ "content": [
89
+ "faq-accordion",
90
+ "comments-composer",
91
+ "code-snippet"
92
+ ],
93
+ "dashboard": [
94
+ "analytics-chart",
95
+ "chart-in-card-full-chart",
96
+ "retention-cohort-with-legend"
97
+ ],
98
+ "data": [
99
+ "stat-cards-kpi-dashboard",
100
+ "search-results-list",
101
+ "order-tracking-timeline"
102
+ ],
103
+ "data-management": [
104
+ "data-export-history",
105
+ "export-flow-delivery"
106
+ ],
107
+ "display": [
108
+ "user-profile-card",
109
+ "bell-menu-empty",
110
+ "image-caption-tile"
111
+ ],
112
+ "error": [
113
+ "banner-system-maintenance"
114
+ ],
115
+ "forms": [
116
+ "login-form-card",
117
+ "signup-form-card",
118
+ "contact-form-card"
119
+ ],
120
+ "input": [
121
+ "filter-popover-form"
122
+ ],
123
+ "layout": [
124
+ "admin-page-header-with-actions",
125
+ "tabs-with-panels",
126
+ "avatar-group-overflow"
127
+ ],
128
+ "marketing": [
129
+ "hero-cta-simple",
130
+ "feature-grid-three-cards",
131
+ "testimonial-pull-quote"
132
+ ],
133
+ "navigation": [
134
+ "admin-topbar-breadcrumb-actions",
135
+ "app-nav-groups",
136
+ "toolbar-icons"
137
+ ],
138
+ "onboarding": [
139
+ "onb-persona-picker",
140
+ "product-tour"
141
+ ],
142
+ "overlay": [
143
+ "alert-dialog-unsaved",
144
+ "destructive-confirm-modal",
145
+ "inline-dialog-rename"
146
+ ],
147
+ "settings": [
148
+ "webhooks-list",
149
+ "api-keys-list",
150
+ "permissions-role-picker-radio"
151
+ ]
152
+ }
153
+ }