Repository navigation
ts-react-linter-driven-development v2.0.0 — generated from the shared core
[2.0.0] - 2026-10-06
Changed
- Generated from the shared core. The plugin is rendered from the same core as
go-linter-driven-developmentandpython-linter-driven-development— twelve
rules, the maxims, the design, TDD, refactoring, testing, review and documentation
skills, the hunter/skeptic/critic review and the repo-brain gate — with TypeScript
and React knowledge. Every canonical example is TypeScript in a React repository;
every falsifying question carries a detect line over.tsand.tsxfiles. @component-designingis@code-designing. The design skill carries the
core's name; the other five skill names are unchanged.- No
CLAUDE.mdin the plugin directory. The 1.x file that instructed Claude to
invoke the orchestrator for every change is gone; the orchestrator skill
auto-triggers in a React project instead. - Commands carry the
tsr-lddprefix./tsr-ldd-autopilot,/tsr-ldd-quickfix,
/tsr-ldd-prepare,/tsr-ldd-analyze,/tsr-ldd-review,/tsr-ldd-status;
/wire-repo-brainstays unprefixed, as in the Go and Python plugins.
Added
- The twelve rules under
rules/, R1-primitive-obsession through
R12-mutation-discipline, each a self-contained hunter rulebook with a TypeScript
canonical example and a detect line on every falsifying question. - The review's detection pass and scope bundle are scripts.
scripts/ldd-scope.sh
writes the bundle from the review's scope rung — a file list, the working tree, the
branch against its base, or the whole repository — with the added comment lines
the critic judges incomments.txt, and prints one summary line.
scripts/ldd-detect.shruns every detect line over the bundle and writes
hits.tsv,hits-all.tsvandcounts.tsv, with the suppression scan as a row;
two runs over one tree write identical counts. Every falsifying question in
rules/R1toR12carries a detect line beside its prose — agreppattern over
.tsand.tsxfiles, apathpattern over their paths, a reference to one of
the R9 gate's questions, or the wordjudgmentfor a question the hunter can only
read. The pre-commit review's first step runs both scripts and reads the counts
table they print; a rule family with a hit gets one hunter carrying its rule files
by path and its family's rows of the hits table, and the comment critic reads the
bundle's comment lines as its inventory. What each question asks is unchanged. - R1 catches containers of primitives. Two falsifying questions: Q7, a nested
container in a signature or a field (Map<string, string[]>,
Record<string, Record<string, number>>), always a finding; Q8, a flat
string[],Record<string, string>or tuple crossing a function boundary, judged
by what its receivers do with it — a lookup, a membership test, a loop that
filters and extracts, each one a method of a type that does not exist yet. The
move is Name the Container; the lint-fixer's routing table, the refactoring
routing table and the design skill's linter triggers carry it as a review-only
row, because ESLint has no rule for it. - R7's mutation question. Q7 asks whether a mutant survives a leaf type's
tests: coverage is the floor, the mutation score the claim, and the move is Kill
the surviving mutant. The TypeScript mechanics name Stryker —npx stryker run
withmutatenaming leaf modules only, never pages, hooks or the wholesrc/
tree — and every survivor is triaged as a missingit.eachrow, dead logic or a
recorded equivalent mutant. The workflow's pre-flight discovers amutateor
strykertarget beside the test and lint commands, and the testing reference's
checklist carries the row. coding-rules/ts-react.md, the TypeScript + React coding-rules handbook. The
twelve rules with TypeScript examples and the binding's positions as asides, the
house rules with their TypeScript spelling, a self-review checklist and the
mechanics; generated fromcore/handbook/andlang/ts-react/handbook/in the
same run as the plugin, and read by a team that does not develop with it.- Nine positions where the rules meet TypeScript and React idiom, recorded in
the main repository'sdocs/language-residue.md:undefinedis the declared
absence andnullstops at the boundary; an optional collaborator is a module
constant supplied by a destructuring default; a self-validating type is the one
function that builds the value,parseX(raw: unknown)at the boundary and
readonlyfields after; the JSDoc summary line is the contract; the kept switch
is over a discriminated union closed byassertNever; effects, timers and queries
have owners and cleanups, and the race is the stale closure and the out-of-order
response; module state is silent for constants and types, silent inmain.tsx
for configuration and wiring, and reported everywhere else; a component is an
orchestrator whose logic lives in hooks and pure functions placed by R4's ladder;
MSW is the real layer for HTTP andvi.mockof an internal module is R6's seam. - Linter routing keyed by ESLint rule ids. The SonarJS complexity family and
react/no-unstable-nested-componentsroute to R3,max-paramsto R1,
sonarjs/max-linesandreact/no-multi-compto R5, the typescript-eslint
no-unsafe-*family at a boundary to R2, exhaustiveness and nested switches to
R11,react-hooks/*and the floating-promise rules to R10,
import/no-mutable-exportsto R8,no-param-reassignand
sonarjs/prefer-read-only-propsto R12. Every suppression form —
eslint-disablein all its spellings,@ts-expect-error,@ts-ignore,
@ts-nocheck,prettier-ignore— is one the lint-fixer never adds. - The agents:
rule-hunter,overabstraction-skeptic,comment-criticand
lint-fixer, each spawned in an isolated context and pointed by path at its rule
files — a hunter gets its rule family's, four hunters at most, with its family's
rows of the detection pass's hits table; the critic gets the bundle's comment
lines. - Seven slash commands:
/tsr-ldd-autopilot,/tsr-ldd-quickfix,
/tsr-ldd-prepare,/tsr-ldd-analyze,/tsr-ldd-review,/tsr-ldd-statusand
/wire-repo-brain. - Repo-brain gate with the TypeScript adapter.
scripts/check-repo-brain.sh
resolves backticked symbols against functions, variables, classes and their
members, interfaces, types and enums, owned by their module and their directory;
apackage.jsondirectory outsidenode_modulesmarks a sub-project. - The six case studies under
examples/, in TypeScript. The over-abstraction
rejection is areadonlyconfig against aCIDRPresencewrapper; the storify
case extracts anIPConfigleaf from a settings hook; the anti-if case dispatches
through aRecord<Channel, …>and aswitchclosed byassertNever; the
switch-to-polymorphism case movesfillUpdateonto the patch kinds; dependency
rejection replacesimport.meta.envreads with oneAppConfigbuilt in
main.tsx; the comment-noise verdicts fall on non-exported JSDoc.
Removed
- The hand-written six-skill text. The 1.x
SKILL.md,reference.mdand
examples.mdfiles are replaced by the rendered core; nothing from them is
carried over verbatim. - Storybook generation as a documentation step. A story is the runnable example
only where the repository has Storybook; the documentation skill no longer
writes.stories.tsxfiles on its own. - The accessibility review checklist. Accessibility is enforced in the linter
phase through the repository'sjsx-a11yconfiguration, where a failing rule is
a mechanical fix, not a review hunter's finding.
Measured against 1.x
Both plugins reviewed the ts-react-mini eval fixture (164 planted violations and
controls, in buzzdan/ldd-evals) under the
same prompt and model (claude-sonnet-5): eight review cases whose prompt names no
slash command and whose graders carry no rule ids, then refereed finding by finding
against the manifest, by substance.
- Whole repository. 1.x found 53 of the 129 planted diseases a review must find,
2.0 found 89: 42 by both, 11 by 1.x alone, 47 by 2.0 alone, 29 by neither. False
positives on the 30 controls: 3 against 1. Cost $3.22 against $6.30. - Scoped cases. 2.0 found as many or more in six of seven (retention 4/3,
endpoint 4/2, ceremony 4/2, optional collaborators 6/4, globals 4/4, the
798-line centerpiece 34/11 of 45); 1.x was ahead on the placement picker (3/2). - What 2.0 sees that 1.x never names: tests (fused success/error tables, call
counts on doubles, sleep-then-assert,vi.mockof an internal hook beside MSW
handlers), test seams (an interface with one production implementer, hand
doubles, a false "avoids an import cycle"), documentation (the orphan doc, its
file:linecitation and phantom symbol, the unwiredCLAUDE.md), suppressions
as findings, the comment critic's verdicts, role-named directories and the
layer-versus-slice split, and three concurrency plants (an interval started in a
constructor and never cleared, a check-then-await race, bare sleeps in retries). - What 1.x sees that 2.0 does not: accessibility (no hunter owns it; 2.0 relies
on the repository'sjsx-a11yrules, which the fixture disables as the house
style does), and the React tree in the whole-repository run, where 2.0's types
hunter declared partial coverage and did not reachcomponents/,hooks/or
pages/DeviceView/, so the nested-component, prop-drilling and sort-in-render
plants went unseen rather than misjudged. 1.x also raised several real bugs
outside the manifest (a cross-tenantlastSeenkey, a score recomputed by hand
and drifting,NaNpassing a port check). - 2.0 weaknesses the run exposed: it asserted a test file was missing that exists
(picker), it rewrote the one WHY comment the ceremony case protects, and its
whole-repository coverage is partial at 167 files.