mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-11 16:34:02 +01:00
Evil Martians' "ten anti-AI-slop moves" as a package: strict tsconfig base (noUncheckedIndexedAccess, exactOptionalPropertyTypes), type-checked typescript-eslint strict+stylistic, unicorn/sonarjs/perfectionist, behaviour rules for tests (expect-expect, no-focused-tests), React (hooks, @eslint-react, jsx-a11y strict, you-might-not-need-an-effect), Playwright, and layer boundaries via eslint-plugin-boundaries 7 with the article's default policies. Knip / jscpd / Stryker bases; Stryker carries no break threshold on purpose. Plugins are dependencies, not devDependencies: a flat config imports them from this package's own node_modules, so a consumer installing from the git tag gets them or the lint cannot run. No build step, so the tag needs no prepare. test/fixture is a mini repo with one planted violation per rule family; test/expected.js names the rule that must catch each, and the suite runs the real CLI over it (in a child process -- v8 coverage merges natively-loaded and transformed copies of the same module into "uncovered"). 35 tests, 100% branch coverage on the factories. eslint/fast.js is the type-free subset for a per-edit hook: 0.52 s cold on one file, measured against 1.28 s for base() without types -- importing a plugin is the cost, so it loads none, nor base.js which imports them. Probed under ESLint 10: jsx-a11y 6.10.2 (peer says <=9) and boundaries 7.2.0 both run; the fixture pins that. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnAYyNH1Sm4iJNidfYbrZJ
34 lines
1.3 KiB
JavaScript
34 lines
1.3 KiB
JavaScript
// The editor-hook subset: the rules that catch the model's most common holes
|
|
// without type information and without loading the heavy plugins.
|
|
//
|
|
// Used by the Claude Code PostToolUse hook that reports (never fixes) lint
|
|
// findings on the file just edited, against a 1.0 s per-turn budget. The
|
|
// full type-aware bar stays in pre-commit; this is the same-session feedback
|
|
// the article calls "put the rules in front of the model".
|
|
//
|
|
// Measured cold on one fixture file (2026-09-16, this machine): bare
|
|
// typescript-eslint 0.50 s; +unicorn 0.87 s; +sonarjs 0.75 s; all of
|
|
// base() without types 1.28 s. Importing a plugin is the cost, not the
|
|
// number of its rules that run, so this file loads none of the three -- nor
|
|
// base.js, which imports them (that alone was +0.55 s).
|
|
import js from "@eslint/js";
|
|
import tseslint from "typescript-eslint";
|
|
|
|
import { DEFAULT_IGNORES } from "./ignores.js";
|
|
import { imports } from "./imports.js";
|
|
|
|
export default tseslint.config(
|
|
{ ignores: DEFAULT_IGNORES },
|
|
js.configs.recommended,
|
|
...tseslint.configs.strict,
|
|
...tseslint.configs.stylistic,
|
|
{
|
|
rules: {
|
|
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
|
|
"@typescript-eslint/no-explicit-any": "error",
|
|
"@typescript-eslint/no-non-null-assertion": "error",
|
|
},
|
|
},
|
|
...imports,
|
|
);
|