ADR-0006: Removing the lint step rather than faking it
Edit this pageStatus: Superseded by ADR-0008 Date: 2026-08-14
Context
The first time CI ran against a fully populated repository, the TypeScript job
failed at pnpm lint. The cause was not a lint violation.
The workspace has no ESLint configuration of any kind — no
eslint.config.js, no .eslintrc.*, and neither eslint nor
eslint-config-next in any package.json. Both applications declared
"lint": "next lint", and two packages declared "lint": "eslint src".
With no configuration present, next lint does not fail — it opens its
interactive setup prompt, "How would you like to configure ESLint?". CI has
no terminal to answer, so the process cancelled and exited non-zero. The bare
eslint src invocations aborted with the ESLint 9 flat-config migration
notice.
The important part: this had been true since the workflow was written. The
lint step had never linted a single file. make lint advertised
"eslint + golangci-lint + squawk" and delivered none of the first.
The obvious fix — add eslint, eslint-config-next and a flat config — was
not available in the session that found this. Adding a dependency requires
regenerating pnpm-lock.yaml, and CI installs with --frozen-lockfile; a
manifest edit without a matching lockfile update breaks every job. The
environment that discovered the problem could not run pnpm install.
Decision
Remove the lint step from CI and delete the phantom lint scripts, rather than leave a step that appears to enforce something it does not.
Concretely: pnpm lint is gone from the TypeScript job, with a comment
explaining why; "lint": "eslint src" is removed from packages/contracts
and packages/shared, since turbo skips packages that do not define a task.
CONTRIBUTING and the changelog both state that no JavaScript or TypeScript
linter currently runs.
Restoring it is tracked as a Next item on the roadmap.
The work is: add eslint and eslint-config-next, write a flat
eslint.config.mjs, fix whatever it finds on first run, and restore the CI
step.
Alternatives considered
Mark the step continue-on-error: true. Rejected, firmly. This is the
same pattern as the "Skip if Dockerfile missing" step that let the release
pipeline report success while publishing nothing for two of three images. A
green check that means nothing is worse than a missing check, because it
actively misleads.
Replace the script with prettier --check. Considered. Prettier is
already a root dependency, so this would have been a real check with no new
dependency. Rejected because it could not be verified in the environment that
made the change — if the repository is not already prettier-clean, the job
turns red for a formatting reason unrelated to the problem being fixed, and we
would be trading one broken job for another.
Add ESLint anyway and hope the lockfile resolves in CI. Rejected. It would
have broken pnpm install --frozen-lockfile for every job in the workflow,
turning one failing step into a completely red pipeline.
Leave it failing until someone fixes it properly. Rejected. The repository was about to be published. A permanently red badge on a security tool's front page is a worse first impression than an honestly narrower set of checks.
Consequences
Accepted costs.
- No JavaScript or TypeScript linting runs. Unused imports, shadowed variables, accessibility problems in JSX and React hook mistakes will not be caught mechanically until this is reversed.
make lintnow overstates what it does for the TypeScript half, until the restoration lands.
Mitigations already in place.
- TypeScript runs in strict mode and
tsc --noEmitcovers all four packages in CI, catching the largest class of errors a linter would. - The codebase contains zero
any, zero@ts-ignoreand zeroeslint-disable— so there is no accumulated suppression debt for a future linter to fight through. gofmt,go vetandgolangci-lintstill cover the Go services, andsquawkcovers migrations.
Gains.
- CI is honest. Every remaining check does what its name says.
- The state is documented in three places a contributor will look — CONTRIBUTING, the changelog and the roadmap — rather than being a surprise.
Reversal criteria met. eslint.config.mjs exists, the dependencies are in
the lockfile, and the CI step is restored and passing. See
ADR-0008.