19 declarations + 23 TOP-LEVEL STATEMENTS. 922 lines. app.js 3,243 -> 2,325 (-28%).
The panel registry, both global keydown dispatchers, the library arrow-nav, and the whole
plugin-facing shortcut API.
━━━ MOST OF THIS SUBSYSTEM WAS NOT DECLARATIONS ━━━
A declaration-seeded dependency closure reports this cluster as 10 names, 246 lines.
It is 42 statements and 922.
window.registerShortcut, createShortcutPanel, getAllShortcuts, unregisterShortcut,
clearWindowShortcuts, the panel registry, and BOTH global keydown dispatchers are bare TOP-LEVEL
STATEMENTS at app.js's top level. A call-graph scan sees NONE of them.
That blind spot has now cost three times:
* it nearly shipped a dead library A-Z rail (#896) — 43 of library.js's exports were
referenced only from app.js's window contract;
* it threw "Assignment to constant variable" in the session carve (#921), where the autoplay
gate's top-level statements wrote state that had just become a read-only import;
* and here it under-reported the slice by 3x.
The extractor takes them by construction now — any top-level statement that TOUCHES a moved
binding comes along — and the SEED is closed to a FIXED POINT, because those statements have
their own dependencies (_modifiersMatch, _isShortcutActive, _handleLibArrowNav, _gridColumns…)
that the declaration closure never walked. Seed -> pull the statements -> the statements need
more names -> re-seed. Iterate until it stops growing.
━━━ syncLibrarySong GOES ACROSS THE SEAM, NOT THROUGH AN IMPORT ━━━
The library arrow-nav calls it on Enter. It cannot be imported: syncLibrarySong reaches
showScreen/playSong, and a module importing app.js closes a cycle. It is the ONE name here that
had to stay behind, so it comes across the host seam — which is exactly what the seam is for.
host.js throws loudly if the wiring is ever dropped, and tests/js/host_contract.test.js fails in
CI if the hook drifts.
VERIFIED. A/B against origin/main in two browsers, IDENTICAL, zero page errors — and driven for
real, not merely present: the plugin API (register / unregister / getAll / panels), THE GLOBAL
KEYDOWN DISPATCHER actually firing a registered shortcut, that same shortcut correctly SUPPRESSED
while typing in a text input, and `?` opening the help modal.
node 1045, pytest 2425, ESLint 0 (no-cycle clean), host contract 2/2, Codex 0.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>