Downgrade lint-staged 17→16, enable engine-strict#90
Merged
Conversation
lint-staged@17 declares engines: { node: ">=22.22.1" } even though
it runs fine on Node 20. That overly-conservative range blocked us
from enabling `engine-strict=true` (which would have surfaced the
Husky-on-Node-18 crash earlier). v16 declares Node ≥20.17, which
matches our actual floor.
Also remove the direct `listr2` devDep pin (^10.2.1) — it was a
holdover from an old lint-staged upgrade attempt, and v10 itself
declares Node ≥22.13. lint-staged@16 brings in a compatible listr2
as a transitive automatically.
With these in place, `engine-strict=true` (added via .npmrc) now
fails installs cleanly on Node <20.19, instead of silently warning
and crashing inside listr2 later.
Verified locally on Node 20.20.2:
- `npm ci` clean under engine-strict
- lint / test / build / smoke all pass
- `npx lint-staged --debug` runs eslint --fix + prettier --write
pipeline on a staged src/ file correctly
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`networkidle0` waits for 500ms of zero network activity, which never arrives on the GH Actions runner — `vite preview` keeps a few connections alive that the runner is slow enough to register as ongoing. PR #90's first CI run timed out at 15s before the page even finished loading. `load` is the right signal: the document + subresources are done, the module script has finished its top-level eval, React has mounted the tree. The existing 1500ms post-load delay still lets the Vanta useEffect run, so the original `(0, sA.default) is not a function` regression is still caught (re-verified locally against the pre-fix App.jsx — smoke fails with the same TypeError). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The first CI run on this branch stayed pegged on the smoke step
for 4+ minutes after passing/failing — Node never exited cleanly
after `browser.close()` + `preview.kill("SIGTERM")`. Something
(child pipes, residual puppeteer handles, vite preview's
grandchild) was keeping the event loop alive.
Add three guardrails:
- 90s overall watchdog that `process.exit(1)`s if we don't reach
a verdict in time.
- Explicit `process.exit(code)` on both success and failure paths
(no more relying on "the event loop will drain").
- SIGKILL backup 1.5s after SIGTERM, in case the preview ignores
the polite signal.
Verified locally: positive case 3.1s, negative case 3.0s, both
exit with the correct code. Watchdog never trips.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
lint-stagedfrom^17.0.4to^16.4.0so its declaredenginesfield matches our actual Node floor (≥20.19). v17 claimed Node ≥22.22.1, which blocked us from turning onengine-strict.listr2^10.2.1 devDep pin — leftover from an old upgrade attempt; lint-staged@16 brings in a compatible transitive automatically. The pinned v10 also declared Node ≥22.13.engine-strict=truevia.npmrc. Nownpm cion Node <20.19 fails cleanly at install time rather than silently warning and crashing later inside listr2.This is the follow-up I called out in
8f6f816— closes the gap where theengines.nodefield was advisory only.Test plan
npm ciclean underengine-strict=trueon Node 20.20.2 (source ~/.nvm/nvm.sh && nvm use 20 && rm -rf node_modules package-lock.json && npm installsucceeds with 0 vulnerabilities)npm run lintpassesnpm testpasses (coverage report unchanged)npm run buildsucceedsnpm run smokepasses (real Chrome smoke against built bundle)npx lint-staged --debugagainst a staged src/ file runseslint --fix+prettier --writeend-to-end, then prevents an empty commit (expected v16 behavior when format pipeline produces no real diff)Notes
A pre-existing
js-yaml ≤ 4.1.1audit finding (GHSA-h67p-54hq-rp68) showed up during install — not introduced by this PR, surfaced via the cleaner lockfile regen. Worth a separate Dependabot pass.🤖 Generated with Claude Code