- Pace dropdown REMOVED from Phrase setup — replaced by a 'Sync to
exercise' checkbox in the Metronome widget (analog to 'Auto' in
single-note modes). pace is derived from the checkbox (checked = tempo,
unchecked = step).
- Preview clicks now registered in PREVIEW_GROUP: stopping/abandoning a
preview cancels its scheduled clicks — no more parallel ghost
metronomes after preview->stop->next exercise.
- Chord pool replaces the chord dropdown entirely (single chord AND
sequences): togglable degree list, empty = all 7.
- Giuliani figures corrected to NOTE sequences (p always takes the bass/
root): p-i-m, p-i-m-a, p-a-m-i, a-i-m, p-i-m-a-m-i, p-m-a-m-i-m,
p-e-a-m-a-m (replaced the fingering-driven patterns that made no
musical sense).
- 'Limit notes' is now one bordered section like Tuner/Metronome, with a
header, Clear-all link, and Strings behind a toggle (row hidden until
restricted).
- MetronomeWidget: the Phrase Mode switch now lives IN the widget as a
Free/Sync toggle. Free = independent metronome (own clock, starts when
toggled, with or without clicks). Sync = silent while idle, starts with
the exercise (count-in included), pendulum mirrors the run's beats.
- Fixed double phraseBeatBus.emit (leftover from an earlier edit) that
flipped the pendulum twice per beat — animation appeared frozen.
- Click decision unified: one sound checkbox governs both the widget and
(in sync mode) the run's click scheduler. 'Click 1 after count-in' is
musically the last count-in click (suppressed duplicate) — now with a
working pendulum the offset is visible rather than confusing.
- Giuliani figures extended: p-i-m-a-m-i, p-a-p-i-m-a, a-m-i-p-i-m,
m-i-a-m-i-m (six-note rolling/bass-skip/tremolo-adjacent figures).
- Arpeggio chord pool: togglable degree list (empty = all 7); functional
and random progressions honor the pool; first bar draws a random chord
from the pool.
- Tests 174/174.
- MetronomeWidget rebuilt cleanly: ONE 'Click sound' checkbox (the earlier
restructure left duplicated option rows behind — neither worked). Widget
body always visible (dimmed when disarmed); toggle arms sound+pendulum.
- Click decision unified: 'sync to metronome' derives phrase clickSound
from the widget's sound checkbox (no separate phrase click option);
'at your pace' clicks when the metronome is armed.
- Chord selection: abwählbare Liste (arpeggioChordSelection) restricts
progression chords; first bar draws a random chord FROM THE SELECTION
(fixed first chord repeated the exercise identically).
- Scales: rhythm setting (quarters/eighths) shared with arpeggios;
drill id includes rhythm to invalidate cached scores.
- Beam fix: register Beam via note.setBeam so VexFlow suppresses flags
(eighths/16ths previously drew BOTH beam and flag).
- Metronome widget: BPM/slider row and pendulum always visible (dimmed
when off); the toggle gates sound + animation only. BPM/Timer mode
switch restored for single-note auto-advance.
- Giuliani right-hand figures as arpeggio patterns: p-i-m, p-i-m-a,
p-a-m-i, m-a-m-i, a-m-i — cycle [root, third, fifth, octave] per figure
with octave register shift per repetition (120-studies feel).
- Pool fix: fretted instruments without active filters now get the full
0-12 fretboard in ALL modes (legacy difficulty ranges no longer clamp
the pool since the Note Set dropdown was removed).
- Tests 174/174.
- Sequence mode: bars (2/4/6/8) with one chord per bar, chosen by
functional rules (I->IV/V/vi...), diatonic cycle, or random (no immediate
repeats); deterministic via melody seed. Chord symbols per bar in the
score model (chordSymbols) rendered above the staff via setSection.
- Rhythm: quarters or eighths (cycling up/down through the pattern).
- Single-chord mode unchanged (whole path, overflow bars if needed).
- Auto-start: 'Start on first note (no count-in)' — step pace begins the
run as soon as the mic detects the first note; no start press needed.
- 'New' button re-rolls the progression (new seed).
- Tests 174/174.
- music/arpeggioGenerator.ts: diatonic triads (I-vii*) built from the
selected key/mode via the shared degree spelling; patterns up / down /
up-down / 1-2-3-5; one or two octaves (cycle ends on the octave; two-
octave path continues from the turning root). Quarter-note rhythm with
final note extended to fill the bar; title is labeled 'Arpeggio -
<tonic> <degree> (pattern, coverage)'.
- Settings: PhraseMaterial 'arpeggio' + arpeggioDegree/Pattern/Coverage
(defaults I / up / one-octave).
- PhraseTrainer: material option 'Arpeggios (generated)' + Chord/Pattern/
Coverage/Meter selects; key/mode reuse the shared Target key controls.
- Tests: 9 arpeggio cases (170 total).
- Metronome/phrase: 'With tempo' renamed to 'Sync to metronome' (auto-enables
the metronome when selected); phrase click now yields to the metronome
click (no more double clicks) with an explicit opt-out checkbox.
- Count-in: subtle numeric badge next to the status line (muted pill, 11px).
- Melody rhythm level 3 'Elaborate': sixteenth/dotted-eighth templates for
4/4 and 3/4; renderer supports 120/360-tick codes and beams 16th pairs.
- Transpose control for library/import material widened to ±2 octaves.
- Tests 161/161 (bar-total invariants hold over 500 seeds at level 2).
- Strings filter: per-string toggle buttons (replaces fret-window-only
semantics as a third 'limits notes' control); combines with fret window
and key filter in targetPool (fretted instruments).
- Key sync checkbox: display key signature can follow the target key
(major/minor mapping), default off — both remain independently settable.
- LiveNoteStaff: optional fixed clef — guitar/bass now keep their usual
clef instead of flipping at middle C; octave markers handle range.
- Unified metronome widget (MetronomeWidget) with animated linear pendulum
synced to the audible click; shown in ALL modes next to the tuner.
Phrase BPM now reads from settings.rhythm.bpm (single source); the
phrase-local BPM control was removed from the setup panel.
- Tests: 160/160; tsc + eslint clean; build ok.
- New shared PracticeFilter settings (keyTonic/keyMode/fretWindow), persisted
via AppSettings.practice, defaults off (behavior unchanged).
- music/targetPool.ts: single source for the effective target pool —
base playable range ∩ fret window ∩ key/mode pitch classes (9 modes incl.
pentatonic, same scale machinery as Phrase Mode).
- useGameLogic now builds validNotes via computeTargetPool.
- TargetNoteControls component (key on/off + tonic/mode, fret window on/off +
min/max) rendered in Controls for all game modes; key is independent of the
displayed key signature.
- Phrase Mode binds its key/fret-window setup to the same shared filter
(read/write mirror) and drops the duplicate controls in its setup panel.
- Tests: targetPool.test.ts (7 cases); suite 156/156 green, build ok.
- color-scheme per theme so native controls (selects, checkboxes, number
inputs, sliders) render dark-native instead of black-on-black.
- Themed .control-select text color; new .control-input class replaces
hardcoded white-on-black inline input styles.
- Tuner widget stays mounted when enabled: idle state (dimmed, needle parked,
'—') instead of appearing/disappearing. Fully theme-var based (was
hardcoded white — invisible in light mode).
- Remove CSS transitions on per-frame values (tuner needle, level meter):
transitions interrupted 60x/sec are left stuck by WebKit/Safari; the
display EMA from the detection loop replaces them.
- VexFlow notation: resolve CSS var() to concrete colors (SVG attributes
can't resolve var(), silently fell back to black) and override VexFlow's
hardcoded #444 ledger-line default; re-render on theme changes
(useLayoutEffect so children read the updated attribute in time).
- Themed switch toggles (were hardcoded #ddd / white — glowed in dark mode).
- Fixed-height pitch readout so the layout stops jumping when a note starts
or stops sounding.
- Split SettingsContext into context/Provider/hook files (fast-refresh);
memoized provider functions; typed webkitAudioContext; prefer-const;
removed 'as any' casts. ESLint now passes clean.