mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-11 03:14:29 +00:00
Root cause: const sY was declared 371 lines after createScoreFx({..., sY})
inside createFactory(). The shorthand {sY} reads the binding immediately
(not a closure), so every factory call threw ReferenceError: Cannot access
'sY' before initialization. highway.js caught it, reverted to 2D, emitted
viz:reverted. THREE.js was never requested.
Fix: hoist sY declaration to just before createScoreFx. Also hoist
_invertedCached, nStr, curX, and highwayCanvas above their first lexical
reference (all were closure false positives, but hoisting makes the code
unambiguously safe and keeps the new ESLint gate clean with 0 errors).
Hoist _bcPanel in bc-panel.js for the same reason.
Regression gate: eslint no-use-before-define (variables:true, functions:false)
scoped over plugins/highway_3d/ (screen.js + src/). Statically catches any
const/let used before its declaration in the factory — the whole class, not
just this pair. RED at broken tip (sY flagged): GREEN after fix.
Pre-existing violations surfaced (all closure false positives, none true TDZ
runtime bugs): highwayCanvas in _v3TopRightChromeBottom body, _invertedCached
and nStr in sY arrow body and DI getters, curX in getCurX DI getter, _bcPanel
in bc-panel.js function bodies — all resolved by hoisting; no silenced errors.
Bump plugin.json 3.53.0→3.54.0 (viz factory change per standing rule).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
91 lines
4.5 KiB
JavaScript
91 lines
4.5 KiB
JavaScript
// Flat ESLint config — MAINTAINER / CI ONLY. Never runs on the serve or Docker
|
|
// path (constitution Principle I: dev-only tooling is exempt, same category as
|
|
// scripts/build-tailwind.sh). It enforces the module-migration guardrails:
|
|
//
|
|
// * max-lines — the 1,500-line size norm, as a WARNING ratchet. Legacy
|
|
// monoliths warn (the "this is over the norm, split it" signal) and shrink
|
|
// as the refactor lands; warnings do not fail CI. Genuinely-large files are
|
|
// exempted below, mirroring the signed register in docs/size-exemptions.md.
|
|
// * import-x/no-unresolved + no-cycle — module hygiene, scoped to the real
|
|
// ES-module graphs the refactor produces (a plugin's src/ tree, .mjs
|
|
// tests). no-unresolved (a HARD error) catches broken import paths;
|
|
// no-cycle enforces the downward-only layering rule. Core's classic scripts
|
|
// have no import graph, so both are dormant today and become live gates the
|
|
// moment module code appears — validated against the first real module
|
|
// plugin (R1 pilot).
|
|
|
|
const importX = require('eslint-plugin-import-x');
|
|
|
|
// Per-file size ceilings — a mirror of docs/size-exemptions.md (canonical).
|
|
// Keep in sync; each entry corresponds to a signed row in the register.
|
|
const SIZE_EXEMPTIONS = [
|
|
{ files: ['**/static/capabilities.js'], max: 1600 },
|
|
{ files: ['**/plugins/capability_inspector/screen.js'], max: 100000 },
|
|
{ files: ['**/plugins/folder_library/screen.js'], max: 100000 },
|
|
];
|
|
|
|
const sizeRule = (max) => ['warn', { max, skipBlankLines: false, skipComments: false }];
|
|
|
|
module.exports = [
|
|
{
|
|
ignores: [
|
|
'node_modules/**',
|
|
'static/vendor/**',
|
|
'plugins/**/assets/vendor/**',
|
|
'**/*.min.js',
|
|
'static/tailwind.min.css',
|
|
],
|
|
},
|
|
// Size norm across all first-party JS. Classic scripts are parsed as
|
|
// scripts (no import/export); module files get their own block below.
|
|
{
|
|
files: ['**/*.js', '**/*.cjs'],
|
|
languageOptions: { ecmaVersion: 'latest', sourceType: 'script' },
|
|
rules: { 'max-lines': sizeRule(1500) },
|
|
},
|
|
// ES-module graphs (a plugin's src/ tree, .mjs tests, core's own static/js/
|
|
// tree): module parsing + the acyclic-imports hard gate + the size norm. A
|
|
// migrated bundled plugin's entry `import './src/main.js'` screen.js must
|
|
// parse as a module — add its glob here in that plugin's migration PR
|
|
// (classic screen.js stays a script).
|
|
//
|
|
// `static/app.js` is listed explicitly: it is served as
|
|
// <script type="module"> (R3a) and now `import`s its carved-out modules, so
|
|
// parsing it as a script would be a syntax error. It is the ENTRY of core's
|
|
// module graph, which is what makes no-cycle meaningful here — a carved
|
|
// module that imports app.js back would close a cycle and fail this gate.
|
|
{
|
|
files: ['**/src/**/*.js', '**/*.mjs', 'static/app.js', 'static/js/**/*.js', 'static/highway.js'],
|
|
languageOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
plugins: { 'import-x': importX },
|
|
// v4 flat-config resolver (resolver-next + createNodeResolver). Without
|
|
// it the import rules silently skip imports they can't resolve.
|
|
settings: { 'import-x/resolver-next': [importX.createNodeResolver()] },
|
|
rules: {
|
|
'max-lines': sizeRule(1500),
|
|
'import-x/no-unresolved': 'error',
|
|
'import-x/no-cycle': 'error',
|
|
},
|
|
},
|
|
// highway_3d plugin — screen.js uses ES-module syntax (scriptType:module)
|
|
// so it needs module sourceType to parse. Add no-use-before-define here
|
|
// (variables: true, functions: false) to catch const/let TDZ violations
|
|
// inside factory functions across the whole plugin tree.
|
|
// Proven to flag the broken-tip regression (fix/h3d-viz-init-fallback):
|
|
// broken: const sY used at createScoreFx DI before its declaration → ERROR
|
|
// fixed: sY hoisted above createScoreFx call → clean (0 errors)
|
|
{
|
|
files: [
|
|
'plugins/highway_3d/screen.js',
|
|
'plugins/highway_3d/src/**/*.js',
|
|
],
|
|
languageOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
rules: {
|
|
'no-use-before-define': ['error', { variables: true, functions: false }],
|
|
},
|
|
},
|
|
// Signed size exemptions (docs/size-exemptions.md) — raise the ceiling so
|
|
// registered files don't warn below it.
|
|
...SIZE_EXEMPTIONS.map(({ files, max }) => ({ files, rules: { 'max-lines': sizeRule(max) } })),
|
|
];
|