|
|
# 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
|
|
|
|
|
|
> **ACTUALIZADO 2026-08-06 tarde.** §3.1 está CERRADA y §3.6 quedó absorbida por
|
|
|
> un eje nuevo que abrió el autor: **el sonido se NOMBRA**
|
|
|
> ([`PLAN-sound-names.md`](./PLAN-sound-names.md), F1–F6 entregadas). Ver §3.0
|
|
|
> antes que nada; lo que sigue vivo es §3.2, §3.3, §3.4, §3.5 y §3.7.
|
|
|
|
|
|
### 3.0 Lo cerrado el 2026-08-06 por la tarde
|
|
|
|
|
|
| Commit | Qué |
|
|
|
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
| `f7a7564b3` | **`allowedTargets`** — el morfo declara a qué partes puede viajar el estampado. Simétrico de `allowedFamilies`, con invariante en `schema.ts`. Resolvió las 12 divergencias que el censo destapó (calendar ×5, pagination ×5, rating-group, toolbar) |
|
|
|
| `0c1d945ba` | **S-12 textarea** (medido 0.30→0.05 y 0.40+risk→0.03) y **S-13 tree-view** (el teclado ya emite) |
|
|
|
| `2f63525da` | **`pack-census.test.ts`** — 4 invariantes mecánicos por regla; nació en rojo, reprodujo la auditoría y destapó dos clases nuevas |
|
|
|
| `7154fb77e` · `769e426c5` | **El sonido se NOMBRA**: catálogo de 16 nombres, tipo estrechado a `SoundName \| SILENT`, reorden del resolver (el nombre ANTES del intent), 71 packs migrados |
|
|
|
|
|
|
### 3.0-bis El sonido se REHIZO otra vez, y esta es la versión buena
|
|
|
|
|
|
⚠️ Lo de §3.0 sobre el catálogo de nombres **quedó superado el mismo día**. Al
|
|
|
oírlo, el autor rechazó el modelo de modulación entero: _«evento.intent =
|
|
|
sonido, y punto»_. Modelo vigente, en dos líneas:
|
|
|
|
|
|
```
|
|
|
nombre = per-emit ?? cascada ?? pack ?? morfo ?? familia[verbo] ?? familia.default
|
|
|
sonido = pack[`${nombre}.${intent}`] ?? pack[nombre] ?? nada
|
|
|
```
|
|
|
|
|
|
| Commit | Qué |
|
|
|
| --- | --- |
|
|
|
| `86fa9a1b7` | El sonido se ELIGE: tabla por verbo en el mapa, catálogo de 10 bases + 6 variantes diseñadas, resolver de dos búsquedas, guard de **distinguibilidad**, gestos por repetición (mueren los 3 resolvers), 135 reglas de pack borradas (de ~165 a 30) |
|
|
|
| `11b54025d` | Pack de ejemplo `ui-mp3` con los ficheros del autor, recortados y normalizados (arrancaban hasta a 347 ms) + `applySoundPack()` |
|
|
|
| `4f1b9d423` · `05d422ef4` | Las cuatro páginas de `/uix/docs/sound` |
|
|
|
|
|
|
**Nada de esto se ha oído en producción todavía** — está medido en el grafo de
|
|
|
audio, no con un oído sobre un componente real. Y el catálogo es una PROPUESTA:
|
|
|
que `open` suene a lo que debe sonar un panel abriéndose es decisión del autor,
|
|
|
y se afina en un fichero.
|
|
|
|
|
|
**Disuelto, no arreglado**: `SOUND_TUNINGS` retirado ⇒ **S-07 deja de existir**
|
|
|
(era su premisa) y **las 10 cabezas de tuning que mentían son hoy nombres**. D.7
|
|
|
retirada por el mismo motivo — con el nombre debajo del intent, aplastar el
|
|
|
perfil evaluativo es inexpresable. Razonado en
|
|
|
[`book-deviations.md`](../decisions/book-deviations.md) §D.7.
|
|
|
|
|
|
✅ **Renombrar `fallbackTarget` → `targetOverride`: HECHO el 2026-08-10** (202
|
|
|
apariciones, 64 ficheros; crónicas conservan el nombre viejo por diseño). Y dejó
|
|
|
de ser cosmético: es la PRECONDICIÓN del censo de emisión. Mientras la opción se
|
|
|
leía como un fallback, un provider que apuntaba a otra PARTE era
|
|
|
indistinguible de uno que apuntaba a la instancia correcta de la parte
|
|
|
declarada. Con el nombre honesto, el runtime puede afirmar la diferencia
|
|
|
(`assertTargetOverride`) y el guard censarla.
|
|
|
|
|
|
### 3.1 Las 17 reglas — CERRADA
|
|
|
|
|
|
Cerrada salvo tres decisiones que el autor no ha tomado y que viven como
|
|
|
**excepciones FIRMADAS** en `pack-census.test.ts` (el waiver registra, no
|
|
|
bendice; borrarlo es lo que cierra cada una):
|
|
|
|
|
|
| Pendiente | Estado |
|
|
|
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
|
| **5 reglas hápticas inertes** (S-30/S-38) | D.8 exige `channels` con justificación escrita, o borrar. ⚠️ Ampliar **destapa S-31**: `shift`/`emerge` no tienen `base.haptic`, así que las firmas parciales (`{kind:'tick'}`) resuelven a `vibrate(NaN)` — hay que completarlas en el mismo commit |
|
|
|
| **gradient-picker `commit-reset`** (S-14) | Verbo delegado: el `Picker` compuesto ya emite el suyo. Es 1 de **6 casos idénticos** (color/date/date-range/gradient/time/time-range) |
|
|
|
| **tooltip `present`/`dismiss`/`dismiss-escape`** | HALLAZGO NUEVO, no está entre los 44: **no existe una sola llamada `trigger(` en `soma/components/tooltip`**. Su regla casa por familia, así que nada dispara y el silencio de hoy es accidental, no el declarado |
|
|
|
|
|
|
Censo de eventos huérfanos (medido): **14 de 249** en 104 morfos con soma. Tres
|
|
|
clases — verbo delegado (6), punto de extensión documentado en prosa
|
|
|
(virtual-list / virtual-grid `handle-scroll*`, que merecerían un `emission: 'app'`
|
|
|
declarado) y contrato muerto (tooltip). Más chronos ×2 (la exclusión de escritura
|
|
|
se levantó el 2026-08-10 — ya accionables).
|
|
|
|
|
|
### 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<string, DeltaValue>` 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 — **ARREGLADO**
|
|
|
|
|
|
`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`).
|
|
|
|
|
|
**Cableado el 2026-08-06 (`d161cedcc`) y medido en navegador el 2026-08-12**:
|
|
|
`SemaPreferences` vivo en el layout, toggle → `'full' | 'off'`; A/B con parche
|
|
|
de prototipo — Sound ON +2 osciladores por click, OFF +0. Detalle en
|
|
|
`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 — ABSORBIDA por el catálogo de nombres
|
|
|
|
|
|
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`.
|
|
|
|
|
|
Sigue siendo decisión de catálogo — y **ahora el catálogo existe**: los niveles
|
|
|
viven en 16 nombres dentro de `src/uix/sema/sound-names.ts`, así que recalibrar
|
|
|
es editar ese fichero y ver el diff en `sound-names.test.ts`, que instantanea qué
|
|
|
suena cada nombre bajo cada intent. Antes había que tocar 71 packs a ciegas.
|
|
|
|
|
|
### 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 `<button>`** en vez de componer el de soma:
|
|
|
por eso nunca ha sonado, y no se arregla bajando un gain.
|
|
|
|
|
|
### 3.8 NO TOCAR sin reabrirlo — S-07
|
|
|
|
|
|
Los 14 afinados del catálogo fijan `gain` como número desnudo, que se aplica en
|
|
|
`replace` y borra el perfil evaluativo del intent (~150 usos). El usuario lo dejó
|
|
|
para tratarlo «más detenidamente». Las 9 reglas de §2.5 ya componen; **el resto
|
|
|
del catálogo sigue igual y es deliberado**.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 4. Cómo verificar en este hilo
|
|
|
|
|
|
- **Audio**: render offline replicando el grafo de `synthesize` y medir pico /
|
|
|
RMS / amplitud en el corte. El patrón exacto está en los mensajes de
|
|
|
`316452263` y `24d30ee1a`.
|
|
|
- **A/B siempre dentro del MISMO componente.** Comparar un Button de otra página
|
|
|
con el transporte del player produjo una contradicción falsa (registrado en
|
|
|
`CONTINUE-sound-engine.md`).
|
|
|
- **Emisión y estampado**: `MutationObserver` sobre `data-event*` del subárbol.
|
|
|
- **Silencio**: contar osciladores es válido para «¿llegó algo al motor?», NO
|
|
|
para «¿se oye?».
|
|
|
- **Mutear antes de reproducir y parar al terminar** — el Chrome que suena es el
|
|
|
del usuario.
|
|
|
- Guards: `sound-names.test.ts` (la instantánea del catálogo) ·
|
|
|
`pack-census.test.ts` (4 invariantes por regla) · `sounds-grammar.test.ts`
|
|
|
(ningún pack AUTORA) · `cascade-scope.test.ts` · `chans/sound.test.ts` ·
|
|
|
`engine-sound.test.ts`.
|
|
|
|
|
|
**Baseline actual** (2026-08-06 tarde, HEAD `769e426c5`): `check` **75** ·
|
|
|
`docs:check` **0/618** · sema+morfo+sound **437/437**. La suite completa deja 6
|
|
|
fallos en `contracts.test.ts` que son AJENOS y preexistentes (medido con y sin
|
|
|
los cambios de este hilo).
|
|
|
|
|
|
---
|
|
|
|
|
|
## 5. El corpus, si hay que releerlo
|
|
|
|
|
|
Núcleo indispensable (leído entero el 2026-08-06): `PLAN-sound-engine.md` ·
|
|
|
`PLAN-sound-redesign.md` · `CONTINUE-sound-engine.md` · `architecture/sema.md` ·
|
|
|
`CANON.md` · `theming/channels.md` · `arts/sound/README.md` ·
|
|
|
`decisions/book-deviations.md` (D.5 · D.7 · D.8 · D.9 · D.12).
|
|
|
|
|
|
El **libro** está en `docs/Disenando_lo_que_ocurre_FINAL.pdf` y el manuscrito en
|
|
|
`src/docs/*.docx`. El PDF no se puede renderizar aquí; el `.docx` es un zip —
|
|
|
extraer `word/document.xml` y quitar etiquetas da el texto completo. Capítulos
|
|
|
que decidieron cosas en esta sesión: **5 §11** y **7 §13** (el silencio es firma
|
|
|
válida), **20** (coordinación multicanal), **22** (contact) y **23** (commit, con
|
|
|
su tabla de canales y el emparejamiento del Toggle).
|