Go to file
Byron Gamatos c6963fdf30
refactor(highway): flip highway.js to an ES module (R3c) (#913)
Two lines. index.html: defer -> type="module". highway.js: one explicit assignment.
highway.js can now `import`, which is the whole point — the carve can begin.

━━━ THE ONE THING THE FLIP ACTUALLY BREAKS: window.createHighway ━━━

A top-level `function createHighway()` in a CLASSIC script IMPLICITLY becomes
window.createHighway. In a module it does not — module declarations are module-scoped, and
the name vanishes from the global object the instant the tag grows type="module".

The constitution names window.createHighway as PUBLIC EXTENSION CONTRACT (alongside
window.playSong / showScreen / feedBack). NOTHING IN-TREE CALLS IT. That is exactly why this
would have shipped: the only consumers are third-party plugins rendering their own highway
panel, and I cannot grep those. Green CI, green tests, and a broken plugin API.

Verified by removing the assignment and reloading:

    flip WITHOUT an explicit assignment:  window.createHighway === undefined   <-- gone
    flip WITH it:                         window.createHighway === function

So it is assigned explicitly now — same object, same behaviour, no longer an accident of how
the file happens to be loaded.

━━━ AND A CORRECTION TO #912 ━━━

#912 (merged) rewrote 73 bare `highway.x` -> `window.highway.x` on the stated grounds that
the flip would turn every one of them into a ReferenceError. HAVING NOW ACTUALLY FLIPPED IT,
THAT WAS WRONG. highway.js already did `window.highway = highway`, which puts the name on the
GLOBAL OBJECT — and bare-identifier resolution falls back to the global object whether or not
a lexical global binding exists. Measured on both builds: bare `highway` resolves either way.

#912 is defensible as hygiene and it does not hurt, but it was not a precondition and it fixed
no latent bug. A correction is posted on the PR so its commit message does not mislead. The
real hazard was the factory, not the instance — same class of breakage, wrong name.

ORDERING is unchanged: classic-defer and non-async type="module" share ONE post-parse
execution queue, in document order, so highway.js keeps its position at index.html:1244.

VERIFIED. A/B against origin/main: 15 probes IDENTICAL, zero page errors — window.highway,
window.createHighway, the full API surface, a real song playing, the chart clock advancing,
and the seek->setTime sync. THE PERF GATE PASSES at 1.85ms against its 12ms budget (module
evaluation costs nothing at render time), which is exactly what #910 was built to tell me.

node 1045, pytest 2416, ESLint 0, Codex 0.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 12:07:28 +02:00
.claude/skills Clean release snapshot 2026-06-16 18:47:13 +02:00
.github R0: module-migration rails (src/ serving, live-edit cache, scriptType loading, governance) (#812) 2026-07-08 10:14:40 +02:00
.specify refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
content/starter Delete content/starter/beethoven-ode_to_joy.feedpak 2026-07-03 23:42:45 +02:00
data/progression Clean release snapshot 2026-06-16 18:47:13 +02:00
docs refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
lib fix(demo): the janitor re-entry guard actually works now (#902) (#909) 2026-07-12 11:30:53 +02:00
plugins fix(plugins): make a module plugin actually re-evaluate on reload (#879) (#897) 2026-07-12 00:19:59 +02:00
scripts perf(harness): add 2D-highway frame-time measurement + capture the R3c gate (H0) (#848) 2026-07-10 23:15:07 +02:00
specs rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
static refactor(highway): flip highway.js to an ES module (R3c) (#913) 2026-07-12 12:07:28 +02:00
tests refactor(highway): make the highway global explicit before the module flip (R3c) (#912) 2026-07-12 11:56:07 +02:00
.dockerignore fix(build): move appstate.py + routers/ under lib/ so the desktop app ships them (#836) 2026-07-10 17:16:34 +02:00
.gitattributes Purge external-format terminology from code, tests and docs 2026-06-16 19:36:53 +01:00
.gitignore Bundle drum_highway_3d + keys_highway_3d as in-tree core plugins (#693) 2026-07-02 00:25:31 +02:00
build-proxmox-ct.sh rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
CHANGELOG.md refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
CLAUDE.md refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
CONTRIBUTING.md rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
docker-compose.nas.yml rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
docker-compose.yml fix(build): move appstate.py + routers/ under lib/ so the desktop app ships them (#836) 2026-07-10 17:16:34 +02:00
Dockerfile fix(build): move appstate.py + routers/ under lib/ so the desktop app ships them (#836) 2026-07-10 17:16:34 +02:00
eslint.config.js refactor(app): carve the plugin loader out of app.js into static/js/ (R3a) (#878) 2026-07-11 18:18:00 +02:00
LICENSE Clean release snapshot 2026-06-16 18:47:13 +02:00
main.py rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
package-lock.json R0: module-migration rails (src/ serving, live-edit cache, scriptType loading, governance) (#812) 2026-07-08 10:14:40 +02:00
package.json R0: module-migration rails (src/ serving, live-edit cache, scriptType loading, governance) (#812) 2026-07-08 10:14:40 +02:00
playwright.config.ts Clean release snapshot 2026-06-16 18:47:13 +02:00
pyproject.toml Clean release snapshot 2026-06-16 18:47:13 +02:00
requirements-test.txt Clean release snapshot 2026-06-16 18:47:13 +02:00
requirements.txt Make the library loader sloppak/loose-only 2026-06-16 19:09:53 +01:00
server.py fix(demo): the janitor re-entry guard actually works now (#902) (#909) 2026-07-12 11:30:53 +02:00
SUPPORTERS.md rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
tailwind.config.js refactor(ui)!: remove the classic v2 shell — v3 is the only UI (R3a) (#871) 2026-07-11 16:33:03 +02:00
TODO.md docs: correct plugin URL casing after the feedBack rename (#576) 2026-06-23 11:20:23 +02:00
uv.lock Clean release snapshot 2026-06-16 18:47:13 +02:00
VERSION Bump version to 0.3.0-alpha.1 2026-07-03 13:41:50 +02:00