|
|
# CONTINUE — eje Theming «theme-reach» — **CERRADO 2026-08-25**
|
|
|
|
|
|
## EMPIEZA AQUÍ
|
|
|
|
|
|
**EL EJE ESTÁ CERRADO** (gate de F3 rediseñado y en verde el 2026-08-25;
|
|
|
sección §«EL CIERRE, EJECUTADO» abajo). Lo que vigila el estado desde hoy no
|
|
|
es este documento sino los guards: `theming-reach-floor.test.ts` (newDebt=0 ·
|
|
|
STALE=0 · reach ≥ 69 % · ≥45 al 100 %), `component-audit` R-5.1/5.2/5.3 en
|
|
|
`error`, y el centinela R-5.4. La deuda restante vive NOMBRADA clave a clave
|
|
|
en `scripts/theming-census-debt.ts` (1088 entradas que sólo pueden menguar).
|
|
|
Trabajo nuevo de theming se abre como entrada nueva de §13/next-features, no
|
|
|
heredando de aquí. Quedan DOS firmas pendientes del autor, registradas en
|
|
|
§13: los 318 privados no-derivados sin ratchet por clave, y el idioma
|
|
|
`var(--{c}-x, fallback)` sin contrato (`mockup`/`text-scramble`).
|
|
|
|
|
|
**El eje ya no tiene cola.** Los 16 componentes que nunca habían pasado están
|
|
|
cerrados o adjudicados, la deuda de artefactos está saldada, y **§12.9 y la
|
|
|
firma B′ quedaron FIRMADAS Y EJECUTADAS** — las dos decisiones más caras
|
|
|
pendientes. Global **69 %** (68 % antes de la clase `structural`), **45
|
|
|
componentes al 100 %**.
|
|
|
|
|
|
## HANDOFF 2026-08-25 (noche) — POR AQUÍ MAÑANA
|
|
|
|
|
|
**Las CINCO firmas del eje están EJECUTADAS y pusheadas** (`2daa683fa`
|
|
|
file-upload · `df3a4d054` form/compuesto · `2ce43db56` tags-input aria ·
|
|
|
`1f8ce293b` avatar · `466b24f34` chip/suelo §55). Después cayeron los
|
|
|
expedientes de §13: `d5a27b87e` (árbol ARIA de tags-input, cierra F-1) ·
|
|
|
`3bf7930ba` (el velo no muere por un atajo + pin de chronos, §56) ·
|
|
|
`318aac207` (la talla de form LLEGA, doctrina anchura-vs-densidad).
|
|
|
|
|
|
### Lo PRIMERO mañana: dos firmas de INSTRUMENTO, en este orden
|
|
|
|
|
|
1. ~~**«La mitad gratis»**~~ — **✅ FIRMADA Y EJECUTADA 2026-08-25**
|
|
|
(`047464389`; ver §«FIRMA EJECUTADA — la mitad gratis» justo abajo).
|
|
|
Expediente original: scratchpad de la sesión
|
|
|
`6314e22b…/scratchpad/bprime/exped/va/informe.md` (1.019 líneas).
|
|
|
2. ~~**La GRANDE: cuatro cegueras + TRES BARRIDOS escalonados.**~~ —
|
|
|
**✅ FIRMADA Y EJECUTADA 2026-08-25** (`6392d6003` S1 · `b4dd5a906` S2 ·
|
|
|
`b9cef9a43` S3; ver §«FIRMA EJECUTADA — la GRANDE» abajo). Se ejecutó
|
|
|
exactamente con el plan de VA: tres barridos escalonados, sin fusionar S2 y
|
|
|
S3, y la atribución quedó limpia.
|
|
|
|
|
|
### FIRMA EJECUTADA (2026-08-25) — «la mitad gratis»: cegueras 4 y 5, coste de ledger CERO
|
|
|
|
|
|
**Qué se firmó** (`047464389`): las dos piezas del expediente VA que NO
|
|
|
compartían el coste caro — el codemod ciego a la IIFE con sus dos hermanos, y
|
|
|
los cinco huecos de la sonda más el sexto propio (el pase de FOCO prometido e
|
|
|
inexistente). Tres ficheros, **ni una entrada del ledger**. Ejecutada por
|
|
|
cuatro agentes (tres constructores + uno ADVERSARIAL con mandato de refutar),
|
|
|
con bases capturadas ANTES de editar.
|
|
|
|
|
|
**Los números**: centinela `label` 1/2 y `switch` 27/52 **byte a byte
|
|
|
idénticos** a las bases pre-firma; sonda de `card` **0 diffs en sus 7 bloques
|
|
|
viejos**; `editable` estrena bloque `open` (25 filas, 6 con `data-editing`) y
|
|
|
dos corridas sobre código idéntico dan **0 diffs en TODOS los bloques**;
|
|
|
`menubar` abre por la entrada del centinela (6 nodos → 7, con el panel) y
|
|
|
`chat-message` 24 filas × 2 corridas = 0 diffs; codemod 145/145 bloques,
|
|
|
avatar `depth 3` con **97** claves (86 públicas + 11 privadas), laboratorio
|
|
|
sobre copias (duplicado inyectado DETECTADO, renombrado = 1 línea); importar
|
|
|
el centinela: 0,85 s sin navegador.
|
|
|
|
|
|
**Las decisiones que deja escritas**:
|
|
|
|
|
|
- `COMPONENT_OVERRIDES` es **UNA tabla**: la sonda la importa y `OPEN_TRIGGER`
|
|
|
se poda de sus copias literales. La guarda de entrypoint lleva
|
|
|
`realpathSync` — hallazgo del adversarial: sin el realpath muere a través de
|
|
|
un junction (exit 0 sin inspeccionar nada), y este repo usa worktrees con
|
|
|
junctions.
|
|
|
- La vía de carga del codemod **SE QUEDA en tsx**: «el censo corre con node
|
|
|
pelado» era FALSO (todo `src/uix/morfo` importa sin extensión).
|
|
|
- `prepareWith` en la sonda sólo corre sin fila en `DEMO_VARIANTS` (re-clicar
|
|
|
APAGA los checkboxes que `prepare()` ya encendió) — y eso deja a la vista la
|
|
|
deuda de `search-field` (§13).
|
|
|
- El no-determinismo de `chat-message` quedó ACOTADO al bloque `rest` de la
|
|
|
sonda (13 vs 16 nodos, chips sin cuajar al medir) — dato para la GRANDE.
|
|
|
|
|
|
**Lo que quedó fuera, con su registro en §13**: el barrido de variantes de la
|
|
|
sonda (ensanche diferido por el propio expediente) · el clear-trigger de
|
|
|
`search-field` en el pase `open` · la asimetría de escenario de los seis con
|
|
|
`prepareWith` sin fila · el cortocircuito `alreadyOpen` que la sonda no tiene ·
|
|
|
y **TRES lectores independientes** de la estructura de `base.ts` (codemod,
|
|
|
censo, centinela — la próxima forma nueva se enseña tres veces). El `catch`
|
|
|
del `prepareWith` del CENTINELA sigue MUDO **a propósito**: es la ceguera 6,
|
|
|
S1 de la GRANDE.
|
|
|
|
|
|
### FIRMA EJECUTADA (2026-08-25) — «la GRANDE»: el guard deja de estar ciego, en tres barridos
|
|
|
|
|
|
**Qué se firmó** (`6392d6003` · `b4dd5a906` · `b9cef9a43`): las cegueras
|
|
|
6+1+3+2 del expediente VA, UNA firma, TRES barridos del ledger ENTERO (91
|
|
|
componentes cada uno), ejecutada con el mismo esquema de agentes que «la mitad
|
|
|
gratis» (tres constructores en serie + adversarial con mandato de refutar:
|
|
|
**12/12 claims confirmados**).
|
|
|
|
|
|
- **S1** — el `prepareWith` GRITA (lo que cae en su catch es un control que
|
|
|
estaba y falló — la fuente de las muertes fantasma) y el STALE ve los
|
|
|
PATRONES (`reasonFor`, mensaje que distingue «retira la exacta» de
|
|
|
«ESTRECHA el patrón»). Barrido: 91/91 verdes, 40,8 min, 0 avisos. Cosecha:
|
|
|
los dos patrones `PLANE_SUPERSEDED` de `toast` (18 claves), rancios desde la
|
|
|
noche de §12.9, RETIRADOS con 3/3 de reproducción.
|
|
|
- **S2** — el chooser tipa la sonda por el VALOR por defecto leído de
|
|
|
`base.ts`, no por el nombre (357 claves cambian de sonda; 320 de la clase A
|
|
|
«vivo por accidente» IACVT). MONÓTONO medido: 91/91, sólo `avatar` +1 y
|
|
|
`stepper` +1, sus dos exactas retiradas. Ni `%` ni enteros se clasifican
|
|
|
(tipar el `0` habría matado en falso 7 claves vivas).
|
|
|
- **S3** — tono+estado: tono en el pase de hover · tono MEDIAL `(^|-)` (las
|
|
|
16 de `tag-group`) · hover para claves de tono muertas (las 21 de
|
|
|
`file-upload`) · seis ejes de estado como DATO, valores del morfo/receta/DOM
|
|
|
real. Barrido: 91/91, 43,8 min, exactamente los 9 previstos, **+140 claves
|
|
|
(catálogo 2776 → 2918, 78 % → 82 % de claves vivas)**. **130/132
|
|
|
`TONE_UNREACHED` reviven; las 2 que no eran `PALETTE_FLOOR`** (el tono HOST
|
|
|
por defecto — test de dos caras en checkbox y radio-group, firma idéntica en
|
|
|
los ocho componentes).
|
|
|
|
|
|
**El ledger después**: 10 patrones retirados + 2 estrechados + 7 exactas
|
|
|
retiradas + la constante `TONE_UNREACHED` RETIRADA (la muerte que su docstring
|
|
|
pedía). Tier de patrones **28 → 16, 15 de los 16 son el único hecho
|
|
|
`PALETTE_FLOOR`**, y el adversarial verificó que los 16 cubren SOLO claves
|
|
|
muertas — cero zombis — y que ninguna clave muerta quedó sin razón (659
|
|
|
muertas, 0 sin adjudicar).
|
|
|
|
|
|
**Dos correcciones al expediente, reproducidas dos veces antes de tocar**: las
|
|
|
`-text` de `tags-input` SÍ reviven (la causa del arquetipo sólo tapa el ítem
|
|
|
RESALTADO; la escena no tiene ninguno, y el token pinta además dos nodos
|
|
|
hermanos fuera de esa regla) · `tag-group.hover-item-fg` la callaba su
|
|
|
`data-state='selected'` nativo — el nodo es un `<a data-archetype='trigger'>`
|
|
|
que ninguna regla de arquetipo toca.
|
|
|
|
|
|
**Deuda nueva registrada en §13** (adversarial, ninguna bloquea): la asimetría
|
|
|
del estampado (`data-color` en TODOS los nodos vs sólo el proveedor en
|
|
|
producción — medido que NO es la causa de ninguna revivida) · el ternario
|
|
|
falsy de la restauración de atributos (un `attr=""` se borra en vez de
|
|
|
restaurarse; hoy inocuo) · `checkbox.stroke-ease` con sonda de color (única
|
|
|
de las 51 de easing) · el residuo del recorte del hover
|
|
|
(`button.palette-element`, escrito en su propia razón).
|
|
|
|
|
|
### EL CIERRE, EJECUTADO (2026-08-25) — deuda B + clase `structural` + R-5 a `error` con LEDGER
|
|
|
|
|
|
**✅ EJECUTADO** con el mismo esquema de agentes (tres constructores + un
|
|
|
adversarial que confirmó 11 claims y refutó dos números de prosa). Cinco
|
|
|
commits: `2c61946fb` (clase `structural`) · `ef47f3447` (deuda B) ·
|
|
|
`69d69d43c` (el ledger de deuda) · `1ba518fcc` (correcciones del adversarial).
|
|
|
|
|
|
- **Deuda B saldada**: `proof-of-human` (20 claves derivadas) ·
|
|
|
`audio-player` (README nuevo; es un skin sobre media-player que consume sus
|
|
|
61 claves y añade 8; sin demo propia a propósito) · `palabras` (sección
|
|
|
honesta SIN tabla: sin contrato en `base.ts`, y sus 117 nombres
|
|
|
`--palabras-*` son la proyección del `scheme-style` del documento — canal
|
|
|
de VALOR, otro eje; la clasificación del censo sobre él queda EN CUESTIÓN,
|
|
|
§13).
|
|
|
- **Clase `structural`**: los cinco 0 %-por-naturaleza (`aspect-ratio` ·
|
|
|
`text-blur` · `cascade` · `motion` · `date-picker`) salen del denominador
|
|
|
con su razón EN el artefacto (forma `LAYER_VOCABULARY`). Reach 68 → 69 %,
|
|
|
no-contract 23 → 18, el gate deja de ser inalcanzable por construcción.
|
|
|
- **R-5 a `error` con LEDGER DE DEUDA — la firma que rediseñó F3**: la deuda
|
|
|
real (1088 claves: 763 global + 325 literal, carriles WIP DENTRO) se
|
|
|
registra UNA vez por clave en `scripts/theming-census-debt.ts` — deuda
|
|
|
registrada, NO excepciones; la válvula sigue intacta y nunca ciega el
|
|
|
ratchet. R-5.1/5.2 a `error` contra el ledger (R-5.3 ya lo estaba): deuda
|
|
|
nueva = rojo NOMBRADO, entrada rancia = STALE hasta borrarla. Los techos
|
|
|
burdos del suelo RETIRADOS (el ratchet es por clave); `atHundred` corrige
|
|
|
su criterio (`public > 0`, 14 → 45). El gate de F3 queda redefinido
|
|
|
honesto: **«censo 100 % ADJUDICADO»** — y está EN VERDE.
|
|
|
- **Pendiente de TU firma, nombrado en §13 y en la cabecera del ledger**: los
|
|
|
**318 privados no-derivados** (deuda por la letra de R-5.1, sin ratchet por
|
|
|
clave — sólo los cubre el `reachPct` grueso) · el idioma
|
|
|
**`var(--{c}-x, fallback)` sin contrato** (`mockup` ×11, `text-scramble`
|
|
|
×2 — otro guard sanciona el idioma, pero no alcanza a `applyTheme` ni al
|
|
|
centinela). · Deuda menor registrada: las fichas de `docs/audit/theming/`
|
|
|
esperan un `--report` supervisado post-`structural` (tarea aparte).
|
|
|
|
|
|
### FUERA del carril de theming (registrados HOY, no se ejecutan desde aquí)
|
|
|
|
|
|
- **E1 — los botones del array de form COMPONEN el Button** (clase A-112):
|
|
|
expediente completo de VC en `exped/vc/` + la corrección de E-talla: E2
|
|
|
ahorró el CONTEXTO pero no la LECTURA — E1 debe pasar `size` al Button que
|
|
|
inyecte o es la regresión medida (26→36 px en xs). Y las partes son MUDAS
|
|
|
(morfo sin evento; verbos canon: `commit-set-add`/`commit-remove`).
|
|
|
- Lo abierto por el ARIA: `tag-group` filas SIN celdas (el «precedente»
|
|
|
refutado midiendo) · `search-field` F-1 · la regla del censo de citas APG.
|
|
|
- El párrafo anchura-vs-densidad querría vivir TAMBIÉN en `reference.md`
|
|
|
junto a la norma tapada (dicho por E-talla, fuera de su alcance).
|
|
|
|
|
|
### Las leyes que dejó el día (sesión 2)
|
|
|
|
|
|
- **Una interrupción del autor MATA a los agentes en vuelo** — informe.md a
|
|
|
disco INCREMENTAL siempre; el disco sobrevive (V1 se recuperó íntegro).
|
|
|
- **El supervisor MIRA las capturas antes de cada commit** (regla del autor).
|
|
|
- **Las demos del sistema NO entran** ni como prueba central de una firma
|
|
|
(reafirmada sobre la captura del velo; la prueba citable es el barrido de
|
|
|
las 14 identidades del catálogo).
|
|
|
- **F5 compartidas se RETIENEN y liberan EN SERIE** cuando varios ejecutores
|
|
|
comparten `next-features`/`CONTINUE` — tres ejecutores hoy, cero pisadas.
|
|
|
- La sonda estándar ganó DOS mentiras registradas (se pisa el `data-size`
|
|
|
forzado sobre nodos compuestos · los `clamp()` fluidos no comparan sin
|
|
|
declarar viewport) — están en §«Lo que el instrumento aprendió».
|
|
|
|
|
|
Lo que queda de firma vieja NO cambia: la lista «Lo que espera TU FIRMA» de
|
|
|
más abajo quedó VACÍA el 2026-08-25 y las entradas EJECUTADAS de hoy están
|
|
|
intercaladas tras esta sección.
|
|
|
|
|
|
### FIRMA EJECUTADA (2026-08-25) — el velo del sistema no muere por un ATAJO
|
|
|
|
|
|
**Qué se firmó** (changelog §56, reverso de §55 el mismo día): al bajar el sobre
|
|
|
de trigger de `popover.css` al suelo, §55 lo dejó a **(0,0,0) — el mismo peldaño
|
|
|
que `archetypes.css`**, que es quien pinta el velo de estado del sistema. Y el
|
|
|
suelo declaraba su superficie con el ATAJO `background:`, que expande a
|
|
|
`background-image: none` — **la propiedad exacta donde vive ese velo**. Resultado:
|
|
|
el velo de hover de todo trigger desnudo dependía de qué hoja cayera después.
|
|
|
No sólo por la regla de hover: el `:where()` deja también la de REPOSO empatada
|
|
|
con la de hover del arquetipo, y ésa sola bastaba. La corrección son DOS
|
|
|
PALABRAS — `background-color:` en `popover.css:60` y `:75`.
|
|
|
|
|
|
**Los números**: **0 px** en el barrido de las **14 identidades del catálogo**
|
|
|
que montan un `[data-popover-trigger]` (68 lecturas en reposo → 0 movidas, 68 en
|
|
|
hover → 0 movidas, `rules split=2` en las 14) con control negativo diff 5 / 4;
|
|
|
las dos sondas del eje a **0 diffs** (`popover` 448 valores / 8 estados, `chronos`
|
|
|
36 832 / 7); y **el velo sobrevive al orden invertido**, donde con el atajo moría
|
|
|
(`linear-gradient(…8 %…)` → `none`). Cae con la firma el pin `chronos.css:417`
|
|
|
(cinco declaraciones a (0,3,0) que ya no defendían nada): **0 diffs en 20
|
|
|
combinaciones `variant` × `size`**, control negativo 20/20 — §13 lo había
|
|
|
adjudicado mal, al velo del `+N more` lo mata `button.css:69`/`:88`. Guarda §55
|
|
|
apartado **(f)** en `active-eidos-config.test.ts`, **4 mutaciones / 4 mordidas**
|
|
|
(las dos primeras muerden la mitad positiva, las dos segundas —el atajo AÑADIDO
|
|
|
junto al longhand— la negativa).
|
|
|
|
|
|
**Lo que quedó fuera, con su número en `next-features.md` §13**: el residuo
|
|
|
`transition` del MISMO empate (suelo `background, border-color` vs arquetipo
|
|
|
`opacity, background-color`, las dos a (0,0,0) — hoy el `border-color` del hover
|
|
|
de popover salta en vez de animarse), la decisión de producto «popover deja de
|
|
|
declarar hover propio» (no es coste cero: 0.9821 → 0.931 **más** el velo hoy,
|
|
|
sólo el velo después) y `calendar-select.css:14`, que **no es un pin** — retirarlo
|
|
|
rompe el tipo en 3 de 4 tallas (12 / 14 / 20 → 16 px).
|
|
|
|
|
|
**Fichas y prosa saneadas**: `chronos.md` (censo 202→198, propuesta 50→47, en
|
|
|
bloques `<!-- mano:… -->` para que sobrevivan a `--report`), `calendar.md` (su
|
|
|
⚠ HALLAZGO «no determinista» lo cerró §55 y ya no apunta a §13), `emoji-picker.md`
|
|
|
y los tres comentarios de código que seguían afirmando **(0,2,0)** del sobre
|
|
|
(`emoji-picker.css`, `gradient-picker.css` —sólo su mitad base, la de estados
|
|
|
sigue viva— y `lib/recipes/base.ts`). Se ANOTAN, no se reescriben: cada medida
|
|
|
fue correcta con la cascada de su día.
|
|
|
|
|
|
### FIRMA EJECUTADA (2026-08-25) — el eje `size` de `form` LLEGA a sus acciones
|
|
|
|
|
|
**Qué se firmó**: ceder el cromo de `submit`/`reset` al `Button` compuesto
|
|
|
(firma del 2026-08-24) destapó el reverso. `form-submit.svelte:20` y
|
|
|
`form-reset.svelte:15` traían su propio `size = 'md'` y **nada les pasaba la
|
|
|
talla del formulario**, así que un `<Form size="xs">` los renderizaba con
|
|
|
`data-size="md"` —36 px de alto y 16 px de letra— **en las cinco tallas**; del
|
|
|
eje sólo sobrevivía el `row-gap`. Quitar el default no arreglaba nada (el
|
|
|
`Button` tiene el suyo): hacía falta el puente, y el precedente es literal.
|
|
|
Nuevo `eidos/components/form/context.ts` calcado **1:1 de `toolbar/context.ts`**
|
|
|
(`Symbol('form-eidos-ctx')` + getter de propiedad), `form.svelte` publica el
|
|
|
`resolvedSize` que ya calculaba, y las dos acciones leen
|
|
|
`size={size ?? form?.size}` — la prop explícita gana, y standalone cae en el
|
|
|
`md` del propio `Button` sin re-declararlo. **Sólo eidos: cinco ficheros, cero
|
|
|
morfo / soma / sema; el contrato de 64 claves y el ledger, intactos.**
|
|
|
|
|
|
**Los números**: alto **−10 / −6 / 0 / +8 / +16** px y letra
|
|
|
**−4 / −2 / 0 / +4 / +12** px, sobre `submit` y `reset` por igual; **`md` no
|
|
|
mueve un solo valor**; 84 diffs en total y **cero** en los cuatro nodos del
|
|
|
array, el widget y el resumen de errores. Sonda estándar antes/después **0 sobre
|
|
|
832 valores en 7 estados**; instrumento propio reproducible (dos pasadas sobre
|
|
|
código idéntico ⇒ 0 diffs). `vitest src/uix/eidos` 443/444 (el rojo es el ajeno
|
|
|
conocido `skin-media-player`), `check` 0 errores atribuidos a los cinco
|
|
|
ficheros, `docs:check` 0/0.
|
|
|
|
|
|
**La doctrina que hubo que adjudicar**: **VERBATIM, no la norma tapada en `md`**.
|
|
|
La tapa de `reference.md` §«Container→part derivation» gobierna contenedores
|
|
|
cuyo eje es ANCHURA (su primer consumidor es `Dialog.Close`); el de `form` es
|
|
|
DENSIDAD declarada, y su propia receta ya había escrito los cinco peldaños
|
|
|
distintos de la acción. Escrita en `next-features.md` §13 §«Anchura vs
|
|
|
densidad», con el corolario de que a `alert-dialog` —mismo agujero, eje de
|
|
|
anchura— le toca la TAPADA.
|
|
|
|
|
|
**Lo que quedó fuera, con su entrada en §13**: `alert-dialog` (no medido),
|
|
|
`Form.ErrorSummary` con un `data-size` que ninguna regla lee, la escalera de
|
|
|
fuente `12·12·14·14·16` de la acción de `form` (que corrige E1 en su carril) y
|
|
|
la cita colgada de `dialog/context.ts:9`.
|
|
|
|
|
|
### FIRMA B′ EJECUTADA (2026-08-24) — la cascada de paleta es una ESCALERA
|
|
|
|
|
|
**Qué se firmó**: los tres escritores de `--{c}-palette-*` pasan a tres peldaños
|
|
|
que **no empatan** — suelo `:where([data-{c}])` `(0,0,0)` < forward
|
|
|
`[data-{c}]:where([data-color], [data-color-custom])` `(0,1,0)` < tono
|
|
|
`[data-{c}][data-color='X']` `(0,2,0)`. Antes el forward genérico se emitía el
|
|
|
ÚLTIMO empatado a `(0,2,0)` con los bloques por tono, así que **ganaba por orden
|
|
|
de emisión** y 419 claves públicas de tono en 49 recetas no pintaban nunca.
|
|
|
|
|
|
**Por qué B′ y no reordenar la emisión** (que es lo que §13 proponía): el orden
|
|
|
es **contrato invisible** —no se lee en el artefacto, no lo verifica un guard sin
|
|
|
recorrer la hoja entera, se rompe moviendo una línea—. La especificidad es
|
|
|
**contrato EN el artefacto**. Y es la misma ley que §12.9 acababa de firmar para
|
|
|
el plano de profundidad: **una doctrina aplicada dos veces**, no dos parches.
|
|
|
|
|
|
**Los números**: neutra en píxel sobre **~297.000 valores computados**
|
|
|
comparados antes/después (70.912 + 34.336 planos en dos lotes, 57.720 en el
|
|
|
tercero, 134.464 con los tonos ESTAMPADOS en las 49 unidades) — **0 diffs
|
|
|
reales**, y los 17 crudos probados ruido reproduciéndolos sobre código idéntico.
|
|
|
**207 de 353 claves** de tono volvieron a mover un valor computado. Guarda por
|
|
|
**mutación** en `active-eidos-config.test.ts:1761` (6 mutaciones, 6 mordidas;
|
|
|
cierre estructural: toda declaración de paleta vive en uno de los tres peldaños;
|
|
|
anti-vacío `> 40`). Contrato del forward **ensanchado de 2 a 49 recetas** —
|
|
|
vigilaba sólo las de paleta pública y era ciego a las 47 privadas. Suite 35/36
|
|
|
(el rojo `skin-media-player` es AJENO y conocido).
|
|
|
|
|
|
**Dónde vive todo**: doctrina en [`theming/changelog.md`](../theming/changelog.md) §53 ·
|
|
|
contrato en [`theming/reference.md`](../theming/reference.md) (bloque THM-2) ·
|
|
|
emisor `src/uix/eidos/lib/render-css.ts` (`isPaletteSlotToken` parte el bucket
|
|
|
host — **sólo las ranuras de paleta bajan**, el chasis se queda a `(0,1,0)`) ·
|
|
|
guarda `active-eidos-config.test.ts` · ledger `scripts/theming-sentinel-exceptions.ts`.
|
|
|
|
|
|
**Tres leyes que deja escritas, y las tres costaron una medida**:
|
|
|
|
|
|
1. **El silencio del guard NO es señal cuando la adjudicación es por PATRÓN.**
|
|
|
`theming-sentinel.ts` detecta STALE sólo contra el ledger EXACTO
|
|
|
(`k in ledger`), nunca contra `SENTINEL_PATTERN_EXCEPTIONS`. Las 207 claves
|
|
|
resucitadas no dispararon ni un aviso: el estrechamiento hubo que hacerlo
|
|
|
comparando a mano contra las 13 entradas. La única que el guard sí vio fue
|
|
|
`editable.risk-border`, que era exacta.
|
|
|
2. **Un tono por defecto ESTAMPADO resuelve por el forward, no por el suelo.**
|
|
|
El envoltorio estampa `data-color` en toda instancia, la default incluida, así
|
|
|
que `<Button color="primary">` lee el forward y `--button-primary-solid` no
|
|
|
pinta. Quitar el atributo ES hablar en silencio, y entonces sí pinta (medido:
|
|
|
`oklch(0.5556 0.1829 305.86)` → `rgb(1, 2, 3)`). Eso es `PALETTE_FLOOR`; el
|
|
|
resto de supervivientes son `TONE_UNREACHED` (el guard no sabe combinar el
|
|
|
estampado del tono con el hover ni con la variante). Ledger 17 → **28 patrones**.
|
|
|
*(Anotación 2026-08-25: la GRANDE retiró `TONE_UNREACHED` — el guard ya
|
|
|
combina; queda `PALETTE_FLOOR` y el tier volvió a 16.)*
|
|
|
3. **Un `0/N` se investiga, no se reporta.** `switch` dio **0 de 12** claves de
|
|
|
tono vivas y `button` sólo 14 de 49 — y ninguna de las dos era la cascada: la
|
|
|
ficha de `switch` monta UN switch y arranca `unchecked` (y todas sus ranuras
|
|
|
cuelgan de `[data-state=checked]`), y `button` no declara `COMPONENT_OVERRIDES`,
|
|
|
así que no se barre `data-variant` y su ficha monta UN botón sólido. Forzando
|
|
|
el estado, las dos alcanzan. Es la ley 2 del §«Lo primero que debes saber»,
|
|
|
confirmada una vez más.
|
|
|
|
|
|
### Lo primero que debes saber mañana
|
|
|
|
|
|
1. **⚠⚠ EL ÍNDICE DE GIT ES COMPARTIDO.** Un solo `.git/index` para todas las
|
|
|
sesiones de este worktree. Verificar con `git diff --cached` NO basta: entre
|
|
|
que miras y confirmas, otra sesión puede reescribirlo. **Verificación y
|
|
|
`git commit` van ENCADENADOS en la misma invocación de shell.** Costó un
|
|
|
commit con trabajo ajeno dentro y un ledger sin parsear durante cuatro
|
|
|
commits de HEAD. Y me lo hice yo mismo una segunda vez con un `git add`
|
|
|
derivado de `git diff` en vez de rutas explícitas.
|
|
|
2. **El instrumento miente antes que el código, y hoy mintió cinco veces.**
|
|
|
La sonda no congelaba nada · el guard mide UN nodo en siete portalados · un
|
|
|
árbol de trabajo rancio da un `0/98` falso · un grep con la frase exacta
|
|
|
encuentra 2 de 7 · y una lista escrita por Python en Windows lleva `\r` y
|
|
|
revienta el barrido entero con «todos fallan igual». **Un `0/N` o un «todos
|
|
|
igual» no es un resultado: es el instrumento.**
|
|
|
3. **Antes de retirar una clave, mira quién la lee** (paso 8.bis de §7.3, nuevo).
|
|
|
`scroll-area.auto-max-block` leía muerta en su demo y la consumen CINCO
|
|
|
recetas ajenas. Retirarla habría roto seis componentes sin que un guard se
|
|
|
pusiera rojo.
|
|
|
|
|
|
### Qué hay para hacer, por orden
|
|
|
|
|
|
- **Nada de tokenización.** Si aparece un componente nuevo, el protocolo §7 del
|
|
|
PLAN es la ley y el brief de agentes vive en el scratchpad de la sesión.
|
|
|
- **Deuda B — 3, cada uno por su razón**: `audio-player` (no tiene README de
|
|
|
eidos donde escribir «Talla y tema»), `palabras` y `proof-of-human` (carriles
|
|
|
propios).
|
|
|
- **Deuda de instrumento, registrada en §13 y sin bloquear a nadie**: el guard
|
|
|
congela `transition` pero NO `animation` (la sonda ya sí) y no fotografía
|
|
|
`transform`/`translate`; `eidos-lint` no conoce las exenciones que el test de
|
|
|
vitest sí tiene; la columna `size` del censo se apaga cuando el eje sube al
|
|
|
TSC. Las tres piden re-verificar el ledger entero, así que son firma pequeña.
|
|
|
- **Lo que espera TU FIRMA** (todo medido, ninguno bloquea):
|
|
|
1. ~~**La cascada de paleta**~~ — **✅ FIRMADA Y EJECUTADA 2026-08-24 como
|
|
|
firma B′**: era la pregunta hermana de §12.9 y se resolvió con la misma
|
|
|
herramienta, `:where()`. Todo (doctrina, contrato, emisor, guarda, ledger)
|
|
|
está en §«FIRMA B′ EJECUTADA» de aquí arriba. **No queda nada que firmar.**
|
|
|
2. ~~**El componente COMPUESTO contra la receta que lo compone**~~ — **✅
|
|
|
FIRMADA Y EJECUTADA 2026-08-24**: el bloque de acción de `form.css` apunta
|
|
|
ya sólo a los dos botones del array de AutoFields, `submit`/`reset` ceden
|
|
|
todo su cromo al `Button` que componen (0 diffs medidos) y mueren sus
|
|
|
cuatro forwards `_palette-*`; las 23 públicas se quedan, re-adjudicadas
|
|
|
como rama que la demo no monta. `gradient-picker` (36) y `emoji-picker` (3)
|
|
|
**ya estaban ejecutados** (2026-08-20 y 2026-08-23, verificado el
|
|
|
2026-08-24: hoy ninguno adjudica una sola clave por supersesión del
|
|
|
compuesto). **Salida barata ya probada**: `toolbar` cede el cromo al
|
|
|
`Button` y no pierde ni una clave, porque su receta no escribe la regla.
|
|
|
**Se ENSANCHA a la TINTA (verificado 2026-08-24)**: la misma firma §5.2 del
|
|
|
harness cubre ya el `color` de `code`. Medido por CDP
|
|
|
(`getMatchedStylesForNode`): sobre `[data-code]` **sólo DOS reglas declaran
|
|
|
`color`** — `[data-code]` (0,1,0) y `[data-uix-docs] code` (0,1,1,
|
|
|
`web/routes/uix/uix.css:792`, `var(--uix-text)` = `rgb(24,24,27)`) — y gana
|
|
|
el harness. Con `data-color='risk'` estampado, `--_code-palette-text` y
|
|
|
`--_code-color` SÍ se mueven, pero `color` no: la cadena del componente
|
|
|
funciona y la pisa la del harness al final. **No es entrada nueva**: es el
|
|
|
mismo expediente que el ledger ya cita para `code.radius`
|
|
|
(`theming-sentinel-exceptions.ts:665`) y `code-block.pre-padding` (`:676`),
|
|
|
y que reaparece por tercera vez en `prose.code-bg` / `code-radius` /
|
|
|
`code-font-family` (`:862-865`). Lo que cambia es el ALCANCE de la firma:
|
|
|
de radio / padding / tipografía **a incluir también la tinta**.
|
|
|
3. ~~**`file-upload` barre DESCENDIENTES**~~ — **✅ FIRMADA Y EJECUTADA
|
|
|
2026-08-24**: la mitad descendiente pasa a cinco selectores por parte propia
|
|
|
(el morfo declara `data-disabled` en 6 nodos y los 6 llevan su attr de
|
|
|
parte, así que el barrido era redundante hacia dentro). Única ocurrencia en
|
|
|
**171** recetas, no 162. `file-upload` e `image-picker` con diff CERO;
|
|
|
`chat-composer` recupera 6 valores —el textarea salía a **0.4³ = 0.064** de
|
|
|
alpha en el tema POR DEFECTO, 925 px— y su entrada del ledger se RETIRA.
|
|
|
Detalle en §8 del PLAN.
|
|
|
4. ~~**Las cuatro claves de `avatar` fuera de gramática**~~ — **✅ FIRMADA Y
|
|
|
EJECUTADA 2026-08-25** (opción A-c): las cuatro **no eran la misma cosa**,
|
|
|
y la medida las separó en tres tratos. **UNA se renombra** —
|
|
|
`badge-color-custom-contrast` → **`badge-fg-custom-contrast`**, la única
|
|
|
tinta de verdad (alimenta `color:`) y alcanzable desde `:root` (medido:
|
|
|
`white` → `rgb(4,5,6)`); es la salida literal del clasificador firmado, que
|
|
|
deja el calificador contextual DETRÁS de la ranura como en el precedente
|
|
|
`scrim-color-on-dark` → `scrim-fg-over-dark`. **DOS se retiran del
|
|
|
contrato** — `ring-color-custom` y `badge-color-custom` son **canal de
|
|
|
valor**: la puerta `data-*-custom` y la escritura inline nacen de la MISMA
|
|
|
expresión del envoltorio, así que no existe ni puede existir instancia en
|
|
|
la que un tema les gane. Pasan a privadas `--_avatar-{ring,badge}-color-custom`
|
|
|
escritas por el envoltorio y leídas con `var(…, currentColor)` — la forma
|
|
|
que `background`, `carousel`, `checkbox-group`, `file-upload` y
|
|
|
`gradient-builder` ya usan (5 de 5 privadas de envoltorio NO se declaran en
|
|
|
la receta), y la adjudicación que `tabs` hizo con su indicador. **UNA queda
|
|
|
EXENTA** — `group-carve-color` alimenta `box-shadow`: es la GEOMETRÍA del
|
|
|
carve, no tinta, y `group-carve-fg` sería gramática correcta con semántica
|
|
|
peor. Contrato público **88 → 86** (medido en vivo: la pestaña se llama ya
|
|
|
«Tokens 86»), censo `--names` **4 desviadas → 0 en TODO el catálogo**
|
|
|
(4556 claves, exentas 13 → 14). Sonda §7.4: **0 diffs sobre 576 valores**,
|
|
|
y el píxel de los nodos con puerta idéntico (anillo ámbar
|
|
|
`rgb(245,158,11)`, insignia violeta `rgb(124,58,237)`, tinta `white`),
|
|
|
incluida la «instancia imposible». **0 píxeles**, como firmaba la opción.
|
|
|
Abrió dos deudas de INSTRUMENTO, las dos en next-features §13: el codemod
|
|
|
de nombres **aborta sobre `avatar`** (`blockRange()` no lee la IIFE, la
|
|
|
misma ceguera que `f68bac4a6` arregló en censo y centinela), y el centinela
|
|
|
**elige el valor de sonda por el NOMBRE** (`fg$`, sin `-fg-`), así que las
|
|
|
cinco claves del catálogo con `fg` MEDIAL reciben `1234px`. Detalle en §8
|
|
|
del PLAN.
|
|
|
5. ~~**`tags-input`** sella `aria-selected='true'` como LITERAL en cada
|
|
|
etiqueta~~ — **✅ FIRMADA Y EJECUTADA 2026-08-25** (opción B-a2): el morfo
|
|
|
ata `aria-selected` al estado que soma YA deriva de `highlightedIndex`
|
|
|
(`v.literal('true')` → `v.stateRef('active')`), una línea. Era el **único
|
|
|
`aria-selected` incondicional del catálogo**. El árbol AX pasa de **dos
|
|
|
`option` con `selected: true` dentro de dos `listbox` con
|
|
|
`multiselectable: false`** a **cero en reposo y exactamente uno navegando**
|
|
|
(medido por CDP). `--tags-input-item-fg` **revive** —el centinela sube a
|
|
|
**71/91** y su entrada del ledger se RETIRA— y la etiqueta **recupera la
|
|
|
afordancia de hover**: reposo y hover eran byte a byte IDÉNTICOS (media RGB
|
|
|
212,10 en los dos) y ahora son 224,58 → 212,10. Diff de sonda: **14
|
|
|
valores de 2.504, todos `background-image` de las dos etiquetas en los
|
|
|
siete pases sin puntero** — el velo de estado saliendo del reposo, y nada
|
|
|
más. Detalle en §8 del PLAN. Lo que NO arregla: la tinta de tono de la
|
|
|
etiqueta activa.
|
|
|
**Enmienda del 2026-08-25**: esa tinta ya no está abierta en §13 sino en
|
|
|
**next-features §12**, como cuarta ocurrencia de §12.5 y con su decisión ya
|
|
|
redactada (`docs/next-features.md:516`) — es de la capa del SISTEMA, no del
|
|
|
componente. Y las dos cifras de esta entrada estaban mal: la especificidad
|
|
|
es **(0,4,0)**, no (0,3,0), y el ganador no es el selector de
|
|
|
`data-highlighted` sino **el BLOQUE** `archetypes.css:245-257`, cuyos dos
|
|
|
selectores —`data-highlighted` y `aria-selected`— casan LOS DOS la
|
|
|
etiqueta activa desde esta misma firma; retirar uno no mueve nada.
|
|
|
Los dos `listbox` anidados que esta entrada describe **ya no existen**: la
|
|
|
firma «el árbol ARIA de `tags-input` habla UN patrón» (2026-08-25, F-1 de
|
|
|
la ficha de componente) los sustituyó por el layout grid del `apg`
|
|
|
—`grid > row > gridcell`, el campo un textbox en su celda— sin mover un
|
|
|
píxel: **0 diffs sobre 2496 valores computados** en los 8 pases de la
|
|
|
sonda, y ningún CSS del ecosistema selecciona por `role`. No es theming y
|
|
|
no toca el ledger de claves; el centinela no se re-corrió en esa firma
|
|
|
(su script está en obras en otra sesión), pero no hay valor computado que
|
|
|
se haya movido.
|
|
|
6. ~~**El chip de añadir reacción de `chat-message`** lo pinta `popover.css`:
|
|
|
los chips de reacción son píldoras redondas y el de añadir un cuadrado
|
|
|
gris.~~ — **✅ FIRMADA Y EJECUTADA 2026-08-25** (opción b, «la ley del
|
|
|
suelo»): el arreglo NO fue de `chat-message` sino del sobre de
|
|
|
`popover.css`, que se autodescribe como _«a baseline button envelope»_ y
|
|
|
estaba a **(0,2,0)** con su `:hover` a **(0,5,0)**. Baja a
|
|
|
`:where(...)` — (0,0,0) — reposo y hover. **Tercera aplicación de la ley**
|
|
|
de §12.9 y de B′/§53, y la primera que cae en una receta escrita a mano.
|
|
|
**76 instancias en 16 rutas, cuatro estados**: 69 no mueven un valor de
|
|
|
receta (los 64 botones desnudos del sitio de docs, `gradient-picker`, la
|
|
|
demo `data-perm-step` y los tres field-trigger excluidos) y **7 mueven, las
|
|
|
7 hacia lo que su propia receta declara** — el chip vuelve a ser **píldora**
|
|
|
(34×26, radio 9999, 12px), `chronos` recupera su `plain`, `calendar` pasa a
|
|
|
ghost y **deja de ser no determinista** (reproducido antes: 2 de 6 cargas en
|
|
|
14px en vez de 16px; después: 8 cargas en dos órdenes, el mismo píxel),
|
|
|
`emoji-picker`, `palabras` y `natural-time-picker` recuperan lo suyo. **0
|
|
|
movimientos** en 167 nodos de referencia. Centinela: `natural-time-picker`
|
|
|
**44/62 → 48/62**; ninguna entrada del ledger salió STALE (ninguna estaba
|
|
|
adjudicada por este sobre). Cierra de paso el empate latente de
|
|
|
`chat-message.css:462`. Guarda por mutación en
|
|
|
`active-eidos-config.test.ts` (§55, 6 mutaciones, 6 mordidas). Doctrina en
|
|
|
`theming/changelog.md` §55; lo que queda abierto —los dos estados a (0,3,0)
|
|
|
y los pines redundantes— en `next-features.md` §13.
|
|
|
|
|
|
**CON ESTO LA LISTA QUEDA VACÍA: no espera NINGUNA firma tuya en este eje.**
|
|
|
Los seis puntos están ejecutados. Lo que siga tiene que abrirse como entrada
|
|
|
nueva, no heredarse de aquí.
|
|
|
|
|
|
### Lo último que se hizo (2026-08-24 noche): §12.9 FIRMADA
|
|
|
|
|
|
**El plano de profundidad es el SUELO, a especificidad cero.** La Decisión 8
|
|
|
daba por bueno el empate a `(0,1,0)` porque «las recetas cargan después de la
|
|
|
fundación y ganan por orden de cascada» — y esa premisa era FALSA: la fundación
|
|
|
se inyecta en runtime y las recetas llegan como chunks de Vite, así que ganaba
|
|
|
quien cargara el último, medido AL REVÉS en dev que en producción. Una moneda al
|
|
|
aire, no una decisión.
|
|
|
|
|
|
La regla de apariencia del plano se emite en `:where(...)`: la receta gana donde
|
|
|
el componente HABLA, el plano pinta lo que CALLA. **El `frost` NO baja** — es un
|
|
|
opt-in explícito por elemento y debe ganarle al fondo del componente.
|
|
|
|
|
|
**Restauró**: los seis tonos de `toast` (4 de 4 distintos donde antes 3 de 3
|
|
|
eran idénticos, y la franja de acento de 0,67 px de gris a 3 px del color de la
|
|
|
intención) · las tres variantes de `tooltip` · 17 claves que salieron STALE
|
|
|
solas del ledger. **Movió**: 16 de 19 adoptantes con diff CERO sobre ~49.000
|
|
|
valores; los tres restantes son la firma trabajando, incluido el `line-height`
|
|
|
que la receta de `link-preview` tenía escrito como pendiente de esta firma.
|
|
|
|
|
|
⚠ **Para medir el plano**: la sonda compartida mide UN nodo en los portalados y
|
|
|
nunca abre la superficie. El «antes» se reproduce EN RUNTIME inyectando la regla
|
|
|
vieja a `(0,1,0)` (`scripts/__plane-open.mjs`), nunca revirtiendo el fichero.
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
> **LO ÚLTIMO (2026-08-24): DOCE componentes en paralelo, con SUPERVISIÓN.**
|
|
|
> `chat-log` 77 → **100 %** (`fd8f01bac`) · `chat-composer` 79 → **100 %**
|
|
|
> (`71a097ddc`) · `rating-group` 80 → **100 %** (`f6a618328`) · `toggle`
|
|
|
> 81 → **100 %** (`edc019515` + `007c2af52`) · `select` 83 → **92 %**
|
|
|
> (`cc010f79a`) · `avatar` 75 → **90 %** (`f68bac4a6`) · `calendar` 84 → **89 %**
|
|
|
> (`509d1144f`) · `file-upload` 76 → **83 %** (`0c06d42aa`) · `editable`
|
|
|
> 75 → **82 %** (`2117d7422`) · `switch` 76 → **81 %** (`bbdc77c07`) ·
|
|
|
> `radio-group` 77 → **81 %** (`f5d252443`) · `card` 78 → **78 % CERRADO**
|
|
|
> (`f3189a05a`). Global **68 %**.
|
|
|
>
|
|
|
> **Los doce se supervisaron uno a uno, y la supervisión encontró cosas.**
|
|
|
> Refutación estática de los doce commits (cero líneas ajenas en el generado),
|
|
|
> centinelas re-corridos, y cinco hallazgos propios que están abajo. **El
|
|
|
> protocolo §7.7 no es un adorno: cuatro de los cinco salieron de él.**
|
|
|
>
|
|
|
> **Lo que enseñó esta tanda, en una línea cada una:**
|
|
|
> el ÍNDICE DE GIT ES COMPARTIDO y verificar el árbol indexado NO BASTA ·
|
|
|
> un árbol rancio hace MENTIR al instrumento sin tocar un commit ·
|
|
|
> la cascada de paleta se lleva TAMBIÉN el tono por defecto ·
|
|
|
> un componente puede BARRER DESCENDIENTES y comerse el token de sus huéspedes ·
|
|
|
> y la sonda y el guard MUEREN con `--import tsx/esm`.
|
|
|
|
|
|
> **HISTÓRICO (2026-08-23, tarde): SIETE componentes.** `navigation-menu`
|
|
|
> 44 → **100 %** (`85988785d`) · `waveform` 55 → **86 %** (`11b92ded6`) ·
|
|
|
> `color-field` 56 → **93 %** (`3c6742b9c`) · `background` 57 → **95 %**
|
|
|
> (`9bdc5a5d5`) · `s-text-virtual-list` 58 → **70 %** (`1f785b6f2`) · `badge`
|
|
|
> 59 → **75 %** (`271fcd4df`) · `cropper` 60 → **94 %** (`f03ee5af4`).
|
|
|
> Global **66 %**. Los siete con diff 0 y su guard limpio.
|
|
|
>
|
|
|
> **Las cinco cosas que enseñaron, en una línea cada una** (detalle abajo):
|
|
|
> el instrumento tiene TRES caras del mismo punto ciego · un guard puede
|
|
|
> CERRAR lo que mide y montar MÁS puede medir MENOS · subir un privado al
|
|
|
> contrato lo somete a reglas nuevas · lo que se escribe INLINE nunca es tema ·
|
|
|
> y la mitad del trabajo que queda es ADJUDICAR, no acuñar.
|
|
|
|
|
|
**Estado: EN EJECUCIÓN — F0 y F1 CERRADAS · F2 en curso, bloque F2-B CERRADO
|
|
|
con su revisión adversarial pasada (2026-08-22); la cola sigue abierta y
|
|
|
`text-gradient` ya está dentro (2026-08-22) y el **2026-08-23 entraron
|
|
|
DIECISÉIS** (tabla abajo).** Alcance global **65 %** (33 % al abrir el eje, 45 %
|
|
|
tras F2-A, 50 % tras F2-B, y **+6 puntos al arreglar la MEDICIÓN**, no el
|
|
|
código). Sin contrato **24**; **al 100 % 25**; alcance <20 % **12**. Últimos: `chart` 9 % → **89 %**
|
|
|
y `result` 14 % → **90 %**, los dos con `global` a CERO tras la COSTURA. El
|
|
|
censo cuenta 54 knobs menos: los literales ANOTADOS salen del ratio (clase
|
|
|
`exception`). Y `prose` 1 % → **83 %**.
|
|
|
|
|
|
**Desde el 2026-08-23 (tarde) NO queda ningún rojo del bloque viejo** —
|
|
|
`drawer` (24), `metrics` (18), `color-picker` (25) y **`float-panel` (12)**
|
|
|
medidos uno a uno y adjudicados por escrito; el guard R-5.4 pasa en todos. Los
|
|
|
tres hallazgos reales que salieron —el velo del cajón que no pinta, las tallas
|
|
|
del cajón que soma escribe inline y el eje `size` del picker que muere en el
|
|
|
portal— están en §13 y esperan firma.
|
|
|
|
|
|
⚠ **Esta frase estuvo MAL un día**: se escribió el 23 por la mañana dando por
|
|
|
cerrado el bloque viejo cuando `float-panel` seguía con sus doce rojos sin
|
|
|
medir, escritos como «lo que queda» en su propio commit del 22. Lo destapó el
|
|
|
barrido del centinela sobre TODO el ledger (`REVIEW-theming-2026-08-23.md`).
|
|
|
**Un componente cuyo commit dice «lo rojo que queda» NO está cerrado**, y la
|
|
|
única forma de saberlo es correr el guard sobre el ledger entero, no sobre los
|
|
|
que tocas.
|
|
|
|
|
|
## LA COLA A ESTÁ CERRADA (2026-08-24)
|
|
|
|
|
|
`scroll-area` 94 → **100 %** · `slider` 97 → **100 %** · `tabs` 96 → **97 %
|
|
|
CERRADO** · `toast` 98 → **100 %**. Global **68 %**, componentes al 100 %
|
|
|
**45**.
|
|
|
|
|
|
**Los cuatro cerraron SIN ACUÑAR UNA SOLA CLAVE**, y eso es el resultado, no un
|
|
|
atajo: a los cuatro les quedaba un literal, y en los cuatro era identidad
|
|
|
(`opacity: 1` que deshace el `0` del estado oculto · el `100%` de un raíl cuyo
|
|
|
knob real es su suelo `min-inline-size` · el `width: 100%` de `fitted`, que ES
|
|
|
«la lista llena el eje» · el `opacity: 1` del polo en reposo de un par
|
|
|
abierto/cerrado). Firmar un literal de identidad y cerrar es una respuesta tan
|
|
|
válida como acuñar.
|
|
|
|
|
|
### Las dos leyes que dejó
|
|
|
|
|
|
1. **⚠⚠ ANTES DE RETIRAR UNA CLAVE, MIRA QUIÉN LA LEE** — ya es el paso
|
|
|
**8.bis de §7.3** (`868bd235b`). `scroll-area.auto-max-block` leía muerta en
|
|
|
su propia demo y la consumen **cinco recetas ajenas** (`combobox`,
|
|
|
`command`, `gradient-picker`, `select`, `palabras`);
|
|
|
`slider.min-block-size` la fija `media-player` para su volumen vertical.
|
|
|
Retirarlas habría roto seis componentes **sin que un solo guard se pusiera
|
|
|
rojo**, porque ninguno mide el catálogo entero. Leer muerto en SU demo no es
|
|
|
leer muerto en el catálogo.
|
|
|
2. **El indicador de un tablist es CANAL DE VALOR, no superficie de tema.** La
|
|
|
ficha de `tabs` proponía acuñar `indicator-width`/`-height` sobre las vars
|
|
|
que `MeasuredIndicator` escribe en cada movimiento: un público encima sería
|
|
|
un knob que un tema puede FIJAR, y fijarlo rompe el deslizamiento. Rechazado
|
|
|
por escrito, con el precedente de `navigation-menu`.
|
|
|
|
|
|
### ⚠⚠ El hallazgo con más coste del eje: §12.9 se lleva la tarjeta de `toast`
|
|
|
|
|
|
**Un toast `risk` y uno `fulfill` visten la misma tarjeta gris.** Re-medido en
|
|
|
la supervisión sobre la demo real con transiciones y animaciones congeladas:
|
|
|
`risk`, `fulfill` y `affirm` computan **idénticos** (fondo, borde, franja de
|
|
|
acento de 0,67 px y sombra). La tarjeta lleva `data-intent` **y**
|
|
|
`data-depth='overlay'`; escribir `--toast-risk-surface` en `:root` no la mueve
|
|
|
y `--depth-overlay-border` la repinta. **La intención llega al DOM y muere en
|
|
|
la cascada** — 21 claves.
|
|
|
|
|
|
Es la primera vez que §12.9 tiene coste de PRODUCTO y no sólo de contrato, así
|
|
|
que sube el precio de dejarla sin firmar. ⚠ Al medirlo, el tono viaja en
|
|
|
**`data-intent`**, no en `data-color`: una sonda que lea `data-color` lo
|
|
|
encuentra `null` y diagnostica «el tono no llega», que es un defecto DISTINTO.
|
|
|
|
|
|
### Qué queda del eje
|
|
|
|
|
|
- **Cola A: nada.** Los 16 que nunca habían pasado, cerrados o adjudicados.
|
|
|
- **Deuda B: tres**, cada uno por su razón — `audio-player` (sin README de
|
|
|
eidos donde escribir la sección), `palabras` y `proof-of-human` (carriles
|
|
|
propios).
|
|
|
- **Pestañas `Tokens`: ninguna pendiente.** Las 15 entregadas, y de propina el
|
|
|
contador de la pestaña pasa a DERIVARSE del contrato en las 105 demos
|
|
|
(`9fc38b19a` + `c88b2f861`): tres mentían (`carousel` 30/27, `drag-drop`
|
|
|
10/9, `link-preview` 33/35).
|
|
|
- ✅ **§12.9 FIRMADA Y EJECUTADA (2026-08-24)** — el plano es el SUELO,
|
|
|
`:where()`, especificidad cero: la receta gana donde el componente HABLA, en
|
|
|
cualquier orden de carga, y el plano sigue pintando lo que CALLA. El `frost`
|
|
|
NO baja (opt-in explícito por elemento). Doctrina en `changelog.md` §29,
|
|
|
emisor en `render-css.ts`, guarda en `active-eidos-config.test.ts`.
|
|
|
**Medido**: de 19 adoptantes, **16 con diff CERO** sobre ~49.000 valores; los
|
|
|
tres que se mueven son la firma haciendo su trabajo (`toast` recupera sus
|
|
|
seis tonos y una franja de acento de 3 px en vez de 0,67 px de gris;
|
|
|
`tooltip` sus tres variantes; `popover`/`tooltip`/`link-preview` el
|
|
|
`line-height` que sus recetas piden — la decisión de píxel que la receta de
|
|
|
`link-preview` tenía escrita como pendiente de esta firma). 17 claves
|
|
|
salieron STALE y se retiraron del ledger.
|
|
|
- **Esperan tu firma**: la cascada de
|
|
|
paleta (que se lleva también el tono por defecto) · el componente compuesto
|
|
|
contra la receta que lo compone (con la salida barata ya probada en
|
|
|
`toolbar`) · el barrido de descendientes de `file-upload` · las cuatro claves
|
|
|
de `avatar` fuera de gramática · el `aria-selected` literal de `tags-input`
|
|
|
· el chip de reacción de `chat-message`.
|
|
|
|
|
|
## LO QUE DEJÓ LA SEGUNDA TANDA DEL 2026-08-24 (ocho componentes)
|
|
|
|
|
|
Ocho más, por cuatro sesiones en paralelo, **con la ley del índice compartido
|
|
|
ya en el brief** — y esta vez ningún commit se llevó trabajo ajeno. Global
|
|
|
**68 %**, componentes al 100 % **36 → 42**.
|
|
|
|
|
|
| componente | antes → después | lo que enseñó |
|
|
|
| --- | --- | --- |
|
|
|
| `chat-message` | 84 → **100 %** | el guard leía 45/75 y las TREINTA muertas eran ejes que la demo no enciende |
|
|
|
| `chat-typing` | 89 → **100 %** | sus puntos son `> span` desnudos y la demo arranca en `idle`: 3 nodos de 8 |
|
|
|
| `fab` | 88 → **100 %** | el centinela **se auto-cancela**: un lift de 1234 px se lleva el nodo de debajo del cursor |
|
|
|
| `image-adjustments` | 67 → **100 %** | **medir de MÁS midió menos**: el pase de hover recorre 30 nodos como mucho |
|
|
|
| `separator` | 67 → **100 %** | sin acuñar UNA sola clave: sus dos `100%` son identidad |
|
|
|
| `collapsible` | 90 → **100 %** | el que ANIMA no tiene un knob de motion: su firma es `emerge-expand`/`-collapse` |
|
|
|
| `toolbar` | 91 → **94 % CERRADO** | **ceder el cromo al compuesto SALE GRATIS** |
|
|
|
| `tags-input` | 88 → **90 % CERRADO** | su tinta de etiqueta **no ha pintado nunca** (`aria-selected` literal en el morfo) |
|
|
|
|
|
|
**Dos techos, y los dos son doctrina**: los 4 privados de `tags-input` son los
|
|
|
cuatro el puente THM-2, y los 2 de `toolbar` son la identidad de la variante
|
|
|
(una barra `ghost` ES la que no tiene relleno ni sombra).
|
|
|
|
|
|
### El hallazgo que más vale de la tanda
|
|
|
|
|
|
**Ceder el cromo al componente compuesto SALE GRATIS.** `toolbar` deja que
|
|
|
`[data-button]` gane —misma especificidad, emitido después— y **no pierde ni
|
|
|
una clave**, porque su receta ya no escribe reglas sobre el botón (A-112).
|
|
|
Medido ANTES de tocar nada: 51/54, y ninguna silenciosa era del botón. Es el
|
|
|
**reverso exacto de `form`**, que conserva 23 declaraciones muertas por la
|
|
|
misma causa. La firma pendiente de §13 («¿manda el compuesto o la receta que lo
|
|
|
compone?») tiene por tanto una salida barata y ya probada: no escribir la regla.
|
|
|
|
|
|
### Lo que la supervisión arregló
|
|
|
|
|
|
- **La sonda NO congelaba nada** (`10832bef4`). El gate del protocolo es «diff
|
|
|
de computed CERO» y quien lo mide leía transiciones a medias y animaciones en
|
|
|
bucle donde pillaran. `chat-typing` dio **18 diffs de `opacity` corriendo la
|
|
|
sonda dos veces sobre código idéntico**; con la congelación, **0 sobre 1.568
|
|
|
valores**. ⚠ El GUARD sigue congelando sólo `transition`: cambiarlo obliga a
|
|
|
re-verificar el ledger entero (§13).
|
|
|
- **164 fichas regeneradas, clasificadas una a una** (`5c8e707a0`): 155 sólo la
|
|
|
fecha, 7 mejoraban, **2 borraban prosa medida** — cosidas. El generador pisa
|
|
|
lo escrito a mano y eso ya está en §13 con su arreglo.
|
|
|
- **Refutado un susto**: una sesión avisó de que había revertido fichas ajenas y
|
|
|
de que cuatro veredictos §5 podían estar vacíos en HEAD. Comprobados los ocho:
|
|
|
**intactos, de 27 a 81 líneas cada uno**.
|
|
|
|
|
|
### Defectos reales anotados, NO corregidos (mueven píxel o tocan morfo)
|
|
|
|
|
|
- **`chat-message`**: el chip de añadir reacción lleva `data-popover-trigger` y
|
|
|
`popover.css` (0,2,0) le pinta fondo, borde, radio, tinta, altura, padding y
|
|
|
tamaño de letra. **Se ve en la captura**: los chips de reacción son píldoras
|
|
|
redondas y el de añadir es un cuadrado gris. Espera decisión de diseño.
|
|
|
- **`tags-input`**: el morfo sella `aria-selected='true'` como LITERAL en cada
|
|
|
etiqueta, así que `archetypes.css` (0,4,0) le fija tinta y velo de estado EN
|
|
|
REPOSO y su token nunca ha pintado. Tiene cara de defecto de a11y (un lector
|
|
|
anuncia todas las etiquetas como seleccionadas). Toca morfo ⇒ §12.
|
|
|
|
|
|
### Cola A: CERRADA (2026-08-24)
|
|
|
|
|
|
Los cuatro, por dos sesiones en paralelo: `scroll-area` 94 → **100 %**
|
|
|
(`3282ef978`) · `slider` 97 → **100 %** (`4d3ca2fd8`) · `tabs` 96 → **97 %
|
|
|
CERRADO** (`300153f9f`) · `toast` 98 → **100 %** (`b8eccc1c4`). **Los cuatro
|
|
|
cerraron sin acuñar UNA sola clave**: sus contratos ya estaban enteros y lo que
|
|
|
quedaba fuera eran tres literales-identidad (un rail al 100 %, una barra al
|
|
|
`opacity: 1`, la lista `fitted` al 100 %, la tarjeta al `opacity: 1`) y, en
|
|
|
`tabs`, el canal de VALOR de soma. Cuando el número no se mueve porque no debe,
|
|
|
eso ES el resultado.
|
|
|
|
|
|
**Lo que dejaron los dos últimos, en una línea cada uno:**
|
|
|
|
|
|
- **`tabs`** — la mitad de un contrato puede vivir en las VARIANTES (40/79 →
|
|
|
70/79 barriendo `data-variant` y usando las dos URL que el propio demo
|
|
|
ofrece), y su indicador es **canal de valor**: `--indicator-{x,y,w,h}` los
|
|
|
escribe `MeasuredIndicator` en cada movimiento, así que un público encima
|
|
|
sería un knob que un tema puede fijar — y fijarlo rompe el deslizamiento.
|
|
|
- **`toast`** — **§12.9 en una tarjeta PORTALADA se lleva la TARJETA ENTERA**,
|
|
|
21 claves, y con coste de PRODUCTO: un toast `risk` y uno `fulfill` visten la
|
|
|
misma tarjeta gris, y la franja de acento no se ve nunca en reposo (el plano
|
|
|
declara el ATAJO `border`, que pisa el `border-inline-start`). Matiz para la
|
|
|
firma: los seis `{tono}-accent` SÍ alcanzan bajo `[data-loading]`, donde el
|
|
|
`@keyframes` del pulso gana a toda declaración normal — **la misma clave
|
|
|
miente en reposo y dice la verdad en animación**. Y una del instrumento:
|
|
|
**poner `openMarker` EMPEORA la medición** cuando la superficie se
|
|
|
auto-descarta (tres corridas discrepando); sin marcador el guard dispara una
|
|
|
tarjeta nueva antes de cada token y da 51/85 tres veces seguidas.
|
|
|
|
|
|
De la deuda B siguen tres: `audio-player` (sin README de eidos donde escribir
|
|
|
la sección), `palabras` y `proof-of-human` (carriles propios). Más las pestañas
|
|
|
`Tokens` que queden pendientes, la deuda hermana que destapó saldar la B.
|
|
|
|
|
|
## LO QUE DEJÓ LA SESIÓN DEL 2026-08-24 (doce componentes + supervisión)
|
|
|
|
|
|
Doce componentes cerrados por cinco sesiones en paralelo, cada uno con su
|
|
|
commit aislado, y **una pasada de supervisión sobre los doce** (refutación
|
|
|
estática de cada commit + centinela re-corrido + medición propia de todo claim
|
|
|
que no fuese trivial). Cinco componentes llegan al **100 %**; `card` cierra en
|
|
|
**78 %** porque ése ES su techo, y así está escrito en su ficha.
|
|
|
|
|
|
### Los cinco hallazgos de la SUPERVISIÓN (no de la ejecución)
|
|
|
|
|
|
1. **⚠⚠ EL ÍNDICE DE GIT ES COMPARTIDO** (`5be7dabf4`). Hay un solo
|
|
|
`.git/index` para todas las sesiones. Construir el índice desde HEAD y
|
|
|
comprobarlo con `git diff --cached` protege del árbol ajeno, **no de la
|
|
|
ventana entre mirar y confirmar**. Costó `edc019515` (salió con tres
|
|
|
fragmentos de `rating-group` y sin la mitad de los suyos), su reparación
|
|
|
`007c2af52`, y **una coma de más que dejó `theming-sentinel-exceptions.ts`
|
|
|
SIN PARSEAR durante cuatro commits de HEAD** (`88a208644`). El guard no
|
|
|
quedaba en rojo: quedaba MUERTO, y sólo se veía en checkout limpio.
|
|
|
**Regla nueva: verificación y `git commit` en la MISMA invocación de shell.**
|
|
|
2. **Un árbol de trabajo rancio hace MENTIR al instrumento sin tocar un
|
|
|
commit.** El guard de `card` daba `0/98` —la firma del instrumento ciego—
|
|
|
por un `theming-sentinel.ts` sucio con el bloque de `chat-log` DUPLICADO.
|
|
|
Desde copia limpia de HEAD: `49/98`, verde. **Antes de creer un `0/N`,
|
|
|
comprueba que el instrumento coincide con HEAD.**
|
|
|
3. **La cascada de paleta se lleva TAMBIÉN el tono por defecto** (`b7f5a7d75`).
|
|
|
El §13 decía que las `{c}-primary-*` salvan a la instancia sin `data-color`;
|
|
|
donde soma trata el color como valor RESUELTO lo estampa siempre y `neutral`
|
|
|
cae con los otros once. Medido en `switch` y `editable`.
|
|
|
4. **El canal inline filtrado al contrato son CUATRO claves, no dos**
|
|
|
(`009af3300` + `8a4bb8e0e`). Los dos de `avatar` parecían fuera porque su
|
|
|
bloque de `base.ts` es una IIFE que el censo no supo leer hasta `f68bac4a6`.
|
|
|
Re-medidos: ni el fondo del badge ni el `box-shadow` del anillo se mueven
|
|
|
desde `:root`, y **no puede existir instancia alcanzable** — la puerta
|
|
|
`data-*-custom` y la escritura inline viajan JUNTAS.
|
|
|
5. **La sonda y el guard MUEREN con `--import tsx/esm`** (`b4e4fe1fe`).
|
|
|
`ReferenceError: __name is not defined` dentro de `page.evaluate`: el
|
|
|
ayudante `keepNames` de esbuild no existe en la página. Van con `node` a
|
|
|
secas. El error no nombra ni a tsx ni a la sonda.
|
|
|
|
|
|
### Lo que enseñó cada componente
|
|
|
|
|
|
| componente | antes → después | lo que enseñó |
|
|
|
| --- | --- | --- |
|
|
|
| `chat-log` | 77 → **100 %** | el instrumento daba 15/31 y las DIECISÉIS «muertas» estaban vivas |
|
|
|
| `chat-composer` | 79 → **100 %** | **`file-upload` BARRE DESCENDIENTES** y se come el token del huésped |
|
|
|
| `rating-group` | 80 → **100 %** | una escala privada sube al contrato; el guard no fotografía `transform` |
|
|
|
| `toggle` | 81 → **100 %** | el guard sólo sabía barrer UN eje: 36/126 → 70/126 sin adjudicar nada |
|
|
|
| `select` | 83 → 92 % | el portal parte el instrumento: el estado que abre TAPA los de reposo |
|
|
|
| `avatar` | 75 → 90 % | su contrato era INVISIBLE para los dos lectores (una IIFE en `base.ts`) |
|
|
|
| `calendar` | 84 → 89 % | una entrada de receta de FAMILIA no se juzga en la ruta de UN componente |
|
|
|
| `file-upload` | 76 → 83 % | una clave que no pintaba en NINGUNO de sus tres botones — retirada |
|
|
|
| `editable` | 75 → 82 % | el guard CERRABA la superficie que medía (sale del modo con un `blur`) |
|
|
|
| `switch` | 76 → 81 % | su tono NEUTRAL cae con los otros once |
|
|
|
| `radio-group` | 77 → 81 % | su punto NUNCA ha pintado su escala (el SVG escribe `1em` inline) |
|
|
|
| `card` | 78 → **78 % CERRADO** | el número cerrado ES el resultado: sus 8 privados son puente y conmutador |
|
|
|
|
|
|
### Dos verdades sobre el GATE del «diff cero»
|
|
|
|
|
|
Dos componentes NO cerraron a cero, y los dos lo declararon. **Los dos son
|
|
|
ruido del instrumento, reproducido por la supervisión sobre código idéntico**:
|
|
|
|
|
|
- `calendar`: **28 diffs corriendo la sonda dos veces sin tocar nada**, en los
|
|
|
dos mismos nodos (`month-select` / `year-select`) y las dos mismas
|
|
|
propiedades. Empate de especificidad resuelto por orden de carga de Vite. Su
|
|
|
commit además era SÓLO comentarios, así que no podía mover un píxel.
|
|
|
- `chat-composer`: 2 diffs de `blockSize` (30 ↔ 36 px) en `[data-…-attach]`,
|
|
|
reproducidos en tres corridas del mismo código.
|
|
|
|
|
|
**Un diff no cero no es automáticamente una regresión — pero SÓLO se puede
|
|
|
declarar ruido reproduciéndolo sobre código idéntico.** Los dos lo hicieron.
|
|
|
|
|
|
### Lo que hay que saber antes de seguir
|
|
|
|
|
|
- **`card` y `radio-group` están CERRADOS por debajo del 100 %** y no es
|
|
|
deuda: sus privados son puente THM-2 y conmutadores por variante. Un público
|
|
|
encima mataría el `color=` por instancia.
|
|
|
- **`file-upload` es HOY el único componente con un barrido de descendientes**
|
|
|
(`[data-file-upload] [data-disabled]`, una sola ocurrencia en 162 recetas).
|
|
|
Acotarlo mueve píxel de cualquier huésped → espera firma.
|
|
|
- **El guard no fotografía `transform`** y ya son tres los componentes que lo
|
|
|
sufren (`background`, `rating-group`, `card`). Arreglarlo obliga a
|
|
|
re-verificar el ledger entero, así que se adjudica de uno en uno.
|
|
|
- **La demo de `chat-log` se TOCÓ como instrumento** (montaba tres de sus seis
|
|
|
partes sólo en la prosa, así que once claves no tenían nodo que pintar). Roza
|
|
|
la regla de que las demos quedan fuera del eje: queda dicho, no escondido.
|
|
|
- **LA COLA, con la separación que la primera redacción se dejó** (corregido
|
|
|
2026-08-24 al revisar: decía once y son treinta y cuatro, contados contra el
|
|
|
censo y el registro §8).
|
|
|
|
|
|
**A. Nunca han pasado por el eje — 16.** Sin entrada en §8 y sin README:
|
|
|
`field-langs` 0 % (bloqueado por el mandato Field) · `chronos` 1 % (carril
|
|
|
WIP) · `mockup` 38 % (⚠ sin ruta de demo) · `sidebar` 55 % (eje propio) ·
|
|
|
`image-adjustments` 67 % · `separator` 67 % · `chat-message` 84 % ·
|
|
|
`fab` 88 % · `tags-input` 88 % · `chat-typing` 89 % · `collapsible` 90 % ·
|
|
|
`toolbar` 91 % · `scroll-area` 94 % · `tabs` 96 % · `slider` 97 % ·
|
|
|
`toast` 98 %.
|
|
|
|
|
|
**B. Pasaron por el eje pero les FALTABA el README «Talla y tema» — 18,
|
|
|
quedan 3.** ✅ **Quince saldados el 2026-08-24** (`a6df34c05`), con la tabla
|
|
|
DERIVADA del contrato y del ledger. Quedan `audio-player` (no tiene README de
|
|
|
eidos: no hay dónde escribir la sección), `palabras` y `proof-of-human`
|
|
|
(carriles propios). ⚠ **Y sale una deuda hermana**: ninguno de los quince
|
|
|
tiene pestaña `Tokens` en su demo — el paso 11 del protocolo llegó después de
|
|
|
que cerraran, así que hasta que la tengan **la tabla del README es la
|
|
|
fuente**, y así está escrito en los quince. La lista original era: Su
|
|
|
número está adjudicado y su commit hecho; lo que falta es el artefacto del
|
|
|
paso §7 que se volvió obligatorio después de que cerraran (`e522e04e6`
|
|
|
recuperó 21, éstos quedaron fuera): `proof-of-human` · `palabras` ·
|
|
|
`audio-player` · `drawer` · `radio-cards` · `password-field` · `tag-group` ·
|
|
|
`popover` · `color-picker` · `timeline` · `stepper` · `aura` · `metrics` ·
|
|
|
`float-panel` · `chart` · `accordion` · `gradient-builder` · `nav-tree`.
|
|
|
**No es cola de tokenización: es deuda de documentación**, y se salda con un
|
|
|
barrido derivado del contrato como el que ya se hizo una vez.
|
|
|
|
|
|
Regenera siempre esta lista del censo, nunca de memoria: el criterio es
|
|
|
«alcance < 100 % y sin sección `## Talla y tema`», y el desempate entre A y B
|
|
|
es si tiene entrada en el registro §8.
|
|
|
|
|
|
## LO QUE DEJÓ LA SESIÓN DEL 2026-08-23
|
|
|
|
|
|
**Dieciséis componentes** (11 cosidos + 6 de cola + 2 adjudicados sin tocar
|
|
|
código), tres pasadas de rojos anteriores (`drawer` 24, `metrics` 18,
|
|
|
`color-picker` 25) y **una corrección a la baja**: `context-menu` 90 → 87 %, al
|
|
|
retirarle un token que mentía.
|
|
|
|
|
|
| componente | antes → después | lo que enseñó |
|
|
|
| --- | --- | --- |
|
|
|
| `menubar` | 15 → 88 % | el plano `overlay` GANA donde el componente habla |
|
|
|
| `field` | 73 → 98 % | sus 18 rojos estaban vivos; `::placeholder` sin `placeholder` |
|
|
|
| `onion-menu` | 29 → 84 % | `:global()` en CSS plano ⇒ regla DESCARTADA |
|
|
|
| `button` | 55 → 91 % | la cascada de paleta anula 419 claves del catálogo |
|
|
|
| `callout` | 27 → 79 % | la base óptica deja de copiar las métricas del sistema |
|
|
|
| `empty-state` | 29 → **100 %** | 26/26 sin una sola adjudicación |
|
|
|
| `dropdown-menu` | 57 → 96 % | y la tipografía del gemelo, RETIRADA |
|
|
|
| `checkbox` | 59 → 72 % | un huérfano que el test de huérfanos no puede ver |
|
|
|
| `image` | 60 → 96 % | la página que nunca alcanza `networkidle` |
|
|
|
| `anchor-nav` | 20 → **100 %** | el censo no veía los bordes POR LADO |
|
|
|
| `banner` | 30 → **100 %** | 4/42 → 53/53 al estampar `data-intent` y barrer variantes |
|
|
|
| `date-range-field` | 29 → **100 %** | una clave pública que giraba OTRA cosa |
|
|
|
| `time-range-field` | 29 → **100 %** | el gemelo con el MISMO defecto copiado |
|
|
|
| `tooltip` | 52 → 75 % | el plano le anula las TRES variantes |
|
|
|
| `audio-player` | 37 → 56 % | el instrumento medía CERO nodos |
|
|
|
| cola pequeña | 6 comp. | `section` TAPABA sus propias claves públicas |
|
|
|
|
|
|
**Las cinco leyes que salieron, en una línea cada una:**
|
|
|
|
|
|
1. **El portal es una frontera de cascada** — un privado de la raíz no la cruza
|
|
|
(mató el eje `size` del color-picker).
|
|
|
2. **El plano `overlay` gana donde el componente habla** — y no sólo la
|
|
|
tipografía: en `tooltip` se queda el fondo, el borde y la sombra, y con ellos
|
|
|
las tres variantes.
|
|
|
3. **La cascada de paleta anula los tonos del componente** — el bloque genérico
|
|
|
va el ÚLTIMO y gana por orden: 419 claves en 49 recetas.
|
|
|
4. **Un respaldo escrito a mano envejece contra su token** — `, 1.4` contra un
|
|
|
`--font-line-height-sm` que vale 1.45, en dos componentes.
|
|
|
5. **Donde hay un par, el defecto viene en par** — los dos range-field traían el
|
|
|
mismo nombre equivocado, copiado al duplicar.
|
|
|
|
|
|
**Lo que el instrumento aprendió (todo en `scripts/`, ya commiteado):**
|
|
|
|
|
|
- `openMarker` — no pulsar lo que YA está abierto (onion-menu nace abierto y el
|
|
|
guard lo cerraba: 12 de 20 tokens muertos).
|
|
|
- `sweepAttr` — barrer una variante mientras se mide (banner, tooltip, button).
|
|
|
- El barrido de tono estampa `data-color` **y** `data-intent` (banner).
|
|
|
- `extraNodes` para hooks de CLASE (onion-menu) y para partes de OTRO chasis
|
|
|
(audio-player: 0 → 48 nodos).
|
|
|
- Caída a `load` cuando `networkidle` no llega nunca (image).
|
|
|
- `urls` para un componente sin ruta (surface, audio-player).
|
|
|
- Excepciones por PATRÓN (`SENTINEL_PATTERN_EXCEPTIONS`) para una razón
|
|
|
arquitectónica que afecta a 56 claves de golpe.
|
|
|
- El censo: literal ANOTADO dentro de un privado = ausencia firmada; y los ocho
|
|
|
longhands de borde POR LADO (+30 filas en el catálogo).
|
|
|
|
|
|
⚠ **Sonda y centinela filtran por `data-{c}-*`**: un componente que estiliza
|
|
|
HTML crudo (prose) o cuyas partes no llevan atributo se mide sobre UN nodo y el
|
|
|
gate no significa nada. Los dos aceptan ya un selector extra
|
|
|
(`EXTRA_NODES` en la sonda, `extraNodes` en `COMPONENT_OVERRIDES`).
|
|
|
|
|
|
## LA REVISIÓN DE LOS 26 (2026-08-23) — lo primero que hay que saber
|
|
|
|
|
|
Todo lo ejecutado desde la revisión del 22 pasó por fin su análisis:
|
|
|
[`REVIEW-theming-2026-08-23.md`](./REVIEW-theming-2026-08-23.md). **33
|
|
|
componentes, 5 errores reales, 5 desviaciones, y la §7.7 con 5 hipótesis y 5
|
|
|
refutaciones.** Arreglado todo (`233ef989b` · `bfe7727b0` · `e522e04e6` ·
|
|
|
`2f243e1c0`). Las cuatro lecciones que cambian cómo se trabaja:
|
|
|
|
|
|
1. **Corre el guard sobre el ledger ENTERO, no sobre lo que tocas.** Así salió
|
|
|
que `float-panel` llevaba DOCE rojos sin adjudicar desde el 22 —escritos como
|
|
|
«lo rojo que queda» en su propio commit— mientras el handoff daba el bloque
|
|
|
viejo por cerrado. Un componente cuyo commit dice «lo que queda» NO está
|
|
|
cerrado.
|
|
|
2. **El nombre de un token no es el de la propiedad.** `badge` acuñó
|
|
|
`min-block-size-{k}` donde la ranura es `height`: 24 componentes dimensionan
|
|
|
por `…-height-{k}` y era el único. R-5.3 no guarda el vocabulario
|
|
|
DIMENSIONAL (§13) — mientras no lo haga, **cuenta el nombre en el catálogo
|
|
|
antes de acuñarlo**, también para las dimensiones.
|
|
|
3. **Los pasos 8 y 9 del protocolo (README «Talla y tema» + pestaña `Tokens`) se
|
|
|
saltaron en 22 componentes de una tanda entera** y nadie lo notó hasta
|
|
|
revisar los `git show --stat`. Si no está en el commit, no se hizo.
|
|
|
4. **Antes de comparar contra una base, comprueba que la base MONTA.** El
|
|
|
worktree necesita `server: { fs: { allow: [...] } }` cuando su `node_modules`
|
|
|
es una junction; sin eso Vite responde 403, la página no hidrata y el diff
|
|
|
sale limpio contra la nada.
|
|
|
|
|
|
## LO QUE DEJÓ LA TANDA DE SIETE (2026-08-23) — léelo antes de seguir
|
|
|
|
|
|
**El instrumento tiene TRES caras del mismo punto ciego, y ninguna se detecta
|
|
|
sola.** El filtro es `data-{c}-*`, así que no ve: (1) HTML crudo estilado por
|
|
|
descendencia (`prose`), (2) partes que compone el CONSUMIDOR — los `<a>` desnudos
|
|
|
de un mega-menú (`navigation-menu`: 10 nodos, ninguno era el panel), y (3) partes
|
|
|
de un componente COMPUESTO — el playhead de `waveform` ES el thumb de un Slider
|
|
|
embebido (4 nodos, ninguno era él). Añade una cuarta forma: **las capas OPT-IN**
|
|
|
(`background` medía 2 de 37 tokens; `badge`, 2 nodos de 5 porque dot / icon /
|
|
|
remove nacen apagados). **Cuenta los nodos SIEMPRE, y si el número es pequeño,
|
|
|
sospecha antes de creerte el gate.**
|
|
|
|
|
|
**Un guard puede cerrar lo que mide, y montar más puede medir menos.**
|
|
|
`navigation-menu` abre por `pointerenter`, y el aparcado del puntero en (0,0)
|
|
|
que el guard hace tras el clic es exactamente el gesto que lo cierra: daba
|
|
|
no-determinismo y las dos caras del error a la vez (falso negativo en las filas,
|
|
|
falso POSITIVO en el token que ensancha el panel). Y en `background`, encender
|
|
|
el foco puntual y el paralaje **bajó** la corrida de 17 a 9 tokens, porque los
|
|
|
dos repintan la capa donde se miden los patrones. Nace `prepareWith` (enciende
|
|
|
TODOS los controles que se le den, al contrario que `openWith`), y con él la
|
|
|
regla: **enciende sólo lo que no tapa, y compruébalo corriendo el guard antes y
|
|
|
después de cada control**.
|
|
|
|
|
|
**Subir un privado al contrato lo somete a reglas que en el CSS no se le
|
|
|
aplicaban.** Dos veces la misma tarde: `badge.min-block-size-*` y
|
|
|
`cropper.zoom-btn-font-size` copiaban el primitivo CRUDO que el CSS usaba, y
|
|
|
`recipe-css-contract` exige la coordenada del BUNDLE. La suite lo caza en el
|
|
|
acto — pero sólo DESPUÉS de escribirlo, así que escribe el bundle desde el
|
|
|
principio.
|
|
|
|
|
|
**Lo que el componente escribe INLINE no es tema, nunca.** `s-text-virtual-list`
|
|
|
se queda en 70 % porque su triple tipográfico lo escribe él en cada render desde
|
|
|
props resueltas (y tiene que ser exacto: el canvas que mide el texto lee
|
|
|
`getComputedStyle`). Igual el `--_background-gradient-image` y el rect del
|
|
|
indicador de nav-menu. Un público encima MIENTE.
|
|
|
|
|
|
**La mitad del trabajo que queda es adjudicar, no acuñar.** `color-field` tenía
|
|
|
13 tokens que nunca se habían medido y `background` 19; los dos con contrato
|
|
|
sano. Un componente sin veredicto §5 no es un componente sin tokens: es uno sin
|
|
|
MEDIR. Y hay dos atajos legítimos: la excepción POR PATRÓN cuando la razón es
|
|
|
arquitectónica (las 40 claves de tono de `badge`, la cascada de paleta) y la
|
|
|
clase «sólo el paso en vigor pinta» para toda escala resuelta por atributo.
|
|
|
|
|
|
**Dos trampas de medición que costaron tiempo:**
|
|
|
|
|
|
- **Congela `transition` en TODA medición a mano.** Una propiedad transicionada
|
|
|
devuelve el valor VIEJO si la lees en el acto — pasó con `color` en
|
|
|
`navigation-menu`, y ya había pasado con el cuentagotas del color-picker.
|
|
|
- **Mide el nodo que PINTA, no el primero que casa el selector.** En
|
|
|
`color-field` sospeché del `@media (prefers-reduced-motion)` durante tres
|
|
|
diagnósticos: la causa era que el primer `[data-color-field-segment]` es un
|
|
|
`literal`, que declara `transition: none` de su propia cosecha.
|
|
|
|
|
|
## LO QUE DEJÓ `navigation-menu` (2026-08-23) — el detalle
|
|
|
|
|
|
**Tres cosas que se repetirán en la cola, y cuestan una medición cada una:**
|
|
|
|
|
|
1. **Cuenta los nodos ANTES de creerte el gate — otra vez, y por una causa
|
|
|
nueva.** Las filas de su mega-menú son los `<a>` **desnudos del consumidor**,
|
|
|
que la receta estiliza por DESCENDENCIA
|
|
|
(`[data-navigation-menu-content] :is(a, …)`). Sonda y centinela filtran por
|
|
|
`data-{c}-*`: veían 10 nodos y **ninguno era el panel ni una fila** — 9 de
|
|
|
sus 19 knobs quedaban fuera del diff. Es la clase de `prose` y `onion-menu`,
|
|
|
pero por **composición del consumidor**. Los dos instrumentos aceptan ya el
|
|
|
selector extra para este componente, y el paso `open` de la sonda —que NO
|
|
|
honraba `EXTRA_NODES`— ahora sí.
|
|
|
2. **Un panel de HOVER lo cierra el propio guard.** Abre con `pointerenter` y
|
|
|
`pointerleave` PROGRAMA el cierre; el guard abre con clic y luego aparca el
|
|
|
puntero en (0,0), que es justo el gesto que lo cierra. Daba
|
|
|
**no-determinismo** (dos corridas del mismo código discrepando) y las **dos
|
|
|
caras del error a la vez**: falso negativo en los tokens de la fila y falso
|
|
|
POSITIVO en `content-link-padding-inline`, que leía «vivo» porque ensancha
|
|
|
el panel que sí se medía. Se arregla con `openBy: 'hover'`. **Regla: antes
|
|
|
de creer un «no effect», comprueba que la superficie seguía abierta.**
|
|
|
3. **`color` puede estar EN TRANSICIÓN.** Forzar `data-disabled` y leer en el
|
|
|
acto devuelve el valor VIEJO: tres diagnósticos falsos («ni el inline lo
|
|
|
mueve») hasta congelar. Es la trampa del cuentagotas del color-picker, en
|
|
|
otro componente y sobre otra propiedad. **Toda medición a mano congela
|
|
|
`transition` — el guard ya lo hace, tu script de un solo uso no.**
|
|
|
|
|
|
**Y dos de doctrina:**
|
|
|
|
|
|
- **El catálogo decide el nombre, no la §4.** Aquí falló de CINCO maneras (las
|
|
|
cuatro conocidas más una nueva: un aviso de capa compartida disparado por
|
|
|
**homonimia** — `menu-indicator` es el check de los CheckboxItem, no el
|
|
|
subrayado de esta barra). Contar en `base.ts` resolvió los 19 nombres.
|
|
|
- **Un nombre de parte que existe en OTRO sitio del mismo componente miente.**
|
|
|
Los gemelos llaman `item-*` a la fila del panel; aquí `item` es el `<li>` de
|
|
|
la barra y el `Link` de barra viste el cromo del trigger, así que ni `item-*`
|
|
|
ni `link-*` valen: `content-link-*` nombra el nodo por donde vive.
|
|
|
|
|
|
**Contabilidad**: el censo decide el eje `size` grepeando `data-size` en el CSS,
|
|
|
y el protocolo §7.4 ORDENA retirar esos bloques — así que **todo componente que
|
|
|
aplique bien el protocolo aparece «sin eje `size`»**. Ya le pasa a `sidebar`,
|
|
|
`nav-tree` y ahora a `navigation-menu`. Registrado en §13; no es deuda.
|
|
|
|
|
|
## LO PRIMERO AL ENTRAR (cinco minutos, en este orden)
|
|
|
|
|
|
1. **Comprueba que el suelo no se ha movido**:
|
|
|
|
|
|
```bash
|
|
|
node --import tsx/esm scripts/theming-census.ts # 162 · 5.137 · 2.770 (60 %) · 24 sin contrato
|
|
|
node --import tsx/esm scripts/theming-census.ts --names # DESVIADAS 0 — la gramática se mantiene
|
|
|
```
|
|
|
|
|
|
El segundo cubre componentes que `component:audit` NO ve (p. ej.
|
|
|
`picker-shell`, eidos-only sin morfo): córrelo siempre, no te fíes del audit
|
|
|
para la gramática.
|
|
|
|
|
|
2. **Arranca el dev server ANTES de medir nada**: `preview_start` con la config
|
|
|
`dev` de `.claude/launch.json` (puerto **5180**). Las sondas se ejecutan con
|
|
|
`node`, no con `tsx`, desde la raíz, y **su default es 5173**: pásales
|
|
|
siempre la URL como tercer argumento.
|
|
|
|
|
|
3. **Lee el veredicto §5 de la ficha** (`docs/audit/theming/{c}.md`). Si está
|
|
|
vacío — lo están **~130 de 171** — lo escribes TÚ midiendo, y luego
|
|
|
ejecutas: ése fue el flujo de todo F2-B. La §4 generada **no se sigue a
|
|
|
ciegas**; ver «Lo que F2-B enseñó».
|
|
|
|
|
|
## QUÉ HACER AHORA
|
|
|
|
|
|
### 1. F2-B está CERRADO — su revisión adversarial (§7.7) se hizo el 2026-08-22
|
|
|
|
|
|
**4 hipótesis · 3 refutadas · 1 hallazgo real.** Detalle en `PLAN §8`. Lo que
|
|
|
hay que recordar de ella:
|
|
|
|
|
|
- **`drag-drop.preview-z` mentió y se retiró**: soma escribe su `z-index`
|
|
|
INLINE, y la adjudicación que lo daba por vivo se había medido sobre un nodo
|
|
|
creado a mano. **Una adjudicación «forzado → alcanza» vale lo que valga el
|
|
|
nodo que se forzó** — si lo creaste tú, no lleva lo que soma le pone.
|
|
|
- **El orden de carga NO es el mismo en dev que en producción** (medido con
|
|
|
build + CDP). El empate de §12.9 sigue abierto, ahora con las dos medidas.
|
|
|
- **Un worktree cuyo `node_modules` es una junction fuera del root no hidrata**:
|
|
|
Vite responde 403 a `@fs/…`. La primera pasada comparó contra una base muerta
|
|
|
sin que nada lo delatara — añade `server: { fs: { allow: [...] } }` a su
|
|
|
`vite.config.ts` y **comprueba que un componente monta antes de comparar**.
|
|
|
|
|
|
### 2. El censo cuenta distinto desde el 2026-08-22 — léelo antes de comparar cifras
|
|
|
|
|
|
**Un privado que DERIVA de un público ya cuenta como alcanzable.** Es lo que F0
|
|
|
encargaba («leer `--_c-x: var(--c-y)` y reclasificar») y sólo se había
|
|
|
implementado para el INFORME: la columna «¿deriva de un público?» de la §3 lo
|
|
|
decía, pero el contador lo seguía puntuando como deuda. Medido: **240 privados
|
|
|
en 59 componentes** estaban en ese estado, haciendo exactamente lo que la
|
|
|
doctrina prescribe y penalizados por ello.
|
|
|
|
|
|
El cierre es TRANSITIVO (`--_a: calc(var(--_b) * .3)` alcanza si `--_b`
|
|
|
alcanza) y tiene muta-prueba: apuntar un privado a un primitivo crudo baja la
|
|
|
cifra, revertirlo la sube. **Global 50 % → 56 %**, privados 625 → 341, al 100 %
|
|
|
10 → 14. `avatar` pasó de 36 % a 75 % y `picker-shell` de 76 % a 95 % **sin
|
|
|
tocar una línea de su código**.
|
|
|
|
|
|
Consecuencia: **cualquier cifra anterior al 2026-08-22 no es comparable con las
|
|
|
de ahora.** Las de este handoff ya son las nuevas.
|
|
|
|
|
|
### 3. Lo que dejó la sesión del 22 (24 componentes en F2-B, todos con 0 diffs)
|
|
|
|
|
|
`grid-list` 85 · `textarea` 80 · `tree-view` 92 · `code-block` 81 ·
|
|
|
`card-group` 90 · `spinner` 70 · `picker-shell` 95 · `link-preview` 100 ·
|
|
|
`drag-drop` 89 · `kbd` 86 · `link` 36 · `code` 100 · `virtual-list` 67 ·
|
|
|
`virtual-grid` 73 · `skeleton` 45 · `label` 100 · `announce` 88 ·
|
|
|
`clipboard` 63 · `scroll-frames` 33 · `mark` 60 · `menu-dial` 38 · `knob` 75 ·
|
|
|
`skin-media-player` 22 · `text-circular` 100 · `text-focus` 100. Más cinco
|
|
|
adjudicados como **0 % estructural** (`aspect-ratio`, `text-blur`, `cascade`,
|
|
|
`motion`, `date-picker`), la revisión adversarial §7.7, el arreglo del censo y
|
|
|
el test del suelo.
|
|
|
|
|
|
**Tres cosas que enseñó y conviene tener delante al seguir:**
|
|
|
|
|
|
1. **La propuesta §4 generada falla de cuatro maneras.** Hereda el
|
|
|
incumplimiento del CSS de partida (si ya violaba `recipe-css-contract`, lo
|
|
|
repite); infla hasta 4× (71 tokens para 23 knobs en `spinner`); nombra por
|
|
|
el primer selector de la regla y no por el nodo pintado (llamaba `root-bg` a
|
|
|
una guía de indentación); y **usa el slot `color` donde la gramática firmada
|
|
|
exige `fg`** — R-5.3 lo caza, pero después de escribirlo.
|
|
|
2. **Declarar un público «de facto» puede MATAR una escala.** Varios
|
|
|
componentes consumen `var(--c-x, <default>)` sin declarar `--c-x`. Si detrás
|
|
|
del fallback hay un privado por talla (`knob`), declarar el público lo mata:
|
|
|
el público va primero y gana siempre. Hay que subir la escala al TSC. Si no
|
|
|
lo hay (`text-circular`, `text-focus`), declarar es seguro.
|
|
|
3. **Cuenta los nodos que ve la sonda antes de creerte un gate verde.** Cuatro
|
|
|
componentes miden UN nodo, `picker-shell` medía CERO. Y el centinela tiene
|
|
|
tres puntos ciegos ya medidos: congela transiciones, su valor grande se capa
|
|
|
contra `min()`, y no ve lo que la demo no monta.
|
|
|
|
|
|
### 3.bis Lo último ejecutado — `text-gradient` (2026-08-22)
|
|
|
|
|
|
**67 % → 100 %**, 7 claves. Detalle y porqués en `PLAN §8` y en el veredicto
|
|
|
§5 de su ficha. Lo que conviene tener delante al seguir con la cola:
|
|
|
|
|
|
- **La ficha §4 falla también contra el CATÁLOGO, no sólo contra la doctrina.**
|
|
|
Proponía conservar `weight` (77 claves del catálogo dicen `font-weight`), y
|
|
|
marcaba `width`/`height` con «⚠ eje físico» cuando el `calc(100% - 2px)`
|
|
|
era UN knob —el trazo del marco— del que el hueco deriva. **Antes de acuñar
|
|
|
un nombre, cuéntalo en `base.ts`**: el catálogo es el que habla.
|
|
|
- **Un literal igual a un paso de escala no se congela: se nombra.**
|
|
|
`1px` → `var(--border-width)`, `blur(4px)` → `var(--blur-sm)`. Y ojo con
|
|
|
`blur`: es familia MÉTRICA del eje `scaling` (theming §23), así que un
|
|
|
literal es ciego al zoom global aunque el computed coincida a scaling 100.
|
|
|
- **Los dos instrumentos ya saben encender una VARIANTE.** La sonda tiene
|
|
|
`DEMO_VARIANTS` (chips que se re-pulsan tras CADA recarga — la sonda recarga
|
|
|
una vez por talla) y el centinela acepta `openWith` apuntando a un chip, no
|
|
|
sólo a un trigger de panel. Sin eso, esta demo daba 2 nodos y los tres tokens
|
|
|
del marco no se medían. **Cuenta los nodos antes de creerte el gate.**
|
|
|
- **Las demos NO forman parte del eje** (autor, 2026-08-22): sólo los
|
|
|
componentes. Un hallazgo de demo o del harness del sitio no se registra ni se
|
|
|
mide; la demo se toca únicamente como INSTRUMENTO (encender una variante para
|
|
|
que la sonda vea los nodos), y lo mínimo.
|
|
|
|
|
|
### 3.ter `text-scramble` ADJUDICADO (2026-08-22) — sin contrato, y por qué
|
|
|
|
|
|
Su 50 % no es deuda ni logro: **dos literales son la técnica sr-only** (como
|
|
|
`text-blur`) y **los dos «públicos» son tipografía que no debería acuñar**, o
|
|
|
sea la firma 1.bis. Escribirle un contrato ahora sería acuñar justo lo que esa
|
|
|
firma propone retirar. Veredicto §5 escrito, cero cambios de código.
|
|
|
|
|
|
De paso salió el **barrido mecánico** que `--radius-xs` y `--font-size-4xl`
|
|
|
pedían: **9 referencias fantasma con fallback** en el catálogo (5.793 nombres
|
|
|
declarados). Tabla en next-features §13. La más grave no es de esta familia:
|
|
|
`--color-content-tertiary` sigue vivo en TRES recetas —es el caso histórico que
|
|
|
`recipe-contract` §1 cita como origen de la regla— y los cuatro
|
|
|
`--style-*-font-variation-settings` de `text.css` significan que **el eje de
|
|
|
fuente variable no llega nunca al primitivo `Text`**. Ninguna se arregla aquí.
|
|
|
|
|
|
### 3.ante LA VÁLVULA DEL CANON ya se lee (2026-08-22)
|
|
|
|
|
|
`recipe-contract` §3: un literal con `/* literal: <razón> */` **en su propia
|
|
|
declaración** es una desviación FIRMADA. `component-audit` la honra desde
|
|
|
siempre; el censo no, porque `strip()` blanquea los comentarios antes de
|
|
|
clasificar — 81 anotaciones contaban como deuda. Ahora caen en la clase
|
|
|
**`exception`, fuera del ratio** como `system`: **54 knobs** en 12 componentes
|
|
|
(prose 21 · proof-of-human 16 · palabras 3 · timeline 2 · result 1 …). Global
|
|
|
58 % → **59 %**.
|
|
|
|
|
|
**Consecuencia práctica al tokenizar**: antes de acuñar un literal, mira si ya
|
|
|
lleva su anotación — si la lleva, el canon ya decidió que ahí no va un token, y
|
|
|
la ficha lo lista ahora en su **§1.4** con la razón escrita. Y si vas a dejar un
|
|
|
literal fuera, ANÓTALO: es la única forma de que no vuelva a contarse como
|
|
|
deuda.
|
|
|
|
|
|
### 3.pre EL PUENTE DE PALETA no es deuda (2026-08-22)
|
|
|
|
|
|
De las **687** declaraciones del catálogo que leen un privado, **130 leen un
|
|
|
`--_{c}-palette-*`**: el puente THM-2 que la capa compartida alimenta por
|
|
|
instancia desde `[data-color]`. **No se acuña**: un público encima dejaría que
|
|
|
un tema lo fijara y matara en silencio el `color=` de cada instancia. Domina la
|
|
|
columna `private` de todo componente con paleta, así que **el techo de ésos no
|
|
|
es el 100 %**. Tres ya adjudicados (`tag-group` 65 %, `stepper` 79 %,
|
|
|
`timeline` 73 %, éste además con el CONMUTADOR por `data-intent`); los demás
|
|
|
heredan la razón: radio-group 10, checkbox 8, file-upload 8, calendar /
|
|
|
editable / los tres grids 7 — pero ojo, esos tienen ADEMÁS `global` y sí les
|
|
|
toca trabajo real.
|
|
|
|
|
|
### 3.quater LA COSTURA (2026-08-22) — lo más importante de la sesión
|
|
|
|
|
|
**El valor es del sistema; el knob es del componente.** Tokenizando `chart` y
|
|
|
`result` di por doctrina que «el texto no recibe tokens del componente» porque
|
|
|
su valor viene del canon, y dejé el CSS leyendo `var(--style-caption-font-size)`
|
|
|
y `var(--color-content-*)` A PELO. Es media doctrina: PLAN §2-A pide que TODO
|
|
|
knob de apariencia lea `--{c}-{slot}`. Sin la costura, un tema no puede aclarar
|
|
|
las anotaciones de un gráfico denso sin mover `caption` en toda la app, y
|
|
|
`getRecipeTokens()` / `/temas` no ven esa superficie. El molde ya estaba
|
|
|
escrito: `--accordion-trigger-font-family: var(--style-label-font-family)`
|
|
|
(§Vertebración tipográfica), y D-TH.2 aclara que **sólo los seis PRIMITIVOS**
|
|
|
quedan fuera. Resultado: chart 49 % → **89 %**, result 23 % → **86 %**, y
|
|
|
`global` a CERO en los dos.
|
|
|
|
|
|
**Dos formas, y se eligen midiendo**: por ROL cuando un rol se repite sobre
|
|
|
muchos nodos (chart: 2 roles × 3 ejes = 6 claves para 19 nodos de texto; por
|
|
|
parte habrían sido ~30 con dos valores) y por PARTE cuando cada parte tiene
|
|
|
tipografía propia y ningún rol la cubre (result: 15). Agrupa las filas por valor
|
|
|
ANTES de decidir.
|
|
|
|
|
|
**Y una nota de §13 retirada por equivocada**: escribí que el censo penalizaba
|
|
|
consumir la capa tipográfica. El censo medía bien; faltaba la costura. **Cuando
|
|
|
la métrica y la doctrina discrepan, sospecha de la lectura antes que del
|
|
|
instrumento.** `listbox` (68 %, ritmo de fila prestado de `list-surface`) es la
|
|
|
misma pregunta un piso más arriba: pendiente de revisar con este molde.
|
|
|
|
|
|
### 3.quinquies `chart` — el instrumento, tres veces ciego
|
|
|
|
|
|
Lo que hay que llevarse de aquí:
|
|
|
|
|
|
- **La ficha pedía 71 claves; ~20 habrían llevado el mismo valor.** Antes de
|
|
|
aceptar una propuesta larga, **agrupa las filas por VALOR**: las 84 de chart
|
|
|
colapsaban a 26. Nombrar por parte lo que es un concepto es la inflación de
|
|
|
`spinner` con otra cara.
|
|
|
- **El texto de un componente no recibe tokens propios**: rol de tamaño de los
|
|
|
estilos con nombre (`caption` / `label`), tinta y peso de las ranuras del
|
|
|
sistema. Sólo se acuña la tinta de lo que NO es texto.
|
|
|
- **El guard ya sabe medir en VARIAS rutas** (`urls` en `COMPONENT_OVERRIDES`):
|
|
|
un token vive si alguna superficie del componente lo sigue. Chart tiene 16;
|
|
|
`picker-shell` ya lleva la del date-picker (su ruta propia es 404).
|
|
|
- **El guard ya lee SVG** (`fill`, `stroke`, `strokeWidth`, `fillOpacity`, `r`,
|
|
|
`rx`…) y **elige el valor centinela por el FINAL del nombre**, no por
|
|
|
subcadena — `slice-stroke-width` recibía un color por contener «stroke».
|
|
|
- Tras cualquier cambio del guard: **re-verificar los 28 componentes con
|
|
|
ledger** (se hizo: cero regresiones, cero STALE). Y ojo, correr doce a la vez
|
|
|
contra el mismo dev server da falsos exit=1 por timeout: repite el que falle
|
|
|
a solas antes de creerte una regresión.
|
|
|
|
|
|
### 4. La cola que queda, por alcance
|
|
|
|
|
|
| componente | knobs | nota |
|
|
|
| --- | ---: | --- |
|
|
|
| `palabras` | 471 (22 %) | **el mayor del catálogo con diferencia**, sin tocar; D-TH.3 decide si entra |
|
|
|
| `field-langs` | 41 | espera el **mandato Field** (firma 2), que NO es tokenización: manda que los x-field incorporen el wrapper Field — cambia composición y mueve píxel |
|
|
|
| `mockup` | 29 (38 %) | ⚠ **sin ruta de demo (404)**, como `picker-shell`: sin sonda ni guard. Y sale NEEDS-WORK en el audit, preexistente |
|
|
|
| `chronos` | 245 (1 %) | el segundo mayor; sin abrir |
|
|
|
| `proof-of-human` | 95 (15 %) | escena de tono fijo firmada; lo demás son hooks de clase (eje aparte) |
|
|
|
| `prose` | 74 (1 %) | su superficie es la capa tipográfica: mismo caso que chart, un piso más arriba |
|
|
|
| `nav-tree` · `banner` · … | varios | ver el censo, `reach < 20 %` = 12 |
|
|
|
|
|
|
**Cerrados el 2026-08-23 (siete)**: `navigation-menu` 100 % · `background` 95 % ·
|
|
|
`cropper` 94 % · `color-field` 93 % · `badge` 75 % · `s-text-virtual-list` 70 % ·
|
|
|
`waveform` 86 %. **El siguiente por alcance entre los medibles y sin bloqueo es
|
|
|
`emoji-picker` (61 %)**, y luego `meter` / `spin-field` (64 %), `pin-input`
|
|
|
(65 %), `dialog` (67 %, ⚠ overlay: no acuñes tipografía hasta §12.9),
|
|
|
`progress` (69 %), `color-swatch` (70 %), `form` (71 %)… El mayor no bloqueado
|
|
|
sigue siendo `chronos` (1 %, carril WIP de D-TH.3, y «tiempo» es el ÚLTIMO de
|
|
|
D-TH.4).
|
|
|
|
|
|
`avatar` ya está al **75 %** y `knob` al 75 % (ambos hechos). `heading` /
|
|
|
`text` / `display` son primitivos tipográficos: su superficie es `--style-*` y
|
|
|
el censo los saca del ratio. `range-calendar` / `month-grid` / `year-grid`
|
|
|
están a 0 % **honesto** (consumen `calendar-surface`).
|
|
|
|
|
|
`heading` / `text` / `display` son primitivos tipográficos: su superficie es
|
|
|
`--style-*` y el censo ya los saca del ratio. `range-calendar` / `month-grid` /
|
|
|
`year-grid` están a 0 % **honesto** (consumen `calendar-surface`).
|
|
|
`alert-dialog`, `css-field`, `mask-field`, `number-field`, `highlight`, `stack`,
|
|
|
`wrap`, `auto-grid` tienen **cero knobs**: no hay nada que tokenizar.
|
|
|
|
|
|
### 5. Lo que espera TU FIRMA (todo medido, nada bloquea la cola)
|
|
|
|
|
|
1. **El plano `overlay` impone tipografía a VEINTE componentes — y en
|
|
|
`tooltip` se queda además el FONDO, el BORDE y la SOMBRA**, con lo que sus
|
|
|
tres variantes computan lo mismo (medido 2026-08-23: `solid`, `outline` y
|
|
|
`ghost` idénticas). Ya no es una pregunta sobre tipografía: es sobre qué
|
|
|
manda, el plano o la receta. Cuatro componentes han tenido que RETIRAR o
|
|
|
ADJUDICAR claves por esto (menubar, dropdown-menu, context-menu, tooltip;
|
|
|
`combobox` sigue con la suya, registrada).
|
|
|
(`font-family` + `line-height` junto a superficie/borde/sombra). ¿Un plano
|
|
|
de profundidad manda sobre la tipografía o sólo sobre la superficie?
|
|
|
— §12.9. **Es la que más urge: cada overlay que se tokenice la arrastra.**
|
|
|
**Y ya tiene MECANISMO** (menubar, 2026-08-23): el plano no sólo impone
|
|
|
donde el componente calla — **GANA donde el componente habla**. Declara
|
|
|
`font-family` y `line-height` con la misma especificidad (0,1,0) y más tarde
|
|
|
en la cascada, así que dos claves acuñadas sobre declaraciones que la receta
|
|
|
YA tenía salieron muertas en el centinela, mientras `color` y `font-size`
|
|
|
del mismo bloque alcanzaban. Traducción operativa: **hasta que firmes, no
|
|
|
acuñes `font-family` ni `line-height` en ninguna superficie `overlay`** —
|
|
|
miente.
|
|
|
1.bis **La familia text-effects ACUÑA tipografía propia contra el canon**
|
|
|
(autor, 2026-08-22: «¿qué sentido tiene que text-effects introduzca
|
|
|
diferentes nombres de tipografía cuando ya hay un canon establecido?»).
|
|
|
**Siete claves en CUATRO de los cinco** (medido al adjudicar
|
|
|
`text-scramble`): `text-focus.word-size` (3rem, vía el fantasma
|
|
|
`--font-size-4xl`) y `word-weight` (900) · `text-circular.weight` (900) y
|
|
|
`font-size` (1.5rem) · `text-gradient.font-weight` (500, subida el 22) ·
|
|
|
`text-scramble.font` y `.size` (sin declarar). La de `text-scramble`
|
|
|
apunta además a `--font-mono`, que NO existe: pinta `ui-monospace` e
|
|
|
**ignora la mono del tema**. `text-blur` es el único limpio: hereda.
|
|
|
Son opiniones del seed react-bits convertidas en contrato por «valor
|
|
|
verbatim». Doctrina F2-B regla 2: una receta CONSUME la capa tipográfica
|
|
|
(`--style-*`) o HEREDA (`link` → `inherit`); un tratamiento de pintura
|
|
|
sobre texto real no tiene tipografía propia (un TextGradient dentro de un
|
|
|
`h1` ES un h1). **Resolución propuesta**: retirar las cinco claves y
|
|
|
heredar; mueve defaults (TextFocus deja de imponer 3rem/900, TextGradient
|
|
|
deja de forzar 500) → firma. Con ello muere el fantasma `4xl`. El módulo
|
|
|
de tipografía NO se toca. Registrado en next-features §13.
|
|
|
2. **El harness del sitio tapa a `code-block` y `code`**: `[data-uix-docs] pre`
|
|
|
pisa SIETE propiedades del `<pre>`, y `[data-uix-docs] code` el radio del
|
|
|
inline. Acotarlo toca el CSS que sirve a ~162 páginas — §13.
|
|
|
3. **El censo no distingue «0 % por deuda» de «0 % POR NATURALEZA»** (cinco
|
|
|
componentes ya). Sin una clase `structural`, **el gate de F3 es
|
|
|
inalcanzable por construcción** — §13.
|
|
|
4. **El velo derrama sobre el subárbol entero en `tree-view`** (`archetype:
|
|
|
'item'` en el `<li>` branch: 336 px velados en vez de 36) — §12.8, morfo.
|
|
|
5. **La selección de fila de `grid-list` nunca ha pintado** (soma estampa
|
|
|
`data-state`, no `data-selected`) — §13, morfo.
|
|
|
6. **El borde de foco de `textarea` sólo se ve con Tab**: hover (0,4,0) >
|
|
|
foco (0,3,0) > invalid (0,2,0) — §13.
|
|
|
7. **CUATRO canónicos sin demo propia** (404): `picker-shell`, `mockup`,
|
|
|
`surface` y `audio-player`. Sin ruta no hay sonda ni guard, y el guard
|
|
|
**miente en verde-rojo**: sobre una página vacía reportó 0/25 para surface,
|
|
|
incluido un `radius` vivísimo. Los tres medibles se apuntaron a la ruta donde
|
|
|
SÍ se renderizan; `mockup` sigue sin poder medirse — §13.
|
|
|
8. Extender la clase `system` del censo a las **capas compartidas** (viene de
|
|
|
antes de esta sesión).
|
|
|
11. **Dos reglas que el navegador DESCARTA**: `onion-menu.css` y
|
|
|
`timeline.css` escriben `:global(svg)` en un CSS PLANO, donde el selector es
|
|
|
inválido. El glifo del onion computa 14px en vez del 70 % que la regla cree
|
|
|
pintar. Arreglarlo mueve píxel en los dos — §13.
|
|
|
10. **⚠⚠ LA CASCADA DE PALETA ANULA LOS TONOS DEL COMPONENTE — 419 claves
|
|
|
públicas** (medido 2026-08-23 en `button`, `badge` y `callout`). El forward
|
|
|
emite un bloque por tono y, AL FINAL, uno genérico `[data-{c}][data-color]`
|
|
|
que resuelve desde el `--palette-*` global; misma especificidad (0,2,0), gana
|
|
|
el último. `--{c}-risk-solid` no mueve nada; `--palette-solid` y
|
|
|
`--color-risk-solid` en el nodo sí. **49 recetas** emiten ese bloque. El
|
|
|
arreglo cabe en el ORDEN DE EMISIÓN y no movería un píxel, pero cambia el
|
|
|
contrato de la jaula del color → §13. **Es la más gorda del eje.**
|
|
|
9. **El eje `size` del `color-picker` muere en el portal** (2026-08-23): la
|
|
|
anchura del panel está cableada al paso `md`
|
|
|
(`--_color-picker-content-width` se declara tres veces y no lo consume
|
|
|
nadie) y el tamaño de las muestras DENTRO del panel también. Un picker
|
|
|
`sm` y uno `lg` abren el mismo panel de 344 px. El arreglo es una escala
|
|
|
por talla en el ámbito del CONTENIDO —que sí lleva su `data-size`—; mueve
|
|
|
píxel en `sm` y `lg` → §13. **Ley general: el portal es una frontera de
|
|
|
cascada; un privado declarado en la raíz no la cruza.**
|
|
|
|
|
|
## EL PROTOCOLO, EN CORTO (el largo está en PLAN-theming.md §7)
|
|
|
|
|
|
Un componente = un commit. Por componente:
|
|
|
|
|
|
1. Leer entero: receta, su bloque en `recipes/base.ts`, README de eidos, morfo,
|
|
|
y el veredicto §5 de su ficha.
|
|
|
2. **Sonda ANTES** (`__theming-probe.ts {c} antes.json <url>`).
|
|
|
3. Escribir el contrato en `recipes/base.ts` — **fusionando en el bloque
|
|
|
existente si ya lo hay** (los forwards de paleta THM-2 ya ocupan bloque en
|
|
|
muchos componentes; un segundo bloque con el mismo nombre se descarta EN
|
|
|
SILENCIO).
|
|
|
4. La receta consume los nombres resueltos; **retirar los bloques `[data-size]`
|
|
|
del CSS** — los emite el TSC, y dejarlos vivos hace que el diff dé 0 por la
|
|
|
ruta vieja.
|
|
|
5. `npm run generate:eidos-css`, sonda DESPUÉS, **diff = 0**.
|
|
|
6. Guard R-5.4 (`npm run theming:sentinel -- {c} <url>`) y **adjudicar cada
|
|
|
«no effect» uno a uno EN EL LEDGER**
|
|
|
(`scripts/theming-sentinel-exceptions.ts`, una razón medida por token) —
|
|
|
el guard falla con un muerto sin adjudicar, y avisa de excepciones STALE.
|
|
|
7. Guards: censo `--only {c}` · `component-audit --only {c}` · `eidos-lint {c}`
|
|
|
· `vitest run src/uix/eidos` (comparar POR FICHERO: el rojo conocido es
|
|
|
`skin-media-player`) · `rtl:check` · `docs:check` · `npm run check`
|
|
|
atribuido POR FICHERO (73 errores globales son de otras sesiones).
|
|
|
8. README del componente con su sección «Talla y tema».
|
|
|
9. **Tab `Tokens` en la demo** — una línea:
|
|
|
`<TokensPanel component="x" stage={stageRef ?? undefined} />` + su botón.
|
|
|
10. Commit con las cifras y los artefactos en el mensaje.
|
|
|
|
|
|
## LO QUE F2-B ENSEÑÓ (2026-08-22 — léelo antes de tocar nada)
|
|
|
|
|
|
**Un alcance bajo puede ser doctrina bien aplicada, no deuda.** `menu-dial`
|
|
|
25 % porque sus ejes de colocación son de la capa `viewport-placement` y la
|
|
|
receta escribe en sus RANURAS DE OVERRIDE; `link` 36 % porque sus escotillas
|
|
|
caen en `inherit`, que es semántico (el enlace toma la tipografía del párrafo);
|
|
|
`scroll-frames` 33 % porque es layout puro. **El % no es la métrica de
|
|
|
calidad** — lo que importa es que lo que queda fuera esté MEDIDO y escrito.
|
|
|
|
|
|
**Cuatro clases que se repiten, con su veredicto ya fijado:**
|
|
|
|
|
|
1. **Un privado con DOS fuentes es un conmutador, no deuda.** Cinco casos
|
|
|
(`textarea`, `spinner`, `skeleton`, `code`, `label`): aplanarlo obligaría a
|
|
|
duplicar cada regla por color. Se queda privado y se adjudica.
|
|
|
2. **Lo que la capa tipográfica posee NO se acuña** (`--style-*`): cinco casos
|
|
|
(`code-block`, `kbd`, `announce`, `code`, `label`).
|
|
|
3. **Un forward de paleta THM-2 leído a pelo** no admite público sin duplicar
|
|
|
la regla.
|
|
|
4. **Identidad ≠ knob**: `100%`, `50%` de un círculo, `line-height: 1` de una
|
|
|
tecla, `transparent` de una variante ghost.
|
|
|
|
|
|
**La propuesta §4 generada FALLA de tres maneras distintas**, y las tres
|
|
|
costaron medición:
|
|
|
|
|
|
- **Hereda el incumplimiento del CSS de partida**: copia el valor verbatim, así
|
|
|
que si ya violaba `recipe-css-contract` (primitivo crudo en vez del bundle),
|
|
|
la propuesta lo repite. Lo cazó la suite en `code-block`.
|
|
|
- **Infla hasta 4×**: en `spinner` pedía **71 tokens para 23 knobs**,
|
|
|
multiplicando UNA coordenada de talla por variante × parte × dimensión —
|
|
|
veinte claves con el mismo valor.
|
|
|
- **Nombra por el primer selector de la regla**, no por el nodo pintado: en
|
|
|
`tree-view` llamaba `root-width` / `root-bg` a la GUÍA de indentación, y
|
|
|
fundía en un solo nombre el `padding-inline` de la fila y el paso de
|
|
|
profundidad, que se SUMAN en el mismo `calc`.
|
|
|
|
|
|
**El instrumento estándar no ve tres clases de componente**, y una sonda que
|
|
|
compara pocos nodos pasa en falso: panel portalado que abre en hover
|
|
|
(`link-preview`: 1 nodo), componente sin demo propia y con partes de nombre
|
|
|
genérico (`picker-shell`: **0 nodos**), y parte que sólo existe durante una
|
|
|
interacción (el fantasma de `drag-drop`, el indicador de `clipboard`, el rótulo
|
|
|
de `scroll-frames`). **Cuenta siempre los nodos que ve la sonda antes de creerte
|
|
|
un gate en verde.**
|
|
|
|
|
|
**El guard R-5.4 ganó SEIS capacidades en este bloque**, todas nacidas de una
|
|
|
medición y con los del ledger re-verificados sin regresión tras cada una:
|
|
|
puntero parqueado tras el blur (`reopen()` corre antes de CADA token), lectura
|
|
|
de `::placeholder` (la nota de §13 que decía que no se podía era falsa),
|
|
|
`COMPONENT_OVERRIDES` de prefijo de atributo y selector de apertura, apertura
|
|
|
por `hover`, y `text-decoration-thickness` / `-underline-offset` en la lista de
|
|
|
propiedades.
|
|
|
|
|
|
**Y dos errores de proceso que costaron tiempo:**
|
|
|
|
|
|
- **El guard de claves duplicadas del handoff inspeccionaba el VACÍO**:
|
|
|
`grep -E` lee ` ` como una `t` literal — 0 coincidencias sobre 130 bloques.
|
|
|
Corregido más abajo con una versión que CUENTA.
|
|
|
- **`$?` tras una tubería es el del último comando**, no el del guard: un
|
|
|
fichero de excepciones con sintaxis inválida pasó por bueno. Comprueba el
|
|
|
exit REAL.
|
|
|
|
|
|
## LO QUE F2-A ENSEÑÓ (léelo antes de tocar nada)
|
|
|
|
|
|
**Sobre los veredictos.** Tres de ocho tenían un error de lectura que sólo
|
|
|
apareció midiendo: el título de `feed` escala por `aria-level`, **no por
|
|
|
talla**; `--gp-current-gradient` lo estampa **soma**, no el wrapper de eidos; y
|
|
|
el trigger de `gradient-picker` no había que tokenizarlo sino **borrarlo**. El
|
|
|
veredicto orienta; la medición decide.
|
|
|
|
|
|
**Un token que no mueve nada es un token que miente.** Ocurrió tres veces:
|
|
|
`table.selected-row-fg` y la tinta de `listbox` (el arquetipo las gana por
|
|
|
especificidad) y **el cromo ENTERO del trigger de `gradient-picker`** (36 de 45
|
|
|
tokens sin efecto — lo pinta `popover.css`, que gana 0,2,0 contra 0,1,0). En
|
|
|
los tres casos la acción correcta fue **retirar la declaración muerta**, y en
|
|
|
los tres retirarla dio 0 diffs, que es la prueba de que estaba muerta.
|
|
|
|
|
|
**Un alias puro no se renombra: se borra.** Los dieciséis `--_mp-*` de
|
|
|
media-player eran alias de su propia fuente; el veredicto pedía renombrarlos y
|
|
|
lo que procedía era eliminar la capa entera.
|
|
|
|
|
|
**Lo que la capa posee, el consumidor no lo acuña.** `listbox` se queda en 68 %
|
|
|
a propósito: su ritmo de fila es de `list-surface`. La métrica penaliza hacer lo
|
|
|
correcto — registrado en `next-features.md` §13.
|
|
|
|
|
|
**Antes de acuñar un `hover-*`, mide contra la capa de estado.** En `listbox` el
|
|
|
`highlighted` pinta DOS veces (plano + velo); se dejó sin token para no
|
|
|
bendecir un duplicado condenado.
|
|
|
|
|
|
**La sonda miente de tres maneras distintas**, y todas costaron tiempo aquí:
|
|
|
congela `transition` pero **nunca `animation`**; el estado `hover` se mide
|
|
|
**después** de forzar tallas, así que arrastra la última; y un empate de
|
|
|
especificidad **resuelto por orden de carga** hace que `tree-grid` dé 0 ó 3
|
|
|
diffs según la recarga. **Ante un diff inesperado, lo primero es correr la
|
|
|
sonda dos veces sobre el MISMO código.** La revisión adversarial encontró y
|
|
|
arregló la causa del caso `feed` (2026-08-21): no era una animación sin
|
|
|
localizar sino la demo aún CARGANDO — el auto load-more mantiene `[data-busy]`
|
|
|
~3 s y la firma sema `commit-settle` anima `box-shadow` sobre el nodo medido.
|
|
|
Sonda y guard esperan ahora a que `[data-busy]` caiga; con eso, dos corridas
|
|
|
del mismo código dan 0 diffs. Y el «falso negativo sin causa» de
|
|
|
`command.input-border` también tenía causa: el centinela ABRÍA haciendo clic
|
|
|
en el input, y un clic de ratón sobre un input de texto SÍ casa
|
|
|
`:focus-visible` — la regla de foco pintaba el borde y el token de reposo
|
|
|
leía muerto. El instrumento viejo acumulaba **22 falsos negativos de 26**;
|
|
|
las tres causas están arregladas en `theming-sentinel.ts`.
|
|
|
|
|
|
## LAS INCIDENCIAS NO SE ARREGLAN AQUÍ
|
|
|
|
|
|
Todo lo que este eje destapa y no le toca arreglar está en
|
|
|
[`docs/next-features.md`](../next-features.md) **§12** (el contrato de cascada
|
|
|
del velo de estado: 131 declaraciones-atajo en 45 componentes, la prop
|
|
|
`hoverable` que no suprime nada, el empate por orden de carga, la banda que
|
|
|
mata el hover, el token de tinta que no puede ganar al arquetipo, el thumb de
|
|
|
`scroll-area` sin velo) y **§13** (huecos de instrumento y de demo, más los
|
|
|
cuatro que salieron de `gradient-picker` y `listbox`).
|
|
|
|
|
|
**Regla**: si una incidencia mueve píxel o toca morfo, se MIDE, se anota ahí y
|
|
|
se sigue. No se arregla dentro del commit del componente.
|
|
|
|
|
|
## PENDIENTE DE FIRMA (nada bloquea la cola)
|
|
|
|
|
|
- **Diseño de `calendar-surface`** — la firma 1 aprobó el PATRÓN, no un diseño
|
|
|
concreto; ese se presenta.
|
|
|
- **`scroll-area.thumb-bg-hover`** — único knob de la firma 3 sin resolver: su
|
|
|
thumb lleva `archetype: 'thumb'`, que no recibe velo. Cambiarlo es morfo.
|
|
|
- **Extender la clase `system` del censo a las capas compartidas**, como se
|
|
|
hizo con `--style-*` para los primitivos tipográficos (§13 del registro).
|
|
|
- ~~El `striped` de `table` inerte con RowDetail~~ — **FIRMADO Y EJECUTADO
|
|
|
2026-08-21**: `:nth-child(even of [data-table-row])` con
|
|
|
`:where(:not([data-selected]))`, mismo (0,6,0) para no matar el hover.
|
|
|
12 diffs exactos (2 filas × 6 estados); selected y hover verificados.
|
|
|
- **El arquetipo `item` de `table` vive en la fila Y en la celda** — el velo
|
|
|
cae en la celda bajo el puntero (`elementsFromPoint`, 2026-08-21). La
|
|
|
decisión de morfo del `hoverable` (§12.2) debe contemplar los dos
|
|
|
portadores.
|
|
|
- **Que soma lea de un token el gap entre diapositivas de `carousel`** — hoy
|
|
|
es canal de valor inline y el trío `item-gap*` se retiró muerto; darle
|
|
|
superficie de tema toca soma (§13).
|
|
|
|
|
|
---
|
|
|
|
|
|
# REGISTRO DE LA SESIÓN DEL 2026-08-20/21 (histórico — no es la agenda)
|
|
|
|
|
|
## EJECUTADO 2026-08-21 — la capa `calendar-surface` (firmada y medida)
|
|
|
|
|
|
**La medición cambió el encargo.** El handoff la vendía como «una capa nueva,
|
|
|
~220 knobs, 43 % → ~48 %». No lo era: la capa **ya existía de hecho**, sin
|
|
|
nombre ni casa. `--calendar-*` se emite en `:root` (76 claves) y sus
|
|
|
consumidores **no acuñan NADA** — `range-calendar` 114 referencias prestadas y
|
|
|
0 propias, `month-grid` 77/0, `year-grid` 77/0, y lo único ajeno que leen es
|
|
|
sistema puro (`--focus-ring-*`, `--state-hover`). Su 0 % era el artefacto de
|
|
|
`listbox` (§13) pero TOTAL.
|
|
|
|
|
|
**Lo que se escribió**: `lib/calendar-surface.css` con el hook
|
|
|
`data-calendar-surface`, cuatro coordenadas por talla (`padding`,
|
|
|
`control-size`, `day-size`, `font-size`, xs..lg — la familia **no tiene xl**, y
|
|
|
la celda va DOS pasos por debajo del bundle de control, deviación que ahora se
|
|
|
lee en un sitio en vez de esconderse en cuatro bloques `[data-size]` idénticos)
|
|
|
y la FORMA del anillo de evento. El vocabulario **se queda en la entrada
|
|
|
`calendar` de la receta**, que pasa a ser la de la FAMILIA: ésta es una capa
|
|
|
HÍBRIDA y es lo que la distingue de `list-surface` / `viewport-placement`, que
|
|
|
componen primitivos y no tienen entrada de receta (76 claves semánticas tienen
|
|
|
que seguir siendo alcanzables una a una por config).
|
|
|
|
|
|
**El defecto que la justificó, medido**: `--calendar-event-shadow` y
|
|
|
`--calendar-day-holiday-shadow` se emitían con ámbito `[data-calendar]` y los
|
|
|
otros tres los leían desde hosts que nunca llevan ese atributo → variable
|
|
|
VACÍA, `box-shadow` inválido en computed, **el anillo sema no pintaba jamás en
|
|
|
tres componentes**. Ahora la forma vive en la capa y el acento entra por
|
|
|
`--_calendar-surface-accent`, que cada superficie alimenta con su forward de
|
|
|
paleta THM-2.
|
|
|
|
|
|
⚠️ **Lo que casi se me cuela, y la lección**: estampar el hook sólo en los
|
|
|
cuatro wrappers standalone dejaba a `DatePicker` y `DateRangePicker` con
|
|
|
`--calendar-padding` VACÍA y el panel a padding 0 — renderizan la superficie
|
|
|
soma por sus PROPIOS wrappers (`date-picker-calendar`, `-month-view`,
|
|
|
`-year-view`, `date-range-picker-calendar`) y un panel portalado no hereda
|
|
|
nada. **Son SIETE wrappers, no cuatro.** La tentación era enganchar la capa a
|
|
|
las cuatro identidades de componente; eso viola la regla 1 de capas
|
|
|
compartidas, y la respuesta correcta es un sello por wrapper.
|
|
|
|
|
|
**El censo aprendió a no penalizar**: `LAYER_VOCABULARY` en
|
|
|
`theming-census.ts` (mismo precedente que D-TH.2-b con `--style-*`). Global
|
|
|
43 % → **45 %**, `calendar` 75 % → **84 %**. Los tres consumidores **siguen
|
|
|
leyendo 0 %**, y es honesto: con el vocabulario de la capa fuera del
|
|
|
denominador sólo les quedan los forwards de paleta THM-2 (que el censo cuenta
|
|
|
como `private` en TODO el catálogo) y literales de layout. Reclasificar el
|
|
|
forward de paleta es la misma pregunta un piso más abajo — anotada en §13.
|
|
|
`list-surface` NO se registró: sus consumidores puentean por privados, otra
|
|
|
forma, y mueve diez componentes de golpe.
|
|
|
|
|
|
## EJECUTADO 2026-08-21 — revisión adversarial de F2-A (§7.7) + guard R-5.4
|
|
|
|
|
|
Molde Sidebar, medición propia contra worktree con solo el CSS revertido a la
|
|
|
base del bloque. **34 hipótesis · 26 refutadas · 8 reales.** Refutado: el
|
|
|
«default idéntico» aguanta en los ocho (0 diffs; los 3 de tree-grid y los 5 de
|
|
|
feed son del instrumento, idénticos corriendo dos veces el mismo código), 0
|
|
|
tokens huérfanos de 336, el bundle ES 1:1 con los primitivos, el «verificado a
|
|
|
mano» de gradient-picker era verdad. Los 8 reales: **(1)** el re-point de
|
|
|
`--command-radius` en el Dialog era declaración muerta con comentario falso —
|
|
|
retirado, 0 diffs; **(2)** el `2.25` vertical del carrusel iba a pelo y
|
|
|
`active-indicator-scale` solo alcanzaba la horizontal — tokenizado, 0 diffs;
|
|
|
**(3)** el trío `item-gap*` de carousel no podía ganar al `gap` INLINE de soma
|
|
|
— retirado, 0 diffs (canal de valor, como `--gp-current-gradient`); **(4)** el
|
|
|
`striped` de table es inerte con RowDetail (parity de `:nth-of-type`) —
|
|
|
PENDIENTE DE FIRMA; **(5-7)** el instrumento tenía 22 falsos negativos de 26
|
|
|
(clic-foco en el input · override solo en `[data-{c}]` · pseudos invisibles) y
|
|
|
la no-determinación de feed era la demo cargando (`commit-settle` sobre
|
|
|
`[data-busy]`) — las cuatro causas arregladas en `theming-sentinel.ts` y la
|
|
|
sonda; **(8)** tres cifras de especificidad del registro §12 estaban desviadas
|
|
|
en uno y el arquetipo de la fila de table vive TAMBIÉN en la celda —
|
|
|
corregidas. **R-5.4 nace**: `npm run theming:sentinel -- <c> <url>`, ledger
|
|
|
`theming-sentinel-exceptions.ts` con una razón medida por token (46
|
|
|
excepciones en los ocho, cinco entradas mías salieron STALE y las borró el
|
|
|
propio guard), doctrina en recipe-contract §4. Dos hallazgos los produjeron
|
|
|
los propios arreglos: el blur apaga `focus-input-border` (adjudicado) y la
|
|
|
espera de asentado desmonta el spinner de feed (adjudicado). Censo tras la
|
|
|
retirada: carousel 35 knobs · 23 públicos · 77 % · 27 claves; global 43 %
|
|
|
intacto.
|
|
|
|
|
|
Lo que sigue es el detalle de cómo se llegó aquí: las firmas, el codemod, el
|
|
|
guard, y el bloque componente a componente. Se conserva porque cada decisión
|
|
|
lleva su porqué medido, pero **la agenda es lo de arriba**.
|
|
|
|
|
|
## EJECUTADO 2026-08-20 — vocabulario de tokens: D-TH.6 (codemod) + R-5.3 (guard)
|
|
|
|
|
|
**Por qué antes que nada** (conversación 2026-08-20): el canon de nombres
|
|
|
existe (theming §6.7 slots + recipe-contract §1 dimensionales) pero **no tiene
|
|
|
guard**, y la medición del 2026-07-01 ya demostró que canon sin guard deriva
|
|
|
30-85 %. Está derivando: el backfill de ayer escribió la forma DOCUMENTADA
|
|
|
(modificador delante, 36 claves) mientras el catálogo habla al revés — cada
|
|
|
componente que se corrija sin firmar esto ensancha la brecha. El guard de
|
|
|
eventos (`eidos-event-vocabulary.ts`) es el precedente: nació de un
|
|
|
`commit-resize` muerto tres meses en una receta; R-4.4 es el otro (una regla de
|
|
|
nombres ya guardada, deuda muerta «en el mismo pass, sin allowlist»).
|
|
|
|
|
|
**FIRMADO 2026-08-20 — el slot de tinta es `fg`; `color` como slot MUERE.**
|
|
|
La sesión del 20 leyó lo que la del 19 no había leído (`arts/color`,
|
|
|
`architecture/eidos.md` entero, motion §17, §25/§38) y encontró que la
|
|
|
pregunta central no era «normalizar hacia lo documentado» sino una
|
|
|
CONTRADICCIÓN entre dos doctrinas: theming §6.7 r7 (`fg`) contra el principio
|
|
|
de plataforma del px/py («el token se llama como la propiedad»: `color`). El
|
|
|
autor adjudicó **`fg`**: el principio de plataforma gobierna los ejes
|
|
|
DIMENSIONALES, no la pareja `bg`/`fg` (si la gobernara, `bg` sería
|
|
|
`background-color`); `color` es la palabra más sobrecargada del sistema
|
|
|
(`--color-*`, `data-color`, 9 roles, `arts/color`); `on-fg` compone; Chakra
|
|
|
v3/Panda hablan la pareja.
|
|
|
|
|
|
**Inventario CORREGIDO 2026-08-20** (instrumental: los `scripts/__names-*.ts`
|
|
|
de esta sesión — `census`, `slots`, `owners`, `audit7`, `audit7b`; el exacto y
|
|
|
regenerable lo produce `--names` en el paso 1). Sobre **3.333 claves públicas**,
|
|
|
**301 desviadas en 66 componentes** — 193 con `color` como slot, 78 con el
|
|
|
modificador DETRÁS a nivel de receta, 30 con ambas. La semilla
|
|
|
`__names-inventory.ts` decía 370 porque contaba como desviadas **47 claves
|
|
|
`{rol}-{slot-de-rol}` que son CANÓNICAS** (`button.primary-solid-hover`,
|
|
|
`toggle.palette-hover`… — `COLOR_ROLE_SLOTS` pone el modificador detrás POR
|
|
|
CONSTRUCCIÓN) — un codemod sobre las 370 las habría roto. Adopción viva:
|
|
|
196 `-color` contra 55 `-fg` (las `fg` son mayormente las del backfill de este
|
|
|
eje). Peores: tag-group 22 · toast 15 · field 13 · calendar 13 · tabs 12.
|
|
|
**Tres familias, tres gramáticas** (el guard codifica las tres): rol/paleta =
|
|
|
modificador DETRÁS (canon) · sistema (`--state-hover`, `--opacity-hover`) =
|
|
|
detrás, fuera del alcance del guard · recipe-level = §6.7 r7 (delante:
|
|
|
`hover-bg`, 13 claves conformes contra 22 `bg-hover`).
|
|
|
|
|
|
**Falsos amigos (22) — FIRMADOS en el acta**: `*-focus-ring-color` (3, espeja
|
|
|
la familia del SISTEMA) · `aura.orb-color-*` (6, color como sustantivo del
|
|
|
orbe) · `gradient-builder.stop-color-*` (4, **stop-color ES la parte** —
|
|
|
verificado: `gradient-builder-stop-color.svelte` + parts DOM) → **se quedan** ·
|
|
|
los 7 con modificador «fuera de vocabulario» resultaron ser DOS clases que el
|
|
|
morfo ya resuelve (valores de `data-state`/ejes declarados: `active`, `partial`,
|
|
|
`read`, `failed`; y `current` = aria, que entra al vocabulario universal) más
|
|
|
una de pseudo-partes (`played`/`buffered`) → **se renombran** (destinos en el
|
|
|
acta) · `background.scrim-color-on-{dark,light}` (2, chocaban con el prefijo
|
|
|
`on-`) → **`scrim-fg-over-{dark,light}`**.
|
|
|
|
|
|
**Hovers neutros — firmado: NO se renombran, MIGRAN**: §38 + R-4.3 deprecan el
|
|
|
hover neutro por componente (es la capa `--state-*`). `dropdown-menu.item-bg-hover`,
|
|
|
`context-menu.item-bg-hover`, `scroll-area.track/thumb-bg-hover`,
|
|
|
`splitter.handle-bg-hover`… la firma 3 del acta ordena su migración a la capa
|
|
|
de estado (captura + diff explicado por componente). El codemod los EXCLUYE y
|
|
|
el `--names` los lista aparte como cola de esa migración.
|
|
|
|
|
|
**LOS CUATRO PASOS ESTÁN HECHOS** (`f09e04fab` acta · `bd916ef3f` codemod ·
|
|
|
`7781d6e4c` guard + doctrina, sin pushear). Lo que queda del bloque, y sólo
|
|
|
esto:
|
|
|
|
|
|
- **El tercer muro espera a la firma 3.** El tipo en `defineRecipes` (molde
|
|
|
`PhysicalAxisKey`) está escrito y probado: dispara sobre **17 claves**, que
|
|
|
son los hovers neutros con `color` en cola de migración. Meterlo hoy rompe
|
|
|
`npm run check` a todo el mundo. Entra cuando la migración las vacíe — dos
|
|
|
líneas: una rama `ColorSlotKey` y las tres excepciones firmadas
|
|
|
(`*focus-ring-color`, `orb-color-*`, `stop-color-*`) deletreadas.
|
|
|
- **`__names-inventory.ts` quedó superado** por `theming-census --names`
|
|
|
(contaba 370 porque metía las 47 role-slot). No se borra sin que lo digas.
|
|
|
|
|
|
El registro de los pasos, para quien audite después:
|
|
|
|
|
|
Los pasos, en orden y con su gate (**el paso 0 murió el 2026-08-20: D-TH.6
|
|
|
está firmada COMPLETA** — ver §«Firmas del 2026-08-20»; la gramática ejecutable
|
|
|
es: slot `fg` · delante lo interactivo, detrás lo dimensional/contextual ·
|
|
|
modificador ∈ universal (+`current`) ∪ `data-state`/ejes del morfo · rol/paleta
|
|
|
detrás · hovers neutros excluidos · renombres nominales de los ex-falsos
|
|
|
amigos en el acta):
|
|
|
|
|
|
1. **`--names` en el censo**: el inventario exacto por clase de desviación,
|
|
|
regenerable, con las 47 role-slot reconocidas como canónicas, los falsos
|
|
|
amigos resueltos por el acta (los 3 grupos que se quedan excluidos; los 4
|
|
|
renombrados contados como desviación con su destino) y los hovers neutros
|
|
|
listados APARTE (van a la firma 3, no al codemod). Muta-prueba del
|
|
|
instrumento: 3 desviadas conocidas salen, 3 role-slot NO salen.
|
|
|
2. **Codemod value-preserving** (molde: px/py del 2026-07-06 y su triple muro):
|
|
|
`-color` → `-fg` (196 + 49 mediales, menos los 3 grupos que el acta deja
|
|
|
quedarse y los hovers neutros que migran aparte), los renombres nominales
|
|
|
del acta (rating-group · chat-message · breadcrumb · waveform ·
|
|
|
`scrim-fg-over-*`), y modificador detrás → delante a nivel receta
|
|
|
(`bg-hover` → `hover-bg`, 22 claves); renombra la clave
|
|
|
en `recipes/base.ts` Y todos los consumidores (`var(--{c}-{clave})` en
|
|
|
css/svelte/ts/md — con `git ls-files`, no de memoria; los .md de HISTORIA
|
|
|
— changelog, errores-toxico, PLAN-affix/background — NO se reescriben),
|
|
|
regenera, y verifica: diff de `generated/` = **renombres 1:1**,
|
|
|
censo global IDÉNTICO (un rename no cambia alcance), sonda de computed en 3
|
|
|
componentes renombrados = **0 diffs**. Un commit, script commiteado como
|
|
|
registro.
|
|
|
3. **Guard R-5.3 en `component-audit`** — de **GRAMÁTICA**, no de lista (a
|
|
|
diferencia del de eventos, que valida pertenencia a un vocabulario cerrado),
|
|
|
y POR FAMILIA: `{rol|palette}-{slot-de-rol}` con modificador detrás
|
|
|
(`COLOR_ROLE_SLOTS`) ∪ recipe-level
|
|
|
`[variante-]?[modificador-]?[parte-]?[slot][-talla]?` donde talla ∈ las 7
|
|
|
canónicas, modificador ∈ vocabulario cerrado y DELANTE, slot ∈ (§6.7
|
|
|
recipe-level ∪ ejes dimensionales de recipe-contract §1), y la PARTE contra
|
|
|
`compileMorfo(morfo).parts` + la allowlist eidos-only (el mismo criterio que
|
|
|
`eidos-lint`). Severidad **`error` directo**: tras el codemod no hay deuda
|
|
|
que tolerar, y la rampa `warn` es como estos guards mueren. **Muta-prueba
|
|
|
obligatoria de tres caras** antes de darlo por bueno: `-bg-hover` rojo ·
|
|
|
`trigger-color` rojo · `primary-solid-hover` VERDE (memoria
|
|
|
`a-guard-that-inspects-nothing-passes`).
|
|
|
4. **Docs en el mismo pass**: recipe-contract §1 gana la fila del modificador
|
|
|
(hoy sólo la insinúa §6.7) y §4 la fila R-5.3; theming §6.7 nota fechada
|
|
|
con la firma de `fg` y el acotamiento del principio de plataforma a los
|
|
|
ejes dimensionales; T-TH.2 del plan se cierra.
|
|
|
|
|
|
Gates del bloque entero: censo global idéntico antes/después del codemod ·
|
|
|
suite eidos sin rojos nuevos · `component:audit` sin fallos nuevos fuera de
|
|
|
R-5.3 · `docs:check` 0 · `rtl:check` 0.
|
|
|
|
|
|
## Después — por dónde seguir
|
|
|
|
|
|
1. `node --import tsx/esm scripts/theming-census.ts` — debe dar **162 recetas ·
|
|
|
5.203 knobs · 1.841 públicos (37 %) · 56 sin contrato** (antes del codemod;
|
|
|
tras él, el MISMO alcance con nombres nuevos). Si no cuadra, alguien tocó
|
|
|
recetas: regenerar el informe (`--report`) antes de nada.
|
|
|
2. Abrir la ficha del componente que toque y leer su **§5 Veredicto**: dice qué
|
|
|
de la propuesta es correcto, qué está mal y qué espera firma. Está verificado
|
|
|
contra el CSS; la §4 generada NO se sigue a ciegas. **Ojo**: los veredictos
|
|
|
se escribieron ANTES del acta del 2026-08-20 — sus «espera firma» se cruzan
|
|
|
con §«Firmas del 2026-08-20» (la mayoría ya están resueltos: calendar,
|
|
|
Field, hover→estado, D-TH.2) y sus nombres propuestos se pasan por la
|
|
|
gramática firmada (p. ej. el `guide-color` de la fila tree-grid de la cola
|
|
|
es `guide-fg`).
|
|
|
3. Ejecutar con el protocolo §7 entero. **Un componente = un commit.**
|
|
|
|
|
|
## PRIMERA POSICIÓN — repaso de los 7 ya corregidos contra la gramática nueva
|
|
|
|
|
|
Encargo del autor (2026-08-20): revisar lo ya ejecutado por si incumple las
|
|
|
reglas nuevas. **Auditados los 7 con `scripts/__names-audit7.ts` y
|
|
|
`__names-audit7b.ts`** (claves públicas + privados + consumo en css/README).
|
|
|
Resultado: **6 de 7 limpios, 1 hallazgo real**.
|
|
|
|
|
|
| componente | claves | veredicto |
|
|
|
| --------------------- | -----: | ----------------------------------------------------------------- |
|
|
|
| `combobox` | 106 | ✅ limpio — ya habla `fg`, sin modificador detrás, privados sanos |
|
|
|
| `natural-time-picker` | 62 | ✅ limpio |
|
|
|
| `date-range-picker` | 24 | ✅ limpio |
|
|
|
| `time-range-picker` | 22 | ✅ limpio |
|
|
|
| `proof-of-human` | 20 | ✅ limpio |
|
|
|
| `time-picker` | 16 | ✅ limpio |
|
|
|
| `gradient-builder` | 72 | ⚠ **1 corrección** (abajo) |
|
|
|
|
|
|
Que los 6 salgan limpios NO es casualidad ni suerte: el backfill de este eje
|
|
|
venía escribiendo `fg` (55 de las ~55 claves `-fg` del catálogo son suyas),
|
|
|
que es exactamente lo que la firma ratificó. La firma **valida** el trabajo
|
|
|
hecho, no lo invalida.
|
|
|
|
|
|
**La corrección — `gradient-builder.checker-color` → `checker-fg`** (1 clave,
|
|
|
consumida 4 veces en `gradient-builder.css:29-32`). Es el color de los cuadros
|
|
|
del damero de transparencia: `color` ahí es **slot**, no sustantivo — cae de
|
|
|
lleno en la regla firmada. Las otras 4 claves que el audit marca
|
|
|
(`stop-color-title-font-size`, `-font-weight`, `-fg`, `stop-color-sliders-gap`)
|
|
|
son **falso amigo verificado**: `stop-color` es la PARTE
|
|
|
(`gradient-builder-stop-color.svelte`, `[data-gradient-builder-stop-color-*]`),
|
|
|
y una de ellas ya termina en `-fg` correctamente. **No se tocan.**
|
|
|
|
|
|
Ejecución: va DENTRO del codemod del paso 2 (misma mecánica, mismos gates), no
|
|
|
como commit aparte — es una clave, y sacarla del codemod duplicaría la
|
|
|
verificación. Si el codemod se retrasa por las firmas pendientes, se ejecuta
|
|
|
sola con el protocolo §7.
|
|
|
|
|
|
## BLOQUE F2-A — CERRADO 2026-08-21 (preparado el 20, ejecutado el 21)
|
|
|
|
|
|
**Los ocho, con su commit y su alcance final:**
|
|
|
|
|
|
| componente | antes → después | commit |
|
|
|
| ----------------- | --------------: | ----------- |
|
|
|
| pieza 0 (censo) | 37 % → 38 % | `bd032534b` |
|
|
|
| `command` | 0 % → 98 % | `4ddea7fe2` |
|
|
|
| `table` | 0 % → 86 % | `564133b48` |
|
|
|
| `media-player` | 0 % → 88 % | `b7a4cef08` |
|
|
|
| `tree-grid` | 0 % → 95 % | `9748733ad` |
|
|
|
| `gradient-picker` | 0 % → 88 % | `d177ee331` |
|
|
|
| `listbox` | 0 % → 68 % | `3b325c439` |
|
|
|
| `carousel` | 0 % → 77 % | `4cab77667` |
|
|
|
| `feed` | 0 % → 94 % | `34a95a550` |
|
|
|
|
|
|
Global **37 % → 43 %**; sin contrato **56 → 49**; al 100 % **6 → 7**. Más
|
|
|
`90aa6dc5f` (el `TokensPanel` que las demos enseñan) y `8324e2ced` (el registro
|
|
|
de incidencias).
|
|
|
|
|
|
El plan del bloque, tal como se preparó:
|
|
|
|
|
|
El primer bloque del backfill bajo TODAS las firmas. Ocho componentes con
|
|
|
veredicto §5 verificado + una pieza de instrumento que va primero. Suma **330
|
|
|
knobs hoy a 0 %**; al cerrar, el global debe rondar **37 % → ~42 %**. Cada
|
|
|
componente: protocolo **§7 entero**, un componente = un commit, con la
|
|
|
gramática firmada (¡el guard R-5.3 y el muro de tipos ya vigilan!).
|
|
|
|
|
|
**Pieza 0 — el instrumento ANTES del bloque (D-TH.2-b, firmada).** La familia
|
|
|
tipográfica B5 mide su superficie por `--style-*` como sistema transversal: el
|
|
|
censo añade `--style-*` a la clase `system` PARA los primitivos tipográficos
|
|
|
(heading, text, display, code, s-text…), con gate: las cifras de TODOS los
|
|
|
demás componentes quedan idénticas, y `heading` pasa de «36 privados» a su
|
|
|
verdad (consume la capa semántica). Va primero porque cambia el suelo del
|
|
|
censo — hacerla a mitad de bloque falsearía los antes/después.
|
|
|
|
|
|
| # | componente | knobs | defectos medidos (censo + ficha) | corrección firmada por el veredicto |
|
|
|
| ---- | ----------------- | ----: | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
|
| 1 ✅ | `command` | 52 | SIN bloque en `base.ts`; 35 globales · 9 privados sin derivar · 6 literales | contrato entero con talla resuelta (patrón Sidebar); `radius` con la adaptación al Dialog como CONTEXTO (lee un público de dialog, legítimo — no partir en dos); `list-padding-inline` + `scrollbar-inset` (patrón combobox); sonda con el palette ABIERTO |
|
|
|
| 2 | `table` | 46 | 23 privados · 14 globales · 5 literales | `root-height-{k}` es la **fila** → `row-height-{k}` al bundle; el prefijo `root-` sobra en el resto; talla |
|
|
|
| 3 | `media-player` | 45 | 37 globales · 8 literales; privados `--_mp-*` ABREVIADOS (§6 r5 los prohíbe) | renombrar `--_mp-*` al nombre completo (⚠ prettier: la anotación `/* literal: */` en la MISMA línea — trampa de natural-time-picker) + tokens; su acento theme-stable está FIRMADO en `base.ts` — no tocarlo; el ⚠ de `bg` son DOS knobs (superficie y velo) |
|
|
|
| 4 | `tree-grid` | 42 | 29 privados · 8 globales | `root-bg-image` son las **guías de indentación**: el knob es la tinta (`guide-fg` — era `guide-color` pre-acta), los 5 gradientes se quedan en la receta; talla |
|
|
|
| 5 | `gradient-picker` | 38 | privados `--gp-*` ABREVIADOS · 23 globales | renombrar `--gp-*` + tokens; `content-width` es **por talla** (20/18/22rem), no un solo knob |
|
|
|
| 6 | `listbox` | 38 | 23 globales · 9 privados; una fila FALSA en la propuesta | tokens; **retirar** la fila `font-size = var(--list-font-size)`: es público de la capa `list-surface` — un consumidor no acuña lo que la capa posee |
|
|
|
| 7 | `carousel` | 36 | 12 globales · 14 privados · 5 literales | tokens + talla; los `indicator-width-{k}` son geometría propia (rem), ni bundle ni desviación |
|
|
|
| 8 | `feed` | 33 | 16 globales · 13 privados | tokens + talla; el título es **por talla** y el feed tipa por debajo del 1:1 (md → sm), verbatim — no «corregirlo» al 1:1 |
|
|
|
|
|
|
**Cada componente engancha su tab `Tokens` en el MISMO commit** (firmado
|
|
|
2026-08-20, a raíz de que el autor viera que la demo de `command` no enseñaba su
|
|
|
superficie de tema — y resultó que ninguna lo hacía). Es una línea:
|
|
|
`<TokensPanel component="x" stage={stageRef} />` más el botón del tab; el panel
|
|
|
(`web/routes/uix/lib/TokensPanel.svelte`) lee el contrato vivo con
|
|
|
`eidos.getRecipeTokens()`, así que no hay tabla que mantener. Un componente
|
|
|
temable cuya demo esconde sus tokens está a medio entregar.
|
|
|
|
|
|
Gates de cada componente (§7.4/7.5, sin excepciones): censo `--only {c}` al
|
|
|
**100 %** o excepción escrita · sonda antes/después = **0 diffs** · centinela
|
|
|
por token nuevo · `component:audit` PASS (R-5.3 incluida) · `eidos-lint` 0
|
|
|
invalid · suite eidos sin rojos nuevos · `rtl:check` 0 · `docs:check` 0 ·
|
|
|
`check` por fichero · README del componente con la tabla «Talla y tema»
|
|
|
(molde `navigation-menu`). Al cerrar el bloque: **revisión adversarial §7.7**
|
|
|
(molde Sidebar: refutar «idéntico», «alcanza», «píxel arriba» con medición
|
|
|
propia).
|
|
|
|
|
|
**Al cerrar F2-A, lo desbloqueado por las firmas espera en este orden**:
|
|
|
|
|
|
1. **Diseño de la capa `calendar-surface`** (firma 1) — se PRESENTA antes de
|
|
|
escribirla (nombre, ejes, qué posee; molde `list-surface` y sus 4 reglas).
|
|
|
Desbloquea los tres gordos del catálogo: `range-calendar` (98) +
|
|
|
`month-grid` (61) + `year-grid` (61) y media `date-range-picker` — 220
|
|
|
knobs, el salto de ~42 % a ~47 %.
|
|
|
2. **Mandato Field ejecutable** (firma 2) — `field-langs` (41) + las mitades
|
|
|
de `time-picker` / `time-range-picker` / `date-range-picker`.
|
|
|
3. El resto del orden B1-B8 de D-TH.4 (`grid-list` 32 · `textarea` 28 · …).
|
|
|
|
|
|
---
|
|
|
|
|
|
## AL TERMINAR EL EJE ENTERO — partir `recipes/base.ts` por componente
|
|
|
|
|
|
Firmado 2026-08-20, a raíz de la pregunta del autor «¿por qué todos los tokens
|
|
|
viven en un fichero?». **Va al final de TODO el themeable**, no al cerrar un
|
|
|
bloque: mientras quede un componente por tokenizar, ese fichero se toca en cada
|
|
|
commit.
|
|
|
|
|
|
`recipes/base.ts` son **6.223 líneas y 128 componentes**, y NO es un fichero de
|
|
|
tokens: es el valor del campo `recipes` de `EidosConfig`, serializable, que un
|
|
|
tema hidrata. Por eso los valores no pueden mudarse a `components/{x}/` — se
|
|
|
intentó y se retiró (`architecture/eidos.md`: «The old `tokens/components/*`
|
|
|
were retired»). Lo que sí puede repartirse es la AUTORÍA:
|
|
|
|
|
|
```ts
|
|
|
// lib/recipes/table.ts
|
|
|
export const tableRecipe = { 'row-height-md': '…', … };
|
|
|
// lib/recipes/base.ts — el valor sigue siendo UNO
|
|
|
export const THEME_BASE_RECIPE_TOKENS = defineRecipes({ table: tableRecipe, … });
|
|
|
```
|
|
|
|
|
|
**Verificado antes de proponerlo, no supuesto**: el muro de tipos de
|
|
|
`defineRecipes` SIGUE disparando cuando las claves llegan por spread desde un
|
|
|
fichero suelto — probado con `trigger-color` (slot `color`) y `padding-x` (eje
|
|
|
físico), ambas dan error de compilación igual que inline. El único consumidor
|
|
|
sensible a la forma es `eidos-purge.ts`, que hace `Object.keys()` y es
|
|
|
indiferente. `recipe-css-contract`, el censo, R-5.3 y `getRecipeTokens()` leen
|
|
|
el objeto compuesto.
|
|
|
|
|
|
Los tres costes que paga el fichero único, todos medidos en la sesión del
|
|
|
2026-08-20: **casi entra un SEGUNDO bloque `table`** que el catálogo habría
|
|
|
descartado en silencio (la trampa está anotada abajo); **una coma perdida
|
|
|
rompió el catálogo entero dos veces**; y es el punto de conflicto de todas las
|
|
|
sesiones concurrentes. Repartido, un error afecta a un componente.
|
|
|
|
|
|
**Por qué al final y no antes**: son ~6.000 líneas movidas en el fichero que
|
|
|
cada commit del backfill toca. Hacerlo con componentes pendientes garantiza
|
|
|
conflicto con toda sesión que esté tokenizando; con el eje cerrado es un commit
|
|
|
mecánico y aislado.
|
|
|
|
|
|
Gate: `THEME_BASE_RECIPE_TOKENS` **idéntico** antes/después (comparación
|
|
|
ESTRUCTURAL del objeto, no del fichero) · censo global idéntico ·
|
|
|
`generated/base.css` sin un solo cambio · el muro de tipos con su muta-prueba
|
|
|
(las dos claves malas siguen sin compilar).
|
|
|
|
|
|
## FIRMA 3 en ejecución — hover → capa de estado (act. 2026-08-20)
|
|
|
|
|
|
**El diagnóstico cambió al empezar.** La firma decía «migrar los hovers neutros
|
|
|
a la capa de estado». Al hacerlo salió que el velo del sistema **no llegaba a
|
|
|
ninguno**, y no por el hover: por la regla BASE. `archetypes.css` pinta el velo
|
|
|
con `:where(...)`, peso **(0,0,0)**; cualquier receta que declare el ATAJO
|
|
|
`background:` sobre ese mismo nodo fija `background-image: none` con **(0,1,0)**
|
|
|
y lo cancela SIEMPRE — ni en hover ni nunca. El hover propio no era un
|
|
|
capricho: era la cicatriz de un velo que no llegaba.
|
|
|
|
|
|
Así que cada migración son DOS cambios: `background:` → `background-color:` en
|
|
|
la base, y fuera el hover propio.
|
|
|
|
|
|
| componente | commit | medido |
|
|
|
| ------------------- | ----------- | -------------------------------------------------------------- |
|
|
|
| `checkbox` | `b35855c20` | 8 diffs, todos en hover: velo + fondo base (2.436 valores) |
|
|
|
| `splitter` | `c66b73810` | 2 diffs en el asa (812 valores) |
|
|
|
| `switch` | `3219a19c3` | 2 diffs en el track off (377); el swap del checked, verificado |
|
|
|
| `date-range-picker` | `0c80a8efb` | **sin medir el pintado** — la demo no monta `kind` month/año |
|
|
|
|
|
|
**Los 6 knobs de la cola eran 47 hasta que se midió la PROPIEDAD**: el velo es
|
|
|
`background-image`, así que un hover de borde (22) o de tinta (19) no es la
|
|
|
capa de estado, sea cual sea su valor. Esos 41 eran deuda de nombre y se
|
|
|
renombraron (`93017975c`).
|
|
|
|
|
|
### Las incidencias van al registro, no al eje
|
|
|
|
|
|
Todo lo que este eje destapa y NO le toca arreglar está registrado en
|
|
|
[`docs/next-features.md`](../next-features.md) §12 y §13 — con su medición, no
|
|
|
como impresión:
|
|
|
|
|
|
- **§12 · El contrato de cascada del velo de estado.** Seis incidencias que son
|
|
|
la misma: nadie fijó cómo compone el velo de `archetypes.css` con las reglas
|
|
|
de una receta. Incluye las 131 declaraciones-atajo en 45 componentes, la prop
|
|
|
`hoverable` que no suprime nada, el empate (0,5,0) que resuelve el orden de
|
|
|
carga, la banda de `tree-grid` que mata el hover, el token de tinta que no
|
|
|
puede ganar al arquetipo, y el thumb de `scroll-area` sin velo al que migrar.
|
|
|
- **§13 · Huecos de instrumento y de demo.** Lo que hizo que una medición
|
|
|
mintiera o no existiera: falsos negativos del centinela, pseudo-elementos y
|
|
|
componentes compuestos que no ve, la sonda que no pasa el ratón por un `<tr>`,
|
|
|
y la lección general — **una sonda sobre una parte que la demo no monta compara
|
|
|
CERO valores y pasa**.
|
|
|
|
|
|
**Regla para las sesiones de este eje**: si una incidencia mueve píxel o toca
|
|
|
morfo, se MIDE, se anota ahí y se sigue; no se arregla dentro del commit del
|
|
|
componente.
|
|
|
|
|
|
### Lo que queda de la firma 3, y por qué no lo he hecho
|
|
|
|
|
|
1. **`scroll-area.thumb-bg-hover` — pide DECISIÓN de morfo.** El thumb lleva
|
|
|
`archetype: 'thumb'`, que NO recibe velo. Migrarlo exige cambiar su
|
|
|
arquetipo, y un arquetipo es morfo: se presenta, no se toca de oficio
|
|
|
(§7.3-9). La alternativa es dejar su hover como excepción anotada.
|
|
|
2. **El hallazgo sistémico: 141 declaraciones en 45 componentes** cancelan el
|
|
|
velo del mismo modo, medido con `scripts/__statelayer-shorthand.ts` (que
|
|
|
comprueba contra el morfo que el atajo cae sobre el nodo VELADO, no sobre
|
|
|
cualquiera). Peores: radio-group 12 · tag-group 8 · checkbox 7 · table 7 ·
|
|
|
combobox 6 · tabs 6. Esto explica la adopción 21/135 que midió la auditoría
|
|
|
del 2026-07-01: el velo estaba escrito y estructuralmente derrotado. **Es un
|
|
|
barrido de catálogo que mueve píxel en 45 componentes: no entra en la firma
|
|
|
3, que se firmó sobre unos knobs concretos.**
|
|
|
3. **Hueco de demo**: `date-range-picker` no expone `kind='month'`/`'year'`
|
|
|
(norma N-6), así que la mitad de su API no se ve ni se mide.
|
|
|
|
|
|
---
|
|
|
|
|
|
## Firmas del 2026-08-20 — el acta (las 14, «FIRMO TODAS»)
|
|
|
|
|
|
Presentadas con recomendación fundada y firmadas en bloque por el autor. El
|
|
|
detalle razonado de cada una vive en la conversación del 2026-08-20 y en la
|
|
|
fila correspondiente del plan §4; aquí el QUÉ ejecutable:
|
|
|
|
|
|
1. **Familia calendar = capa compartida** (molde `lib/list-surface.css`: attr
|
|
|
de capa, un eje = token público + ranura privada `var(--_x, var(--x))`,
|
|
|
guardada por `shared-layer-contract.test.ts` + `layer:check`). NUNCA ~150
|
|
|
alias `--calendar-*`. Desbloquea `range-calendar` (98), `month-grid` (61),
|
|
|
`year-grid` (61) y media `date-range-picker`. El diseño de la capa
|
|
|
(nombre, ejes, qué posee) se presenta antes de escribirla.
|
|
|
2. **Mandato Field: ejecutable.** Los x-field/pickers componen el wrapper
|
|
|
Field; las alturas de segmento salen del eje size a nivel familia
|
|
|
(`--field-control-height-{k}`); muere la re-duplicación `height-{xs..xl}`
|
|
|
por componente (theming-audit §2-B: computaban `auto` desde su nacimiento).
|
|
|
3. **hover → capa de estado, donde reaparezca** (empezando por los 3 knobs de
|
|
|
`combobox`). Mueve píxel hacia el canon §38/R-4.3 ⇒ cada migración lleva
|
|
|
captura antes/después y su diff explicado en el commit. Desbloquea la poda
|
|
|
D-2 (changelog §38 ◇: los `--{x}-bg-hover` huérfanos, incluido
|
|
|
`pagination.selected-bg-hover` = capa sobre acento).
|
|
|
4. **D-TH.6 completa** — slot `fg` + modificador DELANTE con la regla:
|
|
|
**delante lo interactivo, detrás lo dimensional y contextual**; modificador
|
|
|
válido ∈ vocabulario universal (+`current`) ∪ valores `data-state`/ejes del
|
|
|
morfo del componente; `waveform.played/buffered` = pseudo-partes;
|
|
|
`scrim-color-on-*` → `scrim-fg-over-{dark,light}`; hovers neutros FUERA del
|
|
|
codemod (migran por la firma 3). Renombres nominales de los ex-falsos
|
|
|
amigos: `item-fg`/`active-item-fg`/`partial-item-fg` (rating-group),
|
|
|
`read-status-fg`/`failed-status-fg` (chat-message), `current-link-fg`
|
|
|
(breadcrumb), `played-fg`/`buffered-fg` (waveform). Se quedan:
|
|
|
`*-focus-ring-color` (sistema), `aura.orb-color-*` (sustantivo),
|
|
|
`gradient-builder.stop-color-*` (parte).
|
|
|
5. **D-TH.1** R-5 dura · **D-TH.3** tracks WIP en censo, `error` sólo fuera de
|
|
|
carril · **D-TH.5** el default no cambia (única excepción: la firma 3, con
|
|
|
captura).
|
|
|
6. **D-TH.2** con la opción (b) de `heading`: la familia tipográfica B5 mide
|
|
|
por `--style-*` como sistema transversal — no se acuñan `--{c}-*`
|
|
|
tipográficos. La lista `KNOB_PROPS` es el perímetro; cambios = firma.
|
|
|
7. **D-TH.4** con enmienda: la cola revisada de este CONTINUE prioriza sobre
|
|
|
el orden de familias B1-B8.
|
|
|
8. **D-TH.7** con enmienda: **R-5.3 a `error` directo tras el codemod**;
|
|
|
R-5.1/5.2 esperan F3.
|
|
|
9. **D-TH.8**: panel de tokens en `/temas`, en F4.
|
|
|
|
|
|
## Lo ejecutado (censo antes → después)
|
|
|
|
|
|
**Bloque del vocabulario, 2026-08-20** (tres commits, sin pushear):
|
|
|
|
|
|
| commit | qué |
|
|
|
| ----------- | --------------------------------------------------------------------------------------------- |
|
|
|
| `f09e04fab` | el acta de las 14 firmas + la revisión de los 7 ya corregidos |
|
|
|
| `bd916ef3f` | codemod: 269 claves · 793 referencias · 101 ficheros · alcance IDÉNTICO · 0 diffs de computed |
|
|
|
| `7781d6e4c` | R-5.3 en `error` (muta-prueba de 3 caras) + recipe-contract §1/§4 + theming §6.7 + checklist |
|
|
|
|
|
|
**Lo que el bloque enseñó** (más caro de lo que parece):
|
|
|
|
|
|
- **El plan del codemod se escribe ANTES de tocar nada.** Releer el
|
|
|
clasificador después da CERO desviaciones —ya están renombradas— y el
|
|
|
verificador del diff pasa sobre el vacío. Costó dos vueltas.
|
|
|
- **Un valor puede cambiar de texto sin cambiar de significado**: 22 privados
|
|
|
reapuntan a nombres nuevos. El gate normaliza por el plan antes de comparar,
|
|
|
o los cuenta como cambio de valor y da rojo en falso.
|
|
|
- **No pasar prettier sobre lo que el codemod tocó.** El árbol tiene CRLF
|
|
|
(`autocrlf=true`) y 88 de 101 ficheros ya salían «sucios» ANTES; un
|
|
|
`--write` en masa reformateó 300 ficheros de deriva ajena. Se midió lo que
|
|
|
importaba —¿alarga el renombrado alguna línea?— y la respuesta fue no en
|
|
|
todos, así que prettier no hacía falta.
|
|
|
- **Clasificar un hover por el NOMBRE es clasificarlo mal**:
|
|
|
`dropdown-menu.item-bg-hover` lee `var(--color-primary-element)` — es el
|
|
|
palette swap con valencia de recipe-contract §2, no el hover bespoke que §38
|
|
|
deprecó. Lo decide el VALOR. Yo lo había listado mal en este mismo handoff.
|
|
|
|
|
|
| componente | alcance | commit |
|
|
|
| --------------------------- | -------------: | ----------- |
|
|
|
| `gradient-builder` (piloto) | 0 % → **80 %** | `3cdb5b5f0` |
|
|
|
| `combobox` | 0 % → **76 %** | `cef2d32f1` |
|
|
|
| `natural-time-picker` | 0 % → **61 %** | `e774ca7e8` |
|
|
|
| `date-range-picker` | 0 % → **42 %** | `07778b597` |
|
|
|
| `time-range-picker` | 0 % → **19 %** | `68eb8af26` |
|
|
|
| `time-picker` | 0 % → **18 %** | `e4fcdd62e` |
|
|
|
| `proof-of-human` | 0 % → **14 %** | `ae91573c3` |
|
|
|
|
|
|
Global del catálogo: **33 % → 37 %** (1.621 → 1.841 knobs públicos).
|
|
|
Informe + instrumento: `2591ec2f0`; revisión de las fichas 11-20: `3bfe0d413`.
|
|
|
|
|
|
## El instrumental (vive en `scripts/`, prefijo `__` = temporal del eje)
|
|
|
|
|
|
```bash
|
|
|
node scripts/__theming-probe.ts <componente> <salida.json> # sonda antes/después
|
|
|
node scripts/__theming-diff.ts <antes.json> <después.json> # el gate: diff VACÍO
|
|
|
npm run theming:sentinel -- <componente> <url> # guard R-5.4: ¿alcanza cada token? (ya no es `__`)
|
|
|
node scripts/__shot.ts <componente> <salida.png> # captura 2× del stage
|
|
|
```
|
|
|
|
|
|
Se ejecutan **con `node`, no con `tsx`** (tsx inyecta helpers que rompen
|
|
|
`page.evaluate`) y **desde la raíz** del repo, contra el dev server en
|
|
|
`localhost:5173`. Los `scripts/__dbg*.ts` y `__sentinel-targeted*.ts` son de un
|
|
|
solo uso (verificaciones dirigidas de ayer); no se commitean.
|
|
|
|
|
|
## Lo que el instrumento aprendió a fuerza de mentir
|
|
|
|
|
|
- **La sonda congela `transition`, NUNCA `animation`**: una propiedad
|
|
|
transicionada devuelve su valor INICIAL justo tras escribir el token (un token
|
|
|
vivo parecía muerto), pero congelar `animation` impide que Presence monte el
|
|
|
panel — y entonces mides un popup que no existe.
|
|
|
- **Un token RESUELTO no se mueve desde `:root`**: se declara en `[data-{c}]` o
|
|
|
en su parte, así que el tema mueve la **coordenada**. El centinela escribe en
|
|
|
`:root` **y** en el host, y aun así los resueltos salen «muertos» por diseño.
|
|
|
- **Un panel portalado no ve el ámbito del componente**: sus tokens se emiten en
|
|
|
`:root` (o con `parts`), y un override scoped no lo alcanza.
|
|
|
- **La demo puede tapar el componente**: `proof-of-human` declara su propio
|
|
|
`min-block-size` y fondo sobre el stage — ahí el centinela no sirve, y se dice.
|
|
|
- **Un valor centinela igual al real lee como «no efecto»** (`9999px` contra un
|
|
|
`--radius-full` que ya era 9999px).
|
|
|
- **Los tokens que SON la transición no se pueden medir congelando** (2026-08-23):
|
|
|
`transition-duration` / `transition-ease` salen muertos SIEMPRE, en cualquier
|
|
|
componente, porque el congelado es el arreglo que hace medible todo lo demás.
|
|
|
Se miden en una pasada aparte, sin congelar (color-picker: 0.12s → 11.5s).
|
|
|
- **Ni `!important` en línea mueve una propiedad EN TRANSICIÓN si lees en el
|
|
|
acto** (2026-08-23): la lectura devuelve el valor viejo y parece un token
|
|
|
imposible de mover. Pasó con el fondo del cuentagotas: tres diagnósticos
|
|
|
falsos hasta congelar.
|
|
|
- **La sonda es CIEGA a un puente de talla por contexto** (2026-08-25, `form`):
|
|
|
fuerza la talla **ESCRIBIENDO `data-size` sobre cada nodo casado que ya lo
|
|
|
lleva** (`__theming-probe.ts:279-281`) — y una parte que COMPONE el `Button`
|
|
|
lleva `data-{c}-…` **y** `data-size`. Se lo pisa DESPUÉS del render, así que
|
|
|
mide el mismo atributo forzado antes y después: **el diff sale 0 por
|
|
|
construcción**, no por ausencia de efecto. Medido: 0 diffs sobre 832 valores
|
|
|
mientras el botón pasaba de 36 px fijos a 26/30/36/44/52. Para esta clase de
|
|
|
firma el instrumento tiene que mover el **chip REAL de la demo** (el prop),
|
|
|
nunca el atributo. La sonda estándar sigue valiendo como gate de «no se movió
|
|
|
nada COLATERAL» — que no es poco, pero no es la prueba.
|
|
|
- **`--font-size-lg` / `-xl` son `clamp()` FLUIDOS** (18→20 y 24→28): una medida
|
|
|
de letra en esas dos tallas **no es comparable entre informes si el viewport
|
|
|
no viaja con ella**. Medido: a 900 px dan 19,05 / 26,10 y desde ~1200 px
|
|
|
saturan en 20 / 28. Costó una desviación aparente de +2 px contra la cifra de
|
|
|
un expediente que no declaraba su ancho. **Declara el viewport en toda medida
|
|
|
de fuente `lg` / `xl`.**
|
|
|
|
|
|
## Trampas que costaron un commit cada una (no repetirlas)
|
|
|
|
|
|
- **Clave duplicada en `recipes/base.ts`**: añadir un bloque que ya existía lo
|
|
|
descarta **en silencio** (gana la segunda). Guard antes de generar — y que
|
|
|
**cuente cuántos bloques ve**: la versión con `\t` que vivió aquí hasta el
|
|
|
2026-08-21 no casaba NINGUNO (`grep -E` lee `\t` como una `t` literal) y salía
|
|
|
«vacío = OK» sin haber mirado nada — el antipatrón del guard que inspecciona el
|
|
|
vacío, en el propio handoff.
|
|
|
|
|
|
```bash
|
|
|
node -e "const t=require('fs').readFileSync('src/uix/eidos/lib/recipes/base.ts','utf8').replace(/\r\n/g,'\n');const k=[...t.matchAll(/^\t'?([a-z0-9-]+)'?: \{/gm)].map(m=>m[1]);const d=k.filter((x,i)=>k.indexOf(x)!==i);console.log('bloques',k.length,'| duplicados',d.length?d:'ninguno')"
|
|
|
```
|
|
|
|
|
|
Debe imprimir los ~130 bloques y `duplicados ninguno`. **Si dice 0 bloques el
|
|
|
guard está roto**, no es que el fichero esté limpio.
|
|
|
- **Dejar vivos los bloques `[data-…][data-size='…']` del CSS** al emitir la
|
|
|
cascada por el TSC: pisan los tokens nuevos con los valores viejos, y el diff
|
|
|
de computed da 0 **porque la ruta vieja sigue mandando**. Lo cazó el centinela.
|
|
|
- **Correr `component:audit` DESPUÉS de `prettier`, no antes**: al renombrar un
|
|
|
privado a su nombre completo, prettier partió tres declaraciones en varias
|
|
|
líneas y **separó la anotación `/* literal: … */` de su valor** — R-2.1 la
|
|
|
exige en la MISMA línea, así que el guard pasó a ver colores crudos donde
|
|
|
antes veía excepciones anotadas. Se arregla con `/* prettier-ignore */` sobre
|
|
|
la declaración: NO acortando el comentario ni tocando el valor. Regresión
|
|
|
real en `natural-time-picker`, cazada un día tarde por correr el audit antes
|
|
|
del formateo.
|
|
|
- **Backticks en `node -e "…"` desde bash**: se ejecutan y vacían el texto. Para
|
|
|
editar markdown con código, usar el editor, no el shell.
|
|
|
- **`prettier --write` sobre un README** no protege de que un Edit se coma un
|
|
|
encabezado: comprobar `grep -c "^## Gaps"` después de insertar secciones.
|
|
|
- Lo de ayer sigue vigente: medir el nodo que el usuario señala (píxel arriba),
|
|
|
el hover es del sistema, el default no cambia, rama compartida sin `stash` ni
|
|
|
`--amend`, `check` **por fichero**.
|
|
|
|
|
|
## Fuentes
|
|
|
|
|
|
- Plan y decisiones: [`PLAN-theming.md`](./PLAN-theming.md) · informe:
|
|
|
[`docs/audit/theming/README.md`](../audit/theming/README.md).
|
|
|
- Auditoría del SISTEMA (fase 1, cerrada): [`theming-audit.md`](../audit/theming-audit.md)
|
|
|
— §B familia calendar, §5.3-3 mandato de Field.
|
|
|
- Doctrina: `docs/theming/reference.md` (§5 talla, §6 nombres, §38 capa de
|
|
|
estado) · `docs/canon/recipe-contract.md` · `docs/canon/tsc.md` ·
|
|
|
`docs/architecture/eidos.md` (vertebración tipográfica, columna `unused`) ·
|
|
|
`src/uix/eidos/components/README.md` (capas compartidas).
|
|
|
- Precedente de la forma por talla: [`PLAN-sidebar.md`](./PLAN-sidebar.md) §3 +
|
|
|
F3 y el bloque `sidebar` de `recipes/base.ts`.
|