You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/continue.md

1907 lines
106 KiB

# Continue
Fecha de corte: 2026-05-19. Rama: `active-uix`.
## Guia vigente: migracion de componentes Soma -> Eidos
Objetivo: migrar componentes uno a uno desde Soma a Eidos sin crear una API
inferior a Air ni a las librerias de referencia, y sin romper fronteras de
capa. Esta es la guia que debe leerse antes de tocar cualquier componente.
### Flujo obligatorio por componente
1. Leer Air en la rama anterior:
`git show morfo-runtime:src/uix/air/components/{name}/...` cuando exista.
Air es la primera baseline visual local.
2. Leer Morfo/Soma actuales del componente:
- `src/uix/morfo/components/{name}.ts`
- `src/uix/soma/components/{name}/...`
- README y tests de Soma si existen.
3. Auditar Morfo/Sema antes de tocar Eidos:
- Clasificar el componente como pasivo, interactivo o mixto.
- Justificar explicitamente cualquier `0 events`. No se acepta por omision.
- Para cada accion de usuario real definir si debe existir evento semantico:
`family`, `verb`, `sequence`, `intent`, `target`, `prewrite` y `commit`.
- Verificar que Soma usa `runtime.trigger(...)` para esas acciones, no solo
callbacks locales (`onValueChange`, `onValueCommit`, etc.).
- No emitir eventos continuos por cada frame/pixel si el evento semantico es
el inicio, el commit o un cambio discreto.
4. Comparar con referentes externos oficiales relevantes:
Radix/Radix Themes, Ark UI, Bits UI, shadcn-svelte, React Aria, Base UI,
Vaul u otros solo si aplican al componente.
5. Crear o actualizar `src/uix/eidos/components/{name}/README.md` antes de
cerrar el componente. Debe incluir:
- baseline Air,
- tabla Soma/Morfo,
- tabla Morfo/Sema con eventos, targets y decisiones,
- tabla comparativa externa,
- decisiones explicitas,
- gaps con decision: implementar, diferir a Soma/Morfo, diferir a v2 o
descartar por no pertenecer a Eidos.
6. Solo despues tocar wrapper, recipe, tokens o contrato.
### Fronteras de capa
- Morfo declara partes, `data-*`, ARIA, eventos y translations.
- Soma posee comportamiento, estado, teclado, foco, formularios, portal,
floating, timers, imagenes, validacion y escrituras DOM headless via
`ActiveDom`.
- Sema/events posee ocurrencias perceptivas; no decide CSS ni tokens.
- Eidos posee wrapper visual, props visuales, recipe CSS, tokens y
documentacion visual.
- Morfo no se da por correcto por existir: cada componente nuevo o revisado
debe auditar si sus `events` representan bien la capa semantica. Componentes
pasivos como `progress`/`meter` pueden tener `0 events`; componentes
interactivos como `slider`, `pagination`, `rating-group`, `number-field` o
`search-field` requieren decision semantica explicita.
- Si una funcionalidad nueva necesita estado, ARIA, DOM imperative o lifecycle,
no se mete en Eidos: se define primero en Morfo/Soma.
- Si una parte publica aparece en Eidos, debe estar respaldada por Morfo/Soma
salvo que sea puramente visual y se documente como excepcion deliberada.
### API Eidos canonica
- Opcion C: root visual + partes attached en el namespace:
`import { Component } from '$uix/eidos/components/component'`.
- Sin `Provider` publico en Eidos.
- Sin APIs flat con snippets como alternativa paralela.
- Sin alias duplicados para compatibilidad: no hay compatibilidad hacia atras.
- Un solo entry mental por componente. No crear dos ficheros root para lo mismo.
- El root vive en `{name}.svelte`; partes en `{name}-{part}.svelte`.
- `index.ts` exporta named namespace y default del mismo namespace.
- Para single-part, el default/root es el componente completo y no se inventan
partes vacias.
- Dentro de wrappers Eidos, las partes de Soma se importan como namespace con
el nombre real del componente: `import * as Collapsible from
'$soma/components/collapsible'`, y se usan como
`<Collapsible.Provider>`, `<Collapsible.Trigger>`, etc.
- Prohibido en wrappers Eidos: `Parts`, `Base`, `SomaXxxProvider`, tags
sueltas `<Provider>`/`<Trigger>`/`<Content>` y cualquier alias `Root`.
### Naming y contratos
- No prefijar tipos con `Eidos` dentro del modulo del componente:
usar `FieldProps`, `FieldSize`, `FieldVariant`, etc.
- No usar nombres legacy `danger/success/warning/info`; el sistema usa
intents canonicos cuando aplica.
- No usar `--eidos-*`, `--soma-*`, `data-soma-*` ni marcadores privados de otra
capa en CSS Eidos.
- Los `data-*` publicos deben venir de Morfo o de props visuales Eidos
documentadas (`data-size`, `data-variant`, `data-color`, etc.).
- Si el CSS necesita un selector nuevo de estado/comportamiento, primero mirar
si debe declararse en Morfo/Soma.
- Los sizes son canonicos y responsive mediante `ResponsiveProp` +
`ActiveEidos.resolve(...)`. No inventar escalas locales sin razon.
- Las props visuales comunes deben mantenerse pequenas: normalmente `size`,
`variant`, `color`, `radius`, `orientation` solo cuando el componente lo
justifica.
### CSS y tokens
- Cada componente tiene `components/{name}/{name}.css` e import explicito en
`src/uix/eidos/index.css`.
- Los valores authorables viven en `THEME_BASE_RECIPE_TOKENS` y se publican en
`src/uix/eidos/generated/base.css` mediante `npm run generate:eidos-css`.
- No introducir colores raw, `font-size` literal en px/rem ni magic numbers si
deben ser tokens.
- El CSS de componente consume `var(--{component}-...)`; los valores salen del
config generado.
- No tocar `web/routes` ni demos salvo orden explicita.
### Decisions fijadas durante esta tanda
- `Popover.side="auto"` se descarta. Soma Floating usa `side` como preferencia
(`top/right/bottom/left`) y `avoidCollisions`/flip/shift resuelven el ajuste.
- `Field.RequiredIndicator` se define en Morfo/Soma antes de Eidos porque tiene
contrato publico y `aria-hidden`; Eidos solo renderiza el `*` por defecto.
- Air `Field.Error` se migra como `Field.ErrorText`, alineado con Soma/Morfo y
Ark UI. No se crea alias `Error`.
- Los comportamientos compartidos de imagen deben modelarse como
`ImageProvider`/provider headless reutilizable en Soma, no como helper suelto
en Eidos ni dentro de `layers`.
- Los tipos/utilidades de color compartidos pertenecen a `src/libs/color` si
tambien los consumen SIUM u otras capas; Soma no debe ser la libreria de
colores transversal.
- `Switch` conserva `Switch.Thumb` como parte publica, pero el root de Eidos
monta un thumb visual por defecto cuando no recibe children. Motivo:
`<Switch />` es el uso minimo documentado en la demo y no puede renderizar un
track vacio. No es una API flat paralela: el compound sigue siendo la forma
avanzada para sustituir el thumb o sus iconos.
### Verificacion minima antes de cerrar un componente
- Regenerar CSS si se tocan recipe tokens:
`npm run generate:eidos-css`.
- Ejecutar tests focales del componente Soma si se toca Morfo/Soma.
- Ejecutar:
- `node --import tsx/esm scripts/eidos-lint-all.ts`
- `npm run check`
- Ejecutar vitest focal:
`npx vitest run src/uix/eidos src/uix/morfo/compile.test.ts src/uix/morfo/schema.test.ts`
y anadir tests Soma concretos si hubo cambios de comportamiento.
- `npm run lint` no es fiable como validacion global ahora mismo: el repo tiene
deuda de formato previa y snippets legacy no parseables. Formatear solo los
archivos tocados con `npx prettier --write ...`.
### Estado actual de la tanda Eidos
- Ultimo componente corregido/verificado: `FileUpload` demo.
- Correccion/demo 2026-05-19:
- Anadio ruta `web/routes/uix/components/file-upload/+page.svelte` siguiendo
`web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`.
- La demo incluye tabs `Live`, `API`, `Morfo`, `Sema`, `Recipe`, `A11y`,
traza por `MutationObserver`, botones Play de Sema y pasos
`data-perm-step` para `remove -> clear`.
- No se instrumenta el boton que abre el picker nativo porque bloquearia las
pruebas automaticas; el evento `trigger-picker` queda cubierto en el tab
Sema mediante Play.
- `web/routes/uix/+layout@.svelte` registra `fileUploadSema` y anade la
entrada de navegacion `File upload`.
- Bug real corregido en `Eidos FileUpload`: el root ahora declara
`files = $bindable([])` y reenvia `bind:files` a Soma.
- Bug real corregido en `Eidos FileUpload.Item`: el snippet argumentado ya no
usa `children` como nombre local; usa `bodyContent`.
- Bug real corregido en `Eidos FileUpload.ItemName` e `ItemSize`: si el
consumidor no pasa children, el wrapper ya no inyecta un snippet vacio que
anulaba el fallback de Soma (`file.name` y `formatBytes(file.size)`).
- Bug de contrato corregido en `Morfo FileUpload`: `ItemPreview.data-type`
pasa a ser opcional porque la prop `type` de Soma es un filtro opcional y
no se emite cuando no se usa.
- Validado despues de `FileUpload` demo:
- `npm run check` -> 0 errores, 0 warnings.
- `SMOKE_SCOPE=/uix/components/file-upload npm run smoke` -> ruta OK.
- `npm run morfo:check` -> `file-upload` PASS; 29 rutas validadas,
38/67 morfos sin demo.
- `npm run perm:check` -> `file-upload` PASS; baseline elimina y limpia;
disabled queda pasivo; 17 demos instrumentadas OK.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> `file-upload`
invalid 0. Persisten solo hotspots conocidos de `progress`/`meter` por
`data-shape='circular'`.
- Navegador integrado: ruta carga sin errores de consola, monta root,
dropzone, trigger, list, dos items, dos progress bars, seis tabs y Sema
muestra cinco botones Play.
- Todos los componentes presentes hoy en `src/uix/eidos/components` salvo
`svg` tienen ruta demo en `web/routes/uix/components`.
- Ultimo componente corregido/verificado antes de esta demo: `TagsInput` demo.
- Correccion/demo 2026-05-19:
- Anadio ruta `web/routes/uix/components/tags-input/+page.svelte` siguiendo
`web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`.
- La demo incluye tabs `Live`, `API`, `Morfo`, `Sema`, `Recipe`, `A11y`,
traza por `MutationObserver`, botones Play de Sema y pasos
`data-perm-step` para `type delimiter -> remove -> clear`.
- `web/routes/uix/+layout@.svelte` registra `tagsInputSema` y anade la
entrada de navegacion `Tags input`.
- Bug real corregido en `Eidos TagsInput`: el root ahora declara
`value = $bindable([])` e `inputValue = $bindable('')`, reenviando ambos
estados bindables a Soma.
- Validado despues de `TagsInput` demo:
- `npm run check` -> 0 errores, 0 warnings.
- `SMOKE_SCOPE=/uix/components/tags-input npm run smoke` -> ruta OK.
- `npm run morfo:check` -> `tags-input` PASS; 28 rutas validadas,
39/67 morfos sin demo.
- `npm run perm:check` -> `tags-input` PASS; baseline e invalid escriben,
eliminan y limpian; disabled/readonly quedan pasivos; 16 demos
instrumentadas OK.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> `tags-input` invalid 0.
- Navegador integrado: tags visibles, input presente, Sema con cuatro eventos
y sin errores de consola.
- Ultimo componente corregido/verificado antes de esta demo: `Editable` demo.
- Correccion/demo 2026-05-19:
- Correccion/demo 2026-05-19:
- Anadio ruta `web/routes/uix/components/editable/+page.svelte` siguiendo
`web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`.
- La demo incluye tabs `Live`, `API`, `Morfo`, `Sema`, `Recipe`, `A11y`,
traza por `MutationObserver`, botones Play de Sema y pasos
`data-perm-step` para `Edit -> type draft -> Save`.
- `web/routes/uix/+layout@.svelte` registra `editableSema` y anade la
entrada de navegacion `Editable`.
- Bug real corregido en `Eidos Editable`: el root ahora declara
`value = $bindable('')` y `editing = $bindable(false)`, reenviando ambos
estados bindables a Soma.
- Bug real corregido en `Eidos Editable.Preview`: si el consumidor no pasa
children, el wrapper ya no inyecta un snippet vacio que anulaba el fallback
`state.displayValue` de Soma.
- Correccion posterior de arquitectura: `Editable` no debe parecer un
`Field/Input` permanente. La baseline real de la rama anterior esta en
`src/uix/terra/editable` (no en Air components) y plantea contenido inline
editable.
- `Morfo/Soma Editable` anade `Control` para agrupar acciones. Los triggers
ya no fuerzan `hidden`; Soma expone `data-editing`, `data-disabled` y
`data-readonly`, y Eidos decide visualmente si muestra `Edit` o
`Save/Cancel`.
- La receta Eidos de `Editable` vuelve a preview inline: caja sutil solo en
hover/focus o al entrar en edicion. Si se quiere una caja permanente debe
usarse `Field`/`Input`.
- Validado despues de `Editable` demo:
- `npm run check` -> 0 errores, 0 warnings.
- `SMOKE_SCOPE=/uix/components/editable npm run smoke` -> ruta OK.
- `npm run morfo:check` -> `editable` PASS; 27 rutas validadas,
40/67 morfos sin demo.
- `npm run perm:check` -> `editable` PASS; baseline edita, escribe y guarda;
disabled/readonly quedan pasivos; 15 demos instrumentadas OK.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> `editable` invalid 0.
- Navegador integrado: preview muestra el valor inicial, input oculto en
preview y sin errores de consola.
- Ultimo componente corregido/verificado antes de esta demo: `Stepper` demo.
- Correccion/demo 2026-05-19:
- Correccion/demo 2026-05-19:
- Anadio ruta `web/routes/uix/components/stepper/+page.svelte` siguiendo
`web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`.
- La demo incluye tabs `Live`, `API`, `Morfo`, `Sema`, `Recipe`, `A11y`,
traza por `MutationObserver`, botones Play de Sema y pasos
`data-perm-step` que avanzan hasta `commit-complete`.
- `web/routes/uix/+layout@.svelte` registra `stepperSema` y anade la entrada
de navegacion `Stepper`.
- Bug real corregido en `Eidos Stepper`: el root ahora declara
`value = $bindable(0)` y reenvia `bind:value` a Soma, tal como prometia
su API documentada.
- Bug real corregido en `Eidos Stepper.Item` y `Stepper.Indicator`: los
snippets argumentados `{ state }` ya no usan `children` como nombre local,
evitando la recursividad/`undefined is not a function` vista en SSR.
- Validado despues de `Stepper` demo:
- `npm run check` -> 0 errores, 0 warnings.
- `SMOKE_SCOPE=/uix/components/stepper npm run smoke` -> ruta OK.
- `npm run morfo:check` -> `stepper` PASS; 26 rutas validadas,
41/67 morfos sin demo.
- `npm run perm:check` -> `stepper` PASS; baseline, RTL y vertical avanzan
los tres pasos hasta completar; 14 demos instrumentadas OK.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> `stepper` invalid 0.
- Navegador integrado: ruta carga sin errores de consola, seis tabs y Sema
muestra dos eventos con Play.
- Ultimo componente corregido/verificado antes de esta demo: `TagGroup` demo.
- Correccion/demo 2026-05-19:
- Anadio ruta `web/routes/uix/components/tag-group/+page.svelte` siguiendo
`web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`.
- La demo incluye tabs `Live`, `API`, `Morfo`, `Sema`, `Recipe`, `A11y`,
traza por `MutationObserver`, botones Play de Sema y pasos
`data-perm-step` para seleccionar y eliminar un tag.
- `web/routes/uix/+layout@.svelte` registra `tagGroupSema` en el shell de
docs y anade la entrada de navegacion `Tag group`.
- Bug real corregido en `Eidos TagGroup`: el root ahora declara
`value = $bindable([])` y reenvia `bind:value` a Soma, tal como prometia
su API documentada.
- Bug real corregido en `Eidos TagGroup.Item`: el snippet argumentado ya no
usa `children` como nombre local; usa `bodyContent` para evitar la
recursividad/`undefined is not a function` vista en SSR.
- Validado despues de `TagGroup` demo:
- `npm run check` -> 0 errores, 0 warnings.
- `SMOKE_SCOPE=/uix/components/tag-group npm run smoke` -> ruta OK.
- `npm run morfo:check` -> `tag-group` PASS; 25 rutas validadas,
42/67 morfos sin demo.
- `npm run perm:check` -> `tag-group` PASS; baseline selecciona y elimina,
variante disabled queda pasiva; 13 demos instrumentadas OK.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> `tag-group` invalid 0.
- Navegador integrado: ruta carga sin errores de consola, seis tabs, Sema
muestra cuatro eventos y Recipe lista selectors morfo/eidos esperados.
- Ultimo componente corregido/verificado antes de esta demo: `Switch`.
- Correccion 2026-05-19:
- `Soma SwitchThumb` expone `{ checked }` al snippet del thumb.
- `Eidos Switch` monta `SwitchThumb` por defecto si el root no recibe
children.
- `Eidos SwitchThumb` pinta `SvgCheck` por defecto cuando `checked=true`.
- Bug corregido: recursividad accidental de snippets en
`switch-thumb.svelte`, que provocaba `500` en `/uix/components/switch`.
- Token anadido: `--switch-thumb-icon-color`, publicado desde
`THEME_BASE_RECIPE_TOKENS` y regenerado en `generated/base.css`.
- Validado despues de la correccion de `Switch`:
- `npx vitest run src/uix/soma/components/switch/switch-provider.svelte.test.ts src/uix/eidos/component-visual-attrs.test.ts src/uix/eidos/recipe-css-contract.test.ts`
-> 3 archivos, 12 tests OK.
- `npm run check` -> 0 errores, 0 warnings.
- Navegador `/uix/components/switch`: status 200; el switch monta thumb,
cambia a `checked` y renderiza `svg[data-svg="check"]` dentro del thumb.
- Ultimo componente cerrado antes de esta correccion: `Field`.
- `Field` anadido en Eidos con `Label`, `RequiredIndicator`, `Control`,
`Input`, `HelperText`, `ErrorText`, `Prefix` y `Suffix`.
- `RequiredIndicator` anadido a Morfo/Soma y cubierto por test del provider.
- Validado despues de `Field`:
- `npx vitest run src/uix/soma/components/field/field-provider.svelte.test.ts src/uix/morfo/compile.test.ts src/uix/morfo/schema.test.ts src/uix/eidos`
-> 11 archivos, 129 tests OK.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> 0 invalid.
- `npm run check` -> 0 errores, 0 warnings.
- Siguiente componente recomendado: iniciar la tabla previa de uno de los
componentes grandes aun no migrados a Eidos (`select`, `combobox`,
`calendar`, `date-field`, `date-picker`, `date-range-picker`, `time-field`,
`time-picker`). Antes de tocar codigo, comparar Air si existe, Soma/Morfo y
referencias externas, y decidir gaps reales.
### Archivos temporales
- No commitear logs temporales:
`.codex-vite-*.log`, `.codex-vite-*.err.log`,
`.codex-taggroup-dev.*.log`, `debug.log`, `md`.
## Corte para continuar manana
- Rama `active-uix` queda con la tanda Soma -> Eidos commitada por fases.
- No se tocaron demos ni rutas; el trabajo fue en `src/uix/eidos/components`,
`src/uix/eidos/lib/recipes/base.ts`, `src/uix/eidos/index.css`, CSS generado
y documentacion.
- Validacion de la ultima tanda:
- `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.
- Regla nueva para continuar Eidos componente por componente:
- La primera referencia es Air en la rama anterior
(`morfo-runtime:src/uix/air/components/{name}`) cuando exista.
- Despues se compara con Soma/Morfo actuales y con referentes externos
relevantes (Radix/Radix Themes, Ark UI, Bits UI, shadcn-svelte y React Aria
si aplica).
- Cada componente Eidos debe tener tabla en `components/{name}/README.md`
con gaps y decisiones antes de tocar wrapper/recipe/tokens.
- Objetivo: no dejar Eidos por debajo de Air ni de las plataformas de
referencia en funcionalidades reales.
- Primer componente auditado con el nuevo protocolo:
- `Dialog`: comparado contra Air, Radix, Ark UI, Bits UI y shadcn-svelte.
- Decision: no se crea `Dialog.Positioner`; `Content.position` cubre esa
responsabilidad visual sobre la grid canonica 3x3.
- Decision: se anaden overrides visuales `width`, `minWidth`, `maxWidth`,
`height`, `minHeight`, `maxHeight` en `Dialog.Content`, serializados como
variables privadas del recipe. Soma sigue siendo dueno de comportamiento.
- Segundo componente auditado con el nuevo protocolo:
- `Drawer`: comparado contra Air (`morfo-runtime`), Soma/Morfo actuales, Vaul,
shadcn-svelte y Ark UI Dialog como referencia de dialog/layer.
- Decision: no se crea `Drawer.Positioner`; la geometria edge-anchored vive
en `data-side` + `data-variant` y en la receta.
- Decision: no se implementa `shouldScaleBackground` de Vaul en Drawer local;
es un efecto global sobre el wrapper de app y requiere contrato de shell.
- Decision: se anaden overrides visuales `width`, `minWidth`, `maxWidth`,
`height`, `minHeight`, `maxHeight` en `Drawer.Content`, serializados como
variables privadas del recipe. El size canonico `sm/md/lg/full` sigue como
preset principal.
- Tercer componente auditado con el nuevo protocolo:
- `Popover`: Air no tenia equivalente en `morfo-runtime`, por tanto la referencia
local pasa a ser Soma/Morfo y la comparativa externa Radix, Ark UI, Bits UI
y shadcn-svelte.
- Decision: no se crea `Popover.Positioner`; la posicion pertenece a Soma
Floating y Eidos solo consume `data-side`, `data-align` y variables CSS.
- Decision: no se crean `Popover.Title`/`Description` hasta que exista caso
real; Popover suele contener UI arbitraria y el etiquetado puede vivir en
contenido consumidor.
- Decision: se anaden `matchAnchorWidth`, `width`, `minWidth`, `maxWidth`,
`height`, `minHeight`, `maxHeight` en `Popover.Content`, serializados como
variables privadas. La receta usa transform-origin y available-height de
Soma Floating.
- Cuarto componente auditado con el nuevo protocolo:
- `Tooltip`: Air no tenia equivalente en `morfo-runtime`; referencia local
Soma/Morfo, comparativa externa Radix, Ark UI, Bits UI y shadcn-svelte.
- Decision: no se crea `Tooltip.Positioner` ni `Tooltip.ArrowTip`; Soma
Floating y Soma Arrow son los duenos de esa geometria.
- Decision: se anaden `matchAnchorWidth`, `width`, `minWidth`, `maxWidth`,
`height`, `minHeight`, `maxHeight` en `Tooltip.Content`, serializados como
variables privadas. La receta usa transform-origin y available-height de
Soma Floating.
- Decision: se alinea Soma con Radix/Bits: el tooltip cierra al activar/clicar
el trigger por defecto. `disableCloseOnTriggerClick` queda como escape hatch
en `Tooltip.Group` y `Tooltip`.
- Componentes Eidos nuevos desde Soma:
- `meter`
- `progress`
- `slider`
- `pagination`
- `rating-group`
- `search-field`
- `number-field`
- `breadcrumb`
- Siguiente decision antes de seguir migrando:
- Continuar con componentes de riesgo bajo/medio (`field`, `toolbar`,
`tag-group`) o parar a definir una tabla de migracion por componente para
los grandes (`select`, `combobox`, `calendar`, `date-field`).
- Para cada componente nuevo conviene escribir primero: partes Soma,
props visuales Eidos, `data-*` que estampa el wrapper, tokens de recipe y
attrs morfo-backed que consumira el CSS.
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.
- Sexta tanda del mismo bloque:
- `NumberField`: root visual `number-field.svelte`, partes `Input`,
`IncrementTrigger`, `DecrementTrigger`, `Scrubber`, `number-field.css`,
`types.ts` e `index.ts`.
- El wrapper conserva formato/parseo/spinbutton/scrub de Soma y solo anade
`size`.
- La receta cubre contenedor, input, triggers, scrubber, focused, scrubbing,
invalid y disabled.
- Validado despues de `NumberField`:
- `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.
- Septima tanda del mismo bloque:
- `Breadcrumb`: root visual `breadcrumb.svelte`, partes `List`, `Item`,
`Link`, `Separator`, `Ellipsis`, `breadcrumb.css`, `types.ts` e `index.ts`.
- El wrapper conserva semantica, current item/link, ellipsis interactivo y
ARIA de Soma; Eidos solo anade `size`.
- La receta consume `data-current` y `data-interactive` declarados por Morfo
y define tokens para gaps, tipografia, links, separador, ellipsis, foco y
transiciones.
- Validado despues de `Breadcrumb`:
- `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 `field`, `toolbar` o `tag-group`.
- 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.
## Actualizacion 2026-05-20
- Se releyo la guia vigente de demos (`web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`)
y se contrasto contra el estado real de `src/uix/eidos/components`.
- Auditoria `src/uix/kimi-audit-eidos.md` aplicada sobre demos/componentes Eidos:
- `date-field` ya tiene README y demo.
- `svg` ya tiene README y queda documentado como primitiva interna sin ruta demo.
- Todas las demos routadas de Eidos tienen las seis tabs canonicas:
`Live`, `API`, `Morfo`, `Sema`, `Recipe`, `A11y`.
- Los demos con eventos tienen `MutationObserver` de `data-event` y botones
`Play` en la tab Sema; los demos 0-event mantienen tab Sema con estado vacio
justificado en su README.
- Los snippets de demos usan `.filter(Boolean)` y no renderizan props falsas.
- Se elimino la tab extra `Gallery` de `Icon`.
- `Checkbox` y `RadioGroup` vuelven a tener `<div data-uix-canvas-inner>` como
primer nodo de la demo.
- `Field`, `NumberField`, `SearchField`, `Slider` y `DateField` tienen tabla
Recipe con selectores clasificados como `morfo` / `eidos`.
- Guardias/correcciones colaterales cerradas:
- `NumberField` usa `ActiveTimers` en `SpinPressRepeater`.
- `SearchField` no registra listeners locales imperativos innecesarios.
- `RatingGroup` usa la key `components.rating-group.value-text`.
- `Field`, `NumberField`, `SearchField` y `Editable` consumen tokens recipe
declarados; `layout-column-gap` queda publicado en el tema base.
- Validacion ejecutada tras esos cambios:
- `npm run check` -> 0 errores, 0 warnings.
- `npm run test` -> 238 archivos, 2335 tests OK.
- `npm run morfo:check` -> 32 demos routadas PASS.
- `node --import tsx/esm scripts/eidos-lint-all.ts` -> invalid=0.
- `SMOKE_SCOPE=/uix/components npm run smoke` -> 32 rutas OK.
- Estado actual de Eidos components:
- Todos los directorios Eidos tienen README.
- Todos los componentes visuales Eidos tienen demo routada salvo `svg`, que es
primitiva interna documentada.
- No se detectan `data-soma-*`, `--soma-*` ni `--eidos-*` en CSS/componentes
Eidos fuera de tests/guardias documentales.
- Siguiente foco:
1. Continuar migracion componente por componente desde Soma a Eidos.
2. Seguir el protocolo obligatorio: Air (`morfo-runtime`) -> Morfo/Soma ->
Morfo/Sema -> referencias externas -> README -> wrapper/recipe/demo.
3. La tanda en curso venia por componentes relacionados con forms; el primer
candidato natural no presente aun en Eidos es `form`.
- No commitear logs temporales ni auditorias sueltas:
`.codex-*.log`, `.codex-*.err.log`, `debug.log`, `md`,
`src/uix/kimi-audit-eidos.md`.
### Correccion de convencion Eidos -> Soma 2026-05-20
- Se corrigio la deriva introducida en wrappers Eidos: no usar `Parts`,
`Base`, `SomaXxxProvider`, `Root` ni tags sueltas para referirse a Soma.
- Convencion obligatoria documentada:
- import interno: `import * as Nombre from '$soma/components/nombre'`;
- uso interno: `<Nombre.Provider>`, `<Nombre.Trigger>`,
`<Nombre.Content>`, etc.;
- API publica Eidos: `<Nombre>`, `<Nombre.Trigger>`, etc.; sin
`<Nombre.Provider>` publico.
- Componentes ajustados en esta correccion: `combobox`, `select` y `form`.
Los errores concretos eran imports namespace correctos pero tags sin prefijo
(`<Input>`, `<Trigger>`, `<Content>`, `<Submit>`, `<Reset>`,
`<ErrorSummary>`).
- `Soma Form.Provider` ahora tipa sus atributos DOM con
`PrimitiveFormAttributes` en vez de `HTMLFormAttributes` crudo. Motivo:
`HTMLFormAttributes.children?: Snippet<[]>` chocaba con el snippet
argumentado `children(snippetProps)` de `WithChild<..., FormProviderSnippetProps>`.
- Documentacion actualizada:
- `src/uix/eidos/components/README.md`: patron interno obligatorio y formas
prohibidas;
- `src/uix/eidos/README.md`: consumo de Soma mediante namespace, sin aliases;
- `src/uix/soma/COMPONENT_GUIDE.md`: regla de atributos HTML primitivos para
evitar choques de `children`.
- Validacion ejecutada:
- `npm run check` -> 0 errores, 0 warnings.
- Guardia manual:
`rg "import \\* as Parts|<Parts\\.|</Parts\\.|<Provider\\b|</Provider>|import \\{ Provider \\}|Provider as Soma|Soma[A-Za-z0-9]+Provider|\\b[A-Za-z0-9]+Base\\b" src/uix/eidos/components -g "*.svelte" -g "*.ts"`
-> sin resultados.
### Correccion Form demo / SIUM 2026-05-20
- `Form` demo creado en `web/routes/uix/components/form/+page.svelte` y
registrado en el sidebar `/uix` junto con `formSema`.
- La demo cubre dos modos:
- manual: `Form + Field` con `createForm` y SIUM;
- auto: `Form.AutoFields` leyendo el AST SIUM.
- Correccion importante: el submit de `$libs/forms/createForm` espera la
validacion Standard Schema asincrona antes de llamar `onValidSubmit`. SIUM
expone `~standard.validate` como async, por lo que el submit no puede
decidir con un placeholder sincronico.
- Validacion en tiempo real:
- el modo visible de la demo es `validationBehaviour: 'onChange'`;
- `onChange` no se llama `onTime`;
- los defaults iniciales de la demo deben ser validos para no pintar todos
los campos como invalidos al montar;
- si una demo quiere mostrar estado inicial invalido, debe documentarlo
explicitamente.
- Regla nueva para demos:
- los snippets son contrato, no decoracion;
- schema, imports, validators, defaults y campos visibles deben coincidir con
el preview;
- no se permite que el preview valide `age` mientras el snippet solo declare
`fullName/email`;
- si el snippet es minimo, debe estar marcado como ejemplo minimo separado,
no como snippet del preview.
- Documentacion actualizada para no repetir los errores:
- `web/routes/uix/lib/DEMO_AUTHORING_GUIDE.md`: seccion `Snippet parity is
mandatory`;
- `src/uix/eidos/components/README.md`: reglas especificas para demos de
formularios y snippets schema-driven;
- `src/uix/eidos/components/form/README.md`: ejemplo con `age`, defaults
validos y `validationBehaviour: 'onChange'`;
- `src/uix/soma/components/form/README.md`: `validationBehaviour` actualizado
a `progressive | onSubmit | onBlur | onChange`, default `progressive`.
- Validacion ejecutada despues de la correccion:
- `npm run check` -> 0 errores, 0 warnings.
- `npx vitest run src/libs/forms/form-core.svelte.test.ts` -> 4 tests OK.
- `SMOKE_SCOPE=/uix/components/form npm run smoke` -> ruta OK.
uix: date-picker + date-range-picker components + component audit infra Two new Eidos components shipped end-to-end (wrapper + recipe + demo + Soma provider hardening) plus a checklist-driven audit pipeline that scores all 67 morfo components against doctrinal completion criteria. New components: - date-picker: full popover-anchored picker over date-field + calendar, with calendar/content/trigger parts and demo route. - date-range-picker: standalone wrapper with own calendar/grid/segment surface, demo route, and recipe CSS. - Both wrappers follow Option C disciplined (root + parts attached via explicit assignment, no Object.assign). Supporting Soma changes: - range-calendar provider tightened (211 LOC of behavior, 167 LOC of tests), README brought up to component doctrine. - date-field, date-picker, date-range-field, date-range-picker Soma providers + READMEs updated for new wrappers. - popover provider/close gain props needed by the picker wrappers. Morfo updates: - date-picker / date-range-picker / range-calendar morfos refined for the new APIs (parts, events, ARIA). Audit infrastructure (new): - src/uix/COMPONENT_COMPLETION_CHECKLIST.md — 81 doctrinal rules across morfo / eidos wrapper / recipe CSS / demo / README / cross-layer scripts. Each rule keyed to active_architecture.md, GUIA_IMPLEMENTACION and DEMO_AUTHORING_GUIDE. - scripts/component-audit.ts + `npm run component:audit` — regex parser over all 67 components, emits tmp/component-audit.md with summary scoreboard + per-component findings. Validates against canonical SEMA_FAMILIES / SEMA_VERBS / ARCHETYPE_VOCABULARY / INTENTS. - Initial baseline: 1 PASS, 64 NEEDS-WORK, 2 BROKEN (tooltip, date-range-picker). Top systemic gaps: translations.label (49), README Gaps/Comparativa/Baseline sections (87 combined), keyboard /event ratio under-declaration (15), apg URL absent (19). Misc: - src/uix/kimi-audit-eidos.md — supplementary audit notes. - .gitignore: ignore .codex-* agent scratch artifacts at repo root. - continue.md + READMEs updated through the migration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### Incidencia DateField / DatePicker / DateRangePicker 2026-05-20
Estado: el usuario prescindio de Codex en este punto. Motivo operativo: el
trabajo de DateField, DatePicker y DateRangePicker no siguio con suficiente
disciplina el contrato acordado para UIX: comparar primero contra
`morfo-runtime`, Air/Terra y frameworks de referencia, cerrar Morfo/Soma antes
de Eidos/demo, y verificar visualmente el comportamiento real.
Desarrollos hechos por Codex durante esta tanda:
- Se crearon/modificaron wrappers y rutas demo Eidos para `date-picker` y
`date-range-picker`, con controles de min/max, meses visibles, segmentos,
navegacion, popup y snippets.
- Se tocaron demo/README de `date-field` alrededor de `granularity`,
`hourCycle`, segmentos readonly, min/max y validacion.
- Se refactorizo parte del dominio compartido de fechas entre calendar,
date-picker, range-calendar y date-range-picker.
- Se intento corregir `RangeCalendar` con validacion min/max, `activeAnchor`,
limpieza parcial de endpoints, `preventDeselect`, limites de longitud y
eventos `commit-start`, `commit-range`, `commit-clear` y `shift-navigate`.
- Se empezo a adaptar `Popover.Close` para acciones de picker modal
(`select`/`close`) y boton de borrado, pero el trabajo no quedo cerrado ni
verificado.
- Se anadieron entradas Morfo/Sema parciales para date picker/range picker y
range calendar, pero el contrato quedo incompleto respecto a la superficie
DOM real.
Errores y problemas no resueltos:
- `DateField` expuso controles confusos: `hourCycle` aparecio sin estar
justificado en la demo y `granularity="hour"` podia mostrar segundos
(`second: 10`), lo que contradice el control visible.
- `DatePicker` y `DateRangePicker` quedaron visualmente por debajo de la
referencia: popup mal posicionado, modo de uno/dos meses con espacios
incorrectos, separacion insuficiente entre meses y verificaciones visuales
incompletas.
- El popup debia poder desplegarse hacia la izquierda del boton cuando el
espacio lo exigiera; la demo no lo resolvio de forma fiable.
- En `RangeCalendar` / `DateRangePicker`, al seleccionar fecha final en el
segundo mes el calendario podia desplazarse al mes siguiente. Ese
comportamiento solo tendria sentido al elegir fecha inicial, no al cerrar el
rango.
- Al deseleccionar una fecha final se podia limpiar tambien la fecha inicial;
la accion correcta es resetear solo el endpoint afectado.
- Con limites de rango, seleccionar por ejemplo el 30 de mayo habilitaba un
intervalo inesperado hasta el 9 de junio, senal de que `maxDays` y los
limites de calendario no estaban explicados ni validados de forma usable.
- La fecha inicial y final no se distinguian visualmente con suficiente claridad
en el calendario.
- Los controles `start segments`, `end segments` y `paged nav` estaban en la
demo aunque su efecto no era visible o no estaba explicado por el preview.
- Se menciono "0 eventos" o ausencia de Sema en wrappers compuestos, y se uso
el README interno como justificacion. Eso fue incorrecto: aunque el wrapper
no posea toda la logica, la demo publica debe documentar la superficie
compuesta y los eventos observables.
- El componente y la demo usaron o dependieron de `data-calendar-*` /
`data-range-calendar-*` que no estaban declarados con la cobertura necesaria
en Morfo. No se puede cerrar un componente si el morfo no declara ni la decima
parte de la superficie real.
Bloqueo de handoff:
1. No continuar desde estos cambios como si estuvieran cerrados.
2. Auditar `DateField`, `Calendar`, `RangeCalendar`, `DatePicker`,
`DateRangeField` y `DateRangePicker` contra `morfo-runtime` (`air` /
`terra`) y React Aria, Ark UI, Bits UI y shadcn-svelte antes de tocar mas
Eidos.
3. Completar primero Morfo: partes, `data-*`, ARIA, estados, eventos,
keyboard, targets de Sema y ownership de cada evento compuesto.
4. Completar Soma despues: seleccion, deseleccion parcial, min/max, `minDays`,
`maxDays`, navegacion paginada, modal/no-modal y acciones `select`, `close`
y `clear`.
5. La demo solo puede exponer controles que cambien algo visible en el stage.
Si `segments`, `paged nav`, `modal`, `clear`, `min` o `max` no se ven, se
retiran o se implementan.
6. Ninguna demo debe inventar atributos Morfo a mano para simular partes. Si el
selector es necesario, se declara en Morfo/Soma primero.
7. La verificacion debe incluir navegador real y capturas: un mes, dos meses,
popup alineado, seleccion/deseleccion, limites, modal/no-modal y clear.

Powered by TurnKey Linux.