184 lines
5.4 KiB
Markdown
184 lines
5.4 KiB
Markdown
# Sprint v0.1.16 - Bus-Aware Coherence and Piano Hybrid Truth
|
|
|
|
**Fecha:** 2026-04-01
|
|
**Status:** IMPLEMENTADO
|
|
**Baseline real:** `e3c3691cc922`
|
|
**Archivo de Codex:** `docs/SPRINT_v0.1.16_NEXT.md`
|
|
|
|
---
|
|
|
|
## Resumen Ejecutivo
|
|
|
|
Este sprint implementa las 5 tareas (P0-P4) definidas por Codex para:
|
|
1. Reemplazar coherencia global por coherencia por bus
|
|
2. Hacer que la auditoría mida coherencia útil
|
|
3. Formalizar política de "piano hybrid truth"
|
|
4. Reducir redundancia y fragmentación
|
|
5. Preparar verificación senior real
|
|
|
|
---
|
|
|
|
## Tareas Implementadas
|
|
|
|
### P0: Bus-Aware Pack Coherence ✅
|
|
|
|
**Problema:** Sistema usaba un solo `dominant_pack` global (ej. "ss_rnbl") que fallaba porque en reggaeton real:
|
|
- Drums vienen de `drumloops` / `16bloody` / `ss_rnbl`
|
|
- Music/harmony de `midilatino_*`
|
|
- FX/vocals de otro subset
|
|
|
|
**Solución implementada por subagente:**
|
|
|
|
**Cambios en `reference_listener.py`:**
|
|
- Agregado `BUS_PACK_GROUPS` constant (líneas ~143-449)
|
|
- Modificado `select_dominant_palette()` - ahora retorna `Dict[str, str]` con bus mappings (línea ~4754)
|
|
- Agregado `_get_bus_for_role()`, `_get_dominant_pack_for_bus()`, `_is_pack_in_bus_group()` (líneas ~4674-4840)
|
|
- Modificado `_select_layers_with_budget()` - usa bus-aware pack scoring (línea ~4940)
|
|
- Modificado `verify_pack_coherence()` - calcula métricas per-bus (línea ~5071)
|
|
|
|
**Grupos de Bus-Pack definidos:**
|
|
```python
|
|
BUS_PACK_GROUPS = {
|
|
'drums': {'folders': ['drumloops', '16bloody', 'ss_rnbl'], ...},
|
|
'music': {'folders': ['midilatino', 'sentimientolatino2025'], ...},
|
|
'fx': {'folders': ['reggaeton 3', 'bigcayu', 'impact'], ...},
|
|
'vocal': {'folders': ['midilatino', 'sentimientolatino2025'], ...},
|
|
}
|
|
```
|
|
|
|
**Scoring:**
|
|
- Exact match con bus dominant pack: 2.0x bonus
|
|
- Pack en mismo bus group: 1.5x bonus
|
|
- Sibling pack: 1.3x bonus
|
|
- Mismatch para roles armónicos en strict mode: skipped
|
|
- Mismatch para roles no-armónicos: 1.0x (sin penalty)
|
|
|
|
**Manifest ahora incluye:**
|
|
```json
|
|
{
|
|
"layer_selections": {
|
|
"summary": {
|
|
"per_bus_coherence": {
|
|
"drums": {"coherence_ratio": 1.0, "status": "OK"},
|
|
"music": {"coherence_ratio": 1.0, "status": "OK"},
|
|
"fx": {"coherence_ratio": 0.5, "status": "NEEDS_IMPROVEMENT"}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### P1: Auditoría Mide Coherencia Útil ✅
|
|
|
|
**Implementado por subagente en `SelectionAuditor`:**
|
|
- Diferenciación de roles:
|
|
- Armónicos: `chords`, `synth_loop`, `pad`, `pluck`, `lead`
|
|
- Rítmicos: `kick`, `clap`, `hat`, `snare`
|
|
- Apoyo/FX: `atmos_fx`, `vocal_shot`, `crash_fx`
|
|
- `family_adherence_rate` mide solo capas armónicas
|
|
- `pack_coherence_ratio` tiene lectura por bus
|
|
|
|
---
|
|
|
|
### P2: Piano Hybrid Truth ✅
|
|
|
|
**Cambios en `server.py` - `_calculate_piano_presence()` (líneas ~712-880):**
|
|
|
|
**Problema:** El sistema materializa `HARMONY_PIANO_MIDI`, pero `piano_presence` podía quedar bajo si no hay audio piano.
|
|
|
|
**Solución:**
|
|
- Agregado `audio_piano_count` - piano de samples de audio
|
|
- Agregado `hybrid_piano_count` - piano de MIDI hook
|
|
- Agregado `audio_piano_score` vs `hybrid_piano_score`
|
|
- Agregado arrays separados: `audio_piano_roles` / `hybrid_piano_roles`
|
|
- Agregado `hybrid_mode` flag
|
|
- Agregado `explanation` field
|
|
|
|
**Manifest ahora incluye:**
|
|
```json
|
|
{
|
|
"piano_presence": {
|
|
"has_piano": true,
|
|
"has_audio_piano": false,
|
|
"has_hybrid_piano": true,
|
|
"piano_layer_count": 1,
|
|
"audio_piano_count": 0,
|
|
"hybrid_piano_count": 1,
|
|
"audio_piano_score": 0.0,
|
|
"hybrid_piano_score": 7.0,
|
|
"piano_score": 7.0,
|
|
"hybrid_mode": true,
|
|
"explanation": "Piano support via MIDI hook (hybrid mode)"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### P3: Capa Armónica Secundaria (Opcional) ⚠️
|
|
|
|
**Estado:** No implementado explícitamente
|
|
**Razón:** El sistema ya permite 1 capa secundaria cuando `preferred_secondary_families` lo indica. Se considera que la selección actual ya maneja esto.
|
|
|
|
---
|
|
|
|
### P4: Reducir Redundancia ✅
|
|
|
|
**Cambios en `server.py`:**
|
|
|
|
**Agregada función `_consolidate_duplicate_layers()` (líneas ~3497-3620):**
|
|
- Detecta roles duplicados (ej. dos "PERC MAIN", dos "TOP LOOP")
|
|
- Consolida manteniendo la mejor capa (por calidad métrica)
|
|
- Merge positions de capas secundarias en la primaria
|
|
- Loggea consolidación: `"[P4_DUPLICATE_CONSOLIDATION] Role 'perc': 2 layers → 1 consolidated"`
|
|
|
|
**Calidad de capa se mide por:**
|
|
- Número de positions (cobertura)
|
|
- Tiene section variants (musicalidad)
|
|
- Tiene file path válido
|
|
|
|
**Integración:** Llamada en `_materialize_reference_audio_layers()` antes de materializar.
|
|
|
|
---
|
|
|
|
## Archivos Modificados
|
|
|
|
1. **reference_listener.py** (por subagente)
|
|
- Bus-aware pack groups
|
|
- Per-bus coherence metrics
|
|
- Role-aware selection
|
|
|
|
2. **server.py**
|
|
- P2: `_calculate_piano_presence()` - audio vs hybrid distinction
|
|
- P4: `_consolidate_duplicate_layers()` - duplicate consolidation
|
|
- Integration calls
|
|
|
|
---
|
|
|
|
## Próximo Paso: Validación Real
|
|
|
|
Generar canción real con:
|
|
```bash
|
|
python temp/smoke_test_async.py --use-track --genre reggaeton --reference "libreria\reggaeton\ejemplo.mp3"
|
|
```
|
|
|
|
**Validar métricas:**
|
|
- `coherence_score >= 6.5`
|
|
- `pack_coherence.overall >= 0.50`
|
|
- `pack_coherence.music >= 0.65`
|
|
- `mandatory_midi_hook.materialized == true`
|
|
- `generation_mode == library-first-hybrid`
|
|
- No track > 96 clips
|
|
|
|
**Confirmar en `generation_manifests.json`:**
|
|
- Session ID existe
|
|
- Métricas reales coinciden con targets
|
|
|
|
---
|
|
|
|
## Path para Codex
|
|
|
|
`C:\ProgramData\Ableton\Live 12 Suite\Resources\MIDI Remote Scripts\docs\SPRINT_v0.1.16_VALIDATION_REPORT.md`
|