Phase 3 (E1). After Phase 1b pulled the embedded "Handoff 2026-05-14" out, the
doc still read as session process ("tras cerrar P1", "punto crítico para
mañana", a "Regla de trabajo vigente" section). Rewrote it as a clean layer
reference: what active-uix is, the two boot paths (createActiveUix /
attachActiveUix), the minimum-contracts table (linked to the executable
contracts.ts — fixed the path: it lives in src/uix/, not active-uix/), the
ownership + degradation rules as timeless invariants, and the shell-boot example.
Dropped the process framing. Spanish kept (consistent with its sibling
active_architecture.md; coordinated EN migration is a later pass).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| `ActiveUix` standalone | `langs` config | `clipboard:false`, `format`, `events`, `portal`, `dom:false` | crea `prefs`, core services y, si `dom:false`, `disabledDom` local | falta config `langs` |
| `ActiveUix` attach | `ActiveApp` core + services `langs`, `dom` | `app.clipboard`, `app.format`, app event engine, `portal` | ninguno para servicios requeridos | falta `langs` o `dom` en app; getter explicito falla si se pide un servicio opcional ausente |
| `SomaRuntime` | `dom` desde `ActiveUix` | event engine, `langs`, `format` | ninguno propio | morfo/event/part inexistente |
| `Sema` directo | `dom` o `projector` si `visual` esta activo | `sound`, `haptic`, `visual:false` | ninguno propio de servicios UIX | `SemaConfigError` sin `dom/projector` y con visual activo |
| `Eidos` | `dom` si `applyDom` | `langs`, `format`, `prefs`, mode/density sources | `applyDom:false` permite render/serializar sin DOM | falta `dom` con `applyDom` activo; componentes visuales fallan si leen un servicio no inyectado |
| `ADom` directo | target/window/document del caller | breakpoints/window | `disabledDom` solo si el caller lo pide explicitamente | errores propios de ADom si no hay DOM real |
## 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. `clipboard` es un servicio de capacidad, no DOM visual. Standalone lo
crea salvo `clipboard:false`; attach lo consume de `app.clipboard` si una
capa lo pide y falla con error explicito si no fue declarado.
7. `prefs.direction` es la preferencia efectiva de direccion; `html[dir]` es
solo su proyeccion DOM.
8. Los wrappers/componentes no deben ser el lugar donde se resuelvan estas
politicas. Primero se cierra el contrato de la raiz activa.
9. El antiguo artefacto `frontend` fue retirado. `ActiveUix` no proyecta
preferencias al DOM: `arts/prefs` proyecta lo transversal y `ActiveEidos`
proyecta lo visual.
10. `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.
## Boot de una shell UIX
Una shell que usa componentes visuales debe cablear tres piezas de forma
| Módulo | Mínimo requerido | Opcional | Fallback si falta | Error si falta |
| --- | --- | --- | --- | --- |
| `ActiveUix` standalone | `langs` config | `clipboard:false`, `format`, `events`, `portal`, `dom:false` | crea `prefs`, core services y, si `dom:false`, `disabledDom` local | falta config `langs` |
| `ActiveUix` attach | `ActiveApp` core + servicios `langs`, `dom` | `app.clipboard`, `app.format`, motor de eventos, `portal` | ninguno para servicios requeridos | falta `langs` o `dom` en app; el getter de un servicio opcional ausente falla explícito |
| `SomaRuntime` | `dom` desde `ActiveUix` | motor de eventos, `langs`, `format` | ninguno propio | morfo/event/part inexistente |
| `Sema` directo | `dom` o `projector` si `visual` activo | `sound`, `haptic`, `visual:false` | ninguno propio de servicios UIX | `SemaConfigError` sin `dom/projector` con visual activo |
| `Eidos` | `dom` si `applyDom` | `langs`, `format`, `prefs`, fuentes mode/density | `applyDom:false` permite render/serializar sin DOM | falta `dom` con `applyDom` activo |
| `ADom` directo | target/window/document del caller | breakpoints/window | `disabledDom` solo si el caller lo pide | errores propios de ADom sin DOM real |
## Reglas de ownership y degradación
1. **Solo los composition roots crean servicios compartidos.**`morfo`, `soma`,
`sema`, `eidos` y los componentes nunca crean `dom`, `langs`, `prefs`,
`format`, `clipboard` ni equivalentes: los reciben de `ActiveUix`.
2. **`dom:false` solo degrada en standalone.** `ActiveUix` expone un
`disabledDom` local y se lo pasa también a `EngineSemantic`; Sema/events no
caen a escrituras DOM directas. En attach no hay creación compensatoria: si la
app no tiene `dom`, `attachActiveUix(app)` falla.
3. **`langs` no es `locale`.** `prefs.language` alimenta las traducciones;
`prefs.locale` alimenta los formatos. No se mezclan.
4. **`clipboard` es un servicio de capacidad, no DOM visual.** Standalone lo crea
salvo `clipboard:false`; attach lo consume de `app.clipboard` cuando una capa
lo pide, y falla con error explícito si no se declaró.
5. **`prefs.direction` es la preferencia efectiva de dirección**; `html[dir]` es
solo su proyección DOM.
6. **`ActiveUix` no auto-proyecta preferencias al DOM.** `arts/prefs` proyecta lo