@nurix/etna 0.18.19 → 0.18.20
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/data/harness-index.json +1 -1
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/skills/design/SKILL.md +65 -0
- package/data/harnesses/code/skills/design/data/catalog/rules.csv +132 -0
- package/data/harnesses/code/skills/design/data/design-md/SCHEMA.md +317 -0
- package/data/harnesses/code/skills/design/data/design-md/library/airbnb.md +235 -0
- package/data/harnesses/code/skills/design/data/design-md/library/airtable.md +232 -0
- package/data/harnesses/code/skills/design/data/design-md/library/anthropic-claude.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/apple.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/binance.md +223 -0
- package/data/harnesses/code/skills/design/data/design-md/library/bmw.md +219 -0
- package/data/harnesses/code/skills/design/data/design-md/library/cal.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/clay.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/clickhouse.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/cohere.md +227 -0
- package/data/harnesses/code/skills/design/data/design-md/library/coinbase.md +237 -0
- package/data/harnesses/code/skills/design/data/design-md/library/composio.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/cursor.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/elevenlabs.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/expo.md +228 -0
- package/data/harnesses/code/skills/design/data/design-md/library/figma.md +221 -0
- package/data/harnesses/code/skills/design/data/design-md/library/framer.md +236 -0
- package/data/harnesses/code/skills/design/data/design-md/library/hashicorp.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/ibm.md +234 -0
- package/data/harnesses/code/skills/design/data/design-md/library/intercom.md +240 -0
- package/data/harnesses/code/skills/design/data/design-md/library/kraken.md +236 -0
- package/data/harnesses/code/skills/design/data/design-md/library/linear-app.md +237 -0
- package/data/harnesses/code/skills/design/data/design-md/library/lovable.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/meta.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/minimax.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/mintlify.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/miro.md +233 -0
- package/data/harnesses/code/skills/design/data/design-md/library/mistral-ai.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/mongodb.md +236 -0
- package/data/harnesses/code/skills/design/data/design-md/library/notion.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/nvidia.md +222 -0
- package/data/harnesses/code/skills/design/data/design-md/library/ollama.md +226 -0
- package/data/harnesses/code/skills/design/data/design-md/library/opencode-ai.md +223 -0
- package/data/harnesses/code/skills/design/data/design-md/library/posthog.md +234 -0
- package/data/harnesses/code/skills/design/data/design-md/library/raycast.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/replicate.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/resend.md +285 -0
- package/data/harnesses/code/skills/design/data/design-md/library/revolut.md +225 -0
- package/data/harnesses/code/skills/design/data/design-md/library/runwayml.md +219 -0
- package/data/harnesses/code/skills/design/data/design-md/library/sanity.md +251 -0
- package/data/harnesses/code/skills/design/data/design-md/library/sentry.md +244 -0
- package/data/harnesses/code/skills/design/data/design-md/library/shopify.md +227 -0
- package/data/harnesses/code/skills/design/data/design-md/library/slack.md +240 -0
- package/data/harnesses/code/skills/design/data/design-md/library/spacex.md +252 -0
- package/data/harnesses/code/skills/design/data/design-md/library/spotify.md +248 -0
- package/data/harnesses/code/skills/design/data/design-md/library/stripe.md +241 -0
- package/data/harnesses/code/skills/design/data/design-md/library/supabase.md +255 -0
- package/data/harnesses/code/skills/design/data/design-md/library/superhuman.md +226 -0
- package/data/harnesses/code/skills/design/data/design-md/library/tesla.md +233 -0
- package/data/harnesses/code/skills/design/data/design-md/library/theverge.md +248 -0
- package/data/harnesses/code/skills/design/data/design-md/library/together-ai.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/uber.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/vercel.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/voltagent.md +245 -0
- package/data/harnesses/code/skills/design/data/design-md/library/warp.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/webflow.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/wired.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/wise.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/x-ai.md +220 -0
- package/data/harnesses/code/skills/design/data/design-md/library/zapier.md +238 -0
- package/data/harnesses/code/skills/design/data/design-md/nurix.md +217 -0
- package/data/harnesses/code/skills/design/data/operator-pack/exemplars/command-center.tsx +249 -0
- package/data/harnesses/code/skills/design/data/operator-pack/exemplars/create-edit.tsx +249 -0
- package/data/harnesses/code/skills/design/data/operator-pack/exemplars/dashboard.tsx +248 -0
- package/data/harnesses/code/skills/design/data/operator-pack/exemplars/entity-detail.tsx +245 -0
- package/data/harnesses/code/skills/design/data/operator-pack/exemplars/list-detail.tsx +223 -0
- package/data/harnesses/code/skills/design/data/operator-pack/exemplars/log-stream.tsx +249 -0
- package/data/harnesses/code/skills/design/data/operator-pack/fixtures.md +88 -0
- package/data/harnesses/code/skills/design/data/operator-pack/surface-catalog.md +132 -0
- package/data/harnesses/code/skills/design/data/operator-pack/trust-rubric.md +76 -0
- package/data/harnesses/code/skills/design/references/create.md +126 -0
- package/data/harnesses/code/skills/design/references/diagnosis.md +108 -0
- package/data/harnesses/code/skills/design/references/hard-rules.md +155 -0
- package/data/harnesses/code/skills/design/references/improve.md +85 -0
- package/data/harnesses/code/skills/design/references/interaction.md +77 -0
- package/data/harnesses/code/skills/design/references/introspect.md +100 -0
- package/data/harnesses/code/skills/design/references/lifecycle.md +73 -0
- package/data/harnesses/code/skills/design/references/personality.md +504 -0
- package/data/harnesses/code/skills/design/references/structure.md +138 -0
- package/data/harnesses/code/skills/design/scripts/derive-personality.mjs +706 -0
- package/data/harnesses/code/skills/design/scripts/detector.mjs +898 -0
- package/data/harnesses/code/skills/design/scripts/generate-fixtures.mjs +551 -0
- package/data/harnesses/code/skills/design/scripts/hook-config.json +11 -0
- package/data/harnesses/code/skills/design/scripts/phase-gate.mjs +386 -0
- package/data/harnesses/code/skills/design/scripts/preship-sweep.mjs +280 -0
- package/data/harnesses/code/skills/design/scripts/render-rung.mjs +690 -0
- package/data/harnesses/code/skills/design/scripts/scaffold.mjs +552 -0
- package/data/harnesses/code/skills/design/scripts/self-integrity.mjs +432 -0
- package/package.json +1 -1
package/data/harness-index.json
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design
|
|
3
|
+
description: Design, build, review, polish, redesign, or introspect internal operator UIs — CRMs, ticket queues, admin panels, analytics dashboards, log viewers, command centers, and any internal/back-office tool an operator, agent, or analyst works in all day. Resolves the project's brand from a design.md, derives structure from the domain objects, emits a working React + Tailwind UI against @nurix/components or shadcn/ui, and holds it to operator-grade quality across a full sixteen-dimension taxonomy. Triggers on "build a dashboard", "design an admin panel", "review this CRM UI", "polish this queue", "redesign this internal tool", "why does this table feel off", "make it feel like Linear", or any create/improve/introspect request for an internal operator interface. Coverage is the operator pack: marketing sites, landing pages, storefronts, homepages, and mobile-native apps are out of scope — no carried pack covers them, so refuse cleanly and redirect. The machinery is not the limit; the packs are.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# design
|
|
7
|
+
|
|
8
|
+
The design skill. Its shipped coverage is the **operator pack**: internal tools — CRMs, ticket queues, admin panels, dashboards, log viewers, command centers. It resolves the brand, derives the structure from the domain objects, emits a React + Tailwind UI, and enforces operator-grade quality across the sixteen-dimension taxonomy. This file is a router — it names where to go and what not to do; the knowledge lives in the references and data below, loaded on demand.
|
|
9
|
+
|
|
10
|
+
## The front gate
|
|
11
|
+
|
|
12
|
+
**Recognition, by precedence — stop at the first that resolves.**
|
|
13
|
+
|
|
14
|
+
1. **Project-declared identity wins.** A resolved `design.md` carrying `product-traits` decides coverage outright.
|
|
15
|
+
2. **The signal checklist recognizes** when no `design.md` speaks: the audience is employees / agents / analysts; the metric is task throughput, not conversion; the surfaces are queues / tables / forms / monitors. The `design.md` library (`data/design-md/library/`) assists the lookup by resemblance — it never overrides the checklist.
|
|
16
|
+
3. **Refuse with a redirect** when no carried pack covers the brief — marketing sites, landing pages, storefronts, mobile-native. State plainly which pack is missing and point elsewhere; never a degraded attempt. The machinery is artifact-agnostic; the boundary is pack coverage, and it moves only by adding a pack.
|
|
17
|
+
|
|
18
|
+
**Then the intent digest — infer and confirm.** Build a structured digest — entities, archetype guesses, density tier, substrate — with **every inference marked as inferred**. Present it once for confirmation before any derivation begins. Ask questions only for strategic unknowns whose answers change the design. Nothing auto-runs on silent inference; nothing stalls on a blanket interview.
|
|
19
|
+
|
|
20
|
+
## Boot order
|
|
21
|
+
|
|
22
|
+
Before **any** design output, read [`references/hard-rules.md`](references/hard-rules.md) — the boot-loaded floor of 131 rules <!-- count:rules=131 --> (bans, deterministic thresholds, mandatory procedures, each keyed to an anchor id). Then route by workflow. JIT loads never happen at boot — they fire at the gate that needs them.
|
|
23
|
+
|
|
24
|
+
| Route | Load, when |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| **create** (nothing exists yet) | [`references/create.md`](references/create.md) at intake; then per phase: [`structure.md`](references/structure.md) at structure, [`personality.md`](references/personality.md) at tokens, [`lifecycle.md`](references/lifecycle.md) + [`interaction.md`](references/interaction.md) at surfaces |
|
|
27
|
+
| **improve** (a UI already exists) | [`references/improve.md`](references/improve.md) + [`references/diagnosis.md`](references/diagnosis.md) |
|
|
28
|
+
| **introspect** (why is it wrong) | [`references/introspect.md`](references/introspect.md) + [`references/diagnosis.md`](references/diagnosis.md) |
|
|
29
|
+
| JIT — archetype exemplar | `data/operator-pack/exemplars/<slug>.tsx` at that archetype's emission gate during surfaces — never at boot |
|
|
30
|
+
| JIT — fixture pair | `data/catalog/fixtures/<id>.{flag,pass}` only when a rule is contested and the contrastive pair teaches it (authoring repo only — pairs are stripped from shipped bundles; when the folder is absent, the finding's exact-fix line carries the teaching) |
|
|
31
|
+
|
|
32
|
+
## The three workflows
|
|
33
|
+
|
|
34
|
+
**Create** makes taste where nothing exists. It runs **six gated phases** — intake, structure, scaffold, tokens, fixtures, surfaces — and closes on the verification ladder. Each boundary is `phase-gate.mjs <phase>`; the next phase does not open until the gate is green. The object pass is never skipped — a small brief earns a proportionally small pass, never a guessed archetype; every surface takes an archetype from the closed six <!-- count:archetypes=6 --> (`list-detail`, `dashboard`, `entity-detail`, `create-edit`, `log-stream`, `command-center`). Fixtures are seeded and generated **before** surfaces, because realistic data is taste-bearing design material. See [`create.md`](references/create.md).
|
|
35
|
+
|
|
36
|
+
**Improve** is one engine over a UI that already exists, run at a point on scope × depth × authority; the verbs — review, polish, redesign, typeset — are parameter bindings, never sibling files. Emission is **jailed to the lever manifest** by default: an edit may emit only values inside the project's `design.md` vocabulary, enforced by `detector.mjs --manifest`. On a foreign UI, **extract a `design.md` first** (`provenance: extracted`) — record what IS, never what should be. Wrong fundamentals are tier-two (`lever-change`) findings: finish the within-levers work, report them, and offer a consent-gated lever run — never change levers unbidden. See [`improve.md`](references/improve.md) + [`diagnosis.md`](references/diagnosis.md).
|
|
37
|
+
|
|
38
|
+
**Introspect** explains **why** a UI isn't working; it reads code and never edits it. **Ask the reader question first**, every run, verbatim — designer / developer / PM — never inferred, never a stored default. Diagnose causes-first (Structure → Behavior → Perception), narrate each finding from the felt symptom down to its cause, render it in the reader's register, and **always file a dated report**. See [`introspect.md`](references/introspect.md) + [`diagnosis.md`](references/diagnosis.md).
|
|
39
|
+
|
|
40
|
+
## Scripts
|
|
41
|
+
|
|
42
|
+
Under `scripts/`; spawn them from this skill directory. All ESM, Node ≥ 22, zero dependencies.
|
|
43
|
+
|
|
44
|
+
- `detector.mjs <file...> [--manifest design.md] [--json]` — per-edit source rules + lever-manifest drift; exit 1 with the fix-or-classify directive (fix now, or classify the inapplicability into the decay ledger — never ignore).
|
|
45
|
+
- `phase-gate.mjs <phase> [--project <dir>]` — validates a phase's exit preconditions; exit non-zero printing the exact fix. Phases: `intake`, `structure`, `scaffold`, `tokens`, `fixtures`, `surfaces`.
|
|
46
|
+
- `preship-sweep.mjs [--project <dir>]` — whole-app catalog sweep + viewport sweep + copy audit + scope cross-check; prints the manual `proc-*` checklist.
|
|
47
|
+
- `render-rung.mjs [--project <dir>] [--url <dev-server>]` — render-only rules at 375/768/1024/1440 plus the render instruments (evidence, never gates); a one-line notice and exit 0 when no headless browser is importable.
|
|
48
|
+
- `derive-personality.mjs <design.md> [--check|--emit <outdir>]` — `--check` is the coverage gate; `--emit` writes `personality.css` + `globals.css`. The gate fails unless all 26 primitives <!-- count:primitives=26 -->, both dials, and every one of the 34 color values (17 semantic <!-- count:semantic-tokens=17 --> + 17 substrate <!-- count:substrate-tokens=17 -->) <!-- count:color-tokens=34 --> is assigned or hinted.
|
|
49
|
+
- `scaffold.mjs <structure.md> --out <dir>` — routes, nav, state-shells, and fixture wiring from the entity/surface map.
|
|
50
|
+
- `generate-fixtures.mjs <structure.md> --seed <n> --out <dir>` — seeded, domain-shaped fixture modules.
|
|
51
|
+
- `self-integrity.mjs` — run from `skills/design/`: anchor parity (prose ↔ catalog), stated counts, fixture-pair presence and contrastive validity. CI-owned.
|
|
52
|
+
|
|
53
|
+
## Project artifacts
|
|
54
|
+
|
|
55
|
+
The skill writes these into the consumer project; the emitted code and these files are the only design record — no sidecar caches.
|
|
56
|
+
|
|
57
|
+
- `design.md` (project root) — the brand document + lever manifest. Create writes it; improve reads and, on a foreign UI, extracts it. Provenance is one of `project | extracted | library | default` (extracted sits at project precedence).
|
|
58
|
+
- `docs/design/structure.md` — the entity/surface map, in a fenced `yaml structure` block; `scaffold.mjs` consumes it.
|
|
59
|
+
- `docs/design/findings/YYYY-MM-DD-<slug>.md` — dated introspect and review reports.
|
|
60
|
+
- `docs/memory/design-decay.md` — the decay ledger: rules skipped or fought, the fix-or-classify classifications, guidance that produced wrong output. Append-only, maintainer-read, human-closed. The skill never self-modifies — it observes decay; the maintainer closes it.
|
|
61
|
+
|
|
62
|
+
## Substrate and scope
|
|
63
|
+
|
|
64
|
+
- Substrate is **`@nurix/components` (default) or `shadcn/ui` only** — the Tailwind + shadcn-flavor floor. Import `@nurix/components` by subpath (`@nurix/components/button`); emit `.tsx`, never `.jsx`.
|
|
65
|
+
- The `components` API reference is a **separate skill** — a pure reference, never invoked from here. `design` ships as one skill with zero cross-skill invocation; all its knowledge is lazily-loaded data under `references/` and `data/`.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
id,dimension,statement,numbers,grade,fire_points,detector,scope_note,provenance,fixture_pair
|
|
2
|
+
typ-01,P1,"Text meets contrast minimums: body against its background, large text at the relaxed floor.","body >=4.5:1; large >=3:1",machine,render,render,"Effective contrast is pixel-measured on the rendered surface (render rung, D32).",WCAG 1.4.3;uxui;gnu;ben;uupm,na
|
|
3
|
+
typ-02,P1,"Body text sits at 14px or above on operator surfaces; nothing renders below 11px anywhere.","body >=14px; hard ban <11px; uupm calls <12px a failure",machine,edit,source,"The <11px absolute ban is the universal source check; body-vs-label 14px scope is best-effort.",new;stitch;uupm,yes
|
|
4
|
+
typ-03,P1,"Form inputs are at least 16px on touch and mobile surfaces to defeat iOS zoom.",">=16px",machine,edit,source,"Touch/mobile surfaces only; desktop operator inputs are exempt.",ben;uupm,yes
|
|
5
|
+
typ-04,P1,"Line-height runs inverse to size: looser for body prose, tighter for headings.","body 1.4-1.6; headings 1.1-1.3",judged,sweep,none,"Prose text only (universality flag); dense table leading legitimately runs tighter and is exempt.",imp;new;gnu;uupm;volt/sentry,na
|
|
6
|
+
typ-05,P1,"Prose measure stays inside the readable band; data tables are exempt.","45-75ch",machine,edit,source,"Tables exempt.",imp;stitch;taste;gnu,yes
|
|
7
|
+
typ-06,P1,"At most two font families per app; the type scale holds a bounded set of distinct sizes.","<=2 families; ~6 distinct sizes",machine,sweep,source,"<=2 families is the hard machine bound; the ~6-sizes figure is advisory scale conformance (universality flag: needs a hard number to gate).",imp;new;ben;taste,yes
|
|
8
|
+
typ-07,P1,"Tabular lining numerals on every numeric column, KPI, timer, and ID.",,machine,edit,source,"The survey's single most convergent operator-table rule; font-variant-numeric on numeric contexts.",floor;new;ben;volt/stripe;volt/binance;uupm,yes
|
|
9
|
+
typ-08,P1,"All-caps micro-labels carry positive tracking; tracking never falls below the negative floor.",">=0.02em; floor >=-0.04em; caps band 0.05-0.12em",machine,edit,source,,imp;ben;taste,yes
|
|
10
|
+
typ-09,P1,"Type sizes come from a fixed rem scale, never viewport-fluid; scale steps hold the ratio band.","step ratio 1.125-1.2",machine,edit,source,"Operator surfaces; ban vw/vh/clamp on font-size.",imp,yes
|
|
11
|
+
typ-10,P1,"Adjacent type-scale steps stay at least a quarter apart.",">=25%",machine,sweep,source,"Given a declared scale.",gnu,yes
|
|
12
|
+
typ-11,P1,"No UI font weight below 400.",">=400",machine,edit,source,,gnu,yes
|
|
13
|
+
typ-12,P1,"Never size type in em; px or rem only.",,machine,edit,source,"em compounds unpredictably.",gnu,yes
|
|
14
|
+
typ-13,P1,"Dense-app type ladder as an advisory reference; the brand's declared scale wins.","H1 30-36/700; H2 24/600; H3 20/600; H4 16/600; body 14-16/400; small 12-13/400",judged,sweep,none,"Advisory ladder, not a gate; the declared scale overrides.",gnu,na
|
|
15
|
+
typ-14,P1,"Typographic characters: curly quotes and apostrophes, en-dash for ranges, real ellipsis and multiply and copyright glyphs, one space after punctuation, never underline non-links, bold XOR italic.",,machine,edit,source,"Lintable copy rules.",ben,yes
|
|
16
|
+
typ-15,P1,"Zero em-dashes in UI copy.",,machine,edit,source,"House rule, binary.",taste,yes
|
|
17
|
+
typ-16,P1,"Serif faces are banned in dashboards and software UIs.",,machine,edit,source,"Scoped to operator surfaces.",stitch,yes
|
|
18
|
+
typ-17,P1,"AI-default fonts are house-taste flags: Inter-as-reflex, Roboto or Arial or system-as-primary, Space Grotesk.",,judged,sweep,none,"House taste; a brand may legitimately choose Inter.",taste;stitch;ben,na
|
|
19
|
+
typ-18,P1,"Ration eyebrow and micro-label uppercase-tracking instances against section count.","<= ceil(sectionCount/3)",machine,sweep,source,"Mechanical count; marketing-scoped, rarely fires on operator surfaces.",taste,yes
|
|
20
|
+
typ-19,P1,"Code and mono type never scales down: fixed at 16px, long lines scroll horizontally rather than wrap.","16px fixed",machine,edit,source,,volt/sentry,yes
|
|
21
|
+
col-01,P2,"Non-text UI components clear the component-contrast floor: input borders, icons, focus rings.",">=3:1",machine,render,render,"Pixel-measured at the render rung.",WCAG 1.4.11,na
|
|
22
|
+
col-02,P2,"One accent, reserved for primary action, selection, and state; the accent stays below the saturation ceiling.","saturation <80%",machine,edit,source,"Saturation <80% is the machine check; the one-accent count is warning-tier judged (status palettes are additional, not accent violations).",floor;stitch;taste;volt/binance;volt/sentry,yes
|
|
23
|
+
col-03,P2,"Color is never the only signal: status always pairs with an icon or text.",,machine,render,render,"Pairing is confirmed on the rendered element (use-of-color, WCAG 1.4.1).",WCAG 1.4.1;uxui;uupm,na
|
|
24
|
+
col-04,P2,"Status colors flow only through semantic tokens: success, warning, destructive.",,machine,edit,source,,floor;D6,yes
|
|
25
|
+
col-05,P2,"Ban literal palette classes, hex/rgb/oklch literals, and dark: prefixes in JSX.",,machine,edit,source,"The survey's most proven machine rule (stitch validate.js).",floor;stitch;uupm,yes
|
|
26
|
+
col-06,P2,"No pure black text or canvas and no pure white surfaces; start near the near-black greys.","#000000; #111827; #1F2937; #ffffff",machine,edit,source,"Fires only when no brand token declares pure black; explicit brand tokens override (universality flag).",gnu;taste;stitch,yes
|
|
27
|
+
col-07,P2,"No opacity or rgba-fabricated shades: every shade is an explicit hex or token.",,machine,edit,source,,gnu,yes
|
|
28
|
+
col-08,P2,"Shade counts stay within bounds: the grey family and each accent family hold a bounded ramp.","greys 8-10; each accent family 5-10",machine,sweep,source,"Token-set count.",gnu,yes
|
|
29
|
+
col-09,P2,"Disabled-state opacity sits in the muted band.","0.38-0.5; ben 40-50%",machine,edit,source,,uupm;ben,yes
|
|
30
|
+
col-10,P2,"Modal scrim sits in the mid black band.","40-60% black",machine,edit,source,,uupm,yes
|
|
31
|
+
col-11,P2,"Hover darkens the base shade by a small delta.","10-15%",judged,sweep,none,"Warning-tier: token ramps quantize the delta, nearest ramp step wins.",ben,na
|
|
32
|
+
col-12,P2,"AI-slop palette ban: purple and blue neon glows and gradients, purple-gradient-on-white, reflex SaaS blue.","#3B82F6",judged,sweep,none,"Warning-tier: hue-range is detectable but a brand may legitimately be purple; the reflex #3B82F6 literal is a source-catchable sub-signal.",stitch;uupm;ben;taste,na
|
|
33
|
+
col-13,P2,"Semantic price and status colors are text-only, never fills, and never repurposed for generic success or error.",,machine,edit,source,"Per token set.",volt/binance,yes
|
|
34
|
+
col-14,P2,"Data-viz elements clear contrast: lines and bars against the background, data labels against theirs.","lines/bars >=3:1; labels >=4.5:1",machine,render,render,"Pixel-measured at the render rung.",uupm,na
|
|
35
|
+
col-15,P2,"One grey family per app: no warm and cool grey mixing.",,judged,sweep,none,"Warning-tier: a deliberate warm-surface/cool-chrome split is a brand decision, not drift.",taste;gnu,na
|
|
36
|
+
spc-01,P3,"Every spacing value lands on the declared 4/8-based scale.","standard 4/8/12/16/24/32/48/64/96px; dense 2/4/8/12/16/24/32px; monotony ceiling >=10 identical",machine,edit,source,"On-scale conformance is the machine core; the monotony sub-check (>=10 identical) does not apply to operator surfaces, where uniform row/cell rhythm is deliberate (universality flag).",gnu;ben;taste;uupm;imp;new,yes
|
|
37
|
+
spc-02,P3,"Adjacent spacing values stay at least a quarter apart.",">=25%",machine,sweep,source,"On the declared spacing scale.",gnu,yes
|
|
38
|
+
spc-03,P3,"Click and tap targets clear the minimum target size (WCAG 2.2 SC 2.5.8); touch-primary surfaces go larger.",">=24x24px; >=44px touch; dense-row 28px; >=8px spacing exception",machine,render,render,"Assembled as one SC 2.5.8 (spatial + interaction restatement); dense data-row controls compact to 28px; undersized allowed only via the >=8px target-spacing exception (int-11). Actual geometry measured at render.",WCAG 2.5.8;HIG;volt/binance;wcag22;deep-research,na
|
|
39
|
+
spc-04,P3,"Numeric table columns right-align, text left-aligns; ban center-aligned data columns.",,machine,edit,source,,new;ben,yes
|
|
40
|
+
spc-05,P3,"Group spacing exceeds within-group spacing so proximity encodes structure.","within 4-16px; between 24-64px",judged,sweep,none,"Judgment on what reads as a group.",imp;gnu,na
|
|
41
|
+
spc-06,P3,"Corners land on a fixed radius scale, one scale per page.","2/4/6/8/12/9999",machine,edit,source,"Per token set.",volt/binance;volt/theverge;taste,yes
|
|
42
|
+
spc-07,P3,"Table rows run tight: vertical cell padding plus hairline dividers, buttons compacted inside dense rows, mono numbers on every figure.","12px vertical padding; 28px button height",machine,edit,source,"Per token set; operator gold.",volt/binance,yes
|
|
43
|
+
spc-08,P3,"Full-viewport height uses min-h dvh, never h-screen or 100vh.","min-h-[100dvh]",machine,edit,source,,stitch;taste;uupm,yes
|
|
44
|
+
spc-09,P3,"Ban calc-percentage layout arithmetic; CSS Grid instead.","calc(33% - 1rem)",machine,edit,source,,stitch;taste,yes
|
|
45
|
+
spc-10,P3,"No horizontal scroll at any viewport; any overflow means the design is broken.","sweep 375/768/1024/1440",machine,render,render,"Real overflow measured at each breakpoint (render rung).",stitch;uupm;taste,na
|
|
46
|
+
spc-11,P3,"Container max-width around the wide ceiling.","~1400px; max-w-7xl",judged,sweep,none,"Operator surfaces are often legitimately full-bleed.",stitch;taste,na
|
|
47
|
+
spc-12,P3,"Section rhythm runs tighter on dense product pages than marketing.","80px dense; 96px marketing",judged,sweep,none,"Advisory.",volt/binance;volt/sentry,na
|
|
48
|
+
spc-13,P3,"Cockpit rule above the density threshold: no card boxes, hairline dividers, tight padding, mono numbers.","density >7",judged,sweep,none,"Warning-tier, dial-conditional: fires only at the declared dense tier.",taste,na
|
|
49
|
+
spc-14,P3,"Content-overload ceilings on action areas, elements, visible required fields, and nav items.",">7 action areas; 15+ elements; 12+ required fields; nav 5-9",judged,sweep,none,"Warning-tier: dense operator surfaces legitimately exceed the element counts.",uxui,na
|
|
50
|
+
spc-15,P3,"Grid and bento integrity: N items fill exactly N cells, no orphan corners, spans interlock.",,machine,render,render,"Mechanical fill; actual cell occupancy confirmed at render (dynamic lists are not statically countable).",taste,na
|
|
51
|
+
dep-01,P4,"z-index values come only from a declared scale; ban arbitrary values.","scale 0/10/20/40/100/1000; ban 999; ban 9999",machine,edit,source,,new;uupm;stitch,yes
|
|
52
|
+
dep-02,P5,"One h1 per view; heading levels never skip.","one h1",machine,sweep,source,"Whole-app cross-file check.",new;uupm,yes
|
|
53
|
+
dep-03,P5,"Dashboard holds a small set of primary metrics above the fold.","<=~4",judged,sweep,none,"Non-deterministic threshold; primary metric is not machine-detectable and command centers legitimately exceed (universality flag).",imp,na
|
|
54
|
+
dep-04,P4,"Border and shadow never do the same separation job on one element.",,machine,edit,source,"Flags an element carrying both a border and an elevation shadow; redundancy judgment noted.",imp;gnu,yes
|
|
55
|
+
int-01,B1,"Every interactive element ships a visible focus-visible ring: contrast, thickness, and offset.",">=3:1; >=2px; uupm 2-4px",machine,edit+render,source,"Ring presence is the file-local source check; ring contrast is verified at the render rung.",imp;WCAG;gnu;uupm,yes
|
|
56
|
+
int-02,B1,"Ban outline:none without a replacement focus style.",,machine,edit,source,,imp,yes
|
|
57
|
+
int-03,B1,"No pointer-only affordances: anything hover-revealed has a keyboard or focus path.",,machine,edit,source,"Partial: flags hover-only reveals lacking a focus path.",floor,yes
|
|
58
|
+
int-04,B1,"Modals use native dialog and inert focus containment; ban nested modals; side panel before modal.",,machine,edit,source,"Partial.",floor;imp,yes
|
|
59
|
+
int-05,B1,"Undo over confirm for reversible actions; confirmation only for destructive irreversible ones.",,judged,sweep,none,"An irreversible action lacking both confirm and undo is auto-critical.",imp;uxui;uupm,na
|
|
60
|
+
int-06,B1,"Optimistic updates only for low-stakes actions, always with rollback.",,judged,sweep,none,,imp,na
|
|
61
|
+
int-07,B1,"Validate on blur, never per keystroke.",,judged,sweep,none,"Scoped or judged: strength meters and character counters are legitimate per-keystroke feedback (universality flag).",imp;gnu;stitch;taste;uupm,na
|
|
62
|
+
int-08,B1,"Labels stay visible above the input; errors render inline below the field; hard ban on placeholder-as-label.","gap 4-8px",machine,edit,source,"Form fields only; a bare search input with a placeholder is the recognized exception (universality flag).",new;gnu;stitch;taste;uupm,yes
|
|
63
|
+
int-09,B4,"Sortable headers carry aria-sort; tables beyond one viewport get a sticky header or first column; a bounded default column set with a picker; bounded pagination, never infinite scroll on work queues.","5-7 visible columns; 1-25 of 150",machine,edit,source,"Most of the rule is source-checkable presence and count.",uxui;new,yes
|
|
64
|
+
int-10,B1,"An aria-live region is present wherever async status updates render.",,machine,edit,source,"Presence.",new,yes
|
|
65
|
+
int-11,B1,"Target-to-target spacing clears the minimum gap (the SC 2.5.8 spacing-exception path).",">=8px",machine,edit,source,"Declared gap on adjacent interactive targets.",uupm,yes
|
|
66
|
+
int-12,B1,"cursor:pointer on every clickable element on web.",,machine,edit,source,,uupm,yes
|
|
67
|
+
int-13,P5,"One primary CTA per screen or region; distinct button tiers; duplicate-intent CTAs fail.",,judged,sweep,none,"Warning-tier: multi-pane surfaces legitimately carry one primary per pane.",gnu;taste;uupm,na
|
|
68
|
+
int-14,B1,"All five button states are present: default, hover, active, focus, disabled.","5 states",machine,edit,source,"Presence of focus/active/disabled styling.",ben,yes
|
|
69
|
+
int-15,S4,"Virtualize lists beyond the item threshold.",">=50 items",judged,sweep,none,"Warning-tier: bounded and paginated lists are exempt; static list length is not reliably known.",uupm,na
|
|
70
|
+
int-16,B2,"Tactile press feedback: a small active translate or scale, responding within the reaction window.","-1px translateY; scale 0.98; <100-150ms",judged,sweep,none,"Warning-tier: suppressed under reduced-motion.",stitch;taste;uupm,na
|
|
71
|
+
int-17,S1,"Every interactive element and image carries a discernible accessible name (axe button-name, select-name, image-alt Critical; link-name Serious).",,machine,render,render,"Deterministic W3C accname on the rendered DOM; gate on the violations bucket only.",axe;deep-research,na
|
|
72
|
+
int-18,S1,"ARIA usage is spec-valid: allowed-attr, required-attr, required-children, valid-attr-value.",,machine,render,render,"duplicate-id-aria excluded (deprecating, WCAG 2.2 dropped SC 4.1.1); gate on violations only.",axe;deep-research,na
|
|
73
|
+
mot-01,B2,"UI transitions hold the default duration band and never exceed the hard ceiling.","default 150-250ms; micro 100-150; state 200-300; larger 300-500; ceiling 500ms",machine,edit,source,"Declared-value ceiling.",imp;ben;uupm,yes
|
|
74
|
+
mot-02,B2,"Per-interaction reference durations as a catalog, not a ban.","button 100; hover 150; tooltip 200; tab 250; modal-open 300; modal-close 250; page 400ms",judged,sweep,none,"Reference values, not bans.",ben,na
|
|
75
|
+
mot-03,B2,"Every animation is gated on prefers-reduced-motion.","0.01ms reset",machine,edit,source,,WCAG 2.3.3;ben;taste;uupm,yes
|
|
76
|
+
mot-04,B2,"Ban spring and bounce easing on operator surfaces and ban linear everywhere; easing strings come from the token set; no orchestrated page-load sequences.","ease-out cubic-bezier(0,0,0.2,1)",machine,edit,source,,floor;imp;ben;stitch;taste,yes
|
|
77
|
+
mot-05,B2,"Animate only transform and opacity, never top, left, width, height, or margin.",,machine,edit,source,"The survey's most convergent motion rule.",ben;stitch;taste;uupm,yes
|
|
78
|
+
mot-06,B2,"will-change only rides an in-progress transform or opacity animation, never blanket, never left dangling.",,machine,edit,source,,D26,yes
|
|
79
|
+
mot-07,B2,"Loading indicators skeleton the content shape, delay to avoid flash, and follow the wait-time thresholds.","delay 150-300ms; nothing <500ms; spinner/skeleton 500ms-2s; progress bar >2s",machine,edit,source,"Partial.",new;stitch;uupm;ben,yes
|
|
80
|
+
mot-08,B2,"Stagger children by a small per-item delay, capped in count and total sequence length.","30-50ms/item; cap ~8 children; total <1s; 80-100ms minimalist",judged,sweep,none,"Warning-tier, register-dependent: operator surfaces skip orchestration entirely.",uupm;taste,na
|
|
81
|
+
mot-09,B2,"Ban scroll-event listeners for animation; observers or scrubbing only.","window.addEventListener('scroll')",machine,edit,source,,taste,yes
|
|
82
|
+
mot-10,B2,"Ban useState for continuous scroll or pointer values; motion values instead.",,machine,edit,source,"Framework-scoped (React).",taste,yes
|
|
83
|
+
mot-11,B2,"Exit runs shorter than enter; press scale stays in the tight band; few animated elements per view.","exit 60-70% of enter; press scale 0.95-1.05; <=1-2 elements",judged,sweep,none,"Warning-tier: coordinated pairs legitimately exceed the element cap.",uupm,na
|
|
84
|
+
sta-01,B1,"Every data surface ships loading, empty, error, and partial/degraded states, plus post-action, cancel, disconnection/timeout, and concurrent-edit where they exist.",,machine,gate,source,"Required states, not afterthoughts; presence checked per surface.",dossier;jam;stitch;ben;uupm,yes
|
|
85
|
+
sta-02,B1,"Empty states are text-first with at most one action, never a dead-end on actionable surfaces, never a literal no-data message.","<=1 action; copy 1-2 sentences",machine,gate,source,"Shape is machine; at most one action (read-only surfaces offer zero, universality flag); copy quality is judged.",floor;imp;gnu;uxui;stitch,yes
|
|
86
|
+
sta-03,B5,"Error copy follows the formula: what happened, why, how to fix; ban dead-ends and silent failures.",,machine,gate,source,"Shape is machine: an error render must carry a recovery affordance (the dead-end/silent-failure detection); the three-part copy quality (diagnose, explain, recover) stays judged.",imp;uxui;jam,yes
|
|
87
|
+
sta-04,B1,"Errors render inline next to the offending field, not banner-only; every error is visible.",,judged,sweep,none,"Warning-tier: system-wide failures legitimately banner.",uxui,na
|
|
88
|
+
sta-05,B1,"Toasts auto-dismiss in the short band, announce politely, and never steal focus.","3-5s; aria-live polite",machine,edit,source,"Attrs.",uupm,yes
|
|
89
|
+
sta-06,B1,"Empty-state taxonomy: first-time, user-cleared, no-results, no-access, and error are distinct states with distinct copy.",,judged,sweep,none,"Judgment on which state applies; presence is machine once the state is declared.",gnu,na
|
|
90
|
+
cod-01,S3,"Emitted CSS defines every token the substrate consumes.",,machine,gate,source,"Coverage check over the full D6 token surface at token emission.",D6,yes
|
|
91
|
+
cod-02,S3,"On improve runs, every value stays inside the lever manifest's vocabulary.",,machine,edit,source,"The D10 golden-rule drift check.",D10,yes
|
|
92
|
+
cod-03,S3,"Every color, spacing, radius, and duration in a diff resolves to an emitted token.","",machine,edit,source,"Token-lock; the survey's only script-proven enforcement pattern (stitch validate.js + uupm resolver).",stitch;uupm,yes
|
|
93
|
+
cod-04,S2,"No elision comments; files compile before done.","",machine,edit,source,"Bans rest-of-code, ellipsis-comment, TODO, and for-brevity markers; files-compile is verified at the compile rung.",taste;stitch,yes
|
|
94
|
+
cod-05,B5,"Anti-fabrication: no invented metrics, no fake round numbers, no by-the-numbers stat sections, no placeholder person or company names; fake-precise mock numbers carry a mock marker; unknowable values use a bracket placeholder.","examples 99.98%; 124ms; 99.99%; 50%",machine,edit,source,"Name and section string bans are machine; number authenticity is judged; critical for KPI-dense operator surfaces.",stitch;taste,yes
|
|
95
|
+
cod-06,P6,"No emoji anywhere and no emoji-as-icons: inline SVG only, one icon family per app, consistent stroke width, never hand-rolled icon paths.","strokeWidth 1.5 or 2",machine,edit,source,"Lucide or Heroicons or Phosphor.",stitch;uupm;taste,yes
|
|
96
|
+
cod-07,S2,"Check dependencies before importing; fonts are self-hosted or use next/font with font-display swap, never a Google Fonts link in prod.",,machine,edit,source,"Dependency check before import is a procedure; the font-link ban and font-display presence are the source checks.",taste,yes
|
|
97
|
+
cod-08,P6,"Image placeholders are deterministic seeds, never broken hotlinks; images declare dimensions; below-the-fold images lazy-load.","picsum.photos/seed/{seed}/{w}/{h}; loading=lazy",machine,edit,source,,stitch;taste;uupm,yes
|
|
98
|
+
cod-09,S2,"Component line ceilings hold and files outside scope are never modified.","<120 ln table; <80 ln section",machine,edit,source,"Ceilings pinned here (survey numbers were illustrative).",uxui,yes
|
|
99
|
+
cod-10,P6,"No div-built fake product screenshots.",,judged,sweep,none,"The number-one LLM-design tell.",taste,na
|
|
100
|
+
cod-11,S2,"Every emitted component exports a typed Props interface; no HTML tags in React Native output.",,machine,edit,source,"Proven (stitch validate.js); the HTML-tag ban is framework-scoped.",stitch,yes
|
|
101
|
+
cod-12,S4,"Runtime perf budgets: LCP, INP, CLS, and frame time.","LCP <2.5s; INP <200ms; CLS <0.1; 16ms frame",machine,render,render,"Runtime metrics measured at the render rung.",taste;uupm,na
|
|
102
|
+
cod-13,B5,"Audit output carries a numeric before to after per finding; no vague language, no feels without a measurable change.",,judged,sweep,none,"The D22 finding-schema contract, enforced by self-integrity over findings rather than the UI detector.",ben,na
|
|
103
|
+
cod-14,B5,"One name per concept, one concept per name, across UI copy, help text, and API names.",,judged,sweep,none,"Legacy-locked internal names may lag a renamed label; divergence must be deliberate, never accidental.",jam,na
|
|
104
|
+
inst-01,P5,"Edge density: Canny edge pixels over total pixels, the cheapest instrument, start here.","Canny edges / pixels; r~0.83 with visual-search times",judged,render,render,"Instrument, never a gate: dense is not bad (lower-complexity-is-better refuted 0-3); a number is evidence inside a judged finding, never a verdict.",rosenholtz 2007;deep-research,na
|
|
105
|
+
inst-02,P5,"Feature congestion of the rendered surface.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",rosenholtz 2007;deep-research,na
|
|
106
|
+
inst-03,P5,"Subband entropy of the rendered surface.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",rosenholtz 2007;deep-research,na
|
|
107
|
+
inst-04,P5,"Grid quality of the layout.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
108
|
+
inst-05,P5,"White-space ratio of the layout.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
109
|
+
inst-06,P5,"Symmetry of the layout.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
110
|
+
inst-07,P5,"Figure-ground contrast of the surface.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
111
|
+
inst-08,P5,"Contour congestion of the surface.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
112
|
+
inst-09,P2,"Colorfulness of the surface.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
113
|
+
inst-10,P2,"Distinct-RGB count of the surface.",,judged,render,render,"Instrument, never a gate: dense is not bad; evidence inside a judged finding, never a verdict.",miniukovich CHI'15;aalto-ui/aim;deep-research,na
|
|
114
|
+
inst-11,B1,"KLM operator-cost of the core loop: sum the typed operators over a fixed path.","P=1.10s; H=0.40s; M=1.35s; K=0.20-0.28s; klm-fa 89.1% agreement",judged,render,render,"Comparative cost model, not throughput ground truth; a judged diagnosis dimension pairing with the D28 core loop and floor P1 throughput; countable clicks, keystrokes, tab-stops, and homings given a fixed path.",card-moran-newell;al-megren 2018;deep-research,na
|
|
115
|
+
trust-01,B1,"AI presence is disclosed on the surface.",,judged,sweep,none,"Absence grades auto-critical (D34).",D34,na
|
|
116
|
+
trust-02,B1,"A human override path is visible.",,judged,sweep,none,"Absence grades auto-critical (D34).",D34,na
|
|
117
|
+
trust-03,B1,"AI-initiated irreversible actions are consent-gated with a preview.",,judged,sweep,none,"Absence grades auto-critical (D34).",D34,na
|
|
118
|
+
trust-04,B1,"AI actions are auditable.",,judged,sweep,none,"Judged trust dimension (D34).",D34,na
|
|
119
|
+
proc-01,S3,"Extract levers before any improve run on a foreign UI.",,procedure,gate,procedure,"Recover the lever manifest from code into a design.md before writing (D10).",D10,na
|
|
120
|
+
proc-02,B5,"Ask the reader question before any introspect run.",,procedure,gate,procedure,"One question, every run; never inferred, never a stored default (D14).",D14,na
|
|
121
|
+
proc-03,P5,"Run the object pass before screens.",,procedure,gate,procedure,"Six-archetype catalog, no brief-size threshold; a small brief earns a proportionally small pass, never a skipped one (D28).",D28,na
|
|
122
|
+
proc-04,P3,"Declare the density tier per surface archetype before emission.",,procedure,gate,procedure,"Global tier plus per-archetype relative modifiers (D31).",D31,na
|
|
123
|
+
proc-05,P7,"Name the taste anchor before look decisions: the selected design.md, project over library over Nurix default.",,procedure,gate,procedure,"Named-reference discipline (D5).",D5;imp,na
|
|
124
|
+
proc-06,S2,"Run the self-critique pass against the brief and the ban list before declaring a create run done.",,procedure,sweep,procedure,"The four-rung verification ladder (D32).",D32,na
|
|
125
|
+
proc-07,S3,"Resolve the design system and persist it before any UI code.",,procedure,gate,procedure,"Resolver-before-code; the machine complement of the named-taste-anchor step, occupied by personality.css emission.",uupm,na
|
|
126
|
+
proc-08,S3,"Token-lock at emission: after resolution, no value lands outside the emitted token file.",,procedure,gate,procedure,"The procedural counterpart of cod-03 (stitch validate.js pattern).",stitch,na
|
|
127
|
+
proc-09,S2,"Run a mechanical pre-flight self-count with a fail condition: count rule instances against thresholds; the output fails if over.",,procedure,sweep,procedure,"No unticked box ships; sharpens the self-critique pass from vibes to counting.",taste,na
|
|
128
|
+
proc-10,P3,"Run numeric-anchored self-audit passes, each carrying an exact-value criterion.",,procedure,sweep,procedure,"Audit canvas, corners-on-scale, shadows, link hover (volt Family-B).",volt,na
|
|
129
|
+
proc-11,P5,"Follow the fixed audit ordering, then consolidate, dedupe, severity-rank, and report before to after.",,procedure,sweep,procedure,"hierarchy -> typography -> palette -> spacing -> buttons -> clutter -> empty states -> shadows -> contrast -> grouping.",gnu;ben,na
|
|
130
|
+
proc-12,B5,"Run the copy self-audit: re-read every visible string and rewrite every flagged one.",,procedure,sweep,procedure,"Kills lorem-slop and fabricated metrics in one pass.",taste,na
|
|
131
|
+
proc-13,B3,"Sweep viewports before done; any horizontal scroll means the design is broken.","375/768/1024/1440",procedure,sweep,procedure,"Fix, do not ship.",stitch;uupm;taste,na
|
|
132
|
+
proc-14,S2,"Cross-check scope: compare deliverable count against scope count and add anything missing before responding.",,procedure,sweep,procedure,,taste,na
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# design.md — schema `design-md/v1`
|
|
2
|
+
|
|
3
|
+
A `design.md` is one operator UI's brand document: nine prose sections that describe the look for a
|
|
4
|
+
human, followed by two fenced machine blocks that make it derivable. `derive-personality.mjs` parses
|
|
5
|
+
both blocks; the prose is for the reader and the emitting agent. The prose informs, the blocks bind.
|
|
6
|
+
|
|
7
|
+
**One schema, every origin.** A project's own `design.md`, a shipped library product entry, the Nurix
|
|
8
|
+
default ([`nurix.md`](nurix.md)), and a manifest [`derive-personality.mjs`](../../scripts/derive-personality.mjs)
|
|
9
|
+
extracts from a foreign UI all use this identical shape. The only thing that varies is the `provenance`
|
|
10
|
+
field. Downstream is unchanged: whichever document resolves, personality synthesis derives the 26
|
|
11
|
+
primitive values and dial defaults from the same two blocks.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Frontmatter
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
---
|
|
19
|
+
schema: design-md/v1
|
|
20
|
+
product: Meridian
|
|
21
|
+
provenance: project # project | library | default | extracted
|
|
22
|
+
sourced: 2026-07-04
|
|
23
|
+
---
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Field | Required | Value |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `schema` | yes | Literal `design-md/v1`. The version tag; a parser refuses an unknown value. |
|
|
29
|
+
| `product` | yes | The product name. For `default` it is `Nurix`; for `project`/`extracted` it is the project's own `data-style` slug source. |
|
|
30
|
+
| `provenance` | yes | One of the four legal origins (below). |
|
|
31
|
+
| `sourced` | yes | ISO date the document was authored, extracted, or last re-sourced. |
|
|
32
|
+
|
|
33
|
+
## Provenance and precedence
|
|
34
|
+
|
|
35
|
+
Four legal `provenance` values; three resolution origins. Look resolution reads `design.md`-first
|
|
36
|
+
and never applies a library match silently (D29/D30 — **propose-confirm**).
|
|
37
|
+
|
|
38
|
+
| Value | Origin | Precedence |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `project` | The project's own `design.md` at repo root, authored by a create run. | **Wins outright** when present. |
|
|
41
|
+
| `extracted` | The project's manifest, recovered from a UI this skill did not build (improve extracts it before touching code — D10). | Same tier as `project`: once written it *is* the project's lever manifest. |
|
|
42
|
+
| `library` | A shipped named-product entry (`library/<product>.md`). | Serves only when the brief names or resembles the product **and the user confirms**. Never applied on inference alone. |
|
|
43
|
+
| `default` | The Nurix default ([`nurix.md`](nurix.md)). | Worn when there is no project document and no confirmed library match. Zero input → default; the default *is* the confirmation. |
|
|
44
|
+
|
|
45
|
+
Matching is propose-confirm: the skill may propose a `library` entry from brief resemblance, presents
|
|
46
|
+
it once, and applies it only on confirmation. The project's own document always beats a proposal.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## The nine prose sections
|
|
51
|
+
|
|
52
|
+
Fixed order. Each is human-facing narration; cite roles and token names, never bare literals in the
|
|
53
|
+
component/layout prose (the values live in the machine blocks). A good entry is concrete and checkable,
|
|
54
|
+
not adjectival.
|
|
55
|
+
|
|
56
|
+
| # | Section | What belongs · what a good entry looks like |
|
|
57
|
+
| --- | --- | --- |
|
|
58
|
+
| 1 | **Visual Theme** | The one-paragraph identity a stranger could repeat: surface polarity (light default; dark opt-in), material feel (flat vs lifted), accent discipline, density posture. Names its anchor surface and its single accent — not a mood board. |
|
|
59
|
+
| 2 | **Color Roles** | Every color by role — background, ink/foreground, the one accent, the status hues — with its value and where it is *allowed*. Reads `role → value → usage rule`; light values first; states the one-accent default. |
|
|
60
|
+
| 3 | **Typography** | The sans/mono families, the size·weight·tracking ramp, and where tabular figures apply. Names each ramp step with its numbers; states that numeric columns render `tabular-nums`. |
|
|
61
|
+
| 4 | **Component Stylings** | How the shared primitives render on the recurring operator components — button, input, card, table row, side panel, badge: fill, radius, border, padding. Each line cites token roles, no literal hex. |
|
|
62
|
+
| 5 | **Layout** | Spacing base unit and scale, the shell dimensions (sidebar expanded/collapsed, topbar, side panel, form/table), grid and container widths, density posture. The dimensions map one-to-one to the layout primitives. |
|
|
63
|
+
| 6 | **Depth** | The elevation strategy: surface ladder vs shadow, hairline discipline, the focus-ring treatment, the z-index scale. Names levels `0..n` with treatment and use; states whether shadow or surface carries hierarchy. |
|
|
64
|
+
| 7 | **Do's & Don'ts** | The enforceable taste rules unique to this brand — reserve the accent, never pill the CTA, never a second chromatic accent. Imperative bullets, each checkable; every don't names the specific off-brand move. |
|
|
65
|
+
| 8 | **Responsive** | Breakpoints and the collapse strategy across the operator sweep (375 / 768 / 1024 / 1440): nav collapse, grid re-flow, side-panel → sheet, density steps. Reads `breakpoint → what changes`. |
|
|
66
|
+
| 9 | **Agent Prompt Guide** | Directives the emitting agent follows verbatim: what to reach for first, the invariants, the scarce elements the machine blocks can't carry (e.g. "lead every queue with the table; accent only on the primary action"). |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Machine block 1 — `design-primitives`
|
|
71
|
+
|
|
72
|
+
Fenced as ` ```yaml design-primitives `. Carries **all 26 visual primitives** (names below, without
|
|
73
|
+
the leading `--`) plus the two behavioral dials, the density tier, and the product-type traits. Every
|
|
74
|
+
key is either a concrete value or a `hint:` (the hint convention, below).
|
|
75
|
+
|
|
76
|
+
| Family | Key | Type / unit | Example |
|
|
77
|
+
| --- | --- | --- | --- |
|
|
78
|
+
| geometric | `radius` | length | `6px` |
|
|
79
|
+
| | `shadow-intensity` | 0–1 multiplier on `--shadow-*` | `0.5` |
|
|
80
|
+
| | `border-weight` | length | `1px` |
|
|
81
|
+
| | `density-gap` | multiplier on the `0.25rem` spacing base | `0.85` |
|
|
82
|
+
| | `density-inset` | multiplier on component insets | `0.85` |
|
|
83
|
+
| typographic | `font-sans` | font stack | `Inter, system-ui, sans-serif` |
|
|
84
|
+
| | `font-mono` | font stack | `JetBrains Mono, ui-monospace, monospace` |
|
|
85
|
+
| | `font-weight-normal` | 100–900 | `400` |
|
|
86
|
+
| | `font-weight-strong` | 100–900 | `600` |
|
|
87
|
+
| | `heading-tracking` | em/px tracking | `-0.01em` |
|
|
88
|
+
| temporal | `duration-unit` | ms base | `50ms` |
|
|
89
|
+
| | `duration-fast` | ms | `100ms` |
|
|
90
|
+
| | `duration-normal` | ms | `150ms` |
|
|
91
|
+
| | `duration-slow` | ms | `250ms` |
|
|
92
|
+
| | `ease-default` | cubic-bezier | `cubic-bezier(0.4,0,0.2,1)` |
|
|
93
|
+
| surface | `contrast-boost` | multiplier (1 = default) | `1` |
|
|
94
|
+
| iconography | `icon-stroke` | px stroke-width | `1.75` |
|
|
95
|
+
| | `icon-size-base` | length | `16px` |
|
|
96
|
+
| layout | `sidebar-width-expanded` | length | `248px` |
|
|
97
|
+
| | `sidebar-width-collapsed` | length | `56px` |
|
|
98
|
+
| | `topbar-height` | length | `52px` |
|
|
99
|
+
| | `side-panel-width` | length | `420px` |
|
|
100
|
+
| | `side-panel-width-rich` | length | `640px` |
|
|
101
|
+
| | `modal-width-max` | length | `560px` |
|
|
102
|
+
| | `form-max-width` | length | `640px` |
|
|
103
|
+
| | `table-row-height` | length | `40px` |
|
|
104
|
+
|
|
105
|
+
Then the dials and traits:
|
|
106
|
+
|
|
107
|
+
| Key | Values | Note |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `verbosity` | `full` \| `default` \| `compact` \| `expert` | Emits `data-verbosity` on `<html>` (D4). |
|
|
110
|
+
| `feedback` | `subtle` \| `minimal` | Emits `data-feedback` (D4). |
|
|
111
|
+
| `density-tier` | `spacious` \| `standard` \| `dense` | The global tier (D31); emits `data-density`; drives `density-gap`/`density-inset` coherently. |
|
|
112
|
+
| `product-traits` | list of trait slugs | Product-type signals the front gate reads (D30) — e.g. `[review-queue, case-detail, fintech]`. Non-empty. |
|
|
113
|
+
|
|
114
|
+
**Derived, never stored.** Emission computes `--ease-enter`, `--ease-exit`, and `--stagger-delay` from
|
|
115
|
+
`ease-default` and `duration-unit`. They are not among the 26, not authored in the block, and not part
|
|
116
|
+
of the coverage gate. Do not add them.
|
|
117
|
+
|
|
118
|
+
## Machine block 2 — `lever-manifest`
|
|
119
|
+
|
|
120
|
+
Fenced as ` ```yaml lever-manifest `. The machine-readable **allowlist** the drift check reads (D10/D19):
|
|
121
|
+
[`detector.mjs`](../../scripts/detector.mjs) flags any emitted value outside this vocabulary — a radius
|
|
122
|
+
not in `radius-scale`, a color that is not one of these tokens, a spacing off `spacing-scale`, a motion
|
|
123
|
+
duration off `motion.durations`.
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
version: 1
|
|
127
|
+
fonts: { sans: "…", mono: "…" } # match font-sans / font-mono
|
|
128
|
+
color-tokens:
|
|
129
|
+
light: { … 17 semantic + 17 substrate tokens, every one valued … }
|
|
130
|
+
spacing-scale: [2, 4, 8, 12, 16, 24, 32, 48, 64] # px, on-scale values ONLY, ascending
|
|
131
|
+
radius-scale: [0, 4, 6, 12, 9999] # px, ascending
|
|
132
|
+
shadow-levels: [none, sm, md] # ordered by increasing intensity
|
|
133
|
+
motion: { durations: [100, 150, 250], easings: ["cubic-bezier(0.4,0,0.2,1)"] } # ms, ascending
|
|
134
|
+
icons: { family: lucide, stroke: 1.75 }
|
|
135
|
+
accent-count: 1
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`color-tokens.light` must value **every** token below. Dark is opt-in; when a project ships dark, add a
|
|
139
|
+
parallel `dark:` map — light is never omitted.
|
|
140
|
+
|
|
141
|
+
- **Semantic (17):** `background` · `foreground` · `card` · `card-foreground` · `muted` ·
|
|
142
|
+
`muted-foreground` · `border` · `input` · `ring` · `primary` · `primary-foreground` · `accent` ·
|
|
143
|
+
`accent-foreground` · `destructive` · `destructive-foreground` · `success` · `warning`.
|
|
144
|
+
- **Substrate (17, the D6 set):** `popover` · `popover-foreground` · `secondary` · `secondary-foreground` ·
|
|
145
|
+
`chart-1` · `chart-2` · `chart-3` · `chart-4` · `chart-5` · `sidebar` · `sidebar-foreground` ·
|
|
146
|
+
`sidebar-primary` · `sidebar-primary-foreground` · `sidebar-accent` · `sidebar-accent-foreground` ·
|
|
147
|
+
`sidebar-border` · `sidebar-ring`.
|
|
148
|
+
|
|
149
|
+
No consumed token falls back to a shadcn-gray default: emission sets all 34 (D6).
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## The `hint:` convention and derivation write-back
|
|
154
|
+
|
|
155
|
+
Where a value needs judgment the document states a **hint** instead of a value: the key's value begins
|
|
156
|
+
with `hint:` followed by the intent in plain words.
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
contrast-boost: hint: nudge borders up a step so the dense table grid reads as a grid
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
A hint **passes** the coverage gate (`--check`) — the key is present and un-missing. It does not pass
|
|
163
|
+
emission: `derive-personality.mjs --emit` resolves each hint to a concrete value by judgment and
|
|
164
|
+
**records its rationale back into the document**, rewriting the line so the resolved document is
|
|
165
|
+
self-explaining and re-derivable:
|
|
166
|
+
|
|
167
|
+
```yaml
|
|
168
|
+
contrast-boost: 1.1 # derived: dense-grid brief → one step up (was hint)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
After resolution no bare `hint:` remains; a re-run of `--check` sees only concrete values. Judgment is
|
|
172
|
+
recorded, never silent (D29).
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Validation — what `derive-personality.mjs --check` enforces
|
|
177
|
+
|
|
178
|
+
The coverage gate. It exits non-zero and **names every offending key** so the fix is mechanical.
|
|
179
|
+
|
|
180
|
+
1. **Frontmatter** present with `schema: design-md/v1` and a legal `provenance`.
|
|
181
|
+
2. **Both blocks present and parseable** — exactly one `design-primitives` and one `lever-manifest`
|
|
182
|
+
fenced YAML block.
|
|
183
|
+
3. **Every primitive assigned or hinted** — all 26 keys present as a value or a `hint:`; fails naming
|
|
184
|
+
any absent key.
|
|
185
|
+
4. **Every dial and the tier assigned** — `verbosity`, `feedback`, `density-tier` set to a legal value;
|
|
186
|
+
`product-traits` a non-empty list.
|
|
187
|
+
5. **Every color token valued** — all 17 semantic + 17 substrate tokens present in
|
|
188
|
+
`color-tokens.light` with a non-empty value; fails naming any missing token.
|
|
189
|
+
6. **Scales non-empty and sorted** — `spacing-scale`, `radius-scale`, and `motion.durations` non-empty
|
|
190
|
+
and ascending; `shadow-levels` non-empty and ordered by intensity; `motion.easings`, `fonts.sans`,
|
|
191
|
+
`fonts.mono` non-empty; `icons.family`/`icons.stroke` present; `accent-count` ≥ 1.
|
|
192
|
+
|
|
193
|
+
A document that passes `--check` is guaranteed derivable — every primitive, dial, and substrate token
|
|
194
|
+
is assigned or hinted before token emission may run (never best-effort, D6/D29).
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Worked example — Meridian (fictional fraud-review console)
|
|
199
|
+
|
|
200
|
+
A dense review-queue + case-detail operator tool. Both machine blocks are complete and fully derived
|
|
201
|
+
(no remaining hints); the prose sections are sketched to one line each for brevity.
|
|
202
|
+
|
|
203
|
+
````markdown
|
|
204
|
+
---
|
|
205
|
+
schema: design-md/v1
|
|
206
|
+
product: Meridian
|
|
207
|
+
provenance: project
|
|
208
|
+
sourced: 2026-07-04
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 1 Visual Theme
|
|
212
|
+
Light, flat, cool-slate operator console; a single indigo accent; dense on purpose.
|
|
213
|
+
|
|
214
|
+
## 2 Color Roles
|
|
215
|
+
Ink #0f172a on #ffffff; indigo #4f46e5 is the only accent; red/green/amber for status only.
|
|
216
|
+
|
|
217
|
+
## 3 Typography
|
|
218
|
+
Inter for text, JetBrains Mono for IDs and amounts; body 14px/400, headings 600, tabular-nums on every numeric column.
|
|
219
|
+
|
|
220
|
+
## 4 Component Stylings
|
|
221
|
+
Buttons `radius`/`primary`, no pill; inputs 1px `border`; table rows `table-row-height`; case detail opens in the side panel.
|
|
222
|
+
|
|
223
|
+
## 5 Layout
|
|
224
|
+
4px base; sidebar 248/56px, topbar 52px, side panel 420/640px, tables full-width.
|
|
225
|
+
|
|
226
|
+
## 6 Depth
|
|
227
|
+
Surface ladder over shadow; hairline `border`; 2px `ring` focus outline; three z-levels.
|
|
228
|
+
|
|
229
|
+
## 7 Do's & Don'ts
|
|
230
|
+
Do reserve indigo for the primary action. Don't pill the CTA; don't add a second chromatic accent.
|
|
231
|
+
|
|
232
|
+
## 8 Responsive
|
|
233
|
+
375 stacks to a sheet; 768 collapses the sidebar; 1024/1440 hold the two-pane queue+detail.
|
|
234
|
+
|
|
235
|
+
## 9 Agent Prompt Guide
|
|
236
|
+
Lead with the queue table; accent only the primary action; keep the case panel beside the work, never a modal.
|
|
237
|
+
|
|
238
|
+
```yaml design-primitives
|
|
239
|
+
radius: 6px
|
|
240
|
+
shadow-intensity: 0.5
|
|
241
|
+
border-weight: 1px
|
|
242
|
+
density-gap: 0.85
|
|
243
|
+
density-inset: 0.85
|
|
244
|
+
font-sans: Inter, system-ui, sans-serif
|
|
245
|
+
font-mono: JetBrains Mono, ui-monospace, monospace
|
|
246
|
+
font-weight-normal: 400
|
|
247
|
+
font-weight-strong: 600
|
|
248
|
+
heading-tracking: -0.01em
|
|
249
|
+
duration-unit: 50ms
|
|
250
|
+
duration-fast: 100ms
|
|
251
|
+
duration-normal: 150ms
|
|
252
|
+
duration-slow: 250ms
|
|
253
|
+
ease-default: cubic-bezier(0.4,0,0.2,1)
|
|
254
|
+
contrast-boost: 1
|
|
255
|
+
icon-stroke: 1.75
|
|
256
|
+
icon-size-base: 16px
|
|
257
|
+
sidebar-width-expanded: 248px
|
|
258
|
+
sidebar-width-collapsed: 56px
|
|
259
|
+
topbar-height: 52px
|
|
260
|
+
side-panel-width: 420px
|
|
261
|
+
side-panel-width-rich: 640px
|
|
262
|
+
modal-width-max: 560px
|
|
263
|
+
form-max-width: 640px
|
|
264
|
+
table-row-height: 40px
|
|
265
|
+
verbosity: default
|
|
266
|
+
feedback: subtle
|
|
267
|
+
density-tier: dense
|
|
268
|
+
product-traits: [review-queue, case-detail, fintech]
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
```yaml lever-manifest
|
|
272
|
+
version: 1
|
|
273
|
+
fonts: { sans: "Inter, system-ui, sans-serif", mono: "JetBrains Mono, ui-monospace, monospace" }
|
|
274
|
+
color-tokens:
|
|
275
|
+
light:
|
|
276
|
+
background: "#ffffff"
|
|
277
|
+
foreground: "#0f172a"
|
|
278
|
+
card: "#ffffff"
|
|
279
|
+
card-foreground: "#0f172a"
|
|
280
|
+
muted: "#f1f5f9"
|
|
281
|
+
muted-foreground: "#64748b"
|
|
282
|
+
border: "#e2e8f0"
|
|
283
|
+
input: "#e2e8f0"
|
|
284
|
+
ring: "#6366f1"
|
|
285
|
+
primary: "#4f46e5"
|
|
286
|
+
primary-foreground: "#ffffff"
|
|
287
|
+
accent: "#eef2ff"
|
|
288
|
+
accent-foreground: "#4f46e5"
|
|
289
|
+
destructive: "#dc2626"
|
|
290
|
+
destructive-foreground: "#ffffff"
|
|
291
|
+
success: "#16a34a"
|
|
292
|
+
warning: "#d97706"
|
|
293
|
+
popover: "#ffffff"
|
|
294
|
+
popover-foreground: "#0f172a"
|
|
295
|
+
secondary: "#f1f5f9"
|
|
296
|
+
secondary-foreground: "#0f172a"
|
|
297
|
+
chart-1: "#4f46e5"
|
|
298
|
+
chart-2: "#0ea5e9"
|
|
299
|
+
chart-3: "#16a34a"
|
|
300
|
+
chart-4: "#d97706"
|
|
301
|
+
chart-5: "#dc2626"
|
|
302
|
+
sidebar: "#f8fafc"
|
|
303
|
+
sidebar-foreground: "#0f172a"
|
|
304
|
+
sidebar-primary: "#4f46e5"
|
|
305
|
+
sidebar-primary-foreground: "#ffffff"
|
|
306
|
+
sidebar-accent: "#eef2ff"
|
|
307
|
+
sidebar-accent-foreground: "#4f46e5"
|
|
308
|
+
sidebar-border: "#e2e8f0"
|
|
309
|
+
sidebar-ring: "#6366f1"
|
|
310
|
+
spacing-scale: [2, 4, 8, 12, 16, 24, 32, 48, 64]
|
|
311
|
+
radius-scale: [0, 4, 6, 12, 9999]
|
|
312
|
+
shadow-levels: [none, sm, md]
|
|
313
|
+
motion: { durations: [100, 150, 250], easings: ["cubic-bezier(0.4,0,0.2,1)"] }
|
|
314
|
+
icons: { family: lucide, stroke: 1.75 }
|
|
315
|
+
accent-count: 1
|
|
316
|
+
```
|
|
317
|
+
````
|