@adia-ai/adia-ui-forge 0.8.62 → 0.8.64
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/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/CHANGELOG.md +317 -275
- package/README.md +54 -18
- package/__init__.py +8 -8
- package/agents/a2ui-maintenance-agent.corpus.json +7 -7
- package/agents/a2ui-maintenance-agent.md +6 -6
- package/agents/a2ui-planner-agent.md +11 -11
- package/agents/demo-audit-agent.corpus.json +4 -4
- package/agents/demo-audit-agent.md +8 -9
- package/agents/framework-checker.md +10 -11
- package/agents/framework-planner-agent.md +9 -10
- package/agents/gen-ui-review-agent.corpus.json +4 -4
- package/agents/gen-ui-review-agent.md +8 -8
- package/agents/package-release-agent.corpus.json +4 -4
- package/agents/package-release-agent.md +9 -10
- package/agents/primitive-authoring-agent.corpus.json +1 -1
- package/agents/primitive-authoring-agent.md +5 -5
- package/agents/routing-corpus.json +46 -46
- package/codex.interface.json +1 -1
- package/commands/gen-ui-review.md +1 -1
- package/commands/package-release.md +2 -2
- package/package.json +1 -1
- package/plugin.yaml +2 -2
- package/prompts/gen-ui-review.md +1 -1
- package/prompts/package-release.md +2 -2
- package/references/contracts/a2ui-mcp-surface.md +7 -7
- package/references/contracts/migration-guide-format.md +6 -7
- package/references/shared/content-trust.md +3 -5
- package/skills/a2ui-maintenance/SKILL.md +13 -16
- package/skills/a2ui-maintenance/evals/evals.json +2 -2
- package/skills/a2ui-maintenance/evals/routing-corpus.json +1 -1
- package/skills/a2ui-maintenance/references/anti-patterns.md +10 -10
- package/skills/a2ui-maintenance/references/chunk-authoring.md +11 -12
- package/skills/a2ui-maintenance/references/corpus-discipline.md +13 -14
- package/skills/a2ui-maintenance/references/data-model-reactivity.md +22 -25
- package/skills/a2ui-maintenance/references/eval-diagnostics.md +21 -21
- package/skills/a2ui-maintenance/references/format-extension-decisions.md +12 -13
- package/skills/a2ui-maintenance/references/leverage-rules.md +6 -6
- package/skills/a2ui-maintenance/references/mcp-pipeline-ops.md +9 -10
- package/skills/a2ui-maintenance/references/mcp-tool-reference.md +11 -12
- package/skills/a2ui-maintenance/references/pipeline-overview.md +33 -38
- package/skills/a2ui-maintenance/references/semantic-fail-lifting.md +13 -14
- package/skills/a2ui-maintenance/references/strategy-engines.md +14 -16
- package/skills/a2ui-maintenance/references/surface-lifecycle.md +10 -11
- package/skills/a2ui-maintenance/references/zettel-calibration.md +14 -16
- package/skills/component-md-authoring/SKILL.md +22 -22
- package/skills/component-md-authoring/agents/openai.yaml +1 -1
- package/skills/cross-harness-authoring-standards/SKILL.md +19 -21
- package/skills/cross-harness-authoring-standards/agents/openai.yaml +1 -1
- package/skills/cross-harness-compatibility-standards/SKILL.md +35 -34
- package/skills/cross-harness-compatibility-standards/agents/openai.yaml +1 -1
- package/skills/demo-audit/SKILL.md +38 -38
- package/skills/demo-audit/evals/routing-corpus.json +1 -1
- package/skills/demo-audit/references/admin-shell-anatomy.md +21 -25
- package/skills/demo-audit/references/app-shell-pitfalls.md +11 -13
- package/skills/demo-audit/references/auto-fix-allowlist.md +3 -3
- package/skills/demo-audit/references/card-anatomy-sweep.md +10 -11
- package/skills/demo-audit/references/chat-shell-anatomy.md +25 -26
- package/skills/demo-audit/references/editor-shell-anatomy.md +25 -28
- package/skills/demo-audit/references/html-attr-sweep.md +12 -13
- package/skills/demo-audit/references/mode7-status-battery.md +4 -4
- package/skills/demo-audit/references/native-leak-annotations.md +8 -8
- package/skills/demo-audit/references/output-contract-worked-example.md +8 -8
- package/skills/demo-audit/references/probe-discipline-and-escalation.md +2 -2
- package/skills/demo-audit/references/visual-probe-triage.md +21 -23
- package/skills/gen-ui-review/SKILL.md +28 -28
- package/skills/gen-ui-review/agents/openai.yaml +1 -1
- package/skills/gen-ui-review/evals/evals.json +1 -1
- package/skills/gen-ui-review/evals/routing-corpus.json +1 -1
- package/skills/gen-ui-review/references/corpus-html-patterns.md +28 -29
- package/skills/gen-ui-review/references/exit-gate-mechanics.md +5 -5
- package/skills/gen-ui-review/references/lookup-maintenance.md +2 -2
- package/skills/gen-ui-review/references/loop-protocol.md +25 -25
- package/skills/gen-ui-review/references/rubric-cosmetic.md +10 -10
- package/skills/gen-ui-review/references/rubric-decompose.md +15 -16
- package/skills/gen-ui-review/references/rubric-score.md +23 -24
- package/skills/gen-ui-review/references/scorecard-worked-examples.md +12 -12
- package/skills/gen-ui-review/references/scores.schema.json +2 -2
- package/skills/llm-client-maintenance/SKILL.md +12 -12
- package/skills/llm-client-maintenance/evals/routing-corpus.json +1 -1
- package/skills/llm-client-maintenance/references/adapter-contract.md +27 -27
- package/skills/llm-client-maintenance/references/add-a-provider.md +25 -25
- package/skills/llm-client-maintenance/references/bridge-facade.md +31 -31
- package/skills/llm-client-maintenance/references/browser-proxy-boundary.md +17 -17
- package/skills/llm-client-maintenance/references/model-registry.md +14 -14
- package/skills/llm-client-maintenance/references/streaming-sse.md +21 -21
- package/skills/package-release/SKILL.md +21 -23
- package/skills/package-release/evals/evals.json +2 -2
- package/skills/package-release/evals/routing-corpus.json +2 -2
- package/skills/package-release/references/authorization-model.md +6 -8
- package/skills/package-release/references/changelog-discipline.md +25 -27
- package/skills/package-release/references/cut-procedure.md +129 -136
- package/skills/package-release/references/gates-catalog.md +42 -43
- package/skills/package-release/references/independent-package-release.md +14 -15
- package/skills/package-release/references/invariants-detail.md +9 -9
- package/skills/package-release/references/mechanization.md +11 -12
- package/skills/package-release/references/migration-guide-authoring.md +20 -20
- package/skills/package-release/references/notes-authoring.md +20 -20
- package/skills/package-release/references/recovery-paths.md +28 -28
- package/skills/primitive-authoring/SKILL.md +19 -19
- package/skills/primitive-authoring/agents/openai.yaml +1 -1
- package/skills/primitive-authoring/evals/evals.json +2 -2
- package/skills/primitive-authoring/evals/routing-corpus.json +2 -2
- package/skills/primitive-authoring/references/INDEX.md +22 -22
- package/skills/primitive-authoring/references/anti-patterns.md +76 -77
- package/skills/primitive-authoring/references/api-contract.md +63 -65
- package/skills/primitive-authoring/references/authoring-cycle.md +47 -50
- package/skills/primitive-authoring/references/canonical-pattern-index.md +118 -118
- package/skills/primitive-authoring/references/code-style.md +50 -52
- package/skills/primitive-authoring/references/common-gotchas.md +23 -23
- package/skills/primitive-authoring/references/composite-demo-protocol.md +42 -45
- package/skills/primitive-authoring/references/css-patterns.md +97 -97
- package/skills/primitive-authoring/references/for-attribute-event-contract.md +12 -12
- package/skills/primitive-authoring/references/form-control-sizing.md +16 -18
- package/skills/primitive-authoring/references/lifecycle-patterns.md +42 -42
- package/skills/primitive-authoring/references/llm-bridge.md +21 -21
- package/skills/primitive-authoring/references/module-promotion.md +51 -51
- package/skills/primitive-authoring/references/primitive-audit.md +16 -16
- package/skills/primitive-authoring/references/shell-patterns.md +81 -81
- package/skills/primitive-authoring/references/svg-authoring.md +62 -66
- package/skills/primitive-authoring/references/token-contract.md +45 -49
- package/skills/primitive-authoring/references/trait-pages.md +8 -8
- package/skills/primitive-authoring/references/worked-example.md +39 -39
- package/skills/primitive-authoring/references/yaml-contract.md +139 -143
- package/skills/site-deployment/SKILL.md +25 -26
- package/skills/site-deployment/agents/openai.yaml +1 -1
- package/skills/site-deployment/evals/routing-corpus.json +1 -1
- package/skills/site-deployment/references/deploy-playbooks.md +51 -53
- package/skills/site-docs-authoring/SKILL.md +14 -14
- package/skills/site-docs-authoring/agents/openai.yaml +1 -1
- package/skills/site-docs-authoring/evals/evals.json +1 -1
- package/skills/site-docs-authoring/evals/routing-corpus.json +1 -1
- package/skills/site-docs-authoring/intent.md +18 -18
- package/skills/ssr-compatibility/SKILL.md +24 -25
- package/skills/ssr-compatibility/agents/openai.yaml +1 -1
- package/skills/ssr-compatibility/evals/evals.json +1 -1
- package/skills/ssr-compatibility/evals/routing-corpus.json +1 -1
- package/skills/ssr-compatibility/references/consumer-workarounds.md +22 -23
- package/skills/ssr-compatibility/references/failure-shapes.md +84 -91
- package/skills/ssr-compatibility/references/guard-patterns.md +54 -58
- package/skills/ssr-compatibility/references/status-ledger.md +17 -17
- package/skills/ssr-compatibility/references/test-without-linkedom.md +26 -27
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# YAML component contract
|
|
1
|
+
# YAML component contract, `<name>.yaml` schema
|
|
2
2
|
|
|
3
3
|
Authoritative source-of-truth fields for `packages/web-components/components/<name>/<name>.yaml` and `packages/web-modules/<cluster>/<name>/<name>.yaml`. The build pipeline (`scripts/build/components.mjs`) reads these yamls + emits sidecar JSON (`<name>.a2ui.json`) that feeds the docs site, the A2UI runtime registries, and consumer harnesses.
|
|
4
4
|
|
|
5
|
-
This is the authoritative schema reference for the authoring lane. The JSON Schema lives at `scripts/schemas/component.yaml.schema.json` (referenced by every yaml's `$schema:` key). Amended 2026-08-16 per ADR-0057: that schema is the documented contract + IDE aid, not a run validator
|
|
5
|
+
This is the authoritative schema reference for the authoring lane. The JSON Schema lives at `scripts/schemas/component.yaml.schema.json` (referenced by every yaml's `$schema:` key). Amended 2026-08-16 per ADR-0057: that schema is the documented contract + IDE aid, not a run validator, no build step evaluates it against the yamls. The build-time checks that DO exist are hand-written throws in `compileComponent()` (`scripts/build/components.mjs`): a missing `component:` field, a `component: Surface` (reserved, the A2UI v1.0 implicit root container, SPEC REQ-011/gh#1353), a `status:` value outside the five-value enum (see §`status:` below), a missing `category:` field OR a `category:` value outside the twelve-value enum (see §`category:` below, ADR-0065), and malformed `a2ui.allowedParents`/`a2ui.allowedChildren` composition constraints (see §composition constraints below, plus a full-build cross-reference check that every referenced name is a real `component:` in the catalog). Every other schema constraint (`required: [name, tag, component, description]`, `minLength`, …) is IDE-visible only. This file covers the human-facing contract: what each field means, when to use which value, and the canonical shape of a complete yaml.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -14,98 +14,98 @@ $schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
|
14
14
|
name: UIMyComponent # Class name (PascalCase, UI-prefixed)
|
|
15
15
|
tag: my-component-ui # Custom element tag (kebab-case, -ui-suffixed)
|
|
16
16
|
component: MyComponent # Short component name (no UI- prefix)
|
|
17
|
-
category: form # Category
|
|
17
|
+
category: form # Category, see §category field below (ADR-0065, twelve-value enum)
|
|
18
18
|
version: 1 # Schema version (always 1 for now)
|
|
19
|
-
status: stable # Stability tier
|
|
19
|
+
status: stable # Stability tier, see §status field below
|
|
20
20
|
description: >-
|
|
21
21
|
Short one-paragraph description of what the component does and when
|
|
22
22
|
to use it. Used by the docs site, sidecar, and a2ui registry. Be
|
|
23
23
|
concrete about behavior + appearance, not generic ("a button").
|
|
24
24
|
props:
|
|
25
|
-
… # Prop schemas
|
|
25
|
+
… # Prop schemas, see §props field below
|
|
26
26
|
events:
|
|
27
|
-
… # Event schemas
|
|
27
|
+
… # Event schemas, fired by the component
|
|
28
28
|
slots:
|
|
29
|
-
… # Consumer-fillable light-DOM insertion points
|
|
29
|
+
… # Consumer-fillable light-DOM insertion points, see §slots vs parts below
|
|
30
30
|
parts:
|
|
31
|
-
… # Template-owned anatomy
|
|
31
|
+
… # Template-owned anatomy, see §slots vs parts below
|
|
32
32
|
css-vars:
|
|
33
33
|
… # CSS custom properties the component reads
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
38
|
-
## `slots:` vs `parts
|
|
38
|
+
## `slots:` vs `parts:`, consumer-fillable vs template-owned anatomy (ADR-0067)
|
|
39
39
|
|
|
40
40
|
**Decision rule**: does an author (a human, or an LLM generating an A2UI
|
|
41
|
-
document) ever place their OWN content at this named span? If yes
|
|
42
|
-
with a stamped fallback when nothing is supplied
|
|
41
|
+
document) ever place their OWN content at this named span? If yes, even
|
|
42
|
+
with a stamped fallback when nothing is supplied, it's `slots:`. If the
|
|
43
43
|
component's own `render()`/template ALWAYS stamps it itself, from a prop or
|
|
44
|
-
attribute, and no author-supplied content is ever accepted there
|
|
44
|
+
attribute, and no author-supplied content is ever accepted there, it's
|
|
45
45
|
`parts:`. **Check element source, never the description prose alone**
|
|
46
|
-
(AGENTS.md: source wins)
|
|
46
|
+
(AGENTS.md: source wins), a name that *sounds* internal
|
|
47
47
|
(`actions`, `text`, `leading`) can still be a real insertion point in a
|
|
48
48
|
given component; `table-toolbar.yaml`'s `actions` slot LOOKS stamped by
|
|
49
49
|
name but its `class.js` explicitly absorbs pre-existing `[slot="actions"]`
|
|
50
|
-
children (a real, author-fillable insertion point)
|
|
50
|
+
children (a real, author-fillable insertion point), the opposite of
|
|
51
51
|
`check.yaml`'s `box`, which `static template = () => html\`<span
|
|
52
52
|
slot="box"></span>\`` stamps unconditionally every render.
|
|
53
53
|
|
|
54
54
|
Both keys share the identical `Slot` schema shape (`description:` required,
|
|
55
|
-
`fallback:` optional)
|
|
55
|
+
`fallback:` optional): the only difference is which key an entry lives
|
|
56
56
|
under. `scripts/build/components.mjs` forwards both verbatim onto the
|
|
57
57
|
sidecar (`x-adiaui.slots` / `x-adiaui.parts`) with no other processing.
|
|
58
58
|
|
|
59
|
-
**Why the split matters
|
|
59
|
+
**Why the split matters, three real consumers read `slots:` and present
|
|
60
60
|
every entry as fillable, with no code-level filtering for anything under
|
|
61
61
|
`parts:`:**
|
|
62
62
|
|
|
63
63
|
- `packages/gen-ui/engine/retrieval/component-entry.js`'s
|
|
64
|
-
`serializeReference()
|
|
64
|
+
`serializeReference()`, feeds the LLM-facing `reference`-detail catalog
|
|
65
65
|
entry (MCP tools, `getComponentAPI()`).
|
|
66
66
|
- `packages/gen-ui/engine/compose/strategies/monolithic/_shared.js`'s
|
|
67
|
-
`adaptV09Component()
|
|
68
|
-
- `scripts/docs/anatomy-sweep.mjs`'s `genSlots()
|
|
67
|
+
`adaptV09Component()`, feeds the monolithic engine's prompt catalog.
|
|
68
|
+
- `scripts/docs/anatomy-sweep.mjs`'s `genSlots()`, renders the docs-site
|
|
69
69
|
"slots" anatomy section.
|
|
70
70
|
|
|
71
|
-
A `parts:` entry never reaches any of the three above
|
|
71
|
+
A `parts:` entry never reaches any of the three above, moving template-owned
|
|
72
72
|
anatomy there is a structural fix, not a naming convention alone. An
|
|
73
73
|
existing entry under `slots:` that's actually template-owned (e.g. a
|
|
74
74
|
component predating this ADR) is a real bug: it advertises to an LLM that
|
|
75
75
|
filling it does something, when the component's own template replaces
|
|
76
|
-
whatever's there on the next render
|
|
76
|
+
whatever's there on the next render, the exact gh#284 destructive-replace
|
|
77
77
|
shape, applied to a *documented* slot instead of an undocumented one.
|
|
78
78
|
|
|
79
79
|
`scripts/dev/audit-slot-vocab-vs-css.mjs` (the yaml-vs-CSS `[slot="X"]`
|
|
80
|
-
cross-check) reads BOTH `slots:` and `parts
|
|
80
|
+
cross-check) reads BOTH `slots:` and `parts:`, a `parts:` entry is still a
|
|
81
81
|
real `slot="X"` DOM attribute the component's own CSS may position, just
|
|
82
82
|
never author-fillable, so it stays in that audit's declared-vocabulary set.
|
|
83
83
|
`scripts/dev/audit-template-child-conflict.mjs` (the gh#284 container-shape
|
|
84
|
-
check) is unaffected either way
|
|
84
|
+
check) is unaffected either way, it only checks for a slot literally named
|
|
85
85
|
`default`.
|
|
86
86
|
|
|
87
87
|
---
|
|
88
88
|
|
|
89
|
-
## `a2ui.allowedParents:` / `a2ui.allowedChildren
|
|
89
|
+
## `a2ui.allowedParents:` / `a2ui.allowedChildren:`, composition constraints (SPEC REQ-011, gh#1353)
|
|
90
90
|
|
|
91
91
|
Optional keys inside the `a2ui:` block, alongside `rules:`. Each is a
|
|
92
92
|
non-empty list of catalog `component:` names (NOT tags) naming the parents
|
|
93
93
|
this component may sit under / the direct children it may contain. The
|
|
94
94
|
reserved name `Surface` (the A2UI v1.0 implicit root container) is legal
|
|
95
95
|
only in `allowedParents` and means "may sit at the surface root". **Omitted
|
|
96
|
-
means unconstrained
|
|
96
|
+
means unconstrained**, never write an empty list (that would mean "allowed
|
|
97
97
|
nowhere"; the build refuses it).
|
|
98
98
|
|
|
99
99
|
`allowedParents` matches the nearest custom-element ancestor, not the
|
|
100
100
|
immediate DOM parent (gh#3310): the generated lint rule's
|
|
101
101
|
`compositionFindings()` walks up past native (non-hyphenated) wrapper
|
|
102
|
-
elements
|
|
103
|
-
tag
|
|
102
|
+
elements, `section`, `div`, `td`, `tr`, `tbody`, and any other plain HTML
|
|
103
|
+
tag, until it finds a real catalog component tag or reaches the surface
|
|
104
104
|
root. This mirrors Light DOM's own composition reality (AGENTS.md: CSS
|
|
105
|
-
positions by tag + ancestor + DOM order)
|
|
105
|
+
positions by tag + ancestor + DOM order), a wrapper interposed for layout
|
|
106
106
|
or semantics (a `<section>` inside a card, a `<td>` in a table body) doesn't
|
|
107
107
|
change a component's logical host. `allowedChildren`, by contrast, still
|
|
108
|
-
matches DIRECT children only
|
|
108
|
+
matches DIRECT children only, a named-slot child that should be exempt
|
|
109
109
|
from the default-slot list is a separate, open gap (gh#3308), not addressed
|
|
110
110
|
by this semantics change.
|
|
111
111
|
|
|
@@ -117,23 +117,23 @@ a2ui:
|
|
|
117
117
|
- …
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
-
**Authoring rule
|
|
120
|
+
**Authoring rule, verify against element source, exactly like the
|
|
121
121
|
`slots:`/`parts:` decision above.** Declare a constraint only when the
|
|
122
122
|
component's own source enforces or assumes it (e.g. `stepper.class.js`
|
|
123
123
|
queries `stepper-item-ui`; `segmented.class.js` warns on non-`segment-ui`
|
|
124
124
|
children). A parent that adopts items through wrappers (menu.class.js's
|
|
125
|
-
deliberate descendant query) must NOT constrain
|
|
125
|
+
deliberate descendant query) must NOT constrain, a declared constraint
|
|
126
126
|
stricter than the source is a defect, not documentation.
|
|
127
127
|
|
|
128
128
|
**`allowedChildren` is a default-slot-only check (gh#3308).** A direct
|
|
129
129
|
child carrying ANY `slot=` attribute is a sibling-level named slot, not a
|
|
130
|
-
default-slot member
|
|
130
|
+
default-slot member, the lint-side matcher (`compositionFindings`)
|
|
131
131
|
exempts it from `allowedChildren` entirely, regardless of the slot's name.
|
|
132
132
|
This is why menu-ui can declare `allowedChildren: [MenuItem, MenuDivider,
|
|
133
133
|
MenuLabel]` for its default slot while still accepting an arbitrary
|
|
134
134
|
focusable element on `slot="trigger"` ("typically button-ui, but any
|
|
135
135
|
focusable element works") without a false positive. When a named slot
|
|
136
|
-
*should* be constrained too (rare
|
|
136
|
+
*should* be constrained too (rare, most named slots exist precisely
|
|
137
137
|
because their content varies), add an `allowedChildrenBySlot:` map
|
|
138
138
|
alongside `allowedChildren:`, keyed by slot name, same catalog-name-list
|
|
139
139
|
shape:
|
|
@@ -150,7 +150,7 @@ a2ui:
|
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
A slot with no entry in `allowedChildrenBySlot` (or the key omitted
|
|
153
|
-
entirely) stays unconstrained by design
|
|
153
|
+
entirely) stays unconstrained by design: this is the common case, and
|
|
154
154
|
matches "omitted means unconstrained" for `allowedChildren`/`allowedParents`
|
|
155
155
|
above.
|
|
156
156
|
|
|
@@ -165,7 +165,7 @@ per gh#2116) across the five opt-out-scoped catalogs (`adia.core.json`,
|
|
|
165
165
|
validator enforces them (`UNALLOWED_PARENT`/`UNALLOWED_CHILD`). Module-tier
|
|
166
166
|
yamls (web-modules) now carry a v1.0 sidecar too and land in `adia.shells`.
|
|
167
167
|
`allowedChildrenBySlot` (gh#3308) is NOT part of this catalog/sidecar
|
|
168
|
-
pipeline
|
|
168
|
+
pipeline, `components.mjs` never reads it, it never lands in
|
|
169
169
|
`x-adiaui`/`catalog-a2ui_1_0.json`, and the A2UI v1.0 protocol validator
|
|
170
170
|
never enforces it. It exists purely for the lint-side check below.
|
|
171
171
|
|
|
@@ -173,7 +173,7 @@ A non-empty `allowedParents`/`allowedChildren`/`allowedChildrenBySlot`
|
|
|
173
173
|
generates an enforced lint rule (LLD-0016 §C4, gh#2647):
|
|
174
174
|
`scripts/build/gen-composition-rules.mjs` emits `scripts/lint/
|
|
175
175
|
rules/generated/composition/<name>.mjs`, which flags a markup file where
|
|
176
|
-
the tag nests under (or contains) a non-declared tag
|
|
176
|
+
the tag nests under (or contains) a non-declared tag, `allowedChildren`
|
|
177
177
|
checked against default-slot children only, `allowedChildrenBySlot`
|
|
178
178
|
against the matching named-slot children (see above). Advisory (`warn`)
|
|
179
179
|
until a corpus-wide rollout promotes it (`npm run build:composition-rules`
|
|
@@ -231,42 +231,42 @@ coverage exactly as either list does.
|
|
|
231
231
|
|
|
232
232
|
---
|
|
233
233
|
|
|
234
|
-
## `examples:` field
|
|
234
|
+
## `examples:` field, a2ui example ids (semantic-id grammar, gh#2492)
|
|
235
235
|
|
|
236
236
|
Each `examples[].a2ui` block is a JSON array of component nodes (the same
|
|
237
237
|
`updateComponents.components[]` shape `.claude/docs/specs/a2ui-editor.md`
|
|
238
238
|
documents for the editor's live doc store). That spec's line "other
|
|
239
239
|
component ids are free-form (convention: `c-{n}` for generated ids)" governs
|
|
240
|
-
**editor-generated** ids only
|
|
240
|
+
**editor-generated** ids only, ids the editor mints when a human drags a
|
|
241
241
|
component onto the canvas. It was never a license for **authored** ids
|
|
242
242
|
inside a component's own yaml examples, and treating it as one produced a
|
|
243
243
|
corpus-wide drift toward cryptic, positional ids (`q`, `k1`, `k1v`, `hdr`)
|
|
244
244
|
that don't describe what they are once an example has more than one or two
|
|
245
|
-
nodes
|
|
245
|
+
nodes, reported in gh#2492 against `blockquote.yaml`, `badge.yaml`,
|
|
246
246
|
`aside.yaml`, `alert.yaml`, and `anchor-bar.yaml` (the last four
|
|
247
247
|
corroborating it as a corpus-wide pattern, not a one-off).
|
|
248
248
|
|
|
249
|
-
**Grammar
|
|
249
|
+
**Grammar, authored `a2ui.examples[]` ids only:**
|
|
250
250
|
|
|
251
251
|
- **Kebab-case, role-descriptive.** The id names what the node IS or DOES in
|
|
252
252
|
the example, not its position in the array. `quote-body`, not `q` or
|
|
253
253
|
`node-2`.
|
|
254
254
|
- **Unique per example.** Scoped to one `examples[]` entry, not the whole
|
|
255
|
-
yaml
|
|
255
|
+
yaml, reusing `header` across two examples in the same file is fine;
|
|
256
256
|
reusing an id twice inside one example is not (the renderer's flat
|
|
257
257
|
`children: string[]` lookup would collide).
|
|
258
258
|
- **Compound ids read parent-then-role** for a node that belongs to a named
|
|
259
|
-
cluster: `kpi-revenue`, `kpi-revenue-value`, `kpi-revenue-label
|
|
259
|
+
cluster: `kpi-revenue`, `kpi-revenue-value`, `kpi-revenue-label`, not
|
|
260
260
|
`k1`, `k1v`, `k1l`. This is what lets a reader studying the copy-paste-able
|
|
261
261
|
example understand the structure from the ids alone, without cross-
|
|
262
262
|
referencing the tree.
|
|
263
|
-
- **Exception
|
|
263
|
+
- **Exception, the root/wrapper id may stay short when the example has
|
|
264
264
|
exactly one top-level container and the short id is still a real word**,
|
|
265
265
|
e.g. `card`, `row`, `panel`, as long as every id it contains follows the
|
|
266
266
|
grammar. A single generic wrapper doesn't need `card-wrapper-root`; a
|
|
267
267
|
wrapper's *children* still do.
|
|
268
268
|
- Ids are internal wiring keys (`children: string[]` references, rendered
|
|
269
|
-
only as `data-a2ui-id`)
|
|
269
|
+
only as `data-a2ui-id`), never user-visible copy, but they double as the
|
|
270
270
|
readable structure of the example a consumer studies, which is the whole
|
|
271
271
|
reason this grammar exists.
|
|
272
272
|
|
|
@@ -289,7 +289,7 @@ reported repro):
|
|
|
289
289
|
|
|
290
290
|
```jsonc
|
|
291
291
|
// before (badge.yaml chart-dashboard, positional style mixed with semantic
|
|
292
|
-
// ids in the SAME example
|
|
292
|
+
// ids in the SAME example, k1/k1h/k1v alongside header-row/dash-title)
|
|
293
293
|
{ "id": "k1", "component": "Card", "children": ["k1h", "k1v"] }
|
|
294
294
|
|
|
295
295
|
// after
|
|
@@ -297,7 +297,7 @@ reported repro):
|
|
|
297
297
|
```
|
|
298
298
|
|
|
299
299
|
**Enforcement**: the `EXAMPLE-ID-GRAMMAR` rule
|
|
300
|
-
(`scripts/lint/rules/shared/example-id-grammar.mjs`, gh#2649
|
|
300
|
+
(`scripts/lint/rules/shared/example-id-grammar.mjs`, gh#2649, moved out of
|
|
301
301
|
the retired `scripts/verify/check-example-ids.mjs` into the shared lint
|
|
302
302
|
rule bank per LLD-0016 §C3) walks every yaml's `examples[].a2ui` nodes and
|
|
303
303
|
reports ids that fail the grammar (a bare 1-2 char id, a `^[a-z]\d+`
|
|
@@ -306,15 +306,15 @@ duplicate). gh#2492 Phase 2 swept the corpus-wide 526 violations across 48
|
|
|
306
306
|
files to zero; `npm run check:example-id-grammar` keeps that promotion
|
|
307
307
|
build-blocking in the `npm run check` chain (non-zero exit on any
|
|
308
308
|
violation) even though the rule's own bank-default severity is
|
|
309
|
-
`advisory
|
|
309
|
+
`advisory`, a new example that violates the grammar now fails the build
|
|
310
310
|
immediately, not just on a future sweep. Known gap: the checker's
|
|
311
311
|
positional-pattern regex catches `letter+digits` (`k1`, `c2`) but not a
|
|
312
|
-
`letter-digit-letter-digit` chain like `g1i1
|
|
312
|
+
`letter-digit-letter-digit` chain like `g1i1`, out of scope for this
|
|
313
313
|
sweep (nothing flagged it), left for a future refinement.
|
|
314
314
|
|
|
315
315
|
---
|
|
316
316
|
|
|
317
|
-
## `status:` field
|
|
317
|
+
## `status:` field, stability tier
|
|
318
318
|
|
|
319
319
|
**Required** for all new components. Existing components default to `stable` if unset, but new yamls MUST set this explicitly.
|
|
320
320
|
|
|
@@ -326,134 +326,132 @@ sweep (nothing flagged it), left for a future refinement.
|
|
|
326
326
|
| `deprecated` | Has a replacement; check the component's `related:` section. Docs site shows a `danger`-variant badge labeled "deprecated". |
|
|
327
327
|
| `early-access` | Customer-preview tier; release notes gate. Docs site shows an `info`-variant badge labeled "early access". |
|
|
328
328
|
|
|
329
|
-
**Ratified, closed enum
|
|
329
|
+
**Ratified, closed enum, compiler-enforced at build time, mirrored in the schema (ADR-0057, ratified 2026-08-15).** The five values above are the whole vocabulary; `draft` is NOT a value (the one `draft` in the estate, `embed-shell.yaml`, was corrected to `experimental` when the enum went live, a sixth value on a single occurrence is data-entry drift, not a vocabulary gap). Enforcement: `scripts/build/components.mjs:105` holds `STATUS_VALUES` and `compileComponent()` (`components.mjs:258-260`) throws on any out-of-enum `status:` at the same place it throws on a missing `component:`, so `npm run verify:components` (`node scripts/build/components.mjs --verify`, a member of the `npm run check` aggregate) hard-fails the yaml with a file-and-value error. An invalid status no longer merely skips a docs badge; it stops the build. `scripts/schemas/component.yaml.schema.json:23-27` declares the same enum (default `stable`) for the `$schema:` IDE contract, but no validator runs that file, the hand-synced constant in `components.mjs` is the live gate. `status` is orthogonal to the ADR-0050 L0–L4 tier ladder (tier = what a component is composed of; status = how much to trust its contract today), and nothing in `packages/gen-ui/engine/retrieval/` filters or ranks on it. Source: ADR-0057.
|
|
330
330
|
|
|
331
331
|
**Guidance**:
|
|
332
332
|
|
|
333
|
-
- Set `beta` or `experimental` at FIRST AUTHORING for any component that's not in the stable API contract yet. Don't default to `stable` and bump later
|
|
333
|
+
- Set `beta` or `experimental` at FIRST AUTHORING for any component that's not in the stable API contract yet. Don't default to `stable` and bump later: the badge is consumer-facing, and stable→beta is a downgrade signal.
|
|
334
334
|
- Only set `stable` after the component has shipped at least one MINOR cycle and gathered consumer feedback. The bar for `stable` is "no API changes anticipated in the next 3 MINOR releases."
|
|
335
335
|
- `deprecated` requires a `related:` entry pointing at the replacement. Without one, consumers can't recover.
|
|
336
336
|
|
|
337
|
-
**Sidecar emission**: `x-adiaui.status` field in `<name>.a2ui.json`. The docs site (`site/site.js`) reads this and injects the badge automatically
|
|
337
|
+
**Sidecar emission**: `x-adiaui.status` field in `<name>.a2ui.json`. The docs site (`site/site.js`) reads this and injects the badge automatically, no HTML change needed in `<name>.examples.html`.
|
|
338
338
|
|
|
339
339
|
**Verification**: `grep -L '^status:' packages/web-components/components/*/*.yaml` should return empty (every yaml has a status). Run before opening any authoring PR that adds new yamls.
|
|
340
340
|
|
|
341
341
|
---
|
|
342
342
|
|
|
343
|
-
## `category:` field
|
|
343
|
+
## `category:` field, functional grouping
|
|
344
344
|
|
|
345
|
-
**Required.** Every yaml sets this; `scripts/build/components.mjs` forwards it verbatim onto the sidecar as `x-adiaui.category`, and `packages/gen-ui/engine/retrieval/catalog.js` reads it from there for every YAML-backed component
|
|
345
|
+
**Required.** Every yaml sets this; `scripts/build/components.mjs` forwards it verbatim onto the sidecar as `x-adiaui.category`, and `packages/gen-ui/engine/retrieval/catalog.js` reads it from there for every YAML-backed component, no second, hand-maintained category list for anything with a yaml SoT. `catalog.js` does still carry one small, DELIBERATE exception: a 3-entry `PSEUDO_TYPE_CATEGORY` map (`section`/`header`/`footer` → `card-child`) for `@adia-ai/a2ui` registry pseudo-types that have no yaml SoT at all (v0.9 composition slot-children, not real primitives), nothing to derive from, so this one small map stays hand-maintained by design, not drift.
|
|
346
346
|
|
|
347
347
|
| Value | When to use |
|
|
348
348
|
| --- | --- |
|
|
349
349
|
| `action` | A standalone, click-to-fire trigger (`button-ui`, `toggle-scheme-ui`). |
|
|
350
|
-
| `agent` | AI/agent-facing surfaces
|
|
350
|
+
| `agent` | AI/agent-facing surfaces, chat, trace, tool output, tabular/chart data views (`chat-thread-ui`, `agent-trace-ui`, `table-ui`, `chart-ui`, `embed-ui`). |
|
|
351
351
|
| `container` | A chrome/wrapping surface that holds other content (`card-ui`, `modal-ui`, `drawer-ui`, `menu-ui`, `command-ui`). |
|
|
352
352
|
| `data` | Structured/tabular data display, not a full agent surface (`tree-ui`, `heatmap-ui`). |
|
|
353
|
-
| `display` | Passive content rendering
|
|
353
|
+
| `display` | Passive content rendering, text, media, status glyphs (`text-ui`, `icon-ui`, `badge-ui`, `avatar-ui`, `link-ui`, `mark-ui`, `richtext-ui`, a non-editable renderer, not a form field). |
|
|
354
354
|
| `feedback` | Status/notification/progress communication (`spinner-ui`, `inline-message-ui`, `progress-ui`, `progress-row-ui`, `step-progress-ui`, `feed-ui`, `feed-item-ui`). |
|
|
355
355
|
| `form` | Data-entry composite/field-level components, not raw bindable controls (`field-ui`, `fields-ui`, `rating-ui`, `toggle-option-ui`). |
|
|
356
356
|
| `input` | Bindable form controls (`input-ui`, `select-ui`, `check-ui`, `switch-ui`, `textarea-ui`, `radio-ui`). |
|
|
357
|
-
| `layout` | Pure structural/spatial primitives
|
|
358
|
-
| `navigation` | Wayfinding/switcher controls, including a switcher family's child items (`breadcrumb-ui`, `pagination-ui`, `menu-item-ui`, `segmented-ui`/`segment-ui`, `tabs-ui`/`tab-ui`, `stepper-ui`/`stepper-item-ui`). `toggle-group-ui` is `navigation` too, but its child `toggle-option-ui` is `form` (a wrapper/item split, like `menu-ui`/`menu-item-ui
|
|
357
|
+
| `layout` | Pure structural/spatial primitives, no content semantics of their own (`row-ui`, `col-ui`, `grid-ui`, `stack-ui`, `list-ui`). |
|
|
358
|
+
| `navigation` | Wayfinding/switcher controls, including a switcher family's child items (`breadcrumb-ui`, `pagination-ui`, `menu-item-ui`, `segmented-ui`/`segment-ui`, `tabs-ui`/`tab-ui`, `stepper-ui`/`stepper-item-ui`). `toggle-group-ui` is `navigation` too, but its child `toggle-option-ui` is `form` (a wrapper/item split, like `menu-ui`/`menu-item-ui`, not a same-category pair). |
|
|
359
359
|
| `shells` | Page-level app-shell composites (`simple-shell-ui` and its siblings). |
|
|
360
360
|
| `utility` | Non-visual/accessibility helpers (`skip-nav-ui`, `visually-hidden-ui`). |
|
|
361
361
|
|
|
362
|
-
**Ratified, closed enum
|
|
362
|
+
**Ratified, closed enum, compiler-enforced at build time, mirrored in the schema (ADR-0065).** These twelve values are the whole vocabulary; the census that ratified them found 18 free-form values in live use (typos like `forms`/`data-display`, one-off singletons, and three named misclassifications), all folded or corrected onto this set as part of the same change. Enforcement: `scripts/build/components.mjs` holds `CATEGORY_VALUES` and `compileComponent()` throws on a MISSING `category:` field (unlike `status:`, `category:` is required, not defaulted) as well as on any out-of-enum value, the same place and severity as the `status:` check above, so `npm run verify:components` hard-fails an invalid OR absent category. `scripts/schemas/component.yaml.schema.json`'s `category` enum mirrors this list for the `$schema:` IDE contract; the hand-synced constant in `components.mjs` is the live gate, same relationship as `status`. Source: ADR-0065.
|
|
363
363
|
|
|
364
364
|
**The six one-off drift values ADR-0065 folded**, each independently justified by what the component does, not a blanket rule:
|
|
365
365
|
|
|
366
366
|
| Drift value | Folds to | Example |
|
|
367
367
|
| --- | --- | --- |
|
|
368
|
-
| `forms` | `form` | `toggle-option.yaml
|
|
369
|
-
| `data-display` | `data` | `heatmap.yaml
|
|
370
|
-
| `content` | `display` | `link.yaml
|
|
371
|
-
| `typography` | `display` | `mark.yaml
|
|
372
|
-
| `control` | `action` | `toggle-scheme.yaml
|
|
373
|
-
| `interaction` | `container` | `admin-command.yaml
|
|
368
|
+
| `forms` | `form` | `toggle-option.yaml`, spelling drift against `form`'s existing members. |
|
|
369
|
+
| `data-display` | `data` | `heatmap.yaml`, joins `tree.yaml`/`tree-item.yaml`, same spelling drift shape. |
|
|
370
|
+
| `content` | `display` | `link.yaml`, inline content rendering, same role as `text-ui`/`code-ui`. |
|
|
371
|
+
| `typography` | `display` | `mark.yaml`, a text-highlight element, same role as `text-ui`. |
|
|
372
|
+
| `control` | `action` | `toggle-scheme.yaml`, a click-to-fire toggle, same shape as `button-ui`. |
|
|
373
|
+
| `interaction` | `container` | `admin-command.yaml`, a command-palette surface, same role as `command-ui`. |
|
|
374
374
|
|
|
375
|
-
Three named misclassifications were also fixed, not folded: `check.yaml`/`switch.yaml`/`textarea.yaml` (`layout` → `input
|
|
375
|
+
Three named misclassifications were also fixed, not folded: `check.yaml`/`switch.yaml`/`textarea.yaml` (`layout` → `input`, bindable form controls, not structural primitives), `tabs.yaml` (`container` → `navigation`, unifying with `tab.yaml`), and `feed.yaml` (`container` → `feedback`, unifying with `feed-item.yaml`). Full rationale and the progress-family partial unification: ADR-0065 Decision §2–§4.
|
|
376
376
|
|
|
377
|
-
**A sibling family (a wrapper + its child items, e.g. `tabs-ui`/`tab-ui`) is not required to share one category by default
|
|
377
|
+
**A sibling family (a wrapper + its child items, e.g. `tabs-ui`/`tab-ui`) is not required to share one category by default**, `menu-ui` (`container`) + `menu-item-ui` (`navigation`) is a deliberate, working split. Where a family's sibling values disagreed with no evident rationale, ADR-0065 unified them; new families should pick per-component, not assume unification is required.
|
|
378
378
|
|
|
379
|
-
**Sidecar emission**: `x-adiaui.category` field in `<name>.a2ui.json`. `packages/gen-ui/engine/retrieval/catalog.js`'s `buildCatalog()` reads this directly per entry
|
|
379
|
+
**Sidecar emission**: `x-adiaui.category` field in `<name>.a2ui.json`. `packages/gen-ui/engine/retrieval/catalog.js`'s `buildCatalog()` reads this directly per entry, no separate registration step.
|
|
380
380
|
|
|
381
381
|
---
|
|
382
382
|
|
|
383
|
-
## Semantic color-family axis
|
|
383
|
+
## Semantic color-family axis, two role-classes, two names (ADR-0044, ADR-0064)
|
|
384
384
|
|
|
385
385
|
Every component carries at most one STYLE axis and one FAMILY axis (the
|
|
386
386
|
semantic color family: `default | info | success | warning | danger`,
|
|
387
387
|
`+primary` where the role-class already carries brand emphasis), and every
|
|
388
388
|
enum value belongs to exactly one axis. The family axis's ATTRIBUTE NAME is
|
|
389
|
-
decided by role-class
|
|
389
|
+
decided by role-class, never one universal name (a same-name meaning-flip
|
|
390
390
|
is a silent-failure migration and poisons the trained corpus, per ADR-0044
|
|
391
391
|
LLD §3):
|
|
392
392
|
|
|
393
|
-
- **Role-class A
|
|
393
|
+
- **Role-class A, `variant` is unclaimed:** the family axis is named
|
|
394
394
|
`variant`. Badge/tag's ratified shape (ADR-0044), plus `rating-ui` and the
|
|
395
395
|
`variant`-only siblings (inline-message, feed-item, empty-state, menu-item,
|
|
396
396
|
progress-row).
|
|
397
|
-
- **Role-class B
|
|
397
|
+
- **Role-class B, an existing identity/style axis already claims the
|
|
398
398
|
selector slot:** the family axis is named `color`. Button's shape
|
|
399
399
|
(`variant`=style, `color`=family), extended by ADR-0064 to `text-ui`
|
|
400
400
|
(`variant`=typography role), `chart-ui`/`heatmap-ui` (`type`=kind),
|
|
401
401
|
`icon-ui` (`weight`=glyph style), `spinner-ui` (`variant`=animation), and
|
|
402
|
-
`toggle-scheme-ui`. Renames owed by this ruling (follow-on build, gh#1376
|
|
403
|
-
— not yet landed): `icon-ui[tone]` → `[color]`, `heatmap-ui[colorScheme]`
|
|
402
|
+
`toggle-scheme-ui`. Renames owed by this ruling (follow-on build, gh#1376, not yet landed): `icon-ui[tone]` → `[color]`, `heatmap-ui[colorScheme]`
|
|
404
403
|
→ `[color]`, `spinner-ui[tone]` → `[color]`.
|
|
405
404
|
|
|
406
|
-
`accent` is RETIRED from the family enum everywhere
|
|
405
|
+
`accent` is RETIRED from the family enum everywhere, ADR-0044 removed it
|
|
407
406
|
from badge/tag/button; ADR-0064 removes it from the seven stragglers
|
|
408
407
|
(text, chart, icon, heatmap, rating, spinner, toggle-scheme) with no
|
|
409
408
|
replacement value. Never mint `accent` in a new enum.
|
|
410
409
|
|
|
411
|
-
Two ratified non-family exceptions
|
|
410
|
+
Two ratified non-family exceptions, the name without the semantics:
|
|
412
411
|
|
|
413
|
-
- `swatch-ui[color]` / `noodles-ui[color]
|
|
412
|
+
- `swatch-ui[color]` / `noodles-ui[color]`, an arbitrary CSS color string,
|
|
414
413
|
not a semantic enum (ADR-0054 §11 exemption, unchanged).
|
|
415
|
-
- `spinner-ui[color]` (post-rename)
|
|
414
|
+
- `spinner-ui[color]` (post-rename), a closed contrast-mode enum
|
|
416
415
|
(`current | subtle | inverse`), NOT the family vocabulary; never assume it
|
|
417
416
|
accepts `info`/`success`/`warning`/`danger` by analogy.
|
|
418
417
|
|
|
419
418
|
---
|
|
420
419
|
|
|
421
|
-
## Catalog tiers
|
|
420
|
+
## Catalog tiers, L0–L4, `origin`, and the promotion rule (ADR-0050, ADR-0066)
|
|
422
421
|
|
|
423
|
-
ADR-0050's L0–L4 ladder is the ONLY tier grammar
|
|
422
|
+
ADR-0050's L0–L4 ladder is the ONLY tier grammar, never mint a second
|
|
424
423
|
manifest format. ADR-0066 refines it three ways:
|
|
425
424
|
|
|
426
|
-
- **`origin: primitive | module` on every L0 entry
|
|
425
|
+
- **`origin: primitive | module` on every L0 entry**, both YAML source
|
|
427
426
|
roots (web-components primitives AND web-modules composites) compile into
|
|
428
427
|
the same `catalog-a2ui_1_0.json` through one shared contract;
|
|
429
428
|
`derive-catalog-tiers.mjs` stamps which root an entry came from onto
|
|
430
429
|
`tier-index.json`. A module is legitimately a member of TWO rungs at two
|
|
431
430
|
grains: its component API (props/events/slots) is L0, its assembled shell
|
|
432
|
-
composition is L3
|
|
431
|
+
composition is L3, ruled correct, not a modeling defect.
|
|
433
432
|
- **The promotion rule, stated once:** patterns/zettel compositions are the
|
|
434
|
-
SOLE promotion source, and they enter the ladder at exactly one point
|
|
435
|
-
pattern → L1 widget, through `curate-l1-widgets.mjs`'s gates (which writes
|
|
433
|
+
SOLE promotion source, and they enter the ladder at exactly one point, pattern → L1 widget, through `curate-l1-widgets.mjs`'s gates (which writes
|
|
436
434
|
only `l1-widgets.json`). The higher rungs (L1 → L2 → L3 → L4) are AUTHORED
|
|
437
|
-
edges
|
|
435
|
+
edges, hand-written `tiers/l*-*.json` manifests whose `composes` reference
|
|
438
436
|
the rung below, reserved/unblocked per ADR-0050's own phasing; a module's
|
|
439
437
|
L3 membership comes from an authored L3 manifest, never from its yaml
|
|
440
438
|
(which contributes only the L0 entry + `origin`). There is no
|
|
441
439
|
patterns↔module edge, primitives and modules never "promote" into each
|
|
442
|
-
other, and nothing promotes automatically or in reverse
|
|
440
|
+
other, and nothing promotes automatically or in reverse, curation is the
|
|
443
441
|
one-way valve (ADR-0050: "corpus derives from catalogs, never the
|
|
444
442
|
reverse").
|
|
445
443
|
- **The two pattern-facing outputs stay separate by design:**
|
|
446
444
|
`site/patterns-index.json` / `pattern-index.md` are a generated,
|
|
447
445
|
developer-facing index over the FULL pattern/template census, intentionally
|
|
448
|
-
independent of the L0–L4 machine-validated schema
|
|
446
|
+
independent of the L0–L4 machine-validated schema, a different audience,
|
|
449
447
|
never a convergence gap to "fix".
|
|
450
448
|
|
|
451
|
-
(`status:` above is orthogonal to the tier ladder
|
|
449
|
+
(`status:` above is orthogonal to the tier ladder, tier = what an entry is
|
|
452
450
|
composed of; status = how much to trust its contract today.)
|
|
453
451
|
|
|
454
452
|
---
|
|
455
453
|
|
|
456
|
-
## `props:` field
|
|
454
|
+
## `props:` field, prop schemas
|
|
457
455
|
|
|
458
456
|
Each prop is a top-level key inside `props:`. The full prop schema:
|
|
459
457
|
|
|
@@ -473,13 +471,13 @@ props:
|
|
|
473
471
|
- ghost
|
|
474
472
|
```
|
|
475
473
|
|
|
476
|
-
### Synthesized universal props
|
|
474
|
+
### Synthesized universal props, `slot` / `hidden` / `ariaLive` / `traits`
|
|
477
475
|
|
|
478
476
|
`deriveProps()` (`scripts/build/derive-genui-catalog.mjs`) prepends three
|
|
479
477
|
props to every component's generated catalog schema before it ever reads a
|
|
480
478
|
yaml's own `props:` block: `slot: {type: string}`, `hidden: {type:
|
|
481
479
|
boolean}`, `ariaLive: {type: string}` (REQ-013 accessibility pair, gh#1353).
|
|
482
|
-
**No yaml SoT declares any of these
|
|
480
|
+
**No yaml SoT declares any of these**, they're synthesized, not authored,
|
|
483
481
|
and a sidecar that ever DOES declare one of these keys itself simply
|
|
484
482
|
overwrites the synthesized definition.
|
|
485
483
|
|
|
@@ -488,27 +486,26 @@ overwrites the synthesized definition.
|
|
|
488
486
|
ratified via PR #2524) rules that `traits: {type: string}` becomes a fourth
|
|
489
487
|
member of this synthesized set, carrying the same space-separated grammar
|
|
490
488
|
as the existing HTML `[traits="…"]` declarative attribute
|
|
491
|
-
(`.claude/docs/specs/traits.md`, "Method 3"
|
|
492
|
-
not a JSON array)
|
|
489
|
+
(`.claude/docs/specs/traits.md`, "Method 3", `"ripple confetti-burst"`,
|
|
490
|
+
not a JSON array), making `traits` legal on every component's A2UI wire
|
|
493
491
|
schema with no renderer change, and, once wired, checked by
|
|
494
492
|
`catalog-validator.js` against the live trait registry
|
|
495
493
|
(`packages/web-components/traits/_catalog.json`) with a **hard FAIL on an
|
|
496
494
|
unknown trait name** (the same rejection behavior the raw HTML mechanism
|
|
497
495
|
already has). As of this writing `deriveProps()` still synthesizes only the
|
|
498
|
-
three props above and `catalog-validator.js` has no trait-name check
|
|
499
|
-
gh#2513 tracks the build.
|
|
496
|
+
three props above and `catalog-validator.js` has no trait-name check, gh#2513 tracks the build.
|
|
500
497
|
|
|
501
498
|
### Sentinel-0 defaults and tag-promoting props (ADR-0102, 2026-09-01)
|
|
502
499
|
|
|
503
|
-
Not every escape hatch belongs on `CatalogComponentCommon
|
|
500
|
+
Not every escape hatch belongs on `CatalogComponentCommon`, a prop scoped
|
|
504
501
|
to one component's own semantics stays on that component's own yaml, even
|
|
505
502
|
when it changes the rendered tag. `text-ui`'s `level` (integer 0-6,
|
|
506
503
|
default `0`) is the worked example: `0` is the sentinel for "no
|
|
507
|
-
promotion, current behavior"
|
|
508
|
-
own `lines` prop already used (`lines: 0` = no clamp)
|
|
504
|
+
promotion, current behavior", the same `0 = off` convention `text-ui`'s
|
|
505
|
+
own `lines` prop already used (`lines: 0` = no clamp), and `1`-`6`
|
|
509
506
|
promotes the rendered element to a real native `<h1>`-`<h6>`, independent
|
|
510
507
|
of `variant` (which stays presentational-only: typography tokens, never a
|
|
511
|
-
tag). `deriveProps()` needs no change for this
|
|
508
|
+
tag). `deriveProps()` needs no change for this, a per-sidecar prop like
|
|
512
509
|
`level` already flows into the generated catalog schema generically; only
|
|
513
510
|
a `CatalogComponentCommon` universal (`slot`/`hidden`/`ariaLive`/`traits`,
|
|
514
511
|
above) needs a wire-schema edit. See ADR-0102 for the full contract
|
|
@@ -520,11 +517,11 @@ above) needs a wire-schema edit. See ADR-0102 for the full contract
|
|
|
520
517
|
|
|
521
518
|
| Use `required: true` | Don't use `required: true` |
|
|
522
519
|
| --- | --- |
|
|
523
|
-
| `field-ui.label
|
|
524
|
-
| `icon-ui.name
|
|
525
|
-
| `nav-item-ui.text
|
|
526
|
-
| `chart-ui.type
|
|
527
|
-
| `tabs-ui.value
|
|
520
|
+
| `field-ui.label`, no visible/accessible label without it | `button-ui.variant`, has a sensible default |
|
|
521
|
+
| `icon-ui.name`, nothing renders without it | `select-ui.placeholder`, useful but optional |
|
|
522
|
+
| `nav-item-ui.text`, empty nav item | `card-ui.size`, affects styling, not function |
|
|
523
|
+
| `chart-ui.type`, can't render a chart of "nothing" | `stat-ui.change-indicator`, optional enhancement |
|
|
524
|
+
| `tabs-ui.value`, needs an initial selected tab | `tag-ui.variant`, has a default |
|
|
528
525
|
|
|
529
526
|
**Heuristic**: ask "if I author `<my-component-ui></my-component-ui>` with nothing else, is the component **broken** or just **default-styled**?" If broken → mark required. If default-styled → don't.
|
|
530
527
|
|
|
@@ -540,11 +537,11 @@ above) needs a wire-schema edit. See ADR-0102 for the full contract
|
|
|
540
537
|
- `rating-ui.value`
|
|
541
538
|
- `tabs-ui.value`
|
|
542
539
|
|
|
543
|
-
**Sidecar emission**: `required: true` propagates to the JSON Schema `required` array in `<name>.a2ui.json`. The A2UI validator + MCP tools consume this array
|
|
540
|
+
**Sidecar emission**: `required: true` propagates to the JSON Schema `required` array in `<name>.a2ui.json`. The A2UI validator + MCP tools consume this array, correct marking improves validation quality on generated UI trees.
|
|
544
541
|
|
|
545
542
|
**Anti-pattern**: marking ALL props required because they all "have a useful value." That defeats the validation signal. `required` is a strict-failure constraint, not a "recommended" hint.
|
|
546
543
|
|
|
547
|
-
### `type: array
|
|
544
|
+
### `type: array`, `items.type` is LOAD-BEARING (gh#970)
|
|
548
545
|
|
|
549
546
|
An array prop's catalog mapping (components.mjs TKT-0010) branches on
|
|
550
547
|
`items.type`:
|
|
@@ -559,14 +556,14 @@ options:
|
|
|
559
556
|
dynamic: true
|
|
560
557
|
```
|
|
561
558
|
|
|
562
|
-
- `items: {type: object}` → `#/$defs/DynamicObjectList
|
|
559
|
+
- `items: {type: object}` → `#/$defs/DynamicObjectList`, rich option
|
|
563
560
|
objects validate.
|
|
564
|
-
- **`items` omitted → `#/$defs/DynamicStringList` silently
|
|
561
|
+
- **`items` omitted → `#/$defs/DynamicStringList` silently**, and the
|
|
565
562
|
dialect validator then REJECTS every real composition that passes rich
|
|
566
563
|
objects ("/options/0 must be string … oneOf"). command-ui and
|
|
567
564
|
combobox-ui both shipped this way; nothing caught it until the
|
|
568
565
|
`exit-gate.corpus` gate at v0.8.34 release pre-flight (that gate runs
|
|
569
|
-
in the release serial suite, NOT in PR CI
|
|
566
|
+
in the release serial suite, NOT in PR CI, the failure lands at cut
|
|
570
567
|
time, weeks after the yaml edit).
|
|
571
568
|
|
|
572
569
|
**Heuristic**: if the prop description says "Array of {…}", the yaml MUST
|
|
@@ -590,14 +587,14 @@ string-list schema is the exact silent-mismatch shape.
|
|
|
590
587
|
**Authoring contract**:
|
|
591
588
|
|
|
592
589
|
1. **DO NOT use these attribute names for any other purpose** (table column markers, sort-state, etc.) inside `<admin-shell>` descendants. The CSS rules will apply unintended layout. Use namespaced names instead (`data-page-col`, `data-sort-col`, `data-my-actions`).
|
|
593
|
-
2. **`admin-shell` ancestor is required**. An earlier dist CSS shipped bare global selectors that applied to ANY element with these attributes on ANY page loading `admin-shell.min.css
|
|
590
|
+
2. **`admin-shell` ancestor is required**. An earlier dist CSS shipped bare global selectors that applied to ANY element with these attributes on ANY page loading `admin-shell.min.css`, including `<table>` headers (silent layout breakage in Safari/WebKit). Source + dist now both prefix `admin-shell` ancestor. This is a hard constraint: the parent-tag selector is the only reliable CDN-safe scoping mechanism (LightningCSS strips `@scope` blocks).
|
|
594
591
|
3. **Outside `<admin-shell>`, these names have NO EFFECT**. If you need `[data-col]` semantics on a non-admin-shell page, you must author your own CSS (the helpers do not apply globally).
|
|
595
592
|
|
|
596
593
|
**Documented for consumers** in the adia-factory plugin's composition references (reserved layout-helper attribute names).
|
|
597
594
|
|
|
598
595
|
---
|
|
599
596
|
|
|
600
|
-
## `data-msg
|
|
597
|
+
## `data-msg-*`, exempt component-side config family (gh#1332/#1464, ADR-0060)
|
|
601
598
|
|
|
602
599
|
`data-msg-required` / `data-msg-pattern` / `data-msg-minlength` /
|
|
603
600
|
`data-msg-maxlength` / `data-msg-min` / `data-msg-max` / `data-msg-bad-input`
|
|
@@ -607,29 +604,28 @@ are read directly by form-associated components (`core/form.js`'s shared
|
|
|
607
604
|
`payment-method-form.class.js`) to override a native constraint-violation's
|
|
608
605
|
default message with a consumer-supplied string.
|
|
609
606
|
|
|
610
|
-
**Disposition: EXEMPT
|
|
607
|
+
**Disposition: EXEMPT, never declared as a yaml `states:`/`props:` entry.**
|
|
611
608
|
Both yaml surfaces this contract offers are the wrong shape for this family:
|
|
612
609
|
|
|
613
610
|
- `states:` declares **presence-boolean host state the component itself
|
|
614
611
|
reflects outward** (idle/loaded/error, this file's own §Reserved section's
|
|
615
|
-
neighbor pattern)
|
|
612
|
+
neighbor pattern), `data-msg-*` carries no state at all; it is a
|
|
616
613
|
consumer-authored string the component only ever *reads*, never sets.
|
|
617
614
|
- `props:` would need one string prop per validation-message key, repeated
|
|
618
|
-
across every one of the 7+ consuming components
|
|
615
|
+
across every one of the 7+ consuming components, but the read path is
|
|
619
616
|
`core/form.js`'s shared mixin, not any single component's own yaml SoT.
|
|
620
617
|
Declaring it per-component would multiply one shared mixin contract across
|
|
621
|
-
every consumer's yaml with no single owning SoT to declare it once
|
|
618
|
+
every consumer's yaml with no single owning SoT to declare it once, a
|
|
622
619
|
cross-cutting mixin-contract change, not a per-component yaml edit.
|
|
623
620
|
|
|
624
621
|
ADR-0060's own boundary discriminator (§Decision 3) already places this
|
|
625
622
|
family outside the trait-tier `data-*` ratification and explicitly routes it
|
|
626
|
-
"to gh#1332's Category A/D triage for its own converge-or-ratify call"
|
|
623
|
+
"to gh#1332's Category A/D triage for its own converge-or-ratify call": this
|
|
627
624
|
section IS that call. The family stays `data-*`, undeclared in any yaml,
|
|
628
625
|
with its contract documented at the shared source instead: `core/form.js`'s
|
|
629
626
|
own header JSDoc (the mixin all consumers share) and the canonical
|
|
630
627
|
`form-system` pattern doc (`packages/web-components/patterns/form-system/
|
|
631
|
-
form-system.examples.html`, rendered directly at `/site/patterns/form-system`)
|
|
632
|
-
— both already enumerate the full family with a worked example. A future
|
|
628
|
+
form-system.examples.html`, rendered directly at `/site/patterns/form-system`), both already enumerate the full family with a worked example. A future
|
|
633
629
|
architectural pass that wants to
|
|
634
630
|
promote this to a declared per-component contract needs its own ADR (the
|
|
635
631
|
scope is a mixin-wide contract change, not a small-ticket edit); nothing
|
|
@@ -648,14 +644,14 @@ node scripts/build/components.mjs --verify # same as above, direct invocation
|
|
|
648
644
|
The build:
|
|
649
645
|
|
|
650
646
|
1. Reads every `<name>.yaml` under `packages/web-components/components/` and `packages/web-modules/<cluster>/`
|
|
651
|
-
2. Hand-checks the source yaml in `compileComponent()
|
|
647
|
+
2. Hand-checks the source yaml in `compileComponent()`, missing `component:` and out-of-enum `status:` both throw (`components.mjs:255-260`). Amended 2026-08-16 per ADR-0057: it does NOT run `scripts/schemas/component.yaml.schema.json` as a validator (an earlier revision of this list claimed it did); the schema file is documentation + IDE contract only.
|
|
652
648
|
3. Emits `<name>.a2ui.json` (the sidecar) co-located with the yaml + js + css
|
|
653
649
|
4. Emits the `traits/_catalog.json` aggregate
|
|
654
650
|
5. `--verify` mode: re-runs steps 1-4 in-memory and fails if any sidecar drifts from disk content (CI hard-fail)
|
|
655
651
|
|
|
656
|
-
**Never hand-edit `<name>.a2ui.json
|
|
652
|
+
**Never hand-edit `<name>.a2ui.json`**: it's regenerated from the yaml. The yaml is the SoT.
|
|
657
653
|
|
|
658
|
-
**Downstream of the sidecars
|
|
654
|
+
**Downstream of the sidecars, two more derived artifacts (gh#970's release-PR stop):**
|
|
659
655
|
|
|
660
656
|
```bash
|
|
661
657
|
node scripts/build/derive-genui-catalog.mjs # genui's five opt-out-scoped catalogs derive FROM the sidecars
|
|
@@ -664,7 +660,7 @@ npm run check:genui-catalog # the drift gate that fails PR CI
|
|
|
664
660
|
|
|
665
661
|
Any yaml change that alters a sidecar's prop schemas STALES the genui
|
|
666
662
|
catalog. The main regen chain (`harvest:chunks` → `build:embeddings:chunks`
|
|
667
|
-
→ `build:patterns-index`) does NOT cover it
|
|
663
|
+
→ `build:patterns-index`) does NOT cover it, it's a separate derivation
|
|
668
664
|
with its own gate, and skipping it passes every local check that isn't
|
|
669
665
|
`check:genui-catalog` itself.
|
|
670
666
|
|
|
@@ -676,8 +672,8 @@ This is the canonical end-to-end procedure for creating a new component yaml + j
|
|
|
676
672
|
|
|
677
673
|
1. **Author `<name>.yaml`** with all required fields:
|
|
678
674
|
- `name:`, `tag:`, `component:`, `category:`, `version: 1`
|
|
679
|
-
- `status
|
|
680
|
-
- `description
|
|
675
|
+
- `status:`, pick from the table above
|
|
676
|
+
- `description:`, concrete one-paragraph
|
|
681
677
|
- `props:` with per-prop `type:`, `default:`, optional `required: true`, optional `enum:` / `values:`
|
|
682
678
|
- `events:`, `slots:`, `css-vars:` as applicable
|
|
683
679
|
2. **Author `<name>.js`** following the `UIElement` / `UIFormElement` patterns (see [code-style.md](code-style.md))
|
|
@@ -700,20 +696,20 @@ This is the canonical end-to-end procedure for creating a new component yaml + j
|
|
|
700
696
|
node scripts/docs/anatomy-sweep.mjs
|
|
701
697
|
```
|
|
702
698
|
|
|
703
|
-
This auto-generates the **canonical anatomy sections** (`slots`, `data-attrs`, `keyboard`, `css-vars`, `a2ui`, `related`) from the sidecar. The sweep is idempotent
|
|
699
|
+
This auto-generates the **canonical anatomy sections** (`slots`, `data-attrs`, `keyboard`, `css-vars`, `a2ui`, `related`) from the sidecar. The sweep is idempotent, skip-on-already-present, safe to re-run. Hand-author `accessibility` and any prop-demo sections; the sweep covers the schema-derivable sections only.
|
|
704
700
|
|
|
705
701
|
Canonical `data-property` vocabulary for `<section data-section data-property="X">`:
|
|
706
|
-
- `usage
|
|
707
|
-
- `props
|
|
708
|
-
- `slots
|
|
709
|
-
- `events
|
|
710
|
-
- `data-attrs
|
|
711
|
-
- `css-vars
|
|
712
|
-
- `keyboard
|
|
713
|
-
- `accessibility
|
|
714
|
-
- `a2ui
|
|
715
|
-
- `related
|
|
716
|
-
- `<prop-name
|
|
702
|
+
- `usage`, canonical worked example
|
|
703
|
+
- `props`, prop reference table
|
|
704
|
+
- `slots`, named-slot semantics
|
|
705
|
+
- `events`, fired events
|
|
706
|
+
- `data-attrs`, `data-*` attributes the component reads
|
|
707
|
+
- `css-vars`, CSS custom properties
|
|
708
|
+
- `keyboard`, keyboard interaction model
|
|
709
|
+
- `accessibility`, ARIA, screen-reader notes
|
|
710
|
+
- `a2ui`, A2UI runtime integration notes
|
|
711
|
+
- `related`, sibling/replacement components
|
|
712
|
+
- `<prop-name>`, visual demo for a specific prop
|
|
717
713
|
|
|
718
714
|
The sweep also **normalizes legacy section data-properties**: `Properties` → `props`, `Events` → `events`, `CSS Tokens` → `css-vars`, `Usage` → `usage`. Run with `--dry` first to preview changes:
|
|
719
715
|
|
|
@@ -734,10 +730,10 @@ After the playbook, the component is consumable by the docs site, the A2UI runti
|
|
|
734
730
|
|
|
735
731
|
## Cross-references
|
|
736
732
|
|
|
737
|
-
- `.claude/docs/specs/component-token-contract.md
|
|
738
|
-
- `.claude/docs/specs/component-implementation-patterns.md
|
|
739
|
-
- [code-style.md](code-style.md)
|
|
740
|
-
- [css-patterns.md](css-patterns.md)
|
|
741
|
-
- [api-contract.md](api-contract.md)
|
|
742
|
-
- [authoring-cycle.md](authoring-cycle.md)
|
|
743
|
-
- `scripts/schemas/component.yaml.schema.json
|
|
733
|
+
- `.claude/docs/specs/component-token-contract.md`, token/variant/mode contract
|
|
734
|
+
- `.claude/docs/specs/component-implementation-patterns.md`, implementation patterns
|
|
735
|
+
- [code-style.md](code-style.md), JS code style rules
|
|
736
|
+
- [css-patterns.md](css-patterns.md), light-DOM CSS cascade rules
|
|
737
|
+
- [api-contract.md](api-contract.md), props/events/slots conventions
|
|
738
|
+
- [authoring-cycle.md](authoring-cycle.md), the 5-step authoring procedure
|
|
739
|
+
- `scripts/schemas/component.yaml.schema.json`, JSON Schema (documented contract + IDE aid; not run as a validator, `compileComponent()` enforces only `component:` and the `status` enum, see §Build pipeline)
|