# ActiveUix `active-uix` es la raiz de composicion de UIX. Su responsabilidad no es ser otra capa de comportamiento, sino entregar a `morfo`, `soma`, `sema` y `eidos` los servicios minimos que necesitan sin que los componentes conozcan `ActiveApp` directamente. ## Handoff 2026-05-13 La regla de ownership queda cerrada: > Solo los composition roots crean servicios compartidos. Si hay `ActiveApp`, > `attachActiveUix(app)` consume sus servicios y falla si falta alguno > requerido. Si no hay app, `createActiveUix(...)` es el composition root local > 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 `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 componente. `prefs` es el unico nombre para preferencias: `ActiveUix` expone el `ActivePrefs` bruto y las capas inferiores consumen vistas acotadas cuando no deben mutar. ## Boot paths actuales `createActiveUix(options)` compone un runtime standalone: - crea `logger`, `timers`, `bus` y `prefs`; - el `bus` usa `createSvelteEngineBus({ logger, clock: timers.clock })`, igual que `ActiveApp`, para que los listeners corran bajo `untrack`; - crea `langs`, `dom` o `disabledDom`, `format` y `events` segun opciones; - conserva `portal` como target generico de portales para que cada capa lo adapte a su API sin acoplar `active-uix` a esa capa; - registra traducciones comunes y `morfo.translations`; - proyecta preferencias globales al DOM. `attachActiveUix(app, options)` se adjunta a un `ActiveApp` externo: - reutiliza `app.prefs`, `app.langs`, `app.dom` y `app.format` si existe; - exige `app.langs` y `app.dom`; si faltan, lanza error de configuracion; - no vuelve a suscribir `langs` a `prefs.language`: esa conexion pertenece a `defineActiveLangs` dentro de `ActiveApp`; - registra traducciones comunes y `morfo.translations`; - no posee el lifecycle del `app`. ## Contratos actuales | Modulo | Minimo requerido | Opcional | Fallback si falta | Error si falta | | ------------------------ | ----------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------- | | `ActiveUix` standalone | `langs` config | `format`, `events`, `portal`, `dom:false` | crea `prefs`, core services y, si `dom:false`, `disabledDom` local | falta config `langs` | | `ActiveUix` attach | `app.prefs`, `app.langs`, `app.dom` | `app.format`, app event engine, `portal` | ninguno para servicios requeridos | falta `langs` o `dom` en app | | `SomaRuntime` | `dom` desde `ActiveUix` | event engine, `langs`, `format` | ninguno propio | morfo/event/part inexistente | | `Sema` desde `ActiveUix` | `dom/projector` inyectado por `ActiveUix` | `sound`, `haptic` | ninguno propio de servicios UIX | por definir para uso directo fuera de `ActiveUix` | | `Eidos` | `prefs`, `dom` si `applyDom` | `langs`, `format` | `applyDom:false` permite render/serializar sin DOM | falta `dom` con `applyDom` activo | | `ADom` | superficie `ActiveDom` | breakpoints/window | `disabledDom` en UIX | por definir fuera de UIX | ## Decisiones cerradas y riesgos abiertos 1. `dom:false` solo degrada en standalone: `ActiveUix` expone un `disabledDom` local y no deja a Sema/events caer a escrituras directas. 2. En attach mode no hay creacion compensatoria: si la app no tiene `dom`, `attachActiveUix(app)` falla. 3. Standalone usa el mismo bus Svelte-aware que `ActiveApp`. 4. Attach mode no duplica la suscripcion `prefs.language -> langs`. 5. `langs` no es `locale`: `prefs.language` alimenta traducciones; `prefs.locale` alimenta formatos. 6. `prefs.direction` es la preferencia efectiva de direccion; `html[dir]` es solo su proyeccion DOM. 7. Los wrappers/componentes no deben ser el lugar donde se resuelvan estas politicas. Primero se cierra el contrato de la raiz activa. 8. `frontend` no es capa obligatoria de UIX. Queda como servicio legacy opt-in de `ActiveApp`; las preferencias UIX se proyectan desde `ActiveUix`. 9. `ActiveUix` no crea ni conoce `Soma` ni `Eidos`: `Soma.create(...)` crea su scope y `Soma.runtime(...)`; `ActiveEidos.create(...)` crea el scope visual si la app necesita CSS runtime. ## Regla de trabajo vigente Tras cerrar P1, siguen vigentes estas restricciones: - no tocar `src/uix/eidos/components/*`; - no crear nuevas fachadas internas; - no introducir `Engine*`/`Active*` por simetria decorativa; - cualquier cambio debe justificar que contrato minimo aclara.