mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-25 14:21:21 +00:00
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>
|
||
|---|---|---|
| .. | ||
| assets/venue/themes/small-club | ||
| capabilities | ||
| js | ||
| lottie | ||
| svg | ||
| v3 | ||
| vendor | ||
| _tailwind.src.css | ||
| app.js | ||
| audio-mixer.js | ||
| capabilities.js | ||
| diagnostics.js | ||
| highway.js | ||
| lottie-api.js | ||
| style.css | ||
| tailwind.min.css | ||
| tour-engine.css | ||
| tour-engine.js | ||