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

5.1 KiB
Raw Permalink Blame History

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.