astra
alpha-0.1-background
alpha-0.1-dir-prefs
alpha-0.1-sec-dom
menubar-v4-safe
active-uix
morfo-runtime
morfo-driven-soma
semantuix
glm-5
main
sium-v1.0
${ noResults }
99 Commits (466b24f34f7be9e0bf40d77d1997c416ae233e7f)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
466b24f34f |
feat(theming)!: el sobre de trigger de popover es un SUELO - tercera ley 55
El "baseline button envelope" que popover.css pinta a sus triggers vivia a (0,2,0) con hover a (0,5,0): le ganaba a las recetas de sus HUESPEDES (el chip de anadir reaccion de chat-message perdia 9/9 propiedades disputadas y salia cuadrado gris entre pildoras - SU receta lo pintaba en el mismo selector-lista y PERDIA), mataba la capa de estado del sistema en hover (chronos plain = caja gris) y dejaba el trigger de calendar en manos del orden de carga (14/16/14/14px medidos - la moneda al aire). El sobre baja a :where() - base y hover, con el :not(field-trigger) DENTRO (where anula especificidad, no matching). El suelo pinta lo que el huesped CALLA; la receta gana donde habla; la capa de estado compone otra vez. Tercera aplicacion de la ley firmada (12.9 planos - B'/53 paleta - y archetypes.css:9-21 ya lo decia para SU capa). Cambio de codigo: 2 lineas. Medido (gate de dos niveles, 76 instancias, 16 rutas, 4 estados): - No afectados: 3 field-trigger diff VACIO; los 66 desnudos ganan EXACTAMENTE los dos valores del SISTEMA que el sobre tapaba (velo de hover de archetypes + su transition). 167 nodos de referencia: 0. - Los 7 movers, valor a valor por CDP hacia lo que SU receta declara: el chip vuelve pildora (36->26px, r9999) - chronos recupera su plain y su hover - calendar mes/anio pasa a su ghost compuesto Y SE VUELVE DETERMINISTA (8 cargas en dos ordenes, mismo pixel; antes 2 de 6 caian del otro lado) - emoji/palabras/ntp a sus recetas (ntp revive 4 claves: 44->48/62). - Capturas antes/despues x8 revisadas por el supervisor (chip, chronos, calendar, emoji, gradient, popover generico, palabras, ntp). - Guarda 55 en active-eidos-config.test.ts validada por SEIS mutaciones (la sexta se anadio porque la primera pasada dejo pasar un verde falso; y el arnes mintio con -t sobre 0 tests - detector de cero-tests anadido). - vitest 35/36 (rojo ajeno skin-media-player) - check 0 atribuibles - docs-check 0/0 - eidos-lint popover/chat-message 0 invalid. Registrado en 13 y fichas: los parches-pin de chronos/calendar pasan a REVISABLES (ahora redundantes o semi) - el suelo comparte peldano (0,0,0) con archetypes.css (medido 16 cargas: archetypes cae despues y el resultado es identico, pero es un empate real sin verificar en produccion) - la dependencia sin registrar de palabras queda anotada junto a su regla (no tiene README de eidos). changelog 55 escrito (la guarda citaba una seccion que debia existir). CON ESTA, LA LISTA "Lo que espera TU FIRMA" DEL CONTINUE QUEDA VACIA. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
2 months ago |
|
|
1f8ce293bb |
fix(theming)!: avatar - el contrato dice la verdad: 4 claves, cero desviadas
Las ultimas CUATRO claves fuera de gramatica de las 4.558 publicas del catalogo, resueltas cada una por lo que ES (no eran cuatro iguales): - `badge-color-custom-contrast` -> `badge-fg-custom-contrast`: la unica TINTA real y alcanzable. Nombre derivado DE la gramatica D-TH.6 (la ranura se sustituye EN SU SITIO; `custom` no es interactivo ni rol, va detras) con el precedente firmado scrim-fg-over-dark - y es la salida literal del clasificador que consume R-5.3. Renombre a mano (el codemod ABORTA sobre la IIFE de avatar - deuda registrada en 13): value-preserving, verificado con sonda dirigida (la clave vieja movia antes y no despues; la nueva al reves). - `ring-color-custom` y `badge-color-custom` RETIRADAS del contrato publico: canales de valor INALCANZABLES (puerta data-*-custom y escritura inline nacen de la misma expresion - mentiras bajo R-5.4). Mecanismo: canal privado de envoltorio `--_avatar-*-color-custom` + respaldo currentColor (el patron de las 5 privadas-de-envoltorio del parque, 5/5 sin declaracion en receta), NO borrado (el CSS las lee) NI privada plana (cero precedente). Ley 8.bis re-aplicada: cero lectores fuera de avatar, re-barrido. - `group-carve-color` EXENTA en NAME_EXEMPT con razon medida: alimenta box-shadow (geometria del carve, no tinta; alcanza en 59 instancias) - `fg` seria gramatica correcta con semantica peor. Medido: sonda 7.4 0/576 - pixel visible IDENTICO (anillo ambar, insignia violeta, tinta white) e instancia imposible identica (currentColor preserva el default retirado) - Tokens 88 -> 86 EN VIVO con el nombre nuevo (captura revisada por el supervisor) - censo --names: DESVIADAS 0 EN 0 COMPONENTES (4.556 claves) - centinela exit 0 - lint 0 - docs-check 0/0 - vitest 442+1 ajeno - check 0 atribuibles. Hallazgo de instrumento NUEVO, adjudicado y registrado en 13: el chooser del centinela elige el valor por NOMBRE y no conoce `fg` MEDIAL (su prueba de tinta es `fg$`): las 5 claves que la propia D-TH.6 fabrica (badge-fg-custom- contrast, bubble-fg-in/-out, scrim-fg-over-dark/-light) reciben 1234px, invalido para color - y el veredicto depende de si el respaldo coincide por azar (bubble-fg-* leen vivas POR ACCIDENTE). Arreglarlo obliga a re-verificar el ledger - firma de instrumento aparte. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
2 months ago |
|
|
2ce43db563 |
fix(morfo)!: tags-input - aria-selected sigue al resalte, no a un literal
`v.literal('true')` era el UNICO aria-selected incondicional de los 18 morfos
que declaran el atributo: el AX tree entregaba DOS option selected:true dentro
de un listbox multiselectable:false (mentira de plataforma), archetypes.css
(0,4,0) clavaba el velo de estado EN REPOSO (la etiqueta vivia en su propio
hover: reposo y hover byte-identicos) y `--tags-input-item-fg` no habia
pintado nunca.
Ahora `v.stateRef('active')` - el estado que soma YA deriva de
highlightedIndex, registrado como fuente por parte (states: { active }).
Precedente en casa: tag-group/listbox/tabs. `severity: 'optional'` NO hace
falta (inerte: solo la leen los checks de data-*, verificado en compile.ts).
Medido (ejecutor E-tags, heredando y VERIFICANDO la edicion de un ejecutor
interrumpido - dos claims sin medir corregidos, uno de atribucion: el tono de
la activa lo enmascara [data-highlighted] (0,3,0), no este atributo):
- Sonda: 14 diffs / 2.504 valores, UNA propiedad (backgroundImage), las dos
etiquetas x 7 pases sin puntero - el velo saliendo del reposo. Hover: 0
diffs = la afordancia recuperada (reposo 224,58 / hover 212,10; antes
212,10 = 212,10). Capturas antes/despues revisadas por el supervisor.
- AX: reposo false,false - ArrowLeft false,TRUE - Escape false,false.
Exactamente una navegando, cero en reposo.
- Centinela 63/91 -> 71/91 (revive item-fg; medida directa oklch(0.2435) ->
rgb(1,2,3)), exit 0, 0 sin adjudicar, 0 STALE, ceguera-a-patrones validada
a mano (17 cubiertas, todas muertas).
- Gates: morfo 222/222 - soma tags-input 3/3 - eidos 442+1 ajeno - check 0
atribuibles - docs-check 0/0 - eidos-lint 0 invalid.
Quedan ABIERTOS y registrados en next-features 13 (sin decidir aqui): el
morfo declara apg:grid pero implementa listbox/option - Provider y Control
llevan ambos role=listbox anidados - la tinta de tono de la activa la
enmascara [data-highlighted] (12.5) - migracion a grid (B-b) como
continuacion. Y una observacion de soma al paso: ArrowLeft desde el input no
saca el foco (:381).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2 months ago |
|
|
df3a4d054b |
fix(theming): form cede el cromo de submit/reset al Button que componen
El bloque de accion de form.css vestia CUATRO nodos con las mismas 23 claves:
submit/reset (que COMPONEN el Button canonico - ahi muertas Y contradictorias:
declaraban un boton solido de tinta blanca mientras se pintaba surface verde,
discrepando en silencio desde siempre) y array-add/array-remove, <button>
PELADOS donde las 23 son su UNICO cromo y estan 23/23 VIVAS (medido montandolos
a la fuerza: la demo nunca los monta).
Ejecuta la doctrina YA FIRMADA que nombra a Form.Submit por su nombre
(component-guide.md:126-146, consumer pattern rule 5) - la opcion de escalar a
(0,2,0) queda descartada por escrito: si se quiere el submit solido, el camino
es <Form.Submit variant="solid">, no ganar la cascada.
- El bloque de accion apunta ya SOLO a los dos botones del array; mueren 4
reglas y se estrechan 5 grupos. Los 4 privados THM-2 de submit/reset fuera
(nadie los consumia): el diff del generado son EXACTAMENTE 14 lineas (su
suelo y su forward). Las 23 publicas SE QUEDAN.
- Ceder submit/reset: 0 px sobre 79.296 valores (16 escenarios, V1) + sonda
0/834 con CONTROL POSITIVO (el CSSOM vivo no contiene una sola regla de
submit/reset ni un --_form-palette-*). El cromo del array, intacto contra
los valores pre-firma; su eje de talla sigue llegando por herencia.
- Centinela 22/64 exit 0, identico conjunto: solo cambia la RAZON de las 23
("rama array que la demo no monta") - la anterior era falsa a medias (los
botones del array NO llevan data-button) y el "24" era un error triplicado
(ficha, README, ledger): son 23.
- CONTINUE: la firma del compuesto EJECUTADA; gradient-picker (36) y
emoji-picker (3) des-RANCIADOS - ejecutados el 2026-08-20/23, hoy 0
adjudicaciones por compuesto (verificado; ademas su mecanismo era OTRO:
especificidad de popover.css, no orden de emision).
- next-features 13: DOS expedientes nuevos destapados y NO ejecutados aqui:
los botones del array deben COMPONER el Button (soma+morfo, clase A-112,
y son perceptualmente mudos) - y el eje size de form NO llega a sus
acciones (<Form size="xs"> renderiza acciones md; solo sobrevive el
row-gap).
Verificacion: V1 (verificador independiente, informe recuperado de disco tras
interrupcion) + ejecutor con gates completos (vitest 442+1 ajeno - check 0
atribuibles - docs-check 0/0 - eidos-lint 0 invalid).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2 months ago |
|
|
ffa45726fd |
feat(color)!: una palabra, un significado - primary/secondary son SIEMPRE jerarquia
La homonimia muere: `primary`/`secondary` significan JERARQUIA DE MARCA en el
catalogo ENTERO, tambien dentro de los seis primitivos de tinta (text, heading,
display, code, label, s-text). El paso de tinta del 82 % se llama `subtle` -
PROP y TOKEN, sin excepcion: el nombre es el contrato en el artefacto (la misma
ley que la FIRMA B' y la 12.9; se rechazo por escrito la via "solo el prop con
tabla de traduccion" - las excepciones legitimas son las FIRMADAS con razon,
no las inventadas al decidir para abaratar).
- Los seis CONTENT_INK, IDENTICOS: {subtle, muted, disabled, on-solid}; el
nivel-1 es el DEFAULT sin prop. `label` gana `on-solid` (cierra la
divergencia de familia registrada en
|
2 months ago |
|
|
e4fa616e5d |
docs(theming): registro post-B' - cinco hechos verificados entran al expediente
Pase de registro de lo que la firma B' descubrio y no arreglo (pre-existente, simetrico antes/despues). Seis claims de agentes -> verificacion adversarial independiente -> DOS murieron (label-inline era diseno firmado de la seccion 43; drag-drop refutado: su forward vive y alcanza) y UNO se fusiono (el color de `code` lo gana `[data-uix-docs] code` (0,1,1) - ES la firma pendiente 5.2 del harness, que se ENSANCHA de radio/padding a la tinta; medido por CDP, solo dos reglas declaran color). Entran en next-features 13 / CONTINUE: - El detector STALE del centinela es CIEGO a los patrones (filtra `k in ledger`, solo exactas): 207 claves revividas por B' y ni un aviso. Arreglo minimo anotado; clase re-verificar-ledger. - El guard no mide tono+estado a la vez (raiz de TONE_UNREACHED): tono solo en el paso estatico, hover sin tono, solo `toggle` declara eje de estado, switch/button sin entrada en COMPONENT_OVERRIDES (48). - Tres huecos de la sonda: el `open` de editable muere por CLIC sobre inputs ocultos (no por el localizador), button sin analogo de barrido de variantes, y NUEVE de las 33 escalas atadas a rol (purple slate indigo gray teal green orange red plum) - `plum` ES `loss`; 24 libres como reserva de sondeo. - Divergencia de familia: `label` es el unico primitivo de tinta sin el paso `on-solid` (tipo y runtime, auto-consistente); decision pendiente. Citas contrastadas contra el arbol (cuatro corregidas del verificador, incluida la deriva de +10 lineas del diff ajeno del sentinel). docs-check 0/0 sobre 815. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
2 months ago |
|
|
8244cb4a62 |
feat(theming)!: FIRMA B' - la cascada de paleta es una ESCALERA sin empates
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).
El orden de emision deja de decidir: la especificidad ES el contrato,
legible en el artefacto (doctrina hermana de la FIRMA 12.9).
- Emisor (render-css.ts): isPaletteSlotToken PARTE el bucket host - solo
las ranuras de paleta bajan al suelo, el chasis del componente queda a
(0,1,0). 49 suelos + 49 forwards reescritos + 0 pares viejos; bloques
por tono (112), capa compartida y gradient finish byte-identicos.
- Neutra en pixel, MEDIDO: ~297.000 valores computados antes/despues
(105.248 planos lotes A+B, 57.720 planos lote C, 134.464 con los tonos
ESTAMPADOS en las 49 unidades, incluidos 5 @active), 0 diffs reales.
Los 17 crudos, probados ruido por reproduccion sobre codigo identico.
- Guarda por MUTACION (active-eidos-config.test.ts): suelo con contenido,
forward de un peldano, par viejo ausente, tono sin envolver, particion
del host, cierre estructural (toda declaracion de paleta vive en un
peldano) - 6 mutaciones inyectadas, 6 mordidas. El contrato del forward
pasa de vigilar 2 recetas a 49 (privadas incluidas, multi-parte bien).
- Ledger: PALETTE_SUPERSEDED muere (describia el mundo viejo); 207 de sus
353 claves pasan a VIVAS y las 146 restantes quedan bajo PALETTE_FLOOR
(el tono-default estampado resuelve por el forward: quitar el atributo
ES hablar en silencio) o TONE_UNREACHED (ningun paso del guard estampa
tono Y hoverea), con razon medida. stepper y tag-group, barridos por
primera vez. El detector STALE es CIEGO a patrones: la retirada fue
manual y por estrechamiento, guiada por medida.
- Docs: changelog 53 - reference THM-2 - next-features 13 (RESUELTA) -
CONTINUE-theming.
Supervision: 4 agentes Opus en 5 fases (baseline plano + baseline
estampado, emisor, guarda, verificacion de parque completo, docs), con
refutacion del supervisor sobre censo, emisor y guarda.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2 months ago |
|
|
5d71d830e9 |
feat(theming)!: FIRMA §12.9 — el plano de profundidad es el SUELO, no el techo
El plano `data-depth` pinta el bundle de elevación (superficie · borde · sombra
· tipografía on-surface) y hasta hoy lo hacía a (0,1,0), la misma especificidad
que la receta del componente. La Decisión 8 daba por bueno ese empate porque
«las recetas cargan después de la fundación y ganan por ORDEN DE CASCADA».
ESA PREMISA ERA FALSA
La fundación la inyecta ActiveEidos en runtime como <style> gestionado, y las
recetas llegan como chunks code-split de Vite: a igual peso ganaba quien
cargara el último, y se midió AL REVÉS en dev que en producción (§13). No era
una decisión de diseño, era una moneda al aire — y la moneda cayó del lado del
plano.
LO QUE COSTABA, MEDIDO
Un toast `risk` y uno `fulfill` vestían la MISMA TARJETA GRIS: los seis tonos
idénticos y la franja de acento —el rasgo que identifica la intención de un
vistazo— reducida a 0,67 px de gris neutro, porque el atajo `border` del plano
pisaba el longhand `border-inline-start` en los cuatro lados. Las TRES variantes
de tooltip computaban lo mismo: `outline` indistinguible de `solid`, `ghost` un
backdrop-filter invisible tras una superficie opaca. Y ~35 claves públicas
quedaban adjudicadas como mudas en cinco componentes, con tres recetas que
habían RETIRADO su tipografía por esto.
LA REGLA
La regla de apariencia del plano se emite envuelta en `:where(...)` —
especificidad CERO. La receta gana donde el componente HABLA, en cualquier
orden de carga; el plano sigue pintando todo lo que el componente CALLA, que es
exactamente lo que significa «baseline». Vale igual para un plano que añada un
tema (jaula abierta).
EL FROST NO BAJA, Y ES DELIBERADO
`[data-depth='{plane}'][data-frost]` conserva sus (0,2,0). El baseline es un
suelo que la receta puede pisar; el frost es una petición explícita por
elemento —alguien escribió `data-frost`— y honrarla significa ganarle al fondo
propio del componente. Mismo atributo, intención opuesta: queda comentado en el
emisor para que nadie los «armonice», y el guard lo fija por los dos lados.
QUÉ MUEVE DE PÍXEL, ENTERO
De 19 adoptantes, DIECISÉIS con diff CERO sobre ~49.000 valores computados. Los
tres que se mueven son la firma haciendo su trabajo:
- toast: 35 diffs (7 fondos + 7 bordes de tono + 21 anchuras). Cuatro tonos
medidos en la demo real: 4 de 4 DISTINTOS donde antes 3 de 3 eran idénticos,
y la franja de acento pasa de 0,67 px de gris a 3 px del color de la
intención.
- tooltip: sus tres variantes vuelven a distinguirse — solid opaco con sombra,
outline transparente con borde, ghost translúcido al 70 %.
- popover, tooltip y link-preview: `line-height` de 1.25 (el `--leading-ui` del
plano) al que cada receta pide. Es EXACTAMENTE la decisión que la receta de
link-preview tenía escrita desde el 2026-08-21: «se quedan declaradas A
PROPÓSITO; retirarlas arreglaría el empate a favor del plano — una decisión
de píxel que pertenece a la firma pendiente de §12.9».
`font-family` no se movió en ninguno: las recetas piden el mismo
`--style-label-font-family` que el plano pinta, así que la seguridad
tipográfica del portal (Decisión 8) queda intacta.
Refutada una hipótesis propia: temía que el atajo `background` del plano
estuviera matando el velo de hover del sistema y que bajarlo lo resucitara
moviendo píxel. `backgroundImage` no cambia en ninguno de los 19 — el velo vive
en los ítems, no en la superficie.
EL LEDGER
17 claves salieron STALE solas y se retiran: toast (3), tooltip (5),
float-panel (5), link-preview (2), popover (2). Los cinco vuelven verdes —
toast pasa de 51/85 a 72/85. El ledger sigue en 87 bloques, sin duplicados, y
parsea.
DOS VECES QUE EL INSTRUMENTO MINTIÓ
La sonda compartida mide UN nodo en dialog, drawer, popover, tooltip,
context-menu, dropdown-menu y link-preview: nunca abre la superficie, que es
justo donde el plano pinta, así que sus «0 diffs» no probaban nada. La medición
buena reproduce el «antes» EN RUNTIME, inyectando la regla vieja a (0,1,0) al
final del head en vez de revertir el fichero — entra como
`scripts/__plane-open.mjs`.
Y el primer barrido del ledger dio 87 de 87 rojos: «todos fallan igual» es la
firma del instrumento, y era la misma trampa del CR de Python en Windows que ya
está registrada. Re-corrido con la lista limpia.
EL BARRIDO DEL LEDGER ENTERO
87 de 87 componentes con entrada en el ledger, re-corridos tras el flip: cero
NO EFFECT sin adjudicar, cero STALE, cero errores. El cambio es global y se
verificó globalmente.
GUARDS
vitest src/uix/eidos 439/440 (el rojo conocido skin-media-player) ·
active-eidos-config 75/75 · npm run check COMPLETED con los 72 errores
preexistentes de la rama y ninguno en ficheros de este cambio · rtl:check 0 ·
docs:check 0 · eidos-lint 0 invalid en los cinco tocados · capturas de las tres
superficies que se mueven.
Un test hermano afirmaba el selector desnudo para un plano añadido por un tema:
ahora afirma `:where()`, porque un plano de tema es un suelo igual que los
cinco de fábrica.
Doctrina en docs/theming/changelog.md §29 (junto a la Decisión 8 que corrige),
cierre del expediente en next-features §13 y handoff al día.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
d4a83cca68 |
docs(theming): la COLA A queda CERRADA — y §12.9 pasa a tener coste de producto
scroll-area y slider al 100 %, tabs cerrado en 97 %, toast al 100 %. Global 68 %, 45 componentes al 100 %. Los cuatro cerraron SIN acuñar una sola clave: a los cuatro les quedaba un literal y en los cuatro era identidad. Firmar un literal y cerrar es una respuesta tan válida como acuñar. LO QUE MÁS PESA, RE-MEDIDO EN LA SUPERVISIÓN Un toast risk y uno fulfill visten la misma tarjeta gris. Disparados los tres tonos en 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; --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. Y queda anotada la trampa de 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 y manda la firma por el camino equivocado. LA LEY QUE DEJARON LOS OTROS DOS Antes de retirar una clave, mira quién la lee: scroll-area.auto-max-block leía muerta en su propia demo y la consumen cinco recetas ajenas; slider.min-block-size la fija media-player. Retirarlas habría roto seis componentes sin que un guard se pusiera rojo. Ya es el paso 8.bis de §7.3. Queda del eje: cero de cola A, tres de deuda B (cada uno por su razón), ninguna pestaña Tokens pendiente, y siete cosas esperando tu firma. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
b8eccc1c4f |
uix(toast): temable — 98 % → 100 %, y el plano se lleva la TARJETA ENTERA
El contrato ya tenía sus 85 claves y `global` era CERO: no se acuña ninguna.
Lo único fuera de alcance era un literal, y era identidad.
Lo que entra:
- `opacity: 1` de la tarjeta firmado con su anotación `/* literal: */`
(recipe-contract §3): es el polo EN REPOSO del par abierto/cerrado, y el
que lleva tokens es el otro (`closed-offset`, `closed-scale`). «Presente
del todo» no tiene un segundo valor que sostener. 98 % → 100 %.
- Guard R-5.4: entrada nueva en `COMPONENT_OVERRIDES` que dispara la tarjeta
con el botón del demo — y que DELIBERADAMENTE no pone `openMarker`. Una
tarjeta se auto-descarta a los 5 s, así que «¿ya está abierta?» no tiene
respuesta útil: con `openMarker` tres corridas sobre código idéntico
discreparon en QUÉ token leía muerto. Sin él, el guard cae al marcador por
defecto (una parte que este componente no tiene) y dispara una tarjeta
nueva antes de CADA token: **51/85 en tres corridas seguidas**, determinista.
- Ledger: 34 adjudicaciones, ninguna retirada, todas MEDIDAS.
- La sonda aprende a disparar el toast (`DEMO_VARIANTS`): medía UN nodo (el
viewport) porque un toast no EXISTE hasta que algo lo lanza. Ahora 8.
EL HALLAZGO — §12.9 con una cara nueva y con coste de PRODUCTO:
`toast-item.svelte` sella `data-depth='overlay'`, y el plano declara
`background`, el ATAJO `border` y `box-shadow` con la misma especificidad
(0,1,0) y más tarde. Medido sobre la tarjeta real con transiciones congeladas:
escribir `--toast-{tono}-surface` / `-border`, `--toast-provider-border-width`,
`--toast-accent-width` o `--toast-provider-shadow` no mueve NADA; escribir
`--depth-overlay-surface` / `-border` / `-shadow` y `--border-width` en la
misma raíz lo repinta todo. Son 21 claves de 85, y a diferencia de `tooltip`
esto se VE: un toast `risk` y uno `fulfill` visten la misma tarjeta gris, y la
franja de acento —un `border-inline-start` que el atajo posterior pisa en los
cuatro lados— no aparece nunca en reposo.
Matiz que sólo aparece midiendo: los seis `{tono}-accent` NO están muertos.
Bajo `[data-loading]` la regla del pulso es (0,2,0) y su `@keyframes` gana a
toda declaración normal — 100 fotogramas del pulso real: sin escribir, el
color interpolado corre en oklab L 0.5032..0.8514; con el token en rgb(1,2,3),
0.0823..0.5032. La misma clave miente en reposo y dice la verdad en animación.
§12.9 sigue SIN FIRMAR, así que las 21 se ADJUDICAN con `PLANE_SUPERSEDED` y
la incidencia se registra en `next-features.md` §12. No se toca desde este eje.
Las 13 restantes: la pareja de transición (el guard congela `transition`),
`closed-offset` / `closed-scale` (estado de salida + `transform`, que el guard
no fotografía), los tres del anillo de foco de la acción (el guard hace
`blur`), los cinco `{tono}-action-hover-bg` (el guard estampa el tono en su
pasada estática y no en la de hover) y `provider-max-width`, cuyo centinela de
1234px se capa contra el `min(100%, …)` — medido desde el otro lado, 120px
encoge la tarjeta de 420 a 280.
Censo: 98 % → 100 % (45 knobs · 45 públicos · 0 globales · 0 privados ·
1 excepción firmada). Global 68 %, al 100 % 42 → 45. Sin cambios en
`recipes/base.ts` ni en `generated/base.css`.
Diff de computed: **0 diffs sobre 1.760 valores en 7 estados** (8 nodos en
reposo, 7 en hover). Capturas 2× de la tarjeta byte a byte idénticas — y van
por un script propio, porque su viewport es `position: fixed` y cae fuera del
recorte del escenario que usa `__shot`.
Más README con su sección «Talla y tema», pestaña `Tokens` en la demo (85
claves, verificada en el navegador) y ficha con veredicto §5.
Guards: centinela 51/85 verde (exit 0, sin STALE) · `component-audit --only
toast` PASS · `eidos-lint toast` 0 invalid (24 morfo-backed, 6 eidos-only) ·
`vitest run src/uix/eidos` 35/36 (el rojo conocido es `skin-media-player`) ·
`rtl:check` 0 · `docs:check` 0 · `check` COMPLETED sin un solo error en
ficheros de toast · prettier limpio sobre el contenido normalizado a LF.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
10832bef4a |
fix(theming): la sonda no congelaba NADA — 18 diffs fantasma sobre código idéntico
El gate del protocolo §7 es «el diff de computed es CERO», y la sonda que lo mide no inyectaba ninguna congelación: una propiedad en transición devolvía el valor VIEJO y una bajo animación en BUCLE devolvía donde el bucle estuviera. Ruido puro sobre el único artefacto que prueba que un commit no mueve píxel. Lo destapó chat-typing, cuyos tres puntos montan el bucle pulse del sistema: 18 diffs de opacity corriendo la sonda DOS VECES sobre el mismo código. Con la congelación de transition Y animation antes de cada instantánea: 0 diffs sobre 1.568 valores. Un token que SEA la motion lee congelado y se mide a mano sin congelar, que es el idioma que el ledger ya usa para transition-duration / -ease. Queda registrado en §13 lo que NO arreglo aquí: el guard congela transition pero no animation, y cambiarlo obliga a re-verificar el ledger entero porque los tokens que son la animación pasarían a leer muertos. Misma clase que «el guard no fotografía transform», mismo bloqueo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
92180c390c |
uix(tags-input): temable — 88 % → 90 % CERRADO, y su tinta no ha pintado nunca
Los cinco knobs fuera de alcance se clasificaron UNO A UNO antes de tocar una
línea, que es la mitad del trabajo:
- **uno era la COSTURA**: `[data-tags-input-control][data-invalid]` leía
`var(--color-risk-border)` A PELO. Entra como
`--tags-input-invalid-control-border`, valor verbatim, con el nombre Y el
default de `field.invalid-control-border` — la misma parte del mismo chasis.
NO se reusó el `risk-border` de la paleta: la cascada `[data-color]` lo
re-enruta por instancia y se llevaría con él el estado inválido, que no es
una elección de tono. `global` a CERO.
- **los otros cuatro son el MISMO puente THM-2**: el borde del control
enfocado y los tres slots de la etiqueta activa leen
`--_tags-input-palette-{border,track,text}`. Ni conmutador ni escala por
talla. No se acuñan (CONTINUE §3.pre): un público encima dejaría que un tema
los fijara y matara en silencio el `color=` por instancia.
**Así que 90 % ES el techo, y es doctrina bien aplicada, no deuda.** Los siete
privados dimensionales ya derivan de públicos; sus bloques `[data-size]` del
CSS SE QUEDAN porque aquí no los emite el TSC (las claves de talla son planas,
sin `scope: 'size:{k}'`) — retirarlos rompería el eje. Migrar esa escala al TSC
es cambio de mecanismo, no de alcance, y queda fuera.
Censo: 46 knobs · público 37 → 38 · global 1 → 0 · privado 4 (el puente) ·
sistema 4 (fuera del ratio) · 88 % → 90 %. Contrato 90 → 91 claves.
`--names`: 0 desviadas (67 conformes + 24 role-slot canónicas).
Diff de computed: VACÍO en las dos superficies. 2.496 valores × 8 estados en el
escenario por defecto (válido, sonda estándar, 10 nodos) y 459 valores × 5
tallas + 3 variantes + hover en el estado INVÁLIDO, con una sonda de un solo
uso porque la demo arranca válida. Captura 2× antes/después byte a byte
idéntica. No se tocó ninguna regla `:hover`, así que el paso 12 no aplica.
Centinela R-5.4: **63/91**, 28 adjudicadas, cuatro razones y todas MEDIDAS:
1. **Las 24 claves de tono — la cascada de paleta** (excepción por PATRÓN). El
wrapper resuelve `color` y estampa `data-color` en TODA instancia, incluida
la del default, así que gana el bloque genérico
`[data-tags-input][data-color], [data-tags-input][data-color-custom]`, que
se emite el ÚLTIMO a la misma (0,2,0) que los ocho por tono. Medido sobre la
etiqueta real forzada a `data-state=active`: `--tags-input-primary-border`
no mueve nada (el borde sigue en `oklch(0.8043 0.0918 309.69)`) mientras
`--palette-border` en el mismo nodo lo repinta (`rgb(4, 5, 6)`); quita
`data-color` y `--tags-input-primary-border` vuelve a pintar
(`rgb(1, 2, 3)`).
2. **`transition-duration` / `transition-ease`** SON la transición que el guard
congela. Medidos sin congelar: 0.12s → 4.321s y
`cubic-bezier(0.4, 0, 0.2, 1)` → `steps(3)`.
3. **`placeholder-fg`**: soma sólo pone el atributo `placeholder` mientras el
input está VACÍO (`isEmpty ? opts.placeholder : undefined`) y el escenario
arranca con dos etiquetas — y `::placeholder` sobre un input SIN placeholder
devuelve el estilo del ELEMENTO (la trampa ya medida en `field`). Vaciar el
escenario no vale para esa corrida: borra los nodos de etiqueta, donde pinta
un tercio del contrato. Medido de las dos formas: pulsando el propio `Clear`
de la demo el input queda con `placeholder="Add tag"`, y forzando el
atributo sobre el input real el token alcanza (`rgb(1, 2, 3)`; default
`oklch(0.61 0 0)` = `--color-content-muted`).
4. **`item-fg` — y ésta NO es del instrumento, es del COMPONENTE.** El morfo
sella `aria-selected='true'` como LITERAL en CADA etiqueta, así que la regla
de `archetypes.css`
`[data-archetype='item'][aria-selected='true']:not([data-state='checked']):not([data-state='on'])`
**(0,4,0)** gana siempre a `[data-tags-input-item]` **(0,1,0)**: la tinta de
la etiqueta es la del arquetipo y su velo de estado se pinta en TODAS las
etiquetas en reposo. Medido: con el atributo tal como se envía el token no
mueve nada (`oklch(0.2435 0 0)`, la del arquetipo); con `aria-selected=false`
sobre la etiqueta real, la misma escritura alcanza (`rgb(1, 2, 3)`). Los
tres slots `*-text` del tono llevan esta SEGUNDA causa encima de la primera.
Es la clase de `table.selected-row-fg` y la tinta de `listbox`. Toca morfo Y
mueve píxel ⇒ se mide, se REGISTRA (next-features §12, con su cara de a11y:
un lector anuncia todas las etiquetas como seleccionadas) y se sigue.
Lo que el instrumento aprendió: **el guard ABRE haciendo clic en el control**,
lo que estampa `data-focus`, y la regla de foco re-tinta el borde a la misma
(0,2,0) pero más tarde — así que `control-border`, un token perfectamente vivo,
leía muerto. Es la clase de `command.input-border`, otra vez, y la cura es
barrer la AUSENCIA (`null`) de `data-focus`, `data-invalid` y `data-disabled`:
**60/91 → 63/91 sin adjudicar una clave de más**, y de paso reviven
`invalid-control-border` y `disabled-opacity`. Es una entrada por componente:
no toca a nadie más. `fab` re-verificado tras el cambio del guard: 11/12, sin
regresión ni STALE.
Guards: censo `--only tags-input` 90 % (global 68 %, no baja) · `--names` 0
desviadas · `component-audit --only tags-input` PASS · `eidos-lint tags-input`
0 invalid (22 morfo-backed, 6 eidos-only) · `vitest run src/uix/eidos` 35/36
ficheros, el único rojo es el conocido `skin-media-player` en `lint.test.ts` ·
`rtl:check` 0 · `docs:check` 0 · `npm run check` COMPLETED, cero errores en los
ficheros tocados (los 72 globales son de otras sesiones) · prettier limpio
sobre el contenido normalizado a LF.
README con su sección «Talla y tema», pestaña `Tokens` en la demo verificada en
navegador (91 claves, cero errores de página) y veredicto §5 escrito en la
ficha.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
5c8e707a0d |
docs(theming): 164 fichas regeneradas — dos perdían prosa medida, y el generador es el culpable
Una sesión regeneró todas las fichas de docs/audit/theming con el --report del censo y las dejó sucias en el árbol. Antes de commitearlas las clasifiqué una a una en vez de mirar la cifra: - 155 sólo cambiaban la FECHA de medida. Inocuo, y correcto: el censo corrió hoy. - 7 traían cifras nuevas y buenas (collapsible y toolbar, que acaban de cerrar) o retiraban una propuesta §4 ya cumplida. Mejora. - 2 —chat-log y chat-composer— BORRABAN prosa medida: donde un humano escribió «_Ninguno_ — los cuatro que había (el padding-block del divisor, el radio de foco de la fila de evento…) están cosidos», la plantilla dejaba «_Ninguno._», y en chat-composer se llevaba además el bloque de las cuatro declaraciones retiradas por muertas. Esas dos van cosidas: el cuerpo de HEAD con la línea de cabecera regenerada. El resto entra tal cual. Que la regeneración sea mayoritariamente buena y ocasionalmente destructiva es el peor reparto posible, porque nadie la mira. Registrado en §13 con su arreglo: extender los marcadores tipo veredicto:end a cualquier bloque que un humano haya ampliado, o que el generador respete una línea que no empiece por su propia plantilla. Mientras tanto, regenerar fichas y commitear sin leer el diff es una pérdida de datos silenciosa. Y con él, la hermana que reportó una sesión de la tanda: snapshot-y-restaura sobre un directorio COMPARTIDO pisa a quien escriba en medio. Dos sesiones hicieron cp -r de docs/audit/theming y la segunda restauró desde un snapshot anterior al trabajo de la primera, devolviéndole sus veredictos a «pendiente» a media faena. El árbol de trabajo también es compartido: respalda por FICHERO tocado, nunca por directorio. Quedan fuera a propósito las fichas de chat-message y tags-input: sus sesiones siguen trabajando. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
9130070bd5 |
docs(theming): la revisión del 24 entra al repo con su plan EJECUTADO — y las ocho entradas §8 que faltaban
REVIEW-theming-2026-08-24.md: 2 errores (los dos de la concurrencia, ya
corregidos), 4 desviaciones, 1 incoherencia real de gramática (las cuatro
claves de avatar, preexistentes y ahora VISIBLES), 9 refutaciones con su
medición, y el barrido del centinela sobre el LEDGER ENTERO: 59 + 23
componentes, cero sin adjudicar, cero STALE. P7 vacío.
Las OCHO entradas §8 que faltaban (emoji-picker, spin-field, pin-input,
dialog, form, skip-link, image-picker, search-field) entran redactadas desde
sus commits y VERIFICADAS por un pase escéptico independiente contra el censo,
el contrato en HEAD y en {sha}^, y los artefactos. El escéptico corrigió tres
antes de entrar — form (el patrón casa 23 claves, no 24; §13 corregido de ~63
a ~62), search-field (nueve tokens del indicador, no ocho) e image-picker (una
cifra no reproducible, reescrita) — que es exactamente para lo que existe el
pase.
Queda UNA cosa del plan, y es firma: P2, la demo como instrumento (el
precedente de chat-log). Presentada aparte con recomendación.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
9bbc58502f |
docs(theming): la cola eran TREINTA Y CUATRO, no once — y dos huecos más del instrumento
Ejecuta P3, P4 y P5 del plan de la revisión del 24.
P4 — LA COLA DEL HANDOFF ESTABA MAL, Y ERA MI ERROR
La bala que escribí al cerrar la tanda listaba once pendientes. Contados contra
el censo y el registro §8 son treinta y cuatro, y la lista sin separar tampoco
servía, porque mezcla dos cosas distintas:
- 16 que NUNCA han pasado por el eje (sin entrada §8 ni README): field-langs,
chronos, mockup, sidebar, image-adjustments, separator, chat-message, fab,
tags-input, chat-typing, collapsible, toolbar, scroll-area, tabs, slider,
toast. Ésa es la cola de verdad.
- 18 que SÍ pasaron y sólo les falta el README «Talla y tema»: el paso se
volvió obligatorio después de que cerraran y
|
2 months ago |
|
|
5be7dabf49 |
docs(theming): el índice de git es COMPARTIDO — verificar el árbol indexado no basta
Ocho sesiones sobre el mismo worktree y un solo .git/index. La técnica que esta rama daba por segura —construir el índice desde HEAD con sólo tus hunks y comprobarlo con git diff --cached— protege del árbol de trabajo ajeno, no de la ventana entre MIRAR y CONFIRMAR: si otra sesión hace su reset + add en ese hueco, tu commit fotografía SU índice. Ocurrido dos veces en una tarde. |
2 months ago |
|
|
c242616eea |
docs(theming): la viñeta de radio-group se pegó a la línea anterior
El commit `f5d252443` construyó su índice desde HEAD insertando la viñeta ANTES del ancla `\n**Deps**: ninguna…`, y ese ancla empieza por el salto de línea: el texto quedó `…ninguna superficie la monta.- **La escala del punto…` en una sola línea, y la lista de §13 perdió un ítem de vista. Sólo el salto de línea. Ni una palabra cambia. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
edc0195156 |
uix(toggle): temable — 81 % → 100 %, y el guard sólo sabía barrer UN eje
Tres knobs fuera de alcance, ninguno por doctrina.
- **El radio** (1 knob, 6 fuentes). La receta leía `--radius-default` y la
escala global `--radius-*` A PELO, así que la única forma de redondear un
toggle era mover el radio de todo el sistema — el agujero que tenía
`navigation-menu`, y el único de los CINCO componentes con escala `rounded`
que no tenía la suya (button, badge, image y color-swatch la declaran).
Entran `radius` (el reposo, default `var(--radius-default)`: sigue siguiendo
el default del arquetipo) y `radius-{sm,md,lg,xl,full}`. El desacople de
`size` se conserva intacto: son pasos de `rounded`, no de talla.
- **El tinte inválido**: `var(--color-threat-element)` a pelo →
`invalid-border` con ese valor (la costura, PLAN §2-A).
- **Los tres literales quedan FIRMADOS** con su anotación y salen del ratio:
el `100%` de `data-block` es identidad y el par `1px` del cuerpo ES la
técnica sr-only.
Censo: 28 knobs · 22 públicos · 81 % → 25 knobs · 24 públicos · **100 %**
(3 excepciones firmadas fuera del ratio). Contrato 119 → 126 claves. Global
del catálogo sin bajar (68 %).
Diff de computed: **VACÍO**. 416 valores en 7 estados (sonda estándar, 2
nodos) más 1.150 valores en 25 celdas de variante / rounded / on / invalid /
disabled / block / icon-only / tono, con `transition` y `animation`
congeladas — porque el escenario de la demo monta UN toggle solid, apagado y
válido, y la sonda no barre esos ejes. Capturas 2× antes y después, miradas.
Centinela R-5.4: **70/126, 56 adjudicadas**, verde. Empezó en 36/126 y la
diferencia NO es adjudicación, es instrumento: las claves `{variante}-*` y
`{variante}-on-*` son las mismas tres variantes en dos ESTADOS, y forzar el
estado con `prepareWith` cambiaba una mitad por la otra (36 → 46, y murieron
las de reposo) — «montar más puede medir menos», esta vez dentro de un
componente. El guard aprende tres cosas, cada una nacida de una medición:
- barrer el **producto cartesiano** de varios ejes (un solo eje da la misma
secuencia de siempre, así que nada de lo que ya tenía `sweepAttr` cambia);
- **quitar** un atributo con `null`, porque sellar `data-invalid` toda la
corrida hacía que el borde inválido ganase a los otros seis bordes;
- aplicar el barrido también en el **pase de hover**, que no barría nada —
que es literalmente la razón escrita en el ledger de
`radio-group.hover-segmented-segment-fg`.
Con eso, 58 y luego 70. Los **12 componentes con `sweepAttr` re-verificados
uno a uno**: cero regresiones, cero STALE (tres dieron exit=1 falso corriendo
doce seguidos contra el mismo dev server; a solas, verdes).
De las 56 adjudicadas, 48 son la cascada de paleta POR PATRÓN, medida aquí:
con `data-color=primary`, `--toggle-primary-solid` no mueve nada y
`--palette-solid` sobre el mismo nodo repinta; quita `data-color` y
`--toggle-neutral-solid` pinta otra vez. Las ocho `neutral-*` caen con las
demás por una razón que conviene escribir: el propio guard ESTAMPA
`data-color=neutral` para probarlas, que es justo lo que enciende el bloque
genérico. Las otras 8 están medidas una a una sobre el nodo real (los cinco
pasos de `rounded`, que la demo no expone; `disabled-opacity`; y el par de
transición, que ES lo que el guard congela).
Guards: censo `--only toggle` 100 % · `component-audit --only toggle` PASS ·
`eidos-lint toggle` 0 invalid · `vitest run src/uix/eidos` sin rojos nuevos
(el conocido `skin-media-player` en `lint.test.ts`) · `rtl:check` 0 ·
`docs:check` 0 · `check` sin errores en ningún fichero tocado · prettier sin
desviaciones NUEVAS sobre el árbol indexado.
Anotado y FUERA por D-TH.5: `[data-toggle]:hover` y
`[data-toggle][data-invalid]` pesan lo mismo (0,2,0) y el hover se declara
antes, así que un toggle inválido bajo el puntero pierde su tinte. Arreglarlo
mueve píxel y es una decisión de escala del sistema — los cuatro controles de
formulario comparten el patrón.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
f5d252443c |
uix(radio-group): temable — 77 % → 81 %, y su punto NUNCA ha pintado su escala
Ocho claves acuñadas, diecisiete bloques `[data-size]` retirados y veinticuatro
adjudicaciones medidas. El default no se mueve: diff de computed 0 sobre 25.263
valores en 47 estados (20 combinaciones de variante x estado x talla con su
pasada de hover, más las 7 de la sonda estándar) y capturas 2x idénticas.
Censo: 77 % → 81 % (knobs 75 → 59, público 56 → 46, global 7 → 1, privado 10
invariante, sistema 2). Contrato 61 → 69 claves. Global no baja (68 %).
QUÉ ENTRA (8 claves)
item-size · dot-size · font-size — los tres ejes RESUELTOS por talla en el
TSC, con `scope: 'size:{k}'` sobre el proveedor, que es quien lleva
`data-size`. Con ellos se van los DIECISIETE bloques `[data-size]` del CSS
(§7.4-4: dejarlos vivos hace que el diff dé 0 por la ruta vieja) y el privado
`--_radio-item-size`, que llevaba el nombre del componente ABREVIADO —
theming §6 r5 lo prohíbe, es la clase de `--_mp-*` y `--gp-*` — y por eso el
censo contaba el ancho y el alto del ítem como deuda.
invalid-indicator-border · invalid-ring · invalid-ring-gap ·
invalid-item-label-fg — el tinte de validación leía `--color-threat-element`
y `--color-threat-text` a pelo. El trío del anillo toma el vocabulario del
gemelo `checkbox`, que ya lo tenía; el borde se llama `indicator-*` porque en
ESTE componente «indicator» es el círculo exterior y `dot-*` el punto.
segmented-segment-padding-block — el hermano que le faltaba a
`-padding-inline`.
UNA CLAVE ACUÑADA Y RETIRADA EN EL ACTO
`row-min-height-touch: var(--touch-target)` para el suelo táctil de la fila.
La suite `recipe-css-contract` la rechazó como referencia FANTASMA: nadie
emite `--touch-target`, es una constante ergonómica escrita a mano en
`archetypes.css` («a hard ergonomic constant — the fingertip, NOT a theme
value»). Y recipe-contract §2 ya lista el touch-target entre los sistemas
transversales que una receta CONSUME y nunca acuña, así que la lectura cruda
es el contrato cumpliéndose. El censo la cuenta `global` sólo porque su lista
`system` aún no conoce el token — el pendiente de firma «extender la clase
system a las capas compartidas».
POR QUÉ 81 % ES EL TECHO
Los diez knobs que quedan fuera leen `--_radio-group-palette-*`: el puente
THM-2 que la capa compartida alimenta por instancia desde `[data-color]`. Un
público encima dejaría que un tema lo fijara y matara el `color=` de cada
instancia. No es deuda; es el componente cerrado en su número.
TRES DECLARACIONES QUE NO PINTAN (medidas, y las tres mueven píxel → firma)
1. La escala del punto NUNCA ha pintado. `<SvgDot>` escribe
`style="width: 1em; height: 1em"` y un inline gana a cualquier regla: el
punto computa 13,3281px en las CINCO tallas mientras el token dice
5/6/7/9/11px, el valor centinela no lo mueve, y quitando el estilo inline
el MISMO token pinta 1234px. Clase «canal de valor inline» del trío
`carousel.item-gap*`, pero con arreglo posible: la forma `!important` que
recipe-contract §3 autoriza justo para saltarse un estilo inline.
2. `[data-radio-group-label][data-disabled]` no casa jamás. Con el grupo
entero deshabilitado la etiqueta lleva `[id, data-radio-group-label,
data-archetype]` y nada más: soma no estampa `data-disabled` en la parte
`Label` (el morfo declara `data: []`). Forzado a mano el token alcanza, o
sea que falta el ATRIBUTO, no la clave — decisión de MORFO.
3. El fondo de un radio marcado Y deshabilitado no llega: la regla de
variante es (0,4,0) y `[data-radio-group-item][data-disabled][data-state=
'checked']` sólo (0,3,0). Medido con el centinela escrito: solid da el
acento a plena intensidad, outline y segmented transparente, ghost la
mezcla al 18 %. Quitar `data-variant` no ayuda: el gemelo
`:not([data-variant])` también es (0,4,0).
Y una cuarta, de escala del SISTEMA y por tanto fuera de este eje (D-TH.5):
el `:hover` del círculo es (0,4,0) y el tinte inválido (0,3,0), así que pasar
el ratón por encima TAPA el borde de error. Las cuatro, en next-features §13.
EL INSTRUMENTO MEDÍA 27 DE 61
No veía el punto (es un `<svg data-svg='dot'>` sin atributo del componente),
ni la variante `segmented` (doce claves), ni los estados disabled / invalid.
El guard lleva ahora `extraNodes` para el punto, el barrido de `data-variant`
y DOS URL más — `?perm.disabled=true` y `?perm.invalid=true`, que esta demo
honra: once adjudicaciones sustituidas por medición real.
CENTINELA 45/69, 24 adjudicadas: 6 del punto (estilo inline), 8 tonos por la
cascada de paleta (mismo patrón que su gemelo checkbox, medido aquí: la clave
no mueve nada, `--palette-solid` en el nodo repinta), 4 del par de transición
congelado, 2 del anillo inválido (necesita `:focus-visible` con modalidad de
teclado), `gap-horizontal` (el par de gap, sólo pinta la mitad en vigor),
`segmented-pill-shadow` (la píldora sólo la renderiza el envoltorio bajo la
variante real), `disabled-item-label-fg` y `checked-disabled-indicator-bg` (las
dos declaraciones muertas de arriba).
GUARDS
censo --only radio-group 81 % · global 68 % (no baja) · component-audit PASS ·
eidos-lint 0 invalid (13 morfo-backed, 24 eidos-only) · vitest src/uix/eidos
sin rojos nuevos (el único es `skin-media-player`, conocido) · rtl:check 0 ·
docs:check 0 · prettier OK sobre el contenido normalizado a LF · check sin
errores en ficheros del componente.
README con su sección «Talla y tema» y la demo con su pestaña Tokens (69
claves, verificada en navegador).
Índice construido a mano desde HEAD sobre los seis ficheros compartidos
(recipes/base.ts, generated/base.css, theming-sentinel.ts,
theming-sentinel-exceptions.ts, PLAN-theming.md, next-features.md): otras
cuatro sesiones los escriben a la vez. Fuera del commit, docs/audit/theming/
README.md — es un agregado global que mezcla trabajo en vuelo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
bc9b9016bb |
docs(theming): file-upload barre DESCENDIENTES y se come el token de sus huéspedes
Lo destapó la sesión de chat-composer y lo dejó sin registrar a propósito (este fichero estaba en manos de otra sesión); la medición de aquí es propia. file-upload declara `[data-file-upload] [data-disabled]` — un selector de DESCENDIENTE, (0,2,0), el mismo peso que `[data-chat-composer-send][data-disabled]`, y se emite más tarde. Dentro de un FileUpload, que es donde la composición documentada pone al composer, el token del composer muere. Medido desde los dos asientos sobre el mismo nodo deshabilitado: suelto y envuelto computa 0.4 en los dos casos —los defaults coinciden, así que el VALOR no delata nada—, pero envuelto la clave del composer desde :root no lo mueve y la de file-upload sí (0.4 -> 0.321). Es invisible hasta que un tema mueva uno de los dos, y entonces el huésped no responde a su propia clave. file-upload es HOY el único componente del catálogo con un barrido así: una sola ocurrencia en las 162 recetas. No es una clase, es una regla concreta que se puede acotar — pero acotarla mueve el píxel de cualquier huésped deshabilitado que hoy hereda, así que es firma, no commit de theming. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
b4e4fe1fe8 |
docs(theming): la sonda y el guard no se pueden lanzar con --import tsx/esm
Medido supervisando calendar. Cualquier script del eje que use page.evaluate muere con «ReferenceError: __name is not defined» DENTRO del navegador: el transform de esbuild que trae tsx envuelve las funciones con su ayudante keepNames, el cuerpo de la evaluación viaja serializado a la página y llega sin él. Reproducido en __theming-probe.ts y en theming-sentinel.ts. Se lanzan con node a secas — Node 24 desnuda los tipos de forma nativa, que es justo lo que hace npm run theming:sentinel. Sólo los scripts SIN page.evaluate (censo, component-audit, eidos-lint) toleran el --import tsx/esm. Vale una sesión entera si se confunde, porque el error no nombra ni a tsx ni a la sonda: nombra una variable que nadie ha escrito. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
509d1144ff |
uix(calendar): temable — 84 % → 89 %, y una entrada de FAMILIA no se juzga en la ruta de UN componente
CERO claves acuñadas: el censo no tenía nada que coser. Su columna `global` ya
era 0 desde la capa calendar-surface (2026-08-21), así que lo único fuera de
alcance eran cuatro literales de IDENTIDAD. Todo el trabajo fue MEDIR, y ahí
estaba el hallazgo.
Qué entra:
- Cuatro literales firmados con su razón (recipe-contract §3), fuera del
ratio: el inline-size: max-content del panel y de la tabla (su anchura ES
day-size × 7 más el espaciado — precedente progress), el min-inline-size:
max-content del panel de mes y el inline-size: 100% de la cabecera. La
propuesta §4 pedía acuñar width / month-panel-width / grid-width para ellos:
sería dar a un tema la anchura de una caja cuya anchura es su contenido.
- Ninguna línea de CSS nueva. Las 74 claves del contrato quedan como estaban.
Censo: 84 % → 89 % (71 knobs, 57 públicos, 4 literales → 67 knobs, 57
públicos, 0 literales, 4 excepciones). Los 7 que quedan fuera son los forwards
de paleta THM-2: no se acuñan. CERRADO en su 89 %. Global 68 %, no baja.
Centinela R-5.4: 45/74 → 68/74, 6 adjudicadas. Verde (exit 0).
Lo que enseñó:
1. Una entrada de receta de FAMILIA no se puede juzgar en la ruta de UN
componente. Esta entrada es el vocabulario de las cuatro superficies de
rejilla de fechas (lo dice lib/calendar-surface.css): range-calendar,
month-grid y year-grid consumen --calendar-* y no acuñan nada — de ahí su
0 % HONESTO. Sus partes llevan data-month-grid-* / data-range-calendar-*,
invisibles al filtro data-calendar: 23 de sus 29 «tokens muertos» eran eso.
Con urls a las tres rutas + extraNodes + barrido de variant, 45/74 → 68/74.
Los tres consumidores NO se han tocado y siguen en su 0 % honesto.
2. Y la propia demo tapa tres claves más: su cabecera monta SELECTORES de mes
y año donde iría el heading, así que heading-{fg,font-size,font-weight} no
tienen nodo aquí; los tiene month-grid.
3. HALLAZGO — el tamaño de letra de los selectores de mes / año es NO
DETERMINISTA. La sonda dio 36 diffs contra un cambio que era SÓLO
comentarios; corrida dos veces sobre el MISMO código dio 24, en los mismos
dos nodos y las mismas dos propiedades. Causa medida:
[data-calendar-month-select][data-button] (calendar-select.css, la regla
que existe precisamente para fijar la letra del Button a la del calendario)
y [data-popover-trigger]:not([data-archetype='field-trigger'])
(popover.css) empatan a (0,2,0), así que gana el módulo que Vite inyecte el
ÚLTIMO: cuatro cargas dieron 14 / 16 / 14 / 14 px, con el orden de las
hojas invertido en la que dio 16. Es la clase del empate por orden de carga
de tree-grid (§12); arreglarlo mueve píxel → next-features §13.
Regla que confirma: ante un diff inesperado, corre la sonda dos veces sobre
el mismo código ANTES de sospechar de tu cambio.
4. calendar.select-min-width no tiene nodo en NINGUNA página del repo: su
único consumidor es [data-range-calendar-month-select] / -year-select, y la
demo de range-calendar renderiza un heading de texto mientras
DateRangePicker importa los selectores del CALENDARIO. Hueco de demo → §13.
Diff de computed: sonda antes/después, 22.656 valores en 7 estados. Los 36
diffs son ÍNTEGRAMENTE el no-determinismo del punto 3 (misma corrida contra sí
misma: 24) y caen en dos nodos y dos propiedades; fuera de ellos, 0. Capturas
2× antes/después: IDÉNTICAS byte a byte.
Guards: censo --only calendar 89 % · component-audit PASS · eidos-lint 0
invalid · vitest src/uix/eidos sin rojos nuevos (los dos son ajenos:
skin-media-player, el conocido, y un fantasma de radio-group de otra sesión) ·
rtl:check 0 · docs:check 0 · npm run check COMPLETED con 0 errores en ficheros
de calendar · prettier limpio sobre el contenido normalizado a LF.
README «Talla y tema» actualizado y pestaña Tokens en la demo (74 claves,
verificada en navegador: 0 errores de consola).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
cc010f79aa |
uix(select): temable — 83 % → 92 %, y un token que ALCANZA y aun así no pinta
Dos claves de COSTURA (PLAN §2-A: el valor es del sistema, el knob es del componente) y tres literales de identidad firmados. Ni un píxel movido. Qué entra en el contrato (101 → 103 claves): - invalid-border — las TRES declaraciones del estado inválido (el borde en reposo, el borde con foco/abierto y el anillo box-shadow que lo dobla) leían --color-risk-border A PELO. Es UNA clave, no dos: la propuesta §4 pedía invalid-trigger-border + open-invalid-trigger-border, y las filas agrupadas por VALOR son una sola. Bare como sus vecinas disabled-* (las ranuras de estado de esta receta son las del trigger) y como las siete invalid-border del catálogo. - group-gap — el hueco entre filas de un grupo iba a var(--space-1) directo. Nombre CONTADO en base.ts antes de acuñarlo: toolbar.group-gap. Tres literales firmados con su razón (recipe-contract §3), fuera del ratio: los dos inline-size: 100% (identidad — el select ES la anchura de su contenedor, el trigger ES la caja del select) y el opacity: 1 del check revelado, que deshace el 0 de la regla base. Censo: 83 % → 92 % (72 knobs, 54 públicos, 3 globales, 3 literales → 69 knobs, 57 públicos, 0 globales, 0 literales, 3 excepciones). Los 5 que quedan fuera son los forwards de paleta THM-2 leídos a pelo: no se acuñan. CERRADO en su 92 %. Global 68 %, no baja. Diff de computed: sonda antes/después, 2.176 valores en 8 estados = 0 diffs. Capturas 2× antes/después (cerrado y abierto): IDÉNTICAS byte a byte. Centinela R-5.4: 69/103, 34 adjudicadas en el ledger, todas MEDIDAS sobre el nodo real con las transiciones congeladas. Verde (exit 0). Lo que enseñó, todo del PORTAL: 1. El guard tiene que mantener el panel ABIERTO para medir los ~30 tokens de dentro, y el estado abierto TAPA los de reposo: trigger-border y trigger-indicator-fg leen muertos abiertos y MUEVEN con el panel cerrado. El instrumento sólo puede estar en un estado a la vez. 2. Tres knobs viven en nodos SIN data-select-*: la z del panel está en el [data-floating-wrapper] que soma porta (el caso popover.content-z) y el ritmo del viewport lo pinta el ScrollArea compuesto. Con extraNodes, 65/101 → 69/103. Nodos: 4 en reposo, 42 con el panel abierto. 3. La cascada de paleta anula sus 24 tonos, aquí en su forma MULTI-PARTE (trigger + content, porque el panel se porta fuera). Medido sobre el trigger abierto: --select-primary-border no mueve nada, --palette-border sobre el mismo nodo repinta. 4. separator-size ALCANZA y aun así no pinta: flex-shrink 1 en la columna del ScrollArea y un panel que desborda (scrollHeight 670 vs clientHeight 310) aplastan su 1px a 0px; con flex-shrink 0 el token sigue (1px → 9px). Un token vivo sobre un nodo aplastado lee igual que uno muerto. Defecto de píxel → next-features §13, no se arregla en este eje. §12.9 respetado: el contenido lleva data-depth=overlay, así que no se acuñó font-family ni line-height para el panel. Guards: censo --only select 92 % · component-audit PASS · eidos-lint 0 invalid · vitest src/uix/eidos sin rojos nuevos (los dos rojos son ajenos: skin-media-player, el conocido, y un fantasma de radio-group de otra sesión) · rtl:check 0 · docs:check 0 · npm run check COMPLETED con 0 errores en ficheros de select · prettier limpio sobre el contenido normalizado a LF. README con su sección «Talla y tema» y pestaña Tokens en la demo (103 claves, verificada en navegador: 0 errores de consola). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
8a4bb8e0e8 |
docs(theming): el párrafo que faltaba de la corrección anterior
El commit
|
2 months ago |
|
|
009af3300d |
docs(theming): el canal inline filtrado al contrato son CUATRO claves, no dos
La entrada §13 del falso positivo inline decía que de los siete wrappers que
escriben un token público en el style, dos estaban en el contrato. Eran cuatro:
los dos de avatar parecían fuera porque su bloque de base.ts es una IIFE que el
censo no supo leer hasta
|
2 months ago |
|
|
b7f5a7d75a |
docs(theming): la cascada de paleta se lleva también el tono POR DEFECTO
El §13 decía que las claves `{c}-primary-*` son el respaldo de la regla
genérica y salvan a la instancia SIN `data-color`. Es cierto donde el atributo
puede faltar — y hay componentes donde no puede.
Cuando el proveedor de soma trata el color como un valor RESUELTO, estampa
`data-color` en toda instancia y `neutral` es su default, no su ausencia. Ahí
el bloque genérico casa siempre y no queda respaldo: medido en `switch` en
estado checked, `--switch-neutral-solid` no mueve nada mientras `--palette-solid`
sobre el nodo repinta.
Amplía el alcance de la firma pendiente: no es «los tonos no canónicos»,
son los tonos. Lo destapó la sesión de `switch` al adjudicar sus doce claves de
tono y encontrarse `neutral` cayendo con las otras once.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
ebfa1ce5ef |
fix(theming): el guard da por VIVO lo que un tema no alcanza — y dos bloques del ledger se descartaban en silencio
Dos defectos del instrumental, los dos medidos, ninguno arreglado en el guard
todavía (el arreglo toca a todos los componentes y pide su re-verificación).
EL GUARD TIENE FALSOS POSITIVOS: ESCRIBE EL CENTINELA EN EL style INLINE
`staticPass` escribe el token en documentElement Y en todos los nodos del
componente — y ahí es donde vive el canal inline de los wrappers. Si un wrapper
escribe un token PÚBLICO en el `style` del nodo, el guard lo pisa, ve el cambio
y lo da por VIVO, aunque un tema (que sólo puede escribir en :root o en una
hoja) no lo alcance jamás. Es la cara opuesta de drag-drop.preview-z.
Censo: siete wrappers escriben un --{c}-* público inline y DOS están en el
contrato — dialog.overlay-opacity y drawer.overlay-opacity. Medido en dialog con
el diálogo abierto y las animaciones congeladas: desde :root el fondo del velo NO
se mueve (color(srgb 0.1098 0.098 0.0902 / 0.2518) idéntico), desde el inline SÍ.
Su token MIENTE y el guard lo bendice. Los otros cinco no están en ningún
contrato: son sólo canal.
El arreglo propuesto va en §13: escribir en todos los nodos MENOS en los cuyo
`style` ya declara ese mismo token, y avisar cuando ocurra — no basta con
escribir sólo en :root, porque eso es justo lo que hace medibles los paneles
portalados. Con re-verificación del ledger entero, así que no entra aquí.
El veredicto de dialog (commiteado hoy) queda corregido con la medición.
DOS BLOQUES DEL LEDGER SE DESCARTABAN EN SILENCIO
`metrics` y `color-picker` aparecían DOS VECES en el mismo literal de objeto, así
que el primero de cada par no existía para el guard — la trampa que el handoff
documenta para base.ts, un piso más abajo. Comprobado antes de tocar nada: en los
dos casos el bloque que gana es SUPERCONJUNTO del muerto, así que no se perdía
ninguna adjudicación; era deuda con riesgo futuro, no un rojo. Retirados los dos
bloques muertos: 69 → 67 entradas, cero duplicados, y `metrics` (54/72) y
`color-picker` (46/71) siguen en verde. De paso, el fichero baja de 63 a 61 hunks
de prettier preexistentes.
Lo destapó la sesión de `progress` al leer el fichero para añadir su bloque.
Rama con varias sesiones en paralelo: índice construido desde HEAD + sólo mis
hunks, verificado con git diff --cached.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
f68bac4a66 |
uix(avatar): temable — 75 % → 90 %, y su contrato era INVISIBLE para los dos instrumentos
Protocolo PLAN-theming §7 sobre `avatar` (incluye `AvatarGroup`, que comparte
receta y fichero). Censo 75 % → **90 %**, contrato 84 → 88 claves, centinela
**83/88** con 5 adjudicadas. El default NO se mueve.
## Lo primero: el instrumento no veía el contrato
La entrada `avatar` de `recipes/base.ts` es la ÚNICA construida por una IIFE (un
helper local genera sus 24 ámbitos compuestos), así que su mapa vive en el
`return {`, un tabulador más adentro. Consecuencia medida:
- el censo la leía como «sin entrada en base.ts» — 84 claves invisibles;
- el centinela **moría** con `no recipe block for avatar`: el componente no se
podía medir, y su gate no significaba nada.
Los dos lectores leen ya la IIFE (dedentan el `return`). Sin este arreglo, todo
lo demás de este commit habría sido humo.
## Lo que entra al contrato (6 claves)
`group-overlap-{xs,sm,md,lg,xl,xxl}` — la escala de solape de `AvatarGroup`.
Había UNA clave, `--avatar-group-overlap`, y la receta la RE-DECLARABA en seis
bloques `[data-size]`: sentada en el elemento, ganaba siempre al `:root` donde
escribe un tema. Medido: `37px` desde el asiento del tema no movía el margen; el
mismo valor escrito sobre el nodo, sí. Ahora el paso viaja por
`--_avatar-group-overlap` y los seis alcanzan desde `:root` (−8,4 · −11,2 · −14 ·
−16,8 · −22,4 · −33,6 px → 37 px, uno a uno).
## Lo que se retira (2 declaraciones muertas, diff 0 las dos)
- `group-max`: el envoltorio escribía `--avatar-group-max` INLINE y la receta
declaraba su default `99`. **No lo leía nadie** — el tope se aplica con
`data-has-max` + `:nth-child(n + M)` porque una variable no entra en
`:nth-child()`, y lo dice el propio comentario del CSS. Retirado de los dos
sitios; el `+3` del grupo sigue exactamente donde estaba.
- el respaldo `, white` de `--_avatar-badge-fg`: el contrato ya declara
`--avatar-badge-color-custom-contrast: white`, así que era inalcanzable y sólo
podía envejecer contra su token. Comprobado en la rama custom: la tinta sigue
computando `rgb(255, 255, 255)`.
## Seis literales firmados (salen del ratio)
Los cuatro `100 %` de Image y Fallback son IDENTIDAD — la parte ES la superficie
del avatar, no una talla propia — y los dos `line-height: 1` mantienen el glifo
centrado por la caja flex.
## Lo que se queda privado (el techo real es 90 %)
`--_avatar-bg`, `--_avatar-fg` y `--_avatar-badge-bg` son un CONMUTADOR: cambian
de fuente con la variante (solid · soft · outline) y su valor sale del forward de
paleta THM-2 que la capa de color alimenta por instancia desde `[data-color]`.
Un público encima dejaría que un tema los fijara y matara el `color=` de cada
avatar.
## Artefactos
- Sonda: **0 diffs** en TRES bases — demo de avatar con insignia y anillo (576
valores), la misma en modo fallback (384) y demo de AvatarGroup (3.072).
- Capturas 2× antes/después de las dos demos: **idénticas al byte**.
- Centinela R-5.4: 83/88, 5 adjudicadas con su medida en el ledger (`size-xxl` y
`font-size-xxl` viven en el paso `xxl`, que el barrido del guard no alcanza —
el límite que `metrics` ya registró; `radius-none` y `ring-width-sm` son «sólo
el paso en vigor pinta»; `group-overlap-xxl` junta las dos cosas).
- El guard aprende `avatar`: la insignia y el anillo son OPT-IN, el barrido de
`data-variant` destapa las 16 claves `*-outline-*`, y `AvatarGroup` se mide en
su propia ruta (21 muertos → 5).
- `eidos-lint` 0 invalid · `vitest src/uix/eidos` sin rojos nuevos (el conocido
`skin-media-player`) · `rtl:check` 0 · `docs:check` 0 · `npm run check`
COMPLETED sin un solo error en `avatar`.
- README «Talla y tema» + pestaña `Tokens` (88 filas, verificada en el navegador
con `networkidle` y clic real).
## Lo que NO se arregla aquí (anotado)
- **R-5.3 preexistente**: cuatro claves `*-color-custom*` donde la gramática
exige `fg`. Son escotillas que el envoltorio escribe INLINE, así que
renombrarlas cambia el contrato público de tres canales: se lista, el audit
sigue en NEEDS-WORK por esto y sólo por esto.
- **Falso POSITIVO nuevo del centinela** (next-features §13): escribe el token
en `:root` y también sobre cada nodo, y para una propiedad personalizada que
la receta re-declara en el ELEMENTO ese inline gana justo lo que un tema
pierde. Es lo que hacía que `--avatar-group-overlap` leyera vivo.
- **El barrido de tallas del guard para en `xl`**: añadir `xxl` dejaría STALE
las seis excepciones de `metrics`, así que se hace con la re-verificación del
ledger entero.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
9c3f17fa60 |
uix(form): temable — 71 % → 86 %, y 24 claves suyas NO PINTAN por una cascada
Diez claves nuevas (54 → 64), un literal firmado, veinte adjudicaciones medidas
y un hallazgo que espera firma. Diff de computed 0 sobre 832 valores en 7
estados; capturas 2× antes/después.
LAS DIEZ IBAN A LOS PRIMITIVOS A PELO
El resumen de errores (error-summary-{bg,fg,border}) —es el señalizador de nivel
de página y su superficie, su tinta y su borde SON el tono risk—, el acento de
formulario inválido (invalid-accent, un privado con UNA sola fuente, no un
conmutador), las tres superficies del árbol de AutoFields, las dos del widget y
el subrayado a media tinta de los enlaces del resumen (link-underline-fg, el par
del -offset que ya existía).
⚠ R-5.3 CAZÓ MI NOMBRE EN EL ACTO: lo acuñé como link-underline-color y la tinta
es `fg` (theming §6.7 r7, firmado el 20). Renombrado antes de commitear. El
guard de nombres funciona — es el vocabulario DIMENSIONAL el que no cubre (ver
badge, hoy mismo).
⚠⚠ VEINTICUATRO CLAVES DEL CONTRATO NO PINTAN, Y ES UNA CASCADA
[data-form-submit], [data-form-reset] y los dos botones del array llevan también
data-button porque COMPONEN el Button canónico, y [data-button] casa con la
MISMA especificidad (0,1,0) pero carga DESPUÉS: gana button.css. Medido
propiedad a propiedad sobre el nodo real —altura, padding-inline, tamaño y peso
de letra, interlineado, hueco, radio, grosor de borde, el par de transición y la
opacidad deshabilitada—: NINGUNA se mueve.
Es el defecto que gradient-picker documentó (36 de sus 45 claves) y que
emoji-picker encontró hoy en su trigger. Allí la respuesta fue RETIRAR las
declaraciones muertas; aquí son 24 claves públicas, y eso es una decisión del
autor, no del que ejecuta. Quedan adjudicadas POR PATRÓN (una razón
arquitectónica escrita una vez) y anotadas en §13 con la pregunta de fondo, que
es la misma de §12.9 con el plano overlay: qué manda, el componente compuesto o
la receta que lo compone. Si mandan las recetas, se sube la especificidad y no
se retira nada; si mandan los compuestos, hay ~63 claves públicas que retirar en
tres componentes.
LAS DEMÁS ADJUDICACIONES SON RAMAS QUE LA DEMO NO MONTA
El layout grid (forzado alcanza — y ojo: su grid-template-columns sólo CAMBIA si
el valor altera el número de columnas; con 90px pasa de una columna de 502px a
cuatro de 110,5), el resumen de errores VACÍO (sin <ul> que indentar ni <a> que
subrayar) y toda la rama de ARRAY de AutoFields: el modo `auto` de la demo monta
group y field, nunca array, item ni widget.
Fuera por doctrina: los tres privados del panel son un CONMUTADOR (variante
plain contra panel) y los cuatro --_form-action-* leen el forward de paleta
THM-2.
VERIFICACIÓN
Sonda antes/después 0 diffs (832 valores · 7 estados) · R-5.4 22/64 con las 20 +
el patrón adjudicados, exit 0 · component:audit PASS (tras el renombrado) ·
--names 0 desviadas · censo --only 86 % · eidos-lint 36 morfo-backed / 0 invalid
/ 0 class-hooks · rtl:check 0 · docs:check 0 · suite eidos 439/440 (el rojo
conocido) · el ledger sigue en sus 63 hunks de prettier previos.
Rama con cuatro sesiones en paralelo: índice construido desde HEAD + sólo mis
hunks (base.ts por bloque), verificado con `git diff --cached`. No entra
docs/audit/theming/README.md — es un agregado global que ahora mismo mezcla
trabajo en vuelo de otras sesiones.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
863c6993c8 |
uix(emoji-picker): temable — 61 % → 100 %, y el cromo del trigger NO era suyo
Siete claves nuevas, TRES RETIRADAS por muertas, tres literales firmados y cinco
adjudicaciones medidas. Contrato 17 → 21. Diff de computed 0 sobre 6.080 valores
en 8 estados (176 nodos con el panel abierto), capturas 2× idénticas.
LOS NOMBRES LOS DIO EL CATÁLOGO
`open-trigger-fg` (accordion lo nombra igual), grid-padding-inline +
grid-padding-block-end (el eje lógico completo, como card-group / combobox /
command) y las tres del marcador de tono, la familia
timeline.marker-{size,radius,bg}. Se llama tone-marker-* y no marker-* porque el
pie lleva además un selector de TONO: dentro del propio componente, `marker` a
secas sería ambiguo.
TRES CLAVES RETIRADAS — EL CROMO DE REPOSO DEL TRIGGER NO ES SUYO
El trigger lleva también data-popover-trigger, y
[data-popover-trigger]:not([data-archetype='field-trigger']) es (0,2,0) contra
el (0,1,0) de esta receta: el radio, la tinta y el tamaño de letra los pinta
popover.css. Medido: mover --emoji-picker-trigger-{fg,radius,font-size} no
cambiaba NADA. Retiradas con sus declaraciones, 0 diffs — la prueba de que
estaban muertas. Es el defecto que gradient-picker documentó (36 de sus 45
tokens) y la misma respuesta. Sobreviven dos por razones distintas:
trigger-size, porque popover dimensiona con `height` y no con el par lógico, y
open-trigger-fg, porque su selector añade [data-state='open'] y gana por orden.
trigger-fg no llegó a existir: se acuñó y se midió muerta en el mismo pase.
CINCO ADJUDICACIONES, TODAS SOBRE NODOS REALES
Las tres del marcador de tono (la demo monta CERO celdas data-tone-capable;
forzado el atributo sobre una celda real, el ::after alcanza: 4px → 37px,
9999px → 37px, y el fondo), preview-name-fg (los hijos de la vista previa son
<span> desnudos, sin atributo del componente, fuera del conjunto medido) y
open-trigger-fg.
⚠ open-trigger-fg OSCILA ENTRE CORRIDAS: 17/21, 16/21, 16/21 con el mismo
código. Medido vivo CUATRO veces —la última replicando paso a paso el staticPass
del propio guard, que movió a la primera talla—, así que el token no miente: lo
que falla es el instrumento. La causa: el panel se cierra en algún punto de la
pasada y, durante la animación de SALIDA, el content sigue en el DOM mientras el
trigger ya perdió data-state='open', que es lo que la regla selecciona;
reopen() mira el CONTENT, cree que está abierto y no reabre. Probé un openMarker
sobre el trigger y NO basta (el clic de reapertura cae en esa misma ventana), así
que lo retiré en vez de dejar un override que no arregla. El arreglo real es que
reopen() espere a la CONDICIÓN en vez de dormir un número fijo — §13. Su entrada
de ledger saldrá STALE en las corridas donde alcanza, y está escrito en la razón
para que nadie la borre por eso.
Y EL INSTRUMENTO DE CAPTURA ESTABA ROTO DESDE SIEMPRE
__shot.ts tenía el puerto 5173 CABLEADO, así que cualquier sesión en otro puerto
moría con ERR_EMPTY_RESPONSE. Es probablemente por lo que los pasos 6 y 13 del
protocolo se saltaron en 33 componentes sin que nadie lo notara. Ahora toma la
URL como argumento —como la sonda y el guard— y un --open opcional para los
componentes cuya superficie sólo existe abierta. Estrenado aquí: capturas antes
y después, miradas y idénticas.
VERIFICACIÓN
Sonda antes/después 0 diffs (6.080 valores · 8 estados) · R-5.4 17/21 con las
cinco adjudicadas, exit 0 · component:audit PASS · censo --only 100 % ·
eidos-lint 17 morfo-backed / 0 invalid / 0 class-hooks · rtl:check 0 ·
docs:check 0 · suite eidos 439/440 (el rojo es skin-media-player, el conocido) ·
el ledger sigue en sus 63 hunks de prettier preexistentes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
0c29c544b1 |
docs(theming): la revisión adversarial §7.7 de los 26 commits — 5 hipótesis, 5 refutadas
Cierra el punto P5 del plan de la revisión: lo ejecutado desde el 22 (33 componentes, dos bloques) por fin tiene su pasada escéptica, con medición propia y no leída de los commits. LA BASE, ANTES DE COMPARAR NADA Worktree en |
2 months ago |
|
|
2f243e1c08 |
docs(theming): la revisión del 23 entra al repo, y el protocolo aprende de sus dos huecos
Añade `REVIEW-theming-2026-08-23.md` —el análisis de los 26 commits posteriores a la revisión del 22 (33 componentes) que no habían pasado ninguno— con lo comprobado, lo refutado y el plan, ya marcado como ejecutado salvo P5. PLAN §7: las capturas 2× (pasos 6 y 13) no se hicieron en NINGUNO de los 33 componentes de los dos bloques. No se recuperan hacia atrás —para ésos el artefacto es el diff en vacío más el centinela—, así que se exigen DESDE el siguiente, y el paso 12 (píxel hacia arriba) queda obligatorio en cuanto el commit toque una regla :hover, que es justo donde el 19 costó cuatro commits. next-features §13 recoge dos huecos más que salieron midiendo: - el escenario de la demo de `background` cambia de ancho entre corridas (870 ↔ 1.350 px con el mismo código), y produce diffs de inlineSize que parecen regresión: una corrida con diffs SÓLO de inlineSize se repite antes de creerla; - `audio-player` no tiene README propio — el cuarto canónico sin ruta de demo es además el único sin documento, así que su «Talla y tema» queda pendiente de que exista dónde ponerla. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
bfe7727b0c |
fix(badge): la clave se llamaba como la PROPIEDAD — min-block-size-{k} → min-height-{k}
Corrección de nombre, sin píxel: la clave por talla que entró esta tarde salió
como `min-block-size-{k}` —el nombre de la propiedad CSS— cuando la ranura del
vocabulario para ella es `height`.
LO DICE EL CANON Y LO DICE EL PROPIO CENSO
recipe-contract §1: «Control height per size → control-height-{size} (o
{part}-height-{size} cuando la parte no es el control) · antipatrón: inventar un
tercer nombre por componente». Y `theming-census.ts` mapea, en su tabla de
propiedades, `min-block-size → height`: la herramienta que mide ya sabía cuál
era la ranura.
MEDIDO EN EL CATÁLOGO, NO SUPUESTO
24 componentes dimensionan por `…-height-{k}` (accordion, field, table,
tree-grid, sidebar, navigation-menu, select, tabs…) y `min-block-size-{k}`
existía SÓLO en badge. El gemelo con la forma exacta —raíz, por talla, sobre
`--size-{k}-control-height`— es `proof-of-human.min-height-{k}`, que además
resuelve igual (clave `min-height` con `declarations` por talla).
R-5.3 NO LO CAZA, Y ESO ES LO INTERESANTE
El guard de nombres cubre la ranura de tinta (`fg` vs `color`) y la posición del
modificador, pero no el vocabulario DIMENSIONAL: una clave con el nombre de la
propiedad pasa. Anotado en next-features §13 con el arreglo propuesto (extender
R-5.3 con la tabla propiedad → ranura que el censo ya tiene).
Verificación: sonda antes/después **0 diffs** (992 valores · 7 estados · 5
nodos) · R-5.4 29/71 idéntico, exit 0 · censo --only 75 % sin cambio ·
`--names` 0 desviadas · docs:check 0 · suite eidos 439/440 (el rojo conocido) ·
`component:audit` NEEDS-WORK preexistente (R-1.5, sin foco).
Sale de la revisión de hoy (`REVIEW-theming-2026-08-23.md`, punto P1).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
233ef989b3 |
fix(theming): float-panel tenía DOCE rojos sin medir — el guard R-5.4 vuelve a verde
El barrido del centinela sobre TODO el ledger (59 componentes) destapó que `float-panel` fallaba: 17/40 con doce tokens públicos sin adjudicar. No es regresión —la bisección de las NUEVE versiones del guard desde `cd6a9f4e3` da siempre 17/40 con los mismos doce— sino un rojo que su propio commit del 22 dejó escrito («lo rojo que queda son 12 tokens anteriores») y que nadie midió. Y la frase del handoff «desde el 23 no queda ningún rojo del bloque viejo» era FALSA: se adjudicaron drawer, metrics y color-picker; éste no. Corregida, con la lección: un componente cuyo commit dice «lo que queda» NO está cerrado, y la única forma de saberlo es correr el guard sobre el ledger ENTERO. LOS DOCE, MEDIDOS UNO A UNO SEIS son el plano de profundidad, y la predicción del 22 era exacta: el contenido lleva data-depth=overlay y [data-depth=overlay] declara background, border, box-shadow, font-family y line-height a la MISMA especificidad (0,1,0) y más tarde en la cascada. Verificado moviendo los tokens del propio plano sobre el nodo (superficie, borde, fuente y leading lo repintan) y enumerando las reglas que casan. border-width cae con border (el plano escribe el shorthand). Misma adjudicación que tooltip, misma decisión abierta (§12.9). ⚠ Y una corrección a mi propio diagnóstico: primero atribuí la sombra a [data-topmost] porque el panel de la demo arranca frontal. Falso — quitando el atributo sigue muerta: es el plano también. Lo que sí depende de topmost es su compañero shadow-topmost, que SÍ alcanza (→ rgb(4,5,6)) porque su regla es (0,2,0) y le gana al plano: la prueba de que la causa es la cascada y no un token roto. TRES son estados o partes que la demo no monta: active-shadow (forzado data-dragging → alcanza), resize-size (lo consumen las asas de ESQUINA se/ne/sw/nw y la demo monta sólo las de borde, e y s) y button-size (lo consumen [data-float-panel-action] y [data-float-panel-stage-trigger], ninguno montado — el único control es el cierre, un <Button> compuesto que se dimensiona solo: el mismo grupo que las tres action-* ya adjudicadas). UNO es el PUENTE DE PALETA: el contenido lleva data-color, así que --_float-panel-accent viene del forward THM-2 (--_float-panel-palette-border → rgb(7,8,9)); sin data-color la clave alcanza (→ rgb(1,2,3)). DOS son la ley del congelado: transition-duration / -ease no pueden moverse bajo un guard que congela `transition`. Pasada aparte: 0.12s → 11.5s y cubic-bezier(0.4,0,0.2,1) → steps(7). DE PASO, DOS ARREGLOS DE LA MISMA REVISIÓN - `background.parallax-travel` estaba MAL CLASIFICADO como estructural («el escenario no tiene scroll timeline»): lo tiene (animation-timeline: view()). Forzando data-parallax + speed 1, el translate sigue al token (14,6 → 60,5 px al mismo scrollY). La causa real es que el guard NO fotografía translate ni transform — registrado en §13 junto al hueco de mask-image, para entrar en PROPS en un pase con re-verificación del ledger entero. - `cropper`: el hueco de composición que el README daba por «anotado» y no lo estaba, ahora es fila de §Gaps con su disposición. Y las tablas de tokens de `cropper` y `waveform` pasan a la sección «Talla y tema», el molde del resto. La nueva constante PLANE_SUPERSEDED se iza sobre el objeto (un `const` usado antes de su declaración reventaba el guard, y el fallo se veía sólo mirando el exit REAL: tras la tubería, `$?` es el del grep). Verificación: R-5.4 float-panel 17/40 con 23 adjudicaciones, cero STALE, exit 0 · docs:check 0 · el ledger vuelve a sus 63 hunks de prettier preexistentes (mis entradas se reformatearon a mano, sin tocar las ajenas). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
9bdc5a5d5d |
uix(background): temable — 57 % → 95 %, y montar MÁS capas hacía medir MENOS
Seis claves nuevas (31 → 37), tres literales firmados, un privado adjudicado y
19 tokens preexistentes medidos uno a uno: no había pasado por R-5.4.
LAS SEIS CLAVES SON LA MISMA COSTURA, DOS VECES
El patrón mesh leía var(--gradient-aurora) y los cinco pasos de escarcha leían
var(--blur-*), los dos A PELO: el VALOR es del sistema, el KNOB es del
componente. Con scrim-blur-* hay además una razón dura — `blur` es familia
MÉTRICA del eje `scaling` (theming §23), así que un literal ahí sería ciego al
zoom global.
TRES LITERALES FIRMADOS, Y EL GRANO NO SE ACUÑA
El 100% de img/video es identidad (una capa de medio ES la caja de su capa). El
grano del ruido es un feTurbulence en un data-URI: la textura ES la técnica —el
único patrón que el UA no elimina bajo forced-colors— y re-escaparlo para
meterlo en el contrato cambiaría el valor serializado sin cambiar la imagen. Su
mando sigue siendo pattern-noise-opacity.
EL 5 % QUE QUEDA ES CANAL DE VALOR
--_background-gradient-image lo escribe background-gradient.svelte EN LÍNEA
desde la prop `colors`. Un público encima no lo alcanzaría —el inline gana— y
mentiría: el caso de --gp-current-gradient y del preview-z que F2-B retiró.
UNA SOSPECHA MÍA, REFUTADA MIDIENDO
La línea del mesh hace lo que un apunte da por roto: un gradiente MESH por el
longhand background-image (su color base final no es capa de imagen válida →
computa `none`). Medido aquí: --gradient-aurora PINTA, porque su serialización
empieza por un radial-gradient. No hay defecto. La nota vale para un mesh
serializado con color base final, no para este token.
EL GUARD: DE 3/37 A 18/37, Y UNA LECCIÓN AL REVÉS
Las partes de este componente son CAPAS OPT-IN independientes (velo, foco,
pausa…), cada una tras su control, y sólo un patrón se renderiza a la vez: sobre
el escenario por defecto casi todo el contrato no tiene nodo que pintar. Nace
`prepareWith` — enciende TODOS los controles que se le den, al contrario que
`openWith`, que para en el primero — y con el barrido de data-pattern sube a 18.
Y la lección: MONTAR MÁS PUEDE MEDIR MENOS. Encender además el foco puntual, la
velocidad de paralaje y la profundidad bajó la corrida de 17 a 9: los tres
repintan el background-image y el translate de la MISMA capa donde se miden los
patrones. prepareWith se dejó en lo que no tapa.
LAS 19 ADJUDICACIONES, FORZANDO SOBRE LA CAPA REAL
Nunca sobre un nodo fabricado. Las dos del mask (fade-*, que el guard no puede
ver porque no fotografía mask-image — hueco de instrumento, §13), las dos del
contexto de tinta (on=dark/light), los ocho pasos de las dos escalas (blur 4→33,
8→33, 12→33, 24→33 px; strength alpha 0.08 · 0.13 · 0.4 · 0.7 → 0.9), el
gradient-drift-duration (24s → 42s, en una capa gradient que EXCLUYE a la de
patrón), los tres del foco puntual (40% → 42px…, y spotlight-fg sólo cuando la
capa NO lleva data-color: con él manda --palette-solid, por diseño), el
parallax-travel (sólo entra por las keyframes ligadas al scroll) y los dos de la
pausa (la demo no monta ese control: cero nodos).
AVISO: LOS CHIPS DE ESTA DEMO SE APLICAN CON RETRASO
Una comparación por chips capturó cada estado con el patrón ANTERIOR —el estado
«mesh» guardaba el glow— y dio 0 diffs por estar desfasada IGUAL en las dos
corridas: un gate verde sobre dos medidas equivocadas. La prueba buena fue la de
EQUIVALENCIA, determinista: cada token nuevo resuelve al mismo valor que el
primitivo que sustituyó (pattern-mesh-image = --gradient-aurora; scrim-blur-{k}
= --blur-{k} = 4/8/12/16/24 px) y lo pintado al forzar el atributo es idéntico
(el mesh pinta el aurora, el ruido pinta su data-URI intacto).
VERIFICACIÓN
Sonda estándar antes/después 0 diffs (384 valores · 7 estados) · equivalencia
token↔primitivo exacta en las seis · R-5.4 18/37 con las 19 restantes
adjudicadas y medidas, cero STALE · component:audit PASS · censo 95 % ·
eidos-lint 3 morfo-backed / 63 eidos-only / 0 invalid / 0 class-hooks ·
rtl:check 0 · docs:check 0 · suite eidos 439/440 (el rojo es skin-media-player,
el conocido). Tras el cambio del guard, command, table, tooltip,
navigation-menu y waveform re-verificados sin regresión ni STALE.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
11b92ded6f |
uix(waveform): temable — 55 % → 86 %, y el playhead era el ÚNICO primitivo crudo
UNA clave nueva, cuatro literales firmados, un préstamo adjudicado. Diff de computed 0 sobre 1.600 valores en 7 estados; R-5.4 11/11, CERO adjudicaciones. LA CLAVE NUEVA NO LA PIDIÓ EL CENSO, LA PIDIÓ EL FICHERO `playhead-bg`. Todas las demás líneas del re-tinte del Slider embebido leen ya un token propio (--slider-secondary-bg: var(--waveform-buffered-fg)) o una identidad (transparent / none / 0px / 1); el thumb era la ÚNICA que pasaba un primitivo CRUDO (--color-content-primary) a un componente compuesto. Con eso, repintar el playhead exigía mover --slider-thumb-bg (todos los sliders de la app) o --color-content-primary (todo). Ahora es el par natural de `playhead-width`, que ya existía. El molde es el re-tinte de media-player, que reenvía --media-player-* en cada línea. El censo no lo veía: una custom property reenviada a un componente compuesto no entra en KNOB_PROPS (D-TH.2). La clase entera queda anotada en §13 — toda receta que re-tinta un embebido puede pasarle primitivos crudos sin que nada lo vea. EL 14 % QUE QUEDA ES UNA FILA, Y ES DOCTRINA La onda deshabilitada lee var(--slider-disabled-opacity). La prueba de si un token es tuyo no es qué valor tiene sino QUÉ DECIDE: aquí decide cuánto se apaga un control deshabilitado, y eso es del Slider — la onda vive fuera de su caja pero es la misma superficie a la vista. Un --waveform-disabled-opacity daría un segundo mando para UNA decisión y permitiría desincronizar cromo y pintura. Préstamo con dueño: se tema en la ficha de slider, como el 82 % de time-picker se tema en la de field. LOS CUATRO LITERALES SON IDENTIDAD, Y AHORA LO DICEN La pintura ES la caja del provider (100% sobre un position:absolute; inset:0), el área de arrastre ES la caja entera («scrubbing means grabbing anywhere on it»), y un playhead abarca todo el alto por definición. Anotación /* literal: */ en su declaración: desviación firmada, fuera del ratio. EL INSTRUMENTO, CIEGO POR UNA CAUSA NUEVA: EL COMPONENTE COMPUESTO La sonda medía 4 nodos —provider, svg y los dos paths— y NINGUNO era el playhead: el cromo entero es un Slider embebido cuyos nodos llevan data-slider*. Con extraNodes, 8. Es la TERCERA cara del mismo agujero: HTML crudo (prose), partes que compone el consumidor (navigation-menu) y partes de un componente compuesto (waveform). En §13, con la pregunta de fondo: hoy hay que sospecharlo y contar los nodos, el instrumento no lo detecta solo. VERIFICACIÓN Sonda antes/después 0 diffs (1.600 valores · 7 estados · 8 nodos) · R-5.4 11/11 sin adjudicaciones · component:audit PASS · censo 86 % con la única fila restante explicada · eidos-lint 4 morfo-backed / 16 eidos-only / 0 invalid / 0 class-hooks · rtl:check 0 · docs:check 0 · suite eidos 439/440 (el rojo es skin-media-player, el conocido) · Chrome: playhead 2px × 40px, onda 544 × 40, trazo 0.6 — idénticos. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
85988785d4 |
uix(navigation-menu): temable — 44 % → 100 %, y el guard cerraba el panel que medía
Bloque B1 de D-TH.4. Contrato 26 → 44 claves: 19 nuevas y UNA retirada.
Diff de computed 0 sobre 2.752 valores en 8 estados; R-5.4 43/44 con una
adjudicación escrita. Global 65 % (al 100 % 25 → 26).
LOS NOMBRES LOS DIO EL CATÁLOGO, NO YO
Ninguno se inventó. Los gemelos cerrados el mismo día (dropdown-menu 96 %,
context-menu 87 %) dan content-{min-width,padding,radius,fg} y
chevron-{size,stroke}; accordion da trigger-font-family y disabled-trigger-fg.
Las cuatro recetas que declaran un chevron lo dimensionan con un LITERAL
(0.42em · 0.5em · 0.625rem): un glifo no es un paso de la escala de espacio.
Al revés con el subrayado del indicador: su 2px ES --border-width-medium, y
dropdown-menu.separator-thickness dice que un grosor decorativo se nombra por
esa familia.
LA §4 GENERADA FALLA DE CINCO MANERAS, UNA NUEVA
Llamaba trigger-width / trigger-height al CHEVRON — nombrando por el primer
selector de la regla ([…-trigger]::after) y colisionando con trigger-height,
que YA EXISTE y es la altura del control. Fundía en content-radius dos nodos
con dos valores. Cruzaba los nombres: content-padding-* para lo que es de la
FILA, y el padding real del panel a «sin nombre mecánico». Llamaba
content-width a un min-inline-size. Y la nueva: abría exigiendo «consume la
capa compartida menu-indicator» — HOMONIMIA, esa capa es el check de los
CheckboxItem de dropdown/context-menu y no toca el subrayado de esta barra
(LAYER_VOCABULARY sólo registra calendar-surface).
LAS FILAS DEL PANEL NO SON item- NI link-
En los gemelos, `item` ES la fila. Aquí `item` es el <li> de la barra (parte
del morfo) y el Link de barra viste el cromo del trigger: --…-item-radius o
--…-link-radius prometerían a un tema un nodo que no alcanzan. Se acuñan
content-link-*, que nombra el nodo por donde vive. Su tinta sigue leyendo
trigger-fg, como venía.
EL PRIVADO ERA UNA ESCALA, NO UN CONMUTADOR
--_navigation-menu-list-gap tenía tres fuentes (0 / --space-1 / --space-2) por
data-size: sube al TSC como list-gap-{sm,md,lg} + el resuelto, el molde que el
bundle del trigger ya tenía al lado. Los dos bloques [data-size] del CSS se
retiran — los emite el TSC, y dejarlos vivos da un diff de 0 por la ruta vieja.
indicator-x ERA DECLARACIÓN MUERTA
Soma escribe las cuatro coordenadas del rect INLINE sobre el indicador
(-x, -y, -w, -h) y la receta lee sólo -w y -h; su propio comentario registra
que sumar translateX(var(--…-x)) DUPLICABA el desplazamiento. No la leía
nadie. Retirada, 0 diffs — la prueba de que estaba muerta (precedente: el
re-point de --command-radius, el trío item-gap* de carousel). -w se queda:
vive, y es canal de valor, no superficie de tema.
EL PANEL NO ACUÑA TIPOGRAFÍA, A PROPÓSITO
Lleva [data-depth='overlay'], y ese plano declara font-family / line-height a
la misma especificidad (0,1,0) y más tarde en la cascada: un token ahí leería
muerto. Es §12.9, pendiente de firma — la misma que hizo retirar claves en
menubar, dropdown-menu, context-menu y tooltip. Sí se acuña la familia de la
BARRA (trigger-font-family), que no es overlay y alcanza.
TRES COSAS QUE APRENDIÓ EL INSTRUMENTO (registradas en next-features §13)
1. Sonda y centinela eran CIEGOS A LA MITAD DEL COMPONENTE. Las filas del
mega-menú son los <a> DESNUDOS del consumidor, estilados por descendencia:
el filtro data-{c}-* veía 10 nodos y NINGUNO era el panel ni una fila — 9
de los 19 knobs fuera del diff. Con EXTRA_NODES / extraNodes la sonda pasa
a 16 nodos abiertos. Y el paso `open` de la sonda no honraba EXTRA_NODES.
2. EL GUARD CERRABA EL PANEL QUE MEDÍA. Este mega-menú abre con pointerenter
y pointerleave programa el cierre; el guard abría con clic y luego aparcaba
el puntero en (0,0) — justo el gesto que lo cierra. Dos corridas del mismo
código discrepaban. Y daba las DOS caras del error: falso negativo en los
tokens de la fila, falso positivo en content-link-padding-inline, que leía
«vivo» por ensanchar el panel que sí se medía. Con openBy: 'hover', dos
corridas idénticas.
3. `color` está EN TRANSICIÓN en esta parte: forzar data-disabled y leer en el
acto devuelve el valor VIEJO — tres diagnósticos falsos («ni el inline lo
mueve») hasta congelar. La trampa del cuentagotas del color-picker, en otro
componente. Congelado: reposo oklch(0.2435 0 0) → disabled oklch(0.61 0 0).
Y una de contabilidad, del instrumento y no del componente: el censo decide el
eje `size` grepeando data-size en el CSS, y el protocolo §7.4 ORDENA retirar
esos bloques. Todo componente que lo aplique bien aparece «sin eje». Ya le
pasa a sidebar y nav-tree. En §13.
VERIFICACIÓN
Sonda antes/después 0 diffs (2.752 valores · 8 estados · 16 nodos con el panel
abierto) · R-5.4 43/44 en dos corridas idénticas, adjudicación única
(disabled-trigger-fg: la demo no monta el estado; forzado alcanza en trigger Y
link, rgb(1,2,3)) · component:audit PASS · censo --only 100 % · eidos-lint 30
morfo-backed / 3 eidos-only / 0 invalid / 0 class-hooks · rtl:check 0 ·
docs:check 0 · suite eidos 439/440 (el rojo es skin-media-player, el conocido)
· check sin error nuevo en los ficheros tocados · Chrome con el panel abierto:
panel 8/10px/224px, fila 8/12/6px, trigger 36px/6px/gap 4px, indicador 2px.
Tras tocar el guard, command, table y tooltip re-verificados sin regresión ni
STALE.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
83a897b925 |
uix(audio-player): temable — 37 % → 56 %, y el instrumento medía CERO nodos
3 claves nuevas (5 → 8) y un literal anotado. El 44 % restante es PRÉSTAMO CON DUEÑO, no deuda: ocho filas que leen `--media-player-*` porque este componente ES la piel de audio de ese chasis, y una ficha nunca propone duplicar un token prestado con prefijo propio (§5.3-3). Acuñado lo único que ESTE reproductor añade sobre el chasis: el peso del título y la insignia LIVE en versalitas espaciadas (peso + tracking). Los dos `600` pasan a `var(--font-weight-semibold)`: el mismo valor, con nombre. Y EL INSTRUMENTO ESTABA CIEGO DEL TODO: MEDÍA 0 NODOS. Tres razones encadenadas: 1. `/uix/components/audio-player` es un 404 — el CUARTO canónico sin ruta propia (picker-shell, mockup, surface y éste). Se mide en la demo del chasis. 2. Sus partes no llevan `data-audio-player-*`: son `data-media-player-*`. Con `extraNodes`, la sonda pasa de 0 a 48 NODOS. 3. Sólo existe tras el chip `media: audio` de esa demo: sonda (`DEMO_VARIANTS`) y guard (`openWith` + `openMarker`) lo pulsan ahora, y el guard barre además las cuatro variantes (card/row/bar/inline). Con eso, 0/8 → 6/8. Las dos que quedan son la insignia LIVE, que sólo existe mientras el proveedor refleja un directo: montada con `[data-live]`, alcanza (600 → 333 y 1,28px → 7px). Gates: sonda con 48 nodos (antes 0) · centinela 6/8 con las dos adjudicadas · censo 56 % · suite eidos con el rojo conocido ajeno · `rtl:check` 0 · `docs:check` 0 · equivalencia comprobada en el computado (título 600, tracking 1,28px). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
6d199133c7 |
uix(tooltip): temable — 52 % → 75 %, y el plano ANULA SUS TRES VARIANTES
3 claves nuevas y 4 literales anotados. Subiría más, pero medir destapó que cinco de sus claves no pintan: el plano `overlay` le gana la superficie ENTERA. Acuñados el desenfoque del velo `ghost` y las dos tintas de la flecha `outline`, que se pintan por selector HERMANO desde el contenido. ⚠⚠ EL PLANO NO SÓLO SE QUEDA LA TIPOGRAFÍA: SE QUEDA EL FONDO, EL BORDE Y LA SOMBRA. `[data-depth='overlay']` declara las tres con la misma especificidad que `[data-tooltip-content]` y más tarde en la cascada. Medido: escribir `--tooltip-bg`, `--tooltip-border` o `--tooltip-shadow` no mueve NADA, mientras `--depth-overlay-surface` / `-border` / `-shadow` repintan el panel. Con `font-family` y `line-height`, son cinco públicos que no alcanzan. Y LA CONSECUENCIA VISUAL ES PEOR QUE LA CONTABLE: LAS TRES VARIANTES SON LA MISMA. Medidas `solid`, `outline` y `ghost` con el panel abierto: fondo, borde y sombra IDÉNTICOS en las tres. `outline` es indistinguible de `solid`; `ghost` sólo se diferencia por un `backdrop-filter` que no se ve porque la superficie que tiene delante es opaca. La máquina de variantes existe, alimenta privados, y el plano la anula entera. → §13. Por eso no se acuñó `ghost-bg`: lo intenté, el centinela lo delató y se retiró antes de commitear. Las cinco que ya estaban quedan ADJUDICADAS, no retiradas: son la FUENTE de esa máquina de variantes, y borrarlas dejaría inválidos los privados sin arreglar nada. La corrección de fondo es la precedencia del plano — la misma firma §12.9 que arrastran menubar, dropdown-menu y combobox. `content-z` sí está vivo, pero en otro nodo: aterriza en el ENVOLTORIO flotante (90 → 4321), que no lleva ningún `data-tooltip-*` y queda fuera del conjunto medido. Instrumento: un tooltip abre por HOVER, no por clic (`openBy: 'hover'`, como link-preview) — con eso pasó de 0/24 a 14/24. El resto se midió con el interruptor `open` de la demo: un panel abierto por puntero exige el ratón quieto sobre el disparador toda la pasada, y no es medida fiable. Gates: sonda 0 diffs en 256 valores × 8 estados · centinela 15/23 con las ocho adjudicadas · censo 75 % · suite eidos con el rojo conocido ajeno · `rtl:check` 0 · `docs:check` 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
694fcb99dc |
uix(surface): ADJUDICADO — el 25 % es su techo, y su ruta de demo es un 404
Cero claves nuevas: sus cuatro knobs son, uno a uno, doctrina bien aplicada. Surface es la cara de PINTURA de Box, y lo que pinta no es suyo: `bg` y `fg` salen del PUENTE DE PALETA (THM-2) —que es exactamente cómo un tema llega a ellos, por el color— y `--_surface-fill-finish` es el CANAL DE VALOR del acabado de degradado, que el generador deriva por instancia (§39). La rama `inherit` del `fg` suave es intencionada: la tinta del contenido se queda en la global porque el tinte del track es discreto, y está escrito en la receta. PERO NO TIENE RUTA PROPIA: `/uix/components/surface` es un 404, como `picker-shell` y `mockup`. El guard medía una página VACÍA y reportaba 0/25 — incluido `radius`, que está vivísimo—. Apuntado a `/temas/gradientes` (cuatro surfaces, dos variantes, tres colores) y a `/blocks/cta`: 1/25, y el que mueve es el radio (10px → 1234px). Ya son TRES los componentes del canon sin demo → §13. Sus 24 claves de tono son la SUPERSESIÓN de la cascada de paleta medida hoy en `button`: el bloque genérico va el último y gana por orden. Adjudicadas con el patrón compartido. Gates: centinela 1/25 con las 24 adjudicadas · censo 25 %, que es el techo · `docs:check` 0 · sin cambios de código. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
e276bb0cce |
uix(dropdown-menu): temable — 57 % → 96 %, y la tipografía del gemelo se RETIRA
9 claves nuevas (20 → 28) y 18 respaldos muertos retirados. Y una corrección a la baja, a propósito: `context-menu` 90 % → 87 %. Es el GEMELO de `context-menu`: mismos nombres, misma doctrina, mismas dos limpiezas de paso —el `font-family` era respaldo de SÍ MISMO y el peso del encabezado llevaba un `500` muerto detrás del token que ya vale 500—. Cosidos la tinta del panel y de la fila, su interlínea, el encabezado entero (tinta, peso y tracking) y el galón del submenú, que ahora tiene sus dos knobs: trazo y caja. EL FILO DEL SEPARADOR DEJA DE SER UN `1px` SUELTO y pasa a ser el trazo fino del sistema (`--border-width`, idéntico hoy): un tema que engorde el hairline lo engorda también aquí. Los 18 respaldos: cada `var(--dropdown-menu-x, …)` llevaba detrás un valor que NO puede ocurrir —las 18 claves están en el contrato— y sólo servía para envejecer contra él. Ninguno movía un píxel; dos ya discrepaban del contrato en la FUENTE. ⚠ `content-font-family` NO SE ACUÑA, Y LA DEL GEMELO SE RETIRA. El panel lleva `data-depth='overlay'` y el PLANO declara la familia con la misma especificidad y más tarde en la cascada: gana él. Quinta prueba de §12.9. `context-menu` la tenía acuñada desde esta misma sesión CON una adjudicación escrita, y eso era media doctrina: un público que no alcanza es un token que miente (R-5.4). Las dos recetas vuelven a su fuente literal con la razón encima. Un tercer caso —`combobox`, misma clave, mismo plano— queda medido y registrado en §13; no se toca aquí porque no es el componente en curso, y cuando §12.9 se firme la decisión será la misma para las cuatro. Gates: sonda 0 diffs en 928 valores × 8 estados (22 nodos con el panel abierto) · centinela 27/28 con la deshabilitada adjudicada · censo 96 % · `component:audit` PASS · suite eidos con el rojo conocido ajeno · `rtl:check` 0 · `docs:check` 0 · captura del panel abierto. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
e68b01f840 |
uix(button): temable — 55 % → 91 %, y la cascada de paleta ANULA 419 claves
Una clave nueva y 17 declaraciones anotadas. Al medirlo salió lo más gordo del
eje hasta hoy: 56 de las 106 claves públicas de este componente no pintan nada,
y no por deuda suya.
Acuñado lo único que faltaba: EL PASO `full` DE LA ESCALA DE RADIO —
`[data-rounded='full']` leía el primitivo global a pelo, así que la forma que
más se retoca (la píldora) era el único escalón fuera del contrato.
Diecisiete declaraciones pasan a excepción firmada, de dos clases: IDENTIDAD
(`fit-content` × 2 —un botón ES su contenido—, el `100 %` de `[data-block]` y
los cuatro `1px` de las cajas sr-only) y AUSENCIA (los `transparent` de `soft`,
`outline`, `ghost` y `plain`: la variante ES la ausencia de cromo, y ponerle
fondo a un `ghost` es pedir un `soft`). Diez claves de `transparent` habrían
sido justo el antipatrón que la doctrina avisa: agrupa por VALOR.
Para que la ausencia cuente, EL CENSO APRENDE LA VÁLVULA UN PISO MÁS ABAJO: un
PRIVADO cuyo valor es un literal CON su razón escrita es una ausencia firmada,
no deuda. Sin eso, cuatro privados marcaban «no deriva» y seis knobs leían
inalcanzables mientras todas las demás ramas del mismo privado leen un público.
⚠⚠ EL HALLAZGO: LA CASCADA DE PALETA ANULA LOS TONOS DEL COMPONENTE.
El último bloque del forward, `[data-button][data-color]`, resuelve
`--button-palette-*` desde el `--palette-*` GLOBAL —que `[data-color='{tono}']`
llena desde `--color-{tono}-*`— y gana a las reglas por tono por ORDEN, con la
misma especificidad (0,2,0). Medido sobre `data-color='risk'`:
`--button-risk-solid` no mueve nada, ni en `:root` ni en el nodo, mientras
`--palette-solid` y `--color-risk-solid` en el nodo repintan. Las siete
`primary-*` son el RESPALDO de esa misma regla y sólo actúan SIN `data-color`.
No es de este componente: 49 recetas emiten el mismo forward genérico y el
contrato tiene 419 CLAVES DE TONO. Medido igual en `badge` y `callout`. El
arreglo cabe en el orden de emisión —el genérico ANTES de los de tono— y no
movería un píxel, porque el valor por defecto de `--button-risk-solid` ES
`var(--color-risk-solid)`; pero cambia el contrato de la jaula del color (un
ancestro que inyecte `--palette-*` dejaría de pisar un tono semántico). Es
firma. → §13.
El techo restante son dos filas de canal de valor: `--_button-fill-finish`, el
acabado de degradado que el generador deriva por instancia.
Un error de método, anotado porque casi cuela: anclé la clave nueva en la
primera línea `'radius-xl'` del fichero y aterrizó en `meter`. Lo delató el
navegador (`--button-radius-full` sin definir ⇒ radio 0). Una inserción se
ancla en el BLOQUE del componente, nunca en una línea de clave.
Instrumento: el guard aprende `sweepAttr` (barrer una variante mientras mide) y
a estampar el TONO que la clave nombra; y el fichero de excepciones gana
PATRONES, para que una razón arquitectónica se escriba una vez y no 56.
Gates: sonda 0 diffs (416 valores; la demo monta UN botón) · equivalencia del
paso `full` comprobada aparte · centinela 34/106 con todo lo demás adjudicado ·
censo 91 % · `component:audit` PASS · suite eidos con el rojo conocido ajeno ·
`rtl:check` 0 · `docs:check` 0 · `check` sin errores propios · captura de las
seis variantes + píldora + tono `risk`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
c679b1b449 |
uix(onion-menu): temable — 29 % → 84 %, y una regla que el navegador DESCARTA
7 claves nuevas (12 → 19) y 5 literales anotados. Lo que queda fuera son TRES filas y ninguna es deuda de tokenización: una es canal de valor y dos viven en una regla inválida. Acuñado el color del ANILLO DEL SECTOR —uno para los dos estados, porque el propio comentario del CSS dice que el hover usa «el mismo color que el anillo de selección, más claro» y lo que los separa es la opacidad, que ya tenía token—, la tipografía de la etiqueta, el radio y la tinta del disparador, y las dos piezas del glifo `+`→`×`. Dos limpiezas de paso: un `var(--style-label-font-family, var(--style-label-font-family))` —respaldo de sí mismo, el defecto que ya se cazó en context-menu— y dos `var(--radius-full, …)` con un respaldo que no puede ocurrir. Cinco literales pasan a excepción POR IDENTIDAD: dos `opacity: 1` que DESHACEN un atenuado (sin atenuar es 1 por definición) y la caja del icono. ⚠ `.onion-menu-icon :global(svg)` NO EXISTE. `:global()` es un envoltorio de SVELTE y esto es un CSS plano: el selector es inválido y el navegador descarta la regla entera. Medido: el glifo computa 14px —el tamaño propio del Icon— y el `70 %` que el fichero cree pintar no pinta. Acuñé un `icon-glyph-size`, el centinela lo delató y lo RETIRÉ; los literales se quedan con el defecto escrito encima, porque arreglar el selector empieza a pintar el 70 % y MUEVE PÍXEL. Mismo bug en `timeline.css:331`; `image-picker.css` ya documentaba la trampa —la lección estaba escrita y se repitió—. → §13. Canal de valor: el fondo del disparador lo escribe el componente INLINE desde el motor de color, como los rellenos de cada sector. No es superficie de tema. TRES CEGUERAS DEL INSTRUMENTO, dos nuevas y genéricas: 1. EL GUARD CERRABA LA SUPERFICIE. Este menú nace ABIERTO y el clic de «abrir» lo cerraba: 12 de 20 tokens leían muertos. Ahora, si hay `openMarker` y ya casa, no se pulsa nada (8 → 14 de golpe). 2. Sus tripas cuelgan de CLASES, no de `data-onion-*`: sonda y guard las miden con `extraNodes` — 37 nodos en reposo contra los 5 con atributo. 3. Congelar las transiciones NO BASTA cuando el nodo está ANIMADO: `rim-glow-opacity` leía 0,482956 —el valor animado— y parecía muerto; con la animación congelada computa 0,45 y sigue al token. → §13. Los cuatro tokens del rim son del look `luminous`, que la demo del componente no renderiza (es una prop de Svelte que emite OTRO marcado, así que no hay atributo que forzar): medidos en `/active/docs/agnt`, que sí lo usa. Gates: sonda 0 diffs en 7.328 valores × 8 estados (37 nodos) · centinela 14/19 con las cinco adjudicadas · censo 84 % · `component:audit` PASS · suite eidos con el rojo conocido ajeno · `rtl:check` 0 · `docs:check` 0 · `check` sin errores propios · capturas de reposo, sector en hover y disparador. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
b7888f7a05 |
uix(field): temable — 73 % → 98 %, y sus 18 rojos estaban VIVOS
8 claves nuevas (60 → 68) y 8 literales ANOTADOS. Lo que falta es el PUENTE DE PALETA (`_palette-text`, THM-2), que no es deuda. Global 63 %. Field es el componente más COMPUESTO del sistema: lo que otras fichas llaman «préstamo con dueño» se cobra aquí, así que su techo pesa más que el de nadie. Acuñados el DISPARADOR DE CONTROL —el icono que abre el calendario, el reloj o la muestra, y revela la contraseña: `size`, `radius`, `fg` y sus dos estados—, el indicador `optional` (gemelo del `required`, que ya tenía token) y el lateral de la etiqueta flotante, que es lo que CORTA el borde bajo el texto. La caja del disparador se mide en `em` a propósito, así que el token guarda la RAZÓN (`1.75em`) y no un píxel por talla. OCHO LITERALES PASAN A EXCEPCIÓN FIRMADA POR IDENTIDAD, no para inflar el ratio: cuatro `inline-size: 100%` (el campo, el control, el input y el control flotante llenan su fila), dos `line-height: 1` (un glifo suelto no tiene interlínea) y dos `1em` del icono dentro del disparador (el glifo ES el tamaño del texto). LOS 20 ROJOS DEL GUARD ESTABAN VIVOS, uno por uno, y tres enseñan algo: - `disabled-opacity` vive en el CONTROL, no en la raíz: el guard leía el nodo equivocado. - `control-placeholder-fg` no leía porque el input de la demo NO TIENE `placeholder`: sin el atributo no existe la caja `::placeholder`, y `getComputedStyle(nd, '::placeholder')` devuelve entonces el estilo del ELEMENTO. Con un placeholder puesto, alcanza. Es genérico → §13. - `segment-height` es un token de FAMILIA que field posee y los pickers consumen —en las rutas de field no lo lee nadie— y además es RESUELTO (declarado por `[data-field][data-size]`), así que escribirlo en `:root` pierde POR DISEÑO: el tema mueve la coordenada. Medido en `/time-picker`: desde `:root` nada, desde el host del campo 28px → 1234px, y moviendo `--field-control-height-md` 28px → 992px. El resto son estado (invalid, disabled, readonly, foco), variante ghost, orientación horizontal, la franja de segmentos, el texto de error —que sólo se RENDERIZA con el interruptor de la demo: forzar el atributo no hace que Svelte monte el nodo— y los dos de transición, que el guard congela. Instrumento: el disparador de control no lo monta NINGUNA demo de field, así que el guard mide ahora `field` sobre DOS rutas (`/field` + `/date-picker`). Gates: sonda 0 diffs en 2.280 valores × 8 estados · equivalencia del disparador comprobada aparte en `/date-picker` (28px = 1.75em con fuente 16px · 4px = `--radius-sm` · misma tinta) · centinela 48/68 con las 20 adjudicadas · censo 98 % · `--names` 0 · `component:audit` PASS · `rtl:check` 0 · `docs:check` 0 · suite eidos con el rojo conocido ajeno · `check` sin errores propios · capturas de reposo, invalid, disabled, etiqueta flotante y disparador. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
df3c8d760e |
uix(menubar): temable — 15 % → 88 %, y el plano `overlay` GANA a la receta
30 claves nuevas (5 → 35): la barra (superficie, marco, radio —uno solo, la
receta lo desacopla de la talla a propósito y el motor de forma deriva el del
disparador de él— y las tres escalas `gap`/`padding`/`height`), el disparador
(tinta, tipografía, escala de `font-size` y de `padding-inline`, el par de la
entrada ABIERTA y la tinta deshabilitada) y el Panel `role=dialog` (tinta +
escala). Global 62 % → 63 %.
Los pasos leen el BUNDLE (`--size-{k}-control-height` / `--size-{k}-font-size`),
no el primitivo crudo que el CSS venía consumiendo; y el
`calc(var(--space-1) * 0.5)` del paso `sm` es `var(--space-0-5)` exacto.
EL HUECO DEL PANEL DEJA DE REPETIR EL VALOR DEL PADDING. Las tres reglas de
`--floating-gap` compensan el sangrado del disparador dentro de la barra con lo
que era una COPIA del padding; ahora leen `--menubar-padding-{k}`, su fuente —
si un tema ensancha el padding, el panel deja de quedar a ras de la barra. No
pueden leer el privado `--_menubar-padding`: esas superficies viajan POR PORTAL
y un privado declarado en la raíz no cruza esa frontera.
⚠ EL PLANO `overlay` GANA A LA RECETA — cuarta prueba de §12.9 y la primera con
MECANISMO. Acuñé `panel-font-family` y `panel-line-height` sobre declaraciones
que la receta YA tenía, y el centinela las dio muertas. Medido:
`[data-depth='overlay']` declara las dos con la MISMA especificidad (0,1,0) y
más tarde en la cascada, así que gana; del mismo bloque, `color` y `font-size`
—que el plano no declara— sí alcanzan. Retiradas del contrato y devueltas a su
fuente literal, con la razón escrita en el CSS. Mientras §12.9 no se firme, un
token de tipografía en CUALQUIER superficie `overlay` miente, y son veinte.
EL HOVER NO SE ACUÑA: ES DEL EJE navigation-menu. `background:
var(--color-surface-overlay)` sobre el disparador mata la capa del sistema
—medido: `background-image` computa `none` en hover con `--state-hover` vivo—,
por las dos razones que `navigation-menu.css` ya documenta al retirar esta
MISMA regla: el shorthand resetea `background-image`, y la regla del arquetipo
va en `:where()`, especificidad CERO. Acuñar un `hover-trigger-bg` habría
fosilizado la invención.
Instrumento: la barra suelta DOS superficies y el Panel —el que lleva sus
knobs— cuelga de la entrada «Format», no de la primera; sonda (`OPEN_TRIGGER`)
y guard (`openWith`) aprenden a abrir la que toca. Y el guard necesitó
`openMarker`: su comprobación de «ya está abierto» busca `[data-{c}-content]`,
que aquí no existe, así que volvía a pulsar el disparador antes de cada token y
CERRABA el panel — media corrida contra una superficie cerrada.
Gates: sonda 0 diffs en 1.470 valores × 8 estados · centinela 34/35 (la
deshabilitada, adjudicada) · censo 88 % · `--names` 0 desviadas ·
`component:audit` PASS · `rtl:check` 0 · `docs:check` 0 · suite eidos con el
rojo conocido ajeno (`skin-media-player`) · `check` sin errores propios ·
capturas de barra, tallas sm/lg, menú abierto y panel.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
27dc6dba35 |
uix(theming): los dos rojos que quedaban — y el eje `size` del picker MUERE EN EL PORTAL
Medidos uno a uno los 18 de `metrics` y los 25 de `color-picker`, los últimos del bloque viejo que el guard R-5.4 arrastraba sin adjudicar. Los dos quedan en verde. Sin cambios de código: esto es medición y registro. `metrics`: los 18 están VIVOS. Ninguno miente; lo que faltaba era el escenario. Seis piden el paso `xxl` (la demo llega a `xl`), dos el icono SIN `data-color` (su defecto sólo pinta cuando no hay color, y todos los de la demo llevan uno), dos las formas `circle`/`square`, cuatro la fila de acciones, uno el gráfico en `end`, uno el borde de la variante `outline`, y dos el sello de sema durante el hold (`data-event-family=signal` + `phase=active`): el destello del valor sólo se mide estampando el sello a mano, porque cuando el guard lee ya se ha ido. `color-picker`: 23 de 25 vivos, y los otros dos son un DEFECTO REAL. EL EJE `size` MUERE EN EL PORTAL, dos veces. `--_color-picker-content-width` se declara TRES veces y no lo consume NADIE: la anchura del panel la fija `--_popover-content-width-override`, cableada al paso `md`. Un picker `sm` y uno `lg` abren el MISMO panel de 344 px, y `content-width-sm`/`-lg` son dos públicos que no mueven nada. Lo mismo con las muestras dentro del panel (`--_color-picker-swatch-size` clavado a `md`): fuera del portal los tres pasos alcanzan (20/24/28 px → 1234 px), dentro sólo el `md`. La causa es una y vale como ley: el portal es una FRONTERA DE CASCADA — un privado declarado en la raíz del componente no la cruza. Misma familia que la capa `list-surface` inalcanzable desde `:root`. El arreglo honesto es una escala por talla en el ámbito del CONTENIDO (que sí lleva su `data-size`); mueve píxel en `sm` y `lg`, así que es firma → §13. Tres cegueras del instrumento, medidas: - El guard CONGELA las transiciones antes de medir —el arreglo que hizo medibles radio-cards y compañía— y `transition-duration`/`transition-ease` SON la transición: sin congelar alcanzan (0.12s → 11.5s). Es genérico: cualquier componente con esos dos públicos los reportará muertos. - Una lectura inmediata de una propiedad EN TRANSICIÓN devuelve el valor VIEJO. Es lo que hacía ilegible el fondo del cuentagotas: ni con `!important` en línea se movía, porque la transición aún no había corrido. - La DEMO pisa el cuentagotas con su regla de ámbito (`.cp-tools-row` le pone `inline-size:auto` y `background`), así que sus dos tokens sólo se miden devolviéndole el consumo del token. Gates: `theming:sentinel metrics` y `color-picker` en verde (54/72 y 46/71, el resto adjudicado por escrito) · `check` sin errores propios · `docs:check` 0/0 · formato sin regresión (los tres ficheros ya venían avisados en HEAD). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
f25f5bb1d0 |
uix(drawer): los 24 rojos medidos uno a uno — y uno era un DEFECTO REAL: el velo no pinta
Sin cambios de código: 24 adjudicaciones medidas y dos hallazgos. El guard queda
en VERDE.
EL VELO DEL CAJÓN NO PINTA. Su regla es
background: color-mix(in srgb,
var(--drawer-overlay-bg) var(--drawer-overlay-opacity), transparent)
y **soma escribe `--drawer-overlay-opacity: 1` INLINE** en el nodo del velo — es
su progreso de arrastre, un número sin unidad. `color-mix` exige ahí un
PORCENTAJE: con `1` la función entera es inválida y el fondo cae a `transparent`.
Medido: el velo abierto computa `rgba(0, 0, 0, 0)`; escribiendo `80%` en el
propio nodo, pinta. Y VISTO en captura: el fondo tras el cajón sale desenfocado
pero **sin atenuar** — el `backdrop-filter` funciona y el tinte no existe. Un
cajón modal sin velo.
No se arregla aquí porque mueve píxel y toca soma (§7.8). Puede arreglarse de un
lado o del otro —que soma escriba un porcentaje, o que la receta no use ese slot
como porcentaje—, y la lección general queda escrita en §13: **un valor que soma
escribe inline y una receta consume tiene que compartir UNIDAD**, o el fallo es
silencioso.
SEGUNDO HALLAZGO: las tallas son canal de valor en el eje que manda. Soma escribe
`width` (o `height`, según el lado) inline en el contenido, así que
`content-width-{sm,md,lg}` no puede ganar desde `:root` en un cajón
izquierda/derecha; el eje cruzado sí alcanza (`height-sm` forzado: 260px →
976px). Misma clase que el `item-gap` de carousel y el `preview-z` de drag-drop,
que se retiraron — pero aquí el token sigue siendo la fuente del valor que soma
resuelve, así que retirarlo o no es firma tuya.
Los otros 22 son lo esperable, y quedan medidos con su valor: el asa —que la demo
no monta y cuyo tamaño INTERCAMBIA ejes según el lado (36px→1234px de largo,
4px→1234px de grosor)—, el anillo de arrastre, el padding `full`, la cabecera y
el pie opcionales, y la z de la variante inline.
Gates: centinela 29/54 con las 24 adjudicadas, exit 0 · docs:check 0 · captura de
la página con el cajón abierto mirada.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
cd6a9f4e3e |
uix(theming): revisión adversarial del bloque — la pasada de HOVER envenenaba a todos los tokens de reposo
Cinco hipótesis, un hallazgo real, cuatro refutadas. Bloque de CATORCE componentes; global del eje 56 % → **62 %**. HALLAZGO REAL — la anomalía de `float-panel` tenía causa, y era del guard. `resize-grip-fg` movía aislado y leía muerto en una corrida completa. Instrumenté el propio guard para probar UNA clave y salió `moved=true`; luego, en la corrida entera, muerto. La causa: **la pasada de HOVER deja el puntero sobre el último nodo que tocó**, y una regla `:hover` gana a la de reposo con la que comparte nodo — el asa re-apunta su color al acento al pasar el ratón. Es decir: **cualquier token de reposo probado DESPUÉS de un token `hover-*` podía leer muerto**. Es exactamente la clase que F2-A arregló con el clic-foco, una pasada más tarde: allí se aparcó el puntero tras ABRIR, aquí faltaba aparcarlo tras HOVERAR. Arreglado. Y entonces el propio guard delató DOS excepciones STALE — `float-panel.resize-grip-fg` y `media-player.track` —, retiradas: dos tokens que el ledger daba por muertos están vivos. Se confirma la regla de F2-A: **un falso negativo siempre tiene causa**; registrarlo como «sin causa» era el paso previo, no el final. REFUTADA «hay tokens huérfanos»: comprobación ESTRICTA —comentarios despojados, que es el hueco por el que `popover.bg` sobrevivió, sobre todo el CSS del árbol— de las **553 claves** de los catorce bloques: ninguna declarada sin que una regla la lea. REFUTADA «el cambio de instrumento rompió algo»: los **27 componentes con ledger re-verificados** tras aparcar el puntero — cero regresiones. Los tres rojos que quedan (`drawer` 24, `metrics` 16, `color-picker` 23) son ANTERIORES al bloque y están anotados con lo que ya se descartó de cada uno. REFUTADA «quedan fantasmas del barrido en lo tocado»: pasa de 9 a **8** — el `--color-content-tertiary` de float-panel murió con su costura. Los ocho restantes son de componentes que este bloque no tocó. CONFIRMADO, y ya estaba escrito: hay gates FINOS. `popover` mide 1 nodo en reposo (7 en abierto), `drawer` 1, `context-menu` 1 + 14 en abierto, `color-picker` 5 + 12. Cada veredicto lo dice, y lo que sostiene esas cifras es el forzado a mano de sus estados, no la sonda. Guards: `--names` sin desviadas · docs:check 0 · censo 62 % (2.877 públicos de 5.137 knobs; `global` 1.145 → 912). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
b4510fbf82 |
uix(float-panel): temable — 59 % → 84 %, muere un fantasma y queda una anomalía registrada
12 claves (28 → 40). Censo float-panel 59 % → **84 %** con `global` a CERO. Cosido: las dos VARIANTES que ajustan desde el default elevado (`outline-*`, `ghost-*`), los botones de su barra (`action-*`, `hover-action-*`) y el asa de redimensionado. MUERE UNO DE LOS NUEVE FANTASMAS DEL BARRIDO de esta mañana: el asa leía `var(--color-content-tertiary, var(--color-content-secondary))` y ese primitivo NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad pintaba, con lo que la referencia muerta desaparece sin mover un píxel. ONCE ADJUDICACIONES MEDIDAS: la demo monta la variante por DEFECTO —ni outline ni ghost— y no tiene botón de acción genérico, sólo el control de cierre; se forzó el atributo de variante y se montó el botón donde el CSS lo selecciona, y el radio del asa sólo pinta bajo `:focus-visible`. Las once alcanzan. Y UNA ANOMALÍA REGISTRADA EN VEZ DE ESCONDIDA: `resize-grip-fg` **mueve** bajo una réplica a mano de la secuencia del propio guard —congelar transiciones, blur, aparcar el ratón, escribir en `:root` y en cada nodo con el prefijo, fotografiar los mismos props con `::before`/`::after`/`::placeholder`— (oklch(0.5032 0 0) → rgb(1,2,3)), y aun así el guard lo da por muerto. Descartado que el nodo no lleve el atributo (lo lleva), que la regla necesite un estado (es la regla base), que sea el valor centinela (es el mismo) y que sea HMR (dos corridas). Queda adjudicado CON la medición y marcado como anomalía en §13: el token está vivo, lo que está en duda es la lectura. Es por donde debe empezar la revisión adversarial de este bloque — el precedente de F2-A dice que estos casos sí tienen causa. Lo rojo que queda son 12 tokens anteriores, y seis de ellos —`bg`, `border`, `border-width`, `shadow`, `font-family`, `line-height`— son el mismo conjunto que en `popover`: el PLANO de profundidad gana sobre el panel (§12.9, pendiente de firma). Gates: sonda antes/después **0 diffs en 1.890 valores** (9 nodos × 7 estados) · censo --only 84 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0 invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 · captura mirada (cabecera, botón de cierre y asa de la esquina en su sitio). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
3fe8b974a6 |
uix(color-picker): temable — 51 % → 75 %, y un prefijo ABREVIADO fuera de todo el árbol
20 claves de costura (54 → 71) y cinco nombres renombrados. Global del eje 60 % → **61 %**. `--cp-*` VIOLABA theming §6 r5 («no abrevies el nombre del componente»). Cinco nombres —`checker`, `checker-cell`, `current-color`, `channel-gradient`, `trigger-color`— y **45 ocurrencias en 8 ficheros**, tres de ellos de SOMA: el provider los estampa inline, su test los lee y sus tipos los declaran. Renombrados a `--_color-picker-*` con `git ls-files` delante; dos de ellos —el damero y el gradiente de canal— ya derivaban de un público, así que el censo los reclasifica solo. Precedente: los `--gb-*` / `--_ntp-*` de F2-A. Cosido: el ritmo del componente, la tinta de la etiqueta, la tipografía del disparador y la del VALOR —que es metadato: mono, regular, tinta e interlineado propios—, el borde de la muestra, el raíl del canal y su pulgar, el hueco del anillo de la muestra y el borde del cuentagotas. UNA SOMBRA QUE SON DOS Y HACEN UNA COSA: el pulgar del canal lleva contorno + elevación en un solo `box-shadow`, así que se acuña como UN token y la regla de foco lo compone con su tercer anillo, en vez de repetir las dos sombras. EL INSTRUMENTO NO VEÍA DOS FAMILIAS DE NODO, y las dos se arreglaron midiendo: las muestras del picker **son `<ColorSwatch>`** (llevan `data-color-swatch`, no `data-color-picker-*`) y sus sliders de canal **son SLIDERS** (el pulgar y el raíl llevan `data-slider-*`). Cuatro tokens vivos leían muertos por eso. LO ROJO QUE QUEDA ES ANTERIOR A ESTE COMMIT: el guard reporta 23 sin adjudicar —las muestras, la rueda de tono (`hue-0..360` + `saturation-floor`), el ancho del panel por talla, el cuentagotas y las dos de transición—, todos del bloque que ya existía. Antes eran **24**, así que la cifra baja. Su pase de medición queda anotado en §13 con dos causas ya descartadas: el panel SÍ abre y sobrevive al blur, al parqueo del ratón y al forzado de `data-size`, y el guard ya ve sus nodos. Lo que este commit añadió está medido: dos adjudicadas montando el disparador de muestra dentro del panel abierto, el resto en vivo. Gates: sonda antes/después **0 diffs en 1.350 valores** (8 estados), medida DOS veces —una tras el renombrado, otra tras la costura— · tests de soma del color-picker **7/7** tras el renombrado · censo --only 75 % · `--names` sin desviadas · component-audit PASS · eidos-lint 0 invalid · suite eidos con el único rojo conocido · rtl:check 0 · docs:check 0 · `check` con 72 errores globales y 0 en los ficheros tocados. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |