feedBack/tests/js
ChrisBeWithYou cc75cb876a
fix(library): tuning filter answers for your instrument, not always guitar (#1003)
* fix(library): tuning filter answers for your instrument, not always guitar

The library indexed exactly one tuning per song, chosen guitar-first (lead >
rhythm > combo, bass only as a last resort), and nothing consulted the
player's instrument. A bassist filtering by tuning was shown the guitar
chart's tuning, so playlists built by tuning contained songs needing a
retune. Reported by a tester building bass practice sets; Covet "Shibuya" is
the clean case, with a custom guitar tuning over a standard bass chart.

Indexes each arrangement role's own tuning and makes the facet, filter, sort
and labels answer for one perspective. `guitar-lead` reads the original
unprefixed columns and adds no payload keys, so the default response is
unchanged. The same defect existed inside guitar -- lead and rhythm charts
can disagree -- so perspective is three-valued (guitar-lead, guitar-rhythm,
bass) driven by one PERSPECTIVES table rather than parallel column families.

Songs with no chart for the perspective fall back to the song-level tuning
rather than vanishing (18 of 59 packs in the test library have no bass
chart), but the fallback is marked inferred in the facet counts and on the
row instead of being silently coalesced. "Only real charts" reuses the
existing `arrangements_has` filter rather than adding one.

Bass-specific handling, from measured content:
- Bass tuning arrays are padded to six entries; charts never reference
  string index 4 or 5. Truncated to four before naming and grouping.
- Grouping uses a canonical open-pitch key, so [-2,0,0,0] and
  [-2,0,0,0,0,0] are one facet row instead of two.
- Offsets above +1 semitone are refused a name. Bassists tune down, near
  never up; one pack ships [5,5,5,5,4,4] (A-D-G-C, unplayable, and its own
  notes sit in the song's real key under standard tuning). Naming that
  would send a player to retune to a tuning that does not exist.

Rhythm deliberately does not truncate -- padding is a bass finding, and
cutting a seven-string array would invent a tuning the chart lacks.

Adds an opt-in `tuning_match=playable` mode alongside exact match: a chart is
offered when your lowest open pitch is at or below its lowest open pitch, so
a five-string bass covers four-string standard and drop-D with no retune.
Open strings only -- note range is not indexed and the scan stays
manifest-only -- so it fails conservative: unknown low pitch is excluded, and
the upper bound is unchecked and documented rather than guessed.

Existing installs would otherwise never populate: the tree-signature fast
path reports "unchanged" forever on a settled library. Rows with NULL marker
columns re-extract, and the fast path is disabled until that backfill
converges (writes use '' rather than NULL, so it self-clears).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFDokqh2H6mEjk1Kgbi6JW
Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>

* test(v3): accept the tuning-perspective indirection in the badge guard

The album-art badge now reads shownTuningName(), so the source-pattern guard
no longer matched the inline `tuning_name || tuning` form and CI went red.
Accept the helper, and pin the helper's own fallback in a companion test so
the guard still fails if a guitar player's tuning label is ever dropped.

Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>

---------

Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 00:04:30 -05:00
..
alpha_warning_banner.test.js refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
app_tour_library.test.js
audio_effects_host.test.js
audio_effects_test_harness.js
audio_element_accessor.test.js
audio_session_compat.test.js
audio_session_host.test.js
audio_session_input.test.js
audio_session_mix.test.js
audio_session_monitoring.test.js
audio_session_routes.test.js
audio_session_stems_bridge.test.js
audio_session_stems.test.js
audio_session_test_harness.js
autoplay_exit.test.js refactor(app): carve the song session out of app.js — playSong, showScreen, closeCurrentSong (R3d) (#921) 2026-07-12 14:22:19 +02:00
badges_handedness.test.js feat(v3): choose handedness in the instrument selector + onboarding (give lefties a break) (#793) 2026-07-05 23:50:30 +02:00
beats_loaded.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
capabilities_claims.test.js
capabilities_diagnostics.test.js
capabilities_lifecycle.test.js
capabilities_manifest_runtime.test.js
capabilities_multi_provider.test.js
capabilities_ownership.test.js
capabilities_test_harness.js
capabilities_versioning.test.js
capability_inspector_nav.test.js refactor(app): carve the plugin loader out of app.js into static/js/ (R3a) (#878) 2026-07-11 18:18:00 +02:00
capability_inspector_render.test.js
career_plugin.test.js fix(career): gig song selection — full-genre pool, working re-roll, and the venue pack loads (#976) 2026-07-15 10:50:55 +02:00
diagnostics_summary.test.js
drum_keys_highway_3d_resize_reframe.test.js Fix 3D drum/keys highways not resizing on fullscreen under splitscreen (#723) 2026-07-02 18:42:26 +02:00
edit_metadata_modal.test.js refactor(app): carve the edit-song modal into static/js/edit-modal.js (R3d) (#919) 2026-07-12 13:43:57 +02:00
editor_pending_view.test.js feat(player): seed editor region handoff state (#762) 2026-07-05 23:37:39 +02:00
gig_song_end.test.js feat(career): extract the whole setlist before the gig starts (no more waiting between songs) (#971) 2026-07-15 00:36:20 +02:00
handshapes_pipeline.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_3d_arp_deferral.test.js
highway_3d_camera_framing.test.js
highway_3d_context_loss.test.js fix(highway_3d): recover from WebGL context loss instead of crashing on alt-tab (#790) 2026-07-05 22:20:32 +02:00
highway_3d_fret_label_render_order.test.js
highway_3d_fret_row_labels.test.js
highway_3d_fret_spacing.test.js
highway_3d_lean_sustain.test.js
highway_3d_lefty.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_3d_overlay_full_cover.test.js
highway_3d_panel_controls.test.js
highway_3d_pool_warm.test.js
highway_3d_render_order.test.js feat(highway_3d): fret wires flash on a confirmed hit (#969) 2026-07-18 21:11:10 -04:00
highway_3d_resize_reframe.test.js perf: remove throttled-trace residuals — program churn, per-frame rect, HUD clock 2026-07-02 00:40:52 +02:00
highway_3d_slide_target.test.js
highway_3d_smooth_clock_pause.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_3d_sustain_bloom.test.js
highway_3d_sustain_rail.test.js
highway_3d_wide_fov.test.js Address review: Reset on All restores defaults verbatim 2026-07-01 02:59:51 -04:00
highway_adaptive_scale.test.js refactor(highway): carve the constants into static/js/highway-constants.js (R3c) (#914) 2026-07-12 12:24:40 +02:00
highway_audio_barrier.test.js
highway_bend_curve.test.js refactor(highway): carve the PURE geometry primitives into highway-geometry.js (R3c) (#915) 2026-07-12 12:31:56 +02:00
highway_chord_harmony.test.js refactor(highway): carve the PURE geometry primitives into highway-geometry.js (R3c) (#915) 2026-07-12 12:31:56 +02:00
highway_chord_render_cache.test.js refactor(highway): carve the 2D drawing layer into highway-draw.js (R3c) (#917) 2026-07-12 13:00:29 +02:00
highway_colors_facade.test.js refactor(app): carve the highway string-colours out of app.js (R3a) (#883) 2026-07-11 19:22:14 +02:00
highway_filtered_notes.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_monotonic_clock.test.js refactor(highway): carve the constants into static/js/highway-constants.js (R3c) (#914) 2026-07-12 12:24:40 +02:00
highway_note_state.test.js refactor(highway): carve the 2D drawing layer into highway-draw.js (R3c) (#917) 2026-07-12 13:00:29 +02:00
highway_pause_throttle.test.js fix(highway): a SUPERSEDED renderer init is not a FAILED one (#970) 2026-07-15 00:36:16 +02:00
highway_phrases.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_renderer_swap_canvas_reset.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_string_colors.test.js refactor(highway): carve the constants into static/js/highway-constants.js (R3c) (#914) 2026-07-12 12:24:40 +02:00
highway_teaching_marks.test.js refactor(highway): carve the 2D drawing layer into highway-draw.js (R3c) (#917) 2026-07-12 13:00:29 +02:00
highway_visibility.test.js refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
host_contract.test.js refactor(app): the host seam + carve section practice out of app.js (R3a) (#887) 2026-07-11 20:58:41 +02:00
juce_engine_reroute.test.js refactor(app): carve the JUCE/desktop audio shims out of app.js (R3a) (#893) 2026-07-11 22:44:03 +02:00
legacy_shim_hits.test.js fix(plugins): make a module plugin actually re-evaluate on reload (#879) (#897) 2026-07-12 00:19:59 +02:00
library_card_actions.test.js
live_guitar_tone_source.test.js fix(tests): re-green the JS suite — 18 stale source-shape tests + 1 real seek-reason violation (#740) 2026-07-03 14:35:07 +02:00
live_performance_hud.test.js fix(v3): floor accuracy percentages so 100% means all notes hit 2026-07-13 00:35:09 +02:00
loop_api.test.js refactor(app): carve the A–B loop out of app.js (R3a) (#888) 2026-07-11 21:32:31 +02:00
loop_restart.test.js refactor(highway): make the highway global explicit before the module flip (R3c) (#912) 2026-07-12 11:56:07 +02:00
midi_input_domain.test.js
no_showscreen_monkeypatch.test.js fix(nav): nobody may monkey-patch window.showScreen — add screen:changing, make the shell listen (#924) (#925) 2026-07-12 16:06:28 +02:00
note_detection_domain.test.js
pedal_cables.test.js
play_button_reroute_guard.test.js refactor(app): carve the playback transport out of app.js — and RETIRE 8 host hooks (R3a) (#894) 2026-07-11 23:26:35 +02:00
play_queue_peek.test.js fix(venue): fly in once per set, not before every song (#978) 2026-07-15 12:39:25 +02:00
play_queue_shuffle.test.js feat(v3): playlist shuffle toggle 2026-07-03 13:07:47 +02:00
playback_app_adapter.test.js refactor(app): carve the playback transport out of app.js — and RETIRE 8 host hooks (R3a) (#894) 2026-07-11 23:26:35 +02:00
playback_compat.test.js
playback_diagnostics.test.js
playback_domain.test.js
playback_test_harness.js
plugin_hydration_wipe.test.js refactor(app): carve the plugin loader out of app.js into static/js/ (R3a) (#878) 2026-07-11 18:18:00 +02:00
plugin_loader_script_type.test.js fix(plugins): make a module plugin actually re-evaluate on reload (#879) (#897) 2026-07-12 00:19:59 +02:00
plugin_module_rollback.test.js fix(plugins): make a module plugin actually re-evaluate on reload (#879) (#897) 2026-07-12 00:19:59 +02:00
plugin_style_injection.test.js refactor(app): carve the plugin loader out of app.js into static/js/ (R3a) (#878) 2026-07-11 18:18:00 +02:00
plugins_page.test.js
progress_calibration.test.js
progression_notifications.test.js
progression_progress_events.test.js
renderer_bus_feeder.test.js refactor(app): carve the JUCE/desktop audio shims out of app.js (R3a) (#893) 2026-07-11 22:44:03 +02:00
section_practice_dismiss.test.js refactor(app): the host seam + carve section practice out of app.js (R3a) (#887) 2026-07-11 20:58:41 +02:00
settings_autosave.test.js refactor(app): carve settings into static/js/settings.js (R3d) (#920) 2026-07-12 14:08:45 +02:00
show_screen_legacy_home.test.js fix(nav): the library sometimes showed the legacy screen — map 'home' inside showScreen (#923) 2026-07-12 16:05:50 +02:00
song_close.test.js refactor(app): carve the song session out of app.js — playSong, showScreen, closeCurrentSong (R3d) (#921) 2026-07-12 14:22:19 +02:00
song_credits_overlay.test.js refactor(app): carve count-in (and the song-credits overlay) out of app.js (R3a) (#890) 2026-07-11 22:05:22 +02:00
song_event_payload.test.js refactor(highway): make the highway global explicit before the module flip (R3c) (#912) 2026-07-12 11:56:07 +02:00
song_restart.test.js refactor(app): lift the shared player state onto a container (R3a) (#889) 2026-07-11 21:52:51 +02:00
song_seek.test.js refactor(app): carve the playback transport out of app.js — and RETIRE 8 host hooks (R3a) (#894) 2026-07-11 23:26:35 +02:00
speed_reset.test.js refactor(app): carve the song session out of app.js — playSong, showScreen, closeCurrentSong (R3d) (#921) 2026-07-12 14:22:19 +02:00
test_utils.js
tour_engine.test.js
tuner_auto_open.test.js refactor(app): carve the song session out of app.js — playSong, showScreen, closeCurrentSong (R3d) (#921) 2026-07-12 14:22:19 +02:00
tuner_core.test.js
tuning_display.test.js refactor(app): carve the tuning-display helpers out of app.js (R3a) (#884) 2026-07-11 19:37:44 +02:00
tuning_targets.test.js refactor(app): carve the tuning-display helpers out of app.js (R3a) (#884) 2026-07-11 19:37:44 +02:00
v3_add_to_playlist_menu.test.js
v3_az_rail.test.js test(v3): sync A–Z rail assertion to the railParams refactor (#702) (#714) 2026-07-02 14:03:05 +02:00
v3_collections.test.js
v3_favorites_toggle.test.js fix(v3): drawer fav-sync honours data-fav-idle (no dim-heart on List View) (#717) 2026-07-02 14:52:40 +02:00
v3_keep_practicing.test.js fix(tests): re-green the JS suite — 18 stale source-shape tests + 1 real seek-reason violation (#740) 2026-07-03 14:35:07 +02:00
v3_library_refresh.test.js refactor(app): carve the library out of app.js (R3a) (#896) 2026-07-11 23:30:30 +02:00
v3_playlist_cover.test.js
v3_songs_score_badge_refresh.test.js
v3_songs_scroll.test.js
v3_songs_tuning.test.js fix(library): tuning filter answers for your instrument, not always guitar (#1003) 2026-07-19 00:04:30 -05:00
v3_songs_window_recycle.test.js fix(v3): recycle library grid cards on scroll instead of rebuilding the window (#742) 2026-07-05 00:19:46 +02:00
v3_theme_read_api.test.js feat(v3): host theme read surface — window.feedBack.theme + always-present --fbv-* tokens (#646) 2026-07-02 13:57:58 +02:00
v3_user_select_policy.test.js
venue_crowd.test.js feat(career): badge ceremony — the crowd erupts, the stamp drops (#941) 2026-07-13 15:07:28 +02:00
venue_instrument_pov.test.js
venue_mood_fx.test.js
venue_scene_3d.test.js fix(venue/highway): flyover replay on arrangement switch, venue on Virtuoso, and the paused throttle starving the venue (#968) 2026-07-14 22:11:52 +02:00
venue_scope.test.js fix(venue): fly in once per set, not before every song (#978) 2026-07-15 12:39:25 +02:00
venue_viz.test.js refactor(app): carve the viz layer out of app.js — and delete the loader seam (R3a) (#880) 2026-07-11 18:41:52 +02:00
visualization_domain.test.js
window_contract.test.js refactor(app): make app.js's window contract explicit — 66 names (R3a) (#874) 2026-07-11 17:09:18 +02:00
working_tuning_capability.test.js feat(core): working-tuning lifecycle — launch default, verified decay, idempotent re-injection + tests (working-tuning PR 9a) (#669) 2026-07-01 11:07:58 +02:00
working_tuning.test.js settings: add host instrument profiles (#753) 2026-07-05 00:16:42 +02:00