- 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
4.8 KiB
4.8 KiB
Delta: generate-song
ADDED Requirements
Requirement: CLI generates REAPER .rpp from arguments
scripts/generate.py MUST accept --bpm, --key, --output, and --seed arguments.
When invoked as python scripts/generate.py --bpm 95 --key Am --output output/song.rpp --seed 42,
the script SHALL produce a valid REAPER .rpp file at the specified output path using seed 42 for all random choices.
Scenario: Happy path — produces 52-bar arrangement
- GIVEN no arguments beyond required ones;
seed=42is the default - WHEN the CLI is invoked with
--bpm 95 --key Am --output /tmp/song.rpp --seed 42 - THEN a .rpp file SHALL be written containing 9 tracks (7 normal + 2 return)
- AND the arrangement duration SHALL equal 52 bars at 95 BPM
- AND all 19 plugins (across tracks, returns, master) SHALL be present in the FX chains
Scenario: Default seed produces reproducible output
- GIVEN two invocations with identical arguments (including
--seed 42) - WHEN both are run in the same environment
- THEN the resulting .rpp files SHALL be byte-for-byte identical
Scenario: Invalid BPM raises ValueError
- GIVEN
--bpm 0or--bpm -10 - WHEN the CLI is invoked
- THEN a
ValueErrorSHALL be raised with message matchingbpm must be > 0
Requirement: validate_rpp_output(rpp_path) -> list[str] checks all structural invariants
The validation function MUST return an empty list for a valid .rpp, and a list of error strings for any violation.
Scenario: Returns empty list for valid output
- GIVEN a .rpp produced by the CLI with all required structure
- WHEN
validate_rpp_output(path)is called - THEN the result SHALL be
[]
Scenario: Detects wrong track count
- GIVEN a .rpp with fewer than 9 tracks
- WHEN
validate_rpp_output(path)is called - THEN the returned list SHALL include
"Expected 9 tracks, got N"
Scenario: Detects missing plugin chains
- GIVEN a .rpp where a track is missing its FXCHAIN block
- WHEN
validate_rpp_output(path)is called - THEN the returned list SHALL include
"Track 'X' missing FXCHAIN"
Scenario: Detects broken audio clip paths
- GIVEN a .rpp containing an audio clip whose
SOURCE WAVEpath does not exist on disk - WHEN
validate_rpp_output(path)is called - THEN the returned list SHALL include
"Audio clip path does not exist: /path/to/file.wav"
Scenario: Detects MIDI clips without notes
- GIVEN a .rpp containing a MIDI clip with zero notes
- WHEN
validate_rpp_output(path)is called - THEN the returned list SHALL include
"MIDI clip has no notes"
Scenario: Detects incorrect arrangement duration
- GIVEN a .rpp whose final item ends before the expected 52-bar duration at the given BPM
- WHEN
validate_rpp_output(path)is called - THEN the returned list SHALL include
"Arrangement ends at beat X, expected at least Y"
Scenario: Detects missing send routing
- GIVEN a .rpp where a non-return track has no
AUXRECVsend to a return track - WHEN
validate_rpp_output(path)is called - THEN the returned list SHALL include
"Track 'X' missing send to return track"
Requirement: scripts/generate.py uses REAPER drumloops with fallback
The script SHALL pick drumloop files from the Ableton drumloop directory, cycling through available files per variant, and SHALL fall back gracefully when a file is absent.
Scenario: Picks from seco and filtrado variants
- GIVEN the CLI is run with
--seed 42 - WHEN the resulting .rpp is inspected
- THEN audio clips SHALL reference files from the
secoandfiltradopools as defined inDRUMLOOP_FILES - AND the variant per section SHALL follow
DRUMLOOP_ASSIGNMENTS
Scenario: Falls back when perc loop file is missing
- GIVEN the file
91bpm bellako percloop.wavdoes not exist - WHEN
build_perc_trackis called for a verse or chorus section - THEN no Perc clip SHALL be added for that section (skip silently rather than crash)
Requirement: Test suite for generate-song
A test file at tests/test_generate_song.py MUST cover the CLI and validation function.
Scenario: CLI end-to-end smoke test
- GIVEN
tmp_pathfixture - WHEN
python scripts/generate.py --bpm 95 --key Am --output {tmp_path}/song.rpp --seed 42is executed as a subprocess - THEN the resulting file SHALL exist and be non-empty
Scenario: Validation passes for valid output
- GIVEN a generated .rpp at a known path
- WHEN
validate_rpp_output(path)is called - THEN it SHALL return
[]
Scenario: Validation detects track count violation
- GIVEN a .rpp with 5 tracks (not 9)
- WHEN
validate_rpp_output(path)is called - THEN the error list SHALL contain a track-count violation message
Scenario: Reproducibility — same seed gives same output
- GIVEN two temp paths
- WHEN the CLI is run with
--seed 42to both paths - THEN both output files SHALL have identical content