# Tasks: reascript-hybrid ## Phase 1: Foundation — Protocol Layer - [x] 1.1 Create `src/reaper_scripting/commands.py` with `ReaScriptCommand` and `ReaScriptResult` dataclasses matching the JSON schemas in the spec - [x] 1.2 Implement `write_command(path: Path, cmd: ReaScriptCommand) -> None` — serializes to JSON with `version: 1` - [x] 1.3 Implement `read_result(path: Path) -> ReaScriptResult` — deserializes JSON; raises `ProtocolVersionError` if `version != 1` - [x] 1.4 Add `ProtocolVersionError` exception class ## Phase 2: Core — ReaScript Generator - [x] 2.1 Create `src/reaper_scripting/__init__.py` with `ReaScriptGenerator` class - [x] 2.2 Implement `generate(path: Path, command: ReaScriptCommand) -> None` — writes a self-contained Python ReaScript - [x] 2.3 The generated script must include hand-rolled JSON parser (~20 lines of string splitting) — no `import json` - [x] 2.4 The generated script must call `GetFunctionMetadata` to verify API availability on startup - [x] 2.5 The generated script must implement the full Phase 2 pipeline: open project → verify FX → calibrate tracks → render → measure LUFS → write result - [x] 2.6 The generated script must handle errors and write `{"status": "error", "message": "..."}` on failure - [x] 2.7 Write `tests/test_commands.py` — test JSON round-trip, version mismatch raises `ProtocolVersionError` - [x] 2.8 Write `tests/test_reagenerator.py` — parse generated script with `ast.parse`, verify it contains required API calls (`Main_openProject`, `TrackFX_GetCount`, `TrackFX_GetFXName`, `SetMediaTrackInfo_Value`, `CreateTrackSend`, `Main_RenderFile`, `CalcMediaSrcLoudness`) ## Phase 3: Integration — CLI Orchestration - [x] 3.1 Create `scripts/run_in_reaper.py` CLI entry point - [x] 3.2 CLI must accept `python scripts/run_in_reaper.py [--output ] [--timeout ]` - [x] 3.3 CLI generates ReaScript file to `REAPER ResourcePath()/scripts/fl_control_phase2.py` - [x] 3.4 CLI writes command JSON to `REAPER ResourcePath()/scripts/fl_control_command.json` - [x] 3.5 CLI polls for `fl_control_result.json` until it exists or timeout reached - [x] 3.6 CLI parses result and prints LUFS metrics; exits 0 on success, 2 on timeout, 1 on error - [x] 3.7 CLI writes `output/song_lufs.json` and `output/song_fx_errors.json` on success ## Phase 4: Integration Test (Manual) - [ ] 4.1 Run `pytest tests/test_phase2.py -k integration` against live REAPER with registered custom Action — skipped in CI - [ ] 4.2 Verify full pipeline: .rpp opens, FX verified, tracks calibrated, render completes, LUFS measured - [ ] 4.3 Verify `fx_errors` correctly identifies a missing plugin slot (empty string from `TrackFX_GetFXName`) - [ ] 4.4 Verify timeout exits with code 2 when REAPER is not running