@adia-ai/adia-ui-forge 0.8.59 → 0.8.60
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 +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +28 -0
- package/package.json +1 -1
- package/plugin.yaml +1 -1
- package/references/contracts/a2ui-mcp-surface.md +1 -1
- package/scripts/lint-rules.generated.mjs +2079 -346
- package/skills/a2ui-maintenance/references/pipeline-overview.md +24 -0
- package/skills/gen-ui-review/scripts/gen-review-decompose.mjs +27 -34
- package/skills/gen-ui-review/scripts/overflow-detect.generated.mjs +101 -0
- package/skills/package-release/references/cut-procedure.md +49 -5
- package/skills/package-release/references/recovery-paths.md +20 -0
- package/skills/package-release/scripts/bump.mjs +36 -6
- package/skills/package-release/scripts/release-pack.mjs +424 -45
- package/skills/primitive-authoring/references/yaml-contract.md +106 -9
|
@@ -89,13 +89,26 @@ check) is unaffected either way — it only checks for a slot literally named
|
|
|
89
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
|
-
non-empty list of catalog `component:` names (NOT tags) naming the
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
non-empty list of catalog `component:` names (NOT tags) naming the parents
|
|
93
|
+
this component may sit under / the direct children it may contain. The
|
|
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
96
|
means unconstrained** — never write an empty list (that would mean "allowed
|
|
97
97
|
nowhere"; the build refuses it).
|
|
98
98
|
|
|
99
|
+
`allowedParents` matches the nearest custom-element ancestor, not the
|
|
100
|
+
immediate DOM parent (gh#3310): the generated lint rule's
|
|
101
|
+
`compositionFindings()` walks up past native (non-hyphenated) wrapper
|
|
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
|
+
root. This mirrors Light DOM's own composition reality (AGENTS.md: CSS
|
|
105
|
+
positions by tag + ancestor + DOM order) — a wrapper interposed for layout
|
|
106
|
+
or semantics (a `<section>` inside a card, a `<td>` in a table body) doesn't
|
|
107
|
+
change a component's logical host. `allowedChildren`, by contrast, still
|
|
108
|
+
matches DIRECT children only — a named-slot child that should be exempt
|
|
109
|
+
from the default-slot list is a separate, open gap (gh#3308), not addressed
|
|
110
|
+
by this semantics change.
|
|
111
|
+
|
|
99
112
|
```yaml
|
|
100
113
|
a2ui:
|
|
101
114
|
allowedParents:
|
|
@@ -112,6 +125,35 @@ children). A parent that adopts items through wrappers (menu.class.js's
|
|
|
112
125
|
deliberate descendant query) must NOT constrain — a declared constraint
|
|
113
126
|
stricter than the source is a defect, not documentation.
|
|
114
127
|
|
|
128
|
+
**`allowedChildren` is a default-slot-only check (gh#3308).** A direct
|
|
129
|
+
child carrying ANY `slot=` attribute is a sibling-level named slot, not a
|
|
130
|
+
default-slot member — the lint-side matcher (`compositionFindings`)
|
|
131
|
+
exempts it from `allowedChildren` entirely, regardless of the slot's name.
|
|
132
|
+
This is why menu-ui can declare `allowedChildren: [MenuItem, MenuDivider,
|
|
133
|
+
MenuLabel]` for its default slot while still accepting an arbitrary
|
|
134
|
+
focusable element on `slot="trigger"` ("typically button-ui, but any
|
|
135
|
+
focusable element works") without a false positive. When a named slot
|
|
136
|
+
*should* be constrained too (rare — most named slots exist precisely
|
|
137
|
+
because their content varies), add an `allowedChildrenBySlot:` map
|
|
138
|
+
alongside `allowedChildren:`, keyed by slot name, same catalog-name-list
|
|
139
|
+
shape:
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
a2ui:
|
|
143
|
+
allowedChildren:
|
|
144
|
+
- MenuItem
|
|
145
|
+
- MenuDivider
|
|
146
|
+
- MenuLabel
|
|
147
|
+
allowedChildrenBySlot:
|
|
148
|
+
trigger: # only if the trigger slot ITSELF needs constraining
|
|
149
|
+
- ButtonUI
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
A slot with no entry in `allowedChildrenBySlot` (or the key omitted
|
|
153
|
+
entirely) stays unconstrained by design — this is the common case, and
|
|
154
|
+
matches "omitted means unconstrained" for `allowedChildren`/`allowedParents`
|
|
155
|
+
above.
|
|
156
|
+
|
|
115
157
|
Pipeline: `components.mjs` validates the shape per-yaml, cross-checks every
|
|
116
158
|
referenced name against the full catalog on a full build, and forwards the
|
|
117
159
|
lists onto `x-adiaui` → `catalog-a2ui_1_0.json`.
|
|
@@ -122,16 +164,71 @@ per gh#2116) across the five opt-out-scoped catalogs (`adia.core.json`,
|
|
|
122
164
|
`adia.shells.json`, gh#2211/ADR-0093), where the vendored `@genui/core`
|
|
123
165
|
validator enforces them (`UNALLOWED_PARENT`/`UNALLOWED_CHILD`). Module-tier
|
|
124
166
|
yamls (web-modules) now carry a v1.0 sidecar too and land in `adia.shells`.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
`
|
|
128
|
-
|
|
129
|
-
|
|
167
|
+
`allowedChildrenBySlot` (gh#3308) is NOT part of this catalog/sidecar
|
|
168
|
+
pipeline — `components.mjs` never reads it, it never lands in
|
|
169
|
+
`x-adiaui`/`catalog-a2ui_1_0.json`, and the A2UI v1.0 protocol validator
|
|
170
|
+
never enforces it. It exists purely for the lint-side check below.
|
|
171
|
+
|
|
172
|
+
A non-empty `allowedParents`/`allowedChildren`/`allowedChildrenBySlot`
|
|
173
|
+
generates an enforced lint rule (LLD-0016 §C4, gh#2647):
|
|
174
|
+
`scripts/build/gen-composition-rules.mjs` emits `scripts/lint/
|
|
130
175
|
rules/generated/composition/<name>.mjs`, which flags a markup file where
|
|
131
|
-
the tag nests under (or contains) a non-declared tag
|
|
176
|
+
the tag nests under (or contains) a non-declared tag — `allowedChildren`
|
|
177
|
+
checked against default-slot children only, `allowedChildrenBySlot`
|
|
178
|
+
against the matching named-slot children (see above). Advisory (`warn`)
|
|
132
179
|
until a corpus-wide rollout promotes it (`npm run build:composition-rules`
|
|
133
180
|
/ `check:composition-rules-fresh`).
|
|
134
181
|
|
|
182
|
+
### `a2ui.noCompositionConstraint:`: the audited "no contract needed" verdict (lld-0029 C2a, PR #3456)
|
|
183
|
+
|
|
184
|
+
The third disposition a yaml can carry. Where `allowedParents` /
|
|
185
|
+
`allowedChildren` declare a containment edge, `noCompositionConstraint`
|
|
186
|
+
records that the authoring-rule audit above was actually run (read
|
|
187
|
+
`<name>.class.js` for `querySelector` / `closest` / `this.children`
|
|
188
|
+
child-tag expectations, then test any parent/child hypothesis against real
|
|
189
|
+
markup in `apps/`, `site/`, `catalog/`, `packages/web-components/patterns/`)
|
|
190
|
+
and found no constraint worth declaring. Its whole purpose is to let a
|
|
191
|
+
reader, or a gate, tell "audited, categorically needs none" apart from
|
|
192
|
+
"never audited". Do not write it as a shortcut: if the audit turns up a
|
|
193
|
+
real constraint, the fix is a genuine `allowedParents` / `allowedChildren`
|
|
194
|
+
addition, not this marker.
|
|
195
|
+
|
|
196
|
+
Shape (`scripts/schemas/component.yaml.schema.json`, `a2ui.noCompositionConstraint`):
|
|
197
|
+
an object with two required keys and nothing else. `reason` is the verdict
|
|
198
|
+
quoted from the disposition table (schema `minLength: 8`); `ticket` is the
|
|
199
|
+
issue whose table recorded it (`^gh#[0-9]+$`). As with every other schema
|
|
200
|
+
constraint (ADR-0057), the shape is IDE-visible only: `compileComponent()`
|
|
201
|
+
never reads this key, so a malformed block does not stop the build.
|
|
202
|
+
|
|
203
|
+
Real example, `packages/web-components/components/badge/badge.yaml`:
|
|
204
|
+
|
|
205
|
+
```yaml
|
|
206
|
+
a2ui:
|
|
207
|
+
noCompositionConstraint:
|
|
208
|
+
reason: 'Referenced generically from a dozen+ unrelated components, not scoped to one parent; own rule says positioning, not ancestry.'
|
|
209
|
+
ticket: 'gh#3270'
|
|
210
|
+
rules:
|
|
211
|
+
- 'Use for small status/count labels attached to another element (notification counts, status pills, version tags).'
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Relationship to the two lists. A yaml carries either the marker or a
|
|
215
|
+
containment list, never both. This is now enforced (gh#3497), not just
|
|
216
|
+
convention: `component.yaml.schema.json` declares the two mutually
|
|
217
|
+
exclusive via the `a2ui` object's own `not` clause, and
|
|
218
|
+
`compileCompositionConstraints()` in `scripts/build/components.mjs` throws
|
|
219
|
+
at build time, naming the file and the offending field, when a yaml
|
|
220
|
+
declares both. `npm run check:components-valid` (part of `npm run
|
|
221
|
+
build:components`) is where that throw surfaces.
|
|
222
|
+
|
|
223
|
+
Pipeline: none. The marker is a yaml-only annotation with no sidecar,
|
|
224
|
+
`x-adiaui`, catalog, or generated-lint-rule forwarding (lld-0029 C2a, by
|
|
225
|
+
design), so a PR that only adds it changes no derived artifact and commits
|
|
226
|
+
no regen. The planned `check:composition-coverage` gate (lld-0029 C3,
|
|
227
|
+
`scripts/verify/check-composition-coverage.mjs`, not landed as of
|
|
228
|
+
2026-09-04) fails any yaml whose `a2ui` block has none of `allowedParents`,
|
|
229
|
+
`allowedChildren`, or `noCompositionConstraint`, so the marker counts as
|
|
230
|
+
coverage exactly as either list does.
|
|
231
|
+
|
|
135
232
|
---
|
|
136
233
|
|
|
137
234
|
## `examples:` field — a2ui example ids (semantic-id grammar, gh#2492)
|