@adia-ai/adia-ui-factory 0.2.4 → 0.8.1
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 +6 -8
- package/.mcp.json +1 -1
- package/CHANGELOG.md +40 -67
- package/README.md +32 -53
- package/agents/app-architect.md +28 -0
- package/agents/routing-corpus.json +202 -0
- package/agents/screen-composer.md +27 -0
- package/bin/adia-info +235 -0
- package/bin/adia-lint +17 -2
- package/commands/adia-genui.md +5 -8
- package/commands/adia-migrate.md +5 -6
- package/commands/adia-orient.md +5 -10
- package/commands/adia-scaffold.md +7 -13
- package/commands/adia-verify.md +5 -6
- package/package.json +5 -6
- package/references/a2ui-mcp-tools.md +11 -8
- package/references/authoring-components.md +25 -1
- package/references/component-model.md +52 -4
- package/references/contracts/a2ui-mcp-surface.md +35 -0
- package/references/contracts/migration-guide-format.md +34 -0
- package/references/data-and-hydration.md +8 -5
- package/references/genui-a2ui.md +12 -6
- package/references/llm.md +22 -39
- package/references/migration.md +110 -36
- package/references/project-shapes.md +11 -13
- package/references/shell-admin.md +5 -2
- package/references/shell-chat.md +5 -3
- package/references/shell-editor.md +1 -1
- package/references/shell-embed.md +40 -26
- package/references/shell-simple.md +5 -2
- package/references/spa-architecture.md +28 -73
- package/references/ssr-integration.md +1 -1
- package/references/verification.md +8 -12
- package/skills/adia-compose/SKILL.md +121 -0
- package/skills/{adia-ui-kit → adia-compose}/assets/figma-make/guidelines/Guidelines.md +3 -3
- package/skills/{adia-ui-kit → adia-compose}/assets/figma-make/guidelines/components.md +1 -1
- package/skills/{adia-ui-kit → adia-compose}/assets/figma-make/guidelines/styles.md +1 -1
- package/skills/{adia-ui-kit → adia-compose}/assets/figma-make/guidelines/tokens.md +3 -3
- package/skills/{adia-ui-kit → adia-compose}/assets/templates/FEEDBACK.template.md +7 -7
- package/skills/{adia-ui-kit → adia-compose}/assets/templates/RESPONSE.template.md +6 -7
- package/skills/adia-compose/references/composition-traps.md +58 -0
- package/skills/adia-compose/references/feedback-discipline.md +20 -0
- package/skills/adia-compose/references/spec-to-ui-reasoning.md +158 -0
- package/skills/adia-data/SKILL.md +78 -0
- package/skills/adia-genui/SKILL.md +83 -0
- package/skills/adia-host/SKILL.md +119 -0
- package/skills/adia-llm/SKILL.md +36 -0
- package/skills/adia-migrate/SKILL.md +95 -0
- package/skills/adia-orient/SKILL.md +135 -0
- package/skills/adia-project/SKILL.md +83 -0
- package/skills/adia-shells/SKILL.md +74 -0
- package/skills/adia-verify/SKILL.md +43 -0
- package/skills/adia-verify/references/verification.md +42 -0
- package/commands/adia-compose.md +0 -10
- package/commands/adia-wire.md +0 -13
- package/skills/adia-ui-compose/SKILL.md +0 -57
- package/skills/adia-ui-data/SKILL.md +0 -62
- package/skills/adia-ui-factory/SKILL.md +0 -113
- package/skills/adia-ui-genui/SKILL.md +0 -74
- package/skills/adia-ui-kit/CHANGELOG.md +0 -41
- package/skills/adia-ui-kit/SKILL.md +0 -442
- package/skills/adia-ui-kit/assets/team-scaffold/archive-README.md +0 -30
- package/skills/adia-ui-kit/assets/team-scaffold/drafts-README.md +0 -57
- package/skills/adia-ui-kit/assets/team-scaffold/inbox-README.md +0 -76
- package/skills/adia-ui-kit/assets/team-scaffold/outbox-README.md +0 -46
- package/skills/adia-ui-kit/assets/team-scaffold/team-root.README.md +0 -51
- package/skills/adia-ui-kit/assets/team-scaffold/tickets-README.md +0 -208
- package/skills/adia-ui-kit/assets/team-scaffold/tickets-REGISTRY.md +0 -81
- package/skills/adia-ui-kit/assets/templates/AGENTS.template.md +0 -128
- package/skills/adia-ui-kit/assets/templates/CLAUDE.template.md +0 -1
- package/skills/adia-ui-kit/assets/templates/figma-make-guidelines.md +0 -90
- package/skills/adia-ui-kit/evals/adversarial-content-trust.json +0 -83
- package/skills/adia-ui-kit/evals/evals.json +0 -55
- package/skills/adia-ui-kit/evals/routing-corpus.json +0 -121
- package/skills/adia-ui-kit/evals/teach-routing-cases.json +0 -92
- package/skills/adia-ui-kit/references/capabilities.md +0 -245
- package/skills/adia-ui-kit/references/catalog-lookup.md +0 -186
- package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v1.md +0 -8
- package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v2.md +0 -3585
- package/skills/adia-ui-kit/references/changelog-archive/CHANGELOG-v3.md +0 -1899
- package/skills/adia-ui-kit/references/common-gotchas-consumer.md +0 -522
- package/skills/adia-ui-kit/references/component-literacy.md +0 -291
- package/skills/adia-ui-kit/references/composition.md +0 -245
- package/skills/adia-ui-kit/references/correction-loop.md +0 -462
- package/skills/adia-ui-kit/references/css-policy.md +0 -343
- package/skills/adia-ui-kit/references/decision-model.md +0 -158
- package/skills/adia-ui-kit/references/diagnostic-output.md +0 -57
- package/skills/adia-ui-kit/references/docs-catalog.md +0 -239
- package/skills/adia-ui-kit/references/exclusions.md +0 -225
- package/skills/adia-ui-kit/references/feedback-authoring.md +0 -466
- package/skills/adia-ui-kit/references/figma-make.md +0 -244
- package/skills/adia-ui-kit/references/flows-auth.md +0 -307
- package/skills/adia-ui-kit/references/flows-content.md +0 -206
- package/skills/adia-ui-kit/references/flows-data.md +0 -348
- package/skills/adia-ui-kit/references/flows-interaction.md +0 -181
- package/skills/adia-ui-kit/references/flows-shells.md +0 -336
- package/skills/adia-ui-kit/references/gap-detection.md +0 -266
- package/skills/adia-ui-kit/references/harness.md +0 -284
- package/skills/adia-ui-kit/references/loading-protocol.md +0 -406
- package/skills/adia-ui-kit/references/local-link.md +0 -198
- package/skills/adia-ui-kit/references/mcp.md +0 -401
- package/skills/adia-ui-kit/references/migration.md +0 -116
- package/skills/adia-ui-kit/references/mission.md +0 -194
- package/skills/adia-ui-kit/references/mode-routing.md +0 -298
- package/skills/adia-ui-kit/references/patterns-agent.md +0 -223
- package/skills/adia-ui-kit/references/patterns-data.md +0 -1065
- package/skills/adia-ui-kit/references/patterns-forms.md +0 -223
- package/skills/adia-ui-kit/references/patterns-layout.md +0 -326
- package/skills/adia-ui-kit/references/patterns-recipes.md +0 -1416
- package/skills/adia-ui-kit/references/patterns-shells.md +0 -1097
- package/skills/adia-ui-kit/references/patterns-traits.md +0 -259
- package/skills/adia-ui-kit/references/patterns-wiring.md +0 -339
- package/skills/adia-ui-kit/references/pev-rationale.md +0 -137
- package/skills/adia-ui-kit/references/reasoning-gate.md +0 -146
- package/skills/adia-ui-kit/references/reasoning-methodologies.md +0 -112
- package/skills/adia-ui-kit/references/recon.md +0 -192
- package/skills/adia-ui-kit/references/rendering-model.md +0 -431
- package/skills/adia-ui-kit/references/response-authoring.md +0 -398
- package/skills/adia-ui-kit/references/session-log-schema.md +0 -203
- package/skills/adia-ui-kit/references/session-log-template.md +0 -118
- package/skills/adia-ui-kit/references/setup.md +0 -652
- package/skills/adia-ui-kit/references/skill-hygiene.md +0 -135
- package/skills/adia-ui-kit/references/spec-to-ui-reasoning.md +0 -394
- package/skills/adia-ui-kit/references/state.md +0 -229
- package/skills/adia-ui-kit/references/teach-protocol.md +0 -421
- package/skills/adia-ui-kit/references/theme.md +0 -142
- package/skills/adia-ui-kit/references/version-check.md +0 -69
- package/skills/adia-ui-kit/scripts/audit-decision-trace.mjs +0 -198
- package/skills/adia-ui-kit/scripts/audit-kit-roster.mjs +0 -366
- package/skills/adia-ui-kit/scripts/changelog-archive.mjs +0 -126
- package/skills/adia-ui-kit/scripts/check-adia-versions.py +0 -404
- package/skills/adia-ui-kit/scripts/run-skill-evals.mjs +0 -358
- package/skills/adia-ui-kit/scripts/validate-session-log.mjs +0 -242
- package/skills/adia-ui-kit/skill.json +0 -102
- package/skills/adia-ui-llm/SKILL.md +0 -51
- package/skills/adia-ui-migrate/SKILL.md +0 -64
- package/skills/adia-ui-migration/CHANGELOG.md +0 -47
- package/skills/adia-ui-migration/SKILL.md +0 -381
- package/skills/adia-ui-migration/skill.json +0 -29
- package/skills/adia-ui-project/SKILL.md +0 -77
- package/skills/adia-ui-shells/SKILL.md +0 -62
- package/skills/adia-ui-spa/SKILL.md +0 -52
- package/skills/adia-ui-ssr/SKILL.md +0 -52
- package/skills/adia-ui-verify/SKILL.md +0 -44
- /package/skills/{adia-ui-kit → adia-compose}/assets/templates/FEEDBACK-OMISSIONS-DEFENSE.template.md +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Contract: a2ui MCP tool surface (consumer side)
|
|
2
|
+
|
|
3
|
+
<!-- VENDORED TWIN: adia-forge ships references/contracts/a2ui-mcp-surface.md
|
|
4
|
+
(producer side). Changes here must be reconciled in BOTH copies. -->
|
|
5
|
+
|
|
6
|
+
The forge SHIPS `@adia-ai/a2ui-mcp` (source: `packages/a2ui/mcp/`); the factory
|
|
7
|
+
PINS it in `.mcp.json` and consumer skills drive it. Source of truth for the
|
|
8
|
+
full tool surface: `packages/a2ui/mcp/TOOLS.md` (30 tools, generated from
|
|
9
|
+
`server.js` — update both together).
|
|
10
|
+
|
|
11
|
+
## Stability rule (the load-bearing clause)
|
|
12
|
+
|
|
13
|
+
- **Changing an existing tool's input/output contract is a breaking change for
|
|
14
|
+
every external MCP client** (Claude Desktop, Cursor, the factory plugin).
|
|
15
|
+
It requires: a dry-run diff of the schema, an explicit operator proceed, a
|
|
16
|
+
version bump of `@adia-ai/a2ui-mcp`, and a factory-side pin update.
|
|
17
|
+
- **Adding tools is additive and safe.** Removing or renaming is breaking.
|
|
18
|
+
- The factory pins an exact version (`npx -y @adia-ai/a2ui-mcp@<exact>`);
|
|
19
|
+
producers must not assume consumers float.
|
|
20
|
+
|
|
21
|
+
## The consumer-load-bearing subset
|
|
22
|
+
|
|
23
|
+
Tools the factory's skills depend on by name — treat their contracts as
|
|
24
|
+
frozen-unless-versioned:
|
|
25
|
+
|
|
26
|
+
| Tool | Consumer use |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `generate_ui`, `refine_ui` | gen-UI generation loop (adia-genui) |
|
|
29
|
+
| `validate_schema`, `check_anti_patterns` | the trust gate on LLM-emitted A2UI (screen-composer) |
|
|
30
|
+
| `search_chunks`, `lookup_component`, `get_component_map`, `get_traits` | catalog literacy (adia-compose — "the MCP is the live catalog, don't memorize names") |
|
|
31
|
+
| `convert_html` | migration aid (adia-migrate) |
|
|
32
|
+
| `server_status` | connectivity probe (adia-verify) |
|
|
33
|
+
|
|
34
|
+
`refine_ui` note: present in the pinned server; keep TOOLS.md's entry in sync
|
|
35
|
+
with `server.js` when either changes (the 2026-06 red-team caught it missing).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Contract: MIGRATION GUIDE format (consumer side)
|
|
2
|
+
|
|
3
|
+
<!-- VENDORED TWIN: adia-forge ships references/contracts/migration-guide-format.md
|
|
4
|
+
(producer side). Cross-plugin imports are forbidden, so changes here must be
|
|
5
|
+
reconciled in BOTH copies. -->
|
|
6
|
+
|
|
7
|
+
`{repo}/.claude/docs/MIGRATION GUIDE.md` is the artifact the forge PRODUCES
|
|
8
|
+
(via `adia-release`, on every breaking cut) and the factory CONSUMES (via
|
|
9
|
+
`adia-migrate`, to drive consumer sweeps). This is the shared shape.
|
|
10
|
+
|
|
11
|
+
## Producer obligations (adia-release, per breaking cut)
|
|
12
|
+
|
|
13
|
+
1. **Version-scope bullet** in the top index: `**\`X.Y.Z\`** — <MINOR/PATCH>
|
|
14
|
+
lockstep cut. <BREAKING: one-line summary | No breaking changes.> See
|
|
15
|
+
[§ vX.Y.Z section below](#anchor).` Every cut gets a bullet, breaking or not —
|
|
16
|
+
the consumer sweep walks this index to find its version span.
|
|
17
|
+
2. **Per-cut section** for breaking cuts, containing, in order:
|
|
18
|
+
- the breaking-change list, each item with: the old form, the new form, and
|
|
19
|
+
a **greppable pattern** (`git grep -n '<old>'`) a consumer can sweep;
|
|
20
|
+
- mechanical vs **judgment items** separated — judgment items (semantic
|
|
21
|
+
flips, behavioral defaults) are explicitly marked *never auto-sweep*;
|
|
22
|
+
- the verify command(s) that prove the sweep landed.
|
|
23
|
+
3. **Anchors are stable** — section headings are linked from release notes and
|
|
24
|
+
consumer tooling; never retitle an existing section.
|
|
25
|
+
4. Soft-API graduations (`_debug.*` → top-level) are documented even though
|
|
26
|
+
non-breaking — consumers key on them.
|
|
27
|
+
|
|
28
|
+
## Consumer expectations (adia-migrate)
|
|
29
|
+
|
|
30
|
+
The sweep discipline reads: index bullet(s) for the span → per-cut sections →
|
|
31
|
+
grep audit with the given patterns → mechanical sweeps → judgment items
|
|
32
|
+
surfaced to the operator → verify gates. A guide entry missing a greppable
|
|
33
|
+
pattern or a verify command is a producer defect — report it upstream, do not
|
|
34
|
+
improvise a sweep.
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
name: data-and-hydration
|
|
3
3
|
load-when: wiring an adia-ui app's data-flow, state ownership, content hydration, or section registration
|
|
4
4
|
load-size: ~2.5k tokens
|
|
5
|
-
required-for: [adia-
|
|
5
|
+
required-for: [adia-data — all modes]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Data, state & hydration — patterns
|
|
9
9
|
|
|
10
|
-
Code shapes for the five data-flow patterns, the three hydration paths, and section wiring. The ownership rules (single-owner · projections-only · attribution) are the `adia-
|
|
10
|
+
Code shapes for the five data-flow patterns, the three hydration paths, and section wiring. The ownership rules (single-owner · projections-only · attribution) are the `adia-data` rubric gates.
|
|
11
11
|
|
|
12
12
|
## The five patterns
|
|
13
13
|
|
|
@@ -41,7 +41,9 @@ await client.mutate({ type: 'order', payload }, { action_source: btn.dataset.act
|
|
|
41
41
|
```js
|
|
42
42
|
table.columns = [{ key:'name', label:'Name', sortable:true }];
|
|
43
43
|
table.data = rows; // NOT: append <option>/<tr> children post-connect —
|
|
44
|
-
select.options = opts; // the element auto-stamps its slots at connected()
|
|
44
|
+
select.options = opts; // the element auto-stamps its slots at connected(); later-
|
|
45
|
+
// appended children land OUTSIDE the stamped popover/listbox
|
|
46
|
+
// as visible flow content and break the parent's layout
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
**5 · Declarative `data-*`** — static flows; state is CSS.
|
|
@@ -59,7 +61,7 @@ select.options = opts; // the element auto-stamps its slots at connected
|
|
|
59
61
|
connected() { if (this.#booted) return; this.#booted = true; this.#load(); }
|
|
60
62
|
```
|
|
61
63
|
|
|
62
|
-
**SSR — server → props → client.** The framework fetches on the server, seeds components as initial props, and the client refreshes via property binding (React `ref`+`useEffect`, Vue `:prop`, Svelte `bind:`). See `adia-
|
|
64
|
+
**SSR — server → props → client.** The framework fetches on the server, seeds components as initial props, and the client refreshes via property binding (React `ref`+`useEffect`, Vue `:prop`, Svelte `bind:`). See `adia-host` / [ssr-integration.md](ssr-integration.md).
|
|
63
65
|
|
|
64
66
|
**Hybrid — SPA island in an SSR page.** The server renders the page and emits the island's seed as a prop/attribute; the island **registers + boots on the client** and owns its own state and in-island routing. The framework owns the page and top-level routing; the island is a self-contained SPA surface inside it.
|
|
65
67
|
|
|
@@ -81,4 +83,5 @@ Rule: exactly one route owner _per scope_ — the framework routes the page; a c
|
|
|
81
83
|
|
|
82
84
|
- **Content-less `<router-ui>`** for in-DOM/in-island tabs: routes _without_ `content`; CSS shows the active view. A content-mode route fetches + `innerHTML`-replaces — wrong for stamped views.
|
|
83
85
|
- **Own the URL** when you need query params: `history.replaceState(...)` and reflect `data-route-path` yourself; don't set `router.routes` (it path-routes and clobbers query params).
|
|
84
|
-
- **Single owner** per piece of state — the
|
|
86
|
+
- **Single owner** per piece of state — the ownership assignments are the `adia-data` rubric gates; the mechanic: a control mutates the route, an observer/CSS reflects it back — never a second source of truth.
|
|
87
|
+
- **Never reset user-set state from a sibling control** — changing one selector (engine, tab) must not auto-reset an unrelated user-controlled one (mode, theme), even if the new selection ignores that setting.
|
package/references/genui-a2ui.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: genui-a2ui
|
|
3
3
|
load-when: authoring a generative-UI experience — mounting the a2ui runtime, feeding generated A2UI, wiring resolvers, or using the corpus
|
|
4
4
|
load-size: ~2.5k tokens
|
|
5
|
-
required-for: [adia-
|
|
5
|
+
required-for: [adia-genui — all modes]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# a2ui runtime & corpus — consumer surface
|
|
@@ -14,8 +14,8 @@ The consumer-facing a2ui runtime (mount + feed + resolve) and corpus (core vs cu
|
|
|
14
14
|
**`<a2ui-root>`** — renders an A2UI surface.
|
|
15
15
|
|
|
16
16
|
- **Author mode:** set `.doc = A2UIMessage[]` (a JS property; setting it re-renders). Use for editors/previews/tests.
|
|
17
|
-
- **Stream mode:** set `src` + `transport` (`sse` | `ws` | `jsonl` | `mcp`); the root opens the stream and reconciles messages as they arrive. (`doc`
|
|
18
|
-
- **Events:** `a2ui-message` (per message) · `a2ui-connected` / `a2ui-error` / `a2ui-closed` (stream) · `a2ui-action` (a child `[data-action]` fired).
|
|
17
|
+
- **Stream mode:** set `src` + `transport` (`sse` | `ws` | `jsonl` | `mcp`); the root opens the stream and reconciles messages as they arrive. (Don't set both — a `doc` reset does not abort an open stream; call `disconnect()` before switching to author mode.)
|
|
18
|
+
- **Events:** `a2ui-message` (per message) · `a2ui-connected` / `a2ui-error` / `a2ui-closed` (stream) · `a2ui-action` (a child `[data-action]` fired).
|
|
19
19
|
|
|
20
20
|
**`<gen-root mode="chat|split|canvas">`** — a layout shell unifying chat + canvas (+ `inspector` to debug the generated tree). Switch layout via `mode`.
|
|
21
21
|
|
|
@@ -30,10 +30,14 @@ The consumer-facing a2ui runtime (mount + feed + resolve) and corpus (core vs cu
|
|
|
30
30
|
|
|
31
31
|
## A2UI message format
|
|
32
32
|
|
|
33
|
+
A2UI describes **layout, not behavior**: component trees + props + data/slot
|
|
34
|
+
bindings + primitive refs — never JS behavior or per-canvas CSS. Behavior comes from the
|
|
35
|
+
substrate's traits or pre-built apps; "make the generator emit JS/CSS" is a won't-fix.
|
|
36
|
+
|
|
33
37
|
A discriminated union the runtime reconciles (set `.doc` to an array of these):
|
|
34
38
|
|
|
35
39
|
- `createSurface` — `{ type, surfaceId, root? }` — start a surface.
|
|
36
|
-
- `updateComponents` — `{ type, surfaceId, components: [{ id, component, children?, ...props }] }` — upsert the tree; `component` is an A2UI type name (`Card`, `Text`, `Stat`, …); other keys are props. A prop can be a **data binding** `{ path: 'kpi/value' }`.
|
|
40
|
+
- `updateComponents` — `{ type, surfaceId, components: [{ id, component, children?, ...props }] }` — upsert the tree; `component` is an A2UI type name (`Card`, `Text`, `Stat`, …); other keys are props. A prop can be a **data binding** `{ path: 'kpi/value' }`. A `textContent` prop only hard-sets text on pure-text leaves (the runtime whitelists them) — on container components it routes through the `text=` attribute instead, because `el.textContent = …` would wipe the slotted children.
|
|
37
41
|
- `updateDataModel` — `{ type, surfaceId, path, value }` — set data (JSON-Pointer path) that bindings read.
|
|
38
42
|
- `wireComponents` — `{ type, surfaceId, controllers?, dataSources?, … }` — declare controllers/handlers/data sources/actions.
|
|
39
43
|
- `meta` — `{ type, feedback? }` — pipeline metadata/reasoning (traces, feedback).
|
|
@@ -49,13 +53,15 @@ Built-in schemes: `resource:` (→ a `/api/...` REST convention), `api:` (direct
|
|
|
49
53
|
|
|
50
54
|
## The loop, end to end
|
|
51
55
|
|
|
52
|
-
`classify_intent` → `assemble_context` (or `search_chunks` to ground) → `generate_ui` → **`validate_schema` + `check_anti_patterns`** → set `root.doc` → `refine_ui
|
|
56
|
+
`classify_intent` → `assemble_context` (or `search_chunks` to ground) → `generate_ui` → **`validate_schema` + `check_anti_patterns`** → set `root.doc` → on failed validation, `refine_ui(intent, previousMessages, validationErrors)` (monolithic; zettel multi-turn refinement uses `refine_composition` with the `state_id` from the prior `compose_from_chunks`). **Validate before every render** — the runtime renders what you give it; garbage in, garbage rendered.
|
|
53
57
|
|
|
54
58
|
## Corpus — core vs roll-your-own
|
|
55
59
|
|
|
56
60
|
- **Shape:** chunks are JSON (`{ name, kind: block|panel|page, component tree, metadata }`), with an `_index`, a `catalog`, and pre-computed `chunk-embeddings`. Harvested from real pages' `data-chunk` markers.
|
|
57
61
|
- **Core:** the MCP ships and retrieves over it — `search_chunks` (keyword always; semantic when `VOYAGE_API_KEY`/OpenAI is set) / `lookup_chunk`. Offline-capable (embeddings are committed).
|
|
58
|
-
- **Roll your own** _(pattern, lightly documented):_ author demo pages → mark regions with `data-chunk` + `data-chunk-kind`/`-domain`/`-description`/`-keywords` →
|
|
62
|
+
- **Roll your own** _(pattern, lightly documented):_ author demo pages → mark regions with `data-chunk` + `data-chunk-kind`/`-slot`/`-domain`/`-description`/`-keywords` (the harvester also reads `-related`/`-tags`) → `npm run harvest:chunks` → point retrieval at your set → (optional) build embeddings (needs a key). **Grounding rule:** every chunk must trace to a real page — no synthetic chunks.
|
|
63
|
+
- **Keep chunks fresh:** after any layout/`@bp` change to `data-chunk`-annotated HTML, re-run `npm run harvest:chunks` in the same session — harvested chunks silently hold the stale values otherwise.
|
|
64
|
+
- **Dev-overlay caveat:** the `?chunks` overlay (`site/dev-chunks.js`) prepends a `<span data-chunk-marker>` into every `[data-chunk]` element — `:first-child`/`:nth-child` rules on those children break during dev only.
|
|
59
65
|
|
|
60
66
|
## Consumer vs maintainer
|
|
61
67
|
|
package/references/llm.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
name: llm
|
|
3
|
+
load-when: wiring @adia-ai/llm — chat/streamChat signatures, StreamChunk handling, the proxy security model
|
|
4
|
+
load-size: ~1.2k tokens
|
|
5
|
+
required-for: [adia-llm]
|
|
6
|
+
---
|
|
2
7
|
|
|
3
|
-
|
|
8
|
+
# `@adia-ai/llm` — the app-side LLM client
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
Chat / streaming / AI features for a consumer app. Snapshot verified against **@adia-ai/llm v0.7.26**. LLM client surfaces drift — confirm precise field names against the installed version and lean on the **smart-proxy contract** (stable) rather than memorized fields.
|
|
6
11
|
|
|
7
|
-
## Import &
|
|
12
|
+
## Import & core API
|
|
8
13
|
|
|
9
14
|
```js
|
|
10
15
|
import { chat, streamChat, createClient } from '@adia-ai/llm';
|
|
@@ -15,16 +20,16 @@ import { MODELS, DEFAULT_MODEL } from '@adia-ai/llm/models';
|
|
|
15
20
|
- `streamChat(opts) → AsyncGenerator<StreamChunk>` — streaming; `for await` the chunks.
|
|
16
21
|
- `createClient(defaults) → { chat, stream }` — a client with baked-in defaults.
|
|
17
22
|
|
|
18
|
-
`ChatOpts` (the fields
|
|
23
|
+
`ChatOpts` (the fields that matter): `model`, `messages: [{role, content}]`, `provider?` (auto-detected from the model name), `system?`, `maxTokens?`, `temperature?`, `signal?` (AbortSignal), `proxyUrl?`, plus Anthropic extras `thinking?` / `cache?`.
|
|
19
24
|
|
|
20
|
-
`StreamChunk` is a tagged union — branch on `chunk.type
|
|
25
|
+
`StreamChunk` is a tagged union — branch on `chunk.type`, handle every branch:
|
|
21
26
|
|
|
22
27
|
```js
|
|
23
28
|
for await (const chunk of streamChat(opts)) {
|
|
24
|
-
if
|
|
25
|
-
else if (chunk.type === 'thinking') showThinking(chunk.text);
|
|
29
|
+
if (chunk.type === 'text') append(chunk.text); // also .snapshot (full text so far)
|
|
30
|
+
else if (chunk.type === 'thinking') showThinking(chunk.text); // Anthropic extended thinking
|
|
26
31
|
else if (chunk.type === 'done') finalize(chunk.usage, chunk.stopReason);
|
|
27
|
-
else if (chunk.type === 'error') fail(chunk.error);
|
|
32
|
+
else if (chunk.type === 'error') fail(chunk.error); // render it — never drop
|
|
28
33
|
}
|
|
29
34
|
```
|
|
30
35
|
|
|
@@ -34,46 +39,24 @@ Anthropic, OpenAI, and Gemini, **auto-detected from the model name** (`claude*`
|
|
|
34
39
|
|
|
35
40
|
## The proxy / security model — read this first
|
|
36
41
|
|
|
37
|
-
**Never ship a provider API key to the browser in production.**
|
|
42
|
+
**Never ship a provider API key to the browser in production.** Two proxy shapes, auto-selected from the `proxyUrl` (a URL matching `/api/llm/<provider>/…` ⇒ passthrough; anything else ⇒ smart):
|
|
38
43
|
|
|
39
|
-
- **Smart proxy (production):** point `proxyUrl` at your own same-origin endpoint (e.g. `/api/chat`). The browser sends a provider-neutral body (`{provider, model, messages,
|
|
44
|
+
- **Smart proxy (production):** point `proxyUrl` at your own same-origin endpoint (e.g. `/api/chat`). The browser sends a provider-neutral body (`{provider, model, messages, system?, maxTokens?, temperature?}`); **your server** holds the real key, reformats per provider, and pipes the SSE bytes back. The browser never sees a key.
|
|
40
45
|
|
|
41
46
|
```js
|
|
42
47
|
for await (const c of streamChat({ proxyUrl: '/api/chat', model, messages })) { … }
|
|
43
48
|
```
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
Reference implementation (monorepo only — `server.js` is not in the npm-published files): `packages/llm/server.js` (`POST /api/chat`).
|
|
46
51
|
|
|
47
|
-
- **Passthrough proxy (
|
|
52
|
+
- **Passthrough proxy (Vite dev ONLY):** a `proxyUrl` matching `/api/llm/<provider>/…` (e.g. a Vite dev proxy). The browser sends the real upstream body **and the real key in headers** — anyone with DevTools can read it. **Never deploy this shape.**
|
|
48
53
|
|
|
49
|
-
When authoring: default to the smart-proxy pattern;
|
|
54
|
+
When authoring: default to the smart-proxy pattern; use passthrough only behind a Vite dev proxy, and say so explicitly.
|
|
50
55
|
|
|
51
|
-
##
|
|
56
|
+
## Chat surface wiring
|
|
52
57
|
|
|
53
|
-
`<chat-shell-
|
|
54
|
-
|
|
55
|
-
```html
|
|
56
|
-
<chat-shell-ui proxy-url="/api/chat" model="claude-sonnet-4-6">
|
|
57
|
-
<chat-header><span slot="name">Assistant</span><chat-status slot="status"></chat-status></chat-header>
|
|
58
|
-
<chat-thread><chat-empty><empty-state-ui heading="Hello!"></empty-state-ui></chat-empty></chat-thread>
|
|
59
|
-
<chat-composer><chat-input-ui placeholder="Message…"></chat-input-ui></chat-composer>
|
|
60
|
-
</chat-shell-ui>
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
- **Properties:** `model`, `provider`, `proxyUrl`, `system`, `thinking`, `streaming`.
|
|
64
|
-
- **Events:** `submit`, `chunk`, `thinking`, `done`, `error`, `abort`, `message`, `clear`.
|
|
65
|
-
- **Methods:** `send(text, {model})`, `appendMessage(...)`, `clear()`, `abort()`; accessors `messages` / `conversation` / `export` / `import(...)`.
|
|
66
|
-
|
|
67
|
-
Set `proxy-url` (or, dev-only, an `apiKey`) and it auto-sends on submit; otherwise it just emits `submit` for you to handle. For SSR, register it client-side like any other component (see `ssr-integration.md`).
|
|
68
|
-
|
|
69
|
-
## Boundary: app LLM vs. UI generation
|
|
70
|
-
|
|
71
|
-
Two separate paths — don't conflate them:
|
|
72
|
-
|
|
73
|
-
- **`@adia-ai/llm`** — a generic chat/streaming client for _your app's_ AI features (a chat box, a summarize button). Knows nothing about A2UI.
|
|
74
|
-
- **a2ui MCP `generate_ui`** — turns an intent into A2UI component markup (retrieval-first, LLM fallback). Use it to _build UI_, then `validate_schema` / `check_anti_patterns` (see `a2ui-mcp-tools.md`).
|
|
75
|
-
- The bridge (`createAdapter` from `@adia-ai/llm/bridge`) is what the A2UI generation pipeline uses internally to call an LLM for that fallback — you rarely call it directly.
|
|
58
|
+
`<chat-shell proxy-url="/api/chat" model="…">` auto-sends on submit via `streamChat` and renders the stream for you; without `proxy-url` (or a dev-only `apiKey` property) it only emits `submit` for you to handle. The full surface — cluster roster, props/events/methods, registration gotchas — lives in [`shell-chat.md`](shell-chat.md); this file owns only the client/proxy contract.
|
|
76
59
|
|
|
77
60
|
## Not in the package (don't assume)
|
|
78
61
|
|
|
79
|
-
Tool/function-calling chunks, structured-output/JSON-schema modes, built-in retry/backoff, and client-side token estimation are **not** surfaced by `@adia-ai/llm`
|
|
62
|
+
Tool/function-calling chunks, structured-output/JSON-schema modes, built-in retry/backoff, and client-side token estimation are **not** surfaced by `@adia-ai/llm` v0.7.26 — handle them in your own server layer. `createAdapter` from `@adia-ai/llm/bridge` is the A2UI generation pipeline's internal LLM adapter; an app rarely calls it directly.
|
package/references/migration.md
CHANGED
|
@@ -1,57 +1,131 @@
|
|
|
1
|
-
|
|
2
|
-
name: migration
|
|
3
|
-
load-when: migrating an adia-ui app — version upgrade, port-to-adia, or mode change
|
|
4
|
-
load-size: ~2.5k tokens
|
|
5
|
-
required-for: [adia-ui-migrate — all types]
|
|
6
|
-
---
|
|
1
|
+
# Migration — types, history, sweep depth
|
|
7
2
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
Consumer migrations: the durable method + the shape of past breaks. The framework MIGRATION
|
|
4
|
+
GUIDE (`.claude/docs/MIGRATION GUIDE.md` in the framework repo — the space in the filename is
|
|
5
|
+
intentional) is the per-version source of truth; its required shape is
|
|
6
|
+
[`contracts/migration-guide-format.md`](contracts/migration-guide-format.md). Loaded by
|
|
7
|
+
`adia-migrate` (all migration types). Versions and examples below are a snapshot, not a registry.
|
|
11
8
|
|
|
12
9
|
## Types
|
|
13
10
|
|
|
14
|
-
- **version-upgrade** — bump `@adia-ai/*` X→Y (lockstep; all packages move together). PATCH
|
|
15
|
-
|
|
16
|
-
- **
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
- **version-upgrade** — bump `@adia-ai/*` X→Y (lockstep; all packages move together). PATCH
|
|
12
|
+
cuts are drop-in; MINOR/MAJOR carry breaking items.
|
|
13
|
+
- **port-to-adia** — an existing app (raw HTML, or legacy `@agent-ui-kit`) → adia-ui: a tag
|
|
14
|
+
rename map (`aui-button`→`button-ui`, `<button>`→`<button-ui>`) + token namespace swap
|
|
15
|
+
(`--n-*`→`--a-*`).
|
|
16
|
+
- **mode-change** — SPA↔SSR: re-own routing (framework router vs `<router-ui>`), registration
|
|
17
|
+
(top-level vs client-hook), and state (signals vs cookies). `adia-host` carries both paths.
|
|
18
|
+
|
|
19
|
+
## The 5-step sweep — depth
|
|
20
|
+
|
|
21
|
+
1. **Read the guide** for the version span: index bullets → per-cut sections. Each breaking
|
|
22
|
+
item ships an old form, a new form, and a greppable pattern (the contract above). A missing
|
|
23
|
+
section, or an item without a pattern/verify command, is a producer defect — pause, report
|
|
24
|
+
upstream; don't improvise a breaking surface.
|
|
25
|
+
2. **Audit** — `git grep -nE '<pattern>'` per item; cluster by component; report file +
|
|
26
|
+
occurrence counts and show the list before changing anything. Consumer code has edge cases
|
|
27
|
+
the canonical regexes don't anticipate (a `variant="danger"` on a non-button custom element
|
|
28
|
+
that shares the prefix).
|
|
29
|
+
3. **Sweep** — mechanical per approved cluster:
|
|
23
30
|
|
|
24
31
|
```bash
|
|
25
32
|
git grep -lE 'button-ui[^>]*variant="danger"' \
|
|
26
33
|
| xargs perl -i -pe 's/(<button-ui[^>]*?)variant="danger"/$1color="danger"/g'
|
|
27
34
|
```
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
Judgment items (below) are flagged, never swept.
|
|
37
|
+
4. **Verify** — `adia-lint` clean of `LEGACY-SHELL`/`NATIVE-PRIMITIVE`; the app's own build +
|
|
38
|
+
the browser gate ([`verification.md`](verification.md)); then the leftover-drift pass below.
|
|
32
39
|
5. **Report** — per-axis counts, manual-review list, gate results, next actions.
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
### Sweep anti-patterns (each shipped a real regression)
|
|
35
42
|
|
|
36
|
-
- **
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- **
|
|
43
|
+
- **One component per sweep.** `<(toast|alert|tag)-ui[^>]*variant="error"` looks efficient, but
|
|
44
|
+
perl/sed alternation captures don't substitute the matched alternative cleanly — loop
|
|
45
|
+
`for tag in toast alert tag` instead.
|
|
46
|
+
- **HTML-attribute regexes don't cover JS property sites.** `<chat-input-ui busy>` and
|
|
47
|
+
`el.busy = true` are two audits — sweep `\.busy\s*=` separately, scoped to app code.
|
|
48
|
+
- **`git grep -lE | xargs perl -i`, never `find … -exec perl`.** git grep excludes
|
|
49
|
+
`node_modules/`, `dist/`, `.git/`; a raw find doesn't.
|
|
40
50
|
|
|
41
|
-
##
|
|
42
|
-
|
|
43
|
-
Semantic flips (`[open]`→`[collapsed]` inverts default visibility), Boolean opt-out inversions (default changes), attribution transfers (`field-ui error` → child input may not exist yet). Surface these with their call sites; let the author decide.
|
|
44
|
-
|
|
45
|
-
## What the path-only sweep misses (leftover-drift categories)
|
|
51
|
+
## Real breaking-change history (before → after)
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
- **v0.0.20 (10 items):** `<button-ui variant="danger">` → `variant="solid" color="danger"`
|
|
54
|
+
(canonical form; the guide's mechanical sweep emits just `color="danger"`, leaning on `solid`
|
|
55
|
+
being the default variant); stage Booleans (`completed`/`active`) → `status="completed|active"`
|
|
56
|
+
enum (timeline/stepper/pipeline); `<table-toolbar-ui>` opt-out Booleans **inverted**
|
|
57
|
+
(`searchable="false"` → `no-search`; default flipped); `<chat-input-ui busy>` → `loading`;
|
|
58
|
+
`variant="error"` alias removed → `danger`; event prefixes dropped (`chat-submit`→`submit`,
|
|
59
|
+
`legend-toggle`→`toggle`, `slide-change`→`change`); `<field-ui error>` moved to the child
|
|
60
|
+
input; `<agent-trace-ui open>` → `collapsed` (**semantic flip — default-visible now**); kebab
|
|
61
|
+
prop keys → camelCase (JS only). Safari floor → 18.
|
|
62
|
+
- **v0.0.29 — three-tier extraction:** `patterns/` moved `@adia-ai/web-components/patterns/*` →
|
|
63
|
+
`@adia-ai/web-modules/{shell,chat,editor,runtime}/*`. Import-path rewrite + add the
|
|
64
|
+
`web-modules` dep.
|
|
65
|
+
- **v0.4.0 — legacy shell shapes retired (ADR-0024):** `<aside data-sidebar>`→`<admin-sidebar
|
|
66
|
+
slot>`; `<dialog data-command>`→`<admin-command>`; `[data-chat-messages/input/empty]`→
|
|
67
|
+
`<chat-thread>/<chat-composer>/<chat-empty>`; `[data-editor-body]/[data-canvas]`→
|
|
68
|
+
`<editor-canvas>` + `<editor-sidebar>`. JS selectors move with the markup. (`adia-lint`
|
|
69
|
+
`LEGACY-SHELL` flags the remnants.)
|
|
70
|
+
- **v0.6.0/0.6.1:** `stat-ui.{js,css}`→`stat.{js,css}` (deep-import only); `<link-ui>` token
|
|
71
|
+
rename `--link-color-*`→`--link-fg-*` (only if you override).
|
|
72
|
+
|
|
73
|
+
## Judgment items (flag with call sites — the author decides, never a sweep)
|
|
74
|
+
|
|
75
|
+
- **Semantic flips** — `<agent-trace-ui open>`→`[collapsed]` is an inversion, not a rename:
|
|
76
|
+
`[open]` was default-hidden/opt-in, `[collapsed]` is default-visible/opt-out. Trace meant to
|
|
77
|
+
show? drop the attribute. Meant hidden? write `collapsed`.
|
|
78
|
+
- **Boolean opt-out inversions** — `<table-toolbar-ui>`: the legacy Booleans defaulted to
|
|
79
|
+
`true`, so a bare `filterable` was a no-op; only an explicit `searchable="false"` carried
|
|
80
|
+
intent (→ `no-search`). A regex can't tell the two apart.
|
|
81
|
+
- **Attribution transfers** — `<field-ui error="…">` moves the message to the child input,
|
|
82
|
+
which may not exist yet in the markup.
|
|
83
|
+
- **JS-only key renames** — kebab property keys (`el['submit-label']`→`el.submitLabel`): the
|
|
84
|
+
HTML attribute form is unchanged, so attribute-only consumers need no change. Audit
|
|
85
|
+
programmatic access only.
|
|
86
|
+
|
|
87
|
+
## Leftover drift — what the path-only sweep misses
|
|
88
|
+
|
|
89
|
+
A vocabulary migration touches the markup but not the CSS selectors that style it, the JS
|
|
90
|
+
comments that mention it, or the metadata that indexes it — different files, so a markup-only
|
|
91
|
+
commit looks complete. Close with a pre/post grep diff:
|
|
48
92
|
|
|
49
93
|
```bash
|
|
50
94
|
grep -rln 'OLD_NAME' . --include='*.md' --include='*.json' | sort > /tmp/pre.txt
|
|
51
95
|
# … sweep …
|
|
52
|
-
grep -rln 'OLD_NAME' . --include='*.md' --include='*.json' | sort > /tmp/post.txt
|
|
96
|
+
grep -rln 'OLD_NAME' . --include='*.md' --include='*.json' | sort > /tmp/post.txt
|
|
97
|
+
diff /tmp/pre.txt /tmp/post.txt # anything left post-sweep is a stale ref to investigate
|
|
53
98
|
```
|
|
54
99
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
100
|
+
Categories that have survived full-path sweeps:
|
|
101
|
+
|
|
102
|
+
- **Bare-name prose mentions** in narrative docs and inventory tables (README, roadmap-style
|
|
103
|
+
indexes) — grep `\b<old-name>\b` over `*.md` / `*.yaml`, not just paths.
|
|
104
|
+
- **Directories named after the renamed thing** (skill dirs, config dirs) — dir vs frontmatter
|
|
105
|
+
mismatch check:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
for skill in $(find . -name 'SKILL.md' -not -path '*/node_modules/*'); do
|
|
109
|
+
dir=$(basename $(dirname "$skill")); name=$(grep -m1 '^name:' "$skill" | sed 's/name: *//')
|
|
110
|
+
[ "$dir" != "$name" ] && echo "MISMATCH: $skill (dir=$dir, name=$name)"
|
|
111
|
+
done
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- **JSON metadata at filename granularity** (highest impact — a stale `source`/`page` field is
|
|
115
|
+
a *silent* harvest miss on the next rebuild; no error is raised):
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
for f in 'old-name.html' 'old-name.contents.html' 'old-name.contents.js'; do
|
|
119
|
+
grep -rn "$f" --include='*.json' | grep -v '/dist/' | grep -v '/node_modules/'
|
|
120
|
+
done
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- **Refs to the directory itself, not the tag** — barrel JS exports, CSS `@import`s, HTML link
|
|
124
|
+
rels, sitemap/content paths name the old *dir*; a tag-rename sweep never touches them. Grep
|
|
125
|
+
the old directory name separately.
|
|
126
|
+
- **Relative-import depth after `git mv`** — grep each moved file for `../` imports and fix the
|
|
127
|
+
depth; builds don't load them, so the breakage surfaces only in the browser. A doc move needs
|
|
128
|
+
a *different* rewrite per linking file's own depth — precompute per file.
|
|
129
|
+
- **Hard-coded source lists in build scripts** — `SOURCES = […]` / include-dir arrays silently
|
|
130
|
+
drop renamed or new siblings while the build runs clean; diff output counts against the
|
|
131
|
+
pre-rename baseline after any rename.
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: project-shapes
|
|
3
|
-
load-when: classifying or laying out an adia-ui app's structure — picking the project shape, the four-axis layout, or page-trio vs page-DUO
|
|
4
|
-
load-size: ~2.5k tokens
|
|
5
|
-
required-for: [adia-ui-factory shape classifier, adia-ui-project (scaffold / add-surface / add-page)]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
1
|
# Project shapes & structure
|
|
9
2
|
|
|
10
|
-
How real adia-ui apps are laid out (synthesized from the chat-ui apps). Three shapes over one four-axis layout, with a page-trio/DUO rule. The **structure rubric** at the bottom is the gate; `bin/adia-scaffold` mechanizes the layout.
|
|
3
|
+
How real adia-ui apps are laid out (synthesized from the chat-ui apps). Three shapes over one four-axis layout, with a page-trio/DUO rule. The **structure rubric** at the bottom is the gate; `bin/adia-scaffold` mechanizes the layout. Loaded by `adia-orient` (shape classifier) and `adia-project` (layout / scaffold / inventory).
|
|
11
4
|
|
|
12
5
|
## The four-axis layout (all shapes)
|
|
13
6
|
|
|
@@ -56,7 +49,7 @@ Use for: a suite of related surfaces (a SaaS admin, a flow set, a demo gallery).
|
|
|
56
49
|
|
|
57
50
|
### Shared-foundation — sibling apps over a shared core
|
|
58
51
|
|
|
59
|
-
Root-level `spec/plan/` for cross-app concerns; each app under `app/<name>/` with its own `spec/plan/src/`; a shared `app/shared/` (DataClient, loaders, mappers, tokens). The embed pattern lives here
|
|
52
|
+
Root-level `spec/plan/` for cross-app concerns; each app under `app/<name>/` with its own `spec/plan/src/`; a shared `app/shared/` (DataClient, loaders, mappers, tokens). The embed pattern lives here — the shell is **`<embed-shell>`** (ships in `@adia-ai/web-modules`, shell cluster); depth: [shell-embed.md](shell-embed.md).
|
|
60
53
|
|
|
61
54
|
```text
|
|
62
55
|
app/
|
|
@@ -75,13 +68,18 @@ Use for: multiple embedded surfaces sharing data context, components, and an emb
|
|
|
75
68
|
|
|
76
69
|
The `.html` shell fetches `.contents.html`, injects it, then dynamically imports `.contents.js` if present. **Rule:** add `.contents.js` only when there's behavior to wire — a DUO with a dead `.contents.js` and a trio missing its setup are both smells.
|
|
77
70
|
|
|
78
|
-
|
|
71
|
+
Two adjacent contracts:
|
|
72
|
+
|
|
73
|
+
- `setup` must be `async function setup(host)` when its body contains top-level `await` — extracting inline page script into a non-async `.contents.js` controller turns that `await` into a parse-time SyntaxError.
|
|
74
|
+
- CSS never takes the `.contents.` infix. HTML/JS get it because they're the dynamically-injected fragment + controller; CSS loads statically via `<link>` in the `.html` shell head and styles chrome + contents together, so its name follows scope (per-app / shared / per-component), not the page-form convention.
|
|
75
|
+
|
|
76
|
+
## State & data — which pattern
|
|
79
77
|
|
|
80
|
-
|
|
78
|
+
The state/data pattern follows the shape, not taste — but the choice is owned by `adia-data`: see [data-and-hydration.md](data-and-hydration.md) for the shape → pattern map.
|
|
81
79
|
|
|
82
80
|
## Components
|
|
83
81
|
|
|
84
|
-
One folder per tag, mirroring the framework: `components/<tag>/<tag>.{js,css}` (folder name = custom-element tag). Authoring discipline:
|
|
82
|
+
One folder per tag, mirroring the framework: `components/<tag>/<tag>.{js,css}` (folder name = custom-element tag). Authoring discipline: [authoring-components.md](authoring-components.md).
|
|
85
83
|
|
|
86
84
|
## Structure rubric `[gate]`
|
|
87
85
|
|
|
@@ -93,4 +91,4 @@ A project is well-structured when (gate = all `[gate]` hold):
|
|
|
93
91
|
- **Components foldered** `[gate]` — every custom element is `components/<tag>/<tag>.{js,css}`.
|
|
94
92
|
- **No duplicated cross-surface code** `[review]` — shared logic lives in `app/shared/` (or `_shared/`), not copied per page.
|
|
95
93
|
|
|
96
|
-
Verify target for a scaffold/edit: this rubric passes, and any new surface renders through `adia-
|
|
94
|
+
Verify target for a scaffold/edit: this rubric passes, and any new surface renders through `adia-verify`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: shell-admin
|
|
3
3
|
load-when: authoring or debugging an admin-shell app frame (sidebar + topbar + command palette + pages)
|
|
4
4
|
load-size: ~2.5k tokens
|
|
5
|
-
required-for: [adia-
|
|
5
|
+
required-for: [adia-shells — admin path]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# admin-shell — the app frame
|
|
@@ -49,7 +49,7 @@ Full SaaS/admin chrome from `@adia-ai/web-modules`. Register the **cluster barre
|
|
|
49
49
|
|
|
50
50
|
## SPA vs SSR
|
|
51
51
|
|
|
52
|
-
SPA mounts the full markup. SSR keeps the shell + chrome fixed and swaps only the **page body** via the framework outlet — replace the inner page content with `{children}` / `<slot/>`; never mount `<router-ui>` (see `adia-
|
|
52
|
+
SPA mounts the full markup. SSR keeps the shell + chrome fixed and swaps only the **page body** via the framework outlet — replace the inner page content with `{children}` / `<slot/>`; never mount `<router-ui>` (see `adia-host`).
|
|
53
53
|
|
|
54
54
|
## Gotchas (mechanized where noted)
|
|
55
55
|
|
|
@@ -61,5 +61,8 @@ SPA mounts the full markup. SSR keeps the shell + chrome fixed and swaps only th
|
|
|
61
61
|
- **Multiple `<admin-page>` in one `<admin-scroll>`** → single-axis scroll breaks; one page per scroll.
|
|
62
62
|
- **`@container (…)` instead of `@container page-content (…)`** → won't react to sidebar collapse.
|
|
63
63
|
- **Legacy shapes** (`<aside data-sidebar>`, `<dialog data-command>`) — retired v0.4.0 (`adia-lint` `LEGACY-SHELL`).
|
|
64
|
+
- **Sidebar nav is `<nav-ui>` + `<nav-item-ui>`**, never `<menu-ui>`/`<menu-item-ui>` — menu-ui is for Popover-API dropdowns, not persistent navigation.
|
|
65
|
+
- **Full-height mount:** an intermediate wrapper (`<main id="app">`) between `body { height: 100dvh; display: flex }` and the shell needs `flex: 1; display: flex; min-height: 0` — without it the flex chain breaks and the shell collapses to content height.
|
|
66
|
+
- **`header-ui` has no CSS of its own** — its icon/heading/description/action grid comes from the parent's `@scope` (`admin-page-header` provides it); bespoke chrome reusing the header-ui vocabulary must supply the grid + text ellipsis locally.
|
|
64
67
|
|
|
65
68
|
Real usage: `apps/saas/app/admin-dashboard/`.
|
package/references/shell-chat.md
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
name: shell-chat
|
|
3
3
|
load-when: authoring a chat-shell LLM conversation surface
|
|
4
4
|
load-size: ~1.5k tokens
|
|
5
|
-
required-for: [adia-
|
|
5
|
+
required-for: [adia-shells — chat path]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# chat-shell — the conversation surface
|
|
9
9
|
|
|
10
|
-
LLM chat chrome from `@adia-ai/web-modules`. Register: `import '@adia-ai/web-modules/chat'`. The **LLM client/proxy/security** lives in `adia-
|
|
10
|
+
LLM chat chrome from `@adia-ai/web-modules`. Register: `import '@adia-ai/web-modules/chat'`. The **LLM client/proxy/security** lives in `adia-llm` — this is the _surface_; that is the _wiring_.
|
|
11
11
|
|
|
12
12
|
## Cluster roster
|
|
13
13
|
|
|
@@ -33,12 +33,14 @@ LLM chat chrome from `@adia-ai/web-modules`. Register: `import '@adia-ai/web-mod
|
|
|
33
33
|
|
|
34
34
|
## Wiring to the LLM
|
|
35
35
|
|
|
36
|
-
Set `proxy-url` (or, dev-only, `apiKey`) and the shell **auto-sends on submit** via `streamChat` and renders the stream for you. Otherwise it just emits `submit` — you call your endpoint and drive the UI with `appendChunk`/`done`/`error`. **Security:** the production pattern is a same-origin smart proxy that holds the key server-side — never ship a provider key to the browser. Full client/proxy contract: `adia-
|
|
36
|
+
Set `proxy-url` (or, dev-only, `apiKey`) and the shell **auto-sends on submit** via `streamChat` and renders the stream for you. Otherwise it just emits `submit` — you call your endpoint and drive the UI with `appendChunk`/`done`/`error`. **Security:** the production pattern is a same-origin smart proxy that holds the key server-side — never ship a provider key to the browser. Full client/proxy contract: `adia-llm`.
|
|
37
37
|
|
|
38
38
|
## Gotchas
|
|
39
39
|
|
|
40
40
|
- Import the **chat barrel**; piecemeal imports leave children unregistered.
|
|
41
|
+
- `chat-input-ui` internally renders `textarea-ui` + `select-ui` (web-components primitives, invisible in your authored HTML) — the app must register those primitives too, or they stay undefined and collapse to 0px.
|
|
41
42
|
- Legacy shapes (`[data-chat-messages]`, `[data-chat-input]`, `[data-chat-empty]`, `[data-chat-name]`) were retired v0.4.0 — use the bespoke tags (`adia-lint` `LEGACY-SHELL`).
|
|
42
43
|
- SSR: register `<chat-shell>` client-side like any component; keep the key server-side.
|
|
44
|
+
- **Reasoning/trace panels must surface their own reliability** — a bare status label (`Domain: data`) reads identically at 3% and 95% confidence; a label that hides the data needed to judge it is pragmatically deceptive. Show the confidence with the claim.
|
|
43
45
|
|
|
44
46
|
Real usage: `apps/genui/app/factory-chat/`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: shell-editor
|
|
3
3
|
load-when: authoring an editor-shell — a design tool / canvas with resizable side panes
|
|
4
4
|
load-size: ~1.2k tokens
|
|
5
|
-
required-for: [adia-
|
|
5
|
+
required-for: [adia-shells — editor path]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# editor-shell — the canvas + panes
|