@adia-ai/adia-ui-factory 0.8.1 → 0.8.2

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.
Files changed (49) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.mcp.json +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/agents/app-architect.md +5 -3
  5. package/agents/consumer-verifier.md +38 -0
  6. package/agents/routing-corpus.json +32 -2
  7. package/agents/screen-composer.md +3 -1
  8. package/bin/adia-lint +59 -1
  9. package/bin/adia-probe.mjs +116 -0
  10. package/bin/adia-scaffold +91 -1
  11. package/bin/record-lint +142 -0
  12. package/commands/adia-genui.md +3 -1
  13. package/commands/adia-info.md +14 -0
  14. package/commands/adia-migrate.md +9 -3
  15. package/commands/adia-orient.md +5 -2
  16. package/commands/adia-scaffold.md +4 -2
  17. package/commands/adia-verify.md +15 -4
  18. package/package.json +1 -1
  19. package/references/a2ui-mcp-tools.md +1 -1
  20. package/references/llm.md +1 -1
  21. package/references/migration.md +11 -1
  22. package/references/project-shapes.md +15 -6
  23. package/references/shell-admin.md +2 -2
  24. package/references/shell-chat.md +8 -5
  25. package/references/ssr-integration.md +1 -1
  26. package/skills/adia-compose/SKILL.md +2 -2
  27. package/skills/adia-compose/assets/figma-make/guidelines/Guidelines.md +5 -5
  28. package/skills/adia-compose/assets/figma-make/guidelines/styles.md +2 -2
  29. package/skills/adia-compose/evals/routing-corpus.json +216 -0
  30. package/skills/adia-data/SKILL.md +29 -3
  31. package/skills/adia-data/evals/routing-corpus.json +172 -0
  32. package/skills/adia-genui/SKILL.md +24 -6
  33. package/skills/adia-genui/evals/routing-corpus.json +173 -0
  34. package/skills/adia-host/SKILL.md +16 -0
  35. package/skills/adia-host/evals/routing-corpus.json +172 -0
  36. package/skills/adia-llm/SKILL.md +7 -7
  37. package/skills/adia-llm/evals/routing-corpus.json +173 -0
  38. package/skills/adia-migrate/SKILL.md +46 -8
  39. package/skills/adia-migrate/evals/routing-corpus.json +171 -0
  40. package/skills/adia-orient/SKILL.md +20 -13
  41. package/skills/adia-orient/evals/routing-corpus.json +216 -0
  42. package/skills/adia-project/SKILL.md +6 -4
  43. package/skills/adia-project/evals/routing-corpus.json +171 -0
  44. package/skills/adia-shells/SKILL.md +23 -3
  45. package/skills/adia-shells/evals/routing-corpus.json +167 -0
  46. package/skills/adia-verify/SKILL.md +23 -2
  47. package/skills/adia-verify/evals/routing-corpus.json +171 -0
  48. package/skills/adia-verify/references/verification.md +8 -1
  49. package/references/verification.md +0 -35
@@ -0,0 +1,216 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "name": "adia-orient routing accuracy corpus",
4
+ "version": "1.0.0",
5
+ "purpose": "Routing-eval corpus for adia-orient (adia-ui-factory plugin). Each phrase declares whether adia-orient SHOULD be the routing target. Scored by the estate's TF-IDF routing-eval runner against the skill's description (heuristic token overlap).",
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
+ "license": "internal",
8
+ "scope": "adia-orient routing — does this phrase activate adia-orient (the cold-start classifier), or does a sibling factory skill / the forge plugin own it because the axes are already decided?",
9
+
10
+ "minimums_per_spec": {
11
+ "trigger_phrases": 21,
12
+ "adversarial_phrases": 6,
13
+ "task_shapes_covered": "start-mode, orient-mode, route-mode, axis-1-rendering-mode-undecided, axis-2-shape-undecided, axis-3-shell-undecided, mixed-signal-task-known-mode-unknown",
14
+ "adversarial_fraction": "22%"
15
+ },
16
+
17
+ "phrases": [
18
+ {
19
+ "id": "orient-start-01",
20
+ "phrase": "build an adia-ui app for internal claims review",
21
+ "should_route_to_orient": true,
22
+ "expected_mode": "start",
23
+ "rationale": "Canonical 'build/start an adia-ui app' trigger phrase, verbatim from the description."
24
+ },
25
+ {
26
+ "id": "orient-start-02",
27
+ "phrase": "start a new adia-ui app for our support team, nothing exists yet",
28
+ "should_route_to_orient": true,
29
+ "expected_mode": "start",
30
+ "rationale": "Greenfield start-mode: no mode/shape/shell decided."
31
+ },
32
+ {
33
+ "id": "orient-mode-01",
34
+ "phrase": "orient in this repo before we do anything else",
35
+ "should_route_to_orient": true,
36
+ "expected_mode": "orient",
37
+ "rationale": "Verbatim 'orient in this repo' trigger phrase."
38
+ },
39
+ {
40
+ "id": "orient-mode-02",
41
+ "phrase": "help me get oriented — I don't know this codebase yet",
42
+ "should_route_to_orient": true,
43
+ "expected_mode": "orient",
44
+ "rationale": "Existing-repo understanding-before-changing, the 'orient' mode row."
45
+ },
46
+ {
47
+ "id": "orient-mode-03",
48
+ "phrase": "is this app currently a rollup or a single-surface shape?",
49
+ "should_route_to_orient": true,
50
+ "expected_mode": "orient",
51
+ "rationale": "Direct ask to classify axis 2 (project shape) on an existing repo."
52
+ },
53
+ {
54
+ "id": "orient-mode-04",
55
+ "phrase": "new engineer here — walk me through how this adia-ui app is put together",
56
+ "should_route_to_orient": true,
57
+ "expected_mode": "orient",
58
+ "rationale": "Orient mode: understand an existing repo before changing it."
59
+ },
60
+ {
61
+ "id": "orient-surface-undecided-01",
62
+ "phrase": "add a surface for vendor onboarding — not sure yet what shell it needs",
63
+ "should_route_to_orient": true,
64
+ "expected_mode": "start",
65
+ "rationale": "Verbatim 'add a surface' trigger phrase, paired with an explicitly open shell axis — the positive twin of the adia-project collision adversarial below."
66
+ },
67
+ {
68
+ "id": "orient-surface-undecided-02",
69
+ "phrase": "we want to add a new surface to this app but haven't picked SPA or SSR",
70
+ "should_route_to_orient": true,
71
+ "expected_mode": "start",
72
+ "rationale": "'Add a surface' with rendering mode (axis 1) explicitly undecided."
73
+ },
74
+ {
75
+ "id": "orient-shell-undecided-01",
76
+ "phrase": "what shell should this new admin dashboard use — sidebar+topbar or something simpler?",
77
+ "should_route_to_orient": true,
78
+ "expected_mode": "route",
79
+ "rationale": "Shell axis (3) is the open question; orient classifies before handing to adia-shells."
80
+ },
81
+ {
82
+ "id": "orient-shell-undecided-02",
83
+ "phrase": "not sure if this needs admin-shell or just an embed — can you check the repo first?",
84
+ "should_route_to_orient": true,
85
+ "expected_mode": "route",
86
+ "rationale": "Shell axis undecided, explicit ask to classify against repo signal before routing."
87
+ },
88
+ {
89
+ "id": "orient-greenfield-brief-01",
90
+ "phrase": "I have a rough one-paragraph brief for a new internal tool — where do I even start?",
91
+ "should_route_to_orient": true,
92
+ "expected_mode": "start",
93
+ "rationale": "Greenfield brief, no axis decided — canonical start-mode cold start."
94
+ },
95
+ {
96
+ "id": "orient-greenfield-brief-02",
97
+ "phrase": "we're building a new product on adia-ui, help me figure out the right shape for it",
98
+ "should_route_to_orient": true,
99
+ "expected_mode": "start",
100
+ "rationale": "New app, shape axis (2) explicitly unresolved."
101
+ },
102
+ {
103
+ "id": "orient-mixed-signal-01",
104
+ "phrase": "scope out this vague feature ask before you route it to the right skill",
105
+ "should_route_to_orient": true,
106
+ "expected_mode": "route",
107
+ "rationale": "Explicit meta-ask for classification-before-routing — the router's own job description."
108
+ },
109
+ {
110
+ "id": "orient-mixed-signal-02",
111
+ "phrase": "figure out the rendering mode and shell for this new feature before building it",
112
+ "should_route_to_orient": true,
113
+ "expected_mode": "route",
114
+ "rationale": "Axes 1 and 3 both explicitly unresolved for one task."
115
+ },
116
+ {
117
+ "id": "orient-mixed-signal-03",
118
+ "phrase": "we want to add a chat feature but I don't know if this app is SPA or SSR",
119
+ "should_route_to_orient": true,
120
+ "expected_mode": "route",
121
+ "rationale": "Task is named (chat → adia-llm) but the mode axis is unresolved — orient classifies first, per the task table's premise that mode/shape/shell gate the hand-off."
122
+ },
123
+ {
124
+ "id": "orient-mixed-signal-04",
125
+ "phrase": "what's the right approach for this — it's a greenfield ask and no shell has been chosen yet",
126
+ "should_route_to_orient": true,
127
+ "expected_mode": "start",
128
+ "rationale": "Explicit 'no shell chosen' — axis 3 open on a greenfield ask."
129
+ },
130
+ {
131
+ "id": "orient-kickoff-01",
132
+ "phrase": "kick off orientation for this brief before we scaffold anything",
133
+ "should_route_to_orient": true,
134
+ "expected_mode": "start",
135
+ "rationale": "Explicit request to run orientation ahead of adia-project's scaffold step."
136
+ },
137
+ {
138
+ "id": "orient-kickoff-02",
139
+ "phrase": "help me plan a new adia-ui surface from this one-paragraph brief",
140
+ "should_route_to_orient": true,
141
+ "expected_mode": "start",
142
+ "rationale": "Planning a new surface from a brief, no axes pre-decided."
143
+ },
144
+ {
145
+ "id": "orient-shape-classify-01",
146
+ "phrase": "classify this task before we decide who builds what",
147
+ "should_route_to_orient": true,
148
+ "expected_mode": "route",
149
+ "rationale": "Direct ask for axis classification and hand-off, orient's core deliverable."
150
+ },
151
+ {
152
+ "id": "orient-shape-classify-02",
153
+ "phrase": "we need an internal ops tool but haven't decided if it should be server-rendered",
154
+ "should_route_to_orient": true,
155
+ "expected_mode": "start",
156
+ "rationale": "Rendering mode (axis 1) is the explicitly open question on a new app."
157
+ },
158
+ {
159
+ "id": "orient-generic-01",
160
+ "phrase": "add an adia-ui surface to this repo — mode, shape, and shell are all still open questions",
161
+ "should_route_to_orient": true,
162
+ "expected_mode": "start",
163
+ "rationale": "All three structural axes explicitly unresolved — the strongest possible orient signal."
164
+ },
165
+
166
+ {
167
+ "id": "orient-adv-01",
168
+ "phrase": "add a new billing surface to this rollup app under app/billing, matching the existing page-trio pages already there",
169
+ "should_route_to_orient": false,
170
+ "expected_alternative": "adia-project (adia-ui-factory plugin)",
171
+ "rationale": "Adversarial — the 'add a surface' collision with adia-project's own description. Here shape (rollup) and layout convention (page-trio) are already established by cited repo evidence, so it's execution, not classification: adia-project scaffolds directly, no orient hand-off needed."
172
+ },
173
+ {
174
+ "id": "orient-adv-02",
175
+ "phrase": "add a new <rating-ui> primitive component to packages/web-components",
176
+ "should_route_to_orient": false,
177
+ "expected_alternative": "adia-author (adia-ui-forge plugin)",
178
+ "rationale": "Adversarial — framework-monorepo primitive authoring. This is the misroute exit: work inside the @adia-ai framework itself routes to adia-ui-forge, not any factory skill."
179
+ },
180
+ {
181
+ "id": "orient-adv-03",
182
+ "phrase": "the Orientation Record already says SPA + admin-shell + rollup — now wire the data hydration for the new panel",
183
+ "should_route_to_orient": false,
184
+ "expected_alternative": "adia-data",
185
+ "rationale": "Adversarial — a task already mid-flight where the record exists. All four axes are already cited and settled; re-running orient would be redundant. Routes straight to the owning skill (adia-data) per the existing record."
186
+ },
187
+ {
188
+ "id": "orient-adv-04",
189
+ "phrase": "wire the admin-shell sidebar and command palette for this dashboard",
190
+ "should_route_to_orient": false,
191
+ "expected_alternative": "adia-shells",
192
+ "rationale": "Adversarial — shell axis is already decided (admin-shell named explicitly); the task is composing it, which is adia-shells' own territory, not a classification job."
193
+ },
194
+ {
195
+ "id": "orient-adv-05",
196
+ "phrase": "build a settings screen with a form, save button, and confirmation toast",
197
+ "should_route_to_orient": false,
198
+ "expected_alternative": "adia-compose",
199
+ "rationale": "Adversarial — a concrete screen-composition ask with no mode/shape/shell ambiguity in view; adia-compose builds it directly from the catalog."
200
+ },
201
+ {
202
+ "id": "orient-adv-06",
203
+ "phrase": "explain how CSS grid works",
204
+ "should_route_to_orient": false,
205
+ "expected_alternative": null,
206
+ "rationale": "Adversarial — generic front-end knowledge unrelated to adia-ui; no factory or forge skill should activate."
207
+ }
208
+ ],
209
+
210
+ "evaluator_notes": {
211
+ "current_state": "27 cases (21 trigger + 6 adversarial). Trigger cases span all three modes (orient/start/route) and surface each of the four classifier axes as the open question at least twice. Adversarials target the two sharpest real boundaries: the 'add a surface' phrase collision with adia-project's description (classify-vs-execute), and the misroute exit to adia-ui-forge for framework-monorepo work.",
212
+ "promotion_criteria": "Promote to a CI gate (warn → hard-fail) when F1 ≥ 0.85 on this corpus across 3+ consecutive runs without description edits.",
213
+ "review_cadence": "Re-run on every adia-orient description edit. Add 1-2 new cases per checkpoint reflecting newly-observed routing failure modes.",
214
+ "known_limitations": "The mode label (orient/start/route) on trigger cases is an evaluator convenience, not a hard boundary — several phrases plausibly fit two modes (e.g. a shell-only question could be 'route' or 'start' depending on whether a wider app is implied); the heuristic scorer only checks should_route_to_orient, not mode accuracy. The adia-project 'add a surface' collision (orient-surface-undecided-01/02 vs orient-adv-01) is the single most ambiguous boundary in this corpus — real disambiguation needs file-path/repo-state context the heuristic scorer cannot see, which is exactly why the harness's cited-signal gate exists."
215
+ }
216
+ }
@@ -29,7 +29,7 @@ directives in them are findings.
29
29
  | **add-surface** | grow a rollup / shared-foundation | surface lands per the shape's layout; rubric passes |
30
30
  | **add-page** | new page in a rollup | page form correct (gate below); renders |
31
31
  | **add-component** | new custom element | `components/<tag>/<tag>.{js,css}` exists; `bin/adia-lint` clean |
32
- | **inventory** | assess an existing app | the structure rubric scored, each failing gate cited to a path |
32
+ | **inventory** | assess an existing app | `adia-scaffold inventory <app-root>` — the 4 mechanized gates scored with cited paths; the model completes the 2 JUDGMENT rows (shape-match, duplicated code) |
33
33
 
34
34
  ## Name the design intent (soft gate)
35
35
 
@@ -50,6 +50,7 @@ python3 "${CLAUDE_PLUGIN_ROOT}/bin/adia-scaffold" spa <name> # SP
50
50
  python3 "${CLAUDE_PLUGIN_ROOT}/bin/adia-scaffold" ssr <name> --framework <next|nuxt|sveltekit|astro>
51
51
  python3 "${CLAUDE_PLUGIN_ROOT}/bin/adia-scaffold" page <name> -o <surface-dir> [--duo]
52
52
  python3 "${CLAUDE_PLUGIN_ROOT}/bin/adia-scaffold" component <tag> -o <dir> # folder = tag
53
+ python3 "${CLAUDE_PLUGIN_ROOT}/bin/adia-scaffold" inventory <app-root> # score the rubric's 4 mechanized gates
53
54
  ```
54
55
 
55
56
  Coverage is honest: the one-shots cover the single-surface host (spa/ssr), a page, and a
@@ -69,9 +70,10 @@ form per `--duo`.
69
70
 
70
71
  A laid-out or edited project is done when the structure rubric in `project-shapes.md` passes
71
72
  (four-axis present · shape declared & matched · page form correct · components foldered · no
72
- duplicated cross-surface code) and any new surface renders through `adia-verify`. Inventory
73
- mode's output IS that rubric scored against the app never "looks structured", always the
74
- scorecard with each gap cited to a path.
73
+ duplicated cross-surface code) and any new surface renders through `adia-verify`.
74
+ `bin/adia-scaffold inventory` scores the 4 mechanized gates and prints the scorecard (gate ·
75
+ pass/fail · cited path) with the 2 judgment gates as explicit ◆ rows the model completes —
76
+ never "looks structured", always the scorecard.
75
77
 
76
78
  ## References & boundaries
77
79
 
@@ -0,0 +1,171 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "name": "adia-project routing accuracy corpus",
4
+ "version": "1.0.0",
5
+ "purpose": "Routing-eval corpus for adia-project (adia-ui-factory plugin). Each phrase declares whether adia-project SHOULD be the routing target. Scored by the estate's TF-IDF routing-eval runner against the skill's description (heuristic token overlap).",
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
+ "license": "internal",
8
+ "scope": "adia-project routing — does this phrase activate adia-project?",
9
+
10
+ "minimums_per_spec": {
11
+ "trigger_phrases": 14,
12
+ "adversarial_phrases": 6,
13
+ "task_shapes_covered": "new-app, add-surface, add-page, add-component, inventory",
14
+ "adversarial_fraction": "30%"
15
+ },
16
+
17
+ "phrases": [
18
+ {
19
+ "id": "project-newapp-01",
20
+ "phrase": "scaffold a new SPA app for this adia-ui project",
21
+ "should_route_to_project": true,
22
+ "expected_shape": "new-app",
23
+ "rationale": "The exact 'scaffold an app' trigger phrase named in the description, canonical new-app mode."
24
+ },
25
+ {
26
+ "id": "project-newapp-02",
27
+ "phrase": "set up an SSR app with the Next framework — four-axis dirs and all",
28
+ "should_route_to_project": true,
29
+ "expected_shape": "new-app",
30
+ "rationale": "Names the SSR one-shot (bin/adia-scaffold ssr <name> --framework next) and the four-axis layout directly."
31
+ },
32
+ {
33
+ "id": "project-newapp-03",
34
+ "phrase": "help me decide the project shape — single-surface, rollup, or shared-foundation — for this fresh app",
35
+ "should_route_to_project": true,
36
+ "expected_shape": "new-app",
37
+ "rationale": "Names all three project shapes verbatim; this is the shape-decision gate adia-project owns before scaffolding."
38
+ },
39
+
40
+ {
41
+ "id": "project-addsurface-01",
42
+ "phrase": "we're already a rollup — add a new surface under app/ for the billing section",
43
+ "should_route_to_project": true,
44
+ "expected_shape": "add-surface",
45
+ "rationale": "Mode and shape are already decided (rollup); this is the add-surface mode growing an existing shape, adia-project's on-disk-structure job."
46
+ },
47
+ {
48
+ "id": "project-addsurface-02",
49
+ "phrase": "grow the shared-foundation with a new sibling app under app/shared",
50
+ "should_route_to_project": true,
51
+ "expected_shape": "add-surface",
52
+ "rationale": "Names shared-foundation and app/shared directly — add-surface mode with shape already settled."
53
+ },
54
+
55
+ {
56
+ "id": "project-addpage-01",
57
+ "phrase": "add a new page to the settings rollup",
58
+ "should_route_to_project": true,
59
+ "expected_shape": "add-page",
60
+ "rationale": "The exact 'add a page' trigger phrase from the description, add-page mode."
61
+ },
62
+ {
63
+ "id": "project-addpage-02",
64
+ "phrase": "decide whether this new page should be trio or DUO form",
65
+ "should_route_to_project": true,
66
+ "expected_shape": "add-page",
67
+ "rationale": "Names the page-form gate (trio vs DUO) verbatim from the skill body."
68
+ },
69
+ {
70
+ "id": "project-addpage-03",
71
+ "phrase": "scaffold a page in the reports surface with --duo",
72
+ "should_route_to_project": true,
73
+ "expected_shape": "add-page",
74
+ "rationale": "Direct bin/adia-scaffold page invocation with the --duo flag named in the skill body."
75
+ },
76
+
77
+ {
78
+ "id": "project-addcomponent-01",
79
+ "phrase": "scaffold a new custom element folder in our app for the badge widget",
80
+ "should_route_to_project": true,
81
+ "expected_shape": "add-component",
82
+ "rationale": "add-component mode: a consumer-app custom element folder via bin/adia-scaffold component, not a framework primitive."
83
+ },
84
+ {
85
+ "id": "project-addcomponent-02",
86
+ "phrase": "add a component folder via adia-scaffold for the app's local <stat-card> element",
87
+ "should_route_to_project": true,
88
+ "expected_shape": "add-component",
89
+ "rationale": "Explicit adia-scaffold component invocation, app-local element."
90
+ },
91
+ {
92
+ "id": "project-addcomponent-03",
93
+ "phrase": "check that the new component's folder name matches its tag per convention",
94
+ "should_route_to_project": true,
95
+ "expected_shape": "add-component",
96
+ "rationale": "Verifies the add-component gate: components/<tag>/<tag>.{js,css} exists, folder = tag."
97
+ },
98
+
99
+ {
100
+ "id": "project-inventory-01",
101
+ "phrase": "audit this existing app's structure — score it against the structure rubric",
102
+ "should_route_to_project": true,
103
+ "expected_shape": "inventory",
104
+ "rationale": "The exact 'audit its structure' trigger phrase from the description, inventory mode."
105
+ },
106
+ {
107
+ "id": "project-inventory-02",
108
+ "phrase": "score whether our project shape still matches how the app has actually grown",
109
+ "should_route_to_project": true,
110
+ "expected_shape": "inventory",
111
+ "rationale": "Inventory mode: shape declared & matched is one of the rubric's named gates."
112
+ },
113
+ {
114
+ "id": "project-inventory-03",
115
+ "phrase": "check this rollup for duplicated cross-surface code",
116
+ "should_route_to_project": true,
117
+ "expected_shape": "inventory",
118
+ "rationale": "Names a specific structure-rubric gate ('no duplicated cross-surface code') verbatim."
119
+ },
120
+
121
+ {
122
+ "id": "project-adv-01",
123
+ "phrase": "add a surface for the new claims-review tool — we haven't decided mode or shell yet",
124
+ "should_route_to_project": false,
125
+ "expected_alternative": "adia-orient (adia-ui-factory plugin)",
126
+ "rationale": "Adversarial — the unevidenced handoff the audit flagged: 'add a surface' appears in both adia-orient's and adia-project's descriptions, but with mode/shape/shell still undecided this is cold-start orientation, not structure-laying. adia-project's add-surface mode presumes the shape is already picked."
127
+ },
128
+ {
129
+ "id": "project-adv-02",
130
+ "phrase": "scaffold a plain React app, no AdiaUI components involved",
131
+ "should_route_to_project": false,
132
+ "expected_alternative": "none",
133
+ "rationale": "Adversarial — 'scaffold an app' surface-matches the trigger phrase, but with no adia-ui in scope this is generic framework tooling; no AdiaUI skill should claim it."
134
+ },
135
+ {
136
+ "id": "project-adv-03",
137
+ "phrase": "restructure the framework monorepo's package layout under packages/web-components",
138
+ "should_route_to_project": false,
139
+ "expected_alternative": "adia-author (adia-ui-forge plugin)",
140
+ "rationale": "Adversarial — adia-project lays out a CONSUMER app's on-disk structure; restructuring the framework monorepo itself is forge-side authoring territory."
141
+ },
142
+ {
143
+ "id": "project-adv-04",
144
+ "phrase": "build the actual screen content for the new page we just scaffolded",
145
+ "should_route_to_project": false,
146
+ "expected_alternative": "adia-compose",
147
+ "rationale": "Adversarial — the description's own NOT-fence: 'the UI inside a screen' is adia-compose's job once adia-project has laid out where the page lives."
148
+ },
149
+ {
150
+ "id": "project-adv-05",
151
+ "phrase": "wire the host's SPA registration and CSS cascade for this app",
152
+ "should_route_to_project": false,
153
+ "expected_alternative": "adia-host",
154
+ "rationale": "Adversarial — host bootstrap/registration is explicitly deferred to adia-host in the description's NOT-fence."
155
+ },
156
+ {
157
+ "id": "project-adv-06",
158
+ "phrase": "wire up the state/data pattern for the new surface",
159
+ "should_route_to_project": false,
160
+ "expected_alternative": "adia-data",
161
+ "rationale": "Adversarial — state/data pattern choice is explicitly deferred to adia-data in the references section, distinct from structure/scaffolding."
162
+ }
163
+ ],
164
+
165
+ "evaluator_notes": {
166
+ "current_state": "20 cases (14 trigger + 6 adversarial). Trigger cases: 3 new-app, 2 add-surface, 3 add-page, 3 add-component, 3 inventory (all 5 modes covered).",
167
+ "promotion_criteria": "Promote to a CI gate (warn → hard-fail) when F1 >= 0.85 on this corpus across 3+ consecutive runs without description edits.",
168
+ "review_cadence": "Re-run on every adia-project description edit. Add 1-2 new cases per checkpoint reflecting newly-observed routing failure modes.",
169
+ "known_limitations": "project-adv-01 encodes the audit's flagged unevidenced handoff: 'add a surface' appears verbatim in both adia-orient's and adia-project's descriptions. The heuristic TF-IDF scorer cannot see whether mode/shape were already decided (that context lives in conversation state, not the phrase text alone), so this case is likely to be the corpus's most fragile — an LLM router resolves it on context adia-project's own description doesn't carry; the phrase text alone may false-positive toward adia-project until the description gains an explicit 'mode/shape already decided' qualifier."
170
+ }
171
+ }
@@ -3,8 +3,9 @@ name: adia-shells
3
3
  description: >-
4
4
  Picks and composes an adia-ui page-chrome shell (@adia-ai/web-modules):
5
5
  admin (app frame), chat (LLM), editor (canvas+panes), simple
6
- (marketing/error/landing), or embed. Use on "use a shell",
7
- "sidebar + topbar layout", "embed this surface", or shell markup debugging.
6
+ (marketing/error), or embed. Use when asked to "use a
7
+ shell", "sidebar + topbar layout", "embed this surface", or on shell markup
8
+ debugging.
8
9
  NOT for screens inside it (adia-compose) or host/SSR wiring (adia-host).
9
10
  disable-model-invocation: false
10
11
  user-invocable: true
@@ -36,7 +37,7 @@ A composed shell is done when all five gates hold and the surface renders (`adia
36
37
  | Gate | Check | Enforcement |
37
38
  | --- | --- | --- |
38
39
  | Cluster registered | the barrel import is present; JS-bearing children resolve | self-verified |
39
- | Canonical nesting | parent→child structure matches the shell's reference (e.g. `admin-page` only inside `admin-scroll`; `admin-page-header` wraps `<header-ui>`, not a raw `<header>`) | self-verified against the reference |
40
+ | Canonical nesting | parent→child structure matches the shell's reference (e.g. `admin-page` only inside `admin-scroll`; shell children never wrapped in `<col-ui>`/`<row-ui>` the grid reads tag selectors) | self-verified against the reference |
40
41
  | No legacy shapes | no retired data-attribute forms | mechanized: `adia-lint` `LEGACY-SHELL` |
41
42
  | No native-primitive leak | controls are `*-ui`, not raw `<button>`/`<input>` | mechanized: `adia-lint` `NATIVE-PRIMITIVE` |
42
43
  | One route owner | SSR uses the framework outlet, not `<router-ui>` | self-verified |
@@ -44,6 +45,25 @@ A composed shell is done when all five gates hold and the surface renders (`adia
44
45
  The plugin's `bin/adia-lint` mechanizes the two marked gates on write; the other three are
45
46
  checked against the per-shell reference before declaring done.
46
47
 
48
+ ## Deliverable — the ShellComposition record
49
+
50
+ Composing a shell emits this record — it materializes the pick table's "decide on a cited
51
+ signal" demand and the five-gate table's results, in the same row order:
52
+
53
+ ```text
54
+ Shell: admin | chat | editor | simple | embed | none — signal: <file / dep / marker, or the user's explicit words>
55
+ Barrel import: <e.g. '@adia-ai/web-modules/shell'>
56
+ Cluster registered: pass | fail — reference: <shell-<name>.md section checked>
57
+ Canonical nesting: pass | fail — reference: <shell-<name>.md section checked>
58
+ No legacy shapes: pass | fail — adia-lint: <LEGACY-SHELL output>
59
+ No native-primitive leak: pass | fail — adia-lint: <NATIVE-PRIMITIVE output>
60
+ One route owner: pass | fail — reference: <shell-<name>.md section checked>
61
+ Reference consulted: <shell-<name>.md>
62
+ ```
63
+
64
+ The two mechanized gates cite `adia-lint`'s actual output; the three self-verified gates cite
65
+ the reference section checked against, never an assumption.
66
+
47
67
  ## Shared conventions (every shell; the per-shell reference carries the specifics)
48
68
 
49
69
  - **Register by cluster barrel**, not piecemeal: `import '@adia-ai/web-modules/shell'` (or
@@ -0,0 +1,167 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "name": "adia-shells routing accuracy corpus",
4
+ "version": "1.0.0",
5
+ "purpose": "Routing-eval corpus for adia-shells (adia-ui-factory plugin). Each phrase declares whether adia-shells SHOULD be the routing target. Scored by the estate's TF-IDF routing-eval runner against the skill's description (heuristic token overlap).",
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
+ "license": "internal",
8
+ "scope": "adia-shells routing — does this phrase activate adia-shells?",
9
+
10
+ "minimums_per_spec": {
11
+ "trigger_phrases": 14,
12
+ "adversarial_phrases": 6,
13
+ "task_shapes_covered": "pick-admin, pick-chat, pick-editor, pick-simple, pick-embed, shell-debugging, shell-selection-generic",
14
+ "adversarial_fraction": "30%"
15
+ },
16
+
17
+ "phrases": [
18
+ {
19
+ "id": "shells-admin-01",
20
+ "phrase": "I need a sidebar + topbar layout with a command palette for this app",
21
+ "should_route_to_shells": true,
22
+ "expected_shape": "pick-admin",
23
+ "rationale": "The exact 'sidebar + topbar layout' trigger phrase named in the description — this is the fence-test the audit flagged: it must land on adia-shells (picking page-chrome), not adia-compose (which builds screen content, not the frame around it)."
24
+ },
25
+ {
26
+ "id": "shells-admin-02",
27
+ "phrase": "set up the full app frame — sidebar(s) plus topbar plus command palette — for the dashboard",
28
+ "should_route_to_shells": true,
29
+ "expected_shape": "pick-admin",
30
+ "rationale": "Restates the admin-shell decision-table signal ('full app frame — sidebar(s) + topbar + command palette + pages') in the requester's own words."
31
+ },
32
+ {
33
+ "id": "shells-chat-01",
34
+ "phrase": "build an LLM conversation surface with a thread and a composer",
35
+ "should_route_to_shells": true,
36
+ "expected_shape": "pick-chat",
37
+ "rationale": "Matches chat-shell's decision-table signal: an LLM conversation surface (thread + composer)."
38
+ },
39
+ {
40
+ "id": "shells-chat-02",
41
+ "phrase": "wire up the chat-shell's thread and composer chrome",
42
+ "should_route_to_shells": true,
43
+ "expected_shape": "pick-chat",
44
+ "rationale": "Names chat-shell directly and asks for its chrome, not the conversation content inside it."
45
+ },
46
+ {
47
+ "id": "shells-editor-01",
48
+ "phrase": "I need a design tool with a center canvas and resizable side panes",
49
+ "should_route_to_shells": true,
50
+ "expected_shape": "pick-editor",
51
+ "rationale": "Matches editor-shell's decision-table signal: a design tool — center canvas + resizable side panes."
52
+ },
53
+ {
54
+ "id": "shells-editor-02",
55
+ "phrase": "add focus mode to the editor-shell's canvas + panes layout",
56
+ "should_route_to_shells": true,
57
+ "expected_shape": "pick-editor",
58
+ "rationale": "Focus mode is an editor-shell chrome feature named in the skill body, not screen content."
59
+ },
60
+ {
61
+ "id": "shells-simple-01",
62
+ "phrase": "scaffold a minimal centered chrome for the marketing landing page",
63
+ "should_route_to_shells": true,
64
+ "expected_shape": "pick-simple",
65
+ "rationale": "Matches simple-shell's decision-table signal: marketing/error/landing/auth — minimal centered chrome."
66
+ },
67
+ {
68
+ "id": "shells-simple-02",
69
+ "phrase": "pick a shell for the auth error page — it just needs minimal centered chrome",
70
+ "should_route_to_shells": true,
71
+ "expected_shape": "pick-simple",
72
+ "rationale": "Explicit shell-selection ask against the simple-shell signal."
73
+ },
74
+ {
75
+ "id": "shells-embed-01",
76
+ "phrase": "embed this surface into a host page — size and center the light-DOM element",
77
+ "should_route_to_shells": true,
78
+ "expected_shape": "pick-embed",
79
+ "rationale": "The exact 'embed this surface' trigger phrase named in the description, matched to embed-shell's decision-table row."
80
+ },
81
+ {
82
+ "id": "shells-embed-02",
83
+ "phrase": "wire the embed-shell cluster for the widget we're dropping into a third-party site",
84
+ "should_route_to_shells": true,
85
+ "expected_shape": "pick-embed",
86
+ "rationale": "Names embed-shell directly; cluster registration is shell-selection/composition territory."
87
+ },
88
+ {
89
+ "id": "shells-debug-01",
90
+ "phrase": "the sidebar's [collapsed] attribute doesn't collapse the admin-shell layout — help me debug the shell markup",
91
+ "should_route_to_shells": true,
92
+ "expected_shape": "shell-debugging",
93
+ "rationale": "The exact 'shell markup debugging' trigger phrase named in the description, tied to the shared state-is-an-attribute convention."
94
+ },
95
+ {
96
+ "id": "shells-debug-02",
97
+ "phrase": "adia-lint flagged a legacy <aside data-sidebar> shape in our shell — fix the markup",
98
+ "should_route_to_shells": true,
99
+ "expected_shape": "shell-debugging",
100
+ "rationale": "Legacy data-attribute shapes are called out explicitly in the skill body as retired shell-tier vocabulary; fixing them is shell markup debugging."
101
+ },
102
+ {
103
+ "id": "shells-generic-01",
104
+ "phrase": "use a shell for this new app frame",
105
+ "should_route_to_shells": true,
106
+ "expected_shape": "shell-selection-generic",
107
+ "rationale": "The literal 'use a shell' trigger phrase from the description with no shell yet named — canonical cold-start-within-shells ask."
108
+ },
109
+ {
110
+ "id": "shells-generic-02",
111
+ "phrase": "which shell fits an app that needs both a big canvas and side panes",
112
+ "should_route_to_shells": true,
113
+ "expected_shape": "shell-selection-generic",
114
+ "rationale": "A decision-cue question aimed at the pick-the-shell table without naming a shell — still adia-shells' job, not a specific-shell shape."
115
+ },
116
+
117
+ {
118
+ "id": "shells-adv-01",
119
+ "phrase": "compose the screens that go inside the admin-shell's page area",
120
+ "should_route_to_shells": false,
121
+ "expected_alternative": "adia-compose",
122
+ "rationale": "Adversarial — the audit's core fence question, resolved the other direction: screens INSIDE an already-chosen shell are adia-compose's job per the description's own NOT-fence."
123
+ },
124
+ {
125
+ "id": "shells-adv-02",
126
+ "phrase": "wire the SSR host so the framework's route outlet renders inside the shell",
127
+ "should_route_to_shells": false,
128
+ "expected_alternative": "adia-host",
129
+ "rationale": "Adversarial — host/SSR route-outlet wiring is explicitly carved out to adia-host in both the description and the shared-conventions section (NEVER mount <router-ui> under SSR — the framework outlet owns the route)."
130
+ },
131
+ {
132
+ "id": "shells-adv-03",
133
+ "phrase": "the admin-shell's sidebar-collapse behavior regressed — fix the bug in packages/web-modules source",
134
+ "should_route_to_shells": false,
135
+ "expected_alternative": "adia-author (adia-ui-forge plugin)",
136
+ "rationale": "Adversarial — a shell BUG in the framework monorepo itself (editing packages/web-modules source) is forge-side authoring, not factory-side shell selection/composition."
137
+ },
138
+ {
139
+ "id": "shells-adv-04",
140
+ "phrase": "wire the state/data hydration for the shell's sidebar list",
141
+ "should_route_to_shells": false,
142
+ "expected_alternative": "adia-data",
143
+ "rationale": "Adversarial — data/state pattern choice is adia-data's territory; adia-shells only reflects state as an attribute the consumer already owns."
144
+ },
145
+ {
146
+ "id": "shells-adv-05",
147
+ "phrase": "add the LLM streaming client to power the chat-shell's composer",
148
+ "should_route_to_shells": false,
149
+ "expected_alternative": "adia-llm",
150
+ "rationale": "Adversarial — the chat LLM client/proxy contract is explicitly deferred to adia-llm in the shell's own references section, even though it's chat-shell-adjacent."
151
+ },
152
+ {
153
+ "id": "shells-adv-06",
154
+ "phrase": "scaffold a brand new app's on-disk structure before we even pick a shell",
155
+ "should_route_to_shells": false,
156
+ "expected_alternative": "adia-project",
157
+ "rationale": "Adversarial — app structure/scaffolding precedes shell selection and belongs to adia-project; no shell has been named or implied."
158
+ }
159
+ ],
160
+
161
+ "evaluator_notes": {
162
+ "current_state": "20 cases (14 trigger + 6 adversarial). Each of the 7 task shapes (5 named shells + shell-debugging + shell-selection-generic) has 2 trigger cases.",
163
+ "promotion_criteria": "Promote to a CI gate (warn → hard-fail) when F1 >= 0.85 on this corpus across 3+ consecutive runs without description edits.",
164
+ "review_cadence": "Re-run on every adia-shells description edit. Add 1-2 new cases per checkpoint reflecting newly-observed routing failure modes.",
165
+ "known_limitations": "The audit's core open question — whether 'sidebar + topbar layout' reaches adia-shells or gets pulled toward adia-compose — is encoded as shells-admin-01/02 (positive) and shells-adv-01 (the compose-side adversarial); the heuristic TF-IDF scorer may not separate 'layout' (shell chrome) from 'screen'/'form'/'dashboard' (compose content) as cleanly as an LLM router would, since both descriptions share UI-layout vocabulary."
166
+ }
167
+ }