@adia-ai/a2ui 0.8.37
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 +1073 -0
- package/README.md +99 -0
- package/a2ui.schema.d.ts +192 -0
- package/controllers/accordion.js +73 -0
- package/controllers/base.js +68 -0
- package/controllers/data-stream.js +281 -0
- package/controllers/form.js +81 -0
- package/controllers/index.js +6 -0
- package/controllers/selection.js +82 -0
- package/controllers/state-machine.js +135 -0
- package/controllers/toggle.js +40 -0
- package/dockables/action.d.ts +55 -0
- package/dockables/action.js +152 -0
- package/dockables/base.d.ts +26 -0
- package/dockables/base.js +30 -0
- package/dockables/controller.d.ts +35 -0
- package/dockables/controller.js +97 -0
- package/dockables/data-source.d.ts +35 -0
- package/dockables/data-source.js +103 -0
- package/dockables/index.d.ts +21 -0
- package/dockables/index.js +6 -0
- package/dockables/lifecycle.d.ts +38 -0
- package/dockables/lifecycle.js +84 -0
- package/dockables/provider.d.ts +28 -0
- package/dockables/provider.js +59 -0
- package/index.d.ts +64 -0
- package/index.js +54 -0
- package/package.json +89 -0
- package/prop-apply.d.ts +13 -0
- package/prop-apply.js +113 -0
- package/registry.d.ts +17 -0
- package/registry.js +418 -0
- package/renderer.d.ts +67 -0
- package/renderer.js +715 -0
- package/stream.d.ts +62 -0
- package/stream.js +521 -0
- package/surface-manifest.d.ts +73 -0
- package/surface-manifest.js +294 -0
- package/surface.d.ts +72 -0
- package/surface.js +222 -0
- package/types.d.ts +26 -0
- package/validate/CHANGELOG.md +1005 -0
- package/validate/README.md +146 -0
- package/validate/index.d.ts +4 -0
- package/validate/index.js +12 -0
- package/validate/validator.d.ts +4 -0
- package/validate/validator.js +1232 -0
- package/wire-factory.d.ts +15 -0
- package/wire-factory.js +134 -0
- package/wiring-engine.d.ts +61 -0
- package/wiring-engine.js +209 -0
- package/wiring-registry.d.ts +80 -0
- package/wiring-registry.js +342 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# `@adia-ai/a2ui/validate`
|
|
2
|
+
|
|
3
|
+
> Formerly the `@adia-ai/a2ui-validator` package; renamed at ADR-0048 P3,
|
|
4
|
+
> which moved the protocol-side half here as a subpath of `@adia-ai/a2ui`.
|
|
5
|
+
> The catalog-aware validator and the LLM semantic judge moved the other way
|
|
6
|
+
> in P1 — they are now `@adia-ai/gen-ui/validate/catalog` and
|
|
7
|
+
> `@adia-ai/gen-ui/validate/semantic`. Sections below that describe those two
|
|
8
|
+
> stages are history, kept for the record.
|
|
9
|
+
|
|
10
|
+
JSON Schema structural validation for A2UI (Agent-to-UI) protocol messages —
|
|
11
|
+
shape, types, required fields, and wiring/registry coherence. Its only import
|
|
12
|
+
is this package's own registry, which is what lets `@adia-ai/a2ui` ship with
|
|
13
|
+
zero dependencies. Originally extracted from
|
|
14
|
+
[`@adia-ai/a2ui-compose`](../../gen-ui/compose/) so non-compose tooling
|
|
15
|
+
(tests, MCP validator tools, CI gates) could depend on validation without
|
|
16
|
+
pulling the full generator graph.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @adia-ai/a2ui-validator
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { validateSchema } from '@adia-ai/a2ui-validator';
|
|
28
|
+
|
|
29
|
+
const messages = [/* A2UI protocol messages */];
|
|
30
|
+
const result = validateSchema(messages);
|
|
31
|
+
if (!result.valid) {
|
|
32
|
+
console.error(result.errors);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Catalog-aware validation (component exists + props match YAML):
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
import { validateAgainstCatalog } from '@adia-ai/a2ui-validator/catalog';
|
|
40
|
+
|
|
41
|
+
const result = validateAgainstCatalog(messages, catalog);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## What's here
|
|
45
|
+
|
|
46
|
+
- **Structural validator** — JSON Schema validation against the A2UI
|
|
47
|
+
protocol schema (message shape, required fields, enum constraints).
|
|
48
|
+
- **Catalog validator** — semantic checks: does this component exist in
|
|
49
|
+
the catalog? Do its props match the YAML contract? Are references
|
|
50
|
+
resolvable?
|
|
51
|
+
- **Semantic validator** (optional, shadow-mode) — LLM-judged output
|
|
52
|
+
quality against a rubric; cached on disk by content hash.
|
|
53
|
+
|
|
54
|
+
## Catalog loading + degradation (gh#742, gh#748)
|
|
55
|
+
|
|
56
|
+
The catalog validator needs the v0.9 component catalog. **First try is the bare
|
|
57
|
+
specifier `@adia-ai/a2ui-corpus`** — that package's `.` export IS
|
|
58
|
+
`catalog-a2ui_0_9.json`, and it is a declared dependency of this package, so a
|
|
59
|
+
plain `npm i @adia-ai/a2ui-validator` install resolves it with no repo layout,
|
|
60
|
+
no static asset server and no bundler config (gh#748: before this, every
|
|
61
|
+
tarball consumer validated in degraded mode, because all three fallbacks below
|
|
62
|
+
resolve `../corpus/...` relative to this module and only work through workspace
|
|
63
|
+
symlinks). On Node, a `createRequire(...).resolve()` + `fs.readFile` retry
|
|
64
|
+
covers runtimes that reject JSON import attributes (`source: 'package-fs'`).
|
|
65
|
+
|
|
66
|
+
The relative-path chain stays as the in-repo / browser fallback. Node reads it
|
|
67
|
+
from disk; the browser **fetches** it module-relative
|
|
68
|
+
(`fetch(new URL('../corpus/catalog-a2ui_0_9.json', import.meta.url))`) — the
|
|
69
|
+
same idiom as `retrieval/catalog.js` and `compose/strategies/monolithic/_shared.js`.
|
|
70
|
+
A spec-correct `import(..., { with: { type: 'json' } })` cannot be the primary
|
|
71
|
+
path: Vite's dev server serves JSON as `text/javascript` and the browser's
|
|
72
|
+
strict MIME check rejects it, so under `npm run dev` that import always throws.
|
|
73
|
+
It remains a second try for bundlers that inline the JSON.
|
|
74
|
+
|
|
75
|
+
If every path fails, the validator degrades **loudly**: one `console.warn` per
|
|
76
|
+
session naming the lost coverage, plus queryable state —
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { getCatalogStatus } from '@adia-ai/a2ui-validator/catalog';
|
|
80
|
+
|
|
81
|
+
getCatalogStatus(); // { loaded, degraded, source: 'package'|'package-fs'|'node-fs'|'fetch'|'import-attributes'|null, reason }
|
|
82
|
+
globalThis.__a2uiValidatorCatalogStatus; // same object, for a dev console / host overlay
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`validateMessages()` also returns `catalogDegraded`. When it is `true`, a green
|
|
86
|
+
`valid` means nothing was structurally checked — absence of evidence, not
|
|
87
|
+
evidence of absence.
|
|
88
|
+
|
|
89
|
+
## The 18 weighted checks
|
|
90
|
+
|
|
91
|
+
`validator.js` runs 18 weighted checks that sum to 100. Default pass
|
|
92
|
+
threshold is `valid: score ≥ 70`. The compose eval harness uses
|
|
93
|
+
`combined: 0.6 × validation + 0.4 × semantic` at threshold 80, so a
|
|
94
|
+
high structural score with low semantic still gets rejected at
|
|
95
|
+
compose time.
|
|
96
|
+
|
|
97
|
+
| Check | Weight | What it catches |
|
|
98
|
+
|---|---:|---|
|
|
99
|
+
| `intentAlignment` | 13 | Output addresses the intent (LLM-free heuristic) |
|
|
100
|
+
| `allTypesRegistered` | 9 | Every `component` value exists in the runtime registry |
|
|
101
|
+
| `noOrphanedChildren` | 9 | Every `children` ID resolves to a real node |
|
|
102
|
+
| `validMessageFormat` | 8 | Top-level shape is valid A2UI |
|
|
103
|
+
| `hasRootComponent` | 7 | Exactly one root |
|
|
104
|
+
| `noBareDivs` | 7 | Use semantic primitives (`<card-ui>`, `<col-ui>`) not bare `<div>` |
|
|
105
|
+
| `cardStructure` | 6 | Card pattern: header / body / footer hierarchy |
|
|
106
|
+
| `flatAdjacency` | 5 | Component IDs are flat (no nested arrays) |
|
|
107
|
+
| `noInlineLayout` | 5 | Use `<col-ui>` / `<row-ui>` / `<grid-ui>` not inline `style="display:flex"` |
|
|
108
|
+
| `textContentSet` | 5 | Text components have actual content |
|
|
109
|
+
| `idUniqueness` | 5 | No duplicate IDs |
|
|
110
|
+
| `interactiveHasLabel` | 4 | Buttons / inputs have accessible labels |
|
|
111
|
+
| `imagesHaveAlt` | 3 | `<img>` has `alt` attribute |
|
|
112
|
+
| `headingHierarchy` | 3 | `h1` → `h2` → `h3` monotonic |
|
|
113
|
+
| `gridVsColumn` | 3 | Right primitive for the layout |
|
|
114
|
+
| `landmarkStructure` | 3 | Page-level `main` / `nav` / `footer` |
|
|
115
|
+
| `noHardcodedColors` | 3 | Token contract — `--a-chrome-*` only |
|
|
116
|
+
| `tabStructure` | 2 | `<tabs-ui>` has `<tab-ui>` children |
|
|
117
|
+
| **Total** | **100** | |
|
|
118
|
+
|
|
119
|
+
**Wiring checks** are tracked separately (don't roll into the component
|
|
120
|
+
score) and sum to 13: `wiringControllersExist` (3), `wiringHostsExist`
|
|
121
|
+
(3), `wiringHandlersExist` (3), `wiringSourcesExist` (2),
|
|
122
|
+
`wiringDataPathsValid` (2).
|
|
123
|
+
|
|
124
|
+
## Status
|
|
125
|
+
|
|
126
|
+
- **Structural + catalog validation** — shipped, default-on. Single
|
|
127
|
+
source of truth for component-shape contracts in A2UI messages.
|
|
128
|
+
- **Semantic validator (Phases 1 + 2)** — shipped. LLM-judge with
|
|
129
|
+
`dominantPattern` (0.5 weight) + `requiredCapabilities` (0.35) +
|
|
130
|
+
`forbiddenNoise` (0.15). Combined-gating opt-in via
|
|
131
|
+
`--gate-mode combined` to the eval harness.
|
|
132
|
+
- **Phases 3–5** — planned per [`semantic-validator.md`](../../../.claude/docs/specs/semantic-validator.md):
|
|
133
|
+
rubric expansion, persisted per-intent thresholds, and judge
|
|
134
|
+
ensembling.
|
|
135
|
+
|
|
136
|
+
## Runtime
|
|
137
|
+
|
|
138
|
+
- `ajv` + `ajv-formats` for structural validation.
|
|
139
|
+
- `@adia-ai/a2ui-runtime` for the registry shape.
|
|
140
|
+
|
|
141
|
+
## Related
|
|
142
|
+
|
|
143
|
+
- Spec: [`.claude/docs/specs/semantic-validator.md`](../../../.claude/docs/specs/semantic-validator.md) — canonical design narrative
|
|
144
|
+
- Audit: `.claude/docs/reports/audit-validator-2026-05-06.md` — 226-line deep-dive with check-by-check rationale + recalibration notes
|
|
145
|
+
- Repo: [`adiahealth/gen-ui-kit`](https://github.com/adiahealth/gen-ui-kit)
|
|
146
|
+
- CHANGELOG: [`CHANGELOG.md`](./CHANGELOG.md)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @adia-ai/a2ui/validate — barrel.
|
|
3
|
+
*
|
|
4
|
+
* Structural validation for A2UI protocol messages — `validateSchema`
|
|
5
|
+
* (shape, types, required fields, wiring/registry coherence).
|
|
6
|
+
*
|
|
7
|
+
* Catalog-aware validation (`validateMessages`) and the LLM semantic judge
|
|
8
|
+
* moved to @adia-ai/gen-ui in ADR-0048 P1: import them from
|
|
9
|
+
* `@adia-ai/gen-ui/validate/catalog` and `@adia-ai/gen-ui/validate/semantic`.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export * from './validator.js';
|