@adia-ai/adia-ui-factory 0.8.8 → 0.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/CHANGELOG.md +20 -0
- package/package.json +1 -1
- package/skills/adia-audit/evals/evals.json +20 -0
- package/skills/adia-audit/evals/routing-corpus.json +144 -28
- package/skills/adia-charts/SKILL.md +127 -0
- package/skills/adia-charts/evals/evals.json +20 -0
- package/skills/adia-charts/evals/routing-corpus.json +155 -0
- package/skills/adia-charts/references/chart-type-catalog.md +65 -0
- package/skills/adia-charts/references/composition-and-theming.md +113 -0
- package/skills/adia-compose/evals/evals.json +21 -0
- package/skills/adia-compose/evals/routing-corpus.json +63 -67
- package/skills/adia-data/evals/evals.json +20 -0
- package/skills/adia-data/evals/routing-corpus.json +40 -54
- package/skills/adia-genui/evals/evals.json +19 -0
- package/skills/adia-genui/evals/routing-corpus.json +47 -57
- package/skills/adia-host/evals/evals.json +19 -0
- package/skills/adia-host/evals/routing-corpus.json +37 -51
- package/skills/adia-llm/evals/evals.json +19 -0
- package/skills/adia-llm/evals/routing-corpus.json +48 -58
- package/skills/adia-migrate/evals/evals.json +19 -0
- package/skills/adia-migrate/evals/routing-corpus.json +45 -54
- package/skills/adia-orient/evals/evals.json +19 -0
- package/skills/adia-orient/evals/routing-corpus.json +81 -89
- package/skills/adia-patterns/SKILL.md +11 -0
- package/skills/adia-patterns/evals/evals.json +19 -0
- package/skills/adia-patterns/evals/routing-corpus.json +40 -47
- package/skills/adia-project/evals/evals.json +19 -0
- package/skills/adia-project/evals/routing-corpus.json +44 -56
- package/skills/adia-shells/evals/evals.json +19 -0
- package/skills/adia-shells/evals/routing-corpus.json +49 -58
- package/skills/adia-tables/SKILL.md +123 -0
- package/skills/adia-tables/evals/evals.json +20 -0
- package/skills/adia-tables/evals/routing-corpus.json +177 -0
- package/skills/adia-tables/references/advanced-patterns.md +152 -0
- package/skills/adia-tables/references/base-table.md +170 -0
- package/skills/adia-tokens/evals/evals.json +18 -0
- package/skills/adia-tokens/evals/routing-corpus.json +124 -22
- package/skills/adia-verify/evals/evals.json +19 -0
- package/skills/adia-verify/evals/routing-corpus.json +46 -55
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# chart-ui — the 18 types, by data shape
|
|
2
|
+
|
|
3
|
+
All types except **sankey** share the `x`/`y` row shape from the main SKILL.md ( `data:
|
|
4
|
+
[{[x]: label, [y]: value, …}]` ). Sankey is the one structural exception, called out below.
|
|
5
|
+
Every entry is normative — grounded in `chart.class.js`'s actual `#render*()` methods, not the
|
|
6
|
+
rendered docs page's prose.
|
|
7
|
+
|
|
8
|
+
## Axis-based (categorical x, one numeric y)
|
|
9
|
+
|
|
10
|
+
| `type` | Shape | When |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| `bar` (default) | vertical bars, one series | the default choice for "compare N categories" |
|
|
13
|
+
| `line` | line + soft area fill, `smooth` prop tunes the curve (0 = straight segments, 1 = max spline) | a single trend over an ordered axis (time, sequence) |
|
|
14
|
+
| `area` | same renderer family as `line` with the fill emphasized | same use as `line`; visually heavier — prefer for one hero series, not several overlaid |
|
|
15
|
+
| `sparkline` | line variant with minimal chrome, wrapped in `[data-sparkline]` | inline/compact — the canonical use is `<chart-ui slot="chart" type="sparkline">` inside `<stat-ui>` |
|
|
16
|
+
| `scatter` | dots plotted at **evenly-spaced index positions** along x, height by `y` value | index-based, not a true bivariate (x-value, y-value) scatter — `x` still supplies the categorical label, not a second numeric axis. For a real two-numeric-axis scatter, none of the 18 types provide it as-is |
|
|
17
|
+
|
|
18
|
+
## Categorical / part-of-whole
|
|
19
|
+
|
|
20
|
+
| `type` | Shape | When |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `pie` | full-circle slices, one value key | share-of-total across few categories |
|
|
23
|
+
| `donut` | ring slices (inner+outer radius); `radius` prop rounds slice corners | same as pie with a center hole — pairs well with a total/label in the empty center |
|
|
24
|
+
| `segments` | ONE horizontal bar split into proportional colored slices | compact in-card distribution widget where a full pie is too heavy |
|
|
25
|
+
| `treemap` | flat squarified rect tiling, area ∝ value; `x` labels each tile | many categories where relative size matters more than precise comparison; not nested (no `children` hierarchy yet) |
|
|
26
|
+
| `funnel` | trapezoid stages, **array order = funnel order top-to-bottom** (not sorted by value) — auto-computes a drop-off % per stage vs. the first | ordered-stage conversion/dropoff (signup → activation → purchase) |
|
|
27
|
+
|
|
28
|
+
## Radial
|
|
29
|
+
|
|
30
|
+
| `type` | Shape | When |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `radar` | polygon, one series, `x` labels each spoke | multi-attribute comparison of a single subject (skill/score breakdown) |
|
|
33
|
+
| `radial-bar` | concentric rings, one ring per datum, sweep ∝ value/max | comparing several progress-style metrics compactly (a "multi progress ring" widget) |
|
|
34
|
+
| `gauge` | half-donut with center value | one KPI vs. a target — reads `max` from the first datum (`data[0].max`) if present; otherwise a single-row `data` treats the value as-is, multi-row `data` treats row 0 as numerator and the sum of all rows as the denominator ("X of Y") |
|
|
35
|
+
|
|
36
|
+
## Multi-series (comma-separated `y`)
|
|
37
|
+
|
|
38
|
+
| `type` | Shape | When |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `stacked-bar` | bars stacked per category, one segment per `y` key | part-of-whole across categories where the total also matters |
|
|
41
|
+
| `grouped-bar` | bars side-by-side per category, one bar per `y` key | comparing series without summing them |
|
|
42
|
+
| `multi-line` | one line per `y` key, shared axes | comparing several trends over the same axis |
|
|
43
|
+
| `composed` | **bar + line combo** — the FIRST `y` key renders as bars, the SECOND as an overlaid line; a third+ key is ignored | two related metrics on different visual channels (e.g. revenue bars + margin % line) |
|
|
44
|
+
|
|
45
|
+
Multi-series types (`stacked-bar` / `grouped-bar` / `multi-line` / `radial-bar`, plus `pie` /
|
|
46
|
+
`donut`) auto-render an **internal legend** below the chart when no external
|
|
47
|
+
`chart-legend-ui[for]` targets it — single-series types (`bar`, `line`, `area`, `scatter`,
|
|
48
|
+
`sparkline`, `radar`, `gauge`, `funnel`, `treemap`, `segments`) never do, because there is only
|
|
49
|
+
one series to label.
|
|
50
|
+
|
|
51
|
+
## Sankey — the one non-`x`/`y` shape
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<chart-ui type="sankey"></chart-ui>
|
|
55
|
+
```
|
|
56
|
+
```js
|
|
57
|
+
chartEl.data = [
|
|
58
|
+
{ source: 'Visit', target: 'Signup', value: 480 },
|
|
59
|
+
{ source: 'Signup', target: 'Trial', value: 210 },
|
|
60
|
+
];
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`x`/`y` attributes are unused for sankey. Each row is a flow link; node columns (left = sources,
|
|
64
|
+
right = targets) and node heights are auto-derived from the unique `source`/`target` values and
|
|
65
|
+
their summed `value` — `from`/`to`/`v` are accepted as aliases for `source`/`target`/`value`.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Chart family — tokens, events, and the a11y contract
|
|
2
|
+
|
|
3
|
+
## Token roster (`chart-ui`, `@scope (chart-ui)`)
|
|
4
|
+
|
|
5
|
+
| Token | Controls | Default |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `--chart-fg` / `--chart-label` / `--chart-value` | axis text, tick labels, value overlays | `--md-sys-color-neutral-*` roles |
|
|
8
|
+
| `--chart-bar` / `--chart-line` / `--chart-dot` | series fill/stroke when NOT per-series-keyed (single-series types) | `--md-sys-color-primary` |
|
|
9
|
+
| `--chart-bar-hover` | bar hover fill | `--a-primary-bg-hover` |
|
|
10
|
+
| `--chart-grid` / `--chart-axis` / `--chart-border` | gridlines, axis line, empty-state dashed border | `--md-sys-color-neutral-outline-variant` family |
|
|
11
|
+
| `--chart-avg` | the optional overlaid average line (bar/line) | `--md-sys-color-warning` |
|
|
12
|
+
| `--chart-area-opacity` | line-chart area fill opacity (`type="line"`'s `[data-area]`) | `0.15` |
|
|
13
|
+
| `--chart-area-fill-opacity` | `type="area"`'s OWN fill opacity — overrides `--chart-area-opacity` for that type so the fill reads as the dominant series, not a soft accent | `0.35` |
|
|
14
|
+
| `--chart-line-width` | line/multi-line stroke width | `2` |
|
|
15
|
+
| `--chart-radius` | internal-legend swatch DOT corner radius only (`[data-legend-dot]`) — NOT the bar/donut/treemap corner radius; that fallback chain is `radius` PROP → `--a-radius` (computed, ancestor-set) → `6`, resolved per-render by `#resolveRadius()` | `4` |
|
|
16
|
+
| `--chart-max-height` | responsive height cap | `28rem` |
|
|
17
|
+
| `--chart-dot-stroke` | line-chart dot outline color | `--md-sys-color-neutral-background` |
|
|
18
|
+
| `--chart-duration` / `--chart-easing` | hover/transition timing | `--a-duration-fast` / `--a-easing` |
|
|
19
|
+
| `--chart-legend-size` / `--chart-legend-dot-size` | internal auto-legend sizing (pie/donut/stacked-bar/grouped-bar/multi-line/radial-bar) | — |
|
|
20
|
+
| `--chart-segments-gap` / `--chart-pie-gap` | gap between segments/pie slices | `2px` / `1.25px` |
|
|
21
|
+
| `--chart-currency-prefix` | `format="currency"` prefix string | `"$"` (falls back in JS — don't rely on a `:where(:scope)` default cascading) |
|
|
22
|
+
| `--chart-perf-budget` | row count before the one-shot perf warning fires | `5000` |
|
|
23
|
+
| `--chart-0` … `--chart-9` | the 10-slot categorical ramp, aliasing `--a-data-0`…`--a-data-9` | theme-stable data palette |
|
|
24
|
+
|
|
25
|
+
Every color-bearing token above resolves through `--md-sys-color-*` or `--a-*` — never author a
|
|
26
|
+
raw hex/`oklch()` override; recolor by overriding the alias, same law `adia-tokens` states for
|
|
27
|
+
every other surface.
|
|
28
|
+
|
|
29
|
+
## Per-series color override — `--color-{key}`
|
|
30
|
+
|
|
31
|
+
For multi-series charts (`y="revenue,users"`), `chart-ui` injects one inline custom property per
|
|
32
|
+
declared series onto the HOST at render time: `--color-revenue: var(--chart-0)`,
|
|
33
|
+
`--color-users: var(--chart-1)`, etc. (slot = index into the 10-slot ramp, wrapping past 10).
|
|
34
|
+
Every series-keyed SVG element's fill/stroke reads `var(--color-{key}, var(--chart-{slot}))`.
|
|
35
|
+
|
|
36
|
+
To recolor ONE named series without touching the rest, set `--color-{key}` on the chart or any
|
|
37
|
+
ancestor:
|
|
38
|
+
|
|
39
|
+
```css
|
|
40
|
+
chart-ui#revenue-trend { --color-users: var(--md-sys-color-tertiary); }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`chart-legend-ui` reads the SAME `--color-{key}` variable for its swatches (falling back to
|
|
44
|
+
`--a-data-{slot}` directly, since a standalone legend may have no chart-ui ancestor to inherit
|
|
45
|
+
the chart-scoped `--chart-{N}` alias from) — override once, chart and legend swatch stay in
|
|
46
|
+
sync automatically.
|
|
47
|
+
|
|
48
|
+
## Event contract
|
|
49
|
+
|
|
50
|
+
All four event NAMES bubble and are shared by `chart-ui` and `heatmap-ui` (heatmap re-emits its
|
|
51
|
+
own `cell-hover`/`cell-click` under these same names so a listener never needs to branch on
|
|
52
|
+
chart kind) — the DETAIL shape differs in the two ways called out below the table, so treat
|
|
53
|
+
`chart-ui`'s shape as the fuller case, not the shared contract:
|
|
54
|
+
|
|
55
|
+
| Event | Fires | Detail |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `chart-hover` | pointer enters a datum (bar/dot/slice/cell); re-fires only when the hovered datum CHANGES | `{ label, value, pct, series, slot, payload, pointerX, pointerY }` |
|
|
58
|
+
| `chart-leave` | pointer leaves the plot area, or a previously-hovered datum with nothing new entering | none |
|
|
59
|
+
| `chart-select` | click/tap on a datum, or Enter/Space on the keyboard-focused datum | same shape as `chart-hover` (pointer coords are synthesized at the focused datum's center for keyboard-triggered selects, so `pointerX`/`pointerY` are always populated) |
|
|
60
|
+
| `legend-update` | the chart's internal `legendData` payload regenerates | none — signal-only; `chart-legend-ui[for]` listens for this to repaint (chart-ui only — see the wiring section below) |
|
|
61
|
+
|
|
62
|
+
`detail.payload` is an array, one entry per series AT THE SAME X COLUMN (multi-series types) —
|
|
63
|
+
`{ series, label, value, pct, slot, hovered }` per entry — so a single `tooltip-ui` can render
|
|
64
|
+
every series' value for the hovered category, not just the one datum the pointer is literally
|
|
65
|
+
over. Single-series types populate `payload` with one entry mirroring the top-level fields.
|
|
66
|
+
**`heatmap-ui`'s detail has no `payload` field at all** (cells are independent, not columns of a
|
|
67
|
+
shared series) — a shared tooltip must treat `payload` as optional. `heatmap-ui` also re-fires
|
|
68
|
+
`chart-hover` on every pointer move inside the SAME cell (to reposition a pointer-follow
|
|
69
|
+
tooltip), which the "only fires when the hovered datum changes" row above describes for
|
|
70
|
+
`chart-ui`, not for `heatmap-ui` — dedupe on `(r, c)` if a listener needs change-only semantics
|
|
71
|
+
for heatmap cells.
|
|
72
|
+
|
|
73
|
+
Wire ONE `tooltip-ui[follows="pointer"][for="chart-id"]` rather than a per-chart-kind listener —
|
|
74
|
+
its presence suppresses `chart-ui`'s internal tooltip popup automatically (detected via
|
|
75
|
+
`document.querySelector('tooltip-ui[follows="pointer"][for=...]')`), so there's no double-render
|
|
76
|
+
to guard against.
|
|
77
|
+
|
|
78
|
+
## `chart-legend-ui` wiring
|
|
79
|
+
|
|
80
|
+
- `[for="chart-id"]` auto-mirrors **`chart-ui` targets only**: the legend reads the target's
|
|
81
|
+
`.legendData` property and re-paints on that target's `legend-update` event. Requires the
|
|
82
|
+
chart to have a matching `id`. Pointing `[for]` at a `heatmap-ui` id silently resolves to an
|
|
83
|
+
empty legend — heatmap-ui never sets `.legendData` or dispatches `legend-update`; use its own
|
|
84
|
+
built-in Less/More strip (`no-legend` prop to hide it) instead.
|
|
85
|
+
- `items='[{"key","label","slot?","pct?"}, …]'` is explicit data and ALWAYS wins over `[for]`
|
|
86
|
+
when both are present — use it for a legend with no live chart-ui counterpart.
|
|
87
|
+
- Clicking a row fires `toggle` (`{ key, active, mode }`); when wired via `[for]`, `chart-ui`
|
|
88
|
+
listens for this on `document` and hides (`on-toggle="hide"`, default) or fades
|
|
89
|
+
(`on-toggle="opacity"`) that series — no manual event handler needed for the common case.
|
|
90
|
+
- `static` renders non-interactive `badge-ui` rows (no `role`/`tabindex`, no toggle affordance)
|
|
91
|
+
for a legend that's pure labeling, not a filter control — rows are `badge-ui` chips in both
|
|
92
|
+
modes (composed, not hand-rolled `<span>`s, since 2026-05-01).
|
|
93
|
+
- `shape="dot|square|line|dashed"` — `line`/`dashed` exist because those swatch shapes aren't
|
|
94
|
+
representable as an icon glyph; match `line`/`multi-line` charts to `shape="line"`,
|
|
95
|
+
categorical charts to `dot` or `square`.
|
|
96
|
+
|
|
97
|
+
## Accessibility & keyboard
|
|
98
|
+
|
|
99
|
+
`chart-ui` sets `role="img"` and an auto-generated `aria-label` ("`{type} chart`") unless the
|
|
100
|
+
author supplies their own. It is natively keyboard-navigable (`tabindex="0"` auto-applied):
|
|
101
|
+
|
|
102
|
+
| Key | Action |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `ArrowRight` / `ArrowDown` | move virtual focus to the next datum |
|
|
105
|
+
| `ArrowLeft` / `ArrowUp` | move virtual focus to the previous datum |
|
|
106
|
+
| `Home` / `End` | jump to first / last datum |
|
|
107
|
+
| `Enter` / `Space` | fire `chart-select` for the focused datum |
|
|
108
|
+
| `Escape` | clear focus, fire `chart-leave` |
|
|
109
|
+
|
|
110
|
+
Keyboard focus emits the SAME `chart-hover` event the pointer path uses, so a
|
|
111
|
+
`tooltip-ui[follows="pointer"][for]` tracks keyboard navigation for free — author it once and
|
|
112
|
+
both interaction modes work. Per-datum focus paints via `[data-a11y-focus]` + the standard
|
|
113
|
+
`--a-focus-ring` recipe; nothing extra to author.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "adia-compose",
|
|
3
|
+
"note": "Trigger-routing suite (gh#369). expect=trigger: the skill should fire on the prompt in a fresh session. expect=no-trigger: a near-miss owned elsewhere (owner named per case) or generic knowledge with no AdiaUI skill involved. Cases derived from evals/routing-corpus.json's phrases array (gh#355 vetted corpus, with rationale) plus the SKILL.md description's own trigger/NOT-fence language.",
|
|
4
|
+
"cases": [
|
|
5
|
+
{ "id": "t01", "prompt": "Build a settings screen for our app", "expect": "trigger" },
|
|
6
|
+
{ "id": "t02", "prompt": "Generate UI for a dashboard from this PRD, as part of the build right now", "expect": "trigger" },
|
|
7
|
+
{ "id": "t03", "prompt": "Compose a form from the catalog", "expect": "trigger" },
|
|
8
|
+
{ "id": "t04", "prompt": "Turn this PRD into a working screen", "expect": "trigger" },
|
|
9
|
+
{ "id": "t05", "prompt": "Convert this Figma export into adia-ui markup for our checkout app", "expect": "trigger" },
|
|
10
|
+
{ "id": "t06", "prompt": "As a user I want to filter my orders — build the screen for that", "expect": "trigger" },
|
|
11
|
+
{ "id": "t07", "prompt": "Theme this screen with our brand tokens and add dark mode", "expect": "trigger" },
|
|
12
|
+
{ "id": "t08", "prompt": "The catalog has nothing for a rating stepper — author a project component in our checkout app to compose it", "expect": "trigger" },
|
|
13
|
+
{ "id": "t09", "prompt": "Compose a confirmation modal flow for deleting a record", "expect": "trigger" },
|
|
14
|
+
{ "id": "n01", "prompt": "Wire up the a2ui runtime so end users can generate their own dashboard layout at runtime", "expect": "no-trigger", "owner": "adia-genui" },
|
|
15
|
+
{ "id": "n02", "prompt": "Pick a shell for the admin app with a sidebar and topbar", "expect": "no-trigger", "owner": "adia-shells" },
|
|
16
|
+
{ "id": "n03", "prompt": "Set up index.html and SSR registration for our Next.js adia-ui app", "expect": "no-trigger", "owner": "adia-host" },
|
|
17
|
+
{ "id": "n04", "prompt": "Add a new primitive component to packages/web-components in the adia-ui monorepo", "expect": "no-trigger", "owner": "adia-author" },
|
|
18
|
+
{ "id": "n05", "prompt": "Run the browser QA gate on the settings screen we just built and check for console errors", "expect": "no-trigger", "owner": "adia-verify" },
|
|
19
|
+
{ "id": "n06", "prompt": "Wire up state hydration for this island using signals", "expect": "no-trigger", "owner": "adia-data" }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -1,216 +1,212 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"name": "adia-compose routing accuracy corpus",
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"purpose": "Routing-eval corpus for adia-compose (adia-ui-factory plugin). Each phrase declares whether adia-compose SHOULD be the routing target. Scored by the estate's TF-IDF routing-eval runner against the skill's description (heuristic token overlap).",
|
|
6
6
|
"scoring_notes": "Heuristic signal, not ground truth. Treat misroutes as a prompt to tighten the skill description, never as a reason to keyword-stuff it. Real harness routing is LLM-driven.",
|
|
7
7
|
"license": "internal",
|
|
8
|
-
"scope": "adia-compose routing
|
|
9
|
-
|
|
10
|
-
"minimums_per_spec": {
|
|
11
|
-
"trigger_phrases": 21,
|
|
12
|
-
"adversarial_phrases": 6,
|
|
13
|
-
"task_shapes_covered": "generic-build, dashboard-generation, form-composition, prd-to-ui, spec-to-ui, mockup-to-ui, user-story-to-ui, navigation-pattern, theming, project-component-authoring, overlay-composition",
|
|
14
|
-
"adversarial_fraction": "22%"
|
|
15
|
-
},
|
|
16
|
-
|
|
8
|
+
"scope": "adia-compose routing \u2014 does this phrase activate adia-compose (build-time, one-shot screen construction from the light-DOM catalog)?",
|
|
17
9
|
"phrases": [
|
|
18
10
|
{
|
|
19
11
|
"id": "compose-generic-01",
|
|
20
12
|
"phrase": "build a settings screen for our app",
|
|
21
|
-
"
|
|
13
|
+
"expected": "adia-compose",
|
|
22
14
|
"expected_shape": "generic-build",
|
|
23
|
-
"rationale": "Canonical 'build a screen' ask
|
|
15
|
+
"rationale": "Canonical 'build a screen' ask \u2014 the skill's own description phrase."
|
|
24
16
|
},
|
|
25
17
|
{
|
|
26
18
|
"id": "compose-generic-02",
|
|
27
19
|
"phrase": "generate UI for a dashboard",
|
|
28
|
-
"
|
|
20
|
+
"expected": "adia-compose",
|
|
29
21
|
"expected_shape": "dashboard-generation",
|
|
30
22
|
"rationale": "'generate UI for' is the skill description's own trigger phrase."
|
|
31
23
|
},
|
|
32
24
|
{
|
|
33
25
|
"id": "compose-generic-03",
|
|
34
26
|
"phrase": "compose a form from the catalog",
|
|
35
|
-
"
|
|
27
|
+
"expected": "adia-compose",
|
|
36
28
|
"expected_shape": "form-composition",
|
|
37
|
-
"rationale": "Explicit 'compose ... from the catalog'
|
|
29
|
+
"rationale": "Explicit 'compose ... from the catalog' \u2014 the skill's core loop."
|
|
38
30
|
},
|
|
39
31
|
{
|
|
40
32
|
"id": "compose-prd-01",
|
|
41
33
|
"phrase": "turn this PRD into a working screen",
|
|
42
|
-
"
|
|
34
|
+
"expected": "adia-compose",
|
|
43
35
|
"expected_shape": "prd-to-ui",
|
|
44
|
-
"rationale": "PRD-shaped input needing UI
|
|
36
|
+
"rationale": "PRD-shaped input needing UI \u2014 triggers the spec-to-ui precondition gate."
|
|
45
37
|
},
|
|
46
38
|
{
|
|
47
39
|
"id": "compose-spec-01",
|
|
48
|
-
"phrase": "here's the product spec
|
|
49
|
-
"
|
|
40
|
+
"phrase": "here's the product spec \u2014 build the UI for it",
|
|
41
|
+
"expected": "adia-compose",
|
|
50
42
|
"expected_shape": "spec-to-ui",
|
|
51
43
|
"rationale": "Spec-shaped input needing UI, per the skill description's 'PRD/spec/mockup needs UI'."
|
|
52
44
|
},
|
|
53
45
|
{
|
|
54
46
|
"id": "compose-mockup-01",
|
|
55
47
|
"phrase": "implement this mockup screenshot as adia-ui components",
|
|
56
|
-
"
|
|
48
|
+
"expected": "adia-compose",
|
|
57
49
|
"expected_shape": "mockup-to-ui",
|
|
58
50
|
"rationale": "Mockup-to-components composition, explicit adia-ui target."
|
|
59
51
|
},
|
|
60
52
|
{
|
|
61
53
|
"id": "compose-mockup-02",
|
|
62
54
|
"phrase": "convert this Figma export into adia-ui markup for our checkout app",
|
|
63
|
-
"
|
|
55
|
+
"expected": "adia-compose",
|
|
64
56
|
"expected_shape": "mockup-to-ui",
|
|
65
57
|
"rationale": "Consumer-side mockup composition into catalog primitives (distinct from figma-generate-* MCP skills, which push code INTO Figma, not the reverse)."
|
|
66
58
|
},
|
|
67
59
|
{
|
|
68
60
|
"id": "compose-schema-01",
|
|
69
61
|
"phrase": "given this user schema, generate the settings form",
|
|
70
|
-
"
|
|
62
|
+
"expected": "adia-compose",
|
|
71
63
|
"expected_shape": "spec-to-ui",
|
|
72
|
-
"rationale": "Schema-shaped input driving form generation
|
|
64
|
+
"rationale": "Schema-shaped input driving form generation \u2014 spec-to-ui-reasoning gate applies."
|
|
73
65
|
},
|
|
74
66
|
{
|
|
75
67
|
"id": "compose-userstory-01",
|
|
76
|
-
"phrase": "as a user I want to filter my orders
|
|
77
|
-
"
|
|
68
|
+
"phrase": "as a user I want to filter my orders \u2014 build the screen for that",
|
|
69
|
+
"expected": "adia-compose",
|
|
78
70
|
"expected_shape": "user-story-to-ui",
|
|
79
71
|
"rationale": "User-story input needing a built screen."
|
|
80
72
|
},
|
|
81
73
|
{
|
|
82
74
|
"id": "compose-dashboard-02",
|
|
83
75
|
"phrase": "put together an analytics dashboard with charts and a legend",
|
|
84
|
-
"
|
|
76
|
+
"expected": "adia-compose",
|
|
85
77
|
"expected_shape": "dashboard-generation",
|
|
86
78
|
"rationale": "Dashboard build using chart-ui/chart-legend-ui catalog primitives."
|
|
87
79
|
},
|
|
88
80
|
{
|
|
89
81
|
"id": "compose-nav-01",
|
|
90
82
|
"phrase": "compose the sidebar navigation pattern for the app",
|
|
91
|
-
"
|
|
83
|
+
"expected": "adia-compose",
|
|
92
84
|
"expected_shape": "navigation-pattern",
|
|
93
|
-
"rationale": "Navigation pattern composition
|
|
85
|
+
"rationale": "Navigation pattern composition \u2014 nav-ui/nav-item-ui selection, per description's 'navigation pattern' trigger."
|
|
94
86
|
},
|
|
95
87
|
{
|
|
96
88
|
"id": "compose-nav-02",
|
|
97
89
|
"phrase": "build a command palette for quick actions",
|
|
98
|
-
"
|
|
90
|
+
"expected": "adia-compose",
|
|
99
91
|
"expected_shape": "navigation-pattern",
|
|
100
|
-
"rationale": "command-ui composition
|
|
92
|
+
"rationale": "command-ui composition \u2014 a named component-selection pick in the skill."
|
|
101
93
|
},
|
|
102
94
|
{
|
|
103
95
|
"id": "compose-form-02",
|
|
104
96
|
"phrase": "wire up a multi-step form using field-ui and select-ui",
|
|
105
|
-
"
|
|
97
|
+
"expected": "adia-compose",
|
|
106
98
|
"expected_shape": "form-composition",
|
|
107
|
-
"rationale": "Explicit catalog primitive names (field-ui, select-ui)
|
|
99
|
+
"rationale": "Explicit catalog primitive names (field-ui, select-ui) \u2014 screen markup composition."
|
|
108
100
|
},
|
|
109
101
|
{
|
|
110
102
|
"id": "compose-theme-01",
|
|
111
103
|
"phrase": "theme this screen with our brand tokens and add dark mode",
|
|
112
|
-
"
|
|
104
|
+
"expected": "adia-compose",
|
|
113
105
|
"expected_shape": "theming",
|
|
114
|
-
"rationale": "Theming via --a-* tokens and scheme toggle
|
|
106
|
+
"rationale": "Theming via --a-* tokens and scheme toggle \u2014 the skill's step 4."
|
|
115
107
|
},
|
|
116
108
|
{
|
|
117
109
|
"id": "compose-theme-02",
|
|
118
110
|
"phrase": "apply the --a-* token set and wire the scheme toggle for this page",
|
|
119
|
-
"
|
|
111
|
+
"expected": "adia-compose",
|
|
120
112
|
"expected_shape": "theming",
|
|
121
113
|
"rationale": "Direct --a-* token + <toggle-scheme-ui> mention, matches description's 'themes via --a-* tokens'."
|
|
122
114
|
},
|
|
123
115
|
{
|
|
124
116
|
"id": "compose-project-comp-01",
|
|
125
|
-
"phrase": "the catalog has nothing for a rating stepper
|
|
126
|
-
"
|
|
117
|
+
"phrase": "the catalog has nothing for a rating stepper \u2014 author a project component in our checkout app to compose it",
|
|
118
|
+
"expected": "adia-compose",
|
|
127
119
|
"expected_shape": "project-component-authoring",
|
|
128
|
-
"rationale": "'Author only what's missing'
|
|
120
|
+
"rationale": "'Author only what's missing' \u2014 a light-DOM PROJECT component in a consumer app, step 3 of the compose loop (distinct from adia-author's framework primitives, see compose-adv-04)."
|
|
129
121
|
},
|
|
130
122
|
{
|
|
131
123
|
"id": "compose-project-comp-02",
|
|
132
124
|
"phrase": "no primitive fits this bespoke billing-summary widget; build it as a project component for our app",
|
|
133
|
-
"
|
|
125
|
+
"expected": "adia-compose",
|
|
134
126
|
"expected_shape": "project-component-authoring",
|
|
135
127
|
"rationale": "Consumer-app project component authored to fill a catalog gap, still inside adia-compose's remit."
|
|
136
128
|
},
|
|
137
129
|
{
|
|
138
130
|
"id": "compose-empty-01",
|
|
139
131
|
"phrase": "add an empty state to the search results screen",
|
|
140
|
-
"
|
|
132
|
+
"expected": "adia-compose",
|
|
141
133
|
"expected_shape": "generic-build",
|
|
142
|
-
"rationale": "empty-state-ui selection inside an existing screen
|
|
134
|
+
"rationale": "empty-state-ui selection inside an existing screen \u2014 ordinary composition edit."
|
|
143
135
|
},
|
|
144
136
|
{
|
|
145
137
|
"id": "compose-table-01",
|
|
146
138
|
"phrase": "build a data table screen listing all invoices",
|
|
147
|
-
"
|
|
139
|
+
"expected": "adia-compose",
|
|
148
140
|
"expected_shape": "generic-build",
|
|
149
141
|
"rationale": "table-ui composition for a new screen."
|
|
150
142
|
},
|
|
151
143
|
{
|
|
152
144
|
"id": "compose-modal-01",
|
|
153
145
|
"phrase": "compose a confirmation modal flow for deleting a record",
|
|
154
|
-
"
|
|
146
|
+
"expected": "adia-compose",
|
|
155
147
|
"expected_shape": "overlay-composition",
|
|
156
148
|
"rationale": "confirm-dialog-ui/modal-ui overlay selection and wiring."
|
|
157
149
|
},
|
|
158
150
|
{
|
|
159
151
|
"id": "compose-genui-boundary-01",
|
|
160
152
|
"phrase": "generate UI for a one-off pricing page from this spec, right now, as part of the build",
|
|
161
|
-
"
|
|
153
|
+
"expected": "adia-compose",
|
|
162
154
|
"expected_shape": "prd-to-ui",
|
|
163
|
-
"rationale": "Boundary case (direction 1 of 2, paired with compose-adv-01): 'generate UI' language, but the ask is a single build-time authoring pass, not an end-user-triggered runtime experience
|
|
155
|
+
"rationale": "Boundary case (direction 1 of 2, paired with compose-adv-01): 'generate UI' language, but the ask is a single build-time authoring pass, not an end-user-triggered runtime experience \u2014 stays adia-compose."
|
|
164
156
|
},
|
|
165
|
-
|
|
166
157
|
{
|
|
167
158
|
"id": "compose-adv-01",
|
|
168
159
|
"phrase": "wire up the a2ui runtime so end users can generate their own dashboard layout at runtime",
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
160
|
+
"expected": "adia-genui",
|
|
161
|
+
"rationale": "Adversarial (direction 2 of 2, paired with compose-genui-boundary-01) \u2014 END USERS trigger generation at runtime via a2ui-root/gen-root; adia-compose's description NEG-fences 'runtime gen-UI (adia-genui)'.",
|
|
162
|
+
"expected_alternative_raw": "adia-genui (adia-factory plugin)"
|
|
172
163
|
},
|
|
173
164
|
{
|
|
174
165
|
"id": "compose-adv-02",
|
|
175
166
|
"phrase": "pick a shell for the admin app with a sidebar and topbar",
|
|
176
|
-
"
|
|
177
|
-
"
|
|
178
|
-
"
|
|
167
|
+
"expected": "adia-shells",
|
|
168
|
+
"rationale": "Adversarial \u2014 shell CHROME selection (admin/chat/editor/simple/embed), not screen content inside one; adia-compose's description NEG-fences 'shell chrome (adia-shells)'.",
|
|
169
|
+
"expected_alternative_raw": "adia-shells (adia-factory plugin)"
|
|
179
170
|
},
|
|
180
171
|
{
|
|
181
172
|
"id": "compose-adv-03",
|
|
182
173
|
"phrase": "set up index.html and SSR registration for our Next.js adia-ui app",
|
|
183
|
-
"
|
|
184
|
-
"
|
|
185
|
-
"
|
|
174
|
+
"expected": "adia-host",
|
|
175
|
+
"rationale": "Adversarial \u2014 host bootstrap/registration/SSR wiring; adia-compose's description NEG-fences 'host wiring (adia-host)'.",
|
|
176
|
+
"expected_alternative_raw": "adia-host (adia-factory plugin)"
|
|
186
177
|
},
|
|
187
178
|
{
|
|
188
179
|
"id": "compose-adv-04",
|
|
189
180
|
"phrase": "add a new primitive component to packages/web-components in the adia-ui monorepo",
|
|
190
|
-
"
|
|
191
|
-
"
|
|
192
|
-
"
|
|
181
|
+
"expected": "adia-author",
|
|
182
|
+
"rationale": "Adversarial \u2014 authoring a FRAMEWORK primitive inside the monorepo itself, not a project component in a consumer app; this is adia-author's remit ('primitives, shells, demos, component yaml SoTs'), the subtle authoring-side-of-the-house boundary paired with compose-project-comp-01/02.",
|
|
183
|
+
"expected_alternative_raw": "adia-author (adia-ui-forge plugin)"
|
|
193
184
|
},
|
|
194
185
|
{
|
|
195
186
|
"id": "compose-adv-05",
|
|
196
187
|
"phrase": "run the browser QA gate on the settings screen we just built and check for console errors",
|
|
197
|
-
"
|
|
198
|
-
"
|
|
199
|
-
"
|
|
188
|
+
"expected": "adia-verify",
|
|
189
|
+
"rationale": "Adversarial \u2014 QA of an already-built screen (headless render, console errors, a11y checks), not composing or fixing the UI; adia-verify's description owns 'verify/QA this page'.",
|
|
190
|
+
"expected_alternative_raw": "adia-verify (adia-factory plugin)"
|
|
200
191
|
},
|
|
201
192
|
{
|
|
202
193
|
"id": "compose-adv-06",
|
|
203
194
|
"phrase": "wire up state hydration for this island using signals",
|
|
204
|
-
"
|
|
205
|
-
"
|
|
206
|
-
"
|
|
195
|
+
"expected": "adia-data",
|
|
196
|
+
"rationale": "Adversarial \u2014 data/state/hydration pattern choice, not screen markup; adia-data's description owns 'wire up the data' / 'hydrate the island'.",
|
|
197
|
+
"expected_alternative_raw": "adia-data (adia-factory plugin)"
|
|
207
198
|
}
|
|
208
199
|
],
|
|
209
|
-
|
|
200
|
+
"minimums_per_spec": {
|
|
201
|
+
"trigger_phrases": 21,
|
|
202
|
+
"adversarial_phrases": 6,
|
|
203
|
+
"task_shapes_covered": "generic-build, dashboard-generation, form-composition, prd-to-ui, spec-to-ui, mockup-to-ui, user-story-to-ui, navigation-pattern, theming, project-component-authoring, overlay-composition",
|
|
204
|
+
"adversarial_fraction": "22%"
|
|
205
|
+
},
|
|
210
206
|
"evaluator_notes": {
|
|
211
207
|
"current_state": "27 cases (21 trigger + 6 adversarial). Each of the 11 task shapes has at least 1 trigger case; the two highest-collision task shapes (dashboard-generation, form-composition, navigation-pattern) get 2 each. The adia-genui boundary is covered in both directions (compose-genui-boundary-01 stays adia-compose; compose-adv-01 routes away to adia-genui) since the build-time/runtime distinction is the sharpest and most-collided fence in the factory plugin.",
|
|
212
|
-
"promotion_criteria": "Promote to a CI gate (warn
|
|
208
|
+
"promotion_criteria": "Promote to a CI gate (warn \u2192 hard-fail) when F1 \u2265 0.85 on this corpus across 3+ consecutive runs without description edits.",
|
|
213
209
|
"review_cadence": "Re-run on every adia-compose description edit. Add 1-2 new cases per checkpoint reflecting newly-observed routing failure modes, especially at the adia-genui and adia-author (forge) fences.",
|
|
214
|
-
"known_limitations": "compose-project-comp-01/02 vs compose-adv-04 (adia-author) share heavy token overlap ('primitive', 'component', 'author')
|
|
210
|
+
"known_limitations": "compose-project-comp-01/02 vs compose-adv-04 (adia-author) share heavy token overlap ('primitive', 'component', 'author') \u2014 the heuristic TF-IDF scorer may not disambiguate monorepo-internal authoring from consumer-app project-component authoring; the harness's live project-context probe (`isFrameworkMonorepo`) disambiguates this in practice, which the heuristic corpus cannot see."
|
|
215
211
|
}
|
|
216
212
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "adia-data",
|
|
3
|
+
"note": "Trigger-routing suite (gh#369). expect=trigger: the skill should fire on the prompt in a fresh session. expect=no-trigger: a near-miss owned elsewhere (owner named per case) or generic knowledge with no AdiaUI skill involved. Cases derived from evals/routing-corpus.json's phrases array (gh#355 vetted corpus, with rationale) plus the SKILL.md description's own trigger/NOT-fence language.",
|
|
4
|
+
"cases": [
|
|
5
|
+
{ "id": "t01", "prompt": "Wire up the data for this dashboard's summary cards", "expect": "trigger" },
|
|
6
|
+
{ "id": "t02", "prompt": "Pick a state pattern for this table — signals or DataClient?", "expect": "trigger" },
|
|
7
|
+
{ "id": "t03", "prompt": "Add CRUD with undo support to the invoice list", "expect": "trigger" },
|
|
8
|
+
{ "id": "t04", "prompt": "Connect the table-ui to the backend via typed reads and pure mappers", "expect": "trigger" },
|
|
9
|
+
{ "id": "t05", "prompt": "Why does my chart-ui drop rows appended after connect?", "expect": "trigger" },
|
|
10
|
+
{ "id": "t06", "prompt": "The state change isn't round-tripping through the signal — mutate doesn't update the projection", "expect": "trigger" },
|
|
11
|
+
{ "id": "t07", "prompt": "Seed the server-fetched props into this SPA island's client-boot state", "expect": "trigger" },
|
|
12
|
+
{ "id": "t08", "prompt": "The SSR framework already fetches the data — wire the initial props into the components", "expect": "trigger" },
|
|
13
|
+
{ "id": "n01", "prompt": "Register the client-side components for this new SPA host", "expect": "no-trigger", "owner": "adia-host" },
|
|
14
|
+
{ "id": "n02", "prompt": "Getting 'HTMLElement is not defined' after upgrading to Next.js", "expect": "no-trigger", "owner": "adia-host" },
|
|
15
|
+
{ "id": "n03", "prompt": "Manage the state for the streaming chat responses in the chat box", "expect": "no-trigger", "owner": "adia-llm" },
|
|
16
|
+
{ "id": "n04", "prompt": "Build the markup for this data table's screen", "expect": "no-trigger", "owner": "adia-compose" },
|
|
17
|
+
{ "id": "n05", "prompt": "Pick the on-disk shape for this new rollup app", "expect": "no-trigger", "owner": "adia-project" },
|
|
18
|
+
{ "id": "n06", "prompt": "Fix the double route owner — router-ui is mounted alongside the framework's router", "expect": "no-trigger", "owner": "adia-host" }
|
|
19
|
+
]
|
|
20
|
+
}
|