@adia-ai/adia-ui-factory 0.2.2 → 0.2.4
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 +12 -3
- package/.mcp.json +1 -1
- package/CHANGELOG.md +12 -0
- package/README.md +24 -1
- package/bin/adia-scaffold +93 -13
- package/package.json +1 -1
- package/references/shell-embed.md +10 -0
- package/references/spa-architecture.md +7 -0
- package/skills/adia-ui-kit/CHANGELOG.md +41 -0
- package/skills/adia-ui-kit/SKILL.md +442 -0
- package/skills/adia-ui-kit/assets/figma-make/guidelines/Guidelines.md +87 -0
- package/skills/adia-ui-kit/assets/figma-make/guidelines/components.md +142 -0
- package/skills/adia-ui-kit/assets/figma-make/guidelines/styles.md +118 -0
- package/skills/adia-ui-kit/assets/figma-make/guidelines/tokens.md +120 -0
- package/skills/adia-ui-kit/assets/team-scaffold/archive-README.md +30 -0
- package/skills/adia-ui-kit/assets/team-scaffold/drafts-README.md +57 -0
- package/skills/adia-ui-kit/assets/team-scaffold/inbox-README.md +76 -0
- package/skills/adia-ui-kit/assets/team-scaffold/outbox-README.md +46 -0
- package/skills/adia-ui-kit/assets/team-scaffold/team-root.README.md +51 -0
- package/skills/adia-ui-kit/assets/team-scaffold/tickets-README.md +208 -0
- package/skills/adia-ui-kit/assets/team-scaffold/tickets-REGISTRY.md +81 -0
- package/skills/adia-ui-kit/assets/templates/AGENTS.template.md +128 -0
- package/skills/adia-ui-kit/assets/templates/CLAUDE.template.md +1 -0
- package/skills/adia-ui-kit/assets/templates/FEEDBACK-OMISSIONS-DEFENSE.template.md +150 -0
- package/skills/adia-ui-kit/assets/templates/FEEDBACK.template.md +213 -0
- package/skills/adia-ui-kit/assets/templates/RESPONSE.template.md +114 -0
- package/skills/adia-ui-kit/assets/templates/figma-make-guidelines.md +90 -0
- package/skills/adia-ui-kit/evals/adversarial-content-trust.json +83 -0
- package/skills/adia-ui-kit/evals/evals.json +55 -0
- package/skills/adia-ui-kit/evals/routing-corpus.json +121 -0
- package/skills/adia-ui-kit/evals/teach-routing-cases.json +92 -0
- package/skills/adia-ui-kit/references/capabilities.md +245 -0
- package/skills/adia-ui-kit/references/catalog-lookup.md +186 -0
- package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v1.md +8 -0
- package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v2.md +3585 -0
- package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v3.md +1899 -0
- package/skills/adia-ui-kit/references/common-gotchas-consumer.md +522 -0
- package/skills/adia-ui-kit/references/component-literacy.md +291 -0
- package/skills/adia-ui-kit/references/composition.md +245 -0
- package/skills/adia-ui-kit/references/correction-loop.md +462 -0
- package/skills/adia-ui-kit/references/css-policy.md +343 -0
- package/skills/adia-ui-kit/references/decision-model.md +158 -0
- package/skills/adia-ui-kit/references/diagnostic-output.md +57 -0
- package/skills/adia-ui-kit/references/docs-catalog.md +239 -0
- package/skills/adia-ui-kit/references/exclusions.md +225 -0
- package/skills/adia-ui-kit/references/feedback-authoring.md +466 -0
- package/skills/adia-ui-kit/references/figma-make.md +244 -0
- package/skills/adia-ui-kit/references/flows-auth.md +307 -0
- package/skills/adia-ui-kit/references/flows-content.md +206 -0
- package/skills/adia-ui-kit/references/flows-data.md +348 -0
- package/skills/adia-ui-kit/references/flows-interaction.md +181 -0
- package/skills/adia-ui-kit/references/flows-shells.md +336 -0
- package/skills/adia-ui-kit/references/gap-detection.md +266 -0
- package/skills/adia-ui-kit/references/harness.md +284 -0
- package/skills/adia-ui-kit/references/loading-protocol.md +406 -0
- package/skills/adia-ui-kit/references/local-link.md +198 -0
- package/skills/adia-ui-kit/references/mcp.md +401 -0
- package/skills/adia-ui-kit/references/migration.md +116 -0
- package/skills/adia-ui-kit/references/mission.md +194 -0
- package/skills/adia-ui-kit/references/mode-routing.md +298 -0
- package/skills/adia-ui-kit/references/patterns-agent.md +223 -0
- package/skills/adia-ui-kit/references/patterns-data.md +1065 -0
- package/skills/adia-ui-kit/references/patterns-forms.md +223 -0
- package/skills/adia-ui-kit/references/patterns-layout.md +326 -0
- package/skills/adia-ui-kit/references/patterns-recipes.md +1416 -0
- package/skills/adia-ui-kit/references/patterns-shells.md +1097 -0
- package/skills/adia-ui-kit/references/patterns-traits.md +259 -0
- package/skills/adia-ui-kit/references/patterns-wiring.md +339 -0
- package/skills/adia-ui-kit/references/pev-rationale.md +137 -0
- package/skills/adia-ui-kit/references/reasoning-gate.md +146 -0
- package/skills/adia-ui-kit/references/reasoning-methodologies.md +112 -0
- package/skills/adia-ui-kit/references/recon.md +192 -0
- package/skills/adia-ui-kit/references/rendering-model.md +431 -0
- package/skills/adia-ui-kit/references/response-authoring.md +398 -0
- package/skills/adia-ui-kit/references/session-log-schema.md +203 -0
- package/skills/adia-ui-kit/references/session-log-template.md +118 -0
- package/skills/adia-ui-kit/references/setup.md +652 -0
- package/skills/adia-ui-kit/references/skill-hygiene.md +135 -0
- package/skills/adia-ui-kit/references/spec-to-ui-reasoning.md +394 -0
- package/skills/adia-ui-kit/references/state.md +229 -0
- package/skills/adia-ui-kit/references/teach-protocol.md +421 -0
- package/skills/adia-ui-kit/references/theme.md +142 -0
- package/skills/adia-ui-kit/references/version-check.md +69 -0
- package/skills/adia-ui-kit/scripts/audit-decision-trace.mjs +198 -0
- package/skills/adia-ui-kit/scripts/audit-kit-roster.mjs +366 -0
- package/skills/adia-ui-kit/scripts/changelog-archive.mjs +126 -0
- package/skills/adia-ui-kit/scripts/check-adia-versions.py +404 -0
- package/skills/adia-ui-kit/scripts/run-skill-evals.mjs +358 -0
- package/skills/adia-ui-kit/scripts/validate-session-log.mjs +242 -0
- package/skills/adia-ui-kit/skill.json +102 -0
- package/skills/adia-ui-migration/CHANGELOG.md +47 -0
- package/skills/adia-ui-migration/SKILL.md +381 -0
- package/skills/adia-ui-migration/skill.json +29 -0
- package/skills/adia-ui-spa/SKILL.md +1 -1
- package/skills/adia-ui-verify/SKILL.md +2 -2
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gap-detection
|
|
3
|
+
load-when: During consultant-posture recon — when classifying gaps between consumer repo state and substrate's current shipped capability. Four gap classes + detection recipes.
|
|
4
|
+
load-size-tokens: ~3,000
|
|
5
|
+
required-for:
|
|
6
|
+
- mode 5 (consultant)
|
|
7
|
+
- audit output authoring
|
|
8
|
+
- remediation plan ranking
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# §GapDetection — Four gap classes, four detection recipes
|
|
12
|
+
|
|
13
|
+
Every finding from §Recon falls into one of four classes. Each class
|
|
14
|
+
has a distinct mechanism, a distinct detection recipe, and a distinct
|
|
15
|
+
remediation shape. **Gap class 0 is a build-blocker** — Gap classes
|
|
16
|
+
1-3 only matter if class 0 passes.
|
|
17
|
+
|
|
18
|
+
### Gap class 0 — Manifest gap (build-blocker)
|
|
19
|
+
|
|
20
|
+
**Mechanism:** consumer's `src/` imports `@adia-ai/*` but
|
|
21
|
+
`package.json` declares zero `@adia-ai/*` deps. `npm install` honors
|
|
22
|
+
the manifest (which says nothing) → `node_modules/@adia-ai/` doesn't
|
|
23
|
+
exist → vite's bare-specifier resolver fails at `npm run dev`. The
|
|
24
|
+
error message ("Are they installed?") is misleading — they were never
|
|
25
|
+
*declared*.
|
|
26
|
+
|
|
27
|
+
This commonly happens when:
|
|
28
|
+
|
|
29
|
+
- A new consumer repo is scaffolded (e.g. `claims-ui-v9`) but the agent
|
|
30
|
+
authored imports before the operator added the deps.
|
|
31
|
+
- A consumer copies `src/main.ts` from a sibling repo without copying
|
|
32
|
+
the corresponding `package.json` entries.
|
|
33
|
+
- A dep was removed from `package.json` (cleanup) but the imports
|
|
34
|
+
weren't swept first.
|
|
35
|
+
|
|
36
|
+
**Detection:**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# (a) Are there @adia-ai/* imports in src/?
|
|
40
|
+
grep -rEn "from ['\"]@adia-ai/" --include='*.ts' --include='*.js' \
|
|
41
|
+
--include='*.tsx' --include='*.jsx' --include='*.vue' --include='*.svelte' \
|
|
42
|
+
src/ 2>/dev/null | wc -l
|
|
43
|
+
|
|
44
|
+
# (b) Are there @adia-ai/* declarations in package.json?
|
|
45
|
+
node -e "const p=require('./package.json'); const deps={...p.dependencies, ...p.devDependencies}; console.log(Object.keys(deps).filter(k=>k.startsWith('@adia-ai/')).length)"
|
|
46
|
+
|
|
47
|
+
# Gap class 0 fires iff (a) > 0 AND (b) === 0.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Interpretation:**
|
|
51
|
+
|
|
52
|
+
| (a) imports | (b) declared | Verdict |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| 0 | 0 | Clean (no use, no declarations) |
|
|
55
|
+
| N>0 | M>0 | Normal — check Gap class 1 (version drift) |
|
|
56
|
+
| 0 | M>0 | Unused declarations — sweep candidate (low priority) |
|
|
57
|
+
| **N>0** | **0** | **Manifest gap — HALT before composing further UI** |
|
|
58
|
+
|
|
59
|
+
**Remediation** — two paths, pick based on consumer intent:
|
|
60
|
+
|
|
61
|
+
**Path A — bundler install** (default for production apps with Vite/webpack):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Match the reference dep shape from a known-good sibling (e.g. claims-ui-v8):
|
|
65
|
+
npm install @adia-ai/web-components@^0.6.X @adia-ai/web-modules@^0.6.X
|
|
66
|
+
# (+ @phosphor-icons/core if main.ts imports icons; check src/main.ts imports)
|
|
67
|
+
|
|
68
|
+
# Then verify:
|
|
69
|
+
ls node_modules/@adia-ai/ # should now exist
|
|
70
|
+
npm run dev # vite resolves cleanly
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Path B — switch to CDN** (since v0.6.30, the zero-install escape hatch):
|
|
74
|
+
|
|
75
|
+
If the consumer's intent is "quick prototype" / "CodePen demo" /
|
|
76
|
+
"marketing page" / "static HTML site" — or if `package.json` shouldn't
|
|
77
|
+
exist at all for the surface — **don't add `@adia-ai/*` deps**.
|
|
78
|
+
Replace the `import` statements with HTML `<link>` + `<script>` tags
|
|
79
|
+
pointing at the CDN bundles:
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<!-- In index.html <head>, NO npm install required -->
|
|
83
|
+
<link rel="stylesheet"
|
|
84
|
+
href="https://cdn.jsdelivr.net/npm/@adia-ai/web-components@0.7/dist/web-components.min.css">
|
|
85
|
+
<link rel="stylesheet"
|
|
86
|
+
href="https://cdn.jsdelivr.net/npm/@adia-ai/web-modules@0.7/dist/shell/admin-shell.min.css">
|
|
87
|
+
<script type="module"
|
|
88
|
+
src="https://cdn.jsdelivr.net/npm/@adia-ai/web-modules@0.7/dist/everything.min.js"></script>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This converts Gap class 0 from a hard-halt into a **mode choice** — the
|
|
92
|
+
operator picks bundler-served OR CDN-served. The CDN path doesn't
|
|
93
|
+
require ANY `package.json` deps for `@adia-ai/*`; the manifest gap
|
|
94
|
+
becomes irrelevant for HTML-first surfaces. See §CSSPolicy → "CDN-bundle
|
|
95
|
+
path" for the full 3-tier policy.
|
|
96
|
+
|
|
97
|
+
**Path A vs Path B — choice tree**:
|
|
98
|
+
|
|
99
|
+
| Signal | Choose |
|
|
100
|
+
|--------|--------|
|
|
101
|
+
| `vite.config.*` or `webpack.config.*` exists | Path A (install) |
|
|
102
|
+
| `<script src=".../@adia-ai/...">` already in HTML | Path B (CDN) |
|
|
103
|
+
| User said "quick" / "prototype" / "demo" / "CodePen" | Path B (CDN) |
|
|
104
|
+
| User has production deployment story / "ship to prod" | Path A (install) |
|
|
105
|
+
| Repo has zero `package.json` (greenfield static HTML) | Path B (CDN) |
|
|
106
|
+
| User has a `src/main.ts` and is mid-Vite-build | Path A (install) |
|
|
107
|
+
|
|
108
|
+
The bundler remediation is still the default for "I scaffolded a Vite
|
|
109
|
+
app and need the deps" — Path B is for cases where the bundler itself
|
|
110
|
+
is the wrong tool, not just for missing deps.
|
|
111
|
+
|
|
112
|
+
The remediation is one `npm install` command (Path A) OR three CDN
|
|
113
|
+
tags in `<head>` (Path B), but the **discipline is to detect the gap
|
|
114
|
+
before authoring any further imports** — otherwise the "compose a
|
|
115
|
+
screen" call ships code that won't start (Path A) OR ships imports
|
|
116
|
+
the CDN page can't resolve (Path B).
|
|
117
|
+
|
|
118
|
+
**Surfacing to operator:** if Gap class 0 fires, do not silently fix
|
|
119
|
+
it — surface the gap with the exact reference shape (from a sibling
|
|
120
|
+
repo if available), the install command, and a one-line explanation.
|
|
121
|
+
The operator decides whether to add the deps or back out the imports.
|
|
122
|
+
|
|
123
|
+
**Anti-pattern:** running `npm install` (no args) to "fix the gap." That
|
|
124
|
+
only installs what's already declared. With zero declarations, it's a
|
|
125
|
+
no-op and the build still fails. The fix is `npm install <package>` —
|
|
126
|
+
which both declares AND installs.
|
|
127
|
+
|
|
128
|
+
**Worked example (claims-ui-v9, 2026-05-23):** `src/main.ts` had 5
|
|
129
|
+
`@adia-ai/*` imports (`web-components`, `web-components/css`,
|
|
130
|
+
`web-components/core/icons`, `web-modules/shell`, `web-modules/shell/admin-shell.css`).
|
|
131
|
+
`package.json` had `{}` for `@adia-ai/*` deps. `npm install` was a
|
|
132
|
+
no-op for that scope; `node_modules/@adia-ai/` didn't exist; vite's
|
|
133
|
+
dependency scanner halted dev-server boot with "could not be
|
|
134
|
+
resolved / Are they installed?". Remediation: `npm install
|
|
135
|
+
@adia-ai/web-components@^0.6.28 @adia-ai/web-modules@^0.6.28`. Sibling
|
|
136
|
+
reference shape was `claims-ui-v8/package.json` (`^0.6.23` of the same
|
|
137
|
+
two packages — same import surface, same publish layout).
|
|
138
|
+
|
|
139
|
+
### Gap class 1 — Version drift
|
|
140
|
+
|
|
141
|
+
**Mechanism:** consumer's installed `@adia-ai/*` versions trail the
|
|
142
|
+
substrate's `latest` dist-tag. The substrate has shipped features /
|
|
143
|
+
fixes the consumer hasn't picked up.
|
|
144
|
+
|
|
145
|
+
**Detection:**
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Substrate's latest dist-tag (each of the 9 packages should match):
|
|
149
|
+
for pkg in web-components web-modules llm a2ui-compose a2ui-corpus \
|
|
150
|
+
a2ui-mcp a2ui-retrieval a2ui-runtime a2ui-validator; do
|
|
151
|
+
echo -n "$pkg "; npm view "@adia-ai/$pkg" version 2>/dev/null
|
|
152
|
+
done
|
|
153
|
+
|
|
154
|
+
# Consumer's declared ranges:
|
|
155
|
+
grep -E '"@adia-ai/' package.json
|
|
156
|
+
|
|
157
|
+
# Consumer's installed actuals:
|
|
158
|
+
for d in node_modules/@adia-ai/*; do
|
|
159
|
+
echo -n "$(basename $d) "; node -p "require('$d/package.json').version"
|
|
160
|
+
done
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Interpretation:**
|
|
164
|
+
|
|
165
|
+
| Declared / Installed / Latest | Drift | Remediation |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `^0.6.0` / `0.6.18` / `0.6.19` | Minor PATCH lag | `npm install @adia-ai/web-components@^0.6.0` — picks up the latest 0.6.x. PATCH cuts are non-breaking. |
|
|
168
|
+
| `^0.6.0` / `0.6.18` / `0.7.0` | Minor MINOR lag | Read v0.7.0 CHANGELOG; decide explicit bump (breaking changes possible). |
|
|
169
|
+
| `^0.4.0` / `0.4.0` / `0.6.19` | Major-relative lag | Trigger §Migration phase — multi-cut breaking-change sweep. |
|
|
170
|
+
| 9-pkg ranges inconsistent | Lockstep break | **Hard failure** — internal `^0.6.0` deps will resolve to mismatched siblings. Fix before any other work. |
|
|
171
|
+
|
|
172
|
+
### Gap class 2 — Spec drift (ADR adoption)
|
|
173
|
+
|
|
174
|
+
**Mechanism:** substrate ships an ADR (e.g. ADR-0024 retired legacy
|
|
175
|
+
shell shapes; ADR-0023 introduced bespoke shell vocabulary). Consumer
|
|
176
|
+
code predates the ADR and still uses the retired shape, or hasn't yet
|
|
177
|
+
adopted the new canonical shape.
|
|
178
|
+
|
|
179
|
+
**Detection:**
|
|
180
|
+
|
|
181
|
+
For each ADR that introduces a vocabulary change, grep the consumer's
|
|
182
|
+
codebase for the *retired* shape. AdiaUI's load-bearing ADRs and their
|
|
183
|
+
grep signatures:
|
|
184
|
+
|
|
185
|
+
| ADR | Introduced | Retired shape (grep target) | Canonical replacement |
|
|
186
|
+
|---|---|---|---|
|
|
187
|
+
| ADR-0023 (v0.4.0) | bespoke shells | `<chrome-shell`, `<chrome-rail`, `<chrome-canvas`, `<page-shell` | `<admin-shell>`, `<editor-shell>`, `<chat-shell>` |
|
|
188
|
+
| ADR-0024 (v0.4.0) | strip JS legacy reads | `data-actions=` (in JS-set host attrs) | `slot="action"` on children |
|
|
189
|
+
| ADR-0029 (v0.6.16) | sealed tsconfig substrate | un-tracked `// @ts-ignore` w/o `TS-MIG-NNN` | tracked override + entry in `.brain/notes/ts-mig-tracking.md` |
|
|
190
|
+
| ADR-0030 (v0.6.10) | `/with-css` opt-in | implicit CSS side-effect imports | `/with-css` subpath OR explicit CSS import |
|
|
191
|
+
| ADR-0032 (v0.6.13) | CSS bridges retired | `--agent-*` tokens, `AgentElement` | `--a-*` tokens, `UIElement` |
|
|
192
|
+
|
|
193
|
+
**Generic grep recipe** (run from consumer repo root):
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Retired shells (ADR-0023):
|
|
197
|
+
grep -rEn '<chrome-(shell|rail|canvas)|<page-shell' \
|
|
198
|
+
--include='*.html' --include='*.js' --include='*.jsx' \
|
|
199
|
+
--include='*.tsx' --include='*.vue' --include='*.svelte' .
|
|
200
|
+
|
|
201
|
+
# Retired tokens / base class (ADR-0032):
|
|
202
|
+
grep -rEn '--agent-|AgentElement|@agent-ui-kit' \
|
|
203
|
+
--include='*.css' --include='*.js' --include='*.ts' \
|
|
204
|
+
--include='*.json' .
|
|
205
|
+
|
|
206
|
+
# Legacy authoring shapes (ADR-0024):
|
|
207
|
+
grep -rEn 'data-actions=' \
|
|
208
|
+
--include='*.html' --include='*.js' .
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Interpretation:** every grep match is a spec-drift finding. The
|
|
212
|
+
remediation is mechanical (find/replace) for most, except where the
|
|
213
|
+
retired shape was carrying state that needs migration (rare; check the
|
|
214
|
+
ADR's "migration notes" section).
|
|
215
|
+
|
|
216
|
+
### Gap class 3 — Capability drift (hand-rolled-when-substrate-now-provides)
|
|
217
|
+
|
|
218
|
+
**Mechanism:** consumer code hand-rolled a pattern (skeleton, toast,
|
|
219
|
+
breakpoint grid, custom dialog) before the substrate shipped a
|
|
220
|
+
first-class equivalent. The hand-rolled code now duplicates what
|
|
221
|
+
substrate provides, drifts from it visually, and accumulates
|
|
222
|
+
maintenance cost.
|
|
223
|
+
|
|
224
|
+
**Detection:** the table in §Recon step 7 maps grep signatures to
|
|
225
|
+
substrate replacements. Run each grep, count matches, and note the
|
|
226
|
+
**leverage ratio**:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
leverage = (N_locations × M_lines_per_location) / replacement_cost
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
High-leverage findings (>10 locations, >5 lines each, replaceable in a
|
|
233
|
+
single PATCH cut) belong in the §DiagnosticOutput "high-priority"
|
|
234
|
+
section. Low-leverage findings (1 location, deliberate carve-out)
|
|
235
|
+
either get a first-principles audit (see §ReasoningMethodologies #4)
|
|
236
|
+
or get accepted as deliberate.
|
|
237
|
+
|
|
238
|
+
**Sniff test before declaring capability drift:**
|
|
239
|
+
|
|
240
|
+
- Does the hand-rolled pattern *predate* the substrate capability? (Check
|
|
241
|
+
the consumer file's `git log` vs the substrate CHANGELOG entry.)
|
|
242
|
+
- Is the hand-rolled pattern doing something the substrate can't? (Read
|
|
243
|
+
the substrate yaml for the prop's full surface; the consumer might
|
|
244
|
+
rely on a behavior the substrate primitive doesn't replicate.)
|
|
245
|
+
- Is there a doc / changelog entry telling consumers to migrate? (If
|
|
246
|
+
yes, this is also a spec-drift finding; classify it once.)
|
|
247
|
+
|
|
248
|
+
### Gap-detection output shape
|
|
249
|
+
|
|
250
|
+
For each finding, capture:
|
|
251
|
+
|
|
252
|
+
```yaml
|
|
253
|
+
- class: manifest-gap | version-drift | spec-drift | capability-drift
|
|
254
|
+
evidence: <file:line> or <grep output>
|
|
255
|
+
count: <N locations>
|
|
256
|
+
substrate_answer: <component / token / ADR>
|
|
257
|
+
remediation: <one-line how-to>
|
|
258
|
+
leverage: high | medium | low
|
|
259
|
+
risk: low | medium | high # behavior delta if remediated
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Roll these up into §DiagnosticOutput. **Manifest-gap findings always
|
|
263
|
+
sort first** — they're build-blockers and other findings can't be
|
|
264
|
+
verified until they're resolved.
|
|
265
|
+
|
|
266
|
+
---
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: harness
|
|
3
|
+
load-when: When wiring AdiaUI MCP server into a consuming app (Claude Desktop / Cursor / Windsurf / Claude Code) or when answering 'how do I add canvas-ui / a2ui-root / registerResolver?'
|
|
4
|
+
load-size-tokens: ~2,700
|
|
5
|
+
required-for:
|
|
6
|
+
- mode 7 (harness wiring)
|
|
7
|
+
- MCP install support
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# §Harness — Inserting the MCP into your app
|
|
11
|
+
|
|
12
|
+
> **⚠ Opt-in gate — read before continuing.** This section is only needed
|
|
13
|
+
> if your app will have **runtime-generated UI from an LLM agent** (i.e. a
|
|
14
|
+
> `<canvas-ui>` / `<a2ui-root>` rendering surface fed by an agent or a
|
|
15
|
+
> stored A2UI document). For **product UIs built from AdiaUI primitives**
|
|
16
|
+
> — dashboards, forms, data tables, auth flows, settings pages — your
|
|
17
|
+
> setup is complete at §Setup. The harness adds no value when the UI is
|
|
18
|
+
> hand-authored markup; it is the runtime substrate for **generative**
|
|
19
|
+
> surfaces specifically. Return here only when adding a generative
|
|
20
|
+
> surface to an existing AdiaUI app.
|
|
21
|
+
|
|
22
|
+
Three integration modes, from simplest to most dynamic. Choose based on
|
|
23
|
+
when generation happens relative to the user's session.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
### Mode A — Author-time (IDE → static files)
|
|
28
|
+
|
|
29
|
+
Generate at development time using the IDE MCP tools or CLI, then commit
|
|
30
|
+
the output as static HTML page fragments. No runtime dependency on the
|
|
31
|
+
MCP server.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Generate from the CLI (instant mode, no LLM key)
|
|
35
|
+
node packages/a2ui/mcp/scripts/generate.mjs "claims list table" > src/pages/claims.html
|
|
36
|
+
|
|
37
|
+
# Or use the IDE MCP tool (Claude Code / Cursor)
|
|
38
|
+
# → generate_ui("claims list with status badge and detail drawer", mode: "instant")
|
|
39
|
+
# → copy the rendered HTML into src/pages/claims-list.html
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The output is plain AdiaUI HTML that §Flows describes. Wire it into your
|
|
43
|
+
admin shell via `router-ui` routing (see §Patterns → Admin shell anatomy).
|
|
44
|
+
Zero runtime dependency.
|
|
45
|
+
|
|
46
|
+
**When to use:** stable UI, content doesn't change at runtime, faster
|
|
47
|
+
page load, no server needed.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### Mode B — Runtime rendering with `<canvas-ui>` API (no streaming, no server)
|
|
52
|
+
|
|
53
|
+
If you have A2UI JSON in hand (from an API, local generation, or cached
|
|
54
|
+
result), feed it directly to `<canvas-ui>`. No network transport, no
|
|
55
|
+
streaming.
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<!-- In your HTML: the rendering surface -->
|
|
59
|
+
<canvas-ui id="gen-canvas"></canvas-ui>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
// In main.js — after generating or fetching A2UI messages
|
|
64
|
+
// v0.6.7+: single import registers canvas-ui + a2ui-root + registerResolver
|
|
65
|
+
import '@adia-ai/web-modules/generative';
|
|
66
|
+
//
|
|
67
|
+
// (Pre-v0.6.7 — still works but verbose:
|
|
68
|
+
// import '@adia-ai/web-modules/runtime/a2ui-root/a2ui-root.js';
|
|
69
|
+
// import '@adia-ai/web-components/components/canvas/canvas.js';)
|
|
70
|
+
|
|
71
|
+
const canvas = document.getElementById('gen-canvas');
|
|
72
|
+
|
|
73
|
+
// Option 1: render a complete set of messages at once
|
|
74
|
+
canvas.reset();
|
|
75
|
+
canvas.processAll([
|
|
76
|
+
{ type: 'createSurface', surfaceId: 's1', components: [ /* ... */ ] },
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
// ⚠ `canvas.doc = [...]` does NOT exist on <canvas-ui> — the `.doc`
|
|
80
|
+
// property lives on <a2ui-root> (which <canvas-ui> internally hosts but
|
|
81
|
+
// does not proxy). Assigning to a non-existent property is a silent
|
|
82
|
+
// no-op; the canvas stays blank with no diagnostic. Use the method API
|
|
83
|
+
// above (`reset()` + `processAll()`) for the canvas surface. If you
|
|
84
|
+
// need the `.doc=` setter shape, target <a2ui-root> directly (Mode C).
|
|
85
|
+
|
|
86
|
+
// Option 2: process messages one at a time (streaming simulation)
|
|
87
|
+
canvas.reset();
|
|
88
|
+
for (const msg of messages) {
|
|
89
|
+
canvas.process(msg);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Option 3: call an endpoint yourself, then render
|
|
93
|
+
const result = await fetch('http://localhost:3456/api/generate', {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: { 'Content-Type': 'application/json' },
|
|
96
|
+
body: JSON.stringify({ intent: 'login form', mode: 'instant' }),
|
|
97
|
+
}).then(r => r.json());
|
|
98
|
+
|
|
99
|
+
canvas.reset();
|
|
100
|
+
canvas.processAll(result.messages);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**`canvas-ui` API:**
|
|
104
|
+
|
|
105
|
+
| Method / prop | What it does |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `.reset()` | Clear the canvas, discard all components |
|
|
108
|
+
| `.process(msg)` | Apply a single A2UI message to the current surface |
|
|
109
|
+
| `.processAll(msgs)` | Apply an array of messages in order |
|
|
110
|
+
| `.pushVersion(msgs)` | Save current messages to history (enables back/forward) |
|
|
111
|
+
| `.back()` / `.forward()` | Navigate history. Return `false` at boundary |
|
|
112
|
+
| `.historyLength` / `.historyIndex` | History stack inspection |
|
|
113
|
+
| `.getHTML()` | Return formatted innerHTML of the inner `<a2ui-root>` |
|
|
114
|
+
|
|
115
|
+
(For the `.doc=` setter shape, see `<a2ui-root>` in Mode C — `<canvas-ui>`
|
|
116
|
+
is method-only by design.)
|
|
117
|
+
|
|
118
|
+
**Registering resolvers (required for data-bound components):**
|
|
119
|
+
|
|
120
|
+
Generated components that bind to real data use `resource://` and
|
|
121
|
+
`api://` URIs. Without a resolver registered, those bindings return
|
|
122
|
+
empty. Wire them in `main.js` before the canvas renders:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
import { registerResolver } from '@adia-ai/a2ui-runtime';
|
|
126
|
+
|
|
127
|
+
// Resolve api:// URIs → your real backend endpoints
|
|
128
|
+
registerResolver('api', async (uri) => {
|
|
129
|
+
// uri e.g. "api://claims?status=open"
|
|
130
|
+
const path = uri.replace('api://', '/api/');
|
|
131
|
+
const res = await fetch(path);
|
|
132
|
+
return res.json();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Resolve resource:// URIs → static or lookup data
|
|
136
|
+
registerResolver('resource', async (uri) => {
|
|
137
|
+
// uri e.g. "resource://claim-statuses"
|
|
138
|
+
return ['Open', 'In Review', 'Approved', 'Rejected'];
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**When to use:** single-page apps that generate UI on demand from user
|
|
143
|
+
input, cached generation results, or test/preview environments.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### Mode C — Live streaming from MCP HTTP server
|
|
148
|
+
|
|
149
|
+
For real-time generative UI where the page streams generated components
|
|
150
|
+
as they arrive, wire `<a2ui-root>` or `<canvas-ui>` to the MCP HTTP
|
|
151
|
+
server's streaming endpoint.
|
|
152
|
+
|
|
153
|
+
**Step 1: start the HTTP MCP server**
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
MCP_HTTP_PORT=3460 node packages/a2ui/mcp/server.js
|
|
157
|
+
# → listening on http://localhost:3460/mcp
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Or via the proxy (which also serves the browser):
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npm run dev # Vite on :5173 + proxy on :3456
|
|
164
|
+
# POST http://localhost:3456/api/generate → same pipeline
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Step 2: wire `<a2ui-root>` in your HTML**
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<!-- SSE streaming from /api/generate -->
|
|
171
|
+
<a2ui-root
|
|
172
|
+
id="gen-surface"
|
|
173
|
+
transport="sse"
|
|
174
|
+
src="/api/generate">
|
|
175
|
+
</a2ui-root>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Or use `<canvas-ui>` for history support:
|
|
179
|
+
|
|
180
|
+
```html
|
|
181
|
+
<canvas-ui id="gen-canvas"></canvas-ui>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Step 3: trigger generation from user input**
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
// v0.6.7+: one barrel for everything
|
|
188
|
+
import { registerResolver } from '@adia-ai/web-modules/generative';
|
|
189
|
+
import '@adia-ai/web-modules/generative';
|
|
190
|
+
|
|
191
|
+
// Register resolvers before any generation triggers
|
|
192
|
+
registerResolver('api', async (uri) => {
|
|
193
|
+
return fetch(uri.replace('api://', '/api/')).then(r => r.json());
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const canvas = document.getElementById('gen-canvas');
|
|
197
|
+
const input = document.getElementById('prompt-input');
|
|
198
|
+
|
|
199
|
+
document.getElementById('generate-btn').addEventListener('press', async () => {
|
|
200
|
+
const intent = input.value.trim();
|
|
201
|
+
if (!intent) return;
|
|
202
|
+
|
|
203
|
+
canvas.reset();
|
|
204
|
+
|
|
205
|
+
// Call the proxy's generate endpoint
|
|
206
|
+
const result = await fetch('http://localhost:3456/api/generate', {
|
|
207
|
+
method: 'POST',
|
|
208
|
+
headers: { 'Content-Type': 'application/json' },
|
|
209
|
+
body: JSON.stringify({ intent, engine: 'monolithic', mode: 'instant' }),
|
|
210
|
+
}).then(r => r.json());
|
|
211
|
+
|
|
212
|
+
canvas.processAll(result.messages);
|
|
213
|
+
canvas.pushVersion(result.messages);
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**`<a2ui-root>` events for observability:**
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
const root = document.querySelector('a2ui-root');
|
|
221
|
+
|
|
222
|
+
root.addEventListener('a2ui-connected', () => console.log('stream connected'));
|
|
223
|
+
root.addEventListener('a2ui-message', e => console.log('message:', e.detail.message));
|
|
224
|
+
root.addEventListener('a2ui-action', e => console.log('action:', e.detail.name, e.detail.params));
|
|
225
|
+
root.addEventListener('a2ui-error', e => console.error('error:', e.detail.error));
|
|
226
|
+
root.addEventListener('a2ui-closed', () => console.log('stream closed'));
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
### Complete harness wiring (Mode B — recommended starting point **for generative surfaces**)
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
// main.js — full harness for a generative UI surface
|
|
235
|
+
import '@adia-ai/web-components/css';
|
|
236
|
+
import '@adia-ai/web-components';
|
|
237
|
+
import '@adia-ai/web-modules/shell'; // per-cluster — the full '@adia-ai/web-modules' barrel ships broken absolute paths at v0.6.7
|
|
238
|
+
import '@adia-ai/web-modules/shell/admin-shell.css'; // REQUIRED — see §CSSPolicy
|
|
239
|
+
// v0.6.7+: single import for canvas-ui + a2ui-root + registerResolver
|
|
240
|
+
import '@adia-ai/web-modules/generative';
|
|
241
|
+
import { installIconLoadersForRegistered } from '@adia-ai/web-components/core/icons';
|
|
242
|
+
import { registerResolver } from '@adia-ai/web-modules/generative';
|
|
243
|
+
|
|
244
|
+
// Icon loader
|
|
245
|
+
installIconLoadersForRegistered(
|
|
246
|
+
import.meta.glob('../node_modules/@phosphor-icons/core/assets/regular/*.svg',
|
|
247
|
+
{ query: '?raw', import: 'default', eager: true })
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// Wire data resolvers BEFORE any generation trigger
|
|
251
|
+
registerResolver('api', async (uri) => {
|
|
252
|
+
const res = await fetch(uri.replace('api://', '/api/'));
|
|
253
|
+
if (!res.ok) return [];
|
|
254
|
+
return res.json();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
registerResolver('resource', async (uri) => {
|
|
258
|
+
// Return static lookup data for resource:// URIs
|
|
259
|
+
const key = uri.replace('resource://', '');
|
|
260
|
+
const lookups = {
|
|
261
|
+
'claim-statuses': ['Open', 'In Review', 'Approved', 'Rejected'],
|
|
262
|
+
'policy-types': ['Auto', 'Home', 'Life', 'Health'],
|
|
263
|
+
};
|
|
264
|
+
return lookups[key] ?? [];
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
```html
|
|
269
|
+
<!-- index.html — the rendering surface -->
|
|
270
|
+
<canvas-ui id="gen-canvas"></canvas-ui>
|
|
271
|
+
<script type="module" src="/src/main.js"></script>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
### Harness checklist
|
|
277
|
+
|
|
278
|
+
- [ ] `@adia-ai/web-modules/generative` imported (v0.6.7+ — registers
|
|
279
|
+
`canvas-ui` + `a2ui-root` + re-exports `registerResolver` in one barrel)
|
|
280
|
+
- [ ] `registerResolver('api', ...)` wired before first generation trigger
|
|
281
|
+
- [ ] `registerResolver('resource', ...)` wired for static lookup data
|
|
282
|
+
- [ ] `canvas.reset()` called before each new generation (clears prior surface)
|
|
283
|
+
- [ ] `canvas.pushVersion(msgs)` called after each successful generation (enables history)
|
|
284
|
+
---
|