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.
svelte-kit-vice/docs/next-features.md

487 lines
30 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
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 `<video>` state port** — the framework has a load-state contract
for `<img>` (`ImageProvider` in `soma/layers`) and none for `<video>`:
`ScrollFrames` listens by hand and so does `Background.Video`. Two consumers
is the threshold this codebase uses to extract a layer.
- **The `Ambient` pack honouring the pause** — the canon publishes the context
(`paused`, `reduced`, `seen`); the pack reads it. A task OF the pack, because
the dependency runs pack → framework and never back.
**Deps**: the parallax entry needs no new service — the two `$adom` ports it
consumes already shipped. The scrim entries are the author's call on the token
vocabulary, so they block on a decision, not on code.
## 12. El contrato de cascada del velo de estado — 2026-08-20
**Origen**: el eje `theme-reach` (F2-A, sesión del 2026-08-20). Al tokenizar
componente a componente aparecieron, medidas una a una, seis incidencias que
son **la misma**: nadie fijó nunca cómo compone el velo de `archetypes.css` con
las reglas de una receta. No se tocan dentro del eje de theming — mueven píxel
y son decisión aparte — pero cada una está medida y localizada.
**La raíz**: `archetypes.css` pinta el velo neutro como
`background-image: linear-gradient(var(--state-hover), var(--state-hover))`, y
lo hace con DOS pesos distintos según el arquetipo — `:where(...)` (0,0,0) para
`trigger`, y especificidad PLENA (0,5,0) para `item` / `option`, «INTENTIONAL
cross-component accent», dice su comentario. Una receta que declare fondo sobre
el mismo nodo entra en una relación que nunca se escribió.
### Las seis, con su medición
1. **El atajo `background:` cancela el velo — 131 declaraciones en 45
componentes.** El atajo fija `background-image: none`; sobre un arquetipo
velado por `:where()` eso lo mata para siempre, no sólo en hover. Medido con
`scripts/__statelayer-analysis.ts`, que comprueba contra el morfo compilado
que el atajo cae sobre el nodo VELADO y no sobre cualquiera. Por clase de
regla: **66 BASE** (mecánicas: pasar a `background-color` no mueve el
reposo), **32 ACENTO** (selected/checked/open: §38 pide `background-color`
para que el velo COMPONGA encima), **23 HOVER** (la migración de la firma 3)
y **10 OTRA** (disabled, dragging, variantes). **Cero valores con
gradiente**, así que el único riesgo técnico del paso a longhand no existe
en este catálogo. El píxel que se mueve: **32 nodos velados que hoy no
reaccionan al ratón** pasarían a hacerlo. Esto explica la adopción 21/135
que midió la auditoría del 2026-07-01: el velo estaba escrito y
estructuralmente derrotado.
2. **La prop `hoverable` de `table` no suprime nada.** El velo de `item` es
incondicional y a (0,5,0), así que una fila se ilumina al pasar el ratón
aunque `hoverable` esté apagada — verificado con hover real, y ocurre desde
antes de tocar la receta. O el arquetipo decide y la prop sobra, o la fila
no es un `item` para el sistema. Decisión de MORFO.
3. **En `tree-grid` el empate lo decide el ORDEN DE CARGA.** El velo de `item`
y el hover de la receta pesan EXACTAMENTE lo mismo (0,5,0), así que gana la
hoja que cargue después — y en el dev server varía entre recargas: seis
corridas de la misma configuración dieron cuatro «sin velo» y dos «con
velo». Un empate resuelto por orden es la misma fragilidad que el canon ya
documenta para las bandas de `z-index`.
4. **En `tree-grid` la banda mata el hover.** La regla de `striped` pesa
(0,7,0) contra los (0,5,0) del hover y usa el atajo: en las filas pares no
ocurre NADA al pasar el ratón. El hover del componente es inconsistente
entre filas.
5. **Un token de receta no puede ganar al arquetipo.** La regla de `item` fija
también `color` en el estado seleccionado, a (0,5,0) contra los (0,3,0) de
la receta: un `table.selected-row-fg` no podía mover nada nunca. Se retiró
con su declaración muerta (un token que no mueve nada es un token que
miente). Mientras el arquetipo pinte tinta, ningún componente puede
tematizar la suya en ese estado.
6. **`scroll-area.thumb-bg-hover` no tiene velo al que migrar.** Su thumb lleva
`archetype: 'thumb'`, que `archetypes.css` no vela, así que la firma 3 no
puede ejecutarse ahí sin cambiar el arquetipo — decisión de MORFO. Es el
único knob de los seis de la cola que sigue sin resolver.
### Qué habría que decidir
En una frase: **quién manda cuando el arquetipo y la receta pintan el mismo
eje**. Las tres piezas concretas: si el velo de `item` baja a `:where()` como
el de `trigger` (y entonces la receta manda, y `hoverable` vuelve a significar
algo); si las recetas pasan a longhand en bloque (66 BASE + 32 ACENTO, mecánico
y sin gradientes de por medio); y si un arquetipo puede fijar `color` sobre un
componente que quiere tematizarlo.
**Deps**: ninguna de código. Es decisión del autor sobre píxel, y el
instrumental para medirla ya existe (`__statelayer-analysis.ts` +
`__theming-probe.ts` + `__tg-rowhover.ts`).
## 13. Huecos de instrumento y de demo del eje theme-reach — 2026-08-20
**Origen**: la misma sesión. Cosas que hicieron que una medición mintiera o no
existiera. Se anotan porque el eje entero se apoya en esas mediciones.
- **El centinela da falsos negativos sobre una propiedad transicionada.**
`command.input-border` salió «no effect» y el token SÍ alcanza — verificado
tres veces a mano con la misma congelación de transición que el propio
centinela aplica. No se encontró la causa; queda sin explicar.
- **El centinela no ve pseudo-elementos.** `::placeholder`, `::after` (el scrim
de media-player) y demás quedan fuera de `getComputedStyle` sobre el nodo, así
que sus tokens siempre salen «muertos».
- **El centinela no ve lo que pinta un componente COMPUESTO.** Los tokens que
media-player reenvía al Slider (`--media-player-track` →
`--slider-track-bg`) pintan en nodos `[data-slider-*]`, fuera del espacio de
atributos del componente medido.
- **La sonda no pasa el ratón por un `<tr>`.** En `table` el conjunto de hover
no incluyó ninguna fila, así que el diff no cubría el estado donde estaba el
hallazgo. Hubo que medirlo con un script aparte.
- **Una sonda sobre una demo que no monta la parte compara CERO valores y
pasa.** Ocurrió con el skin de audio: `/uix/components/audio-player` da 404
porque la demo es la de `media-player` con el chip `media`, y la sonda cargaba
en modo vídeo. Resuelto con `scripts/__probe-audio-skin.ts`, pero la clase de
fallo es general: **una parte condicional necesita que la sonda la monte**.
Afecta al menos a captions, buffering y paneles portalados de media-player, al
estado vacío y la barra de carga de `command`, y al overview de
`date-range-picker`.
- **`date-range-picker` no expone `kind='month'` / `'year'` en su demo**
(norma N-6), así que la mitad de su API no se ve ni se mide.
- **Un componente COMPUESTO puede tener su cromo entero muerto sin que nada
avise.** `gradient-picker` re-declaraba altura, padding, tipografía, color,
fondo, borde, radio, hover y foco de su trigger, y NADA de ello pintaba:
`popover.css` gana con `[data-popover-trigger]:not([data-archetype='field-trigger'])`
(0,2,0 contra 0,1,0). Lo cazó el centinela —36 de 45 tokens sin efecto— y
retirarlo dio 0 diffs. **Merece un guard**: una declaración de receta que
ninguna cascada puede ganar es deuda muerta, y hoy sólo aparece si alguien
pasa el centinela por ese componente. El instrumento para detectarlo ya
existe (`__theming-sentinel.ts`); falta convertirlo en regla.
- **`--gp-current-gradient` es un nombre ABREVIADO en SOMA.** Lo estampa
`gradient-picker-provider.svelte.ts` (no el wrapper de eidos, como decía la
ficha), y viola theming §6 r5. No es knob de tema —es un canal de valor— pero
el nombre es deuda; renombrarlo toca soma, otra capa.
- **Hooks por CLASE en una receta de eidos.** `gradient-picker` usa
`.gradient-picker-trigger-swatch` y `.gradient-picker-trigger-label` en vez
de `data-*`; `eidos-lint` los cuenta (`class-hooks: 2`) y el centinela no los
ve, porque filtra nodos por atributo.
- **El foco del trigger de `gradient-picker` es opaco** (`--color-primary-solid`)
mientras el resto del catálogo lleva la mezcla suave del sistema
(`--focus-ring-color`, 52 %). Quedó sin tocar porque alinearlo mueve píxel —
y de hecho quedó sin token, porque la regla entera está muerta bajo popover.
- **La demo del bloque F2-A ya enseña los tokens** (`TokensPanel`), pero los
~155 componentes sin contrato siguen sin superficie donde verlos hasta que se
tokenicen.
**Deps**: ninguna. Son mejoras del instrumental del eje, ejecutables cuando
estorben.

Powered by TurnKey Linux.