fix(staffml): restore working eslint config and fix errors it surfaces - #1981
Conversation
interviews/staffml/package.json pinned eslint to 10.4.0 (bumped from 9.39.4), but eslint-config-next 16.2.6's nested eslint-plugin-react only supports eslint through ^9.7. Running `npm run lint` crashed outright with "TypeError: contextOrFilename.getFilename is not a function" instead of reporting lint results. CI never caught this since staffml-validate-dev.yml does not run a lint step, so this went unnoticed for anyone who bumped ESLint but never ran lint locally. Pinned eslint back to 9.39.5 (latest 9.x, already resolved as the nested peer dependency version). With lint actually running, it surfaced three real errors: - lib/hooks/useFullQuestion.ts: summaryRef.current was written directly in the render body. Moved the sync into a useLayoutEffect, which still runs before the fetch effect on the same commit (so the ref is current when read) without mutating a ref mid-render. - lib/plans.ts, lib/progress.ts: require() calls for sibling modules that have no circular dependency on the caller, so they were unnecessary and swallowed by an unrelated try/catch in plans.ts. Replaced with static imports.
|
🎉 Thanks for contributing to StaffML! We appreciate you sharing your knowledge. A maintainer will review the math and logic shortly. P.S. If you haven't already, please drop a ⭐ on the repository! |
|
Without lint actually running, this repo had zero automated defense against this whole class of bug for as long as the eslint config stayed broken, since CI doesn't run lint either. It's not about style nitpicks here, it's the only check in the whole pipeline built to catch unsafe patterns like ref-mutation-during-render before a user hits the specific timing that turns it into a real, visible bug. eslint is important :) |
|
Thanks @Shashank-Tripathi-07! 🎉 I added @Shashank-Tripathi-07 to staffml for: bug, code, test, tool. The contributor tables are now handled directly by this workflow; no follow-up command is needed. |
Summary
Ran a full audit of StaffML (
interviews/staffml): installed deps, rantsc,eslint,vitest, launched the dev server, and drove it end to end with Playwright across all pages. This PR is the first fix that audit turned up.Problem
interviews/staffml/package.jsonpinseslintto10.4.0(bumped from9.39.4in a prior dependency-bump commit).eslint-config-next@16.2.6pulls in its own nestedeslint-plugin-react@7.37.5, whose peer range only reacheseslint@^9.7(confirmed vianpm view eslint-plugin-react peerDependencies). Runningnpm run lintcrashes outright:CI never caught this because
staffml-validate-dev.ymldoes not run a lint step, sonpm run linthas apparently been broken for any contributor since that bump landed.Fix
eslintback to9.39.5(latest 9.x; also the version npm was already resolving as the nested peer dependency duringnpm ci, per theERESOLVEwarnings).lib/hooks/useFullQuestion.ts:summaryRef.current = summarywas written directly in the render body, which thereact-hooks/refsrule (part ofeslint-config-next16's hook-purity rules) flags as unsafe — writing to a ref during render can leave stale values behind an interrupted or Strict-Mode-double-invoked render. Moved the sync into auseLayoutEffect, which still runs before the fetch effect on the same commit (so the ref is current when read) without mutating a ref mid-render.lib/plans.ts,lib/progress.ts: both had arequire()call reaching into a sibling module (./progress,./corpus) that has no circular dependency on the caller — confirmed neithercorpus.tsnorprogress.tsimports back intoplans.ts. Theplans.tsone was also silently swallowed by an unrelatedtry/catch, meaning any failure there would leavetodayCompletedat 0 with no signal. Replaced both with static top-level imports.Verification
npx eslint .— was crashing (TypeError, exit 2); now runs clean at 0 errors (94 pre-existing style warnings remain, out of scope here).npx tsc --noEmit— clean, no new type errors.npx vitest run— 24 test files / 131 tests, all passing.npm run build— production static export succeeds, all 15 routes prerendered.