--- title: Next features — initiative registry type: registry audience: human + agent authority: backlog of user-decided future initiatives — records scope, sequencing and dependencies; it does NOT record verdicts (those live in the RFCs / changelog / book-deviations when executed) status: living — items enter by explicit user decision during audits and sessions; remove an item when it ships (and link where it landed) created: 2026-07-06 --- # Next features — initiative registry Rules of this file: one entry per initiative, dated, with its origin (which audit/session raised it), its scope in one paragraph, and its dependencies. Entries are **registered, not started** — starting one is a session decision. Detail lives in the linked doc, never copied here. ## 1. Tonal-ramp contrast parity (measure, then construct) — 2026-07-06 · Stage 1 DONE 2026-07-19 · Stage 2 CLOSED 2026-07-20 > **Stage 1 SHIPPED (2026-07-19).** Measured with `scripts/contrast-audit.ts` > (33 scales × 2 modes); drift + user verdicts ratified as doctrine in > [`theming/reference.md §40`](./theming/reference.md) + [`changelog.md §44`](./theming/changelog.md). > Outcome: `text·11` = secondary tier, `text-strong` = AA-guaranteed; the border > vocabulary is Radix-subtle by design (only `solid·9` clears 3:1 by > construction) with a decorative-vs-load-bearing split; the focus ring is a > config axis (`primitives.focusRing` + `color.focus`, single `outline` per §32) > whose shipped default is soft — hardening is a config-value choice, kept as-is. > **Stage 2 CLOSED (2026-07-20) — no solver needed.** The 6 decisions were > locked (D1 band · D2 measured-pass · D3 flip-only · D4 opt-in · D5 runtime-first > · D6 now), then **execution disproved the premise**: the template morph does not > _compute_ text contrast, it **inherits** it (steps 11/12 copy the donor's L-curve > verbatim; L-driven contrast is ~chroma-invariant under gamut-mapping), so any > scale generated from a §40-compliant donor library clears the ratified text > floors **by construction**. Verified on three banks — authored base, leave-one-out > regeneration, and 45 out-of-distribution seeds — **0 hard-gate failures** > (min WCAG 9.7:1). The luminance solver would have had nothing to resolve for > realistic inputs → dropped as speculative. **Delivered instead:** the ratified > pair table as shared data (`$color` → `CONTRAST_PAIRS`), the audit refactored to > consume it + a morph-generated regression bank (`scripts/contrast-audit.ts`), and > a CI guard that locks the inheritance (`eidos/lib/contrast-invariant.test.ts` — > fails if a future donor/generator breaks it). With D2, the base stays verbatim > ground-truth; **no base→seeds migration**. > **Plan + decision + outcome record:** > [`process/contrast-stage2-plan-2026-07.md`](./process/contrast-stage2-plan-2026-07.md); > chronicle [`changelog.md §45`](./theming/changelog.md). **Origin**: A.7 follow-up (theming audit F). The on-solid pair is now computed at generation with a single criterion ([`rfcs/rfc-color-engine.md`](./rfcs/rfc-color-engine.md) §8, `eidos/lib/on-solid.ts`). M3 still guarantees more: contrast **by construction across its whole tonal ramp** (container/on-container pairs at fixed tone deltas — ΔT 40 ≈ 3:1, ΔT 50 ≈ 4.5:1). Our equivalent promises (text-11 on bg-2/element-3, border-7 vs bg-2 at the 3:1 non-text floor, text over composited soft surfaces a2/a3) rest on Radix-style curation, unmeasured. **Stage 1 — pair-contract verification** (the A.7 pattern generalized): a canonical table of slot pairs + floors (a user-decided doctrine session), a measurement pass over pairs × 33 scales × 2 modes at generation (`on-solid.ts` generalizes; the compositing math exists in `$color`), and the resulting drift list goes to user verdicts (retune vs annotated exception). Infrastructure is small; the fallout is the unknown. **Stage 2 — by-construction generator (CLOSED 2026-07-20, solver dropped).** The plan proposed a luminance solver that resolves each step to satisfy Stage 1's pair table for a seed. Execution disproved its premise: the morph **inherits** text contrast from the donor (steps 11/12 copy the donor's L-curve verbatim; L-driven contrast is ~chroma-invariant under gamut-mapping), so every scale from a §40-compliant donor library clears the ratified floors by construction. Measured across three banks (authored base, leave-one-out regeneration, 45 out-of-distribution seeds): **0 hard-gate failures, min WCAG 9.7:1.** The solver had nothing to resolve for realistic inputs → dropped (speculative). What shipped: the pair table as shared data (`$color` `CONTRAST_PAIRS`), the audit consuming it + a morph-generated regression bank, and a CI guard (`eidos/lib/contrast-invariant.test.ts`) that locks the inheritance. The BASE stays verbatim ground-truth (D2); no base→seeds migration. **Sequence**: Stage 1 first (it is the spec for Stage 2). No M3-style `on-*` vocabulary expansion — our slots already encode the pairs; the table formalizes them without inflating the namespace. ## 2. Per-theme palette-contrast cascade emission — 2026-07-06 **Origin**: A.7 execution. The per-instance `palette-contrast` cascade lives in the STATIC foundation — one polarity for all themes. Today polarity is computed per configured theme and unanimous (33/33 scales agree across base-light/base-dark); on disagreement the `*-light` theme wins (`computeLightSolidScales`, documented in [`rfcs/rfc-color-engine.md`](./rfcs/rfc-color-engine.md) §8). **Trigger**: the day a real configured theme disagrees on a scale's polarity, emit the cascade per-theme instead of statically. Not before — no speculative machinery. ## 3. Component audit (post-system) — 2026-07-06 **Origin**: user decision during the theming audit — "de momento no tocamos los componentes, merecen una auditoría adicional una vez que se haya resuelto estas". Gate: the system-level audit (F/G) closes first. Registered items so far, to seed its scope: - **Named-styles adoption by controls** (from A.3): controls/recipes that hand-declare typography instead of consuming `--style-*` / size-bundle typography — likely by error, to be confirmed per component. - **Letter-spacing bundle adoption**: ~34 recipes consume `font-size` / `line-height` from the size bundle but not `letter-spacing`; plus ~7 raw letter-spacing literals in component CSS. - **Tier-A `data-depth` stamping coverage**: overlays that should stamp their plane (dialog / drawer / tooltip / menubar / combobox) per [`rfcs/rfc-depth.md`](./rfcs/rfc-depth.md) §5. - **Calendar family → shared layer/archetype** (user design verdict, 2026-07-07): the calendar-grid vocabulary (accent set, day geometry, the holiday/event marks fixed in audit B.2) becomes a FIRST-CLASS shared layer — today the family borrows it informally (measured: range-calendar consumes 79 `--calendar-*` tokens, month-grid 65, year-grid 65, date-range-picker 38, date-picker 4 — ~250 cross-component borrows), and **chronos will draw from it too** when its track lands. Materialization to decide at execution: a morfo part-archetype for the day cell (the 26-set grows) and/or a `calendar-surface` shared recipe à la list-surface (`--list-item-*` precedent). This supersedes "per-component composition repairs" for the B.2 borrowers: the marks reach the whole family through the shared layer instead. - **Field family composition — segments under `[data-field]`** (user design verdict, 2026-07-07, audit B.1): segment height derives from the SIZE axis at the FIELD family level — `field` recipe declares `segment-height` with size-scoped declarations (`calc(var(--field-control-height-{k}) - var(--space-2))`; the TSC `size:` scope axis exists, unused so far), and the per-component copies die (each x-field today re-declares the whole `height-{xs..xl}` family the field recipe already has). **MANDATED by the B.1-(i) verdict**: date/time/color-field MUST incorporate the Field wrapper (segments under `[data-field][data-size]` — probed live: today they don't) as part of the component audit; the three broken per-component `segment-height` tokens and their consumers were removed (they had computed `auto` since birth — zero visual change). - Whatever F/G registers as "component-level adoption gap" in `docs/audit/theming-audit.md` when that report lands (deliverable G of the 2026-07 theming audit). ## 4. `architecture/sema.md` hold-sync — 2026-07-06 **Origin**: A.4/A.5 execution (holds single-source). `SEMA_HOLDS_BY_INTENT` (`src/uix/sema/holds.ts`) is now THE only hold table (resolver + visual channel consume it; `sema-map.ts`'s per-family hold column died). The chapter [`architecture/sema.md`](./architecture/sema.md) still narrates per-family holds in ~34 places. **Blocked**: the file is the author's WIP (uncommitted edits) — sync it when the author's pass lands, not before. ## 6. THM-2 rollout — per-instance palette to all surfaces — SHIPPED 2026-07-12; scope boundaries REVERTED by the open-color-cage initiative (2026-07-18/19) Shipped in `05f0031c` (media-player Batch-4 + 14 surfaces + vocab + 4 props) and `cc7e9a16` (avatar root). Every per-component palette cascade now collapses into the shared `--palette-*` layer (size win, behavior-preserving for roles); the vocabulary gained the alpha `surface`/`surface-hover` + `hover` slots. > **REVERSED (2026-07-18/19) — "abrir la jaula del color".** THM-2 originally > kept semantic controls (checkbox/radio/stepper/editable/select/file-upload) > and `Avatar.Badge` role-restricted "by design". A later user decision reverses > that: `color` accepts the FULL system (role / intent / 33 scales / raw CSS = > `ComponentColorProp`) on **every** component, no exceptions — content-ink > primitives keep their axis as an additive union. Enforced by two guards in > `recipe-css-contract.test.ts`. Full record + the closed queue (incl. the > chart SVG resolver and the Card/Avatar custom-color fix): > [`process/open-color-cage-2026-07.md`](./process/open-color-cage-2026-07.md). > Only `qr-code` stays out (its `color` is the QR module ink, not a scale). ## 5. Book editorial note — "el hold es suelo, no tijera" — 2026-07-06 **Origin**: A.4/A.5 verdict. The mechanism (hold = floor for the expression, never a scissor; expression waits animation-finish after the hold, capped by an absolute `MAX_EXPRESSION_WAIT_MS`, never derived from the hold) is recorded in [`decisions/book-deviations.md`](./decisions/book-deviations.md) D.12 as a candidate **editorial appendix** for the book (_Diseñando lo que ocurre_, HOMOGENEIZADO edition) — the book gives qualitative regions and this is the materialization doctrine worth feeding back to the source. ## 7. Chat block v2 — 2026-07-18 **Origin**: the `chat-*` v1 initiative (comparative study + plan, session 2026-07-18; user scoped v1 to the room core). v1 shipped `chat-log` (Feed + end-anchored VirtualList), `chat-message`, `chat-composer` (Textarea + FileUpload composition) and `chat-typing`, plus the `$libs/chat` helpers and the VirtualList `anchor: 'end'` extension. The deferred surface, registered with disposition (each item also lives in its component README §Gaps): - ~~**`chat-list`** — the conversation-list pane (rooms, unread badges, typing-in-list).~~ **✅ SHIPPED 2026-07-19** — composes `Listbox` (single-select + keyboard) with an avatar/title/preview/meta row; unread bold + `Badge`, typing-in-list composes `ChatTyping`. Virtualization for very long lists deferred (pairs with the VirtualList bidirectional item). - ~~**`emoji-picker`** — a real picker component (color-picker scale: categories, search, skin tones).~~ **✅ SHIPPED 2026-07-21** — composes `Popover` + `Command` (search + grid keyboard + combobox/listbox a11y, its documented "grid mode") + two `ToggleGroup`s (categories + skin tone). Data is the vendored `$libs/emoji` (baked from emojibase, MIT — `scripts/generate-emoji-data.ts`): ~1,900 emoji, 316 tone-capable. The grid double-registers Command's List/Item so it keeps the a11y but wears its own grid-cell styling. Delegated (no own events). Full-grid virtualization + per-emoji tone + image emoji (Twemoji/Noto) deferred. The quick-set Popover in `ChatMessage.ReactionAdd` stays as the inline tapback bar (different UX). - **Mention autocomplete (`@`)** — combobox-in-textarea for `chat-composer`; pairs with the future `words`/`palabras` integration. - **Threads UI** — the side-panel composition over the already-shipped `Feed.Thread` semantics. - ~~**Jump-to-message highlight** — `signal-emphasize-target` on `chat-message` (the morfo event was deliberately left out of v1).~~ **✅ SHIPPED 2026-07-19** — `emphasized` prop → `data-emphasized` row flash (visual-only, no sema event: reference apps flash silently; the app scrolls via a reply's `onJump` then toggles `emphasized` for ~1.4s). - ~~**Read-by list** — "seen by N" avatar row (Teams/Messenger pattern) on `chat-message`.~~ **✅ SHIPPED 2026-07-19** — `ChatMessage.ReadBy` part (the app composes `AvatarGroup`; the sender's `onMessageSeen` feeds it). - **VirtualList chat-mode refinements** — bidirectional sparse ranges for jump-into-history far from the loaded window. - ~~**Typing avatars** — faces next to the `chat-typing` dots (Messenger).~~ **✅ SHIPPED 2026-07-19** — `ChatTyping.Avatars` slot (compose `AvatarGroup`). - **Delegate-family ↔ agent chat** — the Aura reservation (§F6 of the scene/pack initiative) once agent conversations land. **Deps**: none to start `chat-list`/`emoji-picker`; mentions depend on the `words` integration decision. The transport stays app-land (`$connection`). ## 8. `blocks` tier — reusable page-function compositions — 2026-07-21 **Origin**: ecosystem analysis session 2026-07-21; user decision: a new tier for **blocks** — named compositions of canon components performing a page function (sticky site header, hero, footer, app shell, docs shell…). Scope: tier infrastructure (`src/uix/blocks/` + `$blocks`, doctrine at `architecture/blocks.md`, B contract, `blocks-check` guard), **7 canon base components first** (`sticky` · `empty-state` · `result` · `callout` · `prose` · `anchor-nav` · `sidebar` — full 9-phase route each), then the block catalog (10 site + 10 app + 3 docs). Admission rule mirrors packs: any behavior with contract surface is promoted to canon BEFORE the block composes it. Detail + per-item fiches: the execution plan at [`process/PLAN-blocks.md`](./process/PLAN-blocks.md). **Status**: D-BLK decisions SIGNED 2026-07-21 (D-BLK.1 amended by the user: the tier lives at `src/uix/blocks/`, not `src/blocks/`). **F0 SHIPPED 2026-07-21** (`069759604`: doctrine + `$blocks` + `blocks:check` + gallery). **Reference study SHIPPED 2026-07-21** (`aff42fee0`: [`process/RESEARCH-blocks-references.md`](./process/RESEARCH-blocks-references.md), 6 research tracks; every phase-0 now checks against it). Amendments E-1…E-5 SIGNED 2026-07-21: F1 = **8** canon components (+`nav-tree`, data-driven docs navigation tree); parity-floor = v1 scope policy; F2 = **14** site blocks (+banner · team · contact · content-section); distribution registered as §9; ⌘K stays app-land. **F3 STARTED 2026-08-19** — `app-shell` shipped with a signed phase 0 (four decisions: the block wires no services, two scroll models by prop, the top bar inside the inset, generated bypass links) and a new canon component in front of it, `SkipLink` (WCAG 2.4.1). It closes ledger row **A-95**, the one thing the tier could not fix from inside any block: with the shell owning the page's heights, an in-flow notice and a pinned header overlap by **0px** (measured; before: 49px, with the hit test landing on the strip). **Deps**: `scheduler` block gated on `chronos` landing; chat-room block explicitly NOT here (canon `chat-*` family, §7 above). ## 9. Blocks distribution — registry + llms.txt + MCP — 2026-07-21 **Origin**: the blocks reference study (E-4 signed 2026-07-21; dossier [`process/RESEARCH-blocks-references.md`](./process/RESEARCH-blocks-references.md) §P6). The ecosystem's 2026 table stakes for component/block distribution are agent-enumerable catalogs: a registry protocol (shadcn `registry.json` / `registry-item.json`), `llms.txt` (+ `llms-full.txt` / `.md` content negotiation) over the docs corpus, and an MCP server so agents can list and install blocks (sv-blocks precedent). Scope when started: (a) `llms.txt` generation from the docs corpus (cheap — the corpus is already Markdown, pairs with F4 docs blocks); (b) a blocks/components registry manifest; (c) an MCP server exposing catalog + morfo contracts (pairs with the contract-introspection superation angle and the palabras F-B agentive track). Registered, not started. **Deps**: F2 catalog existing (something to distribute); F4.3 props-table work shares the morfo-introspection substrate. ## 10. Barcode — deferred symbologies + GS1 profiles — 2026-07-29 **Origin**: the `Barcode` component (shipped 2026-07-29; design record + dispositions in [`eidos/components/barcode/README.md`](../src/uix/eidos/components/barcode/README.md) §Gaps). v1 covers the Retail + Logistics set — Code 128 (A/B/C auto), EAN-13/8, UPC-A/E, Code 39, ITF/ITF-14 — from their published ISO standards, in the zero-dependency `$libs/barcode` encoder. **Shipped the same day, out of this registry: the ISBN input profile.** An ISBN barcode IS an EAN-13 (ISO 2108, Bookland 978/979), so it entered as a profile over `ean13` — separators tolerated in the numeric symbologies, ISBN-10 read and converted after validating its own base-11 check digit — and explicitly NOT as a ninth `symbology` value, which would make `data-symbology` claim a standard that does not exist. The doctrine is recorded in the component README §ISBN. Four dispositions stay **diferir**, each a self-contained follow-up over the same encoder: - **Codabar · MSI · Pharmacode** — the niche tail JsBarcode still ships. Pure table work: each is a symbology module + its vectors. - **GS1-128 (FNC1 + Application Identifier parsing)** — a _profile_ of Code 128, not a new encoder: the FNC1 code value plus an AI grammar so the HRI can print the bracketed form. The natural pair for a logistics-facing app, and the same shape the ISBN profile already established. - **EAN-2 / EAN-5 add-ons + the upper `ISBN 978-…` line** — the periodical / book supplements and the book-cover convention; they extend the EAN geometry (a second text band, a composed add-on symbol) rather than replacing it. Hard constraint recorded with them: **we do not hyphenate**. The hyphen positions are not computable from the number — they need the International ISBN Agency's prefix-range tables, versioned data with an expiry date, which is a maintenance clock a zero-dependency library must not swallow. The hyphenated string comes from the consumer's catalogue. - **2D — DataMatrix · PDF417 · Aztec** — explicitly NOT this component: each is a whole different encoder (own Reed–Solomon, matrix layout). They belong beside `QrCode` as their own components, sharing the display-primitive shape. **Deps**: none — the encoder's `BarcodeResult` (module lattice + guards + HRI groups in module space) already generalises; the 2D entries would instead reuse the `$libs/qr` shape. ## 11. Background — parallax, the scrim scale, and the pack seam — 2026-08-18 **Origin**: the `Background` component (design record, measurements and dispositions in [`eidos/components/background/README.md`](../src/uix/eidos/components/background/README.md); plan and signed decisions in [`process/PLAN-background.md`](./process/PLAN-background.md)). It ships as the HOST of a surface's background layers — a child that pins itself behind its parent's content, with the parent adopted by a foundation rule rather than wrapped. Patterns, gradients, scrims, images and video are in; so is the WCAG 2.2.2 pause control. **Scope of this registry entry** — what the component deliberately does NOT own yet, each a self-contained follow-up: - **Parallax and the scroll seam** — `animation-timeline: view()` with a `ScrollProgress` fallback, `attach='fixed'`, the pointer `depth` axis. The infrastructure landed with the component (`$adom`'s `ScrollProgress` and `prefersReducedData`); the layers that consume it did not. It is the one follow-up with a mechanism already chosen and measured against browser support, so it is also the one most likely to move first. - **The scrim `strength` scale is not ordered by weight** — measured: `subtle` veils MORE than `overlay`, and `overlay` and `muted` resolve to the same number. The names come from the semantic opacity scale, which says how opaque an ELEMENT is; borrowing them for a VEIL imports an ordering that means something else. Renaming or renumbering is an API change, not a fix in passing. - **A bright photograph is illegible at every scrim weight** — white copy over the heaviest veil measures below AA. Either the scale gains a step above `--opacity-subtle`, or the doctrine becomes "the answer is a graded scrim", stated once and demonstrated. - **A shared `