Review phrase mode requirements and specify implementation contracts

This commit is contained in:
2026-09-14 00:21:43 +02:00
parent 0d11570b58
commit 6e24b94a91
2 changed files with 668 additions and 271 deletions

View File

@@ -1,300 +1,147 @@
# Phrase Mode — Requirements & Implementation Plan
# Phrase Mode — Reviewed Requirements & Plan
**Status: DRAFT — awaiting approval ("Go") before implementation.**
**Status: revised draft; implementation still requires the user's “Go”.**
This document describes a proposed third game mode ("Phrase Mode") for the Sheet
Music Trainer. It is written as stakeholder requirements: what the mode does,
what it deliberately does **not** do, how it will be built, and which decisions
need the owner's sign-off. Section 8 lists the open decisions together with the
defaults I will assume if no feedback arrives in time — so an autonomous
overnight run can proceed without blocking on any of them.
This replaces the initial GLM draft. The product direction is good; the review
corrects several music, audio, scope, and deployment assumptions. Implementation
must follow this document **and** [the implementation contract](docs/PHRASE_MODE_IMPLEMENTATION.md).
The contract makes behavior and acceptance tests explicit for the next model.
If they appear inconsistent, resolve the inconsistency before implementing;
do not treat the original draft in Git history as an alternative specification.
---
## 1. Recommendation
## 1. Vision
Add **Phrases**, alongside **Sight Reading** and **Ear Training**. Keep the
existing modes and their defaults. In Phrases, display a few bars of one melodic
line and follow the player through them. No chords or simultaneous voices yet.
Today the app trains **single notes**: one note appears, you play it, the app
confirms, repeat. This is great for building note-lookup reflexes, but real
sight-reading is about reading **sequences** — a bar or a few bars of connected
music, played in order, ideally in time.
Three material choices, not three additional top-level modes:
Phrase Mode adds exactly that, without disturbing the minimal feel of the
existing modes:
- **Melodies:** reproducible, rule-based generation in a selected key/mode and range.
- **Scales:** ascending, descending, or up-and-down scales in any key, optionally
constrained to a fretboard region. This is a core requirement, not spare-time polish.
- **Exercises:** a small, verified file-backed collection and basic local ABC import.
- The staff shows **1–8 bars of single-voice music** (notes with real durations,
bar lines, key/time signature).
- You **play the notes one by one**; the app tracks your position and gives the
same kind of quiet, unobtrusive feedback as today.
- Two paces: **Step mode** (beginner — play each note correctly, no clock) and
**Tempo mode** (metronome — the phrase moves on the beat, hit or miss).
- Material comes from two sources: **rule-based generated melodies** (in a key,
scale or fretboard position of your choosing) and a **bundled library of fixed
exercises** (e.g. Giuliani studies, folk tunes) parsed at runtime from a
simple text file format.
Two practice paces:
Zen mode, mic handling, virtual instruments, themes and all existing modes stay
as they are. Phrase Mode is *additive*: a third toggle next to "Sight Reading"
and "Ear Training".
- **At your pace** (default): wait for each correct pitch; rhythm is displayed,
not assessed. Wrong notes don't advance; an explicit Skip is available.
- **With tempo:** one-bar count-in, then advance according to written durations;
mark pitches matched during their slots and continue past misses. This is
deliberately forgiving **pitch-following with a metronome**, not a precise
assessment of note attacks, release times, or rhythmic accuracy.
## 2. User stories
All generation, imports, and practice remain browser-local. No backend, runtime
LLM calls, accounts, analytics, or new network dependency for practicing.
| # | Story |
|---|--------|
| U1 | As a guitar student, I want the app to generate short melodies within a key and a fretboard position, so I practice reading connected lines instead of isolated notes. |
| U2 | As a beginner, I want a mode where the phrase waits for me: the next note is only "armed" after I played the current one, so I can go at my own pace. |
| U3 | As a more advanced student, I want the phrase to advance on the metronome, marking notes I hit in time vs. missed, so I practice real sight-reading under tempo. |
| U4 | As a classical player, I want to practice fixed material (e.g. Giuliani right-hand studies) from a library, so I rehearse real repertoire. |
| U5 | As a future contributor, I want exercises stored in a simple text format in the repo, so more pieces can be added later — found somewhere else, converted, or generated. |
| U6 | As a user of the existing modes, I expect Zen mode, hints, virtual instruments and themes to keep working unchanged in the new mode. |
## 2. Important corrections to the first draft
## 3. Requirements
| Initial assumption | Reviewed requirement |
|---|---|
| Reusing `MatchTracker` unchanged solves sequence matching | It can repeatedly accept a held pitch. Add per-note result latching and repeated-note re-arming. A tied continuation is not a new attack. |
| `pitchData` is a fresh detection stream | Its pitch can remain displayed for 200 ms after detection stops. Add a separate timestamped raw frame stream, including null frames, for phrase matching. Keep existing display smoothing. |
| The metronome is an already-correct phrase clock | `useMetronome` calls `onTick` when scheduling audio, up to about 100 ms before it sounds. Schedule sounds ahead, but advance the cursor only when the clock reaches the event. |
| Speaker gating can simply cover every sound | Gating 400 ms after every metronome click would disable much of practice. Preview/virtual-note gating and metronome behavior need separate policies. |
| Fretboard positions come “for free” | Pitch ranges help generation, but hints must respect string/fret constraints. A microphone cannot identify which string/fret produced an equivalent pitch. Do not claim fingering verification. |
| Existing key-signature helpers suffice for phrases | They neither restrict current random-note generation nor track accidentals through a measure. Preserve pitch spelling and implement measure-aware accidentals. |
| Giuliani arpeggio studies are automatically single-voice and easy to transcribe | Many contain simultaneous bass/upper notes or sustained voices. Verify a source and explicitly label any single-line adaptation. Never invent an exercise and attribute it to Giuliani. |
| ABC is a roughly 300-line, notation-perfect shortcut | A documented subset is reasonable; full ABC is not. Validate supported syntax and reject unsupported music instead of silently changing it. MIDI is also viable, especially quantized MIDI; it is deferred for scope, not because it is inherently unsuitable. |
| Hiding the single-note UI prevents regressions | `useGameLogic` currently runs unconditionally in `App`. Its matching/metronome effects must actually be inactive in Phrases. |
| Pushing `origin/main` deploys GitHub Pages | `origin` is git.0jm.de; `github` is the GitHub remote. The checked-in workflow deploys on GitHub `main`. Do not conflate backup and production deployment. |
### 3.1 Core (MUST)
## 3. Stakeholder requirements — required for v1
- **R1 — Third game mode.** `gameMode: 'phrase'` alongside the existing two.
Header shows three toggles. Switching modes must not regress existing modes.
- **R2 — Multi-bar rendering.** The staff renders a phrase of 1–8 bars with
correct notation: key signature (reusing existing key machinery), time
signature, note durations (whole/half/quarter/eighth, dots if the library
needs them), bar lines. Reuses the per-instrument clef + guitar transpose
logic, incl. grand staff for piano. Notes fit the width; narrow screens show
fewer bars per system (wrapping into multiple systems).
- **R3 — Cursor & feedback.** The note you currently have to play is visually
marked (e.g. colored). Played notes get subtle pass/fail coloring. No big
popups per note — the "minimal feeling" of the existing modes must be kept.
- **R4 — Step mode (beginner).** The next note is armed only after the current
one was matched (same flicker-tolerant matching as today: `MatchTracker`,
50 ms hold). Wrong notes simply don't advance (plus the existing "skip"
affordance to bail out of a note).
- **R5 — Tempo mode.** Metronome at the existing BPM setting; 1-bar count-in;
the cursor advances at each note's notated duration regardless of hit/miss.
A note counts as *hit* if the correct pitch is detected and held for the
match threshold at any point within its window. Missed notes are marked but
never stop the run. At the end: a compact summary (X/Y notes) with
*Retry* / *Next phrase*.
- **R6 — Generated melodies.** Rule-based generator producing short
single-voice melodies: all pitches within the chosen key/scale **and** the
instrument's playable note set (existing difficulty ranges — incl. custom
fret windows, i.e. "position playing" comes for free via the existing
custom_fret difficulty), durations summing exactly to full bars, sane
musical rules (see 4.1), deterministic under a seed → fully unit-testable.
- **R7 — Exercise library.** A bundled set of fixed exercises parsed at
runtime from the chosen file format (see 5), plus a picker in the mode's
UI (title list, grouped by source/difficulty).
- **R8 — Play-phrase preview.** A "Play" button (and keyboard shortcut) plays
the phrase through the existing `AudioEngine` so the user can hear it before
reading it — the phrase analog of the existing "Play Note".
- **R9 — Zen mode compatibility.** Phrase Mode honors Zen mode (hide chrome,
keep staff + minimal controls) and works in landscape/mobile layouts.
- **R10 — No regressions.** Existing tests pass; new logic is unit-tested;
build and lint stay green; README and TECHNICAL_REALIZATION.md updated.
| ID | Requirement / observable outcome |
|---|---|
| R1 | **Preserve simplicity.** Third mode only; a compact material selector and transport. Advanced generation/import settings live in a collapsible panel. No per-note popups or dashboard. |
| R2 | **Readable notation.** A moving highlight in a stable, responsive view of 1–4 bars at a time; pieces may be longer. Show real durations, rests, ties, bar numbers, clef, and key/time signatures. Do not shrink eight bars onto a phone. |
| R3 | **Correct sequential matching.** Wrong notes wait in at-your-pace mode. Repeated equal pitches need separate playing; holding one note cannot finish a phrase. Rest and tie behavior is explicitly defined in the contract. |
| R4 | **Forgiving tempo practice.** Count-in, Start/Pause/Resume, misses that never stop the run, and a compact matched/skipped summary. No claim of millisecond-level rhythmic assessment. |
| R5 | **Musical generation.** 1–8 bars, default two bars in 4/4; 3/4 also supported. Seeded generation respects the selected scale and playable note set. Favor steps, small contours, and a stable ending rather than unconstrained randomness. |
| R6 | **Any key and scale drills.** All 12 tonic pitch classes; major, natural minor, major/minor pentatonic, and the diatonic modes. One-/two-octave scales or a scale-through-position drill; up/down/both. Only offer a full octave scale when the range can contain it. |
| R7 | **Position-aware guidance.** Reuse note-set/tuning settings; additionally offer a phrase-local fret window for fretted instruments, including bass. Restrict hints to allowed positions. Explain that mic matching checks pitch, not fingering. |
| R8 | **Fixed material.** File-backed library with provenance, work/exercise identification, and adaptation notes. Aim for 4–8 good items, not a quota of unverified transcriptions. Include verified Giuliani material if a suitable lawful source is available. |
| R9 | **Add material without rebuilding.** Minimal local `.abc` file import, validation feedback, and a documented example. In-session use is sufficient; no library manager or import persistence required. |
| R10 | **Focused practice.** Select a bar range in a longer exercise. Retry preserves exactly the same notes; Next moves to the next range (or generates a new melody). Optional Repeat loops the selected range with a count-in in tempo mode. |
| R11 | **Listen before playing.** Cancellable phrase preview at the selected BPM, isolated from scoring. It must stop on mode/material changes and not leave queued notes sounding later. |
| R12 | **Zen, mobile, and accessibility.** Zen retains discreet touch-accessible transport/mic controls and Retry/Next at completion. Keyboard use, visible focus, non-color-only current-note indication, both themes, and reduced motion work. |
| R13 | **Safe lifecycle.** No background scoring/playback after leaving the mode. Pause on a hidden tab, capture interruption, or audio suspension. Existing microphone permission/error handling and virtual instruments remain usable. |
| R14 | **Tested delivery.** Unit/integration tests plus real-browser checks of notation, virtual playing, and synthetic microphone input. Existing tests, lint, and build pass. Documentation states actual limitations. |
### 3.2 Nice to have in v1 (SHOULD — done only if time permits after the core)
### Default experience
- S1 — End-of-phrase auto-advance ("practice loop"): after the summary, the
same phrase repeats (Retry) or the next one loads automatically.
- S2 — Scale drill material: runs/arpeggios in a selected key and position,
as either generated material or tiny bundled exercises (this is the
"scales in different positions" ask expressed in the simplest useful form).
- S3 — Repeat marks / looping a sub-range of a longer exercise.
- S4 — Ear-training variant of phrases ("listen to the phrase, then play it
back") — deliberately deferred, see 3.3.
Open Phrases → a two-bar C-major melody in the current instrument range → press
Start → play the highlighted notes at your pace → Retry the identical melody
or choose New melody. Nothing sounds until requested; microphone capture still
requires permission/user intent. If the microphone is unavailable, choose the
virtual instrument rather than presenting an unplayable screen.
### 3.3 Explicitly out of scope for v1 (WON'T)
Settings are progressive: the compact selector can read
“Melody · C major · At your pace”; editing it opens the setup panel. The old
single-note metronome and key-signature controls must not also appear as
competing phrase controls.
- **Chords / multiple simultaneous voices.** The matching pipeline is
monophonic by design (single pitch per frame). The data model will keep a
`voice`-shaped structure so a polyphonic future is not blocked, but v1
renders and matches single voice only.
- **Polyphonic pitch detection** (fundamental research territory).
- **Scoring history / statistics persistence.**
- **Importing arbitrary user files via file picker** — the library lives in
the repo; a user-facing importer (file picker → localStorage) is a small
follow-up once the format is proven.
- **MIDI import.** See 5 for the reasoning; can be added later as a
build-time/offline converter into the same internal model.
## 4. Content and format decisions
## 4. Functional specification
**ABC is the primary v1 interchange format**, with a deliberately limited,
documented single-voice subset. The normalized score is independent of ABC,
so a future MIDI or MusicXML adapter can use the same trainer and renderer.
### 4.1 Melody generator (rule set for v1)
Support common simple notation, including rests, dotted durations, and ties.
Simple repeats and pickups have explicit bounded behavior in the contract.
Unsupported tuplets, polyphony, meter changes, etc. produce actionable errors.
Do not advertise support for arbitrary ABC files.
Configurable via settings: key/mode, number of bars, rhythm complexity level,
and the existing difficulty range (which constrains the playable pitch set,
including fretboard position via the custom fret window).
A bundled exercise must identify its source and the transcription's rights,
not just cite the composer's death date. Generic arpeggio patterns may be
original exercises; they must not be presented as numbered historical studies.
If a Giuliani transcription cannot be verified, ship other verified/original
material and record that limitation. Do not let content research block the app.
Rules (v1 — deliberately simple, testable invariants in parentheses):
## 5. Scope boundaries and optional improvements
1. Pitch pool = scale of the chosen key/mode ∩ playable notes of the
instrument/difficulty. *(invariant: every generated pitch ∈ pool)*
2. Start on a stable degree (1, 3 or 5 of the scale); end on the tonic
(or dominant), placed on a strong beat.
3. Mostly stepwise motion (≈70% steps of a 2nd); leaps mostly 3rd/4th,
rare 5th/6th/octave; a leap is followed by a step in the opposite
direction (classic counterpoint heuristic — produces melodic, not
chaotic, lines). *(invariant: no two consecutive leaps > 4th without
an intervening step in opposite direction)*
4. No immediate repetition of the same pitch more than twice in a row.
5. Rhythm: per-bar patterns drawn from a complexity-tiered pool
(level 1: quarters; level 2: + paired eighths / half notes; level 3:
+ dotted quarters & mixed). No rests in v1. Final note ≥ half note.
*(invariant: durations per bar sum to the bar exactly)*
6. Motivic shape: 4-bar phrases built as 2 bars of motif + 2 bars answering
(transposed/varied motif) — cheap to implement, dramatically improves
"sounds like a melody" impression. Optional at difficulty level 3 only.
7. v1 keys: all majors and minors from the existing key-signature list plus
major/minor **pentatonic**; additional modes (Dorian, Mixolydian, …) are
trivial follow-ups of the same scale machinery.
**Not v1:** chords, polyphonic recognition, a full notation editor, complete
ABC/MIDI/MusicXML compatibility, phrase ear-training, persistent score history,
strict onset/duration scoring, exhaustive fingering optimization, or automatic
production deployment.
### 4.2 Playback state machine
**Only after all required behavior is working:** more repertoire, scale-in-thirds
and arpeggio drill patterns, motif-based call/response generation, saving the
last phrase setup locally, and a MIDI adapter. These must not displace audio
correctness, scales, Zen/mobile behavior, import validation, or tests.
```
IDLE → (start) → COUNT_IN (tempo mode only) → PLAYING → DONE → (retry|next) → …
In PLAYING: cursor at note i,
step mode: wait for match(i) → color green → cursor i+1
tempo mode: window(i) = [t_i, t_i + dur_i); at window end evaluate
MatchTracker state → green/red → cursor i+1
```
## 6. Implementation sequence and checkpoints
Matching reuses `MatchTracker` unchanged (hold 50 ms, 150 ms flicker grace).
The mic is gated during speaker output exactly as today (`audioEngine.
isAudible()`), so the preview button and virtual instruments can't self-match.
| Phase | Deliverable | Gate before continuing |
|---|---|---|
| P0 | Baseline checks; normalized score, range/scale helpers, matcher/transport contracts; feature branch | Existing tests still green; regression fixtures added |
| P1 | Generated melodies + scale drills + phrase renderer + at-your-pace mode | Playable through mic and virtual input; repeated notes/rests/ties covered; responsive/Zen path usable |
| P2 | Tempo transport, count-in, pause/resume, preview, cancellation | Fake-clock and synthetic-audio tests prove no early cursor, self-scoring, or stale events |
| P3 | ABC adapter, verified library, local import, range selection/repeat | Every bundled file validated; invalid/unsupported imports handled; source notes recorded |
| P4 | Accessibility/lifecycle regression pass, browser QA, docs, delivery | All R1–R14 checked; limitations and exact verification results written down |
### 4.3 UI concept
Quality work in P4 is **not optional**. Optional features are cut first if the
implementation budget is tight. Finish required phases or explicitly report
what is incomplete; never declare the task done just because it compiles.
- Header: third toggle **"Phrases"** (naming: see 8.1).
- Main stage (non-zen): phrase staff; below it a compact status line
(step mode: "Play the highlighted note" / tempo mode: bar count-in
indicator + running hit/miss count); controls: Play (preview),
Restart, New phrase / Next exercise, plus the existing hint/virtual
instrument buttons which keep working (hint marks the current note's
fretboard position).
- End of phrase: one-line summary + Retry / Next. No modal, no confetti.
- Zen mode: staff + exit button only, as today.
## 7. Handoff and publishing
## 5. Fixed-material file format — recommendation
- Implementation begins only after approval. Read
[the implementation contract](docs/PHRASE_MODE_IMPLEMENTATION.md) before coding.
- Work on `feature/phrase-mode`, branched from the current local state. Preserve
the existing local commits. Commit coherent, tested checkpoints.
- A normal backup push of the **feature branch to `origin`** is the proposed
delivery default after “Go”. Do not update either remote's `main`, merge,
force-push, or trigger production deployment without explicit approval.
- Verify actual model/tool availability before delegation; do not assume the
suggested GLM model ID or a subagent tool exists. Use cheaper workers only
for bounded independent work with fixed interfaces and tests. The main
implementer reviews all output. No unbounded retry/research loops.
- Maintain a short implementation checklist with R1–R14 status, test commands,
decisions/deviations, known limitations, commit, and push status. This is the
completion/handoff artifact, not a claim that physical-instrument testing was
performed when only synthetic input was available.
The internal representation is a plain TypeScript model (notes with midi +
duration in beats, metadata) that both the generator and the library feed
into. The open question is the ** interchange format** for the library.
| Option | Pros | Cons |
|--------|------|------|
| **ABC notation** ✅ recommended | Text: easy to bundle in git, to author by hand, to LLM-generate, to review in diffs; huge public-domain corpus (folk tunes in ABC everywhere); encodes bars, durations, key, **and note spelling** directly — maps 1:1 onto VexFlow; a subset parser is ~300 lines, fully unit-testable | Little pre-existing classical-pedagogy material in ABC (Giuliani studies must be transcribed — but arpeggio studies are extremely regular and transcribe quickly) |
| MIDI | Abundant files; import of anything | Binary; durations need quantization (grid inference); no spelling — must be re-derived; repeats/structure opaque; parser + quantizer ≈ same size as ABC parser with worse output |
| MusicXML | Notation-perfect | Heavy, verbose, no light-weight parser; overkill for monophonic v1 |
**Recommendation:** bundle exercises as small `.abc` files in the repo
(`src/exercises/library/`), parsed at runtime by a small subset parser
(inline notes, durations, octaves, accidentals, bar lines, key/meter/time
headers, simple `|:` `:|` repeats expanded at parse time; no ties/grace
notes/tuplets in v1). Seed library (public domain — Giuliani died 1829):
- Giuliani Op. 1 right-hand arpeggio studies (selection, transcribed)
- 1–2 Sor/Carcassi-style étude excerpts if the arpeggios go fast
- A handful of well-known public-domain folk melodies
- Scale/run patterns as tiny generated "built-ins" if useful
MIDI stays possible later: an offline converter (Node script) MIDI → same
model can be added without touching the app.
## 6. Technical plan
New code, mirroring the existing layout:
```
src/
├── music/
│ ├── scales.ts # scale/mode definitions, key→pitch-class sets
│ ├── melodyGenerator.ts # rules → Phrase model (seeded RNG, pure)
│ └── NoteUtils.ts # extended: duration→VexFlow glyph mapping (shared)
├── exercises/
│ ├── model.ts # Phrase / PhraseNote / ExerciseInfo types
│ ├── abcParser.ts # ABC subset → Phrase (pure, tested)
│ ├── library.ts # bundled .abc index + metadata
│ └── library/*.abc # the exercise files themselves
├── hooks/
│ ├── usePhraseTrainer.ts # state machine from 4.2 (uses MatchTracker)
│ └── usePhraseClock.ts # audio-clock lookahead scheduler (tempo mode),
│ # patterned after the existing useMetronome
├── components/
│ ├── PhraseSheetMusic.tsx # multi-bar VexFlow renderer w/ cursor+colors
│ ├── PhraseControls.tsx # mode-local buttons/status line
│ └── ExercisePicker.tsx # library picker (R7)
└── types/SettingsTypes.ts # new phrase-related settings
```
Integration approach in `App.tsx`: pitch detection stays exactly as-is and
produces `pitchData` once. If `gameMode === 'phrase'`, App renders the
`PhraseTrainer` subtree (staff + controls) fed by the same `pitchData`, mic
gate and audio engine; the existing single-note subtree is untouched. This
keeps `useGameLogic` clean and guarantees the existing modes are unregressed
by construction.
Settings additions (all optional, with defaults — existing installs keep
working):
```ts
phrase?: {
material: 'generated' | 'library';
libraryId?: string; // selected exercise
key: string; // generator key/mode (e.g. 'G', 'Am', 'C-penta-maj')
bars: number; // 1–8
rhythmLevel: 1 | 2 | 3;
pace: 'step' | 'tempo';
bpm: number; // tempo mode; defaults to existing rhythm.bpm
}
```
Tempo-mode scheduling follows the proven metronome pattern (lookahead timer
scheduling against `AudioContext.currentTime`) so cursor movement doesn't
drift; note windows are derived from the same schedule, not from `Date.now()`.
### Testing
- `melodyGenerator.test.ts` — invariants from 4.1 (pool membership, bar sums,
leap rules, determinism under seed).
- `abcParser.test.ts` — golden strings for each syntax feature; error cases.
- `usePhraseTrainer` logic — extract pure reducer/clock math and test the
state machine transitions with a fake clock (step & tempo mode, hit/miss).
- Renderer gets a thin smoke test; visual QA happens in the browser.
- Full `npm run lint && npm run build && npm test` must pass before finishing.
### Execution / cost control
- Core architecture, integration and the clock/trainer logic: implemented
directly (these are the parts where mistakes are expensive).
- Delegate to cheaper subagents (pi supports spawning agents with a cheaper
model, e.g. GLM-5.3-Flash): ABC transcriptions of the Giuliani studies,
the parser/generator test corpora, the exercise picker UI and other
template-like UI work — each with tight, verifiable specs, and their output
re-checked by the main agent before merging.
- Each phase ends in a green build + commit, so the night produces usable
checkpoints, not one big risky blob.
## 7. Implementation phases
| Phase | Contents | Exit criterion |
|-------|----------|-----------------|
| **P1** | Model + scales + generator (rules 1–5) + multi-bar renderer + Step mode end-to-end (R1–R4, R6 core) | Playable generated melodies in step mode, no clock |
| **P2** | Tempo mode: phrase clock, count-in, per-window hit/miss, summary (R5) | Full generated-melody experience |
| **P3** | ABC parser + bundled library + picker (R7), Play-preview (R8) | Fixed exercises playable in both paces |
| **P4** | Motifs/pentatonic (rule 6–7), S1/S2 if time, Zen-mode polish, keyboard shortcuts, help text, README/TECH docs, final lint/build/tests, push | Night done |
If time runs short, P1–P3 are the must-have spine; everything in P4 is
incremental and can be dropped mid-phase without leaving the app broken.
## 8. Open decisions — defaults if no feedback
| # | Decision | Default I'll assume |
|---|----------|---------------------|
| 8.1 | Mode name / labels | Third toggle labeled **"Phrases"**; existing two keep their current names ("Sight Reading", "Ear Training"). If you'd rather rename the pair (e.g. "Notes" / "Ear" / "Phrases"), say so — cosmetic change. |
| 8.2 | Library format | **ABC** (rationale in 5). MIDI deferred to a later offline converter. *If you feel strongly about MIDI as the primary format, this is the decision to veto.* |
| 8.3 | Tempo-mode strictness | Lenient: misses are marked, never abort. No per-note gating beyond the existing 50 ms hold. |
| 8.4 | Generator keys in v1 | Majors + relative minors from the existing key-signature list + major/minor pentatonic. Church modes: later. |
| 8.5 | Phrase length default | 4 bars, 4/4 only in v1 (3/4 comes free with the model; generator stays 4/4 unless trivial to add). |
| 8.6 | Hints in phrase mode | Reuse existing hint toggle: fretboard/piano hint marks the **current** note only. |
| 8.7 | Publishing | Repo `main` is currently 4 commits ahead of `origin`. Pushing `main` triggers the GitHub Pages deploy. Default: at the end of the night, push **everything** (your 4 commits + mine) after a green build, so the work isn't lost. Say "don't push" if you'd rather review first. |
| 8.8 | Seed library size | ~10–15 items (5–8 Giuliani arpeggio studies, 3–5 folk tunes, 1–2 technical patterns). Quality-checked, not bulk-dumped. |
**Approval:** reply "Go" (optionally with edits/vetoes on the table above) and
I'll implement autonomously overnight following P1→P4.
**Approval defaults:** Phrases label; ABC subset with local import; scales and
all-key support required; at-your-pace/two-bar defaults; tempo mode is forgiving;
feature-branch backup only. Reply “Go”, optionally changing these defaults.