# CONTINUE — auditoría del sistema semántico y sus arreglos > **Kickoff para la sesión siguiente**: _«Lee `docs/process/CONTINUE-sema-audit.md` > y sigue por la cola de §3, empezando por las 17 reglas.»_ > **Fecha**: 2026-08-06 · Rama `alpha-0.1-dir-prefs` (compartida — otra sesión > trabaja en `blocks`; `git reset -q` + add sólo lo propio, siempre). > **Fuente de verdad de los hallazgos**: [`AUDIT-sema-2026-08-05.md`](./AUDIT-sema-2026-08-05.md) > — 44 confirmados tras refutación adversarial, con fichero, línea y evidencia. > Este documento sólo dice **qué se cerró, qué queda y cómo medirlo**. --- ## 1. Cómo empezó, para que nadie repita el camino El usuario oyó que «no se oyen muchos componentes: Switch, Toggle, algunos botones de la toolbar». El diagnóstico inicial fue **incorrecto por medir a medias** y la corrección la dio él: _«el silent emitía sonido, ese era el problema»_. Tenía razón, y de ahí salió todo lo demás. Lecciones de método que costaron tiempo real y que valen para cualquier hilo de este repo: - **Medir la envolvente NO es medir la salida.** Se midió la automatización del `AudioParam` (0.0001) y se declaró silencio; la salida real de esa misma firma con intent `risk` era **−13.9 dBFS**, más fuerte que un botón. Para verificar audio: **render offline replicando el grafo** (`OfflineAudioContext`) y medir el pico de muestra. Contar osciladores miente. - **«Lee toda la documentación» es precondición, no consejo.** Se le preguntó al usuario por D.8 sin haber leído `sema.md` §componentes continuos, que contenía la respuesta. La lectura completa del corpus de sema + motor son ~24 000 líneas en 42 ficheros; el núcleo indispensable está en §5. - **Un guard que no has visto fallar no vale.** Los cuatro guards nuevos de esta sesión nacieron en rojo. Dos de ellos **corrigieron el arreglo** que estaban vigilando (ver §2.4). - **El árbol está compartido.** Clasificar siempre «míos vs ajenos» por contenido del diff, nunca por confianza. --- ## 2. Lo cerrado en esta sesión | # | Qué | Commit | | --- | ---------------------------------------------------------------------------- | ----------- | | 2.1 | El silencio deja de ser aritmética: **`SILENT`**, valor canónico | `24d30ee1a` | | 2.2 | La rugosidad pasa a **trémolo EN SERIE** (era aditivo sobre el `AudioParam`) | `316452263` | | 2.3 | Saneamiento documental: deriva propia, copias podridas, dos leyes muertas | `432106f1f` | | 2.4 | **`contact-press`** en los toggles + D.7 canónica + **D.8 reescrita** | `b9d73c19b` | | 2.5 | D.7 sin versos sueltos (7 infractores) + guard del intent | `4fccf1662` | | 2.6 | Una regla de cascada casa con SU objetivo, **nunca con un ancestro** (S-01) | `ccfea0f10` | ### 2.1 `SILENT` — el silencio es un VALOR, no una resta Había tres claves silenciadoras (`commit.silent`, `emerge.silent`, `contact.silent`), cada una restando el gain base de SU familia. No eran silencio: eran un número, y las capas posteriores mueven números. Medido: un toggle «silenciado» con intent `risk` salía a **−13.9 dBFS** y con `threat` a **−6.7**, frente a **−9.3** de un botón normal — porque los deltas de intent suman **rugosidad** (`risk` +0.2, `threat` +0.4), eso cruzaba el umbral del AM, y el modulador estaba conectado al `AudioParam` de la envolvente. Hoy: `SILENT` (exportado por `$uix/sema`) se declara en el slice del canal y el **resolver lo honra retirando ese canal**. Absorbente: ningún delta lo resucita. Se levanta sólo REEMPLAZANDO el slice con una firma completa. ### 2.2 El trémolo, en serie `modulatorGain.connect(envelope.gain)` — conectar a un `AudioParam` **suma**. Ahora hay una etapa de ganancia en serie a `1 - depth` con el modulador sobre su propio `.gain`. Medido viejo→nuevo: el clic de cierre de cada earcon de `signal` **0.0666 → 0.0002**; la cola de `commit+risk` 0.263 → 0.103; y `commit.subtle`+`threat` de RMS **0.143 → 0.018** (era 7× su nivel declarado). **Contrapartida declarada**: los earcons con rugosidad bajan 1.6–2.7 dB. ### 2.4 Decisiones FIRMADAS — no re-litigar - **`contact-press`** (directiva del autor). Los tres toggles declaran los dos momentos del libro: el CONTACTO habla (`contact.soft`, gain 0.08 — el «click breve opcional» del cap. 22) y el COMMIT calla (`SILENT`, cap. 23: «sonido: cierre opcional»). ⚠️ Deroga el anexo Tabla 1, que decía «un único evento; el contacto es implícito»; la reversión está escrita en `compile.test.ts`. - **D.7 canónica, con enmienda por su motivo**: no se canoniza un sample sobre un evento cuya familia **tenga `base.sound`**. `handle`/`sustain`/`delegate` salen de la lista — sin base no hay nada que aplastar, y los 14 usos de `sound()` sobre `handle` son la única fuente sonora del gesto. - **D.8 reescrita**: `activeChannels` es el DEFAULT de la familia, no una prohibición. `channels` ajusta en las dos direcciones; **ampliar exige justificación perceptual escrita**. Lo prohibido es declarar una firma de canal que la activación no incluye (regla inerte). ### 2.5 El hallazgo que conecta dos capas Al arreglar D.7 con `soundTuning('commit.soft', …)`, **el guard lo tumbó**: un afinado de escalera trae su `gain` como **número desnudo**, y eso se aplica en modo `replace` igual que el sample. **D.7 y S-07 son el mismo defecto en dos capas.** Las 9 reglas corregidas **componen** (`gain: { op: 'add', value: -0.25 }`). --- ## 3. LA COLA — por dónde seguir, en orden El usuario aprobó todo lo de abajo **menos S-07**, que se trata «más detenidamente» y por tanto NO se toca sin reabrirlo con él. ### 3.1 Las 17 reglas de 212 que no disparan o disparan mal ← EMPEZAR AQUÍ Todas con evidencia en `AUDIT-sema-2026-08-05.md` (S-08, S-12, S-13, S-14, S-15, S-30, S-37, S-38, S-39): | Componente | Defecto | Efecto medido | | ------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | **textarea** | Las 2 reglas apuntan al `provider`; el estampado cae en el `input` | `commit-submit` suena **6×** más fuerte; el aviso de desbordamiento **13×** | | **navigation-menu** | `fallbackTarget` GANA sobre el part del morfo → 2 reglas `emerge` muertas | abrir/cerrar suena con la base de familia (0.2) en vez de 0.08 / 0.05 | | **gradient-picker** | Regla para `commit-reset`, evento que el proveedor nunca emite | regla muerta + doc que miente | | **chronos** | 2 reglas para `handle-drag` / `handle-resize`, que nadie emite | ⚠️ chronos es de **escritura excluida** — auditar, no editar | | **tree-view** | `select(value)` sin elemento no dispara: el teclado no emite NADA | asimetría teclado/ratón; 2 reglas sólo alcanzables con puntero | | 5 reglas | Escriben en un canal que la familia no activa (las inertes de D.8) | letra muerta — ahora infracción explícita | | 10 reglas | Aplican un tuning cuya cabeza de familia MIENTE sobre la base que modifican | la ley de nombrado ya escrita las señala | ⚠️ **`fallbackTarget` gana sobre el `target` declarado en el morfo pese a su nombre** (`runtime.svelte.ts:757`). Es la causa raíz de dos de las filas. Decidir si se renombra o se documenta. ### 3.2 Los silenciosos - **`preload()` se cuelga en `resume()`** fuera de un gesto → no precarga nada Y abre un `AudioContext` en el arranque de la página (`engine-sound.ts:248`). - **Las opciones de motor se descartan en silencio**: `createActiveUix({ events: { sound: { masterGain: 0.5 } } })` compila y **no hace nada** — `EngineSemantic` filtra las claves antes de construir el canal (`engine.ts:299-319`). El aviso que existe en `SoundChannel` no llega a dispararse. - **El fallback de sample es mudo**: 4 salidas de fallo sin un diagnóstico, y el catálogo `SOUND_DIAGNOSTIC_EVENTS` no tiene evento para ello. Un 404, un CORS o un códec no soportado quedan enmascarados para siempre. - **3 de los 5 WAV son código muerto**: `whoosh`, `pop`, `ding` no los referencia ningún pack. - **Tipos**: la rama `Record` de `SemaSignatureOverride` desactiva toda comprobación de clave y valor — un `gain` de tipo _string_ llega hasta el audio. - **`applyMapOverrides` se traga las erratas de ruta** y crea ramas fantasma. ### 3.3 El interruptor Sound del topbar de las demos no silencia nada `web/routes/uix/+layout@.svelte` no pasa `preferences` al canal, que se queda en `'full'`. El framework sí lo soporta. Medido y sin tocar (viene del hilo del audio, `CONTINUE-sound-engine.md`). ### 3.4 El `announce` no compila `AnnounceFn` toma la prioridad en una bolsa de opciones y `uix.announce` la toma posicional; y **ninguna raíz cablea el canal**, así que activarlo cae en el fallback que añade un SEGUNDO par de live regions. `sema.md` ya enseña el adaptador de una línea; falta la decisión de código. ### 3.5 La instantánea perceptual ← la que impide que todo esto vuelva Guard propuesto y aprobado: una **tabla commiteada con la firma resuelta de cada (componente, evento, intent neutral)** — gain, hold, háptico. Cualquier cambio en algo que el usuario percibe rompe el test hasta que la instantánea se actualice **en el mismo commit**, así que el cambio aparece en el diff en vez de esconderse dentro de un pack. Habría cazado de golpe toda la clase 3.1. ### 3.6 Recalibrar los gains tras el fix del AM Los earcons con rugosidad bajaron 1.6–2.7 dB porque el trémolo ya no suma nivel. Es corrección, no pérdida, pero cambia el volumen percibido de `signal` y de todo `risk`/`threat`. Decisión de catálogo. ### 3.7 Ejes, no tareas - **`contact` está ausente en 84 de los 91 morfos con eventos.** Hoy lo expresan 7 (los tres toggles de esta sesión + button, file-upload, navigation-menu, palabras). El libro le dedica el capítulo 22 entero y CANON §8 lo pone como regla 1: «contact precede al resultado cuando hay acción directa». Es el eje que explica por qué media interfaz no responde al «¿me has sentido?». - **`Toolbar.Button` reimplementa su `