chore(lint): fail lint on warnings (--max-warnings 0)

`lint` failed only on errors, so a warn-level rule was a channel nothing
consumed. `react-hooks/exhaustive-deps` reported two stale-closure
`useCallback` deps in App.tsx on every run, `npm run ci` passed anyway,
and the defect was caught only by a review round on #2076.

Add `--max-warnings 0` to all six lint scopes — each of
clients/{web,cli,tui,launcher}'s `eslint .`, plus the root's `lint:core`
and `lint:shared` — so a warning fails `lint`, and therefore `validate`
and `ci`. All six were already warning-free, so no suppressions, rule
downgrades, or ignore-list widening were needed.

Also promote `react-hooks/exhaustive-deps` to `error` in both React
scopes (web, tui). The flag makes severity irrelevant to the gate; it
does not make it read correctly in an editor.

Document the invariant in AGENTS.md as a new "Lint has no warning tier"
section, note it in the README beside the type-aware-linting paragraph,
and mirror it into .github/copilot-instructions.md.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-23 10:47:29 -04:00
commit 99a194ca69
6 changed files with 30 additions and 7 deletions

View file

@ -27,7 +27,7 @@
"test:cli-headers": "vitest run headers.test.ts",
"test:cli-metadata": "vitest run metadata.test.ts",
"pretest": "npm run test-servers:build && npm run build",
"lint": "eslint .",
"lint": "eslint . --max-warnings 0",
"format": "prettier --write src __tests__ \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\"",
"format:check": "prettier --check src __tests__ \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\""
},

View file

@ -14,7 +14,7 @@
"scripts": {
"build": "tsc",
"postbuild": "node scripts/make-executable.js",
"lint": "eslint .",
"lint": "eslint . --max-warnings 0",
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json",
"format": "prettier --write src __tests__ scripts \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\"",
"format:check": "prettier --check src __tests__ scripts \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\"",

View file

@ -27,7 +27,8 @@ export default defineConfig([
},
rules: {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
// `error`, not `warn` — see the web config (#2085).
"react-hooks/exhaustive-deps": "error",
},
},
{

View file

@ -22,7 +22,7 @@
"validate": "npm run format:check && npm run lint && npm run typecheck && npm run build && npm run test",
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"lint": "eslint .",
"lint": "eslint . --max-warnings 0",
"format": "prettier --write src __tests__ \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\"",
"format:check": "prettier --check src __tests__ \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\""
},

View file

@ -27,6 +27,14 @@ export default defineConfig([
ecmaVersion: 2020,
globals: globals.browser,
},
rules: {
// Promoted from the recommended set's `warn` (#2085). A stale-closure
// defect was reported correctly on every run and still reached review,
// because `lint` fails only on errors. `--max-warnings 0` now fails the
// gate either way; this makes the severity read correctly in an editor
// too, rather than depending on a CLI flag.
"react-hooks/exhaustive-deps": "error",
},
},
{
// Test setup files re-export utilities and mix components with helpers — the

View file

@ -25,7 +25,7 @@
"test:integration": "npm run test-servers:build && vitest run --project=integration",
"test:integration:watch": "npm run test-servers:build && vitest --project=integration",
"test-servers:build": "tsc -p ../../test-servers --noCheck",
"lint": "eslint .",
"lint": "eslint . --max-warnings 0",
"format": "prettier --write src server .storybook \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\"",
"format:check": "prettier --check src server .storybook \"*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}\"",
"preview": "vite preview",