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 }
2203 Commits (ffa45726fdfe989c4fcf16f72a4b2139c1614c46)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
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 |
|
|
fde65af7ea |
docs(theming): el registro §8 recoge tabs y toast, con su sha — y la cola A CIERRA
Los dos commits de esta sesión, con sus cifras y sus artefactos:
- `tabs` 96 % → 97 % CERRADO (`300153f9f`) — 79 claves, ninguna acuñada,
centinela 70/79 con 9 adjudicadas.
- `toast` 98 % → 100 % (`b8eccc1c4`) — 85 claves, ninguna acuñada, centinela
51/85 con 34 adjudicadas.
Y con ellos la Cola A queda CERRADA: los cuatro (`scroll-area`, `slider`,
`tabs`, `toast`) cerraron **sin acuñar una sola clave**. Sus contratos ya
estaban enteros y lo que quedaba fuera eran literales-identidad y, en `tabs`,
el canal de VALOR de soma. Cuando el número no se mueve porque no debe, eso ES
el resultado — y así está escrito en el handoff.
Lo que enseñaron los dos últimos, para el que siga:
- §12.9 en una tarjeta PORTALADA se lleva la TARJETA ENTERA, no sólo la
tipografía — 21 claves de `toast`, y con coste de producto: un toast `risk`
y uno `fulfill` visten la misma tarjeta gris. Medido, adjudicado con
`PLANE_SUPERSEDED` y registrado en next-features §12; sin firma no se toca.
- La misma clave puede mentir en reposo y decir la verdad en animación: los
`{tono}-accent` alcanzan bajo `[data-loading]`, donde el `@keyframes` del
pulso gana a toda declaración normal.
- Poner `openMarker` puede EMPEORAR la medición cuando la superficie se
auto-descarta: tres corridas del guard discreparon sobre código idéntico.
- El indicador de `tabs` es canal de valor: `MeasuredIndicator` escribe su rect
en cada movimiento, y un público encima sería un knob que rompe el
deslizamiento al fijarse.
Guard: `docs:check` 0 · prettier limpio sobre el contenido normalizado a LF.
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 |
|
|
868bd235bf |
docs(theming): el protocolo aprende a mirar QUIÉN LEE una clave antes de retirarla
R-5.4 dice que un token que no mueve nada es un token que miente, y esta pasada ha retirado varias con razón: file-upload.button-bg no pintaba en ninguno de sus tres botones, avatar.group-max no lo leía nadie, editable.control-border no la consumía ninguna regla. Pero leer muerto en SU demo no es leer muerto en el CATÁLOGO, y las dos sesiones de hoy lo enseñaron a la vez. scroll-area.auto-max-block salía silenciosa en su propia página y la consumen cinco recetas ajenas —combobox, command, gradient-picker, select y palabras—. slider.min-block-size sólo la lee la orientación vertical, que su demo no monta, y es justo la que media-player fija para su volumen. Retirar cualquiera de las dos habría roto seis componentes sin que un solo guard se pusiera rojo, porque ninguno mide el catálogo entero. Entra como paso 8.bis de §7.3, con el comando: un grep sobre src/uix/eidos/components/ antes de retirar nada. Si aparece alguien más, la clave no se retira: se adjudica con esa razón. Las dos sesiones lo hicieron por criterio propio, sin que el protocolo lo pidiera. Ahora lo pide. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
999481e08c |
docs(theming): el registro §8 recoge scroll-area y slider, con su sha
Los dos cierran la cola A por arriba y los dos cierran **sin acuñar una sola clave**: llegaban con `global` y `private` a cero y un único literal cada uno, que se firma como identidad (`opacity: 1` de la barra visible · `inline-size: 100%` del rail horizontal). Diez adjudicaciones entre los dos, todas medidas. - `scroll-area` 94 % → 100 % (`3282ef978`) — la clave que el guard leía muerta (`auto-max-block`) es la que CINCO componentes escriben sobre su propio ScrollArea. - `slider` 97 % → 100 % (`4d3ca2fd8`) — con un solo valor el tick ACTIVO no existe: `data-active` es una relación con el rango, no un estado del tick. El registro va aparte del commit del componente porque un commit no puede contener su propio sha, y el marcador `(COMMIT)` ya costó trece entradas sin resolver. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
4d3ca2fd81 |
uix(slider): temable — 97 % → 100 %, y con un solo valor el tick ACTIVO no existe
CERO claves acuñadas. El componente llegaba con `global` a cero, `private` a
cero —sus cuatro privados son la escala por talla, que ya deriva de públicos— y
treinta y nueve claves cubriendo su cromo entero; lo único fuera de alcance era
UN literal. Este commit lo firma, adjudica sus siete silenciosas y escribe los
artefactos que le faltaban.
QUÉ ENTRA
- **El literal se firma como identidad**: `inline-size: 100%` en
`[data-slider][data-orientation='horizontal']` — un rail ocupa su contenedor.
El knob de verdad ya existe y es su SUELO: `min-inline-size`. Mismo
precedente que `separator.css:26`, cerrado el mismo día también sin acuñar.
- **Siete adjudicaciones en el ledger**, todas MEDIDAS sobre los nodos reales,
con `transition` congelada salvo donde el token ES la transición:
- `min-block-size` — sólo la lee `[data-orientation='vertical']` y el
escenario arranca horizontal. Con el chip de orientación: 160px -> 1234px.
- `active-thumb-scale` / `active-thumb-shadow` — el pickup vive en
`[data-slider-thumb]:active`, que pide el puntero MANTENIDO, y el pase
estático del guard lo aparca. Con `mouse.down()` real sobre el thumb real:
scale 1.15 -> 4.56, y la sombra sigue al centinela.
- `active-tick-bg` — un tick lleva `data-active` sólo mientras su valor cae
DENTRO de [min(valores), max(valores)] (soma, `SliderTickProvider.isActive`),
así que un pulgar único en 40 con ticks en 0/50/100 deja los tres inactivos:
la marca activa no es un estado del tick, es una RELACIÓN CON EL RANGO. Con
el chip `multiple` (20–80) el tick 50 se activa y el token alcanza.
- `disabled-opacity` — el escenario arranca habilitado; con su interruptor,
0.4 -> 0.123.
- `transition-duration` / `transition-ease` — SON la transición que el guard
congela; medidos sin congelar, 0.12s -> 11.5s y steps(4).
- README con su sección «Talla y tema» (39 claves por grupo, con la distinción
`hit-size-{k}` = agarre vs `track-size-{k}` = pintura) y veredicto §5 de la
ficha con las cifras.
QUÉ NO SE TOCA
- **Nada se retira ni se renombra**, y no es prudencia: este contrato lo COMPONEN
otros SIETE componentes que re-tiñen o re-dimensionan estas mismas claves sobre
su Slider embebido — `media-player`, `skin-media-player`, `waveform` (su
playhead ES este thumb), `color-picker`, `gradient-builder`,
`image-adjustments` y `time-range-picker`. `min-block-size`, que el centinela
leía muerta, es justo la que `media-player` escribe para su volumen vertical.
- `base.ts` y `generated/base.css`: sin cambio de contrato no hay nada que
regenerar. 39 -> 39 claves.
ARTEFACTOS
- Censo: 97 % (33 knobs · 31 públicos · 1 literal · 1 sistema) -> **100 %**
(32 · 31 · 0 literal · 1 excepción · 1 sistema). Global 68 %, no baja.
- Sonda antes/después: **0 diffs sobre 1.376 valores computados**, 7 estados,
7 nodos (raíz · secondary-range · range · thumb · 3 ticks).
- Captura 2× antes y después: idénticas.
- Centinela R-5.4: **32/39**, las 7 restantes adjudicadas -> verde.
- component-audit PASS · eidos-lint 25 morfo-backed / 5 eidos-only / **0
invalid** · `vitest run src/uix/eidos` 35/36 ficheros (el rojo conocido es
`skin-media-player`) · rtl:check 0 · docs:check 0.
- `npm run check`: UN error en `web/routes/uix/components/slider/+page.svelte`
(`Property 'keyboard' does not exist`, línea del `sliderMorfo.parts[2]`),
**PREEXISTENTE** desde `1857c7854` y ajeno a este commit; ningún otro error en
ficheros de slider.
- Prettier: los hunks de deriva del fichero son los MISMOS que en HEAD (2 en el
README, 0 en el CSS); mi bloque no añade ninguno.
NOTA DE CONCURRENCIA: la pestaña `Tokens` de su demo (paso 11 del protocolo) la
escribí yo, pero entró en HEAD por `9fc38b19a` + `c88b2f861` de otra sesión, que
la arrastró con un `git add` derivado y lo declaró. No se re-commitea aquí.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
3282ef9786 |
uix(scroll-area): temable — 94 % → 100 %, y la clave que el guard leía muerta la escriben CINCO componentes
CERO claves acuñadas. El componente llegaba con `global` a cero, `private` a
cero y trece claves públicas que ya cubrían su cromo entero; lo único fuera de
alcance era UN literal. Este commit lo firma, adjudica sus tres silenciosas y
escribe los artefactos que le faltaban.
QUÉ ENTRA
- **El literal se firma como identidad**: `opacity: 1` en
`[data-scroll-area-scrollbar][data-state='visible']` deshace el `0` del
estado oculto de la regla de encima — es el otro extremo de un par, no un
knob. Un `--scroll-area-visible-opacity` sería una clave cuyo único valor
sensato es `1`, y además asimétrica: el `0` hermano el censo ni lo cuenta.
Precedente literal en `navigation-menu.css:360` y `select.css:363`.
- **Tres adjudicaciones en el ledger**, todas MEDIDAS sobre los nodos reales:
- `auto-max-block` — su regla pide `[data-autosize]` y el escenario monta el
modo fijo. Forzado sobre la raíz real: `max-block-size` none -> 1234px, y
al quitar el token vuelve a `none`. NO es decorativa: la escriben
`combobox`, `command`, `gradient-picker`, `select` y `palabras` sobre su
propio ScrollArea. Retirarla habría roto cinco componentes. El atributo lo
estampa el envoltorio de eidos desde una prop, no lo declara el morfo, así
que la excepción de demo de PLAN §7.8 tampoco lo abre.
- `transition-duration` / `transition-ease` — SON la transición que el guard
congela para poder medir lo demás. Medidos sin congelar: 0.12s -> 11.5s y
cubic-bezier(0.4, 0, 0.2, 1) -> steps(4), en la barra y en el thumb.
- README con su sección «Talla y tema» (13 claves por grupo) y veredicto §5 de
la ficha con las cifras.
QUÉ NO SE TOCA
- `thumb-bg-hover` se queda con el modificador DETRÁS: es un hover NEUTRO, y
los hovers neutros están EXCLUIDOS del codemod de D-TH.6 porque migran a la
capa de estado (firma 3). Su migración sigue bloqueada por morfo — el thumb
lleva `archetype: 'thumb'`, que no recibe velo.
- `base.ts` y `generated/base.css`: sin cambio de contrato no hay nada que
regenerar. 13 -> 13 claves.
ARTEFACTOS
- Censo: 94 % (17 knobs · 15 públicos · 1 literal · 1 sistema) -> **100 %**
(16 · 15 · 0 literal · 1 excepción · 1 sistema). Global 68 %, no baja.
- Sonda antes/después: **0 diffs sobre 896 valores computados**, 7 estados,
4 nodos (raíz · viewport · barra vertical · thumb).
- Captura 2× antes y después: idénticas.
- Centinela R-5.4: **10/13**, las 3 restantes adjudicadas -> verde.
- component-audit PASS · eidos-lint 17 morfo-backed / 1 eidos-only / **0
invalid** · `vitest run src/uix/eidos` 35/36 ficheros (el rojo conocido es
`skin-media-player`) · rtl:check 0 · docs:check 0 · `check` con **cero**
errores en ficheros de scroll-area.
- Prettier: los hunks de deriva del fichero son los MISMOS que en HEAD (3 en el
README, 3 en el CSS, ambos preexistentes); mi bloque no añade ninguno.
NOTA DE CONCURRENCIA: la pestaña `Tokens` de su demo (paso 11 del protocolo) la
escribí yo, pero entró en HEAD por `9fc38b19a` + `c88b2f861` de otra sesión, que
la arrastró con un `git add` derivado y lo declaró. No se re-commitea aquí.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
300153f9f6 |
uix(tabs): temable — 96 % → 97 %, y su indicador es CANAL DE VALOR, no tema
El contrato ya estaba entero (79 claves) y NO se acuña ninguna: las tres declaraciones que quedaban fuera lo están por doctrina, y así se firma. Lo que entra: - `width: 100%` de `fitted` firmado con su anotación `/* literal: */` (recipe-contract §3): es IDENTIDAD — `fitted` ES «la lista llena el eje inline», y un token ahí sólo podría tomar un valor sin desdecir la prop. Sale del ratio: 96 % → 97 %. - La propuesta §4.1 de la ficha (acuñar `indicator-width` / `-height` sobre `var(--indicator-w, 0px)`) se RECHAZA por escrito. Esas vars son el canal de VALOR de soma: la capa `MeasuredIndicator` escribe el rect del trigger activo en cada movimiento, así que un público encima sería un knob que un tema puede FIJAR — y fijarlo rompe el deslizamiento. Misma adjudicación que `navigation-menu` lleva escrita para su propio `indicator-w` (y la razón por la que su `-x` se retiró, muerto). El comentario de la receta lo dice ahora en el sitio donde se lee. - Guard R-5.4: entrada nueva en `COMPONENT_OVERRIDES` (barrido de `data-variant` line/surface/pills/segmented + las dos superficies de URL del propio demo, `perm.orientation=vertical` y `perm.disabled=true`): 40/79 → **70/79** sin adjudicar una clave de más. - Ledger: 9 adjudicaciones, todas MEDIDAS a mano sobre los nodos reales — los cuatro tokens de transición (el guard congela `transition`), los tres del anillo de foco (el guard hace `blur` a propósito), `trigger-bg` (la demo monta el Indicator y la regla que sube la etiqueta por encima de la píldora gana 0,2,0; sin indicador alcanza) y `scrollable-fade`, que además pinta por `mask-image`, fuera del juego de propiedades del guard. - README con su sección «Talla y tema» (tabla derivada del contrato) y pestaña `Tokens` en la demo (79 claves, verificada en el navegador). - Ficha `docs/audit/theming/tabs.md` con su veredicto §5. Comprobado y refutado: el trigger NO compone el `Button` canónico (`tabs-trigger.svelte` → `Tabs.Trigger` de soma, un `<button>` desnudo), así que la clase «el compuesto gana a la receta que lo compone» de toolbar / form no le aplica y no hay declaración muerta que ceder. Censo: 96 % → 97 % (77 knobs · 74 públicos · 2 globales · 0 literales · 1 excepción firmada · 1 sistema). Sin cambios en `recipes/base.ts` ni en `generated/base.css` — no hacía falta regenerar. Diff de computed: **0 diffs sobre 2.016 valores en 8 estados** (8 nodos en reposo, 7 en hover). Capturas 2× antes/después, idénticas. Guards: centinela 70/79 verde · `component-audit --only tabs` PASS · `eidos-lint tabs` 0 invalid (13 morfo-backed, 44 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 tabs · prettier limpio sobre el contenido normalizado a LF. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
c88b2f861d |
fix(demos): completo los tres contadores que faltaban — y declaro que el commit anterior se llevó trabajo ajeno
ERROR MÍO, DE LA CLASE QUE LLEVO DOCUMENTANDO TODO EL DÍA El commit anterior dice que scroll-area, slider y tabs quedaban «en manos de otra sesión» para una segunda pasada. Es verdad que mi script los excluyó — y falso que no entraran: el `git add` que escribí barría `git diff --name-only web/routes/uix/components/`, o sea TODAS las demos sucias, no sólo las que mi script tocó. Así que me llevé la pestaña Tokens que esa sesión estaba añadiendo a esos tres, a medio hacer y sin su commit. Es exactamente el hazard del índice compartido que registré en §13 esta misma tarde, con la vuelta de tuerca de que aquí no me lo hizo otra sesión: me lo hice yo, con un `git add` derivado de un `git diff` en vez de una lista explícita. La regla del brief dice «rutas EXPLÍCITAS» por esto, y no la seguí. NO LO REVIERTO, LO COMPLETO Revertir destruiría trabajo ajeno en vuelo, que es peor. El contenido que entró es correcto y está completo. Lo que faltaba es lo que mi propio commit prometía: los tres seguían con el contador escrito a mano. Convertidos al derivado, así que ahora el repo entero tiene CERO números a mano en las pestañas Tokens. Verificado en navegador sobre slider: el contador dice 39, el panel lista 39 filas y ninguna sin resolver. Lo que la otra sesión debe saber: sus tres ficheros de demo ya están en HEAD; su commit encontrará esos hunks aplicados. El resto de su trabajo (receta, contrato, README, ficha) no lo toqué. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
9fc38b19a4 |
fix(demos): el contador de la pestaña Tokens se DERIVA del contrato — tres ya mentían
El panel de Tokens existe precisamente para no escribir a mano lo que el contrato ya sabe: pregunta a ActiveEidos.getRecipeTokens(). Pero el número junto a la etiqueta de la pestaña SÍ estaba escrito a mano, y derivó como deriva siempre una segunda fuente de verdad. Auditadas las 105 demos que montan el panel: 90 contadores correctos, 15 sin contador y TRES que mentían — carousel decía 30 y son 27, drag-drop 10 y son 9, link-preview 33 y son 35. Nadie edita un badge cuando cambia una receta. Nace web/routes/uix/lib/TokensTabCount.svelte, que hace la MISMA pregunta que el panel de debajo y filtra los forwards con guion bajo. 102 demos convertidas; las tres que faltan (scroll-area, slider, tabs) están en manos de otra sesión y van en una segunda pasada, para que el índice compartido no vea nunca dos escritores sobre un fichero. Verificado en navegador: carousel pasa de decir 30 a decir 27, con 27 filas en el panel y ninguna sin resolver; metrics, que no tenía contador, dice 72 y lista 72. npm run check COMPLETED con los 72 errores preexistentes de la rama y ninguno en los 102 ficheros. Dos sesiones de esta tanda discreparon sobre si poner el contador —una lo puso a mano, otra lo omitió por ser justo lo que el panel evita—. Tenían razón las dos a medias: el contador es útil y no debe escribirse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
99a9011dd9 |
uix(demos): la pestaña Tokens en cinco demos — la superficie de tema se VE
El paso 11 del protocolo (`PLAN-theming.md` §7) llegó DESPUÉS de que estos cinco cerraran su tokenización, así que su superficie de tema no se veía en ninguna parte. La demo ES el producto: un componente temable cuya demo esconde sus tokens está a medio entregar. Las cinco piezas del molde de `collapsible`, sin una sola lista escrita a mano: el panel pregunta a `ActiveEidos.getRecipeTokens(name)`, de modo que un token que se añada, se renombre o se caiga aparece aquí sin que nadie se acuerde de tocar la demo. El `stage` que recibe cada panel es el nodo del escenario que ya existía en cada fichero (`stageRef`), no uno nuevo. Filas que lista cada panel — el número es el de claves públicas de su bloque en `lib/recipes/base.ts`, no una cifra copiada: radio-cards 40 password-field 30 aura 37 gradient-builder 72 (6 de ellas estructuradas: «por talla / ámbito») nav-tree 18 Verificado en Chrome de verdad, abriendo la pestaña en las cinco páginas: las tres columnas resuelven sobre el escenario vivo, cero filas sin resolver («—») y cero errores de consola. `npm run check`: 72 errores preexistentes, ninguno en estos ficheros. De paso: `gradient-builder` declaraba su `type Tab` en una línea de 101 columnas que prettier ya quería partir antes de esta sesión; al tocar esa misma línea queda en su forma canónica y el fichero pasa a estar limpio. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
43360ad0ae |
uix(demos): la pestaña Tokens en los cinco que cerraron antes del paso 11
`metrics`, `float-panel`, `stepper`, `timeline` y `tag-group` tokenizaron su
receta ANTES de que existiera el paso 11 del protocolo (`PLAN-theming.md` §7),
así que su superficie de tema no se veía en ninguna parte. La demo ES el
producto: un componente temable cuya demo esconde sus tokens está a medio
entregar.
Ninguna lista escrita a mano. El molde es `collapsible` —
`<TokensPanel component="{kebab}" stage={stageRef} />`—, y el panel pregunta a
`ActiveEidos.getRecipeTokens(name)`: se deriva del contrato VIVO de
`lib/recipes/base.ts`, así que una clave añadida, renombrada o retirada aparece
aquí sin que nadie tenga que acordarse de la demo.
Verificado en Chrome sobre el dev server, pestaña a pestaña. Cada fila resuelve
su valor computado sobre el escenario de la propia demo; ninguna queda en «—»:
metrics 72 filas
float-panel 40 filas
stepper 69 filas
timeline 45 filas
tag-group 91 filas
Las cinco cifras casan exactamente con las claves públicas (las que no empiezan
por `_`) del bloque de cada componente en `src/uix/eidos/lib/recipes/base.ts`.
Cero errores de consola en las cinco páginas.
`npm run check`: 72 errores / 62 avisos, ninguno en estos cinco ficheros —
idéntico antes y después. Los cinco `+page.svelte` arrastran deriva de formato
PREVIA (37–75 líneas cada uno ya sucias en HEAD); no se toca aquí, y el botón
nuevo copia literalmente la forma del hermano `Recipe` que tiene encima.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
ccdb7fc506 |
fix(demos): SIETE demos de la familia chart afirmaban no tener tokens, y tienen 45
La pestaña «Eidos recipe» de chart decía «No --chart-* tokens — the chart styles from global theme tokens directly», y desde el commit que la tokenizó hay 45 claves públicas en recipes/base.ts. Al añadirle la pestaña Tokens al lado, la demo se contradecía consigo misma: un panel listando 45 junto a un párrafo jurando que no hay ninguna. Lo destapó la sesión que añadió la pestaña, sobre chart. El grep con el que fui a comprobar si era un caso aislado pedía la frase entera y me devolvió DOS — line-chart repetía la de chart palabra por palabra. Repetido sin filtro de frase: son SIETE. area-chart, bar-chart, pie-chart y scatter-chart la dicen corta («styles from global theme tokens») y sparkline con otra coda. Es la memoria «grep en brief vuelve certificado»: un barrido que pide la redacción exacta encuentra las copias literales y pierde las variantes, que es justo donde vive el resto del defecto. Corregidas las siete con lo que es cierto, y sin perder lo que la frase vieja acertaba: los seis derivados VISTEN la receta de chart —su superficie son esas 45 claves, no un bloque propio— y las series siguen re-tiñéndose con el tema, porque el default de cada clave ES el token global que antes se leía a pelo. Eso es exactamente lo que la costura §2-A promete y aquí queda escrito para quien lea la demo. npm run check COMPLETED con los 72 errores preexistentes de la rama, ninguno de estos siete ficheros. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
e423b90c5b |
uix(demos): la pestaña Tokens en cinco demos — y `chart` no tenía escenario
Paso 11 del protocolo (PLAN-theming.md §7) sobre cinco componentes que cerraron su tokenización ANTES de que el paso existiera: su superficie de tema no se veía en ninguna parte. La demo es el producto; un componente temable cuya demo esconde sus tokens está a medio entregar. Nada escrito a mano — el panel se deriva del contrato vivo vía `ActiveEidos.getRecipeTokens(name)`. Mismo molde que collapsible. Filas que lista cada panel, verificadas EN CHROME sobre localhost:5180 (pulsada la pestaña, contadas las filas, las tres columnas resueltas al 100 %: ni un solo «—» en la columna que COMPUTA sobre el escenario): accordion 76 color-picker 71 drawer 54 popover 46 chart 45 Cuadran una a una con las claves públicas del bloque de cada componente en `src/uix/eidos/lib/recipes/base.ts`. `chart` era el raro: no tenía `stageRef`, así que nace aquí — `bind:this` en el `[data-uix-stage-area]` del escenario principal, NO en el de la galería de presets, que lleva el mismo atributo. Los otros cuatro ya lo tenían y conservan su nombre. Guards. `npm run check`: 72 errores, todos preexistentes y ajenos — ningún diagnóstico cita los cinco ficheros ni TokensPanel. Prettier: los cinco ya fallaban `--check` en HEAD con el contenido normalizado a LF, y el diff entre prettier(HEAD) y prettier(árbol) es EXACTAMENTE lo añadido, o sea que las líneas nuevas ya son canónicas y no arrastro deuda ajena. Cero errores de consola en las cinco páginas. Queda fuera, dicho para que no se pierda: el texto de la pestaña Recipe de `chart` sigue afirmando «No --chart-* tokens — the chart styles from global theme tokens directly». La tokenización posterior lo dejó obsoleto, y ahora contradice al panel de la pestaña de al lado, que lista 45. No lo toco: es copy ajeno a este paso. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
5f00609abe |
fix(theming): la prosa escrita a mano en una ficha SOBREVIVE a la regeneración
El generador de fichas conservaba un solo bloque —el veredicto §5, entre sus marcadores— y reescribía todo lo demás desde la plantilla. Así que una elaboración que un humano hubiera añadido en §1.1–§1.4 desaparecía en silencio: donde alguien 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 regeneración dejaba «_Ninguno._». Le pasó DOS VECES en el mismo día a las dos fichas de chat-*: la primera la cosí a mano, y mientras trabajaba otra sesión regeneró y la volvió a borrar. Restaurar a mano es jugar al topo; el defecto está en el generador. EL CONTRATO NUEVO Prosa a mano entre `<!-- mano:start -->` y `<!-- mano:end -->`, y el generador la re-inserta después del MISMO encabezado bajo el que estaba. Un bloque cuyo encabezado ya no exista NO se pierde: se añade al final bajo «Prosa rescatada» para que alguien lo reubique. Perder prosa no es nunca el comportamiento por defecto. Verificado corriendo `--report` sobre las 170 fichas con la prosa ya envuelta: los cuatro bloques de chat-log y chat-composer siguen ahí después. Que la regeneración sea mayoritariamente inocua y ocasionalmente destructiva es el peor reparto posible, porque nadie lee ese diff. Ahora no hace falta leerlo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
2498010a21 |
docs(theming): el handoff recoge la segunda tanda del 24 — ocho componentes, seis al 100 %
chat-message, chat-typing, fab, image-adjustments, separator y collapsible al 100 %; toolbar cerrado en 94 % y tags-input en 90 %, los dos por doctrina y no por deuda. Global 68 %, y los componentes al 100 % pasan de 36 a 42. Esta vez ningún commit se llevó trabajo ajeno: la ley del índice compartido ya iba en el brief. EL HALLAZGO QUE MÁS VALE Ceder el cromo al componente compuesto SALE GRATIS. toolbar deja que [data-button] gane —misma especificidad, emitido después— y no pierde ni una clave, porque su receta ya no escribe reglas sobre el botón. Medido antes de tocar nada: 51/54, y ninguna silenciosa era del botón. Es el reverso exacto de form, que conserva 23 declaraciones muertas por la misma causa. La firma pendiente de §13 tiene una salida barata y ya probada: no escribir la regla. LO QUE LA SUPERVISIÓN ARREGLÓ La sonda no congelaba nada, y es la que mide el gate del protocolo. Con transition y animation congeladas, los 18 diffs fantasma de chat-typing pasan a 0 sobre 1.568 valores. Las 164 fichas regeneradas quedaron clasificadas una a una en vez de por la cifra. Y refutado un susto: una sesión avisó de que cuatro veredictos §5 podían estar vacíos en HEAD; comprobados los ocho, intactos. DOS DEFECTOS REALES ANOTADOS Y NO TOCADOS El chip de añadir reacción de chat-message lo pinta popover.css y se ve en la captura: los chips de reacción son píldoras redondas y el de añadir un cuadrado gris. Y el morfo de tags-input sella aria-selected='true' como literal en cada etiqueta, así que archetypes.css le fija la tinta en reposo y su token nunca ha pintado — con cara de defecto de a11y. Los dos esperan decisión. Quedan cuatro de la cola A: scroll-area, tabs, slider y toast. 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 |
|
|
82aa500797 |
docs(theming): el registro §8 recoge fab y tags-input, con su sha
Las dos entradas que faltaban de la tanda del 24, cada una con el sha resuelto (la deuda de los trece `(COMMIT)` no se repite): - `fab` 88 % → 100 % (`5fd2fcdd8`), contrato 10 → 12, centinela 11/12 con 1 adjudicada. El cualificador de MODO va detrás; el guard no fotografía `translate` y el centinela se auto-cancela al llevarse el nodo de debajo del cursor. - `tags-input` 88 % → 90 % CERRADO (`92180c390`), contrato 90 → 91, centinela 63/91 con 28 adjudicadas. Sus cuatro privados son el puente THM-2, así que 90 % es su techo; y su `item-fg` no ha pintado nunca porque el morfo sella `aria-selected='true'` en cada etiqueta. docs:check 0. 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 |
|
|
bcb958e5dc |
docs(theming): el registro §8 recoge chat-message y chat-typing, con su sha
Las dos entradas del bloque de hoy sobre la familia chat, con las cifras medidas y su «lo que enseñó»: `chat-message` 84 % → 100 % (`f882e1b9d`, contrato 75 → 81, centinela 77/81 con 4 adjudicadas) y `chat-typing` 89 % → 100 % (`d39147c11`, contrato 7 → 8, centinela 8/8 sin adjudicar). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
d39147c119 |
uix(chat-typing): temable — 89 % → 100 %, con UNA clave y siete de sus ocho ya vivas
Protocolo PLAN-theming §7 sobre `chat-typing`. Censo 89 % → **100 %**, contrato 7 → **8** claves, centinela **8/8** con **cero adjudicadas**. ## Lo que entra: una clave, y es la COSTURA `dot-radius` (`var(--radius-full)`), el único knob que leía el sistema a pelo. El valor sigue siendo el del sistema; el knob pasa a ser del componente. **El nombre sale del CATÁLOGO, no del generador.** La ficha proponía `indicator-radius` —nombra por el primer selector de la regla, `[data-chat-typing-indicator] > span`— cuando el nodo que PINTA es el punto y el contrato ya habla `dot-size` / `dot-gap` / `dot-fg`. Es el defecto de `tree-view` («root-bg» para una guía de indentación) en pequeño. ## Lo que el instrumento no veía: 3 nodos de 8 Los tres puntos son `> span` DESNUDOS del indicador —sin `data-chat-typing-*`, la clase de la pastilla del separador de `chat-log`— y la demo arranca con NADIE escribiendo, así que `data-state='idle'` esconde a todos los hijos (presencia = visibilidad, N-7). Con el selector extra y un typer encendido por `prepareWith`: **8 nodos**, y el centinela ya daba **7/7 antes de tocar el código**. ## El diff de computed NO cerró en cero, y es RUIDO reproducido 18 diffs, los 18 de `opacity` y los 18 en los tres `span[data-animation-style=pulse]`. Sus puntos montan el loop `pulse` del SISTEMA, que anima `opacity` sin parar, así que cada lectura cae en una fase distinta: corriendo la sonda dos veces sobre el MISMO código salen los mismos 18 (control `after` vs `after2`). Ninguna otra propiedad se mueve, la clave tocada es `border-radius`, y las capturas 2x antes/después son **idénticas byte a byte** (1.568 valores · 7 estados · 8 nodos). ## Guards censo `--only chat-typing` 100 % (global 68 %, no baja; los que llegan al 100 % pasan de 36 a 42) · `component-audit` PASS · `eidos-lint` 0 invalid (8 morfo-backed, 0 eidos-only) · `vitest run src/uix/eidos` sin rojos nuevos (el único vivo es el conocido `skin-media-player`) · `rtl:check` 0 · `docs:check` 0 · `check` COMPLETED sin un solo error del componente · prettier limpio sobre el contenido normalizado a LF. README con su sección «Talla y tema», demo con pestaña `Tokens` (8 claves, verificada en navegador) y ficha con su veredicto §5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
f882e1b9d9 |
uix(chat-message): temable — 84 % → 100 %, y las TREINTA muertas eran ejes que la demo no enciende
Protocolo PLAN-theming §7 sobre `chat-message`, el mayor de la familia chat.
Censo 84 % → **100 %**, contrato 75 → **81** claves, centinela **77/81** con 4
adjudicadas. El default NO se mueve: diff de computed VACÍO (4.192 valores · 8
estados · 16 nodos) y capturas 2x antes/después **idénticas byte a byte**, en
reposo y con la barra tapback abierta.
## Otra vez, lo caro fue VER
El guard leía **45/75** antes de tocar una línea de código. Una fila de chat es
una PILA de superficies opt-in (reply citado, read-by, estado de entrega,
mención) y de ejes de PRESENTACIÓN (`run`, `direction`, `emphasized`) que la
demo arranca en su posición más pobre: `solo` + `in`, sin ninguna de las cuatro.
Con las superficies encendidas por `prepareWith` y los cinco ejes barridos como
PRODUCTO: **71/75 antes de acuñar nada**. La sonda pasó de 12 nodos a 16 en
reposo, y a 24 con el panel abierto.
## Lo que entra (6 claves, la COSTURA de los seis globales)
`focus-radius` · `mentioned-fg` · `reply-fg` · `reaction-fg` ·
`reaction-inner-gap` · `quick-react-radius`. El valor sigue siendo el del
sistema; el knob pasa a ser del componente.
**Los nombres salen del CATÁLOGO, no del generador.** La ficha proponía `radius`
(colisiona con `emphasize-radius`, que ES la esquina en reposo de la MISMA
fila), `bubble-fg` (el knob es de la MENCIÓN: `mentioned-bg` y
`mentioned-accent` ya existían), `reaction-width` + `reaction-height` para el
glifo (`reaction-height` ya existe y es la altura del CHIP) y
`quick-reactions-width` para un `max-content` que es identidad.
## El caso que obligó a decidir: `reaction-gap` ya existía con otro sentido
La receta la pinta en la fila `reactions` — el hueco ENTRE chips — mientras el
knob nuevo es el ritmo INTERNO del chip, el emoji y su cuenta. Mismo valor
(`--space-1`), dos papeles: un chip más denso no es una fila más apretada.
Reusar la clave habría cambiado en silencio lo que mueve un tema que ya la usa,
así que entra como `reaction-inner-gap`. El resto del bloque `{parte}-gap` de
esta receta (`meta-gap`, `read-by-gap`, `header-gap`, `actions-gap`) significa
«dentro de la parte»: la anómala es la vieja, y renombrarla es churn con riesgo.
## Lo que SALE: una regla que no ha pintado nunca
`[data-chat-message-reaction] svg, [data-chat-message-reaction-add] svg` fijaba
`1.1em` en los dos ejes «porque un svg de sólo viewBox computa 0x0». El glifo
por defecto es el `Icon` compuesto, que emite `style="width:
var(--icon-size-sm); height: ..."` EN LÍNEA, y un estilo en línea gana a todo
selector. Medido: **16 px** (el paso `sm` del icono), no los 15,4 px que `1.1em`
daría sobre los 14 px heredados. La otra mitad del selector no tiene nodo: los
chips llevan un emoji de texto. **Retirada: 0 diffs.** Tercera vez en la familia
(chat-log y chat-composer, ayer).
## Identidades firmadas (4, fuera del ratio)
`inline-size: max-content` de la barra tapback (la barra ES su fila de emoji),
`line-height: 1` de la celda (la celda es la caja del glifo) y los dos
`opacity: 1` de la pastilla de acciones (el final del fundido 0 → 1).
## Adjudicadas (4) — las cuatro son límites del INSTRUMENTO, medidas a mano
- `bubble-tail-radius` — el guard fotografía UNA esquina (`borderTopLeftRadius`)
y la cola es la de ABAJO. Medido en las 8 combinaciones dirección x run:
4 px → 1234 px en `solo` y `last`, en las dos direcciones. Su hermana
`bubble-radius-run` lee viva porque `middle` aplana la esquina START, que sí
está en la lista.
- `emphasize-duration` — ES la transición que el guard congela para medir todo
lo demás. Sin congelar: 0,24 s → 4,321 s.
- `focus-radius` — la fila sólo es tabulable compuesta DENTRO de un Feed (soma
fusiona la identidad de `Feed.Article` cuando hay Feed ancestro) y su propia
demo la monta suelta: `:focus-visible` no tiene nodo ahí. Medido en la demo de
`chat-log`, donde las filas SÍ son artículos de feed (`tabindex=0`): reposo
6 px, enfocada 4 px → 1234 px, por foco programático y por recorrido con Tab.
- `quick-react-hover-scale` — `transform` no está en la lista de propiedades del
guard (punto ciego ya adjudicado en background / rating-group / card) y la
celda es un botón PORTALADO con regla `:hover`. Con puntero real:
`matrix(1.18…)` → `matrix(7.77…)`.
## Un defecto real medido y NO corregido aquí (mueve píxel)
El chip de añadir reacción lleva también `data-popover-trigger`, y
`[data-popover-trigger]:not([data-archetype='field-trigger'])` pesa (0,2,0)
contra los (0,1,0) de `[data-chat-message-reaction-add]`: su fondo, borde,
radio, tinta, altura, padding y tamaño de letra los pinta `popover.css`. Se ve
en la captura — los dos chips de reacción son píldoras redondas y el de añadir
es un cuadrado gris. Los `reaction-*` no mienten (alcanzan sobre los chips
normales), así que no hay nada que retirar: es una decisión de diseño. Clase
`gradient-picker` / `emoji-picker`. Queda REGISTRADO, no tocado (D-TH.5).
## Guards
censo `--only chat-message` 100 % (global 68 %, no baja) · `component-audit`
PASS · `eidos-lint` 0 invalid (37 morfo-backed / 41 eidos-only) · `vitest run
src/uix/eidos` sin rojos nuevos (el único vivo es el conocido
`skin-media-player`) · `rtl:check` 0 · `docs:check` 0 · `check` COMPLETED sin un
solo error del componente · prettier limpio sobre el contenido normalizado a LF.
README con su sección «Talla y tema», demo con pestaña `Tokens` (81 claves,
verificada en navegador) y ficha con su veredicto §5.
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 |
|
|
2b6b6aa10b |
docs(theming): el registro §8 recoge image-adjustments y separator, con su sha
Las dos entradas de la tanda, con el sha PUESTO (no el marcador `(COMMIT)`, que ya dejó trece filas sin resolver): `image-adjustments` 67 % → 100 % (`e76d2db2b`) y `separator` 67 % → 100 % (`acf9c3a23`). Lo que las dos dejan escrito, y no estaba en el registro: - **El techo puede estar en el contrato que YA existe.** `separator` cierra en el 100 % sin acuñar una sola clave: sus dos knobs fuera de alcance eran los `100%` de cada orientación, que son la IDENTIDAD del primitivo y se FIRMAN. - **Medir de más midió menos, y por un tope numérico**: el pase de hover del centinela recorre como mucho 30 nodos, así que ampliar `extraNodes` de una fila a seis empujó el control medido al puesto 32 y su token leyó muerto por una razón ajena a él. - **Un token muerto por la ORIENTACIÓN que la demo no monta se arregla midiendo**: `sweepAttr` sobre `data-orientation` recorre las dos sobre los mismos nodos, mientras que cambiar el chip de la demo cambia una por la otra. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
9e471e818d |
docs(theming): el registro §8 recoge collapsible y toolbar, con su sha puesto
Las dos entradas de la sesión del 24, cada una con el sha REAL del commit del componente (que es por lo que van en un commit aparte: trece entradas quedaron un día con el marcador `(COMMIT)` sin resolver y hubo que arreglarlas). - `collapsible` 90 % → 100 % (`1621de93c`) — una clave, la costura del `gap` del encabezado; el que ANIMA su apertura no tiene un solo knob de motion porque su firma es el par de eventos, no un `@keyframes`. - `toolbar` 91 % → 94 % CERRADO (`26713f288`) — cero claves acuñadas: sus dos privados son conmutadores por variante cuya segunda rama es la identidad de la variante, y ceder el cromo del botón al `<Button>` compuesto le sale GRATIS, al revés que a `form`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
acf9c3a234 |
uix(separator): temable — 67 % → 100 %, SIN acuñar una sola clave
Su alcance no subía porque le faltaran tokens: subía firmando lo que nunca fue
un knob. Los dos que quedaban fuera eran `inline-size: 100%` en el horizontal y
`block-size: 100%` en el vertical — la IDENTIDAD del primitivo. Una regla ocupa
su contenedor; un separador que no lo hiciera sería otro componente, y su propio
README ya lo decía en sus Gaps («Horizontal already fills 100%»). Llevan ahora su
anotación `/* literal: … */` (recipe-contract §3) y salen del ratio.
Contrato **3 → 3 claves**: no entra ninguna, y ésa es la decisión. `thickness`
(el mismo token alimenta `block-size` en horizontal e `inline-size` en vertical),
`fg` (el slot 6 `--color-neutral-separator`, que existe para retocar divisores
sin tocar bordes de control) y `min-length` son TODA su apariencia. Acuñar un
`--separator-length` habría sido inventar un eje que nadie pidió.
Censo: 6 knobs · 4 públicos · 2 literales · **67 %**
→ 4 knobs · 4 públicos · 0 literales · 2 excepciones · **100 %**.
Diff de computed **VACÍO**: 448 valores, 7 estados, sonda antes y después
(el cambio es de comentarios: no puede mover un píxel, y se midió igual).
Capturas 2× antes/después, miradas: idénticas.
Centinela R-5.4 **2/3 → 3/3, cero adjudicadas**, y ahí estuvo el trabajo:
`min-length` leía MUERTO y no mentía. La demo arranca en el ejemplo `stacked`,
que monta sólo reglas horizontales, y la mitad de la receta cuelga de
`[data-orientation='vertical']`. Se arregla midiendo, no adjudicando: un
`sweepAttr` sobre `data-orientation` en `COMPONENT_OVERRIDES` recorre las DOS
orientaciones sobre los mismos nodos. Cambiar el chip de la demo al ejemplo
`toolbar` no habría servido — cambia una orientación por la otra en vez de
sumarlas, la trampa de «montar MÁS puede medir MENOS» otra vez.
Guards: censo `--only separator` 100 % · `component-audit` PASS ·
`eidos-lint` invalid 0 · `vitest run src/uix/eidos` 35/36 ficheros (el rojo
conocido `skin-media-player`) · `rtl:check` 0 · `docs:check` 0 · `check` sin un
solo error atribuible a este componente · prettier limpio con el contenido
normalizado a LF.
Más el README con su sección «Talla y tema», la pestaña `Tokens` de la demo
(3 claves, verificada en navegador) y el veredicto §5 de su ficha, que escribe
la cifra cerrada: el techo de este componente ES el 100 %.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
26713f2887 |
uix(toolbar): temable — 91 % → 94 % CERRADO, y ceder el cromo del botón SALE GRATIS
Cero claves acuñadas, y eso es el resultado: el censo daba `global 0` — la receta ya lee su propio contrato en cada declaración, con el eje `size` resuelto por el TSC a través de siete privados que sólo reapuntan claves públicas por talla. Lo que quedaba fuera del alcance eran tres cosas CLASIFICADAS, no tres deudas. La mitad del trabajo de este eje es adjudicar. 1. Los DOS privados son CONMUTADORES por variante, medidos variante a variante sobre el nodo real: `--_toolbar-bg` vale `var(--toolbar-bg)` (oklch(0.9821 0 0)) en `surface` y `transparent` en `outline` y `ghost`; `--_toolbar-shadow` vale `var(--toolbar-shadow)` y `none` en las mismas. Ese segundo valor es la IDENTIDAD de la variante, no un knob: una barra `ghost` ES la que no tiene relleno ni sombra, y un público encima dejaría que un tema la rellenara y matara la variante en silencio. Se quedan privados (clase «conmutador» de F2-B, sexto caso tras textarea, spinner, skeleton, code y label). Ni escala por talla ni puente THM-2: esta barra no tiene paleta. 2. El único literal es una IDENTIDAD y ahora está FIRMADO: el `inline-size: 100%` del separador horizontal abarca el eje transversal de la barra — el mismo trabajo que `align-self: stretch` hace en el gemelo vertical (medido: 112 px sobre un contenedor de 126 px). Su grosor y su suelo sí son tokens. Con su anotación `/* literal: */` sale del ratio. 3. LA CASCADA DEL COMPONENTE COMPUESTO NO LE CUESTA UNA SOLA CLAVE, y es la lección. `Toolbar.Button` compone el `<Button>` canónico, así que sus nodos llevan `data-button` Y `data-toolbar-button`, y `[data-button]` casa con la misma especificidad (0,1,0) pero se emite DESPUÉS. La diferencia con `form` —que conserva 24 declaraciones que Button anula— es que esta receta YA CEDIÓ el cromo del botón (A-112) y no escribe ni una regla `[data-toolbar-button]`. Medido ANTES de tocar nada: 51/54 vivos, y ninguna de las tres silenciosas era del botón. Las claves `control-*` visten el Link y el GroupItem, que sí son superficie de la barra. Censo: 35 → 34 knobs · público 30 · privado 2 · literal 1 → 0 · excepción 0 → 1 · sistema 2 · 91 % → 94 %. Contrato 54 claves, intacto. Global del catálogo 68 %, sin bajar. Diff de computed: VACÍO — 2.464 valores en 7 estados sobre 11 nodos (la barra, sus tres botones compuestos, dos separadores, el grupo, sus tres items y el enlace). Capturas 2× antes/después: idénticas. Centinela R-5.4: 52/54, dos adjudicadas, cero muertas sin razón. - `transition-duration` / `transition-ease` SON la transición que el guard congela para poder leer todo lo demás. Medidas sin congelar sobre el Link real, que transiciona CUATRO propiedades: `0.12s ×4 → 4.321s ×4` y `cubic-bezier(0.4, 0, 0.2, 1) ×4 → steps(3) ×4`. Al ledger con esa razón. - `disabled-opacity` NO se adjudica: se ARREGLA. El guard enciende ahora el interruptor «group disabled» de la demo, y comprobado que no tapa nada — la regla de hover es `[data-toolbar-link]:hover, [data-toolbar-group-item]:hover:not([data-disabled])` y el Link no pertenece al grupo, así que conserva las dos claves de hover. Corrido antes y después del control: 51/54 → 52/54, el conjunto muerto encoge en uno y no gana ninguno. Guards: censo `--only` 94 % · `component-audit --only toolbar` PASS · `eidos-lint toolbar` 16 morfo-backed / 5 eidos-only / 0 invalid · `vitest run src/uix/eidos` 35/36 ficheros (el rojo es `skin-media-player`, el conocido) · `rtl:check` 0 · `docs:check` 0 · `check` COMPLETED sin un solo error atribuible a este componente · prettier: la anotación `/* literal: */` sobrevive en la MISMA línea y mi bloque del README queda limpio; los 12 hunks de deriva del README y los 12 de la demo son PREEXISTENTES en HEAD y no se tocan. Artefactos de documentación del protocolo: README con su `## Talla y tema` derivada del contrato (los nueve ejes + la clasificación de los privados), pestaña `Tokens` en la demo (54 claves resueltas en vivo, verificada en navegador) y veredicto §5 de la ficha. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
e76d2db2be |
uix(image-adjustments): temable — 67 % → 100 %, y medir de MÁS midió menos
Sus cuatro knobs fuera de alcance eran LA COSTURA (PLAN §2-A) y ninguno una
clave nueva de diseño: el valor se queda donde estaba, el knob pasa a ser del
componente.
Entran cuatro claves (contrato 12 → 16), valor verbatim:
- `head-gap` = `var(--space-2)` y `label-line-height` = `var(--leading-ui)`,
que la receta leía a pelo — un tema no podía apretar la línea de cabecera sin
mover esos primitivos en toda la app.
- `hover-reset-fg` = `var(--color-content-primary)`. NO es un hover inventado
por componente: es TINTA, y el velo del sistema es `background-image`, que un
control sin superficie no puede recibir. Molde del catálogo: once
`hover-{parte}-fg` ya escritos así.
- `focus-reset-radius` = `var(--radius-sm)`. Precedente exacto
`rating-group.focus-radius`, la misma declaración dentro de la misma regla
`:focus-visible`. La §4 generada proponía `reset-radius` (el control no tiene
radio en reposo) e `item-label-line-height` (el bloque ya habla `label-*`):
el catálogo decide el nombre, no la propuesta.
El literal que quedaba se FIRMA, no se acuña: `outline-color: Highlight` bajo
`@media (forced-colors: active)` es la palabra clave del sistema — la paleta del
SO manda ahí. Pasa a `exception`, fuera del ratio.
El canal de VALOR sigue sin acuñarse y aquí no había ninguno que confundir: la
salida del panel es la CADENA `filter` que soma entrega por `onFilterChange`,
nunca toca el CSS de la receta.
Censo: 18 knobs · 10 públicos · 4 global · 1 literal · 3 sistema · **67 %**
→ 17 knobs · 14 públicos · 0 global · 0 literal · 3 sistema · 1 excepción
· **100 %**.
Diff de computed **VACÍO**: 5.440 valores, 7 estados, 26 nodos, sonda antes y
después. Capturas 2× antes/después, miradas: idénticas.
Píxel hacia arriba (§7.4-12, obligatorio porque toca una regla `:hover`): el
píxel bajo el puntero ES el `<button data-image-adjustments-reset>`; el hover
mueve `color` y SÓLO `color` en ese nodo (oklch(0.5032 0 0) → oklch(0.2435 0 0))
y ni él ni un solo ancestro pintan `background-image`, ni en reposo ni en hover.
Centinela R-5.4 **15/16**, 1 adjudicada — y el instrumento enseñó dos cosas:
1. `hue-track` leía muerto (11/12) y estaba vivísimo: pinta en el `::before` del
`<Slider>` COMPUESTO, cuyo nodo lleva `data-slider*`. Clase de `waveform`.
`extraNodes` en `COMPONENT_OVERRIDES`.
2. Ese selector apunta SÓLO a la fila `hue`, y la precisión es funcional: con
las seis filas el conjunto medido pasó a 32 nodos y el reset se volvió el
nº 32, fuera del tope de 30 del pase de hover — `hover-reset-fg` leía muerto
por una razón ajena al token. **Medir de más midió menos.**
La adjudicación restante es de estado: `focus-reset-radius` sólo pinta bajo
`:focus-visible` y el guard desenfoca a propósito; medido a mano sobre el
reset real, 4px → 1234px.
Guards: censo `--only image-adjustments` 100 % · `component-audit` PASS ·
`eidos-lint` invalid 0 · `vitest run src/uix/eidos` 35/36 ficheros (el rojo
conocido `skin-media-player`) · `rtl:check` 0 · `docs:check` 0 · `check` sin un
solo error atribuible a este componente · `--names` sin desviadas suyas ·
prettier limpio con el contenido normalizado a LF.
Más el README con su sección «Talla y tema», la pestaña `Tokens` de la demo
(16 claves, verificada en navegador) y el veredicto §5 de su ficha.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
5fd2fcdd86 |
uix(fab): temable — 88 % → 100 %, y el modo va DETRÁS, no delante
Le faltaban DOS knobs y los dos son del pill extendido: el FAB circular no declara ni `padding-inline` ni `gap`, pero la regla `[data-button][data-fab][data-extended]` sí, y leía `var(--space-5)` / `var(--space-2)` A PELO. La COSTURA del PLAN §2-A: el valor sigue siendo del sistema, el knob pasa a ser del componente. `global` a CERO. Claves que entran (2, defaults verbatim): - `--fab-padding-inline-extended: var(--space-5)` - `--fab-gap-extended: var(--space-2)` El nombre lleva el cualificador DETRÁS. `extended` es un MODO del FAB, no un estado interactivo (el vocabulario cerrado es hover · active · selected · disabled · checked · open · focus · invalid · current), así que cae en la otra mitad de la frase firmada en D-TH.6 —«delante lo interactivo, detrás lo dimensional y contextual»—, igual que `sidebar.width-icon` y `radio-group.gap-vertical`. Un `--fab-padding-inline` a secas habría prometido a TODO FAB un padding que sólo tiene el pill. Lo que NO se acuña, y por qué el 100 % no lleva las tres claves de la §4: el `font-size: 1em` del glifo es identidad de contexto y ya lleva su anotación `/* literal: */` (fuera del ratio por recipe-contract §3), y la colocación flotante es de la capa `viewport-placement`, cuya ranura de override Fab escribe sin acuñar vocabulario paralelo (`--fab-offset` / `--fab-z` se retiraron por eso en 2026-08-15). La composición NO le quita nada, y valía la pena medirlo: el mismo `<button>` lleva `data-button` Y `data-fab`, la forma exacta del hallazgo de `gradient-picker` (36 claves muertas bajo `popover.css`). Aquí no ocurre por construcción — las reglas dimensionales del FAB casan `[data-button][data-fab][data-fab-size]` (0,3,0) contra los (0,2,0) de `[data-button][data-size]`, así que ganan sea cual sea el orden de carga de los chunks. Medido: padding computado 20px = `--space-5`, no el del Button. Tampoco lleva `data-depth`, así que §12.9 no le aplica. Censo: 16 knobs · público 14 → 16 · global 2 → 0 · excepción 1 (fuera del ratio) · 88 % → 100 %. Contrato 10 → 12 claves. Diff de computed: VACÍO en las dos formas. 416 valores × 7 estados en el escenario por defecto (circular, sonda estándar) y 188 valores × 4 tallas + hover en el pill extendido, con una sonda de un solo uso porque la demo arranca circular. Capturas 2× antes/después byte a byte IDÉNTICAS en las dos. No se tocó ninguna regla `:hover`, así que el paso 12 no aplica. Centinela R-5.4: **11/12**, 1 adjudicada. `lift` es la laguna del INSTRUMENTO, no del token: la receta lo consume con la propiedad `translate` (no `transform`, para no pisar el press-squeeze del Button) dentro de una regla `:hover`, y el guard ni fotografía `translate` —la misma laguna ya adjudicada tres veces sobre `transform` en background / rating-group / card— ni pasa el ratón en su pasada estática. Medido a mano con puntero real: `--fab-lift: 1234px` escrito ANTES de entrar da `translate: 0px -1234px` a los 300 ms → alcanza. Y trae una trampa nueva: el centinela SE AUTO-CANCELA — un lift de ese tamaño se lleva el nodo de debajo del cursor, `:hover` cae y el valor vuelve a `none` hacia t+900 ms. Añadirle una pasada de hover al guard no lo mediría. El instrumento aprendió dos cosas de este componente, las dos por el §2 «cuenta los nodos»: un FAB es UN nodo, así que su segunda superficie pintada —el hueco de icono del Button compuesto— entra por `EXTRA_NODES` (1 → 2 nodos); y su eje de talla es `data-fab-size`, NO `data-size`, así que el barrido genérico del guard no sellaba nada. Con el barrido cartesiano `data-fab-size` × `data-extended` el guard pasa de **3/12 a 11/12** sin adjudicar una sola clave de más. Los dos interruptores son entradas por componente: no tocan a nadie más y no exigen re-verificar el ledger. Guards: censo `--only fab` 100 % (global 68 %, no baja) · `--names` 12 conformes, 0 desviadas · `component-audit --only fab` PASS · `eidos-lint fab` 0 invalid (14 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» (tabla derivada del contrato), pestaña `Tokens` en la demo verificada en navegador (12 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 |
|
|
1621de93c4 |
uix(collapsible): temable — 90 % → 100 %, y el que ANIMA no tiene un knob de motion
Una sola clave, y es la COSTURA (PLAN §2-A): el `gap` del encabezado leía `var(--space-2)` A PELO. El valor es del sistema; el knob no era de nadie, así que un tema no podía apretar esta cabecera sin mover el paso de espaciado en toda la app. El nombre lo decide el CATÁLOGO, no la propuesta de la ficha: `trigger-gap` ya existe ocho veces en `base.ts`, cinco de ellas con exactamente `var(--space-2)`. Qué entra: - `--collapsible-trigger-gap: var(--space-2)` — valor verbatim, cero píxel. Qué NO entra, y por qué: - Los dos knobs restantes son SISTEMA TRANSVERSAL, fuera del ratio: el velo de hover es `linear-gradient(var(--state-hover), var(--state-hover))` (la capa de `archetypes.css`, nunca una invención por componente) y el anillo de foco es `--focus-ring-*`. - **No hay clave de motion que acuñar.** Este componente «anima su apertura» y aun así su receta no declara un solo `@keyframes`: la firma es el par de eventos `emerge-expand` / `emerge-collapse` que materializa `EidosConfig.motion.signatures` (recipe-contract §2, R-4.5). Lo único suyo es el par `transition-*`, que ya estaba en el contrato. Censo: 12 knobs · público 9 → 10 · global 1 → 0 · sistema 2 · 90 % → 100 %. Contrato 11 → 12 claves. Global del catálogo 68 %, sin bajar. Diff de computed: VACÍO — 736 valores en 8 estados (reposo, cinco tallas, abierto y hover) sobre 3 nodos, que son las TRES partes del morfo, en cerrado y en abierto. Capturas 2× antes/después, reposo y abierto: idénticas. Centinela R-5.4: 10/12, dos adjudicadas, cero muertas sin razón. - `transition-duration` / `transition-ease` SON la transición que el guard congela para poder leer todo lo demás (la clase que `color-picker` documentó el 2026-08-23). Medidas sin congelar sobre el encabezado real: `0.18s, 0.18s → 4.321s, 4.321s` y `cubic-bezier(0.4, 0, 0.2, 1) ×2 → steps(3) ×2` — dos entradas porque el trigger transiciona `background` Y `color`. Al ledger con esa razón. - `disabled-opacity` NO se adjudica: se ARREGLA. Encender el interruptor `disabled` de la demo para toda la corrida se habría llevado el tinte de hover por delante (`pointer-events: none` en el provider — «montar más mide menos»), así que el estado se mide como SUPERFICIE EXTRA por la URL de la demo (`?perm.disabled=true`), precedente `radio-group`. 8/11 → 10/12. Guards: censo `--only` 100 % · `component-audit --only collapsible` PASS · `eidos-lint collapsible` 7 morfo-backed / 0 invalid · `vitest run src/uix/eidos` 35/36 ficheros (el rojo es `skin-media-player`, el conocido) · `rtl:check` 0 · `docs:check` 0 · `check` COMPLETED sin un solo error atribuible a este componente · prettier: mi bloque limpio, la deriva del README y de la demo es PREEXISTENTE en HEAD y no se toca. Artefactos de documentación del protocolo: README con su `## Talla y tema` derivada del contrato, pestaña `Tokens` en la demo (12 claves resueltas en vivo, verificada en navegador) y veredicto §5 de la ficha. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
bf6cd201cf |
docs(theming): el handoff recoge la deuda B saldada — quince de dieciocho
Quedan tres, y los tres por una razón concreta: audio-player no tiene README de eidos donde escribir la sección, y palabras y proof-of-human son carriles propios. Y queda anotada la deuda hermana que destapó hacerlo: ninguno de los quince tiene pestaña Tokens en su demo, porque el paso 11 del protocolo llegó después de que cerraran. Hasta que la tengan, la tabla del README es la fuente — está escrito en los quince README, no sólo aquí. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
a6df34c052 |
docs(theming): quince componentes recuperan su README «Talla y tema» — la deuda B de la revisión
La revisión del 24 separó la cola en dos: 16 componentes que nunca han pasado por el eje y 18 que SÍ pasaron y sólo deben el README «Talla y tema». Esto salda quince de esos dieciocho. La tabla es DERIVADA del contrato y del ledger, nunca escrita a mano: lo que un lector ve es lo que dice base.ts. Con dos formas según el tamaño —tabla de clave/valor hasta 30 claves, agrupada por parte por encima— y, cuando el guard tiene adjudicaciones escritas para el componente, la lista de qué da por silencioso y con qué razón medida. drawer 54 claves (24 adjudicadas) · accordion 76 · metrics 72 (17) · gradient-builder 72 · color-picker 71 (24) · stepper 69 · tag-group 91 · popover 46 (12) · chart 45 · timeline 45 · float-panel 40 (22) · radio-cards 40 (4) · aura 37 (11) · password-field 30 (6) · nav-tree 18. LO QUE NO ENTRA, DICHO EN VOZ ALTA - audio-player no tiene README de eidos: no hay dónde escribir la sección. Queda como el decimosexto, aparte. - palabras y proof-of-human son carriles propios, fuera de esta pasada. - NINGUNO de los quince tiene pestaña Tokens en su demo. El generador escribía «la pestaña Tokens de su demo lista estas mismas claves», que habría sido FALSO en los quince; sustituido por lo que es cierto, con un aviso de que el paso 11 del protocolo llegó después de que estos componentes cerraran y de que hasta entonces la tabla del README es la fuente. La otra mitad de la deuda —las quince pestañas— sigue abierta. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
2370fe5378 |
docs(theming): FIRMADO — completar una demo que no monta su propio componente es instrumento, no diseño
Cierra P2, lo último del plan de la revisión del 24, y con él la revisión entera. LA TENSIÓN, Y DÓNDE CAE Dos doctrinas chocaban en el commit de chat-log: «las demos quedan FUERA del plan de theming» contra «la demo ES el producto, un testbed interactivo con profundidad canónica». La primera se escribió para dos cosas concretas —que un hallazgo de demo no se registre ni se mida, y que nadie rediseñe una demo «ya que estamos»—, y las dos siguen en pie. Lo que no cubría: una demo que sólo menciona en PROSA partes que la receta viste y el morfo declara no es un testbed, es una página. En chat-log eran tres de sus seis partes sin montar y ONCE claves vivas sin un nodo donde probarse. LA EXCEPCIÓN, CON CUATRO CONDICIONES VERIFICABLES 1. Sólo partes o estados del PROPIO componente, declarados en su morfo. 2. Contenido mínimo canónico: el ejemplo más corto que hace existir la parte. 3. El diff de computed sobre lo que YA estaba montado sigue siendo CERO. 4. Declarado en el mensaje de commit, con las claves que pasan a medibles. Y la mitad que no se toca: lo aprendido mirando una demo sigue sin entrar en el ratio ni en el registro. La excepción abre la mano para MEDIR, no para contabilizar. chat-log cumple las cuatro —comprobado: separator-day, event y divider-unread están los tres en su morfo—, así que su commit queda validado retroactivamente. LAS TRES DESCARTADAS, Y POR QUÉ Revertir el montaje habría convertido once claves VIVAS en verdes-por-excusa, que es lo contrario de lo que R-5.4 significa. Una ruta de sonda aparte duplica superficie por componente y contradice «la demo ES el producto» por el otro lado. Y los nodos sintéticos chocan de frente con verify-with-real-components, ya firmado. Con esto la revisión del 24 queda CERRADA: plan §6 ejecutado entero. 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 |
|
|
df839849a4 |
docs(theming): trece entradas del registro decían (COMMIT) donde va el sha
El §8 existe para que cualquiera pueda ir del número al cambio que lo produjo. Trece entradas —las doce de la tanda del 23/24 más progress— llevaban el marcador (COMMIT) sin resolver, así que daban la cifra y no el camino. Resueltos los trece contra el log. toggle lleva los dos, porque su trabajo quedó partido en dos commits por la carrera del índice compartido. Mismo defecto que las ocho entradas que faltan del todo (D1 de la revisión del 24): un registro a medias no es un registro. 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 |
|
|
2e0f4b6504 |
fix(theming): el guard aprende a decir OSCILANTE, y deja de dar falsas alarmas
Un token puede leerse vivo unas corridas y muerto otras sobre el MISMO HEAD, sin mentir: la culpa es de la apertura del guard, no del contrato. Hasta hoy eso rompía el ledger por los dos lados. - Si el token está adjudicado y la corrida lo lee VIVO, el guard gritaba STALE y la sesión siguiente borraba una adjudicación correcta. - Si NO está adjudicado y la corrida lo lee muerto, el guard fallaba R-5.4 con un token que alcanza perfectamente. Una razón que empiece por OSCILLATES: describe justo eso. El guard la respeta en los dos sentidos: adjudica cuando lee muerto y, cuando lee vivo, imprime «oscillating — read ALIVE this run; the entry stays» en vez de STALE. Marcadas las dos carreras ya medidas: - emoji-picker.open-trigger-fg (17/21 vs 16/21 en el mismo código; vivo cuatro veces, una de ellas replicando el staticPass paso a paso). Tres corridas: vivo, vivo, muerto — exit 0 las tres, ninguna falsa alarma. - editable.submit-fg (vivo 3 de 4, 42/56 vs 41/56). Salir del modo edición es lo que hace un blur y el guard abre por foco + prepareWith, así que la superficie que mide no es determinista. Cuatro corridas: exit 0 las cuatro. Sale del plan de la revisión del 24 (P6). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
764a28088f |
docs(theming): dos fichas se quedaron con la cifra VIEJA en la cabecera, y el agregado al día
Supervisando la tanda: `select` y `calendar` commitearon su veredicto §5 con las cifras correctas (83 -> 92 y 84 -> 89) pero la CABECERA de la ficha seguía diciendo el número de antes. Un lector ve la cabecera primero. El árbol de trabajo tenía la regeneración del script de auditoría, con las cifras buenas — y BORRANDO la prosa medida de las fichas: las razones de cada literal y de cada retirada colapsadas a «Ninguno.». Ni una versión ni otra estaban bien, así que van cosidas: el cuerpo de HEAD (la prosa) con las líneas de cabecera regeneradas (las cifras). Cinco líneas en total, ningún párrafo perdido. Y el agregado `docs/audit/theming/README.md`, que es dato generado sin prosa, entra tal cual: alcance global 67 % -> 68 %, componentes al 100 % 28 -> 36. Lo demás que quedaba sucio en el árbol era ruido de fin de línea (PLAN §8, next-features) y se restauró desde HEAD. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
c05349c3ff |
docs(theming): el handoff recoge la tanda de DOCE y lo que encontró supervisarla
Doce componentes cerrados por cinco sesiones en paralelo — cinco al 100 % (chat-log, chat-composer, rating-group, toggle) y card cerrado en su 78 %, que ES su techo. Global 66 % -> 68 %. Y la parte que importa: los doce se supervisaron uno a uno, y la supervisión encontró cinco cosas que la ejecución no vio. Cuatro salieron del §7.7. Las dos primeras son de la rama, no del eje: el índice de git es COMPARTIDO —verificar el árbol indexado no basta, porque otra sesión puede reescribirlo entre que lo miras y confirmas— y un árbol de trabajo rancio hace mentir al instrumento sin tocar un solo commit (el guard de card daba 0/98 por un fichero sucio; desde HEAD limpio, 49/98 verde). Las otras tres son del eje: la cascada de paleta se lleva también el tono por defecto, el canal inline filtrado al contrato son cuatro claves y no dos, y la sonda y el guard mueren con --import tsx/esm. Queda escrito además el gate del diff cero con su matiz: dos componentes no cerraron a cero y los dos lo declararon; los dos son ruido reproducido sobre código idéntico. Un diff no cero no es automáticamente una regresión, pero sólo se declara ruido reproduciéndolo. Y dicho sin esconderlo: la demo de chat-log se tocó como instrumento. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
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 |
|
|
88a2086441 |
fix(theming): HEAD lleva cuatro commits con el ledger del centinela ROTO por una coma
`scripts/theming-sentinel-exceptions.ts` tiene `},,` en la costura entre el bloque de `rating-group` y el de `toggle`: un literal de objeto con una coma de más, o sea que el fichero NO PARSEA. Lo introdujo |
2 months ago |
|
|
b139b4280b |
docs(theming): el §8 salió con la entrada de rating-group y radio-group DUPLICADA
Mismo error que la sesión anterior, en otro fichero y por la misma causa: para construir el índice desde HEAD recorté MI entrada del árbol de trabajo entre dos marcas —«desde la mía hasta la de chat-composer»— y entre medias otra sesión había insertado las suyas. El recorte se las llevó, y HEAD acabó con `rating-group` y `radio-group` dos veces (507/517 y 560/570). Se borran las DOS copias inyectadas; las originales, con su sitio en el orden, se quedan. Ningún otro cambio. **La lección, para la próxima**: en una rama con sesiones concurrentes, recortar del árbol de trabajo «desde X hasta Y» sólo es seguro si NADA puede aparecer entre X e Y. Cuando lo que separa a X de Y es un fichero compartido, el recorte tiene que terminar en el FIN de lo mío, no en el principio de lo siguiente — que es exactamente lo que ya había fallado con el override del guard una hora antes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
f3189a05ac |
uix(card): temable — 78 % → 78 %, y el número CERRADO es el resultado
Card es un primitivo con paleta, y su columna `private` no es deuda: es el puente THM-2. Clasificados uno a uno sus ocho knobs fuera de alcance ANTES de tocar una línea —que es la mitad del trabajo—: - cuatro leen `--_card-palette-*` DIRECTO: el velo de hover de `ghost` y `outline`, la descripción en `solid` y el filete del pie en `solid`; - los otros cuatro leen el conmutador por VARIANTE (`--_card-bg`, 4 fuentes; `--_card-fg`, 2) en la raíz, el título y el cuerpo, y sus ramas son ese mismo puente. Un público encima de cualquiera dejaría que un tema lo fijara y matara en silencio el `color=` de cada instancia (CONTINUE-theming §3.pre). El techo de card **no es el 100 %**, y forzar la cifra habría sido romper la jaula del color. Lo único que faltaba era **la costura**: la rama `outline` del conmutador leía `var(--color-surface-default)` a pelo — el valor es del sistema, el knob es de la card. Entra **`outline-bg`** con ese valor verbatim, y el centinela lo confirma vivo. Ni `ghost` ni el borde transparente se acuñan: son identidad. Censo: 37 knobs · 28 públicos · **78 %** (idéntico, y así queda escrito en la ficha). Contrato 97 → **98** claves. Global del catálogo sin bajar (68 %). Diff de computed: **VACÍO**. 1.216 valores en 7 estados (sonda estándar, 6 nodos = la card y sus cinco ranuras) más 2.484 valores en 18 celdas de variante / tono / rounded / selected / disabled / lift, con `transition` y `animation` congeladas — porque el escenario monta UNA card `soft` y la sonda no barre variantes. Capturas 2× antes y después, miradas. Centinela R-5.4: **49/98, 49 adjudicadas**, verde. 40 por PATRÓN (la cascada de paleta, medida aquí: con `data-color=primary` `--card-primary-track` no mueve nada, `--palette-track` sobre el mismo nodo repinta, y sin `data-color` `--card-neutral-track` vuelve a pintar) y 9 forzadas sobre el nodo real. Dos merecen leerse: - **el trío `emerge-*` no pinta en la demo, y no es culpa de la demo**: el montaje CEDE al sistema de motion (`:not([data-animation-style])`) y el escenario arranca con el preset `select-pop`. Quitado el atributo, los tres alcanzan — y `emerge-distance` tiene ADEMÁS una segunda causa: alimenta `--motion-distance-md` y la animación acaba en `translate 0` con `fill-mode: both`, así que `transform` en reposo no puede enseñarlo nunca (se mide leyendo el hook, 8px → 1234px); - **`hover-lift` y `press-scale` mueven `transform`, que el guard no fotografía** — mismo hueco que `rating-group.item-hover-offset` (§13). Hallazgo de composición, MEDIDO y no forzado: dentro de un `CardGroup` el eje `radius` de la card está muerto — `[data-card-group] [data-card]` es (0,2,0) contra la (0,1,0) de la receta, así que manda `--card-group-card-radius` (`--card-radius-md: 1234px` no mueve nada; el del grupo mueve las dos cards). Es la anidación concéntrica de §30, deliberada y documentada en `card-group.css`; se registra porque significa que el token de la card no tiene efecto en ese contexto. Guards: censo `--only card` 78 % · `component-audit --only card` PASS · `eidos-lint card` 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, fuera del eje: la raíz declara `background:` en ATAJO, lo que fija `background-image: none` y cancela el velo del sistema — card es uno de los 45 componentes de la incidencia §12 de next-features. Arreglarlo mueve píxel. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
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 |
|
|
007c2af52c |
uix(toggle): el ledger y el guard del commit anterior, que un índice COMPARTIDO se llevó
Reparación, no trabajo nuevo. `edc019515` salió con la mitad del componente: la receta, el CSS, el README, la demo y la ficha entraron; el ledger R-5.4, el guard y la entrada del §8 se quedaron fuera, y en su lugar viajaron fragmentos de OTRA sesión (rating-group). Causa medida: en esta rama el ÍNDICE de git es un recurso compartido — entre el `git add` verificado y el `git commit` otra sesión hizo su propio `reset` + `add`, y el commit fotografió su índice, no el mío. Verificar el árbol indexado no basta si alguien puede reescribirlo DESPUÉS de mirarlo; la verificación y el commit tienen que ir en la misma invocación. Sin esto `npm run theming:sentinel -- toggle` falla: el contrato tiene 126 claves y el ledger no tenía ninguna. Lo que entra: - **Ledger** (`theming-sentinel-exceptions.ts`): las 8 adjudicaciones medidas de toggle (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) y la excepción POR PATRÓN de sus 48 claves de tono — la cascada de paleta, 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. - **Guard** (`theming-sentinel.ts`): el barrido de VARIOS ejes como producto cartesiano (un solo eje da la misma secuencia de siempre), el valor `null` que QUITA el atributo, el mismo barrido en el pase de HOVER, y el override de toggle. 36/126 → 70/126 sin adjudicar nada. Los 12 componentes con `sweepAttr` re-verificados uno a uno: cero regresiones, cero STALE. - **`PLAN-theming.md` §8**: la entrada de toggle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
f6a618328a |
uix(rating-group): temable — 80 % → 100 %, y su ÚNICO hover mueve lo que el guard no fotografía
Cuatro claves acuñadas, tres privados jubilados, dos literales firmados y seis
adjudicaciones medidas. El default no se mueve: diff de computed 0 sobre 5.624
valores en 27 estados y capturas 2x idénticas.
Censo: 80 % → 100 % (público 12 → 13, global 1 → 0, literal 2 → 0 —los dos pasan
a `exception`, fuera del ratio—, privado 0, sistema 1). Contrato 25 → 29 claves.
Global no baja (68 %).
QUÉ ENTRA (4 claves)
gap · item-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 tres privados `--_rating-group-*` y los cuatro bloques
`[data-size]` que los conmutaban: eran «privado con fuentes por TALLA», o sea
una ESCALA, y una escala sube al contrato. Un tema alcanza ahora la coordenada
resuelta además de los cinco pasos que ya alcanzaba.
invalid-item-fg — la costura: el tinte de validación leía
`--color-threat-element` a pelo, igual que en sus hermanos de formulario
(checkbox, radio-group, pin-input). El valor es del sistema; el knob es del
componente.
DOS LITERALES FIRMADOS (fuera del ratio)
`inline-size: 100%` / `block-size: 100%` sobre el glifo son IDENTIDAD: el SVG
llena la caja del ítem, y la caja ES el eje de talla. Llevan su anotación
`/* literal: … */` con la razón en la misma línea, más un
`/* prettier-ignore */` sobre la regla para que el formateo no separe la
anotación de su valor (la regresión que costó un día en natural-time-picker).
Nota honesta: la demo pinta las estrellas con TEXTO (★/☆), así que esa regla
no tiene nodo en esta ruta — su razón es estructural, no medida en pantalla.
CENTINELA 23/29, 6 adjudicadas, ninguna es deuda
partial-item-fg necesita `allowHalf` y medio valor · invalid-item-fg necesita
[data-invalid], y encenderlo en la demo taparía item-fg, active-item-fg y
partial-item-fg durante toda la corrida (su regla es (0,3,0)) · focus-radius
necesita :focus-visible, que el guard quita a propósito · el par de transición
ES la transición que el guard congela.
Y la sexta es un HUECO DE INSTRUMENTO nuevo: **item-hover-offset mueve un
`transform`**, propiedad que el guard no fotografía. Es el único knob de esta
receta que mueve uno, así que leía muerto estando vivo — medido a mano sobre
el ítem realmente hovereado: matrix(1, 0, 0, 1, 0, -1) → matrix(1, 0, 0, 1, 0,
-40). Añadir `transform` a la lista obliga a re-verificar los componentes con
ledger, así que queda anotado en next-features §13.
El guard gana además un `prepareWith` con el interruptor `disabled` de la
demo: `disabled-opacity` era el único knob tras un estado, esta demo no tiene
switch por URL, y encenderlo no tapa nada (el único hover de la receta ya
estaba fuera del alcance del instrumento).
CARRERA DE ÍNDICE — dónde está el resto de este trabajo
El commit `edc019515` (`toggle`, otra sesión) se llevó cuatro fragmentos míos
que estaban en el índice compartido cuando confirmó: el `prepareWith` de
rating-group en `theming-sentinel.ts`, su bloque de seis adjudicaciones en
`theming-sentinel-exceptions.ts`, su entrada del §8 del PLAN y su viñeta de
next-features §13. El contenido es correcto y ya vive en HEAD; se anota aquí
para que la trazabilidad no se pierda. Lección: en esta rama el índice es
compartido, así que entre construirlo y confirmar no puede mediar NADA.
GUARDS
censo --only rating-group 100 % · global 68 % (no baja) · component-audit PASS
· eidos-lint 0 invalid (12 morfo-backed, 0 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 (29
claves, verificada en navegador).
Índice construido a mano desde HEAD sobre los dos ficheros compartidos que
quedaban (recipes/base.ts, generated/base.css). 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 |