Skip to content

Adopt anti-slop lint rules - #20

Merged
kualta merged 4 commits into
mainfrom
anti-slop-lint
Aug 16, 2026
Merged

Adopt anti-slop lint rules#20
kualta merged 4 commits into
mainfrom
anti-slop-lint

Conversation

@kualta

@kualta kualta commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the anti-slop Oxlint rules via the shared @flow-industries/lint package, and fixes every finding in this repo (34).

Biome still owns formatting and the general lint set; Oxlint runs only anti-slop on top. bun run lint is now biome check && oxlint.

New: cssVars()

Five components asserted { "--x": v } as React.CSSProperties to smuggle CSS custom properties past React's types. src/utils/css-vars.ts replaces all of them: keys are still checked (they must match --${string}) but nothing is asserted into a type it isn't. satisfies cannot do this job — the excess-property check rejects a fresh literal either way — so the helper is the honest fix.

Behaviour fixes found along the way

  • form.tsx had dead error handling. The contexts defaulted to {} as FormFieldContextValue, which made the existing if (!fieldContext) throw unreachable and placed it after the first use of fieldContext.name. Contexts now default to null, and useFormField guards both contexts before use (after all hooks, so hook order is stable).
  • sidebar.tsx setOpen accepted an updater it never advertised. The context type is setOpen: (open: boolean) => void, but the implementation also took (prev) => next for one internal call. Dropped the union so the implementation matches its published contract; toggleSidebar now passes !open. Its dependency list was corrected accordingly.

Other fixes

  • dock.tsx (4), status-widget.tsx, chart.tsxRecord<K, V> annotations on constant maps replaced with satisfies.
  • status-widget.tsxderiveOverall filtered endpoints then re-read e.results as ProbeResult[]; now a single filter chain that narrows on its own.
  • input-group.tsx(e.target as HTMLElement).closest(...) became e.target instanceof HTMLElement && …, a real runtime check.
  • sidebar.tsx — the tooltip prop's string | TooltipProps convenience union is discriminated with tooltip instanceof Object (a string primitive is not an Object) instead of typeof.
  • chart.tsx — the Recharts config lookup no longer indexes with as keyof typeof; it collects candidate fields and picks whichever names a real config entry, which is behaviour-preserving. Theme CSS generation iterates a typed THEME_KEYS tuple instead of Object.entries + an assertion. Primitive tests use coercion round-trips (String(x) === x, Number(x) === x) rather than typeof.
  • logo.tsx, profile-pill.tsx — conditional empty-object spreads replaced with plain optional properties.

Testing

  • bun run lint (Biome + Oxlint) clean; bun run typecheck clean. The 8 remaining Biome warnings are pre-existing on main (verified by stashing this branch's changes).
  • Browser, against bun run dev:
    • Showcase page: status-widget renders "All systems operational" off the live API, exercising the rewritten deriveOverall.
    • Mounted the changed components on a scratch page (since the showcase does not include them) and asserted computed styles: --ratio: 1.7777, --sidebar-width: 16rem, --skeleton-width: 75%, --gap: 2, --color-desktop/#8ab4ff — every cssVars call resolves.
    • Chart tooltip renders jan / Desktop 120 / Mobile 80, so the rewritten config lookup still resolves labels from the payload.
    • Sidebar toggles expanded → collapsed → expanded, confirming the setOpen change.
    • Both tooltip forms render: a bare string gives "String form" and { children } gives "Object form".
    • Scratch page removed afterwards; no app console errors.

Blocked on a publish

@flow-industries/lint@0.2.0 is not on npm yet (the publish needs a 2FA OTP). Until it lands, bun install --frozen-lockfile cannot resolve it, so CI on this PR will fail and bun.lock still records 0.1.0. Once published, the branch needs one follow-up commit: bun install to regenerate the lockfile. Everything else here is final.

How this was verified

Ran locally against a linked build of the new lint package.

@kualta

kualta commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Superseded detail: the Oxlint layer described above has been replaced in this branch by biome-anti-slop — the same 15 rules as Biome GritQL plugins, one linter instead of two. bun run lint is plain biome check again, .oxlintrc.json is gone, and Biome is bumped to 2.5.8 (the plugins need ≥2.5.0). All findings fixed in this PR stay fixed; a planted violation was used to confirm the plugins actually load and report. See flow-industries/lint#3 for the shared-package side.

@kualta
kualta merged commit 01658a9 into main Aug 16, 2026
3 checks passed
@kualta
kualta deleted the anti-slop-lint branch August 16, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant