You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
5.8 KiB
87 lines
5.8 KiB
---
|
|
title: Packs — encapsulated opt-in collections
|
|
type: reference
|
|
audience: human + agent
|
|
authority: E1 architecture — the pack tier: what it is, the canon-vs-pack admission rule, the P contract, the promotion path
|
|
status: current
|
|
---
|
|
|
|
# Packs
|
|
|
|
A **pack** is an encapsulated, opt-in collection that sits ABOVE the UIX
|
|
layers and OUTSIDE the component canon. It consumes the framework; the
|
|
framework never references it. The live inventory is the `src/packs/` tree —
|
|
never a list in a doc.
|
|
|
|
Packs exist so that **decorative surface area does not dilute the canon**:
|
|
the catalog's value is contract density (events, ARIA, keyboard, tokens other
|
|
layers consume); a pack's value is parameterized leaf decoration. Mixing the
|
|
two would put fashion-velocity artifacts inside the doctrine that must age
|
|
slowly.
|
|
|
|
## The admission rule (canon vs pack)
|
|
|
|
> **Canon** = anything with contract surface that others consume — semantic
|
|
> events, ARIA/keyboard behavior, state machines, tokens targeted by other
|
|
> recipes. It enters through the 9-phase route and the acceptance matrix.
|
|
>
|
|
> **Pack** = a decorative leaf with parameters — nothing else in the system
|
|
> selects against it, listens to it, or inherits from it. It enters through
|
|
> the P contract below, and stays out of `component:audit`.
|
|
|
|
If a pack piece grows contract surface (a real event, an a11y obligation, a
|
|
token another recipe wants), that is the signal to **promote it to the
|
|
canon** through the full route — never to grow the pack's privileges.
|
|
|
|
## Hard boundaries
|
|
|
|
1. **Dependency direction is one-way**: `src/packs/*` may import `$uix/*`,
|
|
`$scene`, `$adom` and the other arts; nothing under `src/{arts,libs,uix}`
|
|
may import from `src/packs/`. Deleting a pack directory must leave
|
|
`npm run check` green — that is the encapsulation proof.
|
|
2. **No morfo, no matrix**: pack pieces declare no morfo and take no row in
|
|
the acceptance matrix. Their DOM is decorative (`aria-hidden` where it
|
|
paints, `pointer-events: none` unless an effect opts into pointer input).
|
|
3. **Packs are removable by construction** — an app that never imports a
|
|
pack pays zero bytes for it (per-module registration, tree-shaken).
|
|
|
|
## The P contract (the pack quality floor)
|
|
|
|
A pack is exempt from the acceptance matrix, NOT from discipline. Every pack
|
|
ships with these six obligations, guarded mechanically (`packs-check`):
|
|
|
|
| P | Obligation |
|
|
| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| P-1 | Every animated piece declares a `reduce` policy (`'static-frame'` \| `'hide'`) — no silent default; reduced motion is honored via the injected DOM port, never a raw `matchMedia`. |
|
|
| P-2 | Full teardown: every mount returns a handle whose `dispose()` releases frames, observers, GL resources and listeners. |
|
|
| P-3 | DOM only through the injected port (`dom.requestFrame` / `observeResize` / `observeIntersection` / `listen`) — raw `requestAnimationFrame` / `ResizeObserver` / `IntersectionObserver` / `addEventListener` in `src/packs/` is an error. |
|
|
| P-4 | Color parameters are token-aware: they accept an eidos custom-property name (resolved via `eidos.resolveToken`, re-resolved on mode change) or a raw CSS color as fallback; hardcoded palettes without a token path are an error for theme-facing params. |
|
|
| P-5 | Decorative DOM is `aria-hidden="true"`; pointer interactivity is opt-in per piece and never traps focus. |
|
|
| P-6 | Off-screen and hidden-tab work is paused; a scene budget guards against unbounded concurrent GL contexts (warn via logger). |
|
|
|
|
## The promotion path (the agentic direction)
|
|
|
|
The first pack (`ambient`, animated backgrounds) exists ahead of a canonical
|
|
consumer: the **agent-presence component** (reserved name: `Aura`) that will
|
|
materialize the `delegate` + `sustain` families — the visual channel is the
|
|
ONLY channel `delegate` activates (see `decisions/book-deviations.md` D.8),
|
|
and today nothing in the catalog expresses it.
|
|
|
|
To make that promotion cheap, the **effects are shared resources, not pack
|
|
internals**: they live with the runtime (`$scene/effects`), the pack mounts
|
|
them decoratively, and `Aura` will mount the same resources semantically
|
|
(states from the agent lifecycle; intent modulating speed / amplitude / hue —
|
|
the visual analog of sound's pitch / gain / contour). Orientative state →
|
|
effect mapping recorded in the plan: idle → mesh/fog/grainient · listening →
|
|
orb/lumen · thinking → aurora/silk · acting/streaming → threads/waves ·
|
|
searching → radar · error (event, not state) → ray. When `Aura` lands, the
|
|
scene runtime is promoted to a `uix.scene` service; until then it stays a
|
|
standalone factory (`createEngineScene`).
|
|
|
|
## Provenance note
|
|
|
|
The seed collection (`web/routes/demos/animations`, 45 effects) is kept
|
|
intact as **comparative reference material** — it is NOT the pack. The pack
|
|
implementations are built clean against the P contract; the originals stay to
|
|
compare against and are excluded from the framework's guards.
|