# Tasks: generate-song CLI ## Phase 1: Foundation — RPP Validator - [x] 1.1 Create `src/validator/rpp_validator.py` with `validate_rpp_output(rpp_path: str) -> list[str]` - [x] 1.2 Implement track count check — count `` blocks with ``, count `NOTE \d+ \d+ \d+` entries - [x] 1.5 Implement arrangement duration check — find last item position + length, assert >= 52 bars × 4 beats - [x] 1.6 Implement send routing check — each non-return track must have `AUXRECV` - [x] 1.7 Implement plugin chain check — each non-return track must have `` with `VST` entry ## Phase 2: Core Implementation — CLI Wrapper - [x] 2.1 Create `scripts/generate.py` with argparse: `--bpm` (float, default 95), `--key` (default "Am"), `--output` (default "output/song.rpp"), `--seed` (int, default 42), `--validate` (flag) - [x] 2.2 Add BPM validation — raise `ValueError` if `bpm <= 0` - [x] 2.3 Add output directory creation — `output_path.parent.mkdir(parents=True, exist_ok=True)` - [x] 2.4 Wire `compose.main()` — set `sys.argv` and call `compose.main()` directly (not subprocess) - [x] 2.5 Wire `--validate` flag — call `validate_rpp_output()` and `sys.exit(1)` on errors ## Phase 3: Testing - [x] 3.1 Write `tests/test_generate_song.py::test_generate_cli_smoke` — subprocess call, assert returncode 0, file exists, size > 0 - [x] 3.2 Write `tests/test_generate_song.py::test_validate_passes_for_valid_output` — CLI with `--validate`, assert `errors == []` - [x] 3.3 Write `tests/test_generate_song.py::test_validate_detects_track_count_violation` — synthesize 5-track .rpp, assert "Expected 9" in errors - [x] 3.4 Write `tests/test_generate_song.py::test_reproducibility_same_seed` — run CLI twice with `--seed 42`, assert byte-identical output ## Phase 4: Verification - [x] 4.1 Run full test suite — `pytest tests/` — verify all 90+ tests pass (existing + new) - [x] 4.2 Run new tests in isolation — `pytest tests/test_generate_song.py -v` — confirm 4 tests pass