# Design: Fix Musical Coherence ## Architecture Decisions ### AD1: Bass pattern — constant over composition The 808 bass pattern is a static 8-bar loop transposed by key. No section-specific variation needed since energy and velocity_mult handle intensity changes. ### AD2: Lead range constraint — filter in _resolve_chord_tones Rather than post-filter melody output, constrain chord_tones at the source. Remove oct_shift -12/+12 from _resolve_chord_tones(), keeping only oct_shift=0. This limits all chord tones to one octave around tonic (octave 4), producing melodies within ~12 semitones. ### AD3: Chord 7ths — change progression quality strings CHORD_TYPES already has m7=[0,3,7,10] and 7=[0,4,7,10]. Switch EMOTION_PROGRESSIONS from "min"/"maj" to "m7"/"7". Voice leading code handles any voicing size transparently. ### AD4: Pad movement — arpeggiate in build_pad_track Replace 3 sustained notes with ascending arpeggio: for each beat, play one chord note, cycling through chord tones. 0.5 beat duration (eighth note), 0.55 volume. Different octave (3) from chords (4). ### AD5: Ozone path — verify and harden The `_build_plugin()` lookup in `_build_master_fxchain()` already resolves correctly from PLUGIN_REGISTRY. Fix by verifying the path and adding an assertion/guard so empty path never reaches the VST element. ## Implementation Notes ### File changes 1. `scripts/compose.py`: - Replace BASS_PATTERN_8BARS with 4-note sparse pattern - Replace build_pad_track() with arpeggiated version 2. `src/composer/melody_engine.py`: - `_resolve_chord_tones()`: remove oct_shift in (-12, 12), keep only 0 3. `src/composer/chords.py`: - EMOTION_PROGRESSIONS: "min"→"m7", "maj"→"7" 4. `src/reaper_builder/__init__.py`: - `_build_master_fxchain()`: use PLUGIN_REGISTRY to populate PluginDef path ### Test updates - test_compose.py: verify bass note positions - test_melody_engine.py: verify range constraint - test_chords.py: verify 4-note voicings - test_calibrator.py: verify Ozone master chain