ESLint + Prettier
The frontend has a lint/format gate: npm run lint, npm run lint:fix, npm run format,
npm run format:check. npm run build (TypeScript check + Vite build) and npm test
remain the other two gates. All four should pass before shipping a frontend change.
Running it #
npm run lint # eslint . — 0 errors required, warnings are OK for now
npm run lint:fix # eslint . --fix — apply auto-fixes
npm run format # prettier --write . — reformat everything
npm run format:check # prettier --check . — CI-safe, no writes
Flat-config rationale #
eslint.config.js is ESM (the package is "type": "module"), composed in this order:
js.configs.recommended— core ESLint correctness rules.tseslint.configs.recommended(typescript-eslint v8) — notrecommendedTypeChecked. Type-aware linting needsparserOptions.projectwiring, andtsconfig.jsonexcludes test files (tsconfig.json→exclude), which would break typed linting on the test suite. This config is fast and needs no project wiring — pragmatic for standing up the gate today. See "Future upgrade" below.eslint-plugin-react-hooks's flatrecommendedconfig.eslint-plugin-react-refresh'svitepreset (Vite HMR hygiene, warn-level).eslint-config-prettier— last, disables every stylistic rule that would fight Prettier.- Global
ignores:dist/,coverage/,node_modules/,src-tauri/,src/core/graphql/generated/,sdk/plugin-sdk/src/generated/and*.config.js.
.prettierrc.json matches the codebase's existing conventions (verified against the
code, not assumed): double quotes, semicolons, trailing commas, 100-column width.
The warn-vs-error split, and why #
Goal: a green gate today, with room to tighten later — not eslint-disable sprinkled
everywhere to force a pass.
Kept at error (correctness, low false-positive rate):
react-hooks/rules-of-hooks— a real violation is always a bug.- The rest of
js.configs.recommended/tseslint.configs.recommendedthat weren't explicitly downgraded below (e.g.no-control-regex,no-useless-assignment,preserve-caught-error,no-constant-binary-expression,no-useless-escape) — the 9 violations these produced on first run were all real, easy fixes (hand-fixed rather than downgraded, since there were only a handful).
Downgraded to warn (noisy, or would need broad manual edits to reach zero):
@typescript-eslint/no-unused-vars—{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, matching the existing_pluginId-style convention.@typescript-eslint/no-explicit-any.react-hooks/exhaustive-deps.react-refresh/only-export-components.- The
react-hooksv7 "React Compiler readiness" rule set —static-components,use-memo,void-use-memo,preserve-manual-memoization,incompatible-library,immutability,globals,refs,set-state-in-effect,error-boundaries,purity,set-state-in-render,unsupported-syntax,config,gating. This is a deviation from the original spec, which anticipatedeslint-plugin-react-hooksshipping just the two legacy rules (rules-of-hooks,exhaustive-deps). The installed version (7.1.1) bundles the full React Compiler static-analysis rule set underrecommended, most of it aterror. The codebase predates these rules and fixing every violation (dozens, across effect/ref/memoization patterns) is out of scope for standing up the lint gate — downgraded towarnso the gate is green today. Flagged to Vision as a deviation; worth a dedicated pass later if the team wants React Compiler compatibility.
Two intentional control-character regexes (turnBudget.ts, generator.ts — used to
strip control chars from user-facing strings) keep no-control-regex at error and
carry a scoped eslint-disable-next-line with justification, since disabling the rule
project-wide would remove a real correctness check for accidental control chars
elsewhere.
No type-aware linting yet #
tseslint.configs.recommendedTypeChecked would catch more (e.g. unsafe any flows,
floating promises) but requires parserOptions.project pointing at a tsconfig.json
that includes the files being linted — including tests, which the current
tsconfig.json excludes. To upgrade:
- Either widen
tsconfig.json'sinclude/remove the test exclusions, or add a second tsconfig (e.g.tsconfig.eslint.json) that includes tests, referenced only fromeslint.config.js. - Swap
tseslint.configs.recommendedfortseslint.configs.recommendedTypeCheckedand addlanguageOptions.parserOptions.project. - Expect a new round of violations; triage warn-vs-error again per the same "green gate first" principle.
CI #
Lint and format are not yet wired into CI — only npm run build runs today. Frontend
CI should run, in order: npm ci → npm run lint → npm run format:check →
npm run build → npm test. This is a CI-workflow change, out of scope for this
change (owned separately).