|
|
|
|
# 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<void>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
docs: cross-layer articulation — eidos README + 2-of-3 rule across all layer docs
Closes the documentation loop on the cross-layer extension pass: morfo
now articulates between soma, sema, and (future) eidos. The "2-of-3 rule"
formalizes when an extension to morfo is justified vs when it should
stay as provider logic.
src/uix/eidos/README.md (new)
- Documents eidos's role and what it consumes from morfo + sema BEFORE
any code exists, so the contract is preparedly clean when implementation
starts.
- Catalogs which morfo fields eidos reads (parts, archetype, states,
data values, events, prewrite, focus, supportsNesting) and which it
ignores (computed state, runtime internals, layers).
- Documents the DOM-as-channel pattern: sema writes data-event* on emit;
eidos reacts to selectors like `[data-event^="dismiss"]`.
- Establishes the boundary with `air` (dead branch reference, not base).
src/uix/README.md (top-level)
- §8 Reglas de dependencia: adds the 2-of-3 rule table making the
morfo-extension contract explicit, plus a list of canonical vocabularies
(archetypes, verbs).
- §10 Reading order: includes eidos README + lib/dom + clarifies which
layers are dead branches.
src/uix/morfo/README.md
- New "Archetypes" section documenting the 24-verb vocabulary, the
Provider-as-trigger vs Provider-as-container distinction, and the rule
for adding new archetypes (≥2 components share the role).
- New "The 2-of-3 rule" section with the same table as the top-level,
listing which extensions did/didn't make it past the rule and why.
- `parts[].archetype` mentioned in the "What morfo contains" list.
src/uix/sema/README.md
- New "Vocabulario canónico de verbs" section listing SEMA_VERBS by
family and the `{verb}-{variant}` composite naming convention.
- Documents `validateEventName()` as advisory tooling.
src/uix/soma/SOMA_ARCHITECTURE.md
- partProps documentation now mentions data-archetype emission.
- New "Cross-layer hooks que soma emite por la regla 2-de-3" section
listing the data-* attrs soma writes that sema and eidos consume.
- Reading-order links updated.
No code changes — all docs.
6 months ago
|
|
|
## 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.
|