Remove UIX audit docs

active-uix
dev 5 months ago
parent 26166b9e3c
commit 0a014ed9e5

@ -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`,

@ -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

@ -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

@ -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

@ -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<S>`.
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`._

@ -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.

@ -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:

@ -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.

@ -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.

Loading…
Cancel
Save

Powered by TurnKey Linux.