You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/docs/theming/channels.md

192 lines
9.5 KiB

---
title: The channels as one system — synthesis
type: notes
audience: human + agent
authority: E3 — the capstone tying the per-channel RFCs to the book's thesis
status: current
source: migrated from src/uix/eidos/CHANNELS_SYNTHESIS.md (2026-07-02, docs-book F7.3)
---
# The channels as one system — synthesis ("Diseñando lo que ocurre")
> The **capstone** of the per-channel RFCs. The thesis of the book *Diseñando
> lo que ocurre*: an interaction **is not** color, or movement, or sound — it
> is **one perceptual occurrence spread across N channels**, under the
> **two-moment** model. This ties together [`rfc-color-engine`](../rfcs/rfc-color-engine.md) ·
> [`rfc-typography`](../rfcs/rfc-typography.md) · [`rfc-depth`](../rfcs/rfc-depth.md) ·
> [`rfc-shape`](../rfcs/rfc-shape.md) ·
> [`rfc-structure`](../rfcs/rfc-structure.md). Live demo: **`/temas/orquesta`** (the mixer).
## 1. Two moments, joined by a token: sema emits, eidos reads
An occurrence flows through **two moments**, connected by the **token**:
- **Sema's moment (emission)** — sema evaluates the occurrence and **emits**
it. Sound + haptics it **executes right there** (runtime channels); for the
visual, it **stamps it as tokens** `data-event-*` (family · intent ·
phase). Sema **knows no DOM/CSS**.
- **Eidos's moment (materialization)** — eidos **reads** those tokens
(+ `data-state`) and **materializes** them in CSS (the visual channel). It
is the **sole visual owner**.
The **token is the contract**: sema writes, eidos reads — which is why the
layers decouple (sema DOM-agnostic, eidos free of semantic logic).
Over that producer → consumer axis runs the **temporal** axis (motion F1) —
*which* token:
| Token | Nature | Who writes it | Eidos reads it as |
|---|---|---|---|
| `data-state` | persistent — what the element **is** | soma / morfo | `presets` |
| `data-event-*` | transient — what **occurs** (during the `hold`) | sema (emits) | `signatures` |
`sequence` (`pre` / `coincident` / `post`) orders the two.
## 2. Expression channels (the book) vs sema channels (runtime)
The book has **8 expression channels** (perceptual dimensions). The framework
docs(sema): la doctrina deja de mentir — deriva propia, copias podridas y dos leyes muertas Pasada de saneamiento documental tras los tres commits de sonido, con el informe de AUDIT-sema-2026-08-05 como mapa. Tres clases de defecto. 1) DERIVA QUE YO MISMO DEJE (lo mas urgente) El 05 renombre las claves silenciadoras a `commit.silent` / `emerge.silent` y el 06 las elimine del catalogo — dejando media docena de docs citando claves que ya no existen, y afirmando ademas comportamientos que ya no ocurren: - switch / toggle / toggle-group README: decian «silent-by-default (`commit.silent`)». Hoy es `commit.medium` (gain 0.1) y suenan. Corregidos con el nivel real y su razon (un tercio de una pulsacion de boton). - tooltip README + docblock del pack: decian que el tuning «resta el gain de la familia, asi que neutral emite a 0» y que «threat / fulfill siguen aflorando». Ambas cosas son falsas desde el 06: es `SILENT`, el resolver retira el canal y NADA aflora, porque no queda ganancia que subir. - toggle-group apuntaba a `LIBRO_VARIACIONES_Y_EXTENSIONES.md`, que es un stub movido; ahora apunta a book-deviations. - La nota del renombrado en D.5 decia «hoy es `commit.silent`»: una clave que vivio UN DIA. Marcada como tal, con la lista de las que siguen vivas. 2) COPIAS PODRIDAS — la ley del corpus es enlazar, no copiar, y estas dos entradas la incumplian - D.9 transcribia `SEMA_HOLDS_BY_INTENT` entera y se habia quedado atras: D.12 corrigio DOS valores el 2026-07-06 (`commit.fulfill` noticed→settled, `signal.loss` noticed→brief, ambos contra el texto del libro) y la copia siguio afirmando los viejos un mes. Sustituida por el puntero a holds.ts + el enumerado generado, con la leccion escrita en el sitio. - sema.md transcribia `SEMA_VERBS` y le faltaban DOS verbos vivos: `commit.unselect` y `handle.zoom`. Retirada; queda el puntero a verbs.ts y a vocabularies.md, que si se genera y tiene guard de frescura. 3) LEYES QUE LA PRACTICA YA HABIA DEROGADO, Y NADIE REGISTRO - El contrato `emit` publicaba `Promise<void>`; devuelve `Promise<string>` desde D.9. Corregido, y explicado que ese string es el id de la ocurrencia — el unico asidero para cerrar una senal persistente con `clear`. - channels.md fijaba «3 canales runtime» y D.8 cerraba la puerta a Announce («hoy no»). El `AnnounceChannel` existe desde el 2026-07-04: built-in, opt-in y exportado. channels.md pasa a 4 con la distincion que importa (visual/sound/haptic EXPRESAN; announce SUSTITUYE) y D.8 queda marcada PARCIALMENTE SUPERSEDED. - sema.md prescribia `{ announce: uix.announce }` — y eso NO COMPILA: las dos firmas no casan (bolsa de opciones vs posicional). Ahora ensena el adaptador de una linea que si compila, y declara que ninguna raiz cablea el canal hoy, asi que activarlo cae en el fallback que anade un SEGUNDO par de live regions. El arreglo de codigo queda sin tomar: es decision de diseno. - La cabecera de engine-sound.ts y la fila de arts/README seguian afirmando como MECANISMO que «`prefs.sound` mapea al bus ui», que la auditoria AU-4 ya habia corregido en el README del propio arte: lo garantizado por construccion es el NEGATIVO (ninguna politica de UI escribe el bus content). AMBIGUEDADES QUE NO RESUELVO PORQUE SON TUYAS, pero que dejan de estar escondidas: D.7 prohibe canonizar samples fuera de `signal` y `proof-of-human` los usa en dos eventos `commit`, aplastando la modulacion por intent que esa misma entrada existe para proteger —y el comentario del pack afirma literalmente lo contrario de lo que hace—; y D.8 declara que los packs deben respetar el `activeChannels` de la familia mientras sema.md prescribe lo contrario y el pack de dialog deja dos reglas inertes. Ambas quedan marcadas con su estado real y los dos caminos excluyentes, pendientes de tu firma. VERIFICADO: docs:check 0/616 · sonido + sema 244/244 · cero referencias vivas a las tres claves muertas (las que quedan en book-deviations son historia declarada como tal, y las de cronica no se reescriben) · prettier: los 6 docs con avisos ya estaban sucios en HEAD, no los toco. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
implements them with sema's **runtime channels**, which are **4** — and here
is the key that avoids the classic confusion:
| Sema channel (runtime) | Covers (the book's expression) | Who materializes it |
|---|---|---|
| **visual** (sema projects `data-event-*`) | movement · presence · depth · shape · color | **eidos** — CSS over `data-event-*` + `data-state` |
| **sound** | sound | sema (`chans/sound`) |
| **haptic** | haptics | sema (`chans/haptic`) |
docs(sema): la doctrina deja de mentir — deriva propia, copias podridas y dos leyes muertas Pasada de saneamiento documental tras los tres commits de sonido, con el informe de AUDIT-sema-2026-08-05 como mapa. Tres clases de defecto. 1) DERIVA QUE YO MISMO DEJE (lo mas urgente) El 05 renombre las claves silenciadoras a `commit.silent` / `emerge.silent` y el 06 las elimine del catalogo — dejando media docena de docs citando claves que ya no existen, y afirmando ademas comportamientos que ya no ocurren: - switch / toggle / toggle-group README: decian «silent-by-default (`commit.silent`)». Hoy es `commit.medium` (gain 0.1) y suenan. Corregidos con el nivel real y su razon (un tercio de una pulsacion de boton). - tooltip README + docblock del pack: decian que el tuning «resta el gain de la familia, asi que neutral emite a 0» y que «threat / fulfill siguen aflorando». Ambas cosas son falsas desde el 06: es `SILENT`, el resolver retira el canal y NADA aflora, porque no queda ganancia que subir. - toggle-group apuntaba a `LIBRO_VARIACIONES_Y_EXTENSIONES.md`, que es un stub movido; ahora apunta a book-deviations. - La nota del renombrado en D.5 decia «hoy es `commit.silent`»: una clave que vivio UN DIA. Marcada como tal, con la lista de las que siguen vivas. 2) COPIAS PODRIDAS — la ley del corpus es enlazar, no copiar, y estas dos entradas la incumplian - D.9 transcribia `SEMA_HOLDS_BY_INTENT` entera y se habia quedado atras: D.12 corrigio DOS valores el 2026-07-06 (`commit.fulfill` noticed→settled, `signal.loss` noticed→brief, ambos contra el texto del libro) y la copia siguio afirmando los viejos un mes. Sustituida por el puntero a holds.ts + el enumerado generado, con la leccion escrita en el sitio. - sema.md transcribia `SEMA_VERBS` y le faltaban DOS verbos vivos: `commit.unselect` y `handle.zoom`. Retirada; queda el puntero a verbs.ts y a vocabularies.md, que si se genera y tiene guard de frescura. 3) LEYES QUE LA PRACTICA YA HABIA DEROGADO, Y NADIE REGISTRO - El contrato `emit` publicaba `Promise<void>`; devuelve `Promise<string>` desde D.9. Corregido, y explicado que ese string es el id de la ocurrencia — el unico asidero para cerrar una senal persistente con `clear`. - channels.md fijaba «3 canales runtime» y D.8 cerraba la puerta a Announce («hoy no»). El `AnnounceChannel` existe desde el 2026-07-04: built-in, opt-in y exportado. channels.md pasa a 4 con la distincion que importa (visual/sound/haptic EXPRESAN; announce SUSTITUYE) y D.8 queda marcada PARCIALMENTE SUPERSEDED. - sema.md prescribia `{ announce: uix.announce }` — y eso NO COMPILA: las dos firmas no casan (bolsa de opciones vs posicional). Ahora ensena el adaptador de una linea que si compila, y declara que ninguna raiz cablea el canal hoy, asi que activarlo cae en el fallback que anade un SEGUNDO par de live regions. El arreglo de codigo queda sin tomar: es decision de diseno. - La cabecera de engine-sound.ts y la fila de arts/README seguian afirmando como MECANISMO que «`prefs.sound` mapea al bus ui», que la auditoria AU-4 ya habia corregido en el README del propio arte: lo garantizado por construccion es el NEGATIVO (ninguna politica de UI escribe el bus content). AMBIGUEDADES QUE NO RESUELVO PORQUE SON TUYAS, pero que dejan de estar escondidas: D.7 prohibe canonizar samples fuera de `signal` y `proof-of-human` los usa en dos eventos `commit`, aplastando la modulacion por intent que esa misma entrada existe para proteger —y el comentario del pack afirma literalmente lo contrario de lo que hace—; y D.8 declara que los packs deben respetar el `activeChannels` de la familia mientras sema.md prescribe lo contrario y el pack de dialog deja dos reglas inertes. Ambas quedan marcadas con su estado real y los dos caminos excluyentes, pendientes de tu firma. VERIFICADO: docs:check 0/616 · sonido + sema 244/244 · cero referencias vivas a las tres claves muertas (las que quedan en book-deviations son historia declarada como tal, y las de cronica no se reescriben) · prettier: los 6 docs con avisos ya estaban sucios en HEAD, no los toco. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 months ago
| **announce** | — (accessible substitute, not a book channel) | sema (`chans/announce`) |
`announce` joined on 2026-07-04 as a built-in opt-in channel: it is the
accessible counterpart the book demands when a modality is unavailable
(`BK-SIGNAL-A11Y`), not a ninth perceptual dimension. `visual`, `sound` and
`haptic` are the three that express; `announce` is the one that substitutes.
> **Don't get confused**: **motion · depth · shape · color are NOT "eidos
> channels"** — they are sema's **`visual` channel**, which sema projects and
> **eidos materializes**. Eidos is the visual channel's *materializer*, not
> the owner of channels of its own. The eidos RFCs (`COLOR/DEPTH/SHAPE_ENGINE`)
> describe *how* eidos materializes each visual facet — not independent
> channels.
Plus **space** ([`rfc-structure.md`](../rfcs/rfc-structure.md)) — **structural,
not expressive**: it doesn't "occur", it is the stage (state-only).
## 3. The layer chain (each with its role)
An occurrence **crosses the layers** — it is not "all sema", and eidos is not
a shim:
1. **morfo** — **declares** the event and its semantics (family · intent ·
verb). The contract / DNA; pure TypeScript, no runtime.
2. **soma** — **fires** it (`runtime.trigger`): the sequence `prewrite →
sema.emit → handler →` state attrs. It writes `data-state` (the
state-moment).
3. **sema** — **emits** it: dispatches the signal to its channels —
**executes** `sound` + `haptic`; **projects** the visual channel by
stamping `data-event-*`. It knows no DOM/CSS.
4. **eidos** — **materializes** it: reads `data-state` (`presets`) +
`data-event-*` (`signatures`) and renders them with its **token engines**
(color · motion · depth · shape · space — the RFCs). It is the **complete
visual system** and the sole owner of the visual.
> Eidos does **not "make sema visible"**: sema contributes the **what**
> (family / semantic intent), eidos contributes the **how** (the visual
> vocabulary and its materialization). Co-layers, not one subordinate.
(The full canonical narrative lives in `CLAUDE.md` → "Sema: open channel
registry".)
## 4. The composition — one event, N channels
The **signature** (`BUILTIN_SIGNATURES` + `BUILTIN_KEYFRAMES`) is
**cross-modal**: a single keyframe carries several modalities. A real example
(`press-squeeze`, family `contact`):
```
contact · press → scale 0.96 (motion)
+ box-shadow → flat (depth recede)
+ --shape-smoothing 2→3 (shape: the corner firms up)
+ tick (sema sound)
+ vibration (sema haptic)
```
One `engine.emit(...)` stamps `data-event-*` (the **visual** channel reacts —
eidos materializes it as color/motion/depth/shape) **and** fires sound +
haptic — from the **same** event. There are no systems coordinating by hand;
there is one occurrence expressing itself through sema's channels.
## 5. Runtime builders — the sextet (an open cage)
Every axis retunable at runtime, same pattern (seed → managed block), opt-in
over the authored scale:
fix(cleanroom): F2+F3+F4-C+SEM-4s1 — lote mecánico, censos con guard, corpus documental y el close polimórfico de los pickers VIVO F2 — lote mecánico (13 ítems): - DEP-2 ogl eliminado (0 imports) · DEP-1 clsx inlineado como toClassString propio + suite de contrato (props.test.ts; soma.md §12 cerrado). - THM-7: los 5 selectores manuales de sema.md reescritos con semaSelector (los ejemplos [data-toast-root] apuntaban a un part INEXISTENTE — la deriva que el builder previene, demostrada en el propio doc). - MOR-1 escape isomorfo + validación de attr-names en semaSelector + 9 tests (selectors.test.ts, matches() real con comillas/corchetes) · MOR-2 partMarkerAttr = única fuente compilador↔builder + test de paridad · MOR-3 _resetCompileCache borrado (0 usos). - SOM-2 keydown continue en match sin handler + keyboardFixtureMorfo · SOM-1 no-await de handlers (censo async = 0; contrato V1 cumplido) + pin. - SEM-2 trigger pre-attacha catch con logger (void trigger sin unhandled rejection; throw intacto para awaiters) + pin · SEM-3 fallback muerto de applyDominance → skip defensivo + timer tope de awaitExpression cancelado · SEC-1 adjudicado YA implementado (assertCssVariableValue desde 2026-05-11) + pin del path de VALOR. - accordion → outline (§32; su outline:none dejaba CERO anillo en HCM) — verificado en vivo · THM-6 radius-full 9999px · EID-4 recuentos 33. F3 — censos con guard: - SOM-3 cerrado: announcer + image-provider migrados a scheduler-preferred (consumidores cableados: date/time-field vía soma.uix.timers; avatar/image vía eidos.timers — verificado en vivo); guard de timers ENSANCHADO de soma/components a TODO soma y pasado a EVIDENCIA (setTimeout exige .schedule( en el fichero — layers/ y datetime/ escapaban del ámbito viejo). - THM-5: R-4.7 nueva (válvula same-line /* important: <razón> */, escaneo comment-blanked) + las 15 declaraciones anotadas con su razón + canon recipe-contract §3/§4. - SOM-4 adjudicado: el censo/guard YA existían (49 pins); knob/mask-field/ timeline pinneados (overrides documentados en call-site); media-player Batch-4 (35 hits, cero renderProps) = único batch restante, registrado. - THM-4 doctrinado en eidos.md §unused (comportamiento/composición = legítimo; deuda = eje visual sin consumidor; hotspots por lotes). F4-C — corpus documental (decisiones de usuario aplicadas): - DOC-3: los 15 enlaces muertos resueltos (repoint a la edición FINAL trackeada / des-link históricos) · docs:check I6-links WARN→ERROR. - DOC-1: tabla «Build contract» MIGRADA a component-guide con estados modernizados (A3–A5 → LIVE + guards de hoy); banners reapuntados; citas de CANON/sema.md historificadas; lápida-redirect en el §13 del fósil. - DOC-4: hold chain → holds.ts · FAQ event:* SUPERSEDED por signatures · gradient añadido a los DOS capstones (sextet real) · nota de paleta de demo-authoring corregida (universalPaletteDecls + decisión THM-2 = mecanismo universal como sucesor del tracker borrado). - DOC-5/6: recuentos anti-frágiles datados · §4.11 dup → §4.12 · Known gaps historificado · N-6/N-7 recuperadas de git (d68d2c45^) y canonizadas en eidos.md §pickers · authoring E2 → canon/tsc.md · air-old des-linkado · EID-3 (placement) en la fila RTL · AUX-2 disabledDom documentado. SEM-4 sesión 1 — el close polimórfico de los pickers, VIVO (D.11): - Reconciliación: los morfos ya no declaran close (delegated al Popover, de-dialoged 06-27); el agujero real era el cierre programático bypaseando dismissWith → save/cancel/select eran perceptualmente SILENCIOSOS. - Fix: PickerShellHandle.setPopoverDismiss + closeWith(cause) en los 5 providers (14 sitios; select/commit → 'save' = commit.save+fulfill, cancel → 'cancel' = emerge; fallback raw para headless) + UN inyector en el eidos PickerShell root (norma N-8). Picker genérico fuera a propósito (ya suena commit-set/cancel por diseño S9). - Verificado en vivo (date-picker): Done → close·commit·fulfill·active · Cancel → close·emerge · cierre real. Gates: matriz 141/141 (los 6 morfos nuevos de la pista de texto paralela también PASS) · contracts 38/38 · eidos 314 · sema 178 · morfo 94 · docs:check 0/0 con I6 en error · baseline propio 57. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
`applyColorScheme` · `applyTypeScale` · `applyDepth` · `applyShape` ·
`applySpacing` · `applyGradients`
And the **capstone composing them**: **`applyTheme(seed)`** — a single seed
fix(cleanroom): F2+F3+F4-C+SEM-4s1 — lote mecánico, censos con guard, corpus documental y el close polimórfico de los pickers VIVO F2 — lote mecánico (13 ítems): - DEP-2 ogl eliminado (0 imports) · DEP-1 clsx inlineado como toClassString propio + suite de contrato (props.test.ts; soma.md §12 cerrado). - THM-7: los 5 selectores manuales de sema.md reescritos con semaSelector (los ejemplos [data-toast-root] apuntaban a un part INEXISTENTE — la deriva que el builder previene, demostrada en el propio doc). - MOR-1 escape isomorfo + validación de attr-names en semaSelector + 9 tests (selectors.test.ts, matches() real con comillas/corchetes) · MOR-2 partMarkerAttr = única fuente compilador↔builder + test de paridad · MOR-3 _resetCompileCache borrado (0 usos). - SOM-2 keydown continue en match sin handler + keyboardFixtureMorfo · SOM-1 no-await de handlers (censo async = 0; contrato V1 cumplido) + pin. - SEM-2 trigger pre-attacha catch con logger (void trigger sin unhandled rejection; throw intacto para awaiters) + pin · SEM-3 fallback muerto de applyDominance → skip defensivo + timer tope de awaitExpression cancelado · SEC-1 adjudicado YA implementado (assertCssVariableValue desde 2026-05-11) + pin del path de VALOR. - accordion → outline (§32; su outline:none dejaba CERO anillo en HCM) — verificado en vivo · THM-6 radius-full 9999px · EID-4 recuentos 33. F3 — censos con guard: - SOM-3 cerrado: announcer + image-provider migrados a scheduler-preferred (consumidores cableados: date/time-field vía soma.uix.timers; avatar/image vía eidos.timers — verificado en vivo); guard de timers ENSANCHADO de soma/components a TODO soma y pasado a EVIDENCIA (setTimeout exige .schedule( en el fichero — layers/ y datetime/ escapaban del ámbito viejo). - THM-5: R-4.7 nueva (válvula same-line /* important: <razón> */, escaneo comment-blanked) + las 15 declaraciones anotadas con su razón + canon recipe-contract §3/§4. - SOM-4 adjudicado: el censo/guard YA existían (49 pins); knob/mask-field/ timeline pinneados (overrides documentados en call-site); media-player Batch-4 (35 hits, cero renderProps) = único batch restante, registrado. - THM-4 doctrinado en eidos.md §unused (comportamiento/composición = legítimo; deuda = eje visual sin consumidor; hotspots por lotes). F4-C — corpus documental (decisiones de usuario aplicadas): - DOC-3: los 15 enlaces muertos resueltos (repoint a la edición FINAL trackeada / des-link históricos) · docs:check I6-links WARN→ERROR. - DOC-1: tabla «Build contract» MIGRADA a component-guide con estados modernizados (A3–A5 → LIVE + guards de hoy); banners reapuntados; citas de CANON/sema.md historificadas; lápida-redirect en el §13 del fósil. - DOC-4: hold chain → holds.ts · FAQ event:* SUPERSEDED por signatures · gradient añadido a los DOS capstones (sextet real) · nota de paleta de demo-authoring corregida (universalPaletteDecls + decisión THM-2 = mecanismo universal como sucesor del tracker borrado). - DOC-5/6: recuentos anti-frágiles datados · §4.11 dup → §4.12 · Known gaps historificado · N-6/N-7 recuperadas de git (d68d2c45^) y canonizadas en eidos.md §pickers · authoring E2 → canon/tsc.md · air-old des-linkado · EID-3 (placement) en la fila RTL · AUX-2 disabledDom documentado. SEM-4 sesión 1 — el close polimórfico de los pickers, VIVO (D.11): - Reconciliación: los morfos ya no declaran close (delegated al Popover, de-dialoged 06-27); el agujero real era el cierre programático bypaseando dismissWith → save/cancel/select eran perceptualmente SILENCIOSOS. - Fix: PickerShellHandle.setPopoverDismiss + closeWith(cause) en los 5 providers (14 sitios; select/commit → 'save' = commit.save+fulfill, cancel → 'cancel' = emerge; fallback raw para headless) + UN inyector en el eidos PickerShell root (norma N-8). Picker genérico fuera a propósito (ya suena commit-set/cancel por diseño S9). - Verificado en vivo (date-picker): Done → close·commit·fulfill·active · Cancel → close·emerge · cierre real. Gates: matriz 141/141 (los 6 morfos nuevos de la pista de texto paralela también PASS) · contracts 38/38 · eidos 314 · sema 178 · morfo 94 · docs:check 0/0 con I6 en error · baseline propio 57. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
(`{ color?, type?, depth?, shape?, space?, gradient? }`) composes the six
axes in **one managed write** (vs six loose `apply*`), **atomically**: the
axes you pass are applied, the ones you omit revert to the authored
foundation. `clearTheme()` reverts everything. For surgical per-axis tweaks,
the individual `apply*` remain. No reference system gathers the six
perceptual axes under a single runtime theme builder.
docs(sema,theming): el orden real, como se autora cada canal, y el hueco del theming Tres cosas que el cambio del sonido dejo sin plasmar. 1. EL ORDEN CANONICO MENTIA. La numeracion 1·2·3·4·5a·5b esta citada como canonica en sema.md, resolver.ts y engine.ts, y despues del reorden era falsa para `sound`: un pack ya no autora en 5a, lo hace en 1.5. Corregido en los tres sitios a la vez, con el porque — todo lo que AUTORA un sonido corre ahi conservando su precedencia relativa; solo cambio su posicion respecto al intent. El resto de la regla (channels/haptic/hold) mantiene el «gana el ultimo» porque no son ejes evaluativos. 2. COMO SE AUTORA CADA CANAL (CANON §7). El reparto por dueño estaba escrito; lo que un componente ESCRIBE, no. Tabla nueva: el canal visual no se escribe (se declara el evento y eidos reacciona), `sound` es UN NOMBRE, `haptic` es un `kind`. La regla es la misma en las tres filas y ese es el punto: un componente dice QUE ocurre, nunca cuan fuerte, cuan brillante ni cuanto dura. El sonido era la excepcion hasta ayer. 3. EL ANALISIS DEL THEMING que el autor pidio (theming/channels.md §5b). Lo que el cambio NO toco: nada de eidos. El canal visual se proyecta estampando data-event-*, y esa ruta quedo intacta — ni una receta, ni un token, ni un selector. Eidos no sabe que existe el sonido y no le hizo falta. Lo que cambio fue DONDE se autora (un catalogo en vez de 71 ficheros) y CUANDO se aplica (antes del intent), ambos dentro de sema. Lo que si cambio, y es lo util: `applyTheme(seed)` retunea SEIS ejes visuales (color·type·depth·shape·space·gradient) y el sonido tiene CERO. Antes esa asimetria se justificaba sola — con 214 reglas autorando 33 firmas a mano no habia objeto que retunear. Hoy hay exactamente uno: 16 nombres en un const. Un eje `sound` en ThemeSeed seria la misma forma que los otros seis. Y las tres puertas de personalizacion, medidas, ninguna llega al catalogo: `overrides.runtime` recorre rutas de SEMA_MAP y el catalogo no esta en el mapa (ademas se traga las erratas, S-09); `overrides.cascade` es por selector, no un tema; `masterGain` se descarta en SILENCIO (S-05/S-32). Un producto puede silenciar y puede pisar una ocurrencia, pero NO puede re-voceear el sistema. Queda escrito en vez de ser folclore. ⚠️ chronos: `src/uix/sema/components/chronos.ts` entro en la migracion de `769e426c5` pese a ser de escritura excluida. Era forzoso — con el tipo estrechado, dejarlo sin migrar rompe la compilacion del arbol entero — y el cambio es mecanico (soundTuning(...) -> nombre), sin decision de diseño. Su SPEC.md NO se ha tocado y sigue citando `soundTuning('commit.soft')`. VERIFICADO: sema+morfo+sound 437/437 · check 75 · docs:check 0/618. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
## 5b. How each channel is AUTHORED — and the asymmetry that is left
The sextet above retunes the **visual** channel at runtime. Sound and haptic
have no equivalent, and after the 2026-08-06 rework that gap is worth naming
precisely, because the reason it existed is gone.
| Channel | Where a component AUTHORS it | Where a THEME retunes it |
| --- | --- | --- |
| visual — color · motion · depth · shape · space | eidos recipes, reacting in CSS to `data-event-*` | `applyTheme(seed)` + the six `apply*` (runtime, atomic) |
| **sound** | **names one entry of `SOUNDS`** (`src/uix/sema/sound-names.ts`) — a word, never a parameter | **nothing** — see below |
| **haptic** | a categorical `kind` (`tick` / `tap` / `pulse` / …) | **nothing** |
**What the sound rework did NOT change.** Nothing in eidos. The visual channel
is projected by stamping `data-event-*`, and that path was untouched: no
recipe, no token, no selector moved. Eidos does not know sound exists and did
not need to. The rework changed WHERE the sound is authored (a catalogue
instead of 71 pack files) and WHEN it is applied (before the intent instead of
after it) — both entirely inside sema.
**What it did change, and it is the useful part.** Until then, "theming the
sound" was not a coherent idea: 214 cascade rules authored 33 hand-written
signatures across 71 files, and there was no object to retune. Today there
is exactly one — sixteen names in one const — so a `sound` axis in `ThemeSeed`
would be the same shape as the other six, and a brand could ship its own
`soft` the way it ships its own colour ramp.
**The measured surface today, for anyone who tries.** Three doors, none of
which reaches the catalogue:
- `overrides.runtime` — path-based mutations of `SEMA_MAP`, so it reaches
family bases and intent deltas but **not** the catalogue, which is a module
const outside the map. It also swallows path typos in silence (audit S-09).
- `overrides.cascade` — app-level rules; the type stays open on purpose so an
app CAN author a raw signature. But it is per-selector, not a theme: you
restyle one occurrence, not the word `soft` everywhere.
- `masterGain` via `createActiveUix` — **discarded in silence** (audit S-05 /
S-32): the engine filters the key before the channel is built.
So: **a product can silence sound, and can override one occurrence, but cannot
re-voice the system.** That is a real gap, it is now cheap to close, and it is
not closed — recorded here rather than left as folklore.
## 6. Position vs the references
No reference system gathers the channels under **one semantic model**.
Material has shape morph + motion (ad-hoc, without integrated
sound/haptics); Apple, continuity + materials (platform-bound); everyone,
color. **UIX gathers them** — the visual channel (sema → eidos) + sound +
haptic (sema) — over the two-moment model, fired from one event, with
runtime builders and an open registry. That is the framework, not the sum of
its parts.
## 7. Demo
`/temas/orquesta` — the mixer: press a control and mute each facet to hear
its part. The **visual channel's** 4 facets materialize with eidos tokens
(toggleable so each can be muted one by one); **sound + haptic** are fired by
the real sema engine (`EngineSemantic.emit`, filtered channels). One event,
sema's channels.

Powered by TurnKey Linux.