diff --git a/continue.md b/continue.md index 052edc3ef..15de3a113 100644 --- a/continue.md +++ b/continue.md @@ -4,18 +4,21 @@ Fecha de corte: 2026-05-13. Rama: `active-uix`. Actualizacion 2026-05-14: -- Reauditoria 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 +- 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`. - Commits nuevos empujados: - `694eb5c5` — `Clarify prefs projection contract` - `223cdf9e` — `Align sema docs with channel ownership` - - `3dc775f4` — `Update UIX reauditoria notes` + - `3dc775f4` — `Update UIX architecture notes` - `b1215549` — `Fix UIX docs theme and popover dismiss` - 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. @@ -68,7 +71,7 @@ a su `portalTo`. No usar nombres como `somaPortalTo` en `ActiveUix`. ## P1 cerrado -1. Auditoria DOM iniciada en `src/uix/dom_audit.md`. +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`. @@ -146,6 +149,9 @@ a su `portalTo`. No usar nombres como `somaPortalTo` en `ActiveUix`. ## Pendiente de limpieza +- Siguiente foco recomendado: Eidos CSS/runtime cleanup. Decidir que parte de + `tokens/components/*`, `tokens/`, `contracts/` y `themes/base/` se borra, + se genera desde `EidosConfig` o queda como recipe estable. - Resolver los 3 warnings de toast cuando se vuelva a tocar la demo. - No commitear logs temporales: `.codex-vite-dialog*.log`, `debug.log`, `md`. - Antes de seguir con componentes, releer `src/uix/active_architecture.md`, diff --git a/src/uix/README.md b/src/uix/README.md index 041ecae0f..0191fc930 100644 --- a/src/uix/README.md +++ b/src/uix/README.md @@ -10,18 +10,17 @@ Documento corto de posicionamiento arquitectónico para `src/uix`. > **Hand-off de continuación**: el estado actual de migración y los próximos > pasos viven en [`continue.md`](../../continue.md). > **Handoff 2026-05-14**: pausa deliberada antes de seguir programando. -> Hay que reauditar la arquitectura completa de UIX, especialmente los -> contratos mínimos entre `active-uix`, `morfo`, `soma`, `sema`, `eidos`, -> `adom`, `langs`, `format` y `prefs`. Ver +> Los contratos mínimos entre `active-uix`, `morfo`, `soma`, `sema`, `eidos`, +> `adom`, `langs`, `format` y `prefs` quedan descritos en > [active_architecture.md](./active_architecture.md), sección -> "Handoff 2026-05-13". Ya queda fijada la regla principal de ownership: +> "Handoff 2026-05-14". Ya queda fijada la regla principal de ownership: > solo `ActiveApp` y `ActiveUix` standalone crean servicios compartidos. > La tabla ejecutable de contratos vive en [contracts.ts](./contracts.ts) > y se valida en [contracts.test.ts](./contracts.test.ts). > La tabla de naming canonico vive en > [active_architecture.md#01-naming-canonico](./active_architecture.md#01-naming-canonico). -> La auditoria P1 de ownership DOM queda en [dom_audit.md](./dom_audit.md): -> las escrituras gestionadas por UIX pasan por `ActiveDom`. +> Ownership DOM P1 queda cerrado: las escrituras gestionadas por UIX pasan +> por `ActiveDom`. > > **Convenciones doctrinales del API** (intent ↔ color, subset por componente, > root visual con partes attached en eidos, sound prepare-time priming): viven en diff --git a/src/uix/active-uix/README.md b/src/uix/active-uix/README.md index 361bd1cb5..a95904230 100644 --- a/src/uix/active-uix/README.md +++ b/src/uix/active-uix/README.md @@ -15,8 +15,8 @@ La regla de ownership queda cerrada: > y crea los servicios/prefs de UIX. `morfo`, `soma`, `sema`, `eidos` y los > componentes no crean `dom`, `langs`, `prefs`, `format` ni equivalentes. -La auditoria de naming empieza a cerrarse asi: `events` es el nombre publico -del motor perceptivo en `ActiveUix` y tambien el nombre del servicio que +La revision de naming queda cerrada asi: `events` es el nombre publico del +motor perceptivo en `ActiveUix` y tambien el nombre del servicio que `defineUixServices(...)` registra en `ActiveApp`. `semantic` queda reservado para el payload declarativo de `morfo.events[].semantic`, no para servicios runtime. `morfo.translations` queda como catalogo declarativo owned por el diff --git a/src/uix/active_architecture.md b/src/uix/active_architecture.md index a72e3a10a..34d5b9d02 100644 --- a/src/uix/active_architecture.md +++ b/src/uix/active_architecture.md @@ -29,9 +29,8 @@ > - **Sema sin slices visuales** — `motion`, `color` y `presence` salen del > mapa perceptivo; Sema resuelve `hold`, `sound` y `haptic`, y Eidos > materializa la respuesta visual desde CSS/token contract. -> - **DOM audit P1 cerrada** — live regions, descripciones ocultas y bloqueo -> de seleccion de texto pasan por `ActiveDom`; ver -> [`dom_audit.md`](./dom_audit.md). +> - **Ownership DOM P1 cerrado** — live regions, descripciones ocultas y +> bloqueo de seleccion de texto pasan por `ActiveDom`. --- @@ -41,15 +40,15 @@ Estado acordado al cierre de la sesion: - **No tocar componentes Eidos** hasta cerrar de nuevo la arquitectura. La carpeta `src/uix/eidos/components/*` queda congelada salvo orden explicita. -- **Reauditar todo UIX antes de seguir**. La tabla autoritativa de contratos - minimos entre modulos vive en `src/uix/contracts.ts` y se valida con - `src/uix/contracts.test.ts`. +- **Contratos mínimos fijados antes de seguir**. La tabla autoritativa de + contratos minimos entre modulos vive en `src/uix/contracts.ts` y se valida + con `src/uix/contracts.test.ts`. - **Regla de composition roots cerrada**. Solo `ActiveApp` y `ActiveUix` standalone crean servicios compartidos. Las capas inferiores consumen servicios desde `ActiveUix` o fallan; no crean `dom`, `langs`, `prefs`, `format` ni equivalentes. -Preguntas que quedan abiertas / cerradas tras la reauditoria: +Preguntas que quedan abiertas / cerradas tras la revision arquitectonica: 1. `ActiveUix`: cerrado. Expone `uix.prefs` bruto porque es composition root o adapter de `ActiveApp`; las capas inferiores usan vistas read-only cuando @@ -93,7 +92,7 @@ Hallazgos P1 resueltos en esta pasada: - La shell `/uix` sigue ese contrato: cablea `createActivePrefsDomProjection` con `uix.prefs/uix.dom`, crea `ActiveEidos.create({ theme: 'base', modeSource, applyDom: true })` y no escribe `uix.prefs.theme`. -- La auditoria DOM P1 queda cerrada: los nodos gestionados por UIX +- Ownership DOM P1 queda cerrado: los nodos gestionados por UIX (live regions, descripciones ocultas) usan `ActiveDom.writeNode/writeText` y el bloqueo de seleccion de texto usa `ActiveDom.apply`. - `SoundChannel` ya no registra listeners globales en el constructor; el diff --git a/src/uix/auditoria-kimi.md b/src/uix/auditoria-kimi.md deleted file mode 100644 index e57dcc170..000000000 --- a/src/uix/auditoria-kimi.md +++ /dev/null @@ -1,362 +0,0 @@ -# Auditoria Arquitectonica UIX — Kimi (2026-05-12) - -## Alcance - -Auditoria de las capas ActiveUix, Morfo, Soma, Sema y Eidos. -NO se analizaron los componentes internos de Soma ni Eidos. - ---- - -## Estado Codex 2026-05-14 - -Esta auditoria queda parcialmente cerrada por fases en la rama `active-uix`: - -- `ActiveUix` ya no expone ni crea `Eidos`; `ActiveEidos` se crea aparte. -- `ActiveEidos` no crea `ActiveDom` propio y falla si necesita DOM real y no - se le entrega una superficie valida. -- `Provider` abstract class fue eliminada; queda solo el contrato de opciones. -- `Morfo.langs` se renombro a `Morfo.translations`. -- `VisualChannel` posee la proyeccion `data-event-*`; `EngineSemantic` solo - orquesta prepare/handle/cleanup de canales. -- `Sema` ya no transporta `motion`, `color` ni `presence` en el mapa canonico. -- `SoundChannel` no registra listeners globales en el constructor. -- `ActivePrefsDomProjection` escribe `dir`, `data-motion`, `data-sound` y - `data-haptic`; `ActiveEidos` escribe `data-theme`, `data-mode` y - `data-density`. -- La proyeccion cross-modal no vive en `ActiveUix`: existe como - `createActivePrefsDomProjection(...)` en `arts/prefs` y debe cablearla el - composition root que quiera esos attrs globales. -- La ruta `/uix` ya sigue el contrato final: no escribe `prefs.theme`; usa - `createActivePrefsDomProjection(...)` para `dir/motion/sound/haptic` y - `ActiveEidos.create({ theme:'base', modeSource, applyDom:true })` para - `data-theme`, `data-mode` y `data-density`. -- La auditoria DOM P1 queda documentada en `src/uix/dom_audit.md`. - -Pendiente vivo: terminar la generacion/retirada de CSS legacy de Eidos. -`createAttrs` queda como selector helper, `registerContract` ya no se usa desde -Soma, y `arts/frontend` queda como servicio legacy opt-in fuera del boot UIX. - ---- - -## 1. Errores arquitectonicos criticos - -### 1.1. Sema viola su propia frontera: conoce DOM y concerns visuales - -**Archivo:** `src/uix/sema/engine.ts` (lineas 113, 202, 232) - -**Problema:** `EngineSemantic` crea un `DomSignalProjector` por defecto y es el quien escribe -`data-event-*` en el DOM durante `emit`. La doctrina dice que Sema es "registry + dispatch" -y que `VisualChannel` materializa la senal, pero en el codigo el engine proyecta **antes** -de llamar a los canales. El `VisualChannel` solo hace `sleep(hold)`; no controla la proyeccion. - -**Impacto:** El canal visual no es autonomo. El engine esta acoplado a la idea de "escribir en el DOM", -lo que rompe la regla _Sema no conoce DOM_. - -**Fix propuesto:** Mover `projector.project()` y `handle.cleanup()` dentro de `VisualChannel.handle()`. -El engine solo despacha la senal; el canal visual gestiona su propio plano DOM. - ---- - -### 1.2. Acoplamiento historico de Eidos/Semantic en `ActiveUix` - -**Estado 2026-05-13:** resuelto por retirada de ambos acoplamientos. `ActiveUix` -ya no expone `eidos` ni el alias `semantic`; el motor perceptivo se expone como -`events?: EngineSemantic` y `ActiveEidos.create(...)` crea el scope visual. -`ActiveEidos` solo es necesario para CSS runtime o authoring de configuracion. - -**Archivo:** `src/uix/active-uix/types.ts` (linea 115), `src/uix/active-uix/active-uix.svelte.ts` (lineas 419-425) - -**Problema historico:** En `types.ts`, `semantic: EngineSemantic | undefined` -(opcional), pero el bridge visual era obligatorio. Sin embargo, -`createActiveUix({ eidos: false })` era valido, lo que hacia que leer el -bridge visual fallase en runtime. Esto contradecia la degradacion graceful que -se aplicaba al motor perceptivo. - -**Impacto historico:** Un componente que intentaba leer el bridge visual en -modo headless (sin CSS) crasheaba; uno que leia el motor perceptivo simplemente -saltaba la senal. - -**Fix aplicado:** retirar ambos acoplamientos de `ActiveUix`: `events` queda -como motor perceptivo opcional y `ActiveEidos` se crea aparte cuando la app lo -necesita. - ---- - -### 1.3. `ActiveEidos` puede crear su propio `ActiveDom` sin permiso de `ActiveUix` - -**Archivo:** `src/uix/eidos/active-eidos.svelte.ts` (lineas 258-263) - -**Problema:** `ActiveEidos.#getDom()` llama `createActiveDom()` si no recibe `dom`. -Esto crea un segundo servicio DOM con sus propios listeners de resize/scroll, -rompiendo el principio de que _ActiveUix es el unico dueno del DOM_. - -**Impacto:** En modo `dom: false` o attach sin dom, `ActiveEidos` silenciosamente instancia -DOM real en lugar de usar el `disabledDom` compartido. - -**Fix propuesto:** `ActiveEidos` debe recibir siempre un `dom` explicito (incluso si es `disabledDom`). -Si falta, debe lanzar error o degradar a no-op, nunca crear uno propio. - ---- - -### 1.4. `Provider` abstract class sigue vivo a pesar de que la doctrina dice "dropped" - -**Archivo:** `src/uix/soma/provider/provider.svelte.ts` -**Documento:** `src/uix/soma/SOMA_ARCHITECTURE.md` §15 - -**Problema:** `SOMA_ARCHITECTURE.md` dice "Provider inheritance dropped", pero -`provider.svelte.ts` sigue exportando `abstract class Provider`. -Esto genera **dos patrones conviviendo**: el legacy (herencia) y el nuevo (SomaRuntime directo). - -**Impacto:** Confusion para nuevos desarrolladores. Doble mantenimiento. - -**Fix propuesto:** Depreciar/Eliminar `Provider`. Todos los componentes deben migrar a -`SomaRuntime` + funciones helper puras. - ---- - -### 1.5. Duplicacion de logica de `prefs` entre `active-uix/prefs.ts` y `eidos/active-eidos.svelte.ts` - -**Archivo:** `src/uix/active-uix/prefs.ts` (lineas 55-69, 71-78) -**Archivo:** `src/uix/eidos/active-eidos.svelte.ts` (lineas 364-375) - -**Problema:** `readPrefsSlot`, `createPrefsPreferenceSource`, `readActiveUixPrefsSlot` y -`createLocaleSourceFromPrefs` hacen esencialmente lo mismo: leer slots de `ActivePrefs` -de forma defensiva. - -**Impacto:** DRY violation. Si cambia la forma de `ActivePrefs`, hay que tocar dos sitios. - -**Fix propuesto:** Extraer un `prefs-bridge.ts` compartido en `$libs/prefs` o `$active-uix`. - ---- - -### 1.6. Morfo incluia `langs` — mezcla de contrato estructural con datos de i18n - -**Archivo:** `src/uix/morfo/types.ts` (linea 604), `src/uix/morfo/registry.ts` (lineas 33-47) - -**Actualizacion 2026-05-13:** el campo publico se ha renombrado a -`Morfo.translations` y el registro a `connectMorfoTranslations`, para distinguir -catalogo declarativo de servicio runtime `langs`. - -**Problema original:** `Morfo.langs` era un catalogo de traducciones embebido en el contrato. -Morfo deberia ser "DNA" puramente estructural. Las traducciones son volatiles y no -forman parte del contrato DOM. - -**Impacto:** Cada vez que cambia una traduccion, el fingerprint del morfo cambia, -disparando re-registros innecesarios en `connectMorfoTranslations`. - -**Fix propuesto:** Separar `MorfoLangCatalog` en un registry aparte. El morfo puede tener -una referencia (`langCatalogId`), pero no el arbol de strings. - ---- - -## 2. Optimizaciones identificadas - -### 2.1. `readBindings` en `SomaRuntime` genera garbage objects en cada tick - -**Archivo:** `src/uix/soma/runtime.svelte.ts` (lineas 213-239) - -```ts -function readBindings(reg, sources): MorfoBindings { - const states = {}; - const props = {}; - const parts = {}; - // ... for-in + asignacion en cada $effect -} -``` - -En un `$effect` reactivo, esto corre en cada cambio de estado. Para 20 partes, son ~60 objetos -nuevos por frame. - -**Optimizacion:** Usar un objeto de bindings mutable reutilizado (pool) o cambiar `readBindings` -a lectura lazy por plan, evaluando solo las fuentes que el `evalAttrPlan` necesita. - ---- - -### 2.2. `EngineSemantic` clona `SEMA_MAP` en cada instancia - -**Archivo:** `src/uix/sema/engine.ts` (linea 107) - -```ts -this.map = applyMapOverrides(SEMA_MAP, opts.overrides?.runtime); -``` - -En tests con muchas instancias, deep-clone del mapa perceptivo completo es costoso. - -**Optimizacion:** Hacer `SEMA_MAP` inmutable y aplicar overrides como un layer de proxy/lookup -en tiempo de resolucion, no en construccion. - ---- - -### 2.3. `SoundChannel` registra listeners globales en el constructor incluso si nunca se usa - -**Archivo:** `src/uix/sema/chans/sound.ts` (eager-init) - -Eager-init de `AudioContext` es correcto para la politica de autoplay, pero registrar un -listener `capture-phase` en `document` al crear `EngineSemantic` es side-effect agresivo. - -**Optimizacion:** Mover el registro del listener a la primera llamada a `emit()` que requiera -sonido, o usar un singleton lazy para `SoundChannel`. - ---- - -### 2.4. `stableStringify` en `registerMorfo` para fingerprint de `langs` - -**Archivo:** `src/uix/morfo/registry.ts` (lineas 97-109) - -```ts -function fingerprintLangNode(node: LangNode): string { - return stableStringify(node); // JSON-like recursivo -} -``` - -Esto se ejecuta en cada `registerMorfo`. Para catalogos grandes, es `O(n)` en cada registro. - -**Optimizacion:** Usar `WeakMap` + referencia de objeto si los catalogos son estaticos (lo son), -o cachear fingerprints por identidad de objeto. - ---- - -## 3. Propuesta de mejor arquitectura - -### 3.1. Contrato minimo tipado por capa - -El documento `active_architecture.md` admite que falta la tabla de contratos. -Propongo definirla como tipos en `src/uix/contracts.ts`: - -```ts -export interface UixServiceContract { - langs: ActiveLangs; // obligatorio - dom: ActiveDom; // obligatorio (puede ser disabledDom) - events?: EventEngineEmitter; // ornamental - eidos?: ActiveEidos; // ornamental - format?: ActiveFormat; // ornamental - prefs: ActivePrefs; // obligatorio -} -``` - -`ActiveUix` deberia implementar esta interfaz y `createActiveUix` deberia validar contra ella -en lugar de logica `if/else` dispersa. - ---- - -### 3.2. Sema debe purgarse de dimensions visuales (`motion`, `color`, `presence`) - -La doctrina de Phase 5 del codex refactor es correcta pero incompleta. Propongo: - -- **`SemaChannelSignatures`** solo debe tener: `sound`, `haptic`, y canales futuros (`a11y`, `voice`). -- El `hold` visual debe vivir en `VisualChannel` como `hold: number | 'brief' | 'noticed'...`, - resuelto desde `SEMA_MAP.families[*].hold` (ya existe), **no** desde `effective.motion.duration`. -- `motion`, `color`, `presence` se eliminan del `EffectiveSignature`. Eidos reacciona a - `data-event-family` + `data-event-intent` directamente en CSS. - -Esto reduce drasticamente el acoplamiento Sema→Eidos. - ---- - -### 3.3. Unificar scopes redundantes - -Estado 2026-05-13: el adaptador `Eidos` ya fue eliminado. `ActiveEidos` -queda como scope visual real y no existe un engine visual separado. `Soma` -sigue como scope headless mientras se decide si debe conservarse o aplanarse. - -La deuda historica era: - -`Soma` y el antiguo adaptador visual repetian una superficie casi identica: -`uix`, `dom`, `events`, `langs` y helpers de capa. Esa duplicacion ya no debe -volver. - -**Propuesta viva:** eliminar solo los adaptadores que no aporten contrato -propio. Los componentes no deben leer la superficie completa de `ActiveUix`; -deben consumir scopes o vistas estrechas: - -```ts -// En un provider headless -const uix = getActiveUix(); -const runtime = uix.runtime(morfo, sources); - -// En un wrapper visual -const uix = getActiveUix(); -const eidos = ActiveEidos.require(); -``` - -Si se quiere evitar que los componentes toquen `ActiveUix` completo, usar **interfaces de capa**: - -```ts -export interface SomaServices { - dom: ActiveDom; - events?: EventEngineEmitter; - langs: ActiveLangs; -} -export interface EidosServices { - dom: ActiveDom; - eidos?: ActiveEidos; - langs: ActiveLangs; -} -``` - -Esto elimina una clase entera de indireccion y la dependencia a `runed/Context` extra. - ---- - -### 3.4. `SomaRuntime` desacoplado de Svelte - -> Nota 2026-05-13: la API publica `registerPart` fue eliminada. La superficie -> canonica de registro queda en `SomaRuntime.part(...)`; esta observacion queda -> como contexto historico de la auditoria. - -`registerPart` usa `$effect` directamente. Para testear el runtime sin un entorno Svelte, -o para reutilizarlo en otro framework, propongo inyectar un `Scheduler`: - -```ts -export interface EffectScheduler { - run(fn: () => void): () => void; // return cleanup -} - -export function createSomaRuntime( - morfo: Morfo, - sources: SomaRuntimeSources, - scheduler: EffectScheduler = svelteScheduler -): SomaRuntime { ... } -``` - -Esto permite testear con `nanostores`, `mobx`, o incluso manual callbacks. - ---- - -### 3.5. Eliminar CSS legacy (`contracts/`, `tokens/`, `themes/base/`) - -Estos directorios son deuda de migracion. `ActiveEidos` ya puede generar todo el CSS estatico -y de theme desde la configuracion viva. Mantenerlos: - -- Duplica fuentes de verdad (engine vs CSS manual). -- Hace que `eidos-lint` sea necesario. -- Incrementa bundle size. - -**Estado 2026-05-13:** existe el primer artefacto generado, -`src/uix/eidos/generated/base.css`, producido con `npm run generate:eidos-css` -desde `EidosConfig` base. `contracts/` ya no se importa desde `index.css`; -ni desde `tokens/index.css`; queda como archivo de consulta/tooling. Aun no se -borran `tokens/` ni `themes/base/`, pero `themes/base/` tampoco se importa ya -en runtime: sus aliases necesarios viven ahora en el CSS generado. -`tokens/components/index.css` solo importa tokens de las recipes activas; el -resto queda como material legacy. El siguiente paso es separar recipes estables -de aliases retirables en `tokens/`. - ---- - -## 4. Preguntas para priorizar - -1. **¿Prioridad inmediata?** ¿Cerrar primero la tabla de contratos minimos - (`active_architecture.md` §102) antes de cualquier refactor? -2. **¿Eliminacion de `Provider` legacy?** ¿Hay componentes que aun no se migraron al patron - `SomaRuntime` directo? ¿Se puede deprecar `Provider` abstracto ya? -3. **¿Sema visual cleanup?** ¿Aceptar que sea un cambio grande? Implica mover - `motion/color/presence` fuera de `SEMA_MAP` y ajustar `VisualChannel`. -4. **Eidos opcional:** resuelto. `ActiveUix` no expone el bridge visual; - `ActiveEidos` se crea aparte. -5. **¿Scopes `Soma`/`Eidos`?** ¿Eliminar ambas clases y dejar que los componentes lean - `getActiveUix()` directamente, o mantener la separacion simbolica? - ---- - -_Auditoria generada el 2026-05-12. Estado de referencia: rama `active-uix`._ diff --git a/src/uix/dom_audit.md b/src/uix/dom_audit.md deleted file mode 100644 index 7e6124794..000000000 --- a/src/uix/dom_audit.md +++ /dev/null @@ -1,67 +0,0 @@ -# UIX DOM Audit - -Fecha: 2026-05-14. Rama: `active-uix`. - -## Criterio - -La regla arquitectonica queda: - -> Las capas UIX no escriben atributos/estilos mutables directamente. Las -> escrituras estructurales y visuales deben pasar por `ActiveDom` -> (`dom.apply`, `dom.remove`, `dom.writeStyle`, `dom.removeStyle`, -> `dom.writeNode`, `dom.writeText`, `dom.removeNode`) o por un proyector -> construido con ese servicio. - -Lecturas DOM (`querySelector`, `dataset`, `textContent` como lectura, -`ResizeObserver.observe`) no violan esta regla por si solas. - -## Superficies correctas - -- `ActivePrefsDomProjection` proyecta prefs transversales (`dir`, - `data-motion`, `data-sound`, `data-haptic`) con `dom.apply` cuando el - composition root lo cablea. -- `SomaRuntime` sincroniza attrs derivados de morfo con `dom.apply`. -- `events`/`Sema` proyecta `data-event-*` solo desde - `VisualChannel.prepare()` usando `DomSignalProjector`, que escribe con - `dom.apply`; `EngineSemantic` no escribe attrs directamente. -- `ActiveEidos` proyecta `data-theme`, `data-mode`, `data-density` e inserta - CSS runtime con `dom.writeStyle` y `dom.removeStyle`. -- La shell `/uix` usa `createActivePrefsDomProjection(...)` para attrs - cross-modal y `ActiveEidos.create({ applyDom:true, modeSource })` para - theme/mode/density. No escribe `prefs.theme`. -- `TextSelection` ya no escribe `style.userSelect` directamente; ahora recibe - `ActiveDom` y actualiza/restaura solo `user-select` y `-webkit-user-select` - mediante `dom.apply`. -- Announcers/live regions y descripciones ocultas de date/time ya no crean - nodos ni escriben texto directamente; usan nodos gestionados de `ActiveDom`. - -## Escrituras directas restantes - -No quedan escrituras directas de producción detectadas por el barrido P1. -Quedan lecturas DOM y fixtures de tests. - -| Archivo | Qué escribe | Estado | -| --------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------- | -| `src/uix/soma/components/announce/global.svelte.ts` | Crea live regions globales y alterna texto. | Corregido via `ActiveDom.writeNode/writeText` | -| `src/uix/soma/datetime/announcer.ts` | Crea live regions para date/time y escribe mensajes. | Corregido via `ActiveDom.writeNode/writeText` | -| `src/uix/soma/datetime/helpers.ts` | Crea/elimina descripcion oculta `aria-describedby`. | Corregido via `ActiveDom.writeNode/removeNode` | - -## Lecturas o efectos DOM no clasificadas como violacion - -- `src/uix/soma/datetime/segments.ts` y `helpers.ts`: leen `dataset.segment`. -- `src/uix/soma/layers/focus-scope.svelte.ts`: lee/focaliza `document.body` - como parte del focus management. Es mutacion de foco, no escritura de attrs. -- `src/uix/soma/components/virtual-list/virtual-list-provider.svelte.ts`: - observa `document.documentElement` con `ResizeObserver`. -- Tests bajo `src/uix/**`: manipulan `document.body` como fixture. - -## Decision cerrada - -Se eligio extender `ActiveDom` con nodos gestionados (`writeNode`, -`writeText`, `removeNode`). No se crea una fachada nueva y no quedan islas DOM -owned fuera del servicio. - -Los eventos de cierre que apuntan a una parte desmontable deben pasar -`fallbackTarget` cuando esa parte pueda no estar registrada. Popover centraliza -ese patrón en `triggerClose(...)`: prefiere `content`, cae al botón/trigger que -provocó el cierre y evita que `SomaRuntime` emita una señal visual sin target. diff --git a/src/uix/morfo/README.md b/src/uix/morfo/README.md index 83ebda333..f9538e857 100644 --- a/src/uix/morfo/README.md +++ b/src/uix/morfo/README.md @@ -9,8 +9,8 @@ Morfo is the single source of truth for a component's parts, data-attrs, ARIA co ## Handoff 2026-05-13 Morfo debe seguir siendo declarativo: no instancia servicios y no conoce -`ActiveUix`. La auditoria pendiente tiene que fijar que campos de morfo son -contrato cross-layer real y cuales pertenecen a cada capa. +`ActiveUix`. La frontera pendiente es fijar que campos de morfo son contrato +cross-layer real y cuales pertenecen a cada capa. Puntos a cerrar antes de seguir: diff --git a/src/uix/sema/refactorizacion_codex.md b/src/uix/sema/refactorizacion_codex.md index aa43116ac..f2da9ae9b 100644 --- a/src/uix/sema/refactorizacion_codex.md +++ b/src/uix/sema/refactorizacion_codex.md @@ -413,7 +413,7 @@ Eidos dependa de un enum cerrado antiguo. ## Plan incremental -### Fase 1: cambiar la auditoria mental sin romper codigo +### Fase 1: cambiar el criterio de lectura sin romper codigo - Documentar que `motion/color/presence` quedan deprecated en Sema. - Prohibir nuevos usos visuales en `sema/components/*`. @@ -473,6 +473,6 @@ Despues de esta refactorizacion, el modulo queda mas alineado con UIX: no pueden resolverse con CSS. - El vocabulario semantico queda estable y reusable por todas las capas. -La primera implementacion recomendada es pequena: actualizar la auditoria y -despues mover `dialogSema` para que solo conserve sound/haptic. Esa migracion -haria visible la frontera nueva sin reescribir todo el engine todavia. +La primera implementacion recomendada es pequena: actualizar el criterio de +lectura y despues mover `dialogSema` para que solo conserve sound/haptic. Esa +migracion haria visible la frontera nueva sin reescribir todo el engine todavia. diff --git a/src/uix/soma/README.md b/src/uix/soma/README.md index fcd43c1cb..fb8ba7931 100644 --- a/src/uix/soma/README.md +++ b/src/uix/soma/README.md @@ -12,10 +12,10 @@ visual a `eidos` mediante el DOM. ## Handoff 2026-05-14 -Soma no debe crecer ahora con `ActiveSoma`/`EngineSoma` por simetria. La -auditoria pendiente debe definir que servicios minimos necesita -`SomaRuntime` de `ActiveUix` (`dom`, `events`, `langs`, `format`, `prefs`), -pero la regla de ownership ya queda cerrada: Soma no crea servicios +Soma no debe crecer ahora con `ActiveSoma`/`EngineSoma` por simetria. El +contrato minimo de `SomaRuntime` con `ActiveUix` (`dom`, `events`, `langs`, +`format`, `prefs`) queda descrito en `src/uix/contracts.ts`. La regla de +ownership ya queda cerrada: Soma no crea servicios compartidos. Recibe `dom` desde el scope `Soma.runtime(...)`; si no hay una superficie `ActiveDom`, falla en la raiz activa, no dentro de un componente.