System

Closed prefs

Brand · radius · paper tweaks via apply_prefs — not layout/animation freeform.

prefs.md

Design contracts — closed prefs

Users may tweak a little. Agents must fail closed.
Prefs ≠ freeform theming. Prefs ≠ layout builder. Prefs ≠ animation catalog.

What prefs are

Closed preset ids only:

KnobIds
brandteal · slate · moss · wine
radiuscompact · default · soft
paperwarm · cool · night
surface (optional)application · marketing · mobile · desktop

Emitted as app/contract-prefs.css + contract.prefs.json via MCP apply_prefs.

Live UI: /{id}/theme → copy MCP call / JSON / CSS.

What prefs are NOT

Not a prefWhere the law lives
Preferred layouts / shell builderslayout.md · data-surface · task recipes
Preferred animations / motion catalogsanimations.md · motionLaws (micro only)
Freeform OKLCH / hex pickersBanned — inventing colors breaks the contract
Second brand accentOne accent → --brand
Per-component skinsCompose shadcn atoms under the kit

Density follows task, not a user slider. Motion stays functional + short and honors prefers-reduced-motion.

Agent workflow

  1. User picks presets on /{id}/theme (or names ids in chat).
  2. Call apply_prefs({ brand, radius, paper }).
  3. Write returned CSS/JSON into the project; import the CSS.
  4. Compose UI under get_contract / recipes.
  5. validate_ui before done.
{
  "contractId": "meridian",
  "brand": "teal",
  "radius": "compact",
  "paper": "warm",
  "surface": "application"
}

Unknown ids → rejection. Extra keys → rejection.

Raw