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/process/CONTINUE-sound-engine.md

90 lines
4.4 KiB

refactor(sound): extraer el motor Web Audio de sema al art `$sound` `sema/chans/sound.ts` tenía 407 líneas de las que ~255 (≈63%) eran maquinaria Web Audio —ciclo de vida del AudioContext, síntesis, samples, desbloqueo por gesto— mezclada con doctrina perceptiva. Deuda arrastrada, con tres síntomas medidos: el import era estático, así que toda app con sema metía el sintetizador en el bundle aunque el sonido estuviera apagado (que es el default); faltaba ciudadanía que `$scene` ya resuelve; y la costura de inyección (`audioContextFactory`) llevaba ahí sin usar desde el principio. Mismo movimiento que `$motion` hizo desde eidos: el art se lleva el RUNTIME, la capa conserva sus DATOS y su doctrina. - `$sound` / `EngineSound`: UN AudioContext por documento (los navegadores los limitan y el gesto de desbloqueo es por contexto), síntesis de earcon, samples con caché y fallback a síntesis, `autoSuspend` OPT-IN —suspender con la pestaña oculta es correcto para earcons y erróneo para contenido, así que es decisión de quien compone— y aviso cuando un segundo contexto va vivo. Puertos `SoundDom` / `SoundTimers` inyectados; no importa ningún otro art ni nada de `$uix/sema`, que es la prueba objetiva del corte. - `SoundChannel`: 407 → 136 líneas. Solo doctrina: el gate de `prepare`, la política de reducción y el reparto «el canal resuelve el NIVEL, el motor aplica la ganancia». Sema no gana ni un import: recibe el motor por puerto. - `uix.sound` en standalone y attach con `ownsSound` (idioma ya shipped: `ownsMotion` / `ownsScene`), fila `sound` en la tabla ejecutable `contracts.ts`, y `defineEngineSound()` para el camino de app. - Tests nuevos: `engine-sound.test.ts` (11), `sound-port.test.ts` (guard de deriva de tipos + la regla de propiedad) y `sound-e2e.test.ts`, que recorre `emit -> cascada -> canal -> art -> grafo real`: el camino que las 16 suites previas no cubrían porque paraban en canales falsos. Sin `diagnostics.ts` ni `errors.ts`, y es decisión: espejo de `$scene`, aquí todo fallo es degradación documentada, no error de programador. Verificación: 17 suites / 198 tests · `check` en la baseline exacta (73 errores, 0 propios) · `sound.test.ts` verde SIN tocar un solo assert, que era el criterio de que el movimiento fue value-preserving. Planes: `PLAN-sound-engine.md` (completo, con el registro de la revisión adversarial E-1..E-7), `PLAN-audio-player.md` (aparcado tras el análisis del reproductor, con sus correcciones en cabecera) y `CONTINUE-sound-engine.md` (handoff). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
# CONTINUE — motor de sonido + reproductor
> **Kickoff para la sesión siguiente**: *"Lee `docs/process/CONTINUE-sound-engine.md`
> y sigue por donde toque."*
> **Fecha**: 2026-07-30 · Rama `alpha-0.1-sec-dom`.
Handoff corto. La verdad detallada vive en los dos planes; esto solo dice **en
qué punto está cada cosa y qué trampas evitar**.
---
## Estado
| Iniciativa | Estado |
| --- | --- |
| [`PLAN-sound-engine.md`](./PLAN-sound-engine.md) | ✅ **COMPLETA** — F0…F4 hechas. Solo queda F5 (desbloquear el reproductor), que es decisión de sesión |
| [`PLAN-audio-player.md`](./PLAN-audio-player.md) | ⏸️ **APARCADO** — D-AP.1…D-AP.12 sin firmar. Su cabecera lleva **5 correcciones pendientes de incorporar** antes de presentar nada |
## Qué se construyó
**`$sound` / `EngineSound`** ([`src/arts/sound/`](../../src/arts/sound/README.md)) — el
runtime Web Audio extraído de `sema/chans/sound.ts`, que tenía ~63% de máquina
mezclada con doctrina. Un `AudioContext` por documento, síntesis de earcon,
samples con caché y fallback, desbloqueo por gesto, `autoSuspend` opt-in y aviso
al segundo contexto vivo.
- `SoundChannel`: **407 → 136 líneas**, solo doctrina (gate de `prepare`,
política de reducción, «el canal resuelve el NIVEL, el motor aplica la
ganancia»).
- Sema **no importa el art**: lo recibe por puerto inyectado.
- `uix.sound` en ambos modos de arranque, con `ownsSound` (idioma ya shipped:
`ownsMotion` / `ownsScene`), fila en la tabla ejecutable `contracts.ts`, y
`defineEngineSound()` para attach.
**Gate al cerrar**: 17 suites / 198 tests · `check` en la baseline exacta
(73 errores, 0 propios) · `sound.test.ts` verde **sin tocar un solo assert**.
## Lo que NO está verificado (y hay que verificar)
1. **La invariante de contexto único en un navegador real.** Hoy **ninguna**
página enchufa `soundEngine` a su propio `EngineSemantic` — el estudio de
sema incluido ([`temas/sema/_lib/audition.ts:35`](../../web/routes/temas/sema/_lib/audition.ts)
monta el suyo con `sound: true`), así que esa página abre un **segundo
contexto**. Con el aviso nuevo ya lo dirá por consola: **abrir `/temas/sema`
y mirar el warn es la primera comprobación de mañana.** Arreglo natural:
pasarle `soundEngine: uix.sound`.
2. **La escucha comparativa fina.** El usuario confirmó que suena, pero no se
hizo un A/B earcon a earcon contra el comportamiento previo.
## Trampas de este repo (verificadas a base de perder tiempo)
- **NO arrancar un dev server si el del usuario está vivo.** `npm run dev` es
`vite dev --force`: reescribe `node_modules/.vite/deps` por debajo del que
corre → dos runtimes de Svelte → la página deja de hidratar
(`lifecycle_outside_component`) → parece regresión de audio y no lo es.
Pasó el 2026-07-30. Verificar con **tests deterministas** (dobles de
`AudioContext`), no levantando servidores.
Recuperación (PowerShell): parar node →
`Remove-Item -Recurse -Force node_modules/.vite/deps` → `npm run dev` →
**Ctrl+Shift+R**.
- **El panel del navegador no pinta** en este entorno (viewport 0×0);
`javascript_tool` sí funciona.
- **Filtrar `npm run check` con cuidado**: las rutas llevan `\\` doble, así que
un patrón `sema.chans` NO casa con `sema\\chans` y da falsos «0 errores
propios». Ocurrió.
- **El árbol está compartido con otras sesiones** (palabras, menubar,
dropdown-menu, blocks/cta, alpha…). `git reset -q` + `add` solo lo propio,
siempre en un bloque atómico.
## Ajenos y preexistentes detectados (NO tocados)
- `contracts.test.ts` 3 rojos: `aura`, `menubar`, `radio-group`.
- `docs:check` 1 error: `eidos/components/callout/README.md:23` dice «8 roles»,
son 9.
- `Board.svelte:42` warn `binding_property_non_reactive` — inofensivo ahí
(lectura imperativa); se arregla con `let els = $state({})`.
- `temas/sema/_lib/audition.ts` tiene 2 errores de tipos preexistentes.
## Siguientes pasos posibles
1. **F5** — desbloquear el reproductor y reescribir su **D-AP.11** contra el art
ya existente (su premisa —«no hay motor»— era falsa).
2. **Cerrar la invariante**: pasar `soundEngine` al `EngineSemantic` del estudio
y comprobar que el warn desaparece.
3. **Retomar el reproductor** por su F0: firmar D-AP.\* con las 5 correcciones
de la cabecera ya incorporadas (segmentos, G-2 bloqueante, ducking…).
**No registrado en `next-features.md` a propósito**: ese fichero está modificado
por otra sesión y no se toca desde aquí.

Powered by TurnKey Linux.