build: #119 add Biome formatter and improve ESLint#132
Open
ryancraigdavis wants to merge 1 commit into
Open
Conversation
Add Biome for consistent code formatting, decoupled from ESLint so correctness and style concerns don't overlap. Add lint:fix, format, and format:check npm scripts. Rework eslint.config.js to layer: - js.recommended for base JS correctness (previously missing, so bugs like no-undef/no-unused-vars in plain JS went unchecked) - eslint-config-next for React/hooks/a11y coverage - eslint-plugin-import-x for import correctness, using a node resolver instead of Next's bundled import plugin, which crashes under ESLint 9 flat config due to a broken TypeScript resolver - eslint-config-prettier last, to disable stylistic rules now owned by Biome Bump CI Node.js version to 26 to match engines requirement.
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Harden ESLint + add Biome (formatter-only)
Branch:
feature/119-hardened-eslint-rules-and-biome-for-formatting→developRepo: Redux_GUI
This PR is plumbing to support future quality gates. It does not turn any gate on, and it does
not reformat any code.
continue-on-error: true). Nothing in thisPR can fail a build or block a merge. Flipping to blocking is a deliberate, separate decision.
biome.jsonis added, butnpm run formatwas notexecuted — zero source files are reformatted in this PR. The repo-wide format sweep is a
separate, isolated commit for later, kept out of here on purpose so this change stays reviewable.
lockfile. App behavior is unchanged (verified — see Verification).
In short: this PR makes the linter useful and honest, and stages the formatter, without
enforcing anything yet. It lets us see what the tools would catch before we commit to gates.
Why
The GUI's ESLint setup was a two-line passthrough of
eslint-config-next/core-web-vitals, run inCI with
continue-on-error: true. Two problems:next/core-web-vitalslayers React/Next/a11y ruleson top of nothing — it does not include ESLint's base
recommendedset. So every coreJavaScript correctness rule was off:
no-undef,no-unused-vars,no-dupe-keys,no-unreachable,use-isnan, etc. The plain-JS bug class went completely unchecked. Thismatters more here than in most repos because the GUI has no test suite at all — ESLint is
the only automated quality gate.
continue-on-error, the linter could report errors and CIstayed green regardless.
This PR fixes (1) and stages the tooling to fix (2) later.
What changed
eslint.config.jsbiome.jsonlinter.enabled: false)package.jsonlint:fix,format,format:checkscripts + 3 devDependenciespackage-lock.json.github/workflows/code-analysis.yml22 → 26(aligns with build/engines)New devDependencies (all dev-only):
@biomejs/biome,eslint-config-prettier,eslint-plugin-import-x.eslint.config.js— the layeringnode_modules,.next,out,build,public(the vendored Q.js library +static assets — must not be linted),
next-env.d.ts.@eslint/jsrecommended — the previously-missing base-correctness floor.next/core-web-vitals— the existing React / hooks / a11y /@nextcoverage + globals.eslint-plugin-import-x— import correctness (import-x/named,import-x/no-unresolved)with a node resolver (correct for a pure-JS repo). See the note below on why import-x and
not Next's bundled import plugin.
no-unused-varsset towarn(there's a backlog; keep it visible, not awall of blocking errors while we're non-blocking anyway).
eslint-config-prettier(last) — turns off stylistic rules so ESLint and the Biomeformatter never fight. ESLint owns correctness; Biome owns formatting. No overlap.
Why import-x instead of Next's bundled
eslint-plugin-import: Next ships a vendoredeslint-plugin-importwhose default resolver is a TypeScript resolver. Under ESLint 9 flat configthat resolver loads with an "invalid interface" and crashes the entire lint run the moment a
resolver-dependent rule hits a file that imports a package. Overriding the resolver setting doesn't
help (ESLint deep-merges
settings, so the brokentypescriptresolver can't be removed byomission).
eslint-plugin-import-xis the maintained, flat-config-native fork; we register it underits own
import-x/*namespace with a node-only resolver and leave Next's rules untouched. This isdev-time only — Next 16's
next builddoes not run ESLint, so none of it can affect the buildor deploy.
biome.json— formatter onlyformatter.enabled: true(2-space, double quotes, semicolons,lineWidth100) — matched to theexisting code style.
linter.enabled: false— Biome does not lint. ESLint remains the linter. Therecommendedruleset is pre-wired but disabled, so adopting Biome's linter later (a separate,much-later decision) is a one-key flip.
assist.actions.source.organizeImports).public/**andpackage-lock.jsonso a future sweep can never touch vendored orgenerated files.
What this fixes / enables
Real bugs surfaced immediately (reported, not enforced — nothing blocks):
borderno-dupe-keyscomponents/Visualization/svgs/SSSPTableSvgReact.js:96requestIsCertificateValiddoesn't exist in../reduximport-x/namedcomponents/pageblocks/VerifyRowReact.js:17Typographdoesn't exist in@mui/materialimport-x/namedpages/index.js:25no-emptyThe two dead imports are notable: they're imported and referenced, so
no-unused-varscannotcatch them — only import resolution does. These are exactly the class of latent bug the old config
was blind to.
Also fixed / aligned:
enginesrequire 26.Foundation laid for future gates (explicitly out of scope for this PR):
warn → erroron chosen rules + dropcontinue-on-error.format:checkin CI.Findings overview
npm run lintnow reports 106 findings — 37 errors, 69 warnings. None block (CI isreport-only). Breakdown:
no-unused-varsreact-hooks/set-state-in-effectreact-hooks/immutabilityimport-x/namedno-dupe-keysno-emptyreact-hooks/exhaustive-depsreact/jsx-no-duplicate-propsThe 34
react-hooks/*errors are pre-existing (they come fromnext/core-web-vitalsand werealready reported by the old config — just ignored by
continue-on-error). This PR neither adds norfixes them; it leaves severity as-is. Whether/when to fix or downgrade them is a follow-up.
Verification
The GUI has no automated tests (no test files, framework, config, or script — confirmed). So
verification was: dependency integrity, a production build, and a live end-to-end smoke test.
npm install --dry-run→ "up to date").next build→ exit 0, all 7 routes prerendered).crashing ESLint config on disk. Next 16 removed lint-during-build.
/renders (HTTP 200) with all five rows;/aboutusrenders (200).info(SAT3)→3SAT;solve(SAT3)→(x1:True,x2:True,x3:False);reduce(SAT3→CLIQUE)→ real CLIQUE instance;visualize(CLIQUE)→ frames.Conclusion: the tooling changes are inert to the running app; Redux behaves identically.
How to try it (Node 26)
Follow-ups (out of scope — do not expect them here)
error, removecontinue-on-error,add
format:checkto CI) — pending sign-off on gates.pre-existing
react-hooks/*errors.