feedBack/tests/js
Byron Gamatos cb236e6c04
refactor(app): carve the A–B loop out of app.js (R3a) (#888)
static/js/loops.js (261) — bodies VERBATIM. app.js 8,421 → 8,224.
The second slice out of the strongly-connected core.

It OWNS the loop state — loopA, loopB, _loopMutationGen. Nothing outside writes
them: restartCurrentSong() looked like it did, but it declares its own local `let
loopA/loopB` shadows, so the module-level bindings only ever change in setLoop /
setLoopStart / setLoopEnd / clearLoop. All four move here. No state container.

DIRECTION IS THE WHOLE DESIGN. loops and section-practice are mutually dependent —
the SCC in miniature. clearLoop() must drop section-practice's selection, and
practiceSection() must call setLoop(). Both edges cannot be imports or no-cycle
(rightly) rejects it. So:

    section-practice  ->  reaches loops through the HOST SEAM (host.setLoop, …)
    loops             ->  imports section-practice DIRECTLY

section-practice is the higher-level feature — a consumer of loops, not the reverse
— so it is the one that takes the indirection. app.js hands the loop module's
exports across into the seam for it. Graph stays acyclic; no-cycle passes.

THE CONTRACT TEST EARNED ITS KEEP IMMEDIATELY. It failed on the first build with
"these hooks are wired by app.js but no module reads them: playSong". My dependency
scan had counted a mention of playSong() inside a COMMENT in loops.js as a real
call. Wired but unused is precisely the "fossil of a rename" case the test exists
for — and it caught it on a path no test executes.

VERIFIED BY DRIVING BOTH SIDES OF THE SEAM. A/B against origin/main in two browsers,
real song loaded:
  * setLoop(5,12) -> true; getLoop() -> 5,12 — IDENTICAL
  * clearLoop() (loops -> section-practice, a direct import) -> getLoop() ->
    null,null — IDENTICAL
  * onPhraseNext() (section-practice -> loops, ACROSS THE SEAM) -> ok — IDENTICAL
  * loadSavedLoop / saveCurrentLoop / deleteSelectedLoop on window — IDENTICAL
  * zero page errors either side. An unwired hook throws, so a live app is itself
    proof the seam is wired.

Harness: loop_api extracts the loop helpers by signature — retargeted to loops.js,
`export` stripped for the vm sandbox, and the sandbox's existing _audioSeek /
_audioTime / formatTime spies are now routed through a `host` object so every
assertion holds unchanged, just through the indirection the real code uses. It is
SPLIT: one test still reads app.js for the window.feedBack API surface, which stayed.

pytest 2396, node 1040/1040, ESLint 0 (no-cycle clean), tailwind clean.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 21:32:31 +02: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 Clean release snapshot 2026-06-16 18:47:13 +02:00
audio_effects_host.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_effects_test_harness.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_element_accessor.test.js Clean release snapshot 2026-06-16 18:47:13 +02:00
audio_session_compat.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_host.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_input.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_mix.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_monitoring.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_routes.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_stems_bridge.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_stems.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio_session_test_harness.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
autoplay_exit.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_diagnostics.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_lifecycle.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_manifest_runtime.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_multi_provider.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_ownership.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_test_harness.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capabilities_versioning.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
diagnostics_summary.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
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 fix(library): Edit Metadata modal — editable Year + don't close on drag-release outside (#623) 2026-06-28 13:42:02 +02:00
editor_pending_view.test.js feat(player): seed editor region handoff state (#762) 2026-07-05 23:37:39 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
highway_3d_camera_framing.test.js fix(highway_3d): dolly back so the fret-number row can't clip off the bottom (#633) 2026-06-29 15:31:24 +02:00
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 Clean release snapshot 2026-06-16 18:47:13 +02:00
highway_3d_fret_row_labels.test.js Clean release snapshot 2026-06-16 18:47:13 +02:00
highway_3d_fret_spacing.test.js fix(highway): apply 3D fret-spacing live instead of reloading (#561) (#562) 2026-06-22 12:08:22 +02:00
highway_3d_lean_sustain.test.js Clean release snapshot 2026-06-16 18:47:13 +02:00
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 fix(highway): stop stale viz frame bleeding through after switching visualizations (#565) 2026-06-22 13:27:21 +02:00
highway_3d_panel_controls.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
highway_3d_pool_warm.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
highway_3d_render_order.test.js Clean release snapshot 2026-06-16 18:47:13 +02: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 Clean release snapshot 2026-06-16 18:47:13 +02:00
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 Clean release snapshot 2026-06-16 18:47:13 +02:00
highway_3d_sustain_rail.test.js Clean release snapshot 2026-06-16 18:47:13 +02:00
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): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_audio_barrier.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
highway_bend_curve.test.js fix(bend): GP8 short-bend curve loss + 2D curve timing + 3D bnv gating (#535) 2026-06-21 00:46:36 +02:00
highway_chord_harmony.test.js feat(highway): render caged + guideTones teaching labels (§6.6) (#545) 2026-06-21 11:58:00 +02:00
highway_chord_render_cache.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_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): lift 79 per-instance closure vars into hwState (R3c H lift) (#849) 2026-07-10 23:19:20 +02:00
highway_note_state.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_pause_throttle.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_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(app): carve the highway string-colours out of app.js (R3a) (#883) 2026-07-11 19:22:14 +02:00
highway_teaching_marks.test.js feat(highway): render teaching marks fg/ch/sd on 2D + 3D (§6.2.2) (#538) 2026-06-21 07:58:04 +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 feat(audio): route feedpak full-mix natively under exclusive output (#824) 2026-07-09 22:18:00 +02:00
legacy_shim_hits.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
library_card_actions.test.js Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
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): reset live performance HUD on backward seek / restart (#607) 2026-06-27 00:47:43 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
midi_input_domain.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
note_detection_domain.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
pedal_cables.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
play_button_reroute_guard.test.js fix(player): keep play/pause button in sync when a JUCE reroute aborts autoplay's play() (#611) 2026-06-27 13:16:28 +02:00
play_queue_peek.test.js play-queue: peekNext() — expose the following track for queue-aware UIs (#719) 2026-07-02 20:50:56 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
playback_compat.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
playback_diagnostics.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
playback_domain.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
playback_test_harness.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
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 refactor(app): carve the plugin loader out of app.js into static/js/ (R3a) (#878) 2026-07-11 18:18:00 +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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
progress_calibration.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
progression_notifications.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
progression_progress_events.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
renderer_bus_feeder.test.js feat(audio): loopback feeder mode + static no-cache — all app audio under exclusive/ASIO (#877) 2026-07-11 18:22:25 +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 Clean release snapshot 2026-06-16 18:47:13 +02:00
song_close.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
song_credits_overlay.test.js feat(highway): show feedpak author/editor credits on song load (#629) 2026-06-28 22:08:44 +02:00
song_event_payload.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
song_restart.test.js refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
song_seek.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
speed_reset.test.js feat(tuner): gate playback until you've tuned — hold autoplay + no-trap Skip/Back/Esc (working-tuning PR 4) (#666) 2026-07-01 11:18:29 +02:00
test_utils.js Clean release snapshot 2026-06-16 18:47:13 +02:00
tour_engine.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
tuner_auto_open.test.js refactor(app): carve the tuning-display helpers out of app.js (R3a) (#884) 2026-07-11 19:37:44 +02:00
tuner_core.test.js Clean release snapshot 2026-06-16 18:47:13 +02:00
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 feat(v3): add "Add to playlist" to a song's ⋮ More menu (#625) 2026-06-28 13:58:14 +02:00
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 feat(library): smart collections as a library provider (#641) 2026-06-29 10:42:41 +02:00
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 fix(v3): refresh Songs grid after a Settings rescan / DLC-folder change (#624) 2026-06-28 13:52:48 +02:00
v3_playlist_cover.test.js feat(v3): content-dependent playlist covers + custom art (#626) 2026-06-28 14:10:15 +02:00
v3_songs_score_badge_refresh.test.js fix(v3): decode stats:recorded filename so post-play score badge refreshes (#620) 2026-06-28 12:39:13 +02:00
v3_songs_scroll.test.js feat(v3): DOM-virtualize the Songs grid (#636 item 3 stage 2) (#643) 2026-06-29 12:26:29 +02:00
v3_songs_tuning.test.js refactor(app): carve the tuning-display helpers out of app.js (R3a) (#884) 2026-07-11 19:37:44 +02: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 fix(v3): reject accidental text-selection of UI chrome (user-select policy) (#637) 2026-06-29 14:44:56 +02:00
venue_instrument_pov.test.js Clean release snapshot 2026-06-16 18:47:13 +02:00
venue_mood_fx.test.js rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
venue_scene_3d.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
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 rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
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