# Spec: Fix Musical Coherence

## Requirements

### R1: Bass Pattern
- 808 Bass MUST use i-iv-i-V pattern over 8 bars
- Each chord gets 2 bars with 1 note on beat 1.0, duration 1.5 beats
- Pitch sequence for Am: A1(33), D2(38), A1(33), E2(40)
- Transposed by key difference from Am

### R2: Lead Melody
- Lead notes MUST NOT exceed 12 semitones between consecutive notes
- Melody MUST use chord tones on strong beats (1 and 3)
- Scale-based passing tones allowed on weak beats
- Octave range constrained to ±6 semitones from root

### R3: Chord Voicings
- ChordEngine MUST produce 4-note voicings (root, 3rd, 5th, 7th)
- Use m7 for minor chords, 7 for major chords
- Voice leading keeps movement ≤4 semitones per voice
- First chord respects requested inversion

### R4: Pad Movement
- Pad MUST have rhythmic movement (arpeggiated eighth-notes)
- Cycle through chord notes in ascending order
- Volume: 0.55 (prevents masking)
- Duration per note: 0.5 beats (eighth note)

### R5: Ozone 12
- Master chain PluginDef MUST have correct .vst3 path
- Filename field MUST match PLUGIN_REGISTRY entry exactly
- No fallback to empty string path

## Scenarios

### S1: Bass timing verification
Given: 8-bar section, key Am, bpm=95
When: build_bass_track runs
Then: First 4 notes at start positions 0.0, 8.0, 16.0, 24.0 (beats)
And: durations all 1.5
And: pitches 33, 38, 33, 40

### S2: Lead range constraint
Given: 4-bar hook motif in Am
When: build_motif(style="hook") runs
Then: all(n.pitch for n in motif) within 12 semitones of tonic
And: max pitch - min pitch ≤ 12

### S3: Chord voicing size
Given: Emotion "romantic", key "Am", 8 bars
When: engine.progression(bars=8) runs
Then: Each voicing has len() == 4
And: Notes include root, 3rd, 5th, 7th intervals

### S4: Pad arpeggiation
Given: 8-bar section, Am key
When: build_pad_track runs
Then: Clip has >24 MIDI notes (arpeggiated, not 3 sustained)
And: Each note duration ≤ 0.5 beats

### S5: Ozone vst3 path
Given: SongDefinition with master_plugins after Calibrator.apply()
When: RPPBuilder writes master FXCHAIN
Then: VST element filename field is "Ozone 12 Equalizer.vst3"
