feat(related): RelatedProgressions — loop-relative suggestions replace the generic table (task L-51)
KB-sourced ranking per the one-screen spec: same canonical degree shape +100 (with the mandatory collapse of consecutive equal degree/quality pairs — a real detector-produced 12-bar fires its blues relatives despite the raw-index matcher bug), same style +40, shared transitions +12 capped 36, degree-set Jaccard, length penalty; floor 24, max 5, never padded; entries render name/style/level/annotation + the chord chain realized in the live key as real buttons -> ChordDetailModal. match.js: additive exports only. Ride-along: dead currentChord prop dropped from the banner mount. Critic PASS (both hand-verified scores recomputed independently; full entry lists byte-matched on three scenarios; collapse counterfactual = 39). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+6
-2
@@ -91,7 +91,9 @@ export function findLoopPosition(chordHistory, loop) {
|
||||
// for each rotation, re-base so the first element is 0, then pick the
|
||||
// lexicographically smallest resulting sequence. Same loop → same string,
|
||||
// regardless of which chord it starts on.
|
||||
function canonicalDegrees(degrees) {
|
||||
// Exported additively for RelatedProgressions' ranking (task L-51,
|
||||
// one-screen.md §5) — no behaviour change.
|
||||
export function canonicalDegrees(degrees) {
|
||||
const n = degrees.length
|
||||
if (n === 0) return ''
|
||||
let best = null
|
||||
@@ -110,7 +112,9 @@ function canonicalDegrees(degrees) {
|
||||
|
||||
// Converts a loop of chord-name strings into semitone offsets from the loop's
|
||||
// own first chord. Returns null if any chord root is unparseable.
|
||||
function loopToDegrees(loop) {
|
||||
// Exported additively for RelatedProgressions' ranking (task L-51,
|
||||
// one-screen.md §5) — no behaviour change.
|
||||
export function loopToDegrees(loop) {
|
||||
if (!loop?.length) return null
|
||||
const pcs = loop.map(chordRootPC)
|
||||
if (pcs.some(pc => pc < 0)) return null
|
||||
|
||||
Reference in New Issue
Block a user