diff --git a/docs/agents/LEDGER.md b/docs/agents/LEDGER.md index 9d493f8..4517444 100644 --- a/docs/agents/LEDGER.md +++ b/docs/agents/LEDGER.md @@ -21,13 +21,13 @@ The shared queue all agents read and write. Lifecycle and rules: [`PROTOCOL.md`] |----|-------|--------|--------|-----------|--------------|--------------------| | M-04 | Seed `sprint-glance-and-loop` from user directive 2026-07-10; schedule the 24×30m loop | maestro | done | — | `docs/agents/LEDGER.md` | sprint seeded, cron created | | C-30 | Loop-detection truth fixtures: new `scripts/loop-fixtures.mjs` (+ smoke wiring) — realistic chord-history cases with expected loops: (a) clean 3-chord loop ×2–3 reps; (b) 3-chord loop with one spurious misdetection inside a rep; (c) consecutive duplicate commits of the same chord; (d) 5-chord loop followed by 2 foreign chords — loop must survive; (e) 7- and 8-chord loops; (f) section change loop-A→loop-B — detection must switch; (g) chromatic non-loop → null. Run each against the CURRENT `detectRepeatingProgression` and mark which fail today (`expectedFail: true`) so the suite is green now and L-30 flips the markers off | quality | done | — | `scripts/loop-fixtures.mjs`, `scripts/smoke.mjs` | fixtures runnable via smoke; failure map of the current algorithm documented in the fixture file header; smoke green (expected-fails annotated, not silently skipped) | -| L-30 | Redesign `detectRepeatingProgression` in `theory.js`: collapse consecutive duplicate chords before matching; tolerate ≤1 substitution/insertion per cycle (noise from misdetection); support loop lengths 2–8; recency-weighted scoring so an old section can't outvote the current loop; keep the pure signature, the rotation-`canonicalize` output, and every other export byte-untouched. Flip all C-30 `expectedFail` markers to passing. **C-30 findings folded in (2026-07-10):** (a) the `reps × len²` scoring artifact is the primary everyday bug — a clean 2-chord vamp ×4 reports a bogus 3-chord `[Am,Am,G]` via self-overlapping occurrences; candidate generation must reject candidates that are rotations/overlaps of a shorter period (not just exact periodic patterns at len ≥ 4); (b) 7/8-loops contain realistic non-adjacent internal chord repeats (`Am … Am`) — period detection must not collapse those into shorter false loops | engineering | claimed | C-30 | `src/lib/theory.js` (detectRepeatingProgression + private helpers only) | all C-30 fixtures green with zero expectedFail markers (incl. `vamp-2x4`/`vamp-2-sustained`); no other theory.js export changed; build + smoke green | -| L-31 | Commit-layer tuning in App.jsx's progression effect (lines ~154-173): a committed loop must survive transient misses (the miss-4-then-clear rule drops the loop during fills/turnarounds); a new loop replaces the old only with consistent evidence; first commit shouldn't need extra rounds when detection is already stable. **Primary trace case (C-30 finding, 2026-07-10):** pre-L-30 detection flaps between the true loop and ghost 4-patterns, so `progressionVoteRef` never sees 2 consecutive identical keys and nothing ever commits — verify post-L-30 stability makes the 2-vote commit reachable in the noisy fixtures, then tune. 🚨 **Audio contract: touch ONLY the progression useEffect + its refs — no callback, ref-sync, or AudioCapture change** | engineering | backlog | L-30 | `src/App.jsx` (progression effect only) | loop survives fixture-style fills end-to-end (hand-trace documented in commit); App.jsx diff confined to the progression effect block; build + smoke green | +| L-30 | Redesign `detectRepeatingProgression` in `theory.js`: collapse consecutive duplicate chords before matching; tolerate ≤1 substitution/insertion per cycle (noise from misdetection); support loop lengths 2–8; recency-weighted scoring so an old section can't outvote the current loop; keep the pure signature, the rotation-`canonicalize` output, and every other export byte-untouched. Flip all C-30 `expectedFail` markers to passing. **C-30 findings folded in (2026-07-10):** (a) the `reps × len²` scoring artifact is the primary everyday bug — a clean 2-chord vamp ×4 reports a bogus 3-chord `[Am,Am,G]` via self-overlapping occurrences; candidate generation must reject candidates that are rotations/overlaps of a shorter period (not just exact periodic patterns at len ≥ 4); (b) 7/8-loops contain realistic non-adjacent internal chord repeats (`Am … Am`) — period detection must not collapse those into shorter false loops | engineering | done | C-30 | `src/lib/theory.js` (detectRepeatingProgression + private helpers only) | all C-30 fixtures green with zero expectedFail markers (incl. `vamp-2x4`/`vamp-2-sustained`); no other theory.js export changed; build + smoke green | +| L-31 | Commit-layer tuning in App.jsx's progression effect (lines ~154-173): a committed loop must survive transient misses (the miss-4-then-clear rule drops the loop during fills/turnarounds); a new loop replaces the old only with consistent evidence; first commit shouldn't need extra rounds when detection is already stable. **Primary trace case (C-30 finding, 2026-07-10):** pre-L-30 detection flaps between the true loop and ghost 4-patterns, so `progressionVoteRef` never sees 2 consecutive identical keys and nothing ever commits — verify post-L-30 stability makes the 2-vote commit reachable in the noisy fixtures, then tune (post-L-30 status: claimed). **L-30 gate findings folded in (2026-07-10):** (a) a 2-rep loop with one corrupted rep FLAPS through data-faithful sub-cycles commit-to-commit until the next clean rep — faster first-commit must NOT let a single transient sub-cycle detection replace an already-committed loop (replacement needs consistent evidence); note non-null detection resets the miss counter, so today's committed loop already survives the flap; (b) ride-along one-line fix: theory.js ~line 601-603 docstring overclaims "ghost occurs exactly once by construction" — false for same-chord-same-phase corruption (behavior fine, comment too strong); (c) deletions untolerated by design — fine at ≥3 reps, degrades to (a)'s flapping at exactly 2. 🚨 **Audio contract: touch ONLY the progression useEffect + its refs — no callback, ref-sync, or AudioCapture change** | engineering | claimed | L-30 | `src/App.jsx` (progression effect only) | loop survives fixture-style fills end-to-end (hand-trace documented in commit); App.jsx diff confined to the progression effect block; build + smoke green | | D-30 | VoicingBrowser gallery: render ALL matching guitar shapes side by side (each = label + ChordDiagram + its own ▶) and all four piano styles side by side (label + MiniPiano thumb + ▶) — no chips, no selection state; grid wraps on narrow viewports; one-at-a-time playback preserved (new play stops the previous). All existing mounts (Voicings section, ChordDetailModal tabs, JamGuide station-enlarge) get the gallery automatically; `show` prop semantics unchanged | design | done | — | `src/components/VoicingBrowser.jsx` | every placeable shape/style visible simultaneously with zero clicks; AA contrast + tokens; keyboard-reachable play buttons; build + smoke green | | D-31 | Glance-mode concept doc: the Knowledge Center panel open WHILE the jam plays — what auto-follows live detection with zero clicks (current station's voicing gallery inline? licks strip for the style? what stays on screen vs behind interaction), density/space budget vs the Roadmap track, narrow-viewport plan, and the migration order for L-33. No user gate: pick the strongest layout, record rationale + rejected alternatives. **Returned once (2026-07-10):** piano gallery width understated ~45% (2-octave crops for rootless 7th-chord voicings → ~940px not 640; scroll is the piano rail's normal state on most loops) + licks strip ~190px not 150 + 4 clarifying notes; layout itself held — fixed + re-gate PASS | design | done | — | `docs/design/glance-mode.md` | doc names every component to touch, the auto-follow rules, and honest space math (what fits at 1280×900 and at narrow) | | L-33 | Implement glance mode per D-31 (`docs/design/glance-mode.md` — the "playhead accordion"): the station column at canonicalPos expands to the full D-30 gallery and advances with the playhead; licks strip below (level-filtered, token-boundary context match, strip-owned "fits — now" chrome, guitar licks under piano tab with honest heading); pin gesture inherits onFocusChord semantics; auto-follow never emits focus-chord and never auto-plays audio; piano rail EXPECTED to scroll (never assert one-row fits); follow the doc's 5-commit migration order | engineering | claimed | D-30, D-31 | `src/components/GlanceRail.jsx` (new), `src/components/JamGuide.jsx`, `src/components/VoicingBrowser.jsx` (optional additive `dense` prop only) | glance behaviours live per the doc; audio contract intact (App.jsx untouched or additive-only); build + smoke green | -| P-30 | KB expansion: **neo-soul/rnb piano** cell (next per `docs/kb-backlog.md` after jazz/gospel) | content | claimed | — | `src/data/kb/rnb/piano.js`, `src/data/kb/index.js` | validator green + registered; renders in the piano tab; prose claims arithmetic-verified | -| P-31 | KB expansion: **blues piano** cell | content | backlog | P-30 | `src/data/kb/blues/piano.js`, `src/data/kb/index.js` | validator green + registered | +| P-30 | KB expansion: **neo-soul/rnb piano** cell (next per `docs/kb-backlog.md` after jazz/gospel) | content | done | — | `src/data/kb/rnb/piano.js`, `src/data/kb/index.js` | validator green + registered; renders in the piano tab; prose claims arithmetic-verified | +| P-31 | KB expansion: **blues piano** cell | content | claimed | P-30 | `src/data/kb/blues/piano.js`, `src/data/kb/index.js` | validator green + registered | | C-31 | Sprint-end sweep: full build + validator + smoke + fixtures, then update PR #3 (push + PR body/comment summarising this sprint) per PROTOCOL §6 | quality | backlog | L-31, L-33, D-30 | (none — verification) | all green; PR #3 updated | > Sequencing: C-30 ‖ D-30 ‖ D-31 ‖ P-30 are file-disjoint and ready now. Then C-30 → L-30 → L-31 (serial chain on theory.js/App.jsx), and D-30+D-31 → L-33. P-31 fills spare iterations. Critic gates every task. @@ -38,6 +38,10 @@ The shared queue all agents read and write. Lifecycle and rules: [`PROTOCOL.md`] > GATE 2026-07-10 (Critic) · **D-31 RETURNED → PASS on scoped re-gate** — first gate verified the playhead-accordion layout, the App.jsx-zero-changes claim (all 7 props already flow; pin inherits selectedStation semantics incl. reset effects), chordContext data support, and the vertical budget (256px at 1280×900 recomputed from real component geometry) but returned one arithmetic finding: expanded piano gallery ~640px understated ~45% (rootless A/B of true-7th chords → 2-octave D-24 crops = 266px thumbs) + licks strip 150→190px. Muse fixed: 940 / 1350–1550 (scrolls at ~1200, not "borderline") / 2300 / 3,500+ / 190 / 1070, "scroll is the piano rail's normal state on most loops", commit-5 must never assert one-row-fits, + 4 notes (token-boundary chordContext match; strip-owned "fits — now" chrome; guitar licks under piano tab stated; licksFor "lifted not reused"). Re-gate recomputed Dm7 rootlessA [17,21,24,28] → 266px from piano.js/MiniPiano.jsx, grep-verified no stale figures, no regression to passed sections. Nuance (non-blocking, for L-33): "any true-7th chord" slightly overgeneral — some rootless voicings fit 1 octave (e.g. Dm7 rootlessB); 940 is the correct conservative worst case. +> GATE 2026-07-10 (Critic) · **P-30 PASS first try** (`b51daa1`) — validator 154 plays green, build green, shared-tree smoke 817/817. Independent arithmetic (own script from SCHEMA/CHORD_TYPES, not Professor's): max per-hand span 11 (≤15), ≤4 notes/hand, combined span ≤23 → every recipe renders for all 12 roots in the 36-key window (zero silent fallbacks); 11 hand-picked prose claims all recompute exactly (♭VI→V sink 1,1,1,1,2; 9sus RH = major triad on ♭7; So What [0,5,10,15,19]; I-RH ≡ vi7-RH pcs; 13sus = Type A bottom+1; ...). Rule-4 idiomatic difference genuine per pair; outside-key 9-on-iii honestly flagged; sources hedged. One chased-and-accepted oddity: ♭VI13 stab's C–F–G♭ pinch is deliberate voice-leading, not a stacking bug. + +> GATE 2026-07-10 (Critic) · **L-30 PASS** (`4cc0009`) — smoke 817/817 (all 17 fixtures plain guards, 9 original greens no regression), validator + build green. Diff confined: theory.js 2 hunks in the repeating-progression section only, `canonicalize` unchanged context; loop-fixtures.mjs = marker removals + historical rewordings, every history/expect array untouched (frozen contract intact). 15 novel generalization probes: 11 correct, 3 data-faithful (only phase-locked exactly-alternating corruption yields a doubled pattern — genuinely 6-periodic data no algorithm could distinguish), 1 better-than-expected (all-reps-edited loop found via clean rotation). Every reportable "ghost" now corresponds to a pattern that exactly recurred — the old structurally-fake ghosts are gone. Perf 0.21–0.73 ms/call ×1000. Consumer contract at App.jsx:154-173 type-matches. 3 non-blocking findings folded into L-31's row. + --- ## Shipped sprint: `sprint-knowledge-center` (branch: `sprint-jamguide-piano` — complete 2026-07-09, PR #3) @@ -152,6 +156,7 @@ Emphasis this sprint: **ship the Jam Guide MVP** (put the 8 guitar style packs o - **Level-tag `FAMOUS_PROGRESSIONS`** (`src/lib/education.js`, Professor): famous-progression cards are exempt from the level filter this sprint (Maestro call 2026-07-08, per D-20 open question 1). - **Drift guards in smoke (Critic, tiny):** two hand-synced duplications need permanent smoke checks — JamGuide.jsx's copy of the validator's `resolveDegree` (fold in the L-24 gate's 16-degree × 14-quality drift test) and the 8-word technique vocab duplicated between `validate-kb.mjs` `LICK_TECHNIQUES` and `LickCard.jsx` `TECHNIQUE_VOCAB` (C-21 finding). - **`pianoVoicing` should return `rootPc` (Luthier, tiny):** callers currently must attach it themselves (JamGuide and VoicingBrowser both do); returning it at the source removes the false-"R" foot-gun for future consumers (D-24 gate observation — NOT a live bug, both call sites verified correct 2026-07-08). +- **`docs/kb-backlog.md` is stale (Professor, tiny):** still lists gospel/pop guitar + jazz/gospel piano as "todo" though shipped; P-30 (rnb piano, 2026-07-10) also needs a done entry — refresh next content iteration (flagged by P-30, outside its lock). - **Fingering view lost at gallery thumb size (Muse, small):** D-30's gallery renders ChordDiagram at `size="thumb"`, which never draws finger numbers — nothing in the browser shows fingering anymore (D-30 gate note 2026-07-10). If pedagogically wanted: tap-to-enlarge to `size="full"` inside a gallery cell. - **Negative-fret shape handling inconsistency (Luthier, small):** `voicings.js` skips shapes that compute negative frets while `chordAudio.guitarShapeToNotes` slides them up an octave — pre-existing, flagged at the L-23 gate; unify someday. @@ -183,6 +188,7 @@ _(Maestro appends one line per completed iteration: ` · - 2026-07-09 · **iteration 8/24 — SPRINT `sprint-knowledge-center` COMPLETE** · done: C-21 (sprint-end sweep — build/validator/smoke all green on 72c6d45; full-App SSR renders; authored vs computed piano paths both proven; zero dead imports; audio contract +1 line since seed) · **PR #3 opened: https://github.com/whattheflat/JamBuddy/pull/3** (supersedes PR #2 — main hadn't absorbed it) · all 21 sprint tasks done, 4 returned-then-fixed by the gate, 0 unresolved · loop cron deleted after 8 of 24 budgeted iterations (board empty) · remaining backlog: EducationPanel retirement, FAMOUS_PROGRESSIONS level tags, smoke drift guards, pianoVoicing rootPc, negative-fret unify, L-12, bass renderer - 2026-07-09 · **iterations 6–7/24** · done: L-25 (`e24aa4b` instrument-scoped modal tabs), C-22 (`b4e8f12` validator hand-span rule, smoke 799), P-23 (`564a9e0` gospel piano cell, 140 plays — returned once: one improv-row scale claim false for vi7/iii7, split into exact rows, PASS re-gate; 39/40 first-pass claims held), L-24 (`2165bb5` authored piano packs render at stations — implementer agent hung at verification after ~1 h, killed, completion-pass agent audited + finished; Critic PASS with 0 resolver drift) · incidents: P-23 stalled once mid-authoring (resumed from transcript, no loss); L-24 hung silently (diff intact, completed by fresh agent) · backlog: resolveDegree drift guard filed · **board empty except C-21 → sprint-end sweep + PR** - 2026-07-08/09 · **iteration 5/24** · done: D-23 (`db397f6` VoicingBrowser show prop + LickCard stack-guard), D-24 (`e2110ae` MiniPiano thumbs crop to voicing span, 266→142 px), P-24 (11 licks rock/country/reggae — KB now **23 licks across 6 styles**, every note pitch-verified) — Critic PASS all three, zero returns · D-24 gate raised a false alarm on the D-21 rootPc fix (its harness bypassed VoicingBrowser; Maestro verified line 297 intact — no regression); hardening idea backlogged (`pianoVoicing` return rootPc) · promoted L-25 · next ready (all file-disjoint): L-24 ‖ L-25 ‖ C-22 ‖ P-23, then C-21 closes the sprint +- 2026-07-10 · **iteration 2/24** · done: P-30 (`b51daa1` rnb piano cell, KB 154 plays — PASS first try, a piano-pack first; found+fixed its own 36-key-window stacking defect pre-review), L-30 (`4cc0009` detector rewrite: dup-collapse, weak-period ghost rejection, len 2–8, ≤1 edit/cycle with ≥2-exact evidence gate, recency-weighted coverage — smoke 817/817, gate ran 15 novel probes, 0.2–0.7ms/call) · L-33 built (playhead accordion + LicksStrip + heard-live fallback, SSR 24/24 self-checked) — gate in flight · L-31 dispatched with both gates' findings folded (flap-survival constraint, docstring ride-along) · both watchdog-stalled agents recovered cleanly via resume · promoted: P-31 · next: gate L-33, land L-31, then C-31 closes - 2026-07-10 · **iteration 1/24** · done: M-04, D-30 (`0945a08` VoicingBrowser gallery — all shapes/styles side by side, no chips; PASS first try), C-30 (`fdd93c7` 17 loop fixtures + smoke wiring; PASS — found the len² self-overlap artifact as the root cause of the user's missed 3-chord loops, folded into L-30/L-31 DoDs), D-31 (`6c7a1a7` glance-mode "playhead accordion" doc — returned once on piano-gallery width math, fixed, PASS re-gate) · in flight: L-30 (detector redesign, dispatched early — C-30 contract ready), P-30 (rnb piano) — both stalled once on the 600s API watchdog near completion, both resumed via SendMessage · promoted: L-33 (ready, locks per D-31 doc) · finding worth noting: "5 chords then 2 others" passes at pure-function level — the live failure is the ghost-pattern flapping starving the 2-vote commit layer (L-31's trace case) - 2026-07-10 · **new sprint `sprint-glance-and-loop`** seeded on the SAME branch (commits extend PR #3) · user asks: all voicing variations side-by-side with no button pushing; fix loop detection (misses a returning 3-chord loop and a 5-chords-then-2-others shape); glanceable zero-click learn session that follows the live jam · loop scheduled: /jam-loop every 30 min × 24 iterations (12 h, cron 13,43) · ready now (file-disjoint): C-30 ‖ D-30 ‖ D-31 ‖ P-30, then C-30→L-30→L-31 and D-30+D-31→L-33 - 2026-07-08 · **iteration 3/24** · done: L-21 (`951d544` VoicingBrowser live in ChordDetailModal Guitar/Piano tabs + JamGuide enlarged stations — the "playable voicings per chord" user ask is now end-to-end), L-23 (`f4e0ac6` getGuitarVoicings base-fret fix — 252 movable-shape placements corrected, A-shape C was labeled fret 1 not 3) — Critic PASS both, zero returns this round · follow-ups filed: VoicingBrowser `show` prop (Muse), negative-fret handling inconsistency (Luthier), stale JamGuide header comment · P-21 lock narrowed to the 3 guitar.js files → P-22 now disjoint · next ready (file-disjoint): P-21 ‖ P-22 ‖ L-22 (licks section may land empty-state-first per D-20 doc)