19 PRINCIPLES · LIDWELL / HOLDEN / BUTLER16 PASS · 3 OPENFULL AUDIT: docs/MILO_UNIVERSAL_DESIGN_AUDIT.md
A principle only counts if it changed something. Each row names the decision, the component or token that carries it, and where to see the evidence.
Audit16.01
✓ PASS 16△ OPEN 3
01Flexibility–Usability Tradeoff
The more flexible a system, the harder it is to use.
Decision: Opinionated by default, flexible by exception. Normal surfaces expose ≤4 controls; every engine parameter lives only in 20 Playground. The Nature gallery gets three sliders (strength, grain, contrast); the playground gets eleven.JEV flexibility gate · tokens/imagery.json recipes · 19-nature vs 20-playgroundPASS
0280/20 Rule
Most use comes from a small share of features.
Decision: Seven primary surfaces (Today, Milo, Goals, Projects, Tasks, Work, Activity) get the rail; nine secondary surfaces are a smaller SecondaryNavigation group that never competes..nav-group + .nav-secondary · 17-screens groupingPASS
03Progressive Disclosure
Show only what is needed now; reveal the rest on request.
Decision: Summarised → tucked → revealed → expanded. TaskSummary is a native <details>; the Run and its steps appear inside the row, not on a new page. Task Detail is the expanded level..disclosure / .run-detail / .steps · JEV disclosure gatePASS
04Hick's Law
Decision time grows with the number of options.
Decision: One primary action per surface (.btn-primary, enforced by the JEV primary gate). Permission requests offer two choices, never a matrix. Milo decides recipe, model and executor itself..permission .actions · JEV primary gate · 09 PermissionRequestPASS
05Recognition Over Recall
Recognising is easier than remembering.
Decision: The command palette lists actions with their shortcuts; Quick Entry shows its hint line; every state is a word, not a colour to decode. Artwork captions name the artist so you never have to remember who painted it..palette .kbd · .quick-entry .hint · .artwork-captionPASS
06Hierarchy
Visual order that matches importance.
Decision: Serif display for the one statement per screen; interface sans for the work; mono microtype for metadata. Rules, not boxes, separate levels. GoalHeader is display-l, ProjectHeader display-m, rows body.tokens/typography.json scale · .object-header variantsPASS
07Five Hat Racks
Information organises by location, alphabet, time, category or hierarchy.
Decision: Hierarchy for intent (Goal → Project → Task → Run → Step), time for Activity, category for Fleet (by machine) and Costs (by lane). Never alphabetical for tasks — order is Milo's ranking.tokens/semantic.json object glyphs · .row-activity time columnPASS
08Constraints
Limit actions to prevent error.
Decision: Destructive actions are level 4 with a scrim and a named object ("Delete the project Daily Bread?"). Voice cannot bypass permission. Moss cannot mean success (token set has no Moss success value)..confirmation.is-destructive · D-011 · JEV moss gatePASS
09Affordance
Form suggests use.
Decision: Buttons have edges; rows lighten on hover and show a left rule when active; disclosures carry ▶ that turns Vermilion when open; the composer's top rule turns Vermilion on focus..btn · .row:hover · .disclosure[open] .glyph · .composer:focus-withinPASS
10Mapping
Controls correspond to their effects.
Decision: The Run expands out of its own row. The theme toggle sits where the theme shows. Recipe buttons sit under the image they change. Pause is on the row it pauses.10 Motion expand demo · .recipe-tabs · data-pause-taskPASS
11Feedback
Every action gets a response.
Decision: Toasts in UI language ("On it." "Done."), the VoicePill's five states, the RunIndicator per row, Progress with a percentage. Nothing spins without a label..toast · .voice-pill[data-state] · .run-indicator · .progressPASS
12Forgiveness
Make errors recoverable.
Decision: Every toast carries Undo. Deletion moves to Trash for 30 days and says so in the confirmation. Pause never loses frames ("Paused. Nothing lost.").site.js toast() · .confirmation body copy · 21 LanguagePASS
13Factor of Safety
Build in margin beyond expected load.
Decision: Contrast targets 4.5:1 where 3:1 would pass; hit areas 44px where 24px would pass; engine works at ≤1600px and caches, so a 6000px museum master never reaches the main thread.15 Accessibility table · tokens/imagery.json performancePASS
14Signal-to-Noise Ratio
Maximise signal, minimise noise.
Decision: No card soup (JEV cardsoup gate), no decorative shadow, no gradient, no icon without a job. Information appears because it is relevant, so Today shows what matters now and nothing else.JEV cardsoup + generic gates · tokens/elevation.jsonPASS
15Aesthetic-Usability Effect
Beautiful things are perceived as easier to use.
Decision: Real art and real nature, credited, transformed by a real engine. The beauty is earned from the source, which is why provenance is a component, not a footnote.06 Art · 19 Nature · .artwork-captionPASS
16Consistency
Similar things look and behave alike.
Decision: One token file feeds CSS, the engine and both platforms; Omarchy and macOS share components and semantics and differ only in material. The glyph vocabulary is fixed in tokens/semantic.json.tools/build_tokens.py · 13 Omarchy · 14 macOSPASS
17Modularity
Compose from independent parts.
Decision: 37 components with no cross-dependencies beyond tokens; engine core has no DOM and runs in Node; recipes are plain JSON the engine accepts unchanged.engine/core.js · engine/recipes.json · 09 ComponentsPASS
18Performance Load
Reduce physical and cognitive effort.
Decision: Voice and Quick Entry from anywhere; Milo picks the executor and model; cost is shown as ⌁ local when it is $0 so you do not have to compute it. Open: the Fleet screen still asks the reader to compare four machines by eye.11 Voice · .cost.is-local · screens/fleet.htmlOPEN — Fleet summary line
19Defaults
Most users never change the defaults.
Decision: Light follows the OS; National Park is the light recipe and Nous the dark; local execution is preferred; ambient motion is on but imperceptible. Open: the default ranking of Today has no user-visible explanation yet, and the notification sound is undecided.shell.html theme bootstrap · tokens/imagery.json · MILO_OPEN_QUESTIONS.mdOPEN — ranking explanation, sound