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/process/REVIEW-theming-2026-08-23.md

189 lines
19 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.

# REVIEW — theming «theme-reach»: lo ejecutado tras la revisión adversarial del 22 (2026-08-23)
**Alcance**: los **26 commits** posteriores a `cd6a9f4e3` (la revisión §7.7 del
bloque de catorce, 2026-08-22), que no han pasado ningún análisis posterior:
`f25f5bb1d` (drawer, rojos) · `27dc6dba3` (metrics + color-picker, rojos) · los 17
de la mañana del 23 (menubar · field · onion-menu · button · callout · empty-state
· dropdown-menu + context-menu · checkbox · image · anchor-nav · banner · surface ·
date-range-field · time-range-field · tooltip · cola pequeña de seis · audio-player)
· los 7 de la tarde (navigation-menu · waveform · color-field · background ·
s-text-virtual-list · badge · cropper). **33 componentes.**
**Qué se ha comprobado aquí, con medición propia** (instrumental en
`scripts/__rv-*.mjs`, un solo uso): gramática de nombres (`--names`) · pureza del
`generated/base.css` commit a commit · equivalencia ESTÁTICA «valor viejo = valor
del contrato» par a par en los 26 commits · `npm run check` atribuido por fichero ·
`prettier --check` en los ficheros tocados (y si la no conformidad era previa) ·
`component:audit` completo · `eidos-lint-all` · sonda ×2 de los siete de la tarde
contra su línea base, con el servidor reiniciado · barrido del centinela sobre
TODOS los componentes con ledger · re-medición dirigida de las adjudicaciones
dudosas · presencia de README «Talla y tema», tab `Tokens` y veredicto §5.
**Qué NO es esto**: la revisión §7.7 completa. Falta la re-medición del «default
idéntico» contra una BASE (worktree en `cd6a9f4e3`) para los 26 de la mañana, el
«píxel hacia arriba» en los hover tocados y el registro de doble animación. Es el
punto P5 del plan.
---
## 1. Errores reales (código o ledger) — 5
| # | dónde | qué | prueba |
| --- | --- | --- | --- |
| E1 | `badge.min-block-size-{xs,sm,md,lg}` + `min-block-size` (`271fcd4df`) | **Nombre fuera de recipe-contract §1**: «Control height per size → `control-height-{size}` (o `{part}-height-{size}`) — inventing a third name per component». El catálogo ya lo dice: `navigation-menu.trigger-height-{k}` se CONSUME como `min-block-size`, `accordion.trigger-min-height-{k}`, `field.control-height-{k}`. R-5.3 no lo caza (guarda tinta y modificador, no el vocabulario dimensional). | `base.ts`: 41 claves `-height-`, 0 precedentes de `min-block-size-{k}`; §1 fila 40 |
| E2 | ledger `background.parallax-travel` (`9bdc5a5d5`) | **Adjudicación MAL CLASIFICADA**: dice «structural — only enters via the scroll-linked keyframes; the measured stage has no scroll timeline». Medido hoy: el escenario SÍ tiene `animation-timeline: view()`; forzando `data-parallax` + speed 1, el `translate` sigue al scroll (−9,7 → 14,6 px) y **el token alcanza** (14,6 → 60,5 px al mismo scroll con `--background-parallax-travel: 400px`). Lee muerto en el guard porque (a) la demo arranca con speed 0 (sin `data-parallax`) y (b) **el guard no fotografía `translate`/`transform`** (tampoco `mask-image`). | `scripts/__bg-parallax.mjs` |
| E3 | README de `cropper` (`f03ee5af4`) | Dice «hueco de composición (el botón de zoom debería componer `IconButton`), **anotado**» — y no está anotado en ningún sitio: ni fila en `## Gaps`, ni next-features §13. | `grep IconButton` sólo en la prosa |
| E4 | `scripts/theming-sentinel-exceptions.ts` | Mis entradas de `color-field` / `background` / `badge` añaden **4 hunks de prettier** (63 preexistentes → 67). Protocolo §7.5.18. | `prettier --check` base vs HEAD |
| E5 | `float-panel` (ledger) + handoff | **12 tokens públicos muertos SIN adjudicar** — `bg`, `border`, `border-width`, `shadow`, `active-shadow`, `font-family`, `line-height`, `resize-size`, `button-size`, `accent`, `transition-duration`, `transition-ease` — y el guard R-5.4 **falla** en él hoy. No es regresión: el commit `b4510fbf8` (08-22) ya lo dejó escrito («lo rojo que queda son 12 tokens anteriores; seis son el plano de profundidad, §12.9») y nadie los midió después. **La afirmación del handoff «desde el 2026-08-23 NO queda ningún rojo del bloque viejo» es FALSA**: `drawer`, `metrics` y `color-picker` se adjudicaron; `float-panel` no. | barrido del centinela, repetido a solas: 17/40, 12 sin adjudicar; ledger idéntico al del 22; ningún commit tocó el componente desde entonces |
## 2. Desviaciones del protocolo — 5
| # | quién | qué | alcance |
| --- | --- | --- | --- |
| D1 | sesión de la mañana | **Ni README «Talla y tema» ni tab `Tokens` en la demo** en NINGUNO de sus commits de tokenización (PLAN §5 F2 «README de eidos con la tabla de tokens»; handoff, protocolo pasos 8 y 9). `git show --stat`: sólo `docs/audit/theming/`, CSS, `base.ts`, ledger. | **20 componentes**: menubar · field · onion-menu · button · callout · empty-state · dropdown-menu · context-menu · checkbox · image · anchor-nav · banner · date-range-field · time-range-field · tooltip · section · sticky · button-group · qr-code · toggle-group · split-button (+ `surface` y `audio-player`, sin demo: sólo README) |
| D2 | yo (tarde) | `waveform` y `cropper`: la tabla de tokens fue a una sección existente (`## Tokens`, `## Recipe tokens`) y no a «Talla y tema» (molde `navigation-menu`). | 2 |
| D3 | las dos sesiones | **Sin capturas 2× antes/después** (§7.2.6, §7.4.13) en ningún commit; **sin «píxel hacia arriba»** (§7.4.12) — relevante sólo donde se tocaron reglas `:hover` (mañana: dropdown/context-menu `hover-item-*`, anchor-nav `hover-link-fg`, menubar; tarde: ninguno). | 33 / los de hover |
| D4 | yo (tarde) | `npm run check` sólo en `navigation-menu`; `prettier --check` en ninguno; guard re-verificado tras cada cambio sobre 3–5 componentes, no sobre el ledger entero. **Subsanado en esta revisión**: check 0 errores en mis ficheros (los 72 globales son ajenos y preexistentes); prettier: los 11 ficheros ya no pasaban ANTES (sólo E4 es mío); barrido completo del ledger abajo. | 6 |
| D5 | las dos sesiones | **Sin revisión adversarial §7.7** de ningún bloque desde el 22: 26 commits, 33 componentes. | todo el alcance |
## 3. Refutado (se comprobó, no hay hallazgo)
- **Gramática**: `--names` → DESVIADAS 0 (3.931 conformes, 447 rol-slot canónicas).
- **Pureza del generado**: 26 commits, cada línea ± de `generated/base.css` es del componente del commit.
- **«El default es idéntico», estáticamente**: los 26 commits, par a par `prop: viejo → prop: var(--c-key)`: cada valor del contrato ES el viejo — o el respaldo que se quitó (`var(--x, V)` → contrato `V`), o el alias de bundle verificado en el generado (`--size-{k}-control-height: var(--control-height-{k})`, `--size-{k}-font-size: var(--font-size-{k})`, `--size-{k}-font-line-height: var(--font-line-height-{k})`). Los tres que parecían cambiar valor eran artefactos del emparejamiento: `anchor-nav` (hover → `hover-link-fg` content-primary; active → `active-link-fg` primary-text, correcto), `dropdown-menu.separator-bg` (el respaldo `--color-border-subtle` era código MUERTO: la clave ya valía `--color-neutral-separator`), `menubar` (`--floating-gap` por talla: `space-1 * 0.5` → `padding-sm = --space-0-5`, misma aritmética; el `font-size` del panel por talla).
- **Sonda ×2 de los siete, servidor reiniciado**: 0 diffs en las 14 corridas salvo `background` corrida 1 — **2 diffs de `inlineSize` del ESCENARIO (870 ↔ 1.350 px)**, el ancho del layout de la demo, no el componente; corrida 2 limpia. Ruido de instrumento, a §13.
- **`component:audit`**: 162 PASS · 4 NEEDS-WORK (`badge` R-1.5 PREEXISTENTE y ya anotado; `gradient-picker`, `mockup`, `motion` ajenos). **`eidos-lint-all`**: 0 invalid, 0 class-hooks.
- **Ledger**: 196 adjudicaciones en alcance; 26 sin medida explícita en su propia línea, de las que 25 son continuaciones «same as…» de una hermana medida y 1 es E2.
- **Barrido del centinela sobre todo el ledger** (59 componentes, tras los cambios del guard de hoy: `extraNodes`, `openBy: 'hover'`, `prepareWith`): **0 STALE, 0 errores de corrida, y un único componente con muertos sin adjudicar — `float-panel` (E5), que ya lo estaba el 22.** Los cambios del guard no han roto nada del ledger. Detalle en §5.
- Mis adjudicaciones de `background.fade-*` («the guard does not snapshot mask-image») son **ciertas**: `maskImage` no está en `PROPS`.
- El barrido de variantes de `badge` (`soft/solid/outline/ghost`) casa con `EIDOS_VARIANTS.chip`.
- `TokensPanel` acepta `stage` opcional (s-text-virtual-list lo omite): sin error de tipos.
## 4. Plan de solución — **FIRMADO Y EJECUTADO 2026-08-23**
| P | estado | commit |
| --- | --- | --- |
| P8 | ✅ `float-panel`: los 12 medidos y adjudicados; guard en verde; frase del handoff corregida | `233ef989b` |
| P2 | ✅ `background.parallax-travel` reescrito; hueco `translate`/`transform` en §13 | `233ef989b` |
| P3 | ✅ `cropper` §Gaps real; «Talla y tema» en cropper y waveform; ledger sin hunks nuevos | `233ef989b` |
| P1 | ✅ `badge.min-block-size-{k}` → `min-height-{k}`; R-5.3 sin vocabulario dimensional, a §13 | `bfe7727b0` |
| P4 | ✅ 22 READMEs «Talla y tema» derivados del contrato + 21 pestañas `Tokens`, verificadas en el navegador | `e522e04e6` |
| P6 | ✅ §13: flicker del escenario de background · `audio-player` sin README · los tres huecos de `PROPS` | `233ef989b` + éste |
| P7 | ✅ PLAN §7: las capturas se exigen DESDE el siguiente componente; píxel-arriba obligatorio si se toca `:hover` | éste |
| P5 | ✅ revisión adversarial §7.7: 5 hipótesis, 5 refutadas, 0 hallazgos nuevos (§6) | éste |
### El plan original
| P | qué | cómo | toca píxel | firma |
| --- | --- | --- | --- | --- |
| **P1** | E1 — renombrar `badge.min-block-size-{xs,sm,md,lg}` → `height-{xs,sm,md,lg}` y el resuelto `min-block-size` → `height` | un commit: `base.ts` + `badge.css` + regenerar + sonda (diff 0 por construcción) + guard (29/71, mismas adjudicaciones) + README + ficha + PLAN §8 («nombre corregido»). El tab `Tokens` sigue en 71. | no | **sí** — renombra una clave pública recién acuñada; el nombre canónico es de §1, pero la decisión de renombrar hoy es tuya |
| **P2** | E2 — reescribir la adjudicación de `background.parallax-travel` («parallax off in the demo (speed 0); forced data-parallax + speed 1 → reaches through the scroll-linked translate (14.6 → 60.5 px at the same scroll); the guard does not snapshot translate») y registrar en §13 el hueco `translate`/`transform` del guard (ya hay precedente en `drawer.handle-active-scale`) | ledger + next-features; un commit docs | no | no |
| **P3** | E3 + D2 + E4 — `cropper` README: fila en `## Gaps` («el botón de zoom compone cromo propio; debería componer `IconButton` — y por eso su hover queda fuera de la capa de estado»); `waveform` / `cropper`: la sección pasa a llamarse «Talla y tema»; ledger: partir mis 4 entradas largas como prettier las quiere (a mano, sin `--write` sobre el fichero entero: tiene 63 hunks ajenos) | un commit docs | no | no |
| **P4** | D1 — los **20 componentes de la mañana**: README «Talla y tema» (tabla de claves públicas + lo adjudicado, molde `navigation-menu`) y tab `Tokens` en la demo (`<TokensPanel component="x" stage={stageRef ?? undefined} />` + su botón con el conteo); `surface` y `audio-player` sólo README (sin demo). | mecánico, sin píxel. Propuesta: **un commit por componente** (el protocolo es «un componente = un commit» y el registro §8 lo referencia así), o un único commit de lote si prefieres cerrar rápido | no | **sí** — por el alcance (20) y por la forma (por componente vs lote) |
| **P5** | D5 — la **revisión adversarial §7.7** de los 26 commits: worktree en `cd6a9f4e3` con `server.fs.allow` (trampa de la junction), comprobar que un componente MONTA antes de comparar, sonda base vs HEAD por componente (33), «píxel hacia arriba» en los que tocaron `:hover` (dropdown-menu, context-menu, anchor-nav, menubar), registro de `animationstart/end` donde se movió un sello (ninguno de los 26, a comprobar), centinela rehecho. Lo estático de esta revisión (§3) entra como hipótesis ya refutadas. | una sesión | no | **sí** — es el guard de bloque del PLAN; decide si antes o después de seguir la cola |
| **P6** | instrumento — registrar en §13: el flicker de `inlineSize` del escenario de `background` (870/1.350) · `translate`/`transform`/`mask-image` fuera de `PROPS` del guard (tres tokens vivos leen muertos: `parallax-travel`, `fade-size`, `fade-at`; y `drawer.handle-active-scale`). Si se añaden a `PROPS`: **re-verificar los ~35 con ledger** antes de commitear (el barrido de §5 es la base de comparación). | docs (+ opcional guard) | no | para tocar `PROPS`, sí |
| **P7** | D3 — capturas 2× antes/después y «píxel arriba» no se recuperan retroactivamente para 33 componentes: se hacen dentro de P5 para los que tocaron hover; para el resto, el diff de computed 0 + el centinela son el artefacto. Anotar en PLAN §7 que las capturas se exigen DESDE el siguiente componente. | docs | no | no |
| **P8** | E5 — `float-panel`: medir los 12 uno a uno con el panel abierto y adjudicar o retirar. Hipótesis ya escrita por el propio commit del 22: los seis de superficie/tipografía son el plano `overlay` (misma clase que `tooltip` / `popover` → adjudicación «SUPERSEDED by the overlay plane», como la de tooltip); `active-shadow` sólo mientras se arrastra; `accent` alimenta un privado que pinta en foco/arrastre (forzar estado); `resize-size` / `button-size` deberían alcanzar (si no, están mal cableados); `transition-*` la ley conocida (pasada sin congelar). Y corregir la frase del handoff. | un commit (ledger + handoff + ficha §5 de float-panel) | no | no — es adjudicar lo medido; si alguno resulta MUERTO de verdad, su retirada sí se presenta |
**Orden propuesto**: **P8 (el guard está en rojo hoy)** → P2 + P3 (docs, diez minutos) → P1 (una clave) → P4 (los 20, mecánico) → P6 → P5 (la revisión de verdad, una sesión). Nada de esto mueve un píxel.
## 6. P5 — la revisión adversarial §7.7, ejecutada (2026-08-23)
**Molde Sidebar: intentar REFUTAR cada afirmación con medición propia, no leer
la del commit.** Base = worktree en `cd6a9f4e3` (`G:/tmp/rv-base`), dev server
propio en 5301, `node_modules` por junction y `server.fs.allow` con las dos
rutas — la trampa que el handoff registra: sin eso Vite responde 403 a `/@fs/…`
y la página NO hidrata, y se compara contra una base muerta. **Comprobado ANTES
de comparar nada**: los diez primeros componentes montan e hidratan en la base
(10, 4, 10, 2, 57, 17, 6, 25, 2 y 1 nodos).
### H1 — «el default es idéntico»: **REFUTADA la duda, 33 de 33**
Sonda del HEAD (la misma en los dos lados, para no comparar instrumentos)
contra base y contra HEAD, componente a componente:
- **31 con 0 diffs**, de 192 a 7.360 valores por componente y de 7 a 8 estados.
Total comparado: **~48.000 valores computados**.
- `surface` daba 0 valores por una URL mía equivocada; en su ruta real
(`/temas/gradientes`, la que su propio override declara) → **0 diffs sobre 896
valores, 4 nodos**.
- `image` (1 diff) y `audio-player` (7 diffs + 1 nodo ausente) son **ruido del
instrumento, probado**: corriendo la sonda DOS VECES contra el MISMO código,
`image` reproduce su diff y `audio-player` da **once** — más que la
comparación base↔HEAD. Las dos propiedades implicadas son estado vivo: la
`opacity` de un `<img>` con animación de entrada (la sonda congela
`transition`, **nunca `animation`** — ley conocida) y el `inline-size` del
rango *buffered* de un audio, que depende de lo que lleve cargado.
### H2 — «el velo cae donde debe»: **verde en los cuatro que tocaron `:hover`**
Píxel hacia arriba (`elementsFromPoint` en el centro del control, pila de
ancestros con `backgroundImage`/`backgroundColor`):
- `dropdown-menu` y `context-menu`: el velo está en `[data-…-item]`, **radio
4px** — el nodo CON forma; el `list-surface` de debajo (radio 6px) limpio.
- `menubar`: la barra pinta el abierto en el propio `<button>` (radio 2px) sin
derramar al `[data-menubar]`; la fila del panel, el velo en su item (4px).
- `anchor-nav`: **sin velo en ninguna capa**, y es correcto — su hover es sólo
tinta (`hover-link-fg`), no capa de estado. Medido sobre un enlace NO activo,
porque el primero que casa el selector lleva `data-active` y pinta otra cosa.
_(El `data-uix-stage-area` sale con velo en varias pilas: es el fondo a cuadros
del harness, y las demos están fuera del eje.)_
### H3 — «no hay doble animación»: **no aplica, y se comprobó**
Ninguno de los 26 commits toca `animation`, `@keyframes`, `data-event` ni
`motion-*` en `src/uix/eidos/components/`. No hay sello movido que pueda
duplicarse.
### H4 — «cada token alcanza»: **rehecho, y destapó E5**
El barrido del centinela sobre los 59 con ledger (§5): 0 STALE, 0 errores, y un
único componente en rojo — `float-panel`, ya arreglado (P8).
### H5 — «el contrato no tiene duplicados ni huérfanos»: **limpio**
144 bloques en `base.ts`, cero duplicados y cero claves repetidas dentro de un
bloque. El test oficial de huérfanos (`recipe-css-contract.test.ts`) pasa.
⚠ **Y aquí mintió mi propio instrumento**: un guard estricto de un solo uso
reportó **185 huérfanos** — los pasos de escala por talla y todas las claves de
tono. Falso: excluía `generated/`, que es exactamente donde el TSC emite el
nombre resuelto y donde el forward de paleta lee los tonos. Un guard de
huérfanos que no mira el CSS GENERADO ve huérfano todo lo que el generador
resuelve.
### Veredicto de P5
**5 hipótesis · 5 refutadas · 0 hallazgos nuevos.** Los dos únicos diffs de la
comparación son ruido reproducible del instrumento, no regresiones, y quedan
registrados en §13. Los hallazgos reales de esta revisión estaban en el análisis
ESTÁTICO (E1–E5) y ya están arreglados.
## 5. Barrido del centinela (todo el ledger, tras los cambios del guard de hoy)
`rv-dyn.sh`, 59 componentes con ledger, uno tras otro contra el mismo dev server
(5180), 2026-08-23 por la tarde:
- **0 excepciones STALE** en los 59 (ninguna adjudicación ha empezado a moverse).
- **0 corridas con error** (ninguna ruta 404 ni timeout: los `urls` de
picker-shell / audio-player / surface resuelven).
- **1 componente con muertos sin adjudicar: `float-panel`, 17/40, 12 sin
adjudicar** (E5). Repetido a solas: idéntico, así que no es el falso exit por
lote del que avisa el handoff.
- Los cinco que re-verifiqué a mano durante la tarde (command 51/57 · table 42/45
· tooltip 15/23 · navigation-menu 43/44 · waveform 11/11) dan lo mismo en el
barrido: los cambios del guard son inocuos fuera de sus overrides.
- Sonda ×2 de los siete de la tarde contra su línea base, en la misma corrida:
**0 diffs en las 14**, salvo `background` corrida 1 (2 diffs de `inlineSize`
del ESCENARIO, 870 ↔ 1.350 px; corrida 2 limpia) — ruido del layout de la
demo, a §13 con P6.
Bisección del guard sobre `float-panel` (`scripts/__sentinel-<sha>.ts`, cada
versión de `theming-sentinel.ts` desde `cd6a9f4e3` contra el ledger de hoy,
idéntico para este componente): **la versión del 22 ya da 17/40 con los MISMOS
12 sin adjudicar**, y cada versión intermedia también. No hay regresión del
guard: es un rojo del 22 que quedó sin medir y que el handoff dio por cerrado.

Powered by TurnKey Linux.