ci: give the package a lint gate, and put typecheck in verify - #11
Merged
Conversation
`verify` here was `build && test`. Two gaps behind that:
- No lint at all. ESLint was not a dependency, there was no config, and no
script referenced it — so the fleet verify floor (lint AND typecheck AND
test) was unmet, and nothing checked this package's source style or its
obvious-error class.
- `typecheck` existed but was not in `verify`. `build` is `tsc -p`, so types
were checked as a side effect of emitting. That is not the same gate: it
conflates "compiles to dist" with "types are sound", and it dies the moment
the build strategy changes.
Both are now explicit: verify = lint → typecheck → build → test.
The ESLint config stays close to the recommended presets on purpose. This is
~1k lines of library code; a bespoke rule set would be a second opinion to
maintain for no benefit. The floor is "lint runs and can fail", not "lint
encodes taste". `no-explicit-any` is a warning rather than an error because
the public API deliberately accepts arbitrary user-supplied form shapes, so
those `any`s are load-bearing.
One finding worth naming: src/react.ts carried
// eslint-disable-next-line react-hooks/exhaustive-deps
with eslint-plugin-react-hooks not installed. Under a working lint that
directive is itself an error ("Definition for rule was not found") — the
comment was writing a cheque the config could not cash, and nobody knew
because lint never ran. Installing the plugin makes the suppression meaningful
and lints the exported hook for real.
CI needs no change: ci.yml and publish.yml already call `npm run verify`
verbatim, so lint now also gates npm releases.
Verified: `npm run verify` passes locally — eslint clean (exit 0), typecheck
clean, build clean, 19/19 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 16, 2026
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.
The gap
verifywasbuild && test. Two things were missing behind that:typecheckexisted but was not inverify.buildistsc -p, so types were checked only as a side effect of emitting. That conflates "compiles to dist" with "types are sound", and it evaporates the moment the build strategy changes.Now explicit:
verify= lint → typecheck → build → test.One thing lint found immediately
src/react.tscarried:// eslint-disable-next-line react-hooks/exhaustive-deps…with
eslint-plugin-react-hooksnot installed. Under a working lint that directive is itself an error —Definition for rule 'react-hooks/exhaustive-deps' was not found. The comment was writing a cheque the config could not cash, and nobody knew because lint had never run.Installing the plugin makes the suppression meaningful and lints the exported hook for real. That's the whole argument for the floor in one line: an unrun gate doesn't just miss bugs, it lets the codebase accumulate instructions to a checker that isn't there.
Config choices, stated
Close to the recommended presets on purpose — ~1k lines of library code doesn't need a bespoke rule set, which would just be a second opinion to maintain.
no-explicit-anyis a warning, not an error: the public API deliberately accepts arbitrary user-supplied form shapes, so thoseanys are load-bearing rather than lazy.dist/andexamples/are ignored (generated, and a standalone Next app respectively).Verification
npm run verifylocally: eslint clean (exit 0), typecheck clean, build clean, 19/19 tests pass.No workflow change needed —
ci.ymlandpublish.ymlalready callnpm run verifyverbatim, so lint now gates npm releases too.🤖 Generated with Claude Code