17 KiB
CONTINUE — auditoría del sistema semántico y sus arreglos
Kickoff para la sesión siguiente: «Lee
docs/process/CONTINUE-sema-audit.mdy sigue por la cola de §3, empezando por las 17 reglas.» Fecha: 2026-08-06 · Ramaalpha-0.1-dir-prefs(compartida — otra sesión trabaja enblocks;git reset -q+ add sólo lo propio, siempre). Fuente de verdad de los hallazgos: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 intentriskera −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 encompile.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/delegatesalen de la lista — sin base no hay nada que aplastar, y los 14 usos desound()sobrehandleson la única fuente sonora del gesto. - D.8 reescrita:
activeChannelses el DEFAULT de la familia, no una prohibición.channelsajusta 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, 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 §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 enresume()fuera de un gesto → no precarga nada Y abre unAudioContexten 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 —EngineSemanticfiltra las claves antes de construir el canal (engine.ts:299-319). El aviso que existe enSoundChannelno llega a dispararse. - El fallback de sample es mudo: 4 salidas de fallo sin un diagnóstico, y el
catálogo
SOUND_DIAGNOSTIC_EVENTSno 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,dingno los referencia ningún pack. - Tipos: la rama
Record<string, DeltaValue>deSemaSignatureOverridedesactiva toda comprobación de clave y valor — ungainde tipo string llega hasta el audio. applyMapOverridesse 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
contactestá 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.Buttonreimplementa 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
synthesizey medir pico / RMS / amplitud en el corte. El patrón exacto está en los mensajes de316452263y24d30ee1a. - 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:
MutationObserversobredata-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).