@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.
- package/CHANGELOG.md +10 -0
- package/catalog/catalog-a2ui_0_9.json +17 -2
- package/catalog/catalog-a2ui_0_9_rules.txt +3 -1
- package/catalog/tier-index.json +6789 -5
- package/catalog/tiers/README.md +54 -5
- package/catalog/tiers/curation/l1-widgets.curation.json +153 -0
- package/catalog/tiers/l1-widgets.json +6789 -0
- package/package.json +1 -1
package/catalog/tiers/README.md
CHANGED
|
@@ -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"
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
+
}
|