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 }
13 Commits (6d4aa05fbd82e309d211515362c2dfd788aed271)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
035a748450 |
feat(sema)!: la señal precede al commit — emit() devuelve {id, settled} síncrono, el hold no bloquea a nadie, y el motor enacta la reducción 'state' (D-full + sema §3.9)
D-full. `EngineSemantic.emit(signal)` deja de ser `Promise<string>` que resolvía
tras el hold y pasa a devolver SÍNCRONAMENTE `EmitHandle { id, settled }`: el id
se acuña sin await, la proyección sigue siendo síncrona en `replace`, y `settled`
cubre cola + proyección + despacho + hold + expresión + limpieza (la limpieza
ocurre ANTES de resolver). El runtime de soma, en `pre`/`coincident`, proyecta y
despacha ANTES del handler en el mismo tick (ya no espera el hold); en `post`,
handler → tick() → emit. `TriggerResult.settled` siempre presente. La a11y del
runtime (announce / foco) corre tras el despacho, no tras el hold. El modelo es
el de la plataforma (`element.animate()` → `Animation.finished`): el estado
cambia en el instante de la acción y la expresión corre en su propio reloj sobre
un nodo que retiene Presence. `pre`/`post`/`coincident` describen el ORDEN entre
proyección y mutación, nunca una espera; `coincident` pasa a ser literalmente lo
que declara.
Medido en Chrome real (servidor propio, misma sonda antes/después; Escape →
`data-state=closed`): dialog 258.6 → 9.1 ms · drawer 286.6 → 9.1 ·
popover 1757.8 → 8.5 · float-panel 1807.8 → 49.7 (n=1, pane oculto). Toggle con
`regime: 'queue'` conserva su forma (contact 20 · estado 28 · commit encolado 156). En los
cuatro el sello `emerge-close` se proyecta ANTES del cambio de estado y
`data-ending-style` aparece (Presence). El «hasta 1,5 s» del informe de auditoría
era real: el tope de `awaitExpression` se pagaba ante cualquier animación viva en
el target (popover, float-panel).
Condición 1 (censo, fase 0): 260 eventos; 39 `pre` + 21 `coincident` (0 sin
`sequence`). Solo 14 tienen handler registrado (los únicos donde D-full adelanta
la mutación; cifra del adversarial, el constructor contó 12); los otros 46 ya mutaban el estado en el mismo tick que un `void
trigger` (sidebar.css:363-375 y tooltip-provider:272 lo tenían escrito con
medición). Los 6 que desmontan (4 overlays + toast + tooltip) tienen Presence.
CERO migraciones necesarias. La regla transversal `[data-event^='emerge-close']
{ animation: dismiss-fade }` (base.css) existe en LETRA sobre los cuatro overlays,
pero el preset de Presence gana la cascada en todo instante (medido con
getComputedStyle): el refutador tenía razón en EFECTO.
Condición 2 (carrera nueva del id síncrono): `clear(id)` / `clearTarget` honran
ocurrencias EN VUELO (`inFlight` + `pendingClears`): la ocurrencia no se registra
como persistente al terminar y limpia como transitoria; `clear` devuelve true.
Reproducida en test (hold corriendo ⇒ tras `settled`, sin proyección residual y
`active` vacío). `dispose()` vacía ambas.
SO4 re-firmado: un target ausente NUNCA salta el handler ni lanza en ninguna
secuencia — se omite prewrite+emit, se reporta por logger con
`SomaRuntimeTargetError` como payload, y el handler corre («sema es ornamental;
una acción del usuario nunca se pierde por un adorno»).
sema §3.9. La política perceptual `'state'` bajo reduce pasa al MOTOR:
`ReducedMotionFallback` vive en sema (morfo lo importa), la señal lleva
`a11y.reducedMotionFallback` (cualquier valor declarado) y el motor, con
`motion.get() === 'reduce'` y `'state'`, devuelve el mismo retorno silenciado que
`channels: []` (antes de `queue`). Soma deja de forzar `channels: []`
(`a11yChannelsOverride` muere) y conserva `'text'`/`'focus'` con `sources.motion`.
S5 se conserva como doctrina (la preferencia gana al morfo y a la llamada); cambia
el enactor. Cierra el emit DIRECTO sin a11y (~76 en el docs site). Dato: hoy
ningún morfo declara `'state'` (9 declaran `'text'`); el valor es contrato y
simetría con la háptica, no un síntoma vivo.
Prosa re-firmada (CANON intacto, silente a propósito): engine.ts docblock ·
sema.md (emit contract, promise semantics, lifecycle, One door, overlays, error
policy, reductions, migration) · morfo.md · active-architecture.md (walkthrough)
· overview.md · soma-architecture.md · chans/types.ts req. 3 · sema/README ·
book-deviations D.9/D.10/D.12 · morfo/types.ts (MorfoEventSequence,
MorfoA11ySemantic) · comentarios del `sequence: 'post'` en dialog/drawer/popover/
float-panel (valor intacto).
Verificación (tras la ronda 2): sema 337/337 · runtime 63/63 · alcance del lote
201 ficheros / 2136 tests · suite entera 5366/5366 (458 ficheros, exit 0) · check 89 errores,
0 en src/, ledger intacto (los ~76 emit de web/routes son fire-and-forget y
compilan con el handle) · gate VERDE tras la ronda 1 (5359/5359; un flake de
gesture.test rotate-detent bajo carga, verde en solitario y dentro del gate) ·
+20 tests (engine 40→53, runtime 56→63) · 3 mutaciones enrojecen y revertidas
byte-idénticas (⚠ diferir la limpieza UN microtask es un no-op observable: la
mutación honesta cruza a macrotask) · adversarial Opus independiente (métodos
propios, árbol byte-idéntico al terminar): doctrina SANA; 8 defectos, cerrados
antes de anclar los 6 que eran del lote — D-1 código (el catch de `settled`
vivía en la rama onFulfilled del trigger: un handler que lanzaba en `pre` dejaba
la rechazada del canal visual sin manejar; ahora se engancha donde nace el
handle, con test de las tres vías) · D-2/D-3 prosa · D-4/D-5 tests (los cuatro
valores del fallback, y el par S5 vuelve a discriminar) · D-8 exactitud
(`clear`/`clearTarget` no honran ni cuentan transitorias en vuelo). Segunda
sonda de Chrome del adversarial: 11.6 · 11.0 · 5.1 · 42.7 ms. D-6 (alcance):
`contracts.test.ts` restaurado a HEAD (su diff era 100 % formateo); el
reformateo prettier de los docs tocados se queda. D-7 PREEXISTENTE, fila
nombrada: `dispose()` durante una ocurrencia en vuelo repuebla `active`
después y deja proyección residual (engine.ts, `finally` + `dispose`).
Pendiente del autor: mirar el cierre de Dialog y Toast en un Chrome que PINTE
(los panes de los agentes estaban ocultos: mutaciones y estilo computado
medidos, frame no visto).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
3 weeks ago |
|
|
f1f686d097 |
feat(theming)!: SS16 - el guard vive donde NACE el valor, y el velo del drawer vuelve a pintar
Firma SS16, quinta aplicacion de la doctrina "la capa sostiene la pluma, no es
la dueña". El censo, el ledger y la ley del espacio cerrado auditaban SOLO
quien LEE (recetas de eidos); quien ESCRIBE la custom property por instancia
vive en soma/arts y ningun instrumento del eje lo habia enumerado jamas.
EL BUG VIVO QUE ESTO DESTAPO — y no se parcheo, se diagnostico
--drawer-overlay-opacity era DOS especies bajo un nombre: el knob de tema (el
contrato dice 62%) y el canal del arrastre (0..1). soma escribia el canal SIN
UNIDAD sobre el nombre del knob; color-mix() exige porcentaje, la funcion caia
invalida y el velo computaba rgba(0,0,0,0): NO PINTABA. Y el inline dejaba el
knob inalcanzable para cualquier tema. Se separan: el publico se queda como
knob (nadie lo escribe en runtime), el arrastre pasa a
--_drawer-overlay-progress (sin unidad, que para un multiplicador es lo
correcto) y la receta los COMPONE - calc(knob * progress) -, asi que el
arrastre ATENUA el tema en vez de destruirlo.
Medido en Chrome: reposo 0.408471 (antes rgba 0,0,0,0) - el tema LLEGA (20%
-> 0.1318, 62% -> 0.4085, 100% -> 0.6588; antes ninguno movia nada) - el
arrastre sigue (Escape real -> alpha 0; 0/0.25/0.5/1 lineal) - control
negativo: reinyectando la escritura vieja el velo vuelve a caer, o sea que la
unidad era el SINTOMA y las dos especies la enfermedad.
⚠ Estaba adjudicado EN PROSA en theming-sentinel-exceptions.ts:815 desde hacia
dias: la excepcion se trago el bug.
LOS 18 NOMBRES A SU SITIO
Clase B (11 en command/dialog/scroll-area/toast + 4 del drawer): forma publica
sin contrato y sin UN SOLO lector en el repo - una API publicada que el
framework no consume. A --_{c}-*, y los README de soma dejan de enseñarlos
como API del consumidor: ahora enseñan LA PARTE, con la formulacion verbatim
que SS15 ya habia verificado. Clase D (tree-view, gradient-picker): tenian
lector, verificados en navegador. --scrollbar-width NO se renombro por
inercia: es una escritura sobre el unico <body>, la doctrina no le llega, y
queda REGISTRADA con su razon en vez de inventarle un dueño.
LA AGUJA - src/uix/value-channels.test.ts (fichero propio, 6 tests)
Vitest y no script, porque el gate termina en la suite y eso es lo que
convierte la doctrina en ley. Deriva el vocabulario de sistema RESTANDO el
contrato a lo que emite el generador (lista derivada, nunca a mano). Barre
NUEVE raices - las siete nuevas verificadas a cero ANTES de asertarlas - y el
quinto test asserta que cada raiz declarada se anduvo de verdad: una raiz que
resuelve a cero ficheros es la puerta que nadie habria visto.
Dos correcciones al dimensionado, por medida: el arbol tiene SEIS formas de
escribir, no cuatro, y una de las que faltaban era LA CANONICA (la
--_${component}-... que SS14 y SS15 firmaron) - un guard ciego a ella habria
dado verde sobre su propio destino. Y un barrido mas ancho marcaba en rojo un
anchor-name, que en gramatica es identico a un nombre de propiedad: probado y
REVERTIDO. El instrumento miente primero.
Mutaciones: cinco, con el arbol byte a byte identico. Incluyen las dos que
prueban lo que las correcciones añaden (una clave _ DEL contrato pasa de verde
a rojo; un --_ legitimo en blocks pasa de rojo a verde).
LO QUE EL ADVERSARIAL CORRIGIO DE MI PROPIA LEY
Dictamen: "es LEY sobre la mitad que barre, y sigue siendo PROSA sobre el
absoluto que enuncia". Cierto: decia "toda escritura por instancia" y la aguja
no mira eidos, donde viven ONCE escrituras de nombres contratados. Corregido -
el enunciado nombra sus nueve raices y DECLARA sus dos fronteras (eidos, con
su expediente abierto; web/routes, congelado); las salidas son CUATRO y no
tres (la cuarta, sistema, es verde); y el registro se queda con cuatro campos
por entrada (since, reason, destination, heldBecause) con un test que exige
los cuatro - la diferencia entre un registro y un cajon.
Y la relectura con ojo de abogado encontro DOS absolutos mas, en direccion
contraria, escritos bajo "WHAT THE GUARD DOES NOT CHECK": "por instancia" no
es decidible estaticamente (el antecedente del guard es MAS ANCHO que el de la
doctrina), y el {c} de --_{c}-* no lo comprueba nadie, solo el guion bajo.
SS18 ABIERTO, y es la respuesta medida a "¿puede volver a nacer un nombre sin
dueño sin que nadie se entere?": SI, desde eidos. 11 contratadas + 18 sin
dueño, partidas en dos especies (la fundacion generando su vocabulario, que es
legitima, y las props ergonomicas del consumidor, que no es lo mismo).
dialog-overlay-opacity es el GEMELO EXACTO del velo del drawer y sigue vivo.
No es "añadir el root": distinguir las dos especies EXIGE FIRMA.
Guards: value-channels 6/6 - recipe-css-contract + reach-floor + generated-css
55/55 - docs:check 0/0 sobre 819 - --debt 1148/0/0 - tsc 0 propios - prettier
limpio.
BREAKING: los 18 nombres publicos ya no existen; el canal se lee --_{c}-* y
sigue sin ser de nadie para fijarlo. Y consumir un --{c}-* del contrato desde
un provider es ROJO desde hoy.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
1 month ago |
|
|
3eb819e7d5 |
docs(uix): tanda 2 del contraste con el corpus — el modelo de los capitulos alcanza a la tuberia unica
La lectura completa del corpus (6 lectores Opus, 6/6 censos, ~4,5M tokens) destapo lo que la tanda 1 no vio, y esta tanda lo cierra: - El modelo «Effects sync attrs» — repetido VERBATIM en cuatro capitulos (morfo, soma-architecture, overview, active-architecture), en sus tablas de piezas, en los cuatro pasos de trigger y en las dos frases-resumen — muere: la pieza es la bolsa de render; ADom aplica solo el prewrite. - morfo.md: partProps re-descrito (bolsa completa), la cadena causal de commits, y las filas de la tabla de ejecutores (data/aria/role → bolsa). - coincident: los DOS docstrings que ensenaban «in-flight» (types.ts y morfo.md) se alinean con la equivalencia FIRMADA de sema.md §slider («emit-then-handler, like pre; declared indivisible») — el hallazgo del informe queda refutado como defecto de runtime y reducido a esto. - glossary: el kind fantasma `internal` (la clase exacta que docs-check:422 mata y su regex no ve en tablas markdown) → `public|private|virtual` real. - El gate entra en la doctrina: check:gate/gate en el loop de verificacion (testing-and-tooling y getting-started), eidos:lint como script npm en su fila, y la tabla de Commands de morfo.md. - Mi propia sobreafirmacion de ayer, calificada: el test SSR es un CANARIO de dos representantes sobre mecanismo compartido, no un censo — el censo por provider queda encolado (P1). morfo:check en getting-started declara su alcance real (data-*; role/aria sin validador DOM). - Supervivientes de C2c: el assert-vacio de cropper (la clase «guard sobre VACIO pasa») retirado con acta; sticky/README deja de citar syncAttrs. - gradient-builder/README: fila data-kind del Track + acotacion mesh v1. - Handoff: DOS fe de erratas — «nunca los vio nadie» era falso (vistos y reducidos 12→3 en cb554ae2e; lo que faltaba era la puerta) y la ley del escritor imperativo gana su excepcion abierta (textarea autosize, con su cierre correcto encolado). Verificacion: docs:check 0/817 · cropper 19/19 · morfo schema+compile 133/133. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
1 month ago |
|
|
c494fb3952 |
refactor(soma)!: §15 — la geometría del posicionador es canal del ANFITRIÓN
Firma A del autor (§14 literal, cuarta aplicación de «la capa es la pluma,
no la dueña»): FloatingContentOpts gana `component` (kebab del morfo, nunca
literal — 11 hilos de creación en 9 anfitriones) y las medidas por instancia
del posicionador aterrizan como `--_{host}-floating-{transform-origin,
available-width,available-height,anchor-width,anchor-height}`. El sexto
nombre que el expediente no contaba (`--floating-native-offset`, rama
nativa) queda canal INTERNO de capa (`--_floating-native-offset`: lo escribe
la capa en su propio wrapper, lo leen solo sus reglas foundation). El lector
COMPARTIDO (preset scale-fade de motion) lee el alias neutro
`--_floating-transform-origin` que cada receta anfitriona declara desde su
canal — cableado sliding-indicator, 9 declaraciones. getFloatingContentCSSVars
(export muerto, next-features §13.ii) MUERE con la firma.
Matiz que la ejecución destapó: el content de MENUBAR compone DropdownMenu —
su canal es --_dropdown-menu-floating-* y el alias de menubar se acota al
PANEL (el canal sigue al componente que POSEE la composición flotante);
split-button y palabras leen el canal ajeno de su composición en el punto de
composición, anotado en cada sitio.
Verificado: suites 96+60+78 en verde - eidos-lint x10 con 0 invalid -
reach-floor 5/5 (ledger 0 NEW / 0 STALE) - component:audit 162 PASS / 4
NEEDS-WORK idéntico - check 0 atribuibles POR FICHERO - dinámica CDP 9/9
anfitriones: canal vivo con px por instancia, los nombres VIEJOS computan
VACÍO en todos, positivo exacto (tooltip max-block-size 525.033px == canal
525.0326px; combobox ídem; panel de menubar anchor-width 886px = la barra;
sidebar popout ENGANCHADO 720px/35px), negativo fijando los viejos en :root
= nada se mueve. Trampa reconfirmada: el popout SIN ANCLAR da undefinedpx —
comprobar que la superficie estaba abierta.
Viaja con atribución declarada (acuerdo por canal con la sesión P0
vicen-42, precedente
|
1 month ago |
|
|
25e59e18f9 |
feat(morfo,soma): el attr de nombrado es un DEFAULT del contrato, no una imposicion
A-85 estaba confirmado desde el ledger de blocks: la demo de site-header
escribia `aria-label` en el trigger del cajon y el canon lo pisaba. El censo
dio la magnitud real — 132 declaraciones en 59 morfos — y la disposicion
escrita (replicar el `prop-truthy` de button en las 132) resulto ser la
direccion inversa a la buena: obligaba a 264 entradas de boilerplate y hacia
que el texto del consumidor diese una vuelta entera por el grafo reactivo para
aterrizar donde ya estaba.
Las 132 declaraciones eran CORRECTAS. El defecto era la precedencia. Asi que
el contrato gana dos clases, por VOCABULARIO y no por declaracion:
contract (role, data-*, aria-expanded, aria-controls, roledescription...)
el runtime SIEMPRE gana; un consumidor que los pisara haria mentir
al componente, y esa garantia es algo que las librerias
user-props-last no tienen.
naming (`ARIA_NAMING_ATTRS`, hoy `aria-label`) el morfo da un DEFAULT y
el attr explicito del consumidor gana — espejo de la propia cadena
de nombre accesible de la plataforma.
Tres puntos, uno por capa, y ninguno de los 132 morfos tocado: `compileMorfo`
clasifica el plan (`consumerWins`) y deja de hoistear esos literales a
staticAttrs; el runtime los saca del efecto `syncAttrs` —el `dom.apply`
post-render ERA el pisado— y los embarca en el bag de la parte, el mismo
vehiculo que `dir`; y `mergeProps` los resuelve consumer-first (`a ?? b`, para
que un `aria-label=""` explicito sobreviva).
Efecto medido que no se buscaba: los labels salen ahora en el HTML de SSR. Antes
los escribia un efecto, que en servidor no corre — el propio ledger lo tenia
medido y nadie habia atado los dos cabos.
`aria-labelledby` se queda en contract A PROPOSITO: es cableado `partRef`, y la
plataforma ya hace que un labelledby del consumidor gane a cualquier label sin
que tengamos que arbitrarlo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
6f42eebfe8 |
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve
El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho
componentes y `emerge-open` en tres. No era estetica — un preset de movimiento
engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna
firma y simplemente no animaba, sin romper una sola prueba.
Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos,
256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran
40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y
`handle-drop` ya existian en 10 y 4 componentes.
`validateMorfo` cierra la puerta: un `events[].name` que no empiece por su
familia ahora lanza. Visto fallar antes con un nombre pelado inyectado.
Lo que el renombrado destapo, y va aqui tambien:
- La receta del splitter enganchaba `commit-resize`, muerto desde
`bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como
slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el
catalogo de morfos — el guard que lo habria cazado en su dia.
- La familia `shift` era muda en el canal visual, contra su propia doctrina
(c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya
describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora
tiene firma direccional: sexto atributo del sello (`data-event-direction`,
`forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por
`:dir()`. Medido: LTR -30px/+30px, RTL los invierte.
- El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro
calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues
—media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze`
moria sin pintar un fotograma. Una superficie, una ranura (A-36).
- 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de
decision, el componente vivo). Las docs desfasadas, corregidas; los nueve
DEFECTOS de codigo obsoleto quedan abiertos y sin tocar.
- `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y
habia tres cosas distintas deletreadas «direction».
check en su linea base con 0 errores nuevos por diferencia de conjuntos ·
docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador
medidas con raton real y rAF vivo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
56a96114f8 |
feat(morfo,soma): la emisión deja de aceptar un elemento anónimo
El defecto que tres auditorías encontraron y ninguna cerró no era que N eventos redirigieran sin declararlo: era que la API de emisión aceptaba un HTMLElement suelto, compensando que el registro de partes perdía la identidad de instancia. Censar y arreglar a mano reproduce el modo de fallo. Esto lo hace inexpresable. F1 — SomaRuntime<M> genérico, SIN default. Nombres de evento, kebabs de parte y claves de events/actions tipados contra la declaración (EventNameOf / PartKebabOf / ActionNameOf, los extractores que semaSelector ya usaba del otro lado). 104 anotaciones migradas + 3 wrappers que devolvían tipado pero tomaban sources ANCHO. SomaRuntime<Morfo> queda sólo en la tabla de contratos. F2 — registro por instancia: Map<part, PartRegistration[]>, pertenencia mantenida por el stream del attachment (poda al desmontar, re-entrada al remontar), resolución liveReg = la instancia VIVA más nueva. Mata de paso la clase "la más nueva muerta ensombrece a una viva". F3 — tres formas legales de destino: el target declarado; el anclaje por instancia (SomaRuntimePart.trigger, tipado por EventNameTargeting, + runtime.partInstance por identidad de referencia); y targetFallback, la cadena por estado de montaje declarada en el morfo y resuelta por resolveEmitTarget — LA resolución única para validación, emit y foco a11y, que ya no pueden discrepar. ~30 componentes migrados; censo de targetOverride 148 -> 89. F4 — A-36 tenía un superviviente. Medido en dropdown-menu: bajo `pre` el `open` no colisionaba con el contact-activate del Button compuesto, se PERDÍA entero porque su content no había montado. Aplicada la receta de float-panel a dropdown-menu Y context-menu. Ahora: contact-activate en trigger, open en content — dos superficies, ambas expresando. Submenús mudos, tres componentes. No era cableado: el morfo no declaraba el evento. onion-menu recibe emerge-expand/emerge-collapse (la forma de TreeView: un nivel revela sus hijos en el sitio); dropdown-menu y context-menu reciben sub-open/sub-close sobre sub-content, distintos del open raíz a propósito porque el sub es su propia superficie flotante. Nacen con la receta A-36 para no repetirla en código nuevo. chronos — declaraba 26 partes y registraba UNA; 17 role= a mano y el ARIA declarado no llegaba nunca al DOM. Se anula la mitad sobre-extendida de la decisión de 29ffe902a: la reutilización sigue viajando por el motor puro, pero la ESTRUCTURA se compone como en Table y Calendar. C1 (las 6 partes que emiten, chronos con cero targetOverride) + C2 (8 singletons) + C3 8/9. Registrar una parte DESTAPA declaraciones falsas, tres veces en un pase: el chip declaraba defaultElement button y ponía type= sobre un div (anida el asa de resize); grid-row declaraba archetype item y pintó la semana entera como fila de lista; y un aria por propRef desaparece en SILENCIO si el provider no publica la fuente. En los tres el arreglo fue la DECLARACIÓN, no el DOM. Verificado: check 74 = línea base medida con stash, DELTA CERO sostenido en cada lote · 458 pasan (chronos+morfo+sema) · navegador limpio en las tres vistas de chronos, con el contrato ARIA vivo por primera vez (aria-labelledby resolviendo a «junio de 2026», aria-readonly/disabled que no se habían emitido nunca). Handoff en docs/process/CONTINUE-perceptual-surface.md. Aparte, y decidido por el autor: docs/process/PLAN-event-name-normalization.md — prefijo de familia siempre; 36 de 252 sin prefijo, cero ambiguos. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
2 months ago |
|
|
b80ccb33cb |
docs(direction): el contrato pasa a ser canon, y el corpus deja de contradecirlo
El eje estaba cerrado en CODIGO y no en DOCUMENTACION. El contrato vivia solo en
`CONTINUE-direction.md`, un handoff que `docs/README.md` declara «never a source
of truth». Un capitulo E2 lo fija ahora: `docs/canon/direction-contract.md`.
Va a canon y no a arquitectura por la misma razon que `recipe-contract.md`: es
normativo y tiene guard ejecutable. Cubre la cadena y donde corre cada eslabon;
por que `undefined` no es `'ltr'`; las DOS atributos —`dir` crudo (nativo, lo que
`:dir()` mira) y `data-dir` resuelto (opt-in, para recetas que necesitan un hook
incondicional)—; cuando el estampado es OBLIGATORIO; la doctrina de selector; las
trampas que el guard no ve; que espeja y que no; y la mitad global de prefs.
EL CORPUS SE CONTRADECIA en cuatro sitios, y dos de ellos ENSENABAN mal:
- `component-guide.md:372` daba la cadena como `prefs → 'ltr'`, DOS eslabones,
mandando al wrapper a leer prefs directamente. Eso excluye la prop.
- `soma-architecture.md` §3.4 presentaba el resolutor a pelo (`soma.prefs.getDir()`
dentro del provider) como LA forma de obtener la direccion — justo lo que el eje
retiro del catalogo.
- `html.ts` ensenaba en su JSDoc `dir?: 'ltr' | 'rtl'`, el union a mano que la
regla E-2.5 ahora prohibe. El mecanismo que ensena (extender para estrechar una
clave HTML) es correcto y sobrevive; solo cambia el ejemplo.
- `active-architecture.md:416` no listaba `lang` en la proyeccion, contra
`contracts.ts` y contra su propio test de frontera. Igual `prefs/README.md`.
Y no lo mencionaba en absoluto: el glosario (`activeDir`, `resolvedDir`,
`data-dir`, RTL-1, el escape `rtl-physical:`), `eidos.md` (RTL-1 es el TERCER
guard de deriva y faltaba junto al builder tipado y eidos-lint), `soma.md`,
`building-a-component.md` (§Known traps es exactamente donde va «la prop mueve la
matematica y deja la pintura atras»), y la tabla de atributos de la arquitectura,
que afirma «todo lo que viaja entre capas viaja por atributos» y omitia `dir`.
El checklist gana cuatro reglas y el guard que faltaba (`rtl:check` no estaba en
la matriz de aceptacion pese a que la tabla canon lo nombra), mas un recorte en
E-3.5: «todas las props visuales mapean a `data-{prop}`» leia como mandato de
estampar `data-dir`, que `:dir()` no puede ver.
DIVERGENCIA DECLARADA (§7): la familia `chart` no tiene prop ni provider y
resuelve leyendo `getComputedStyle(node).direction`. Es el unico sitio del
catalogo que hace lo que §1 prohibe. Se registra en vez de esconderse.
Tres verificadores adversariales sobre el barrido; sus hallazgos, corregidos:
RTL-1 estaba anunciado como guard de TODO el capitulo (solo cubre §4) · «nunca
lee al padre» era absoluto y borraba la composicion sancionada en el punto de
llamada · el estampado se afirmaba incondicional en un sitio y condicional en
otro · las cuatro filas nuevas usaban una aplicabilidad que ni la leyenda ni
`component-audit.ts` conocen.
`docs:check` 0 errores sobre 564 docs. `check` 77 = la linea base.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
3097cfcb69 |
revert: deshacer la auditoría entera — se hizo sin leer la doctrina
Revert de los 7 commits de la sesión del 2026-07-29/30: |
2 months ago |
|
|
c39170abbf |
fix(uix): la auditoría del sistema — lo que los guards no veían
Auditoría clean-room de todo ActiveUIX (excluido `web/`), componente a
componente. Lo que sale de aquí no es una lista de bugs: es un patrón.
El framework validaba que lo escrito fuese VÁLIDO, no que lo declarado
se CUMPLIESE — y sus guards fallaban ABIERTOS.
## El colapso de las uniones de props (95 → 0)
Un `Props` de eidos es `{ …props propias… } & <atributos nativos>`.
Cuando el elemento declara un atributo homónimo, la intersección funde
ambos y una unión estrecha contra el `string` nativo COLAPSA a `string`.
Causa: `Without<T, U> = Omit<T, keyof U>` invocado como `Without<T, {}>`
— `Omit<T, never>`, un no-op — 433 veces en soma; sólo 3 con argumento
real. Invisible para `svelte-check`: ensanchar un tipo no es un error,
es una garantía perdida.
Medido: 95 props en 72 componentes. `<Avatar color="nonsense">`
compilaba. `ComboboxInput.size` chocaba con el `<input size>` numérico
y era inusable. Migrado con codemod sobre AST (nunca regex) a
`Own & Omit<Nativos, keyof Own>`: 92 tipos en 73 ficheros + carousel a
mano. `check` no se movió.
Garantía nueva: `eidos/prop-surface.test.ts` (PROP-1) compara los
literales de la anotación del autor contra los de la propiedad pública.
Verificado que falla reintroduciendo el defecto.
## Los cuatro guards que fallaban abiertos
- `translations:check` crasheaba en CADA ejecución de su historia — un
stripper de comentarios borraba `//` dentro de strings. Sustituido por
import dinámico. Al arrancar destapó 8 slots `texts` sin traducción.
- `soma-attr-audit` agotaba el timeout de 5 s: sin veredicto, verde por
omisión.
- `component-audit` D-7.4 hacía `continue` mudo cuando el tipo no
resolvía. Ahora resuelve con el checker de TypeScript
(`scripts/prop-unions.ts`): puntos ciegos de 124 → 3.
- `component-audit` R-1.1: el regex casaba `[data-motion='reduce']` y
daba PASS por el motivo equivocado.
Regla adoptada: un guard que no puede evaluar TIENE que decirlo. El
informe lleva ahora bloque «Not verified» y recuento en el resumen.
## D-1 · tooltip y D-2 · card, cableados
`tooltip` declaraba 3 eventos `emerge` que nadie emitía. Ahora emiten;
`present` pasa a `sequence: 'post'` — con `'pre'` el hold de ~240 ms
gateaba el montaje del propio overlay.
`card` declaraba `commit-select` sin emisor posible (scope sin soma).
Puente headless en `soma/components/card/` con la forma ya establecida
por `menu-dial` / `onion-menu`: eidos posee estado y render, soma posee
sólo el `SomaRuntime` que emite.
## Documentación: 22 mentiras corregidas
`docs/` afirmaba guards inexistentes (`NO_MISSING_PROVIDER_TESTS`),
APIs con firma equivocada y un modelo de Motion que el código no
implementa. Corregido en CANON, arquitectura, glosario, theming/motion,
checklist y los README de `motion` / `callout` / `arts/motion`.
## Además
- CardGroup: la descripción se metía en la primera celda del grid.
- Motion: `data-state` siempre estampado, salida real en `leave()`,
token fantasma `--motion-stagger-each-default` eliminado.
- `engine-motion`: `handoffState` Map → WeakMap (fuga por nodo).
- `mockup`: primitivo crudo → token de rol (R-4.6).
- 5 catálogos de traducción que faltaban.
Handoff: `docs/process/CONTINUE-audit-2026-07-29.md`.
Batería: check 0 errores en src · vitest server 3701/3701 ·
docs:check 0/0 · component:audit 161 PASS / 2 NEEDS-WORK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2 months ago |
|
|
d0f41fb21a |
refactor(libs): own port of runed + tabbable — drop 2 runtime deps (F1+F2)
Removes the two runtime dependencies that broke the "framework depends on nobody" doctrine, porting them into our own code (same move as floating-ui -> $ethereal). F1 (dropped the deps): - tabbable -> src/libs/dom/tabbable-core.ts (getComputedStyle/CSS.escape resolved from the node's own window, iframe-safe); consumed by the existing tabbable.ts wrapper and surfaced via $adom. - runed Context + watch/watch.pre/watchOnce -> $libs/reactive. - runed ElementSize -> $adom/element-size.svelte.ts, rebuilt window-correct on the node's own window (not defaultWindow). - Rewired ~33 watch + 3 Context imports; floating (ElementSize) and focus-scope (tabbable) now consume $adom. F2 (rest of the pure reactive runes -> $libs/reactive): - Previous, IsMounted, onCleanup, interval, debounce/Debounced, throttle/Throttled, StateHistory, FiniteStateMachine, resource. - Dropped runed's React-style use* prefix; reused framework toValue (=extract) + MaybeActiveOrGetter; added Setter<T>. runed + tabbable removed from package.json. `npm run check` = 59 (baseline, 0 in ported files); tests unchanged (pre-existing failures only). F3 (remaining DOM-reactive runes -> $adom on ActiveDom, + PersistedState -> $storage) is pending: see docs/process/continue-runed-tabbable-port.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
3 months ago |
|
|
62a62075f9 |
docs(book): F7.5 (2/2) — COMPONENT_GUIDE moved; guides/ batch COMPLETE
src/uix/soma/COMPONENT_GUIDE.md (1449 L, English body) moved to
docs/guides/component-guide.md. The only Spanish passage — the
archetype-canon banner (2026-06-19) — translated in the move; the rest
is verbatim. Banner's ARCHETYPE_COHERENCE_AUDIT link reaches into src
(audit fossil, stays with the code); the checklist cross-link is now
the sibling ./completion-checklist.md and the 'soma/README s9' mention
now names architecture/soma.md (its post-F7.2 home). Corpus swept:
authoring + README E4 stratum rows (also stale THEMING_GUIDE name),
building-a-component phases 0/2, architecture/{soma-architecture s4/
s13-tree/s17, overview, morfo, active-architecture}.
F7.5 complete: docs/guides/ = component-guide, completion-checklist,
demo-authoring, component-audit. docs:check 0 errors, warns back at
the 11 baseline.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
3 months ago |
|
|
1a710c12ff |
docs(book): F7.2 (7/7) — soma-architecture chapter translated; architecture/ batch COMPLETE
src/uix/soma/SOMA_ARCHITECTURE.md (1058 L, Spanish) translated to English as docs/architecture/soma-architecture.md, same s1-s17 numbering: layer architecture, design principles, the closed six-piece model + SomaRuntime, component model (picker composition), runtime parts, the layers inventory, the Soma class + date/time domain + statics convention, the reactive system, internal helpers, data-* contracts, IDs, barrels, boundaries, directory structure, anti-patterns, current shape, stability rule, checklist. The frozen per-provider test list (dated 2026-05-15, ~140 L) became the timeless fact: the NO_MISSING_PROVIDER_TESTS guard + the test tree ARE the coverage inventory (testing-and-tooling aligned). Stub with the full sN map at the old path; corpus links swept. F7.2 is complete: docs/architecture/ now holds the whole E1 stratum in English (7 chapters, ~5.4k lines), with thin stubs + sN maps next to the code. docs:check 0 errors (251 docs). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
3 months ago |