# 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 <rpp_path> [--output <wav_path>] [--timeout <seconds>]`
- [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