# Continue
Fecha de corte: 2026-05-17. Rama: `active-uix` .
Actualizacion Eidos component migration 2026-05-17:
- Inicio de la migracion Soma -> Eidos siguiendo `soma/COMPONENT_GUIDE.md`
y `eidos/components/README.md` .
- Componentes migrados:
- `Progress` : root visual `progress.svelte` , `Progress.Indicator` ,
`progress.css` , `types.ts` e `index.ts` con disciplined option C.
- `Meter` : root visual `meter.svelte` , `Meter.Indicator` , `meter.css` ,
`types.ts` e `index.ts` con disciplined option C.
- Decisiones aplicadas:
- Eidos no crea comportamiento: ambos wrappers envuelven `Provider` e
`Indicator` publicos de Soma.
- La unica prop visual anadida es `size?: ResponsiveProp<'sm' | 'md' | 'lg'>` ,
resuelta con `ActiveEidos.resolve(...)` y proyectada como `data-size` .
- `Progress` usa el `data-state` de Soma (`indeterminate`, `loading` ,
`loaded` ) para cargar/terminar/indeterminado.
- `Meter` usa el `data-state` de Soma (`below`, `optimum` , `above` ) para
zonas visuales; no se anade intent ni color en Eidos.
- Los tokens base viven en `THEME_BASE_RECIPE_TOKENS` y se regenero
`src/uix/eidos/generated/base.css` .
- Guardias actualizadas:
- `component-visual-attrs.test.ts` protege `data-size` en `Progress` y
`Meter` .
- `scripts/eidos-lint-all.ts` reconoce `data-floating-wrapper` como marcador
publico actual y retira el sufijo legacy `flat` .
- `components/README.md` refleja `meter` y `progress` como migrados.
- Validado:
- `npx vitest run src/uix/eidos` -> 7 archivos, 84 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> 0 invalid, sin drift
hotspots.
- Segunda tanda del mismo bloque:
- `Slider` : root visual `slider.svelte` , partes `Range` , `Thumb` , `Tick` ,
`slider.css` , `types.ts` e `index.ts` con disciplined option C.
- La receta usa las posiciones inline calculadas por Soma y solo define
track, range, thumb, ticks, foco, disabled y size visual.
- `component-visual-attrs.test.ts` , `components/README.md` ,
`THEME_BASE_RECIPE_TOKENS` , `index.css` y `generated/base.css` quedan
actualizados.
- Validado despues de `Slider` :
- `npx vitest run src/uix/eidos` -> 7 archivos, 84 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> 0 invalid, sin drift
hotspots.
- Tercera tanda del mismo bloque:
- `Pagination` : root visual `pagination.svelte` , partes `PrevTrigger` ,
`NextTrigger` , `Item` , `Ellipsis` , `pagination.css` , `types.ts` e
`index.ts` .
- El root conserva el snippet de Soma con `{ pages, totalPages }` y solo
anade `size` visual resuelto por `ActiveEidos` .
- La receta cubre controles, estado selected, disabled, ellipsis y focus.
- Validado despues de `Pagination` :
- `npx vitest run src/uix/eidos` -> 7 archivos, 84 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> 0 invalid, sin drift
hotspots.
- Cuarta tanda del mismo bloque:
- `RatingGroup` : root visual `rating-group.svelte` , parte `Item` ,
`rating-group.css` , `types.ts` e `index.ts` .
- No se inventa icono/star por defecto ni API nueva; el wrapper conserva los
snippets de Soma (`items` en root y `state` en item) y la receta estiliza
`active` , `partial` , `inactive` , foco, vertical/horizontal y disabled.
- Validado despues de `RatingGroup` :
- `npx vitest run src/uix/eidos` -> 7 archivos, 84 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> 0 invalid, sin drift
hotspots.
- Quinta tanda del mismo bloque:
- `SearchField` : root visual `search-field.svelte` , partes `Input` ,
`ClearTrigger` , `search-field.css` , `types.ts` e `index.ts` .
- El wrapper conserva el snippet de Soma (`value`, `isEmpty` , `isFocused` ,
`clear` ) y solo anade `size` .
- La receta cubre contenedor, input, clear trigger, focused, invalid, empty
y disabled.
- Validado despues de `SearchField` :
- `npx vitest run src/uix/eidos` -> 7 archivos, 84 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> 0 invalid, sin drift
hotspots.
- Siguiente bloque sugerido:
- Migrar otro grupo de bajo riesgo desde Soma a Eidos: candidatos reales por
morfo/soma existentes son `number-field` , `field` o `toolbar` .
- Antes de tocar componentes grandes (`select`, `combobox` , `calendar` ,
`date-field` ) conviene fijar una tabla por componente: partes Soma,
props visuales Eidos, recipe tokens y attrs esperados.
Actualizacion Eidos components audit 2026-05-17:
- Se acometieron los hallazgos autorizados sobre `src/uix/eidos/components`
sin tocar demos ni rutas `web/routes/uix` :
- `Tabs` instala su contexto visual de forma sincronica durante init, no en
`$effect` ; los hijos `Tabs.Content` ya no pueden inicializar sin contexto.
- `Tabs.Indicator` deja de observarse a si mismo con `ResizeObserver` , para
evitar loops de medida provocados por sus propias escrituras inline.
- `Avatar.Image` ya no arranca oculto cuando hay `src` ; la visibilidad queda
derivada de `src` y de la ultima URL fallida.
- `Accordion.Trigger` ya no contiene `<style>` scoped; la regla de layout del
label vive en `accordion.css` .
- `Toast.Close` emite `data-icon-only` cuando renderiza el icono por defecto,
igual que `Dialog.Close` , `Drawer.Close` y `Popover.Close` .
- `Soma` expone `data-floating-wrapper` como marcador publico del wrapper
flotante; `Popover` y `Tooltip` dejan de depender de
`data-soma-floating-wrapper` en CSS.
- Guardias anadidas/reforzadas:
- `component-api-contract.test.ts` falla si un wrapper Eidos reintroduce
`onMount` , `<style>` scoped o `data-soma-*` .
- `component-visual-attrs.test.ts` cubre ahora `toast-close.svelte` y su
`data-icon-only` .
- Tests de Tooltip/LinkPreview esperan tambien el nuevo
`data-floating-wrapper` .
- Validado:
- `npx vitest run src/uix/eidos/component-api-contract.test.ts src/uix/eidos/component-visual-attrs.test.ts src/uix/eidos/recipe-css-contract.test.ts`
-> 3 archivos, 7 tests OK.
- `npx vitest run src/uix/soma/components/tooltip/tooltip-provider.svelte.test.ts src/uix/soma/components/link-preview/link-preview-provider.svelte.test.ts`
-> 2 archivos, 5 tests OK.
- `npx vitest run src/uix/soma/components/popover/popover-provider.svelte.test.ts`
-> 1 archivo, 2 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 81 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Pendiente deliberado:
- Ninguno del bloque auditado. Los `font-size: 0.9rem/0.85rem` restantes
quedaron migrados despues de esta nota a tokens de recipe canónicos.
Actualizacion Eidos recipe typography 2026-05-17:
- Cerrado el ultimo hallazgo P3 de la auditoria de componentes:
- `dialog.css` ya no usa `font-size: 0.9rem` ; consume
`--dialog-trigger-font-size` .
- `popover.css` ya no usa `font-size: 0.9rem` ni `0.85rem` ; consume
`--popover-trigger-font-size` y `--popover-close-font-size` .
- `popover.css` ya no usa fallback cromatico literal para overlay; consume
`--popover-overlay-bg` .
- Los nuevos tokens viven en `THEME_BASE_RECIPE_TOKENS` y se regenero
`src/uix/eidos/generated/base.css` con `npm run generate:eidos-css` .
- `recipe-css-contract.test.ts` ahora falla si un CSS de componente
reintroduce colores raw (`#...`, `rgb(...)` , `hsl(...)` ) o `font-size`
literal en `px/rem` .
- Validado:
- `npx vitest run src/uix/eidos/recipe-css-contract.test.ts src/uix/eidos/generated-css.test.ts`
-> 2 archivos, 5 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 79 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion Eidos intent wording 2026-05-17:
- Limpieza de naming en `src/uix/eidos/components/icon/*` :
- `IntentIcon` y `INTENT_ICON` ya no describen el intent como propiedad de
Sema. El tipo sigue importandose desde la fuente unica `$uix/intent` y los
comentarios hablan de `Intent` canonico.
- Validado:
- `rg "sema intent|Sema intent" src/uix src/arts` -> 0 resultados.
- `npx vitest run src/uix/eidos` -> 7 archivos, 81 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion Eidos flat residue cleanup 2026-05-17:
- Retirado CSS muerto de `checkbox.css` para la antigua marca
`data-checkbox-flat` / `data-checkbox-label` ; ningun componente ni morfo lo
emitia y chocaba con la convencion actual sin APIs flat.
- `ToasterProps` ya no usa la palabra "Flat" en su docstring; queda descrito
como convenience/default layout para no confundirlo con la API flat retirada.
- `component-api-contract.test.ts` anade guardia contra marcadores
`data-*-flat` en fuentes de componentes Eidos.
- Validado:
- `rg "data-[a-z0-9-]+-flat|flat default|Flat <Toaster>" src/uix/eidos/components`
-> 0 resultados.
- `npx vitest run src/uix/eidos/component-api-contract.test.ts src/uix/eidos/recipe-css-contract.test.ts`
-> 2 archivos, 10 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 82 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion Eidos CSS entry guard 2026-05-17:
- `index.css` limpia comentario stale de la fase "air-translated"; las recipes
actuales se tratan como entrada activa de Eidos.
- `recipe-css-contract.test.ts` anade guardia para que todo
`components/{name}/{name}.css` este importado desde `src/uix/eidos/index.css` .
- Validado:
- `npx vitest run src/uix/eidos/recipe-css-contract.test.ts` -> 6 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion Eidos legacy layout guard 2026-05-17:
- `lint.test.ts` elimina fallback al layout CSS raiz retirado
(`components/{name}.css`) y anade guardia explicita: todo CSS de componente
debe vivir en `components/{name}/{name}.css` .
- Limpieza de comentarios stale:
- `events.css` referencia `EngineSemantic` , no `SemanticEngine` .
- `toast.css` deja de hablar de "phase 2".
- `components/README.md` corrige "retiraled".
- Validado:
- `npx vitest run src/uix/eidos/lint.test.ts src/uix/eidos/recipe-css-contract.test.ts`
-> 2 archivos, 20 tests OK.
- `rg "retiraled|SemanticEngine|phase 2|older flat|flat layout still" src/uix/eidos`
-> 0 resultados.
- `npx vitest run src/uix/eidos` -> 7 archivos, 84 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion Eidos config audit 2026-05-17:
- Resuelta la parte no-componente de la auditoria consolidada de
`src/uix/eidos` :
- `validateTypography(...)` ya no asume que `sizes` , `families` ,
`weights` o `styles` existen y son objetos; ahora produce issues de
validacion.
- `validateSizePrimitive(...)` y `validateTextMetric(...)` degradan campos
ausentes o mal tipados a issues, sin `TypeError` por `.trim()` .
- `validateColorScale(...)` valida escala como objeto plano y rechaza pasos
`null` / `undefined` .
- `primitives.shadow` queda incluido en la validacion de shape.
- El contrato CSS de `size-*-font-line-height` y
`size-*-font-letter-spacing` apunta a
`primitives.typography.sizes.{fontSize}.lineHeight/letterSpacing` , no a
`primitives.size.*.fontSize` .
- `renderThemeCss(config, themeId)` ya no contiene el caso magico
`themeId === 'base-light'` ; el renderer puro deriva el selector solo del
`themeId` . `ActiveEidos` sigue siendo quien decide usar `:root` cuando
aplica runtime CSS.
- Tests nuevos en `src/uix/eidos/active-eidos-config.test.ts` cubren
tipografia incompleta, size/text metric incompletos, escalas con `null` ,
shape de `shadow` , paths de contrato tipografico y selector raw por
`themeId` .
- Validado:
- `npx vitest run src/uix/eidos` -> 7 archivos, 78 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Nota historica: en ese momento quedo pendiente porque se pidio no tocar
componentes aun; queda resuelto en la actualizacion de componentes del
2026-05-17:
- `avatar-image.svelte` : estado `visible` derivable desde `src` .
- `tabs-indicator.svelte` : `ResizeObserver` observa el propio indicador.
- `accordion-trigger.svelte` : unico scoped style dentro de componente.
- `toast-close.svelte` : falta `data-icon-only` consistente con Close de
Dialog/Drawer/Popover.
- `popover.css` y `tooltip.css` : selectores acoplados a
`data-soma-floating-wrapper` .
Actualizacion Eidos ecosystem 2026-05-16:
- Correccion de alcance: no seguir tocando demos/rutas ni
`src/uix/eidos/components/*` sin orden explicita. El foco vigente es el
ecosistema Eidos fuera de componentes: `ActiveEidos` , `eidos/lib` ,
contrato/generacion/persistencia, tests de runtime y documentacion de capa.
- Persistencia reforzada: `readEidosConfigFromDocument(...)` y
`parseEidosConfigFromJson(...)` ya no aceptan solamente un envelope valido;
al convertirlo en runtime validan tambien las `options` contra el contrato
completo de `EidosConfig` y lanzan `EidosConfigValidationError` si el tema
persistido no es usable.
- `parseEidosConfigDocument(...)` queda definido como parser de envelope
versionado (`kind/version/options`), no como validador semantico del tema.
- Guardia anadida: el contrato CSS de Eidos debe estar alineado con los
renderers generados; cada token `static` debe aparecer en `renderStaticCss()`
y cada token `theme` en `renderThemeCss('base-light')` .
- Overrides runtime reforzados: `ActiveEidos` valida y clona `cssVariables`
iniciales aunque `applyDom:false` , y `setCssVariables(...)` es
transaccional. Un mapa invalido no reemplaza el bloque de variables vigente.
- Validacion de config reforzada: documentos persistidos con `options`
malformadas fallan como `EidosConfigValidationError` con issues de contrato,
no como `TypeError` de runtime.
- IDs de theme y nombres de escalas de color quedan validados como segmentos
CSS kebab-case antes de generar selectores o custom properties desde config.
- Claves authorables de tipografia (`families`, `weights` , `styles` ) deben
generar sufijos CSS validos; `typography.sizes` permanece canonico.
- Motion e icon dejan de depender solo de tipos TS: sus key sets canonicos
(`DURATION_KEYS`, `EASE_KEYS` , `MOTION_DISTANCE_KEYS` ,
`MOTION_SCALE_KEYS` , `ICON_STROKE_WIDTH_KEYS` ) se exportan y validan en
runtime antes de generar CSS.
- Primitivas estaticas base reforzadas: `space` valida sufijos CSS abiertos,
`controlHeight` y `radius` usan key sets canonicos, y `focusRing` valida
valores no vacios.
- Grupos semanticos de color (`surface`, `content` , `border` , `focus` ) quedan
cerrados con key sets canonicos y valores no vacios antes de generar tokens
de theme.
- Overrides de `semantics.color.roles.*.slots` quedan validados: solo slots
canonicos y pasos `1..12` .
- Valores CSS del `EidosConfig` comparten la misma defensa que los overrides
runtime: no pueden contener `;` , `{` ni `}` .
- Documentos persistidos con grupos opcionales malformados (`primitives.*`,
`themes.*` , `recipes.*` ) fallan temprano como `EidosConfigValidationError` .
- Validado:
- `npx vitest run src/uix/eidos/active-eidos-config.test.ts` -> 35 tests OK.
- `npx vitest run src/uix/eidos/active-eidos.test.ts` -> 19 tests OK.
- `npx vitest run src/uix/eidos` -> 7 archivos, 75 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion permutation runner 2026-05-16:
- Segunda tanda de demos `/uix/components/*` instrumentada con
`data-perm-step` :
- `accordion` , `collapsible` , `dialog` , `drawer` , `popover` ,
`radio-group` , `toast` y `tooltip` .
- La cobertura interactiva actual queda en 12 demos: `accordion` ,
`checkbox` , `collapsible` , `dialog` , `drawer` , `popover` ,
`radio-group` , `switch` , `tabs` , `toast` , `toggle` , `tooltip` .
- `scripts/permutation-check.ts` ya no depende de `networkidle` en
`page.goto` ; carga con `domcontentloaded` , espera una estabilizacion hibrida
(`networkidle` corto si llega + settle explicito) y distingue
`SKIP no route` de `SKIP no demo load` .
- El settle por defecto de cada paso pasa a 500ms para no validar antes de que
los effects de Soma hayan proyectado atributos DOM en dev mode.
- `toastMorfo` corrige `data-swipe` como atributo opcional: solo existe
durante un gesto de swipe. `data-swipe-direction` sigue siendo estable.
- Validacion:
- `npx vitest run src/uix/soma/components/toast/toast-provider.svelte.test.ts`
-> 2 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `node --import tsx/esm scripts/permutation-check.ts http://127.0.0.1:5190`
-> 12 demos instrumentadas OK, 28 pasos.
- Pendiente inmediato:
- `avatar` e `icon` tienen ruta pero no interaccion significativa aun; se
quedan como `SKIP no perm instrumentation` .
- Los 53 morfos restantes no tienen ruta `/uix/components/{kebab}` en el
shell actual; no contarlos como cobertura hasta que exista demo.
Actualizacion permutation axes 2026-05-16:
- Variantes URL del runner activadas en demos que ya tenian estado real para
honrarlas:
- `accordion` : `disabled` .
- `collapsible` : `disabled` .
- `checkbox` : `disabled` , `invalid` .
- `radio-group` : `dir` , `disabled` , `invalid` .
- `switch` : `disabled` , `invalid` .
- `tabs` : `dir` , `orientation` , `disabled` .
- `toggle` : `disabled` , `invalid` .
- `tooltip` : `dir` , `disabled` .
- En variantes `disabled` , los pasos interactivos se omiten desde la propia
demo para validar el estado estatico deshabilitado sin forzar clicks sobre
controles inactivos.
- Validacion: `node --import tsx/esm scripts/permutation-check.ts
http://127.0.0.1:5192` -> 12 demos instrumentadas OK, 54 pasos, 28 variantes
URL.
Actualizacion Eidos component API guard 2026-05-16:
- `src/uix/eidos/component-api-contract.test.ts` ahora tambien valida que los
miembros declarados en cada `XxxNamespace` coincidan con las asignaciones
explicitas del barrel (`Tabs.Trigger = Trigger`, etc.).
- Esto cierra el hueco que dejaba el cast `const Tabs = TabsRoot as
TabsNamespace`: TypeScript no detecta una asignacion olvidada despues del
cast, pero la guardia estatica si.
- Validacion: `npx vitest run src/uix/eidos/component-api-contract.test.ts`
-> 3 tests OK; `npm run check` -> 0 errores, 0 warnings.
Arranque rapido para mañana:
- Rama `active-uix` queda por delante de `gita/active-uix` con los commits de
limpieza de Soma/UIX ya hechos y validados.
- Ultimos commits relevantes:
- `Keep Soma internals off public alias`
- `Narrow Soma root barrel`
- `Remove Soma common langs facade`
- `Guard Sema runtime boundaries`
- `Inject ActiveDom into Soma scroll lock`
- `Record Soma scroll lock validation`
- Validacion final del bloque:
- `npm run check` -> 0 errores, 0 warnings.
- `npm run test` -> 233 archivos, 2248 tests OK.
- Estado arquitectonico cerrado hoy:
- Dentro de Soma no se importa desde `$soma/*` ; el alias publico queda para
consumidores externos y tests de superficie.
- `$soma` raiz solo expone el scope `Soma` y su error de contexto; helpers
publicos se consumen desde subpaths explicitos.
- `soma/core/langs.ts` eliminado; `common.*` pertenece a `src/uix/langs.ts` .
- Sema queda protegido contra listeners globales nativos y `console.*` .
- `ScrollLock` de Soma inyecta `ActiveDom` hacia `BodyScrollLock` .
- Decision de cierre:
- La fase Soma queda terminada. No seguir corrigiendo Soma a ciegas salvo
bug concreto o regresion nueva.
- La siguiente fase autorizada es volver a Eidos, empezando por auditoria de
componentes Option C y su relacion con Soma/Morfo sin reabrir runtime
general ni arquitectura ActiveUix.
- Lo primero para continuar:
1. Arrancar Eidos leyendo primero `src/uix/eidos/README.md` ,
`src/uix/eidos/components/README.md` , `src/uix/active_architecture.md` y
este archivo.
2. Auditar componentes Eidos Option C: root visual + partes attached,
imports desde subpaths publicos de Soma, sin `Provider` visual publico,
sin flat snippets y sin duplicar behavior headless.
3. Validar las rutas actuales bajo `web/routes/uix/components/*` despues de
cualquier cambio Eidos; el smoke navegador limpio de Soma queda como
baseline.
4. Decidir si el directorio vacio `src/uix/soma/components/avatar/` se borra
o se deja como placeholder documentado. Hoy Avatar es `eidos` scope.
Decidido: no hay accion versionable; solo existe un directorio local
vacio (`components/`) y Git no lo registra. No crear placeholder Soma.
5. Sium P0 de integridad queda cerrado: `isPlainObjectRecord` , `email` ,
`regex` con flags mutables y docs de `ctx.rootValue` .
6. Mantener fuera de commits los logs sueltos (`.codex-vite-*`,
`debug.log` ) salvo que el usuario pida conservarlos.
Actualizacion Eidos 2026-05-16:
- Primera pasada de componentes Option C ejecutada:
- Barrels multi-part normalizados a asignacion explicita per-property
(`const Drawer = DrawerRoot as DrawerNamespace; Drawer.Trigger = Trigger;`)
y sin `Object.assign` .
- Tipos root visuales renombrados a `AccordionProps` , `DrawerProps` ,
`DialogProps` , `TabsProps` , etc. Eidos ya no define `XxxProviderProps` ;
`ProviderProps` solo aparece como alias importado desde Soma cuando la
superficie headless lo llama asi.
- `src/uix/eidos/components/README.md` actualizado con la convencion real.
- `Toaster` deja de usar un alias interno `Provider` para no reintroducir el
modelo mental retirado.
- Aniadido `src/uix/eidos/lib/style.ts` con `composeInlineStyle(...)` y
aplicado a wrappers que mezclan estilo del consumidor con custom properties
de receta: overlay de Dialog/Drawer, Toast.Viewport, Checkbox.Group,
RadioGroup, Tabs.Indicator, Icon y primitives SVG.
- Validacion de esta pasada:
- `npm run check` -> 0 errores, 0 warnings.
- `npx vitest run src/uix/eidos` -> 4 archivos, 56 tests OK.
- `npm run test` -> 233 archivos, 2270 tests OK.
- SSR smoke de `web/routes/uix/components/{accordion,avatar,checkbox,
collapsible,dialog,drawer,popover,radio-group,switch,tabs,toast,toggle,
tooltip}` -> HTTP 200.
- Siguiente foco recomendado en Eidos:
1. Auditar recipes/CSS contra tokens generados por `ActiveEidos` y decidir
que CSS legacy queda como recipe por componente y que debe generarse.
2. Revisar componentes visuales que anaden partes eidos-only (`Header`,
`Footer` , `Status` , `Main` , SVG primitives) para documentar si necesitan
morfo propio o si son recipe primitives privadas.
3. Revisar tests de componentes Eidos: hoy hay cobertura del runtime Eidos,
pero no tests unitarios especificos para wrappers visuales.
Actualizacion Eidos recipes 2026-05-16:
- Inicio del barrido recipe/CSS:
- `checkbox.css` consumia `--checkbox-stroke-duration` y
`--checkbox-stroke-ease` solo como fallback inline; ambos pasan a
`THEME_BASE_RECIPE_TOKENS.checkbox` .
- `popover.css` consumia `--popover-overlay-z` con fallback; pasa a
`THEME_BASE_RECIPE_TOKENS.popover` .
- Regenerado `src/uix/eidos/generated/base.css` con
`npm run generate:eidos-css` .
- Validacion:
- `npm run check` -> 0 errores, 0 warnings.
- `npx vitest run src/uix/eidos` -> 4 archivos, 56 tests OK.
- Pendiente del mismo eje:
- Convertir el barrido recipe/CSS en test estable o script robusto (el
parser rapido usado hoy no sirve con objetos TS complejos y comentarios).
- Revisar tokens declarados pero no usados para separar: reserva doctrinal
intencional vs residuo de CSS legacy.
Actualizacion Eidos auditoria Kimi 2026-05-16:
- Hallazgos corregidos:
- `tabs-indicator.svelte` pasa de `onMount` a `$effect` con cleanup ligado
al `ref` . Nota: `onMount` no es incompatible con Svelte 5, pero `$effect`
encaja mejor aqui porque el observer depende del elemento enlazado.
- Icono `folder-root.svelte` exportado como `FolderRoot` y catalogado como
`folder-root` / `FolderRoot` ; se elimina el falso `FolderProvider` .
- Comentario de `toggle.svelte` corregido: Eidos expone `<Toggle>` , no
`<Toggle.Provider>` .
- Helpers repetidos de `eidos/lib` centralizados en `utils.ts` :
`clonePlain` , `isPlainRecord` , `hasOwn` , `toKebab` .
- `isPlainRecord` queda unificado como objeto literal o null-prototype; no
acepta arrays ni instancias de clase.
- Hallazgos evaluados pero no aplicados:
- `dialog.svelte` y `drawer.svelte` no necesitan `data-size` en el root:
sus props visuales viven en `Content` ; `variant` /`direction` son headless
y ya los proyecta Soma/Morfo.
- `icon.svelte` mantiene `class` como prop DOM idiomatica; cambiar a
`className` seria menos natural en Svelte y no resuelve un bug real.
- `StyleBlockManager` , builder de recipes y action separada para Tabs
quedan como refactors posibles, no P0/P1.
- Validacion:
- `npm run check` -> 0 errores, 0 warnings.
- `npx vitest run src/uix/eidos` -> 4 archivos, 56 tests OK.
- `npm run test` -> 233 archivos, 2270 tests OK.
Actualizacion Eidos recipe contract 2026-05-16:
- Cerrado el barrido recipe/CSS con una guardia versionada:
`src/uix/eidos/recipe-css-contract.test.ts` .
- Si un CSS de componente consume `--{component}-*` , el alias debe existir
en `THEME_BASE_RECIPE_TOKENS` .
- Si el theme base declara un alias publico, debe estar consumido por el
componente, por sus fuentes Svelte/TS o por otro token compuesto.
- Limpieza aplicada:
- `Toggle` consume sus tokens publicos de variante (`solid`, `outline` ,
`ghost` ) en vez de duplicar formulas dentro del CSS. Se retira el naming
residual `surface-*` porque la variante publica es `solid` .
- `Checkbox` , `RadioGroup` y `Switch` ya no publican tokens de intents que
sus tipos no pueden activar.
- `Toast` elimina los tokens tipograficos de `message` , parte que la propia
recipe documenta como retirada; conserva `message-color` porque lo usa el
item como color base.
- `Accordion` , `Tabs` , `Tooltip` y `RadioGroup` conectan tokens que estaban
declarados pero no consumidos (`indicator-*`, `list-bg` , `content-z` ,
`indicator-bg-checked-disabled` ).
- `Icon` mantiene `--icon-size` y `--icon-stroke-width` : son consumidos por
`icon.svelte` , no por CSS.
- Regenerado `src/uix/eidos/generated/base.css` con
`npm run generate:eidos-css` .
- Validacion:
- `npx vitest run src/uix/eidos/recipe-css-contract.test.ts` -> 3 tests OK.
- `npx vitest run src/uix/eidos` -> 5 archivos, 59 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion Eidos component API 2026-05-16:
- Corregida documentacion stale de `Collapsible` : ya no describe dos shapes,
ni flat con snippet `trigger` , ni `<Collapsible.Provider>` publico. La
superficie vigente es `<Collapsible>` + `.Trigger` + `.Content` ; el provider
de Soma queda como detalle interno.
- Corregido comentario stale en `Dialog.Close` : no existe un auto-render flat
de `<Dialog>` .
- Guardia nueva `src/uix/eidos/component-api-contract.test.ts` :
- barrels de componentes sin `Object.assign` ;
- sin export publico de `Provider` ;
- sin imports publicos desde `*-provider.svelte` ;
- cada componente publico, salvo `svg` primitives, tiene root
`{component}.svelte` .
- Validacion:
- `npx vitest run src/uix/eidos` -> 6 archivos, 61 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Smoke local one-shot con Vite + Playwright sobre `/uix` y
`/uix/components/{accordion,avatar,checkbox,collapsible,dialog,drawer,
icon,popover,radio-group,switch,tabs,toast,toggle,tooltip}` -> OK
(sin `pageerror` , `console.error` , `requestfailed` relevante ni
`__uix_lang_missing__` ).
- `scripts/check-eidos-recipes.ts` actualizado: ya no apunta al arbol
historico `/test/eidos/*` ; ahora prueba `/uix/components/toggle` ,
`/uix/components/switch` y `/uix/components/dialog` , detectando puertos
5173-5180.
- `scripts/eidos-lint-all.ts` afinado: mantiene allowlist explicita de attrs
y partes Eidos-only documentadas (`Header`, `Footer` , `Status` , `Main` ,
`Handle` , indicadores, `data-columns` , `data-ready` , wrapper flotante, etc.)
y ahora sale con codigo 1 si aparecen selectores invalidos. La ejecucion
actual queda en invalid=0 y sin drift hotspots fuera de esa allowlist.
Actualizacion smoke 2026-05-16:
- `scripts/smoke-check.mjs` deja de apuntar al arbol retirado
`src/routes/test/soma` y descubre rutas concretas `+page.svelte` bajo
`web/routes` .
- Soporta `SMOKE_SCOPE=/uix` para limitar la pasada a UIX cuando no haga falta
recorrer la documentacion de Active.
- La prueba falla por `pageerror` , `console.error` real, warnings de
traduccion/contexto, request failures same-origin y
`__uix_lang_missing__` renderizado. Los recursos externos opcionales se
ignoran como request failures para que el smoke offline no confunda red
bloqueada con regresion local.
- Validado contra Vite local: `node scripts/smoke-check.mjs
http://127.0.0.1:5181` -> 41 rutas OK (`/`, `/active/*` , `/uix/*` ).
- Documentacion sincronizada:
- `src/uix/soma/COMPONENT_GUIDE.md`
- `src/uix/morfo/README.md`
- `src/uix/soma/components/calendar/README.md`
- `src/uix/soma/components/range-calendar/README.md`
- `scripts/probe-toast-dismiss.ts` ahora usa por defecto
`/uix/components/toast` .
- `scripts/morfo-check.ts` queda reconectado parcialmente: valida los morfos
que tienen ruta concreta bajo `/uix/components/{kebab}` y marca el resto como
`SKIP` en vez de fallar por rutas inexistentes. Se puede cambiar el prefijo
con `MORFO_ROUTE_PREFIX` .
- Al volver a ejecutar `morfo-check` , aparecieron y se corrigieron dos
incoherencias de Morfo:
- `fieldMorfo` declaraba los valores de `data-state` como `states` , pero su
fuente runtime real es `state` ; tambien se corrige `aria-busy` para mirar
`state === 'loading'` .
- `schema.ts` permite ahora `emit: 'value'` sin `value` source cuando el attr
es declarativo/manual. Esto cubre `Form.AutoFields` , donde el componente
escribe valores como `data-form-auto-fields-field={path}` sin pasar por
`SomaRuntime` .
- Validacion:
- `node --import tsx/esm scripts/morfo-check.ts http://127.0.0.1:5182` ->
14 morfos con ruta OK, 53 `SKIP` .
- `npx vitest run src/uix/morfo/schema.test.ts src/uix/morfo/registry.test.ts src/uix/morfo/compile.test.ts`
-> 41 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Pendiente deliberado: `scripts/permutation-check.ts` sigue siendo runner
historico del arbol `/test/soma` ; no usarlo como release gate hasta
reconectarlo a una route map real del docs shell actual.
- `scripts/permutation-check.ts` reconectado al shell actual:
- usa `/uix/components/{kebab}` por defecto;
- admite `PERM_ROUTE_PREFIX` para otros shells;
- salta morfos sin ruta como `SKIP no route` ;
- salta rutas sin `data-perm-step` ni `perm-axes` como
`SKIP no perm instrumentation` ;
- si todavia no hay demos instrumentadas, sale limpio con
"No instrumented routed demos found".
- `src/uix/morfo/PERMUTATION_RUNNER.md` actualizado: la antigua infraestructura
`_perms.svelte.ts` queda marcada como retirada; las paginas actuales deben
leer `?perm.*` desde su ruta si optan a permutations.
- Primeras rutas instrumentadas con `data-perm-step` :
- `/uix/components/toggle`
- `/uix/components/switch`
- `/uix/components/checkbox`
- `/uix/components/tabs`
- Validacion: `node --import tsx/esm scripts/permutation-check.ts
http://127.0.0.1:5184` -> 4 demos instrumentadas OK, 9 pasos, 53 sin ruta,
10 sin instrumentacion.
- Smoke actualizado para esperar `domcontentloaded` + settle en vez de
`networkidle` ; `/uix/components/icon` puede ser pesado y no debe fallar por
actividad de red prolongada si no hay `pageerror` , consola real ni fallbacks.
- Validacion smoke posterior: `node scripts/smoke-check.mjs
http://127.0.0.1:5185` -> 41 rutas OK.
Actualizacion Eidos visual wrappers 2026-05-16:
- Nueva guardia `src/uix/eidos/component-visual-attrs.test.ts` :
asegura que los wrappers Eidos que publican props visuales sigan estampando
los `data-*` que consumen las recipes (`data-size`, `data-variant` ,
`data-color` , `data-position` , `data-columns` , `data-motion` , etc.).
- Documentado en `src/uix/eidos/components/README.md` que esta guardia protege
el cableado wrapper -> recipe sin convertir Eidos en runtime headless.
Actualizacion 2026-05-16:
- Barrido de wrappers publicos Soma frente a providers cerrado:
- `DateField.Provider` y `TimeField.Provider` vuelven a materializar su
root publico por defecto (`< div {... mergedProps } > `) y aceptan `ref` /
`restProps` , coherente con su morfo (`kind: public`,
`defaultElement: 'div'` ).
- `DateField` ya respeta la prop `dir` ; la direccion efectiva se pasa al
provider y a la navegacion de segmentos en vez de ignorarse y leer solo
`soma.prefs` .
- `DatePicker` , `DateRangePicker` , `TimePicker` y `TimeRangePicker`
mantienen root virtual: sus props root ya no anuncian `PrimitiveDivAttrs`
ni `child` con `props: {}` .
- `ColorPicker.Area` ya aplica de verdad los overrides locales
`xChannel` / `yChannel` ; antes los tipos los exponian pero el wrapper los
descartaba.
- Guardias nuevas en `src/uix/contracts.test.ts` para roots publicos
Date/Time Field y roots virtuales picker.
- Validado: `npx vitest run src/uix/contracts.test.ts` + tests focales de
date/time pickers/fields -> 52 tests OK; `color-picker-provider` -> 5
tests OK; `npm run check` -> 0 errores / 0 warnings; `npm run test` ->
233 archivos, 2251 tests OK.
- Soma queda en estado funcionalmente cubierto a nivel provider/runtime:
`npm run check` -> 0 errores / 0 warnings, `npm run test` -> 233 archivos,
2242 tests OK, y la guardia de `*-provider.svelte.ts` sin test directo
devuelve `NO_MISSING_PROVIDER_TESTS` .
- Lo que falta para cerrar Soma de verdad no es mas cobertura de providers, sino
las capas exteriores:
1. Auditar wrappers Svelte publicos (`*.svelte`) frente a sus providers:
props bindables, snippets, forwarding de attrs, eventos y defaults.
2. Auditar barrels publicos (`index.ts`, `exports.ts` ) para que no expongan
clases runtime internas, reexports muertos ni fachadas sobre `$libs` .
3. Validar rutas `/uix/components/*` con navegador: sin `pageerror` , sin
errores de consola, sin warnings de traduccion inesperados y con flujos
basicos interactivos.
4. Sincronizar inventario/documentacion Soma con el estado real: componente
activo, visual-native, wrapper publico, provider runtime y tests.
5. Mantener la doctrina DOM actual: escrituras gestionadas, listeners
globales, focus/scroll imperativos y portal/query global pasan por
`ActiveDom` ; lecturas locales (`getBoundingClientRect`, `contains` ,
`closest` , `scrollTop` , etc.) siguen siendo responsabilidad del componente.
6. Dejar optimizaciones de rendimiento para despues de cerrar API publica y
wrappers: virtualizacion compartida, datetime compartido y micro-churn del
runtime solo si aparecen datos reales o tests que lo justifiquen.
7. Cerrado: guia/documentacion Soma alineada con el estado actual:
pertenencia no-Soma apunta a Eidos, no Air; `{name}-provider.svelte.ts`
contiene clases provider/state concretas sin herencia; `soma.runtime()` es
el camino canonico dentro de providers; demos viven en
`web/routes/uix/components/{name}` ; Eidos consume Soma por subpaths
publicos y Sema posee percepcion/eventos.
- Auditoria `src/arts/sium/kimi-audit.md` leida y evaluada. Mi veredicto:
buena auditoria, bastante alineada con el rol real de Sium como codec +
validador + introspeccion para Active, pero con dos matices:
- La prioridad critica correcta es integridad de datos, no ampliar Sium hasta
parecerse a Zod.
- Algunos fixes descritos como "1 linea" no lo son si queremos mantener
contratos `decodeSync` , `~sium` y `Form.AutoFields` coherentes.
- Sium P0 cerrado, sin cambios breaking:
1. `isPlainObjectRecord(...)` acepta solo objetos planos o null-prototype; se
rechazan `Date` , `RegExp` e instancias de clase.
2. `email()` usa una regex conservadora de producto: dominio sin puntos
dobles y TLD practico de 2+ caracteres.
3. `regex(pattern)` clona una vez el patron sin flags mutables `g` /`y`, de
modo que no toca `lastIndex` del regex recibido.
4. README y tipos de Sium aclaran que `ctx.rootValue` es passthrough opcional;
el core no lo sintetiza. Las validaciones cross-field sobre datos
decodificados deben vivir en un `refine()` del `object()` y usar el valor
decodificado recibido por ese refine.
5. Validado: `npx vitest run src/arts/sium/test` -> 18 archivos, 366 tests OK;
`npm run check` -> 0 errores, 0 warnings; `npm run test` -> 233 archivos,
2262 tests OK.
6. Cerrado: `optional/nullable/defaulted` con inner async conservan el
short-circuit sync del sentinel (`undefined`, `null` o default). Si el
valor definido necesita entrar al inner async, `decodeSync` /
`validateSync` siguen lanzando `SiumAsyncSchemaError` .
7. Validado tras wrappers async: `npx vitest run src/arts/sium/test` -> 18
archivos, 368 tests OK; `npm run check` -> 0 errores, 0 warnings;
`npm run test` -> 233 archivos, 2264 tests OK.
- Sium P1 coordinado con consumidores:
1. No cambiar `lazy()` a `kind: 'lazy'` hasta que
`src/uix/soma/components/form/components/form-auto-fields.svelte` sepa
renderizar/posponer ese kind. Hoy `SchemaKind` no incluye `lazy` .
2. Anadir refinements pequenos y utiles: `finite` , `safe` , `positive` ,
`nonempty` , `uuid` solo si hay uso inmediato en Active/Form.
3. Anadir utilidades de objeto (`partial`, `pick` , `omit` , `extend` ) y
estructuras (`tuple`, `record` ) cuando AutoFields y `~sium.shape` tengan
contrato de introspeccion claro.
4. Considerar `preprocess` y `coerce` como features de formularios, no como
ampliacion generalista.
- Sium P2 interno:
1. Cerrado: `types/_helpers.ts` incorpora `createDomainValueSchema(...)` y
`createDomainRangeSchema(...)` . `colorValue` , `dateValue` , `timeValue` ,
`dateRange` y `timeRange` comparten ahora el patron identity codec +
guard + widget + range order sin mover esa logica a `core` .
2. Cerrado: combinadores (`object`, `array` , `union` , `discriminated` ) usan
la misma semantica por ruta que wrappers. Un schema marcado `async` puede
completar `decodeSync` si el input no necesita tocar trabajo async (por
ejemplo field optional async ausente, array vacio o union sync-first). Si
la ruta seleccionada necesita async, sigue lanzando `SiumAsyncSchemaError` .
3. Cerrado: `lazy()` documenta limites de datos runtime autociclicos y lanza
`SiumLazyResolvingError` cuando el thunk usa el proxy mientras resuelve o
devuelve el mismo proxy como schema final. No se anade `WeakSet` global
porque la deteccion de ciclos de datos debe ser una capa de normalizacion
del dominio si entran datos no confiables.
4. Validado tras `lazy()` : `npx vitest run src/arts/sium/test` -> 18
archivos, 370 tests OK; `npm run check` -> 0 errores, 0 warnings;
`npm run test` -> 233 archivos, 2266 tests OK.
5. Validado tras paths sync/async de combinadores: `npx vitest run
src/arts/sium/test` -> 18 archivos, 374 tests OK; `npm run check` -> 0
errores, 0 warnings; `npm run test` -> 233 archivos, 2270 tests OK.
- Validacion Sium domain factory:
- `npx vitest run src/arts/sium/test/color.test.ts src/arts/sium/test/date.test.ts src/arts/sium/test/time.test.ts src/arts/sium/test/standard-schema.test.ts` -> 4 archivos, 122 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Criterio de cierre para Sium antes de tocar consumidores UI:
- Tests focales de `src/arts/sium` verdes.
- `npm run check` sin warnings.
- README y tipos `SchemaKind` /`SiumShape` sincronizados.
- `Form.AutoFields` actualizado antes de cualquier kind nuevo visible en
`~sium` .
- Ninguna feature nueva entra si solo duplica Zod/Valibot sin consumidor
propio de Active.
- Soma public surface:
- Cerrado: el wrapper publico de Select pasa de
`components/select-provider.svelte` a `components/select.svelte` . El
runtime interno sigue en `select-provider.svelte.ts` .
- Cerrado: `Command` , `Form` y `Table` ya no reexportan motores de `$libs` .
Los consumidores deben importar `computeFuzzyScore` desde `$libs/strings` ,
`createForm` desde `$libs/forms` y `createTable` /tipos desde
`$libs/datagrid` .
- Guardia nueva en `src/uix/contracts.test.ts` : ningun barrel publico de Soma
puede exportar desde `*provider.svelte` ni desde `$libs/*` .
- Guardia nueva adicional: cada `Provider` publico debe salir de
`components/{component}.svelte` ; no se permiten nombres especiales para el
wrapper raiz.
- Documentacion corregida: `AlertDialog` ya importa `createForm` desde
`$libs/forms` , no desde `$soma/components/form` .
- Documentacion corregida: `ColorField` ya no marca `ColorPicker` como
planned, y los links a docs planned inexistentes de `ColorRange*` quedan
como texto sin enlace.
- Guardia nueva: los links relativos entre README de componentes Soma deben
apuntar a documentos existentes.
- Cerrado: los imports internos de produccion de Soma ya no usan el alias
publico `$soma` ; Drawer, Toast, Toggle, Switch, Dismissal, Floating y
`types` pasan a imports relativos.
- Guardia nueva: `src/uix/contracts.test.ts` rechaza imports internos de
Soma hacia su propio alias publico, dejando `$soma/*` para consumidores
externos y tests de superficie.
- Cerrado: el barrel raiz `$soma` queda limitado al scope `Soma` y su error
de contexto. Helpers como `provider` , `keyboard` , `runtime.svelte` ,
`types` , `css` , `id` , `props` , `components` , `layers` y `datetime` se
consumen desde sus subpaths explicitos.
- Cerrado: eliminado `soma/core/langs.ts` , que era una fachada muerta sobre
`src/uix/langs.ts` . El vocabulario `common.*` pertenece a UIX y
`ActiveUix` lo registra; Soma solo lo referencia mediante `v.commonRef` .
- Guardia nueva: Sema no puede registrar listeners globales nativos
(`document/window.addEventListener`) ni usar `console.*` en produccion; los
canales deben pasar por servicios inyectados y logger.
- Cerrado: `ScrollLock` de Soma recibe ahora `ActiveDom` del scope y lo pasa
a `BodyScrollLock` ; el helper de ADom resuelve document/window/listeners
desde el runtime inyectado, con fallback nativo solo para uso standalone y
tests.
- Validacion global tras inyectar `ActiveDom` en `ScrollLock` :
- `npm run test` -> 233 archivos, 2248 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Documentacion corregida: README, arquitectura y comentario de
`core/soma.svelte.ts` ya no recomiendan que el propio Soma importe desde
`$soma/*` .
- Smoke Playwright de rutas `/uix` actuales cerrado:
`/uix` , Accordion, Checkbox, Collapsible, Dialog, Drawer, Popover,
RadioGroup, Switch, Tabs, Toast, Toggle y Tooltip cargan con HTTP 200,
sin `pageerror` , sin errores/warnings de consola y sin `requestfailed` .
- Smoke navegador actualizado para las rutas montadas bajo `web/routes/uix` :
`/uix` , Accordion, Avatar, Checkbox, Collapsible, Dialog, Drawer, Icon,
Popover, RadioGroup, Switch, Tabs, Toast, Toggle y Tooltip cargan sin
overlay de error, sin `__uix_lang_missing__` y sin errores/warnings de
consola. La primera pasada produjo un falso positivo por HMR en `Icon` y
por textos legitimos `500ms/5000ms` en Tooltip/Toast; la repeticion limpia
en pestaña nueva quedo verde.
- Validacion global posterior:
- `npm run test` -> 233 archivos, 2245 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Validacion global tras limpiar alias/barrels/fachadas:
- `npm run test` -> 233 archivos, 2248 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
Actualizacion 2026-05-15:
- Auditoria Soma/Eidos ampliada aplicada por fases y empujada:
- Cobertura nueva para Select, Popover, Toast y RangeCalendar.
- Las clases runtime internas `DialogProvider` , `DrawerProvider` y
`PopoverProvider` dejan de exportarse desde los barrels publicos; los
wrappers siguen usandolas por import directo.
- `computeCommandScore` ya no se reexporta desde Command; el algoritmo vive
como `computeFuzzyScore` en `src/libs/strings` .
- `table-core` se mueve a `src/libs/datagrid` con su test.
- `form-core` se mueve a `src/libs/forms` , usa el Standard Schema comun de
`src/libs/standard-schema.ts` , elimina la copia local de Soma y anade tests
de dirty/touched/reset, issues y submit async.
- Inventario de Soma actualizado: ya no lista como planned componentes que
existen en el arbol activo.
- `SelectType` /`ScrollAlignment` y el resto de tipos publicos de componentes
salen de `types.ts` ; los barrels ya no exportan contratos desde
`*-provider.svelte.ts` .
- `Dismissal` y `SafePolygon` usan `uix.timers` cuando Soma lo tiene
disponible, con fallback nativo solo para uso standalone fuera de UIX.
- Cobertura nueva para Combobox: selección single/multiple, `inputValue` y
filtrado de items disabled.
- Cobertura nueva para DatePicker, DateRangePicker y TimePicker: registro
runtime, cierre controlado tras selección y escritura de sliders de hora al
valor compartido.
- Cobertura nueva para TimeRangePicker: valores por endpoint, sliders y cierre
al completar ambos extremos.
- Cobertura nueva para TimeRangeField: validación de rango y foco de label
via `ActiveDom` .
- Cobertura nueva para TimeField: validación, sync de segmentos 12h y commit
solo cuando los segmentos de tiempo renderizados estan completos.
- Correccion TimeField: el announcer se inicializa con `$effect` en vez de
`onMount()` dentro de la clase, y `datetime` separa
`areAllTimeSegmentsFilledDOM(...)` del helper de fecha.
- Cobertura nueva para DateRangeField: validación de rango y foco de label
via `ActiveDom` .
- Cobertura ampliada para DateFieldProvider: validación, sync de segmentos
date/time y commit solo cuando los segmentos renderizados estan completos.
- Correccion DateField: el announcer se inicializa con `$effect` en vez de
`onMount()` dentro de la clase.
- Cobertura nueva para VirtualList: cálculo de ventana, `scrollToIndex` y
compensación anti-jump.
- Correccion VirtualList: la compensación de mediciones dinámicas sobre
viewports internos pasa por `ActiveDom.scrollTo(...)` y usa
`scrollOffset + delta` como fuente reactiva.
- Cobertura nueva para VirtualGrid: cálculo de ventana 2D y `scrollToCell`
via `ActiveDom` .
- Cobertura nueva para NumberField: parsing localizable, teclado spinbutton,
triggers, props ARIA y scrubber.
- Correccion NumberField: el root expone `dir` efectivo (`prop -> prefs`) en
lugar del prop crudo.
- Cobertura nueva para FileUpload: aceptación/rechazo de ficheros, dropzone,
input oculto, items, progress, remove y clear.
- Cobertura nueva para ColorField: commit por segmentos, edición hex con
teclado, selector de formato, input oculto y foco de label via `ActiveDom` .
- Cobertura nueva para ColorPicker: helpers de canales, trigger/value/hidden,
area 2D, slider de canal y swatches con commit/cierre.
- Cobertura nueva para NavigationMenu: timers UIX de apertura/cierre,
enlace item/trigger/content, foco por teclado, list y link props.
- Cobertura nueva para TreeGrid: expansión, selección/rango, filas visibles
bajo ancestros colapsados, navegación, row/cell/header y expand trigger.
- Cobertura nueva para DropdownMenu: trigger open/close, scoping de items,
item select, checkbox/radio groups, submenu delayed/open y group/separator.
- Cobertura nueva para ContextMenu: apertura por `contextmenu` con anchor
virtual, scoping de items, item select, checkbox/radio, submenu delayed/open
y group/separator.
- Cobertura nueva para Menubar: coordinación de menús hermanos, hover-follow,
navegación horizontal entre triggers y cambio de menú desde content.
- Cobertura nueva para Listbox: props ARIA root, selección, navegación,
typeahead, indicador de item y grupos.
- Cobertura nueva para TreeView: expansión/selección, navegación root,
typeahead, props de ramas/hojas y partes auxiliares.
- Cobertura nueva para Accordion: modo single/multiple, eventos open/close
por item, navegación de triggers y props de header/content.
- Cobertura nueva para Checkbox: commits check/uncheck, estado indeterminate,
hidden input y sincronización con CheckboxGroup.
- Cobertura nueva para RadioGroup: roving tabindex, selección síncrona,
navegación con auto-select, hidden input y guardas readonly/disabled.
- Cobertura nueva para Switch: commit-toggle runtime, keyboard, hidden input,
integración con FieldProvider y thumb.
- Cobertura nueva para Toggle: commit-toggle runtime, attrs DOM via
`ActiveDom` , integración con FieldProvider y guardas readonly/disabled.
- Cobertura nueva para ToggleGroup: modos single/multiple, roving tabindex y
navegación de items saltando disabled.
- Cobertura nueva para Tabs: registro de trigger/content, activacion
automatic/manual, navegacion roving, fallback tab stop y partes
list/content/indicator.
- Cobertura nueva para Slider: contrato provider/range/thumb/tick,
snapping/clamping, drag pointer confirmado y teclado de thumb.
- Cobertura nueva para Progress y Meter: `data-value/data-min/data-max`
emitidos por morfo/runtime, estados derivados e indicador sincronizado.
- Cobertura nueva para Collapsible: refs cruzadas trigger/content, eventos
`expand/collapse` y guardas disabled.
- Cobertura nueva para Clipboard: copia via `uix.clipboard` , reset con
`uix.timers` , labels traducidos/override y errores `onError` .
- Cobertura nueva para Tooltip: delay/close con `uix.timers` , skip-delay
de grupo, focus/blur, disabled y partes trigger/content/arrow.
- Cobertura nueva para Field: wiring de partes/ARIA, input guardado por
disabled/readonly e integración con parent Form.
- Cobertura nueva para SearchField: props root/input/clear, input/submit/
clear, foco y OR-merge con Field.
- Cobertura nueva para Pagination: rangos/ellipsis, clamp reactivo, slice,
triggers prev/next, item selected y disabled global.
- Cobertura nueva para Breadcrumb: label/labelledby, separator, link current
con mirror al item y ellipsis decorativo/interactivo.
- Cobertura nueva para Toolbar: roving focus, focusin, group single/multiple
y separator.
- Cobertura nueva para Stepper: conteo/estado de steps, attrs runtime,
selección lineal/no lineal, teclado y prev/next/completed.
- Cobertura nueva para ScrollArea: medición de overflow, viewport,
visibilidad/timers de scrollbar, track click, thumb y corner.
- Cobertura nueva para Splitter: registro de paneles, clamp,
collapse/expand y resize por pointer/teclado con attrs ARIA/data.
- Cobertura nueva para PinInput: props del input oculto, merge con Field,
patrón/paste, completion y estado de celdas/caret.
- Cobertura nueva para RatingGroup: slider attrs, merge con Field,
half hover/click, clearable y teclado LTR/RTL.
- Cobertura nueva para TagGroup: labels/root grid, roving por DOM
renderizado, selección/removal, link y remove button.
- Cobertura nueva para Announce: alternancia polite/assertive, timers UIX,
regiones ARIA declarativas y uso standalone.
- Cobertura nueva para Feed: attrs APG feed/article/title, navegación
PageUp/PageDown, threads anidados y sentinel IntersectionObserver.
- Cobertura nueva para TagsInput: add/paste/blur, navegación de tags,
delete/clear triggers y props de input/control.
- Cobertura nueva para Editable: activación preview/trigger, foco via
`ActiveDom` , commit/cancel por teclado/blur y guards disabled/readonly.
- Cobertura nueva para AlertDialog: contratos action/cancel, labels
traducidos/override y cierre delegado al Dialog base.
- Cobertura nueva para Carousel: detección de slides, navegación por
trigger/teclado, props de partes e intervalos autoplay via `uix.timers` .
- Cobertura nueva para GridList: merge con Field, selección/rango básico,
navegación/typeahead, celdas focusables y checkbox de fila.
- Cobertura nueva para LinkPreview: delays open/close con `uix.timers` ,
touch guard, content hover/cancelClose y props Floating/Arrow.
- Cobertura nueva para Table: root/section/header/cell props desde
`$libs/datagrid` , selección de fila y disclosure `RowDetail` .
- Cobertura nueva para Form: submit inválido con foco via `ActiveDom` ,
attrs runtime y partes Submit/Reset/ErrorSummary sobre `$libs/forms` .
- Cobertura nueva para ToastProvider: viewport hotkey via `ActiveDom` ,
runtime por item, ARIA/parts, auto-dismiss y close action.
- Cobertura nueva para DragDrop: ruta de teclado start/nav/drop, filtros
`accept` , prevención de drag, cancel y preview.
- Validado por fase:
- `npm run check` -> 0 errores, 0 warnings.
- `npm run test` -> 233 archivos, 2242 tests OK.
- tests focales de Select/Popover/Toast/RangeCalendar -> 11 tests OK.
- tests focales Dialog/Drawer/Popover/Select -> 10 tests OK.
- `command-provider.svelte.test.ts` -> 2 tests OK.
- `$libs/datagrid/table-core.svelte.test.ts` -> 8 tests OK.
- `$libs/forms/form-core.svelte.test.ts` -> 3 tests OK.
- `combobox-provider.svelte.test.ts` -> 3 tests OK.
- tests focales DatePicker/DateRangePicker/TimePicker -> 7 tests OK.
- `time-range-picker-provider.svelte.test.ts` -> 3 tests OK.
- `time-range-field-provider.svelte.test.ts` -> 3 tests OK.
- `time-field-provider.svelte.test.ts` -> 3 tests OK.
- `date-range-field-provider.svelte.test.ts` -> 3 tests OK.
- `date-field-provider.svelte.test.ts` -> 7 tests OK.
- `virtual-list-provider.svelte.test.ts` -> 3 tests OK.
- `virtual-grid-provider.svelte.test.ts` -> 2 tests OK.
- `number-field-provider.svelte.test.ts` -> 4 tests OK.
- `file-upload-provider.svelte.test.ts` -> 4 tests OK.
- `color-field-provider.svelte.test.ts` -> 4 tests OK.
- `color-picker-provider.svelte.test.ts` -> 4 tests OK.
- `navigation-menu-provider.svelte.test.ts` -> 4 tests OK.
- `tree-grid-provider.svelte.test.ts` -> 4 tests OK.
- `dropdown-menu-provider.svelte.test.ts` -> 6 tests OK.
- `context-menu-provider.svelte.test.ts` -> 6 tests OK.
- `menubar-provider.svelte.test.ts` -> 4 tests OK.
- `listbox-provider.svelte.test.ts` -> 4 tests OK.
- `tree-view-provider.svelte.test.ts` -> 4 tests OK.
- `accordion-provider.svelte.test.ts` -> 4 tests OK.
- `checkbox-provider.svelte.test.ts` -> 4 tests OK.
- `radio-group-provider.svelte.test.ts` -> 4 tests OK.
- `switch-provider.svelte.test.ts` -> 5 tests OK.
- `toggle-provider.svelte.test.ts` -> 4 tests OK.
- `toggle-group-provider.svelte.test.ts` -> 4 tests OK.
- `tabs-provider.svelte.test.ts` -> 4 tests OK.
- `slider-provider.svelte.test.ts` -> 4 tests OK.
- `progress-provider.svelte.test.ts` + `meter-provider.svelte.test.ts`
-> 4 tests OK.
- `collapsible-provider.svelte.test.ts` -> 3 tests OK.
- `clipboard-provider.svelte.test.ts` -> 2 tests OK.
- `tooltip-provider.svelte.test.ts` -> 3 tests OK.
- `field-provider.svelte.test.ts` -> 3 tests OK.
- `search-field-provider.svelte.test.ts` -> 3 tests OK.
- `pagination-provider.svelte.test.ts` -> 3 tests OK.
- `breadcrumb-provider.svelte.test.ts` -> 3 tests OK.
- `toolbar-provider.svelte.test.ts` -> 3 tests OK.
- `stepper-provider.svelte.test.ts` -> 3 tests OK.
- `scroll-area-provider.svelte.test.ts` -> 3 tests OK.
- `splitter-provider.svelte.test.ts` -> 3 tests OK.
- `pin-input-provider.svelte.test.ts` -> 3 tests OK.
- `rating-group-provider.svelte.test.ts` -> 3 tests OK.
- `tag-group-provider.svelte.test.ts` -> 3 tests OK.
- `announce-provider.svelte.test.ts` -> 3 tests OK.
- `feed-provider.svelte.test.ts` -> 3 tests OK.
- `tags-input-provider.svelte.test.ts` -> 3 tests OK.
- `editable-provider.svelte.test.ts` -> 3 tests OK.
- `alert-dialog-provider.svelte.test.ts` -> 2 tests OK.
- `carousel-provider.svelte.test.ts` -> 3 tests OK.
- `grid-list-provider.svelte.test.ts` -> 3 tests OK.
- `link-preview-provider.svelte.test.ts` -> 2 tests OK.
- `table-provider.svelte.test.ts` -> 2 tests OK.
- `form-provider.svelte.test.ts` -> 2 tests OK.
- `toast-provider.svelte.test.ts` -> 2 tests OK.
- `drag-drop-provider.svelte.test.ts` -> 2 tests OK.
- guardia `*-provider.svelte.ts` sin test directo -> `NO_MISSING_PROVIDER_TESTS` .
- guardia `rg "from './.*provider\\.svelte'" src/uix/soma/components -g 'exports.ts'`
-> 0 resultados; Select ya no conserva el wrapper publico con nombre
`select-provider.svelte` .
- Commits nuevos empujados:
- `a3bcb66c` — `Refresh UIX audit follow-up docs`
- `25870b4e` — `Expand Soma component coverage`
- `e1a21269` — `Hide internal Soma provider classes from barrels`
- `4829ce13` — `Move command scorer to shared strings lib`
- `02c1fb43` — `Move table core to datagrid lib`
- `d319ec6b` — `Move form core to forms lib`
- `701f83d6` — `Document Soma coverage and domain lib split`
- `3050d273` — `Align Select public types and Soma inventory`
- `eaeebd69` — `Route Soma layer timers through UIX scheduler`
- `9fa00fa2` — `Move Soma public types out of providers`
- `05f87dc4` — `Add Combobox provider coverage`
- Auditoria UIX post-Soma/Eidos aplicada parcialmente:
- `SoundChannel` ya no usa `document.addEventListener/removeEventListener`
directamente para el unlock listener; consume una superficie DOM inyectada
compatible con `ActiveDom.listen(...)` y `ActiveDom.getDocument(...)` .
- Se rompe el ciclo type-only `sema/types.ts <-> sema-map.ts` moviendo ids,
signatures y overrides de canales a `src/uix/sema/channels.ts` .
- Se rompe el ciclo type-only de Floating moviendo `Side` , `Align` ,
`Boundary` , `SIDE_OPTIONS` y `ALIGN_OPTIONS` a
`src/uix/soma/layers/floating/placement.ts` .
- Tests iniciales añadidos para los puntos de mayor riesgo de Soma:
Dialog, Drawer, Command, Calendar y DateField.
- Validado:
- `npm run check` -> 0 errores, 0 warnings.
- `npx vitest run src/uix/sema src/uix/soma/layers/floating` -> 117 tests OK.
- `npx vitest run` focal de los 5 nuevos tests Soma -> 16 tests OK.
- Commits nuevos empujados:
- `802ebce6` — `Tighten sema channel and floating contracts`
- `c6d24eee` — `Add high-risk Soma provider tests`
- `Intent` queda como vocabulario unico en `src/uix/intent.ts` . No existen
alias `EidosIntent` , `UixIntent` , `ToastIntent` ni `SemaIntent` ; Sema usa
`IntentBinding` / `IntentPolicy` cuando necesita especializar el contrato
del evento, pero el intent canonico no pertenece a una capa concreta.
- `MorfoData` valida nombres `data-*` : solo acepta atributos publicos
lowercase kebab-case; `data-_*` queda reservado para estado privado del
provider y no puede declararse en morfo.
- `frontend` queda eliminado del arbol activo: no hay `src/arts/frontend` ,
factory `defineActiveFrontend` , alias `$frontend` , ruta `/active/docs/fend`
ni servicio `services.frontend` . Las referencias documentales restantes son
notas explicitas de retirada o usos genericos de la palabra frontend.
- `themeDimension(...)` y `densityDimension(...)` fueron retiradas del catalogo
publico de `$prefs` . Las preferencias visuales `theme/mode/density` son
entradas de `ActiveEidos` ; `prefs` mantiene solo dimensiones transversales o
custom via primitivas genericas.
- `SemaActiveChannel` fue eliminado. La unica fuente publica para canales es
`SemaChannelId` .
- Verificaciones ejecutadas despues de la retirada:
- `npm run check` -> 0 errores, 0 warnings.
- `npm run test` -> 165 archivos, 2002 tests OK.
- Commits nuevos empujados:
- `a4cbe0c0` — `Tighten intent and morfo contracts`
- `fbacd113` — `Remove frontend art`
- `68dd40ef` — `Remove visual prefs dimensions`
Actualizacion 2026-05-14:
- Revision post-cambios aplicada. La supuesta perdida de proyeccion cross-modal
queda resuelta como aclaracion de ownership: la proyeccion vive en
`arts/prefs` mediante `createActivePrefsDomProjection(...)` , no en
`ActiveUix` .
- Documentacion de ecosistema actualizada en `src/uix/*` y `src/arts/*` :
ownership de prefs/proyeccion/Eidos, naming canonico (`langs`, `events` ,
`active-app` , `storage` , `connection` , `session` , `cache` , `timer` ,
`logger` ) y marcas historicas en docs de diseno antiguas.
- Archivos documentales de revision retirados. Las conclusiones vigentes quedan
absorbidas por `src/uix/active_architecture.md` , los README de capa y
`src/uix/contracts.ts` .
- Limpieza Eidos CSS/runtime aplicada: `index.css` ya solo importa fonts,
`generated/base.css` , `archetypes.css` , `events.css` y recipes activas.
Se retiraron CSS historicos de `contracts/` , `themes/base/` ,
`tokens/motion.css` , `tokens/index.css` y los token files de componentes.
- Migracion Eidos recipe tokens aplicada: los aliases `--{component}-*`
viven en `EidosConfig.recipes` , el tema base los define en
`src/uix/eidos/lib/recipes/base.ts` , y `generated/base.css` los publica
desde `npm run generate:eidos-css` .
- Superficie de consulta de recipes aplicada: `ActiveEidos.listRecipes()` y
`getRecipeTokens(component)` exponen aliases para editores de theme sin
inspeccionar CSS ni devolver handles mutables del config interno.
- La shell `/uix` ya no carga fuentes remotas; reutiliza las fuentes locales
de Eidos (`Instrument Sans`, `Azeret Mono` ) para que las validaciones
Playwright no dependan de red externa.
- `src/uix/contracts.test.ts` ahora incluye guardias de regresion para que
`ActiveUix` no vuelva a bootear Soma/Eidos, los providers Soma no usen
`registerContract/registerPart` , y la shell `/uix` no escriba `prefs.theme` .
- Naming `langs` : constantes runtime y diagnosticos ya usan `langs` /
`langs.mono` ; se corrigieron menciones documentales residuales `[lang]` y
`lang.mono` .
- Contrato directo fuera de `ActiveUix` aclarado: `EngineSemantic` con visual
activo necesita `dom` o `projector` y falla con `SemaConfigError` si faltan;
`ADom` directo solo usa `disabledDom` cuando el caller lo pide.
- `src/arts/prefs/README.md` reescrito al modelo actual schema-based. Se
elimina la arquitectura historica de capabilities como guia principal; las
dimensiones visuales `theme/mode/density` pertenecen a `ActiveEidos` .
- `src/uix/morfo/README.md` actualizado: fija `translations` , `commonRef` ,
registro via `registerMorfo` y `soma.runtime(...)` como contrato vigente.
- `frontend` retirado como artefacto: no queda factory, alias ni ruta activa.
- Validacion global ejecutada: `npm run check` , tests focales UIX/arts y
`npm run build` pasan. Solo queda el warning de chunks grandes del build.
- Eidos general queda cerrado sin tocar componentes: no hay `EngineEidos` ,
wrapper `Eidos` , `eidos/engine` ni `eidos/core/headless` ; se anade guardia
de regresion en `contracts.test.ts` .
- `recipes` queda como `RecipeTokenSet` plano por decision: subir a tipo
estructurado solo cuando exista builder/consumer real que lo necesite.
- Commits nuevos empujados:
- `694eb5c5` — `Clarify prefs projection contract`
- `223cdf9e` — `Align sema docs with channel ownership`
- `3dc775f4` — `Update UIX architecture notes`
- `b1215549` — `Fix UIX docs theme and popover dismiss`
- `6da10987` — `Prune legacy Eidos CSS runtime`
- `d822597f` — `Generate Eidos recipe tokens from config`
- `65958538` — `Expose Eidos recipe token queries`
- `4233be62` — `Update UIX continuation notes`
- `2df58074` — `Use local fonts in UIX docs`
- `8ad04714` — `Refresh UIX architecture docs`
- `e2ba371b` — `Add UIX architecture regression guards`
- `71e05765` — `Align langs diagnostic wording`
- `607dfdbb` — `Clarify direct UIX service contracts`
- `475ac775` — `Refresh prefs architecture docs`
- `35958a49` — `Clarify morfo translation contract`
- `bd37e5dd` — `Clarify legacy frontend density docs`
- Validado de nuevo:
- `npx vitest run src/uix/contracts.test.ts src/arts/prefs/test/dom-projection.test.ts src/uix/active-uix/active-uix.svelte.test.ts src/uix/eidos/active-eidos.test.ts src/uix/soma/runtime.svelte.test.ts` -> 79 tests OK.
- `npx vitest run src/uix/sema/engine.test.ts src/uix/soma/runtime.svelte.test.ts` -> 48 tests OK.
- `npx vitest run src/uix/eidos/active-eidos-config.test.ts src/uix/eidos/generated-css.test.ts src/uix/eidos/active-eidos.test.ts src/uix/contracts.test.ts` -> 52 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- `npx vitest run src/uix/contracts.test.ts` -> 12 tests OK.
- `npm run check` tras wording `langs` -> 0 errores, 0 warnings.
- Playwright `/uix` : toggle dark actualiza `html[data-theme="base-dark"]` ,
`html[data-mode="dark"]` y mantiene `html[data-density="comfortable"]` ;
sin `pageerror` , sin errores de consola y sin `requestfailed` .
## Estado validado
- `ActiveUix` ya no crea ni conoce `Soma` ni `Eidos` .
- Solo `ActiveApp` y `createActiveUix(...)` standalone crean servicios compartidos.
- `attachActiveUix(app)` reutiliza servicios de `ActiveApp` y falla temprano si faltan `langs` o `dom` .
- El servicio runtime de traducciones se llama `langs` . No confundir:
- `prefs.language` alimenta `langs` .
- `prefs.locale` alimenta `format` .
- `prefs.direction` , `prefs.motion` , `prefs.sound` y `prefs.haptic` se
proyectan mediante `createActivePrefsDomProjection(...)` .
- `events` es el nombre publico del motor perceptivo en `ActiveUix` ; `semantic` queda solo como payload de `morfo.events[].semantic` .
- `ActiveEidos` queda aplanado: no existe engine visual separado ni directorio `engine` bajo Eidos.
- Los helpers de configuracion/render/persistencia de Eidos viven en `src/uix/eidos/lib` .
- `ActiveEidos` asume configuracion, validacion, contrato CSS, render, persistencia y scope visual.
- Shells UIX deben pasar modo/densidad visuales a `ActiveEidos` mediante
`modeSource` /`densitySource`; no escribir `prefs.theme` .
- Los componentes Eidos siguen congelados salvo orden explicita.
Validaciones ejecutadas en esta fase:
- `npx vitest run src/uix/eidos/active-eidos.test.ts src/uix/eidos/active-eidos-config.test.ts` -> 37 tests OK.
- `npx vitest run src/arts/adom/test/active-dom.test.ts src/uix/soma/runtime.svelte.test.ts src/uix/morfo/registry.test.ts src/uix/sema/resolver.test.ts src/uix/sema/chans/sound.test.ts src/uix/sema/chans/visual.test.ts src/uix/eidos/active-eidos.test.ts src/uix/eidos/active-eidos-config.test.ts src/uix/contracts.test.ts` -> 115 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
## Arquitectura acordada
La regla central queda asi:
```text
ActiveApp o ActiveUix standalone crean servicios.
ActiveUix expone servicios y prefs.
Morfo declara contrato y translations.
Soma consume ActiveUix/Soma scope y transcribe morfo al DOM via uix.dom.
Sema/events emite ocurrencias perceptivas; no debe inventar servicios.
ActiveEidos consume ActiveUix y resuelve config/tokens/CSS runtime.
Los componentes no crean servicios compartidos.
```
`portal` queda como preferencia/target generico de `ActiveUix` ; Soma lo adapta
a su `portalTo` . No usar nombres como `somaPortalTo` en `ActiveUix` .
## P1 cerrado
1. Ownership DOM P1 cerrado.
- Corregido: `TextSelection` ya escribe/restaura `user-select` via `ActiveDom.apply` .
- Corregido: announcers/live regions de Soma y descripciones ocultas de date/time
usan `ActiveDom.writeNode/writeText/removeNode` .
- Correcto: `ActiveUix` prefs, `SomaRuntime` , `VisualChannel` /`DomSignalProjector`
y `ActiveEidos` usan `ActiveDom` .
- Barrido P1 sin escrituras directas de produccion restantes; quedan lecturas DOM
y fixtures de tests.
2. Tabla de contratos minimos cerrada como codigo/tests:
`src/uix/contracts.ts` + `src/uix/contracts.test.ts` cubren `ActiveUix` ,
`SomaRuntime` , `EngineSemantic/events` , `ActiveEidos` y `Morfo` .
3. Sema queda purgado de las slices visuales `motion` , `color` y `presence` .
El mapa canonico resuelve solo `hold` , `sound` y `haptic` ; Eidos reacciona
visualmente a `data-event-*` y a sus propios tokens CSS.
4. Naming `langs` revisado en mensajes/docs/tipos principales. Quedan solo
usos tecnicos validos (`< script lang = "ts" > `, `v.langRef(...)` ) o menciones
historicas explicitas.
5. `attachActiveUix(app)` no crea sustitutos si faltan servicios requeridos.
6. `SoundChannel` ya no registra listeners globales en el constructor; prima
el contexto en `prepare()` solo cuando una senal sonora entra en el gesto.
7. `createActivePrefsDomProjection(...)` proyecta `dir` , `data-motion` ,
`data-sound` y `data-haptic` ; `ActiveEidos` proyecta `data-theme` ,
`data-mode` y `data-density` .
8. `SomaRuntime` , `registerMorfo` y `applyMapOverrides` tienen optimizaciones
basicas de churn/copia aplicadas.
9. `frontend` retirado; `ActiveApp` ya no puede declarar un servicio visual
shell heredado.
10. `themeDimension` /`densityDimension` retiradas; el catalogo `$prefs` no
ofrece dimensiones visuales UIX.
## Pendiente P2
1. Soma: la API canonica publica de parte es `runtime.part(...)` .
`registerContract(...)` ya no se llama desde Soma; `registerMorfo(...)` lo
registra todo. `createAttrs(...)` queda solo como helper tipado para
`querySelector` /tooling, no como mecanismo runtime.
2. Morfo: los atributos `data-*` con valor libre ya se modelan con
`emit: 'value'` ; `progress/meter` declaran `data-value` , `data-min` y
`data-max` en morfo y `SomaRuntime` lo cubre con test dedicado.
3. Morfo translations: mantener `translations` en el morfo, `commonRef` para
textos compartidos y `langs.ts` solo como constantes imperativas legacy.
4. Frontend/ActiveApp: cerrado. `frontend` no existe como artefacto activo ni
como servicio opt-in. Las preferencias transversales se proyectan desde
`arts/prefs` ; las visuales pertenecen a `ActiveEidos` .
5. ActiveApp docs: actualizado que `langs` , `dom` , `format` y `events` son
servicios opt-in; no hay servicio visual shell heredado.
## Eidos cerrado para modulo general
1. Primitivas visuales sin tocar componentes: `layout` ya queda incorporado
al `EidosConfig` con `containerWidth` , `containerPaddingInline` ,
`contentWidth` y `aspectRatio` , y se genera en CSS/contrato como
`--container-width-*` , `--container-padding-inline` , `--content-width-*`
y `--aspect-ratio-*` .
2. Mantener `EidosConfig` como authoring object persistible y CSS-only como
modo valido mediante `themeSource: 'css'` .
3. Density queda como primitive bridge: `scale` , `spaceScale` , `controlScale`
y `contentScale` para `compact` , `comfortable` , `spacious` ; `ActiveEidos`
proyecta `data-density` y Eidos publica aliases activos como
`--density-space-scale` .
4. `src/uix/eidos/generated/base.css` queda como primer artefacto CSS generado
desde `EidosConfig` base mediante `npm run generate:eidos-css` ; `index.css`
lo importa como foundation estatica.
5. Cerrado: los tokens per-component de las recipes activas quedan como
aliases estables y authorables en `EidosConfig.recipes` .
6. Los CSS historicos de `contracts/` y `themes/base/` quedan retirados del
arbol activo. El contrato se publica desde `ActiveEidos.getCssContract()` /
`renderContractCss()` y el base desde `generated/base.css` .
7. `tokens/` ya no forma parte del entrypoint estatico. Las recipes CSS
consumen los mismos custom properties, pero los valores salen de
`generated/base.css` .
8. `ActiveEidos.listRecipes()` y `getRecipeTokens(component)` exponen los
aliases para editores de theme sin leer CSS. El tipado plano de `recipes`
es intencional mientras no haya builder/consumer estructurado.
9. No reintroducir engine visual separado, carpeta `engine` , ni wrapper `Eidos` sin
contrato propio.
## Pendiente de limpieza
- Validacion navegador `/uix` cerrada despues de mover recipe tokens y retirar
fuentes remotas: carga sin `requestfailed` , sin errores de consola y el
toggle dark sigue aplicando `data-theme` , `data-mode` y estilos visuales.
- Siguiente foco autorizado: Eidos components. Empezar por auditoria Option C
contra `src/uix/eidos/components/README.md` ; no mezclar esa fase con runtime
general, `ActiveUix` , `ActiveEidos` ni Soma salvo que aparezca una
regresion concreta.
- Warnings de toast resueltos; `npm run check` queda en 0 errores / 0 warnings.
- No commitear logs temporales: `.codex-vite-dialog*.log` , `debug.log` , `md` .
- Antes de seguir con componentes, releer `src/uix/active_architecture.md` ,
`src/uix/active-uix/README.md` , `src/uix/eidos/README.md` ,
`src/uix/soma/README.md` y este archivo.