test 11 now extracts the real nutColor from screen.js via regex and
pins it against a literal ('#f5f3f0'). Three-layer guard:
1. guard: BG_DEFAULTS literal is present in screen.js
2. guard: nutColor key is extractable
3. literal-pin: extracted value == '#f5f3f0' → fail loudly if
production drifts (verified: mutating screen.js to '#deadf5'
makes the test fail on the pin assertion; revert confirmed clean)
Fixture and fallback assertion both use PROD_NUT_COLOR (the extracted
value), so they track production automatically.
panel_controls stub updated: added _applyBloom to the createFx stub
(Toby r1 added _applyBloom to the return set; stub was one short).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
Move longestConsecutiveRun, drawChordDiagram, _drawDiagramCached,
drawSectionHud, drawToneHud, drawLyrics out of screen.js IIFE into
plugins/highway_3d/src/overlay.js as export function createOverlay({ diagRenderCache }).
Surprises vs approved contract:
• longestConsecutiveRun (lines 4338–4352) co-moved — called only by drawChordDiagram
• DIAG_SIZE_MIN, DIAG_SIZE_MAX, DIAG_CELL_MAX DELETED from screen.js (lines 573–575);
only users were inside the O-section; moved not copied to avoid drift
• _DIAG_CACHE_MAX DELETED from screen.js factory scope (line 3256); moved not copied
Beyond-subst rewires (2):
1. Factory wrapper createOverlay({ diagRenderCache })
2. _diagRenderCache → diagRenderCache (DI param) in 3 sites in _drawDiagramCached
Base run stated: 253/253 on a993d2b
Post-cut: 262/262 (+9 tests — 8 overlay class-killers + 1 panel-controls stub)
Named mutations verified RED:
• createOverlay({ diagRenderCache: new Map() }) → test 6 RED (ref-severance)
• void _DIAG_CACHE_MAX in screen.js → test 4 RED (bare private)
plugin.json: 3.42.0 → 3.43.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
Extracted _pc* subsystem (420 lines) from screen.js IIFE into
src/bg-control.js using a factory DI pattern (createBgControl({...})).
Exports: createBgControl({ BG_STYLE_IDS, _bgReadGlobal, _bgSubscribe,
_bgUnsubscribe, getVenueSceneOverride })
→ { _pcAcquire, _pcRelease }
screen.js: const { _pcAcquire, _pcRelease } = createBgControl({...})
Beyond-subst (2):
1. Factory wrapper (IIFE-scope closure → DI params) — factory export pattern
required because DI values are IIFE-scope, not ES module imports.
2. _venueSceneOverride → getVenueSceneOverride() (live accessor, 1 call site
in _pcSync — mutable let at screen.js:1523 must be read per-call).
DI values all defined before the createBgControl call (screen.js):
- BG_STYLE_IDS: line 1435 | _bgReadGlobal: 1825
- _bgSubscribe/_bgUnsubscribe: 1917-18 | _venueSceneOverride: 1523
First _pcAcquire caller: init() in createFactory() (~line 14850 post-cut).
Construction order correct: createBgControl call before createFactory.
Surprise declared to god before commit (outbox/h3d-cut5-surprise.json):
No bc-panel.js dependency — §8's anticipation was wrong. The
_bcCreateController call at what was ~line 8082 is in _bcSyncMode
(P-section / factory scope), not the H-section. bg-control.js has ZERO
dependency on bc-panel.js.
Tests:
- tests/js/highway_3d_bg_control.test.js (new, 13 class-killers):
stranded-caller (test 13, factory-adapted from bc-panel test 12),
construction-order (tests 11-12), DI completeness (test 2),
live-accessor enforcement (test 3), lifecycle (tests 4-7).
- plugins/highway_3d/tests/background_control.test.js: retargeted from
screen.js slice → bg-control.js factory eval; all 20 existing behaviour
tests preserved (load() uses vm.createContext + augmented return getters).
- tests/js/highway_3d_panel_controls.test.js: createBgControl stub added.
Suite: node --test tests/js/highway_3d*.test.js plugins/highway_3d/tests/*.test.js
base 222/222 (f69c544) → tip 235/235 (+13: 13 new class-killers)
plugin.json: 3.40.0 → 3.41.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
Move all _bc* constants, mutable state, and functions (~670 lines) from
screen.js B-section (lines 27-695) to src/bc-panel.js.
Public API: _bcCreateController, _bcIsDesktop (2 named exports).
window.h3dBcApplySettings assigned at bc-panel.js module scope (1
beyond-subst; body verbatim — scope moves from IIFE to ES module top-level).
THREE_URL / THREE_CDN dead-code tombstoned (unused since three-loader.js).
Vendor files untouched (R2); asset URL constants verbatim (R3).
Delta note: original survey estimated ~1,333 lines for B-section. Actual is
~670 because (a) prior cuts 1b/2/3 moved material that was interleaved in the
B-section range, and (b) the original survey section boundaries were wrong —
the B-section ends where the H-section factory begins, not at line 695 of the
pre-cut file.
Completeness grep (post-cut):
grep -nP '^\s*(function|const|let|var)\s+_bc' screen.js
→ 2 hits: _bcActive and _bcSyncMode at line 8081-8082 (factory-scope
H/P-section helpers that orchestrate the imported controller; not B-section
symbols — confirmed F-section in the survey table).
B-section _bc* definitions in IIFE: 0.
Suite: node --test tests/js/highway_3d*.test.js plugins/highway_3d/tests/*.test.js
tests 221 pass 221 fail 0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
Moves 12 pure-function / compile-time-constant exports from the screen.js
IIFE into a new src/utils.js ES module:
Color utils: _h3dHexToInt, _clampByteI, _darkenInt, _lightenInt
String-count: resolveStringCount
Tuning/pitch: _NOTE_NAMES_SHARP, _BASE_OPEN_MIDI_BASS4/5, _BASE_OPEN_MIDI_GUITAR6/7/8,
_baseOpenStringMidis, _midiToPitchLabel, _openStringPitchLabelsForTuning
Splitscreen: _ssActive, _ssIsCanvasFocused
Free-identifier audit: all clean. resolveStringCount uses MAX_RENDER_STRINGS
and NSTR — copied as compile-time constants (both = 6) matching IIFE values.
_ssActive/_ssIsCanvasFocused read window.feedBackSplitscreen live per call.
Survey discrepancy declared: the 12 functions span two non-contiguous regions
in current screen.js (lines 741–882 and 1490–1503) rather than the plan's
original 1703–2193 range; function list from the plan is exact.
New test file highway_3d_utils.test.js: 19 class-killer tests.
Mutation-verified (3-char shorthand removal → RED, original → GREEN).
Panel-controls sandbox: 16 stubs added for the new imports.
Suite: node --test tests/js/highway_3d*.test.js plugins/highway_3d/tests/*.test.js
188→207/207 pass.
Plugin: 3.38.0 → 3.39.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
Move the D-section (~21 lines) from screen.js factory scope to its own module.
Exports:
- loadThree() — memoised import() with local-vendor→CDN fallback; same body verbatim
- T (live let-binding) — updated to the Three.js namespace on first resolution
screen.js gains: import { loadThree, T } from './src/three-loader.js'
screen.js loses: let T = null; let threeLoadPromise = null; function loadThree()
T and loadThree remain accessible to the IIFE via module-scope closure. The live
let-binding means the IIFE reads the populated T after loadThree() resolves
without any call-site changes.
Panel-controls vm test: strip regex extended to consume all consecutive import
lines; T: null + loadThree stubs added to sandbox context.
Class-killer tests (8 new — highway_3d_three_loader.test.js):
- loadThree exported (mutation: rename/remove → import fails)
- T exported as mutable let (mutation: const → T=mod throws TypeError)
- T=mod in both .then handlers (mutation: remove both → T stays null)
- memoisation guard !threeLoadPromise (mutation: remove → race + duplicate loads)
- CDN fallback .catch chain (mutation: remove → deploy failures unrecoverable)
- threeLoadPromise reset on failure (mutation: remove → no retry possible)
- screen.js imports loadThree+T (wiring confirmed)
- IIFE no longer declares local T or threeLoadPromise (shadow defeated)
All class-killer mutations confirmed distinguishable before commit.
Base run (5e401af): 180/180 pass.
Post-cut run: 188/188 pass.
Command: node --test tests/js/highway_3d*.test.js plugins/highway_3d/tests/*.test.js
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
Moves 7 exports from screen.js to a new ES module src/geometry.js:
geoFretX (was fretX, now 2-arg), dZ, slideTrailEnd, camBaseDistU,
camLowFretPullbackU, computeBPM, _makeGaussTex.
Internal helpers _fretXLog / _fretXUniStep / _fretXUni are module-private
inside geometry.js. Module-level constants (SCALE, K, FRET_SCALE, NFRETS,
FRET_SPACING_*, TS) are duplicated at geometry.js module scope — values
are compile-time and never vary at runtime.
screen.js keeps a 1-arg delegator (1 beyond-subst):
const fretX = f => geoFretX(f, _h3dFretUniform);
No call site changes; fretMid / fretColumnWorldW / slideOffsetWorldX /
_recomputeFretSpacingDerived stay in screen.js and use the delegator.
Tests:
- highway_3d_geometry.test.js: class-killer via import() with 9
known-answer assertions (geoFretX uniform/log invariants, dZ linearity,
slideTrailEnd, computeBPM BPM estimate).
- highway_3d_fret_spacing: test updated to match delegator pattern + adds
GEOMETRY_JS read to verify geoFretX export.
- highway_3d_sustain_bloom: retargeted _makeGaussTex check to GEOMETRY_JS
(definition moved); call-site check stays on SCREEN_JS.
- highway_3d_panel_controls: vm loader strips ES import line and injects
geometry stubs; all factory-statics tests unaffected.
Suite: 169/169 pass
node --test tests/js/highway_3d*.test.js plugins/highway_3d/tests/*.test.js
Version bump: 3.35.0 -> 3.36.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
* Update GitHub repo references from feedback* to feedBack*
* rename: slopsmith -> feedBack, byron -> got-feedBack
Renames across the entire codebase:
- slopsmith/Slopsmith/SLOPSMITH/SlopSmith -> feedBack/FeedBack/FEEDBACK/FeedBack
- byron/Byron/Byrongamatos -> got-feedBack/got-feedBack/got-feedBack
- /home/byron/ -> /opt/got-feedBack/
- byron@ougsoft.com -> hi@got-feedBack.org
- github.com/byrongamatos/ -> github.com/got-feedback/
- com.byron. -> com.got-feedback.
- SLOPSMITH_ env vars -> FEEDBACK_ with backward-compat fallback
- Protocol/storage strings migrated with read-old/write-new pattern
- window.slopsmith JS API -> window.feedBack (canonical) + backward-compat alias
Refs: #rename-slopsmith
* rename: complete regen against current main + fix backward-compat alias
Regenerated the slopsmith->feedBack / byron->got-feedBack rename on top of
current main (3 commits had landed since the branch: #572/#554/#574),
resolving the four content conflicts in favour of main's newer content
(autoplay/auto-exit, accuracy-badge, Virtuoso re-home, feedpak badge).
Completion fixes on top of the mechanical rename:
- Re-apply rename to post-branch content the original rename never saw:
window.slopsmith(.Tour) consumers in lessons.js / notifications.js /
onboarding-tour.js, and the matching JS + python tests (autoplay_exit,
progression_*, test_feedpak_extension FEEDBACK_* env vars). The test env
vars now match server.py (which reads FEEDBACK_SYNC_STARTUP /
FEEDBACK_SKIP_STARTUP_TASKS), so the sync-startup test exercises the real
path again.
- Restore the window.slopsmith backward-compat alias dropped during conflict
resolution, and move the bus aliases to AFTER the _feedBackExisting merge
block so they reference the fully-assembled object (also fixes the
loop_api.test.js API-surface regex, which the original PR latently broke).
- Drop the stray empty data/web_library.db (runtime DB lives in CONFIG_DIR)
and gitignore it.
- Fix stale tone-source test: feed[dB]ack -> fee[dB]ack to match shipped
source labels.
Verified locally (org CI billing-blocked): JS 819/819 pass; pytest 1669
passed / 1683 collected with 0 import errors; zero residual slopsmith/byron
except the two intentional window.slopsmith aliases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* rename: implement advertised backward-compat + prune dead community plugins
Address gaps where PR #537's "Backward compatibility" section was advertised
but not implemented, and clean up the community plugin list.
Env vars (FEEDBACK_* canonical, legacy SLOPSMITH_* honoured):
- New lib/env_compat.py (getenv_compat / env_flag_compat) + tests. server.py
(_env_flag + all FEEDBACK_* reads), diagnostics_hardware, gp2midi and
tailwind_rebuild now resolve the legacy alias, so existing SLOPSMITH_UI /
SLOPSMITH_PLUGINS_DIR / etc. deployments keep working.
- Fix the rename collapsing plugins/__init__.py and minigames/routes.py from
`FEEDBACK_PLUGINS_DIR or SLOPSMITH_PLUGINS_DIR` into a redundant
`FEEDBACK_ or FEEDBACK_` (the fallback was silently lost).
Storage (app.js update-channel):
- Read feedBack-update-channel, fall back to legacy slopsmith-update-channel,
and clear the legacy key on write — so a user's update-channel preference
survives the rename instead of resetting to "stable".
Community plugin list (README): the rename rewrote third-party repo URLs we
don't own. Probed every one; their owners never renamed, so:
- Restore the 13 live community plugins to their real slopsmith-* names.
- Prune 6 that are 404 to the public (topkoa splitscreen/stems, OmikronApex
tuner, Jafz2001 nam-rig-builder, DeathlySin song-preview, Erikcb91 shuffle).
- Fix a pre-existing Guitar Theory clone-command typo (nam-tone -> guitar-theory).
Verified: env_compat 7/7, JS 819/819, pytest 1690 collected / 0 import errors,
rename-sensitive + startup suites green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: byrongamatos <xasiklas@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>