# Sema `Sema` define el dominio semántico canónico de UIX y orquesta la emisión de señales perceptivas. ## Qué es - familias canónicas: `contact`, `commit`, `alert`, `handle`, `emerge`, `sustain` - intents canónicos: `neutral`, `affirm`, `fulfill`, `risk`, `threat` - normalización entre shape estructurado y label canónico - validación mínima del dominio - `EngineSemantic` como canalizador de ocurrencias `Sema` no decide qué evento ocurrió. El provider lo decide. `EngineSemantic` recibe la ocurrencia y orquesta su materialización en el canal perceptivo visual (DOM). ## Qué ya no es `Sema` ya no es un runtime multimodal. No contiene: - resolver de canales - sound/motion/color/presence engines - mapa perceptivo por canal - política global de accesibilidad por canal Eso pertenece a capas futuras y separadas: - `EngineSemantic` publica ocurrencias semánticas - `ActiveDom` materializa esas ocurrencias como `data-event*` en el DOM - `SoundEngine`, `VibraEngine` y otros engines modales se suscribirán al engine ## El contrato `emit` ```ts semantic.emit(event: SemanticEvent): Promise ``` Una sola firma. Cubre los tres escenarios cuando se compone con `dom.apply`: ```ts // Cambio estructural sin señal dom.apply(change) // Cambio estructural con señal await semantic.emit(event) dom.apply(change) // Señal sin cambio estructural void semantic.emit(event) ``` ### Semántica de la Promise `emit(event)` resuelve cuando: - la señal `data-event*` ya fue escrita al DOM - ha pasado **un rAF** para que CSS pueda observarla y arrancar transitions - todavía está visible en el DOM No resuelve antes (no hay frame para que CSS reaccione) ni después de la limpieza (la señal ya no estaría visible cuando el commit estructural entre). ### Ciclo de vida interno de `emit` ``` 1. Sema genera id/sesion del evento 2. Sema llama a dom.apply(eventSignal) // data-event, data-event-phase, data-intent 3. Sema espera 1 rAF 4. Sema resuelve la Promise // <- el caller hace su dom.apply estructural 5. Sema mantiene la señal N frames extra (hold del evento, default 1) 6. Sema llama a dom.apply(remove eventSignal) ``` ### Política de errores - Si el cambio estructural lanza tras el `await`, no afecta a Sema. Su trabajo (escribir señal + esperar frame) ya terminó. La cleanup pasa igual. - Si Sema falla escribiendo la señal, la Promise rechaza. El caller decide si aborta el cambio estructural o lo aplica igual. - En el escenario fire-and-forget (`void semantic.emit(event)`), una rejection se propaga como unhandled promise — política consciente. ## Vocabulario canónico de verbs (`SEMA_VERBS`) Cross-component action verbs. `morfo.events[].name` debería alinear con este vocabulario para que sema/sound/vibra puedan suscribir por verb y eidos pueda escribir selectores transversales (`[data-event^=dismiss]`). ``` emerge: present · dismiss · open · close · expand · collapse commit: commit · cancel · confirm · submit · reset · fail alert: announce · alert contact: activate · select · toggle handle: acknowledge · edit · drag · resize sustain: tick · progress ``` Definido en [`verbs.ts:SEMA_VERBS`](./verbs.ts). ### Composite event names Los eventos pueden tener variantes con la convención `{verb}-{variant}`: ```ts 'dismiss' // bare verb 'dismiss-outside' // verb + variant 'commit-save' 'commit-cancel' 'close-after-fail' ``` `validateEventName(name)` extrae head + variant y reporta si el head es canonical. Advisory — no rechaza morfos, solo flagea drift para tooling y revisión. ```ts import { validateEventName } from '$uix/sema' validateEventName('commit-save') // { name: 'commit-save', head: 'commit', matchesCanonical: true, variant: 'save' } validateEventName('frob-glob') // { name: 'frob-glob', head: 'frob', matchesCanonical: false, variant: 'glob' } ``` ## Relación con Morfo y Soma - `Morfo` declara los eventos semánticos del componente en `morfo.events` - `Provider` decide cuándo ocurren y llama a `semantic.emit(...)` - `MorfoRuntime` orquesta la secuencia `prewrite -> emit -> handler -> effects` - `Sema` aporta el vocabulario, la normalización y la validación del dominio, y publica las ocurrencias ## Dependencias - `Sema` puede usar `Dom` (`semantic.emit` llama a `dom.apply` para escribir `data-event*`). Dependencia hacia abajo, legítima. - `Dom` no conoce `Sema`. - `Sema` recibe `dom` por construcción, no lo importa duro de `$uix/adom`. ## Regla de arquitectura `Morfo` autoriza la semántica del componente. `Sema` define el vocabulario canónico y orquesta la señal perceptiva. `Provider` decide cuándo emitir. `Dom` aplica. Ver [src/uix/README.md](../README.md) §2.bis para la vista cross-layer.