DocumentationDecision recordsADR-0050
oxfmt and oxlint gate the v2 TypeScript
The v2 gate checked Rust with cargo fmt and cargo clippy -D warnings, but TypeScript only with tsc.
accepted
Context
The v2 gate checked Rust with cargo fmt and cargo clippy -D warnings, but
TypeScript only with tsc. The house conventions (function declarations for
standalone functions, arrow callbacks, no silent catch, Props for a
component's only local type) existed only as written guidance, and formatting
had drifted between an 80- and a 100-column style.
The anti-slop Oxlint plugin offers stricter type-evidence rules. Applied in
full to v2 it reports over 1,200 findings, most of them legitimate boundary
code: typeof guards and unknown parameters where IPC, storage, and sync
payloads are decoded, and conditional spreads that omit optional fields.
Decision
Format and lint every v2 TypeScript and JavaScript source from the repository
root with oxfmt (.oxfmtrc.json, 100 columns) and oxlint (.oxlintrc.json).
Both run in tools/scripts/build.sh, so ./bin/check and CI fail on any
finding. v1/ keeps its own configuration.
The rule set is:
- oxlint's
correctnesscategory plus explicit rules for the house conventions:func-style(declarations; a typed variable may hold an arrow when it implements a function-type contract),prefer-arrow-callback(named function expressions stay allowed somemoandforwardRefcomponents keep their display names),no-explicit-any, type-only imports,typeoverinterface, andreact/no-unstable-nested-components. - A vendored subset of
anti-slopintools/oxlint/anti-slop/: chained type assertions, widen-then-assert,Reflect.get/Reflect.apply, module mocking,objectparameters, and aliases that resolve tounknown. - A local
skriuwplugin intools/oxlint/skriuw/:no-silent-catch(acatchmust contain a statement; comments do not count,noop()marks a deliberate swallow) andlocal-type-name(a.tsxmodule's single, non-exported type is namedProps; other modules keep descriptive names becausePropsmeans component props).
Test code, harnesses, and e2e drivers may use any and chained assertions for
test doubles.
Deferred
These rules are off, not rejected. Each needs a behavior-reviewed migration before it can gate:
- React Compiler rules (
react/refs,set-state-in-effect,purity,immutability, and related) andexhaustive-deps: roughly 190 findings in code that reads refs deliberately under the performance contract. jsx-a11y: roughly 150 findings, mostly role and focus semantics that change interaction behavior when fixed.anti-slopboundary rules (no-runtime-typeof,no-unknown-parameters,no-unknown-returns,no-unsafe-dictionary-type,require-safety-comment-for-type-assertion): these conflict with decoding at trust boundaries until those boundaries have schema parsers.
Consequences
- Style review becomes mechanical; the reformat commit is listed in
.git-blame-ignore-revs. - Suppressions need an inline reason and are visible in review.
- Upgrading oxlint requires upgrading
@oxlint/pluginsto the same exact version.
On this page