From dc1778a13447b17ccd854d3560e999fec76ece79 Mon Sep 17 00:00:00 2001 From: vadimwit Date: Sun, 14 Jun 2026 15:49:56 +0100 Subject: [PATCH] design: three Jam Guide visualization concepts for user selection (tasks D-00a/b/c) Muse explored three distinct philosophies for the live Jam Guide panel: - Stage: live-play-at-a-glance (current chord huge, next preview, one big grip) - Playbook: study/comparison grid (loop chords x voicings, more-ways expand) - Roadmap: improv-first highway (playhead, guide tones, scale, voice-leading rails) Each in docs/design/jam-guide-concept-{a,b,c}.md. Awaiting user pick (D-SEL). Co-Authored-By: Claude Fable 5 --- docs/agents/LEDGER.md | 12 ++- docs/design/jam-guide-concept-a.md | 82 ++++++++++++++++++ docs/design/jam-guide-concept-b.md | 116 +++++++++++++++++++++++++ docs/design/jam-guide-concept-c.md | 130 +++++++++++++++++++++++++++++ 4 files changed, 338 insertions(+), 2 deletions(-) create mode 100644 docs/design/jam-guide-concept-a.md create mode 100644 docs/design/jam-guide-concept-b.md create mode 100644 docs/design/jam-guide-concept-c.md diff --git a/docs/agents/LEDGER.md b/docs/agents/LEDGER.md index 72a2057..b7c821c 100644 --- a/docs/agents/LEDGER.md +++ b/docs/agents/LEDGER.md @@ -7,13 +7,19 @@ The shared queue all agents read and write. Lifecycle and rules: [`PROTOCOL.md`] --- -## Active sprint: `sprint-jam-guide` (branch: not yet cut) +## Active sprint: `sprint-jam-guide` (branch: `sprint-jam-guide`) Emphasis this sprint: **ship the Jam Guide MVP** (put the 8 guitar style packs on screen, synced to live detection) + **reframe the repo as a learning platform**. Weights this sprint: Luthier 3, Muse 3 (design-heavy), Professor 2, Herald 2, Critic gate. +**Design-first gate (user directive 2026-06-14):** before D-02 locks a layout, Muse explores *several distinct* visualization concepts and the **user picks** one. D-01x/D-02 implement the chosen concept. + | id | title | domain | status | depends-on | files (lock) | definition of done | |----|-------|--------|--------|-----------|--------------|--------------------| -| M-01 | Cut `sprint-jam-guide` branch; seed sprint | maestro | ready | — | (branch) | branch off main, ledger header set | +| M-01 | Cut `sprint-jam-guide` branch; seed sprint | maestro | done | — | (branch) | branch cut off ensemble-system HEAD (carries agents+KB+skill), ledger header set | +| D-00a | Viz concept **A — "Stage"**: optimised for live play at-a-glance (big current chord, next-chord preview, one recommended voicing) | design | in-review | — | `docs/design/jam-guide-concept-a.md` | ASCII mockup at panel proportions, interaction model, KB-data mapping, pros/cons, ≤16-line preview block | +| D-00b | Viz concept **B — "Playbook"**: optimised for study/comparison (full progression grid × multiple voicings per chord, "more ways" expansion) | design | in-review | — | `docs/design/jam-guide-concept-b.md` | same DoD as D-00a | +| D-00c | Viz concept **C — "Roadmap"**: optimised for improv guidance (progression timeline, position-in-loop, voice-leading/scale hints, what's coming) | design | in-review | — | `docs/design/jam-guide-concept-c.md` | same DoD as D-00a | +| D-SEL | **User selects** a concept (or a blend); Maestro folds it into D-01x/D-02 | maestro | blocked | D-00a, D-00b, D-00c | `docs/agents/LEDGER.md` | chosen concept recorded; layout tasks rewritten to match | | L-01 | Shared util: extract `findLoopPosition` + degree-relative loop matcher (rotation-invariant) from `ProgressionBanner.jsx` into `src/lib/match.js` | engineering | backlog | M-01 | `src/lib/match.js`, `src/components/ProgressionBanner.jsx` | matcher maps detected loop → style progression id, rotation-invariant; existing banner still works; build green | | L-02 | `JamGuide.jsx` panel shell: mounts last in `App.jsx`, reads `kb/index.js`, instrument+style tabs from registry, collapsed header → ~70vh | engineering | backlog | L-01 | `src/components/JamGuide.jsx`, `src/App.jsx` | panel renders, tabs generate from KB, matches current loop or shows fallback; build green | | D-01 | `ChordDiagram.jsx`: 6-string × 5-fret SVG, consumes the KB shape format (movable `rootStr`+`offsets`, open `frets`+`onlyRoot`), key-aware fret placement | design | backlog | L-01 | `src/components/ChordDiagram.jsx` | renders any KB guitar shape correctly in any key; uses design tokens; chord-tone colour tier | @@ -41,3 +47,5 @@ Emphasis this sprint: **ship the Jam Guide MVP** (put the 8 guitar style packs o ## Iteration log _(Maestro appends one line per completed iteration: ` · · `.)_ + +- 2026-06-14 · done: M-01 · in-review (awaiting user pick): D-00a/b/c viz concepts · next: D-SEL (user chooses) → then L-01/D-01/D-02 implement chosen concept diff --git a/docs/design/jam-guide-concept-a.md b/docs/design/jam-guide-concept-a.md new file mode 100644 index 0000000..7768e71 --- /dev/null +++ b/docs/design/jam-guide-concept-a.md @@ -0,0 +1,82 @@ +# Jam Guide — Concept A: "Stage" + +> Design concept for the Jam Guide panel (ledger task **D-00a**). One of three concepts; the user picks. Tokens: `bg-surface` #0f0f0f, `bg-panel` #1a1a1a, `border-border` #2a2a2a, accent #a855f7, amber #f59e0b. Colour language inherited from `Fretboard.jsx`: **chord tone = accent purple**, **now-playing = amber**, scale = gray. + +## 1. Name + thesis + +**Stage** — a stage-monitor for your hands. It optimises for the **half-second glance mid-jam**: the current chord huge and unmistakable, the *next* chord pre-loaded so you can move in time, and exactly **one** big recommended voicing to put your fingers on. Everything a textbook would add collapses away. For the player who is already playing and just needs to be *told the next move*, readable across a rehearsal room. + +## 2. Mockup — realistic panel proportions (full-width, short) + +Real example: **Standard 12-bar blues in A** (`blues-12bar`, detected loop `A7→D7→E7`), play **"Barre-chord shuffle"** from `blues/guitar.js`. The big diagram is the `E_BARRE7` grip — `{ rootStr:6, offsets:[0,2,0,1,0,0] }` — placed in A: root on low E at fret 5, so the barre sits at fret 5. + +``` +┌─ JAM GUIDE ──── Blues · 12-bar in A ────────────────── [Guitar▾] [Blues▾] [Stage|Playbook|Roadmap] ⌃collapse ─┐ +│ │ +│ NOW ░░░ NEXT ░░░ ── Barre-chord shuffle ── I7 IV7 V7 │ +│ ┌────────────┐ shuffle · root on 6th str ● ○ ○ ○ │ +│ │ │ ┌────────┐ bar 5 of 12 ┌──5fr──────────────┐ ○ ○ · · │ +│ │ A7 │ → │ D7 │ ╾╾╾╾╾╾╾╾╾╾╾○╾╾╾ ── loop ── e│ ● │ ← R ● ○ · ○ │ +│ │ │ └────────┘ ▮▮▮▮▮▮▮▮▮▮░░░░░ B│ ● │ ← 5 ○ ○ · │ +│ │ I7 │ IV7 2 bars → change G│ ● │ ← 3 │ +│ └────────────┘ D│ ● │ ← R │ +│ ↑ playing now prep this A│ ● │ ← 5 │ +│ E│ ● (5fr, barre) │ ← R "Strum short │ +│ ▸ improv: A mixolydian · target the 3 (C♯) └───────────────────┘ — shuffle's in │ +│ R=purple 3=amber accent the damp hand" │ +└────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +The `NOW` block is the loudest thing on screen — a single giant amber chord name with its Nashville/Roman number under it. `NEXT` is a smaller ghosted card to its right with an arrow and a literal countdown ("2 bars → change") fed by the loop-position logic. The right two-thirds is **one** large `ChordDiagram` (the recommended voicing for the *current* chord) plus a 12-bar position strip (`I7 IV7 V7` mini-map) so the eye can confirm where it is in the form without reading the whole grid. + +## 3. Interaction & live-sync model + +- **Chord change (detection):** when `currentChord` flips, the `NOW` card cross-fades (reuse the 200 ms `scale(0.85)→1` animation already in `ProgressionBanner.jsx`), the old `NOW` slides left into a brief "just played" ghost, and `NEXT` promotes into `NOW`. The big diagram swaps to the new chord's recommended voicing. +- **Loop detected:** the position strip (`▮▮▮▮▮░░░`) and "bar N of 12" appear; without a loop, Stage still works — `NEXT` simply shows the most-likely next chord from `ProgressionSuggestions` and the bar-counter hides. +- **Position in loop:** drives the `NEXT` card and the countdown ("2 bars → change"). The countdown is the differentiator — it lets the player *prepare the grip* before the change lands, which is the whole point of a stage monitor. +- **Animates:** only the `NOW`/`NEXT` swap and the position-strip fill. Deliberately almost nothing else moves, so the panel never competes with playing. +- **Taps:** tap `NOW` diagram → cycle to the *next way to play* this chord (the other plays in the same `plays[id]` array, e.g. "9th-chord stabs"). Tap `NEXT` → make it the focus (peek ahead). Tap the improv line → expand the one-line scale/target hint into the lick. Tap the collapse chevron → shrink to a one-line header (chord + next), the always-visible resting state. + +## 4. KB-data mapping (buildable from data we already have — guitar packs exist) + +| Panel part | KB source | +|---|---| +| `NOW` / `NEXT` chord names + numerals | detected `currentChord` + matched progression `degrees`/`rn` rendered in the live key (rotation-invariant match, L-01 util) | +| Which progression + "12-bar in A" label | matched `progressions[].id` + `name` + `keyInfo.root` | +| Position strip `I7 IV7 V7` + bar counter | progression `rn` + `bars` arrays; active index from `findLoopPosition` | +| "2 bars → change" countdown | sum of `bars` from active step to the next chord change | +| Big chord diagram | `plays[id][playIndex].chords[step].shape` — movable `rootStr`+`offsets` placed by key (or open `frets`+`onlyRoot`); rendered by `ChordDiagram.jsx` (D-01) | +| "Barre-chord shuffle" label + tip | `plays[id][playIndex].label` + `.tips`; per-chord caption from `chords[step].note` | +| Finger dots / R·3·5 labels | `shape.offsets` → pitch classes vs `getChordTones(currentChord)`; root + 3rd get the colour tier | +| Improv one-liner | `improv.scales[].scale` matched to current chord + `improv.targetNotes` | +| "more ways" on tap | length of `plays[id]` array | + +Every field above exists today in the eight shipped guitar packs. Piano/bass packs don't exist yet; Stage degrades cleanly — the instrument tab only lists instruments present in `kb/index.js`, exactly as L-02 specifies. + +## 5. Pros / cons / sacrifices + +**Pros** +- **Fastest possible read** mid-jam: one chord, one next, one grip — no scanning. The thing the user actually needs in the half-second is the biggest thing on screen. +- **Preparation, not just status:** the `NEXT` card + bar countdown is unique to this concept — it tells you the move *before* it happens, which is what a live monitor is for. +- **Cheapest to build & cheapest to animate:** renders one `ChordDiagram` at a time (vs a full grid), so it's the lightest on the audio thread and the simplest D-01/D-02 surface. + +**Cons** +- Shows **one voicing at a time** — you can't compare three ways to play A7 side by side without tapping. +- Less of a "study" surface; a player who wants to learn the whole form's options at rest gets less here than in Playbook. + +**Sacrifices:** the full progression grid (all chords × all plays visible at once). Stage trades breadth for legibility — it assumes you'll learn the catalogue at home and use Stage to *perform*. + +```PREVIEW +STAGE — one chord, the next, one grip. A stage-monitor for your hands. +┌─ JAM GUIDE · Blues 12-bar in A ················· [Guitar][Blues] ─┐ +│ NOW NEXT Barre-chord shuffle I7 IV7 V7 │ +│ ┌──────────┐ ┌──────┐ ┌──5fr──────────┐ ▮▮▮▮▮░░░ │ +│ │ │ → │ D7 │ e│ ● │ bar 5 / 12 │ +│ │ A7 │ └──────┘ B│ ● │ │ +│ │ │ 2 bars → G│ ● ←3 │ ↑ amber = now │ +│ │ I7 │ change D│ ● │ ● purple = root │ +│ └──────────┘ E│ ● 5fr barre │ │ +│ ↑ playing prep this └───────────────┘ │ +│ ▸ A mixolydian · target the 3 (C♯) │ +└───────────────────────────────────────────────────────────────────┘ +``` diff --git a/docs/design/jam-guide-concept-b.md b/docs/design/jam-guide-concept-b.md new file mode 100644 index 0000000..e3527ae --- /dev/null +++ b/docs/design/jam-guide-concept-b.md @@ -0,0 +1,116 @@ +# Jam Guide — Concept B: "Playbook" + +> Ledger task **D-00b** · domain: design · author: Muse +> Tokens: `bg-surface` #0f0f0f · `bg-panel` #1a1a1a · `border-border` #2a2a2a · `accent` #a855f7 · `amber` #f59e0b + +## 1. Name + thesis + +**"The Playbook"** — the whole loop opened flat like a method-book page: a grid where **columns are the chords of the progression** and **rows are different ways to voice it**, so you can read *across* the loop and *down* the voicings in a single glance and choose how you want to play it. + +This is the **deepest-information** of the three concepts. Stage answers "what do I play *right now*"; Roadmap answers "where am I going". Playbook answers **"how is this whole thing played, and what are my options"** — the panel you open between choruses to study, then internalise. + +--- + +## 2. Mockup — Blues 12-bar in A (real KB data, full-width ~70vh) + +Rendered from `kb/blues/progressions.js` (`blues-12bar`) + `kb/blues/guitar.js` (`plays['blues-12bar']`). The 12-bar form collapses to its **3 distinct chords (I7 · IV7 · V7)** as columns — the grid teaches the *vocabulary*, the bar map (top strip) teaches the *form*. Each cell is a `ChordDiagram` (D-01). `●` = fretted/finger, `○` = root, `×` = muted, numbers above = barre fret. + +``` +┌─ JAM GUIDE ────────────────────────────── [ Guitar ▸ Piano Bass ] [ Jazz ‖ BLUES ‖ Rock Bossa Funk … ] ──┐ +│ │ +│ Matched: Standard 12-bar · A major your loop: A7 → D7 → E7 ♻ bar 5 / 12 · 96 BPM shuffle │ +│ form: ┃A7┃A7┃A7┃A7┃D7┃D7▸┃A7┃A7┃E7┃D7┃A7┃E7┃ ← active bar pulses amber, sweeps L→R with the band │ +│ ───────────────────────────────────────────────────────────────────────────────────────────────────────────── │ +│ I7 · A7 IV7 · D7 ◀ playing now V7 · E7 │ +│ │ +│ Barre shuffle ●○ ● ● ● ● fr5 ●× ●○ ● ● ● ● fr5 ◀━━━━━ ●○ ● ● ● ● fr7 │ +│ ▸ beginner-safe │○│ │ │ │ │ │×│○│ │ │ │ │ ◀ active col │○│ │ │ │ │ │ +│ R-5-♭7-3 E-shape A7 A-shape D7 (glows) E-shape E7 │ +│ "root on 6th str" "same fret, root str up" "two frets above IV" │ +│ ───────────────────────────────────────────────────────────────────────────────────────────────────────────── │ +│ 9th stabs ×○♭7 ● ● ● fr5 ×○♭7 ● ● ● fr5 ×○♭7 ● ● 13 fr7 (V13) │ +│ ▸ intermediate │×│○│♭│●│●│●│ │×│○│♭│●│●│●│ │×│○│♭│●│●│●│ pinky → 13 │ +│ R-3-♭7-9 (Texas) "slide in ½-step below" "IV9" "V13 — horn-section hook" │ +│ ───────────────────────────────────────────────────────────────────────────────────────────────────────────── │ +│ Tritone shells ×○ ● ● × × fr5 ×○ ● ● × × fr5 ×○ ● ● × × fr7 │ +│ ▸ minimal/comp R-♭7-3 only "inner pair drops 1 fret → IV" "Chicago grip" │ +│ │ +│ ⌄ more ways (2) — Jimmy Reed boogie · Stormy Monday walk-up │ +│ ═══════════════════════════════════════════════════════════════════════════════════════════════════════════── │ +│ IMPROV over I7 → A Mixolydian · over IV7 → D Mixo · target the 3rds C♯→F♯→G♯ · the blues curl: ♭3↗3 │ +│ lick ▸ B.B. box in C: e|8 10b12 10 8 · D bent to E (the 3rd) tap a cell to hear it ♪ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +Header reads tokens directly: panel `bg-panel`, hairlines `border-border`, the matched-style tab and active highlights `accent` (#a855f7), the live bar/now-playing pulse `amber` (#f59e0b) — matching `ProgressionBanner`'s existing "active = accent ring, numeral = amber" language so the two panels feel like one instrument. + +--- + +## 3. Interaction & live-sync model + +**Active-column highlight (the live thread).** The detected `currentChord` maps to a *column*, not a single cell. Reusing `findLoopPosition` (extracted to `src/lib/match.js` per L-01), the panel finds the loop index, looks up which of the 3 chord-columns that bar belongs to, and lights the whole column: an `accent` left-border rail, a faint `bg-accent/8` column wash, and an `◀ playing now` caret over the header. Because Playbook shows the *whole* loop at rest, the highlight is a **moving spotlight over a static page** — your eye already knows where the next column is, so you read ahead in rhythm. The top **bar-map strip** carries the finer-grained pulse (which of 12 bars), sweeping amber L→R; the grid columns carry the coarser "which chord". Two clocks, one glance. + +**"More ways ▾" expansion.** Each cell stack shows the first **2–3 plays** that fit the panel height; remaining plays (the KB has up to 4–5 per progression — Jimmy Reed boogie, Stormy Monday walk-up, etc.) collapse behind a single `⌄ more ways (N)` row at the grid foot, labelled with their play titles so you know what you're expanding. Click → the grid grows new rows in place (panel scrolls internally, header + bar-map stay pinned). Per-row, a small `▸` chevron on the row label toggles that row's **tips** line (the `tips` string) and per-cell `note`/`extensions` annotations from collapsed to shown — dense by default, denser on demand. + +**Instrument / style tabs.** Top-right: style tabs generated from `kb/index.js` keys (`jazz blues rock bossa funk reggae country rnb` today, growing as the loop fills cells) — the matched style is auto-selected and shown `accent`-filled; the others are quiet `text-gray-400` and switch the whole grid (re-voicing the same detected loop in another idiom — the core "Jazz→Bossa over one ii–V–I" payoff). Top-left: instrument segmented control (Guitar live; Piano/Bass dimmed until those packs exist, driven by `instruments` keys present in the registry). Both persist to settings. + +**Scroll vs collapse.** Collapsed, the panel is a **single header strip** (`Matched: … · your loop · ♻ bar n/12`) always visible at the bottom of the app scroll — identical resting footprint to the other two concepts. Click the header (or scroll into it) → expands to ~70vh. Inside, the grid scrolls **vertically** (more rows than fit) with the header, bar-map, and improv footer pinned; on narrow viewports it reflows (see §5) so columns never crush. + +--- + +## 4. KB-data mapping (proves it's buildable today) + +Every cell is driven by existing fields in the shipped guitar packs — nothing new is invented: + +| UI element | KB source (`kb/blues/…`) | +|---|---| +| Column headers (I7 · IV7 · V7) + `name`, key chip | `progressions.js` → `rn`, `name`, `mode`; deduped against `degrees`/`qualities` to the distinct chords | +| Top bar-map strip `┃A7┃A7┃…┃` | `progressions.js` → full `degrees` × `bars`, rendered absolute in the detected key | +| Row labels ("Barre shuffle", "9th stabs", "Tritone shells") | `guitar.js` → `plays['blues-12bar'][].label` | +| Row level badge (`▸ intermediate`) | `plays[][].level` | +| Each diagram cell | `plays[][].chords[stepForThisColumn].shape` → `ChordDiagram` (D-01); movable `rootStr`+`offsets` placed at the column chord's fret in the detected key; open shapes via `frets`+`onlyRoot` | +| Cell colour-tone label (`R-3-♭7-9`), `13`/`♭7` glyphs | `chords[].extensions` + the shape's computed pitch classes (chord-tone tier = `accent`, same as Fretboard) | +| Per-cell caption | `chords[].note` ("same fret, root str up", "V13 — pinky reaches the 13") | +| Per-row tips (▸ reveal) | `plays[][].tips` | +| "more ways (N)" titles | the remaining `plays['blues-12bar']` entries beyond the visible rows | +| IMPROV footer | `improv.scales[].over/scale`, `improv.targetNotes`, `improv.licks[].tab/description` | +| Style/instrument tabs | `kb/index.js` registry keys + each style's `instruments` keys | + +Because a 12-bar has many bars but few distinct chords, the **column reducer** (distinct `degree`+`quality` pairs, order of first appearance) keeps the grid to 3–4 columns even for a 12-bar — exactly what makes "down the voicings" legible. A 4-chord loop (Axis I–V–vi–IV) yields 4 columns; the same component, no special-casing. + +--- + +## 5. Pros / cons / what it sacrifices + +**Pros** +- **Most information per screen.** You see the entire loop *and* 3–5 ways to voice each chord at once — the only concept that supports true *comparison* ("shells vs barres vs 9ths") side by side. This is the deepest-study option, the method-book page. +- **Teaches vocabulary, not just the moment.** Reading *down* a column is a voicing lesson; reading *across* a row is the form. Level badges (beginner→advanced grips in one stack) let a player climb difficulty in place. +- **Reuses every KB field with zero waste** — multiple `plays`, `level`, `tips`, `extensions`, `note`, improv — so the agent-authored content is fully surfaced (Stage/Roadmap show a slice; Playbook shows the book). +- **Grid is reflow-friendly:** narrow → one play per row, columns scroll horizontally (the kb-plan §4 "smart fit" fallback) without changing the mental model. + +**Cons** +- **Density is the cost.** It is *not* a glance-and-go panel mid-solo — there's a lot on screen, and the moving column-spotlight is the only thing that's instant. A player needs a beat to study it; if they want "just tell me the one chord now," Stage wins. +- **Diagram real-estate pressure.** 3–5 rows × 3–4 columns of SVG diagrams is the heaviest render of the three; cells must shrink on small windows (mitigated by collapse + reflow, but a 13" laptop shows ~3 rows before scroll). +- **Bar-form abstraction.** Collapsing 12 bars to 3 columns is powerful but hides bar-by-bar order *in the grid* — recovered by the top bar-map strip, but that's a second thing to read. + +**What it sacrifices:** *immediacy*. The whole design trades instant glanceability for completeness — a deliberate inversion of Stage. It assumes the musician has a moment (a turnaround, a verse they know, a teacher's pause) to look down and *study*, then look up and play. The active-column spotlight is the lifeline that keeps it usable even mid-jam, but the panel's centre of gravity is **learning the loop**, not surviving the next bar. + +--- + +```PREVIEW +┌ JAM GUIDE · Playbook ──────────[Guitar][Jazz‖BLUES‖Rock…]┐ +│ Matched: 12-bar · A maj loop A7→D7→E7 ♻ bar5/12 96BPM │ +│ form ┃A7┃A7┃A7┃A7┃D7┃D7▸┃A7┃A7┃E7┃D7┃A7┃E7┃ (amber sweep) │ +│ ──────────── I7·A7 ──────── IV7·D7 ◀now ──── V7·E7 ────── │ +│ Barre shuffle ●○●●●● fr5 ×●○●●● fr5 ●○●●●● fr7 │ +│ ▸ beginner E-shape A7 A-shape (glows) E-shape E7 │ +│ 9th stabs ▸ ×○♭7●●● fr5 ×○♭7●●● fr5 ×○♭7●●13 V13 │ +│ int (Texas) R-3-♭7-9 "IV9" horn hook │ +│ Tritone shell ×○●●×× fr5 ×○●●×× fr5 ×○●●×× fr7 │ +│ minimal/comp R-♭7-3 inner pair −1 Chicago grip │ +│ ⌄ more ways (2): Jimmy Reed · Stormy │ +│ ═════════════════════════════════════════════════════════ │ +│ IMPROV I7→A Mixo · target 3rds C♯→F♯→G♯ · curl ♭3↗3 ♪tap │ +│ ▲ columns = loop chords · rows = ways to voice · scan ↕ │ +└──────────────────────────────────────────────────────────┘ +``` diff --git a/docs/design/jam-guide-concept-c.md b/docs/design/jam-guide-concept-c.md new file mode 100644 index 0000000..c0e297d --- /dev/null +++ b/docs/design/jam-guide-concept-c.md @@ -0,0 +1,130 @@ +# Jam Guide — Concept C: "Roadmap" + +> **Thesis:** Don't show chords — show the *journey through the loop* and what to solo over it. A horizontal timeline with a live "you are here" playhead, each station previewing its guide tones (3rds & 7ths) and the scale to blow over, with voice-leading rails drawn *between* the chords so the player sees the next note coming before it arrives. + +Concept C is the **improv-first** option. Where Concept A optimises for *playing the chord in front of you* and Concept B for *comparing voicings at rest*, Concept C optimises for the soloist's question: **"the loop is turning — what do I aim at next, and what scale carries me there?"** The chord *voicing* diagram is present but demoted to a thin strip; the hero is the **improv map**: a lane of guide-tone targets and a lane of voice-leading arrows running left-to-right under a moving playhead. + +It leans hardest into the learning-platform vision in `GOAL.md` Part 2 (L2 "next-chord preview tier", target-note highlighting) and the curriculum's **Tier B — Playing the Changes** (guide tones, the 7th-falls-to-the-3rd rail) and **Tier D — Functional Ears** (seeing the loop as motion, predicting the V). + +--- + +## 1. Name + thesis + +**Roadmap** — the live progression as a horizontal highway: a playhead drives left-to-right through the loop, each chord is a station showing its **target tones + scale**, and **voice-leading rails** connect each station to the next so you read the change one beat early. + +--- + +## 2. Mockup (full-width panel, ii–V–I in C — the gold-standard `jazz-251-major`) + +Detected loop `Dm7 → G7 → Cmaj7`, key C major, mode major. Playhead currently over G7, leaning into Cmaj7. Active station glows accent-purple; the rest are dimmed by age exactly like the existing `ProgressionBanner` opacity tiers. + +``` +┌─ JAM GUIDE ───────────────────────────────────────────── [Guitar ▾] · Jazz │ Blues │ Rock │ Bossa … ─┐ +│ ii–V–I in C major · your loop: Dm7 → G7 → Cmaj7 · ♻ 2 bars/chord · ~132 BPM │ +│ │ +│ ┌──── bar 1 ───────────┬──── bar 2 ───────────┬──── bars 3-4 ──────────────┐ ◀ lookahead 1 beat │ +│ │ Dm7 (ii7) │ ▶ G7 (V7) ◀ now │ Cmaj7 (Imaj7) │ │ +│ │ D dorian │ G mixolydian │ C major (avoid 4) │ ← SCALE lane │ +│ ├──────────────────────┼──────────────────────┼────────────────────────────┤ │ +│ │ guide tones │ guide tones │ guide tones │ │ +│ │ 3rd ● F 7th ○ C │ 3rd ● B 7th ○ F │ 3rd ● E 7th ○ B │ ← TARGET lane │ +│ │ ╲ │ ╲ │ │ (land these on 1) │ +│ │ C ─────────▶ B │ F ─────────▶ E │ ( B holds → next loop ) │ ← VOICE-LEADING │ +│ │ 7th of ii falls ½ │ 7th of V falls ½ │ resolved — get light │ rails (7→3) │ +│ ├──────────────────────┼──────────────────────┼────────────────────────────┤ │ +│ │ ▣▣·▣· shell │ ▣·▣▣· shell │ ▣▣·▣· shell │ ← voicing strip │ +│ │ R–♭3–♭7 (tap ▸) │ R–3–♭7 (tap ▸) │ R–3–7 (tap ▸) │ (secondary) │ +│ └──────────────────────┴──────────────────────┴────────────────────────────┘ │ +│ ◐──────────────────────────────●───────────────────────────────────────── loop playhead │ +│ │·····│·····│·····│·····│·····│●····│·····│·····│·····│·····│·····│·····│ ← beat grid (you here) │ +│ │ +│ TIP In any ii–V–I the 7th of one chord falls a half-step to the 3rd of the next — C→B, F→E. │ +│ That two-note rail is the whole map. · tap a station → its guide tones light the fretboard ▸ │ +└───────────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +The same panel over a **minor blues** (`blues-minor`-style, key A minor) reads as a longer highway — 12 stations scroll horizontally under the fixed playhead, the TARGET lane showing the ♭3/♭7 of each i7/iv7/V7 and the VOICE-LEADING rail highlighting the chromatic approach into bar 11's return home. The lookahead flag always sits one chord to the right of the playhead so the soloist sees the *incoming* target before the band gets there. + +**Why this layout:** the three stacked lanes (SCALE / TARGET / VOICE-LEADING) are the literal pedagogy of "playing the changes" turned into a picture you read at a glance. The voicing strip is one row, not the hero — a soloist needs *where to aim*, not *how to grip*, and can tap to expand a grip when comping. + +--- + +## 3. Interaction & live-sync model + +**Playhead = loop position, continuously.** The `●` rides the beat grid driven by the onset/BPM pipeline (`handleOnset` tempo histogram → BPM) and the `findLoopPosition` util (extracted in L-01). Two sync layers: + +- **Coarse (chord-accurate, ships first):** the active *station* is whatever `findLoopPosition(chordHistory, detectedProgression)` returns — exactly how `ProgressionBanner` already highlights the loop. Re-uses proven logic; no new timing risk. The playhead snaps station-to-station on each detected change. +- **Fine (beat-interpolated, phase 5 polish):** between detected changes, advance the `●` across the station's beat cells by interpolating `(now − lastOnsetTime) × BPM/60`, clamped to the station's `bars × 4` beats. Purely visual easing — if detection corrects the position, the playhead re-snaps. Degrades gracefully to coarse when BPM is unknown. + +**Lookahead.** The station immediately right of the playhead carries a persistent **lookahead flag** ("◀ lookahead"). Its TARGET lane is pre-lit at ~60% brightness a configurable lead (default 1 beat) before the playhead crosses the barline — this is L2's "next-chord preview tier" and the bassist's walking-line scaffold. The flag answers "what's coming" without the player losing the current station. + +**Tap to drill deeper (progressive disclosure):** +- **Tap a station** → emits `onChordClick(chord)` (the prop `ProgressionBanner` already fires) so the existing `Fretboard`/`Piano` views light that chord's tones, *plus* a Roadmap-specific extra: the station's two guide tones render in the accent tier and its scale in the pentatonic/scale tiers — i.e. "show me where to aim on the neck." +- **Tap the SCALE label** → toggles the fretboard between the full scale and the chord-tone-only skeleton for that chord (the curriculum's "chord inside the scale" drill). +- **Tap the voicing strip `▸`** → expands that one cell into a full `ChordDiagram` (D-01) inline, without leaving the roadmap. This is the only place Concept C surfaces a real grip; it stays out of the way until asked. +- **Tap TIP** → expands the progression's `tip` plus any `lick.tab` whose `over` matches this progression id, rendered as monospace tab under the highway. + +**Live behaviour when no loop is matched.** Fallback to a single-station roadmap centred on `currentChord`: its guide tones, a `getCompatibleScales`-derived scale, and the voicing strip — so the panel is never empty (same fallback contract as the kb-plan §4 matching note). + +**Keyboard / a11y.** Left/Right arrows move focus station-to-station (independent of the playhead); Enter = tap; the active station carries `aria-current="true"` and a visible focus ring (`ring-accent`). The playhead has `role="progressbar"` with `aria-valuetext` = current chord + beat. All lane colours meet AA against `bg-panel` (the accent `#a855f7` on `#1a1a1a` and amber `#f59e0b` for the held/secondary tone both clear 4.5:1; dimmed stations never drop below the 0.25 opacity floor the banner already uses for legibility). + +--- + +## 4. KB-data mapping — what's data vs. what's computed + +| Roadmap element | Source | Data field / helper | +|---|---|---| +| Station chord names (`Dm7 G7 Cmaj7`) | **derived at runtime** | detected loop → key root + `progression.degrees` + `qualities`, resolved like `getSuggestedProgressions` already does | +| Roman numerals (`ii7 V7 Imaj7`) | **data** | `progression.rn` (display) — falls back to computed `toRomanNumeral` for the no-match case | +| Bars per station (`bar 1 / bars 3-4`) | **data** | `progression.bars` — drives station width on the highway | +| SCALE lane (`D dorian`, `G mixolydian`) | **data, with computed fallback** | KB `improv.scales[{over, scale, why}]` keyed by the chord's `rn`. If a style's pack has no `improv.scales` entry for a degree → **compute** a default from `SCALES`/`getCompatibleScales` (e.g. Mixolydian over a dom7) | +| "avoid 4" / scale caveats | **data** | `improv.scales[].why` (the jazz pack literally says "avoid sitting on the 4th over the maj7") | +| TARGET lane — 3rd & 7th tones | **fully computed** | `getChordTones(chord)` → index 1 = 3rd, last = 7th (per `CHORD_TYPES.intervals` ordering). *No KB field stores guide tones; theory.js derives them.* | +| VOICE-LEADING rails (`C ▶ B`, `F ▶ E`) | **computed** | for adjacent stations, find the 7th of chord *n* and the 3rd of chord *n+1*; draw a rail when they're a half/whole step apart. The "7→3 falls ½" relationship comes from comparing `getChordTones` outputs — pure interval math | +| TARGET-lane prose hint | **data** | `improv.targetNotes` ("Land the 3rd of each chord on the downbeat") | +| Voicing strip (mini grid + `R–3–♭7`) | **data** | `plays[progId][0].chords[i].shape` (rendered tiny) + `.note` label; full grip on tap via `ChordDiagram` | +| TIP line | **data** | `progression.tip`; lick tab from `improv.licks[].tab` filtered by `over === progId` | +| Playhead position | **computed (live)** | `findLoopPosition` (L-01) + BPM from `handleOnset`; no KB data | +| BPM / feel label | **data + live** | `meta.tempoRange` / `meta.feel` for context; live BPM from the onset pipeline | + +**Honesty note — the load-bearing computed pieces.** Concept C's two hero lanes are *not in the KB at all*: +1. **Guide tones** (3rd/7th badges) are computed from `getChordTones`. The KB stores *that* a scale fits and *that* the 7th resolves (prose), but never the literal pitches — those are derived per detected key. This is a feature: it stays key-agnostic (kb-plan principle 1) and works in all 12 keys for free. +2. **Voice-leading rails** are computed by diffing consecutive chords' tone sets. No new `theory.js` function is strictly required — `getChordTones` + a small `voiceLeadingPairs(chordA, chordB)` helper (≤15 lines: match each tone of A to its nearest tone in B, keep moves ≤2 semitones) covers it. I'd flag this helper to Maestro as a tiny shared `theory.js`/`match.js` addition Luthier owns; Muse only consumes its output. + +Everything else is straight KB reads. The scale lane degrades gracefully: data-driven where a pack authored `improv.scales`, computed-default where it didn't — so the roadmap renders for *any* style cell, even a minimal one. + +--- + +## 5. Pros / cons / what it sacrifices + +**Pros** +1. **Directly teaches improv** — guide tones + scale + voice-leading rails are the curriculum's "playing the changes" pillar rendered literally; this is the only concept that answers *"what do I solo with?"* rather than *"what's the chord?"* +2. **Lookahead is built in** — the one-beat-early next-target preview is L2's headline learning feature and the thing a soloist physically needs; it's structural here, bolted-on elsewhere. +3. **Maximises the KB's prose assets** — `improv.scales[].why`, `targetNotes`, `tip`, and `licks` (rich, sourced text the Professor wrote) get top billing instead of being buried under diagrams. +4. **Key-agnostic by construction** — the two hero lanes are computed, so one KB cell drives a correct roadmap in all 12 keys with zero extra data. + +**Cons** +1. **Two computed subsystems** (guide-tone extraction, voice-leading pairing) before it looks "real" — more theory.js surface than A or B, which mostly *display* stored data. Mitigated: both are tiny and reuse `getChordTones`. +2. **Horizontal scroll on long forms** — a 12-bar blues exceeds one screen; stations must shrink or scroll. The fixed-playhead / scrolling-highway pattern solves it but is more layout work than a static grid. +3. **Voicing is genuinely secondary** — a player who opened the panel to *find a grip* has to tap to get it. That's the deliberate trade (see below). + +**What it sacrifices** +- **Voicing comparison.** Concept B shows 3 ways to grip every chord side-by-side; Concept C shows *one* grip per station as a thumbnail and makes you tap for the rest. A jammer whose actual need is "give me a chord shape right now" is better served by A or B. Roadmap bets that the higher-value, harder-to-find guidance is *where to aim your solo* — and that voicings, being concrete and well-served elsewhere in the app, can wait behind a tap. + +--- + +```PREVIEW +ROADMAP — improv-first: the loop as a highway you solo across + ii–V–I in C Dm7 → G7 → Cmaj7 ♻ 2 bars/chord ~132 BPM + ┌── Dm7 (ii7) ──┬─▶ G7 (V7) ◀now ─┬── Cmaj7 (Imaj7) ──┐ ◀ look- + │ D dorian │ G mixolydian │ C major (avoid 4) │ ahead + │ 3rd●F 7th○C │ 3rd●B 7th○F │ 3rd●E 7th○B │ ← targets + │ C ──▶ B │ F ──▶ E │ ( B holds → loop )│ ← 7→3 rail + │ ▣▣·▣· shell ▸ │ ▣·▣▣· shell ▸ │ ▣▣·▣· shell ▸ │ ← voicing + └───────────────┴─────────────────┴────────────────────┘ + ◐────────────────●────────────────────────────────── playhead + │··│··│··│··│··│●·│··│··│··│··│··│··│ beat grid (here) + TIP 7th of one chord falls ½-step to the 3rd of the next: + C→B, F→E — that two-note rail is the whole map. + tap a station → its guide tones light up the fretboard ▸ +```