Files
renato97 48bc271afc feat: SDD workflow — test sync, song generation + validation, ReaScript hybrid pipeline
- compose-test-sync: fix 3 failing tests (NOTE_TO_MIDI, DrumLoopAnalyzer mock, section name)
- generate-song: CLI wrapper + RPP validator (6 structural checks) + 4 e2e tests
- reascript-hybrid: ReaScriptGenerator + command protocol + CLI + 16 unit tests
- 110/110 tests passing
- Full SDD cycle (propose→spec→design→tasks→apply→verify) for all 3 changes
2026-05-03 22:00:26 -03:00

112 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Archive: reascript-hybrid
**Archived**: 2026-05-03
**Status**: Complete — 110 tests pass (verify PASS)
---
## Summary
Added a Phase 2 pipeline that runs inside REAPER via ReaScript for FX verification, track calibration, audio rendering, and loudness measurement. Phase 1 (.rpp generation via RPPBuilder) is unchanged and works standalone. The two-phase architecture enables offline composition with in-DAW verification.
---
## Specs Synced
| Domain | Action | Details |
|--------|--------|---------|
| reascript-generator | Created | ReaScriptGenerator class, command protocol, ReaScript API subset, Phase 2 pipeline steps |
New `reascript-generator` domain capability added to the system.
---
## Files Changed
| File | Change | Description |
|------|--------|-------------|
| `src/reaper_scripting/__init__.py` | Created | `ReaScriptGenerator` class — generates self-contained Python ReaScript files |
| `src/reaper_scripting/commands.py` | Created | `ReaScriptCommand`, `ReaScriptResult` dataclasses + `write_command()`, `read_result()`, `ProtocolVersionError` |
| `scripts/run_in_reaper.py` | Created | CLI entry point for Phase 2: generate script → write command JSON → poll result → print LUFS |
| `tests/test_reaper_scripting.py` | Created | 16 unit tests (command protocol, generator output, error handling) |
---
## Tasks Completed
All 3 implementation phases per `tasks.md` — all complete. Phase 4 (integration test against live REAPER) marked manual/skipped.
**Phase 1 — Protocol Layer (1.11.4)**: `commands.py` with `ReaScriptCommand`, `ReaScriptResult`, `write_command()`, `read_result()`, `ProtocolVersionError`.
**Phase 2 — ReaScript Generator (2.12.8)**: `ReaScriptGenerator` in `__init__.py` generating self-contained Python ReaScript with hand-rolled JSON parser, API availability check, full Phase 2 pipeline, and error handling.
**Phase 3 — CLI Orchestration (3.13.7)**: `run_in_reaper.py` with argparse CLI, script path resolution via REAPER ResourcePath, command/result JSON round-trip, timeout handling, LUFS output files.
**Phase 4 — Integration Test (4.14.4)**: Manual testing against live REAPER — skipped in CI.
---
## Verification
- **Test result**: 110 tests pass (`pytest tests/ -q`)
- **New tests**: 16/16 pass (`pytest tests/test_reaper_scripting.py -v`)
- **Implementation**: `ReaScriptGenerator.generate()` writes valid Python; protocol round-trips correctly; `ProtocolVersionError` raised on version mismatch
---
## Architecture Decisions
| Decision | Choice | Rationale |
|----------|--------|-----------|
| JSON file protocol over python-reapy | `fl_control_command.json` / `fl_control_result.json` in REAPER ResourcePath | No network dependency; REAPER owns timing; JSON is human-readable for debugging |
| Self-contained ReaScript (no `import json`) | Hand-rolled JSON parser via string splitting (~20 lines) | Maximum REAPER version compatibility; avoids import-time failures |
| Separate `commands.py` for protocol | `ReaScriptCommand`, `ReaScriptResult` isolated from generator | Protocol is stable and testable in isolation |
| `track_calibration` JSON array | Stateless interface for volume/pan/sends per track | Retry-friendly; command JSON valid for replay if REAPER crashes mid-calibration |
---
## ReaScript Hybrid Pipeline
```
Phase 1 (offline, Python) Phase 2 (inside REAPER, ReaScript)
───────────────────────── ─────────────────────────────────
RPPBuilder.build() Main_openProject(rpp_path)
│ │
▼ ▼
output/song.rpp TrackFX_GetCount + TrackFX_GetFXName
→ fx_errors (missing plugins)
│ │
│ SetMediaTrackInfo_Value(VOLUME/PAN)
│ CreateTrackSend for each send
│ │
│ ▼
│ Main_RenderFile → output/song.wav
│ │
│ ▼
│ CalcMediaSrcLoudness
│ → integrated_lufs, short_term_lufs
│ │
│ ▼
│ write result.json
run_in_reaper.py
→ generate phase2.py
→ write command.json ──────────────────────────────►
→ poll result.json ◄──────────────────────────────
→ print LUFS, write fx_errors.json
```
---
## Archive Contents
- `proposal.md`
- `spec.md`
- `design.md`
- `tasks.md` ✅ (11/12 tasks complete — Phase 4 manual)
---
## SDD Cycle Complete
The change has been fully planned, implemented, verified, and archived. Ready for the next change.