Skip to content

Releases

ts-react-linter-driven-development v2.1.0 — one set of thresholds, mixed-diff routing, hunter listings

Choose a tag to compare

@buzzdan buzzdan released this 22 Oct 09:34
4077431

[2.1.0] - 2026-10-18

Changed

  • A whole-repository review leaves the mutant question to scoped reviews. On
    --all, the hunter does not judge the question "does a mutant survive a leaf's
    tests?". Its receipt reads per-leaf, not judged, and its not reached: line names
    the three leaf directories with the most hits, each as the scoped review that
    judges it (/tsr-ldd-review <dir>). A scoped review judges the question in full. The lead for
    the mutant question also skips .tsx files, components/, hooks/ and context/.
  • The god file has a mechanical lead. The question "is one feature's code spread
    across layer directories?" lists the longest files in scope with wc -l and checks
    each against sonarjs/max-lines (600). A file over the limit, or with
    a max-lines directive that silences the rule, is a violation when it stands in for the
    whole slice.
  • The review command says how to cover a large repository. On a repository
    larger than a few dozen source files, --all reports PARTIAL coverage. The
    command names the form that covers everything: one review per directory
    (/tsr-ldd-review <dir>).

Fixed

  • A claim that something is missing needs a listing. A rule hunter that reports
    a missing test file, doc, case or cleanup now carries the ls, find or grep
    command that looked for it, run over the repository and not only the review's
    bundle, and that command's output. Without the listing there is no finding. A
    hunter once reported a test file as missing when it existed outside the scope.
    When the hunter's budget leaves no call for the listing, the claim appears in the
    hunter's not reached: line as unverified; the report never drops it.
  • A cluster title carries its rule ids. The review reference shows every cluster
    title as 🔗 CLUSTER: <anchor> — <rules>, the same form as the skill. Agents
    followed the reference, so the rule ids were on the lines below the title, and the
    report graders missed correct clusters.
  • The mutant hand check reads the error assertions. The hand check opens the
    leaf's test file, also when the file is outside the review's scope, and reads each
    error assertion. An assertion that matches only a word all the leaf's errors share
    (toThrow('tenant')) lets a removed check or a changed message survive, and it is a
    violation.

ts-react-linter-driven-development v2.0.0 — generated from the shared core

Choose a tag to compare

@buzzdan buzzdan released this 18 Oct 10:32
81783e4

[2.0.0] - 2026-10-06

Changed

  • Generated from the shared core. The plugin is rendered from the same core as
    go-linter-driven-development and python-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 .ts and .tsx files.
  • @component-designing is @code-designing. The design skill carries the
    core's name; the other five skill names are unchanged.
  • No CLAUDE.md in 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-ldd prefix. /tsr-ldd-autopilot, /tsr-ldd-quickfix,
    /tsr-ldd-prepare, /tsr-ldd-analyze, /tsr-ldd-review, /tsr-ldd-status;
    /wire-repo-brain stays 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 in comments.txt, and prints one summary line.
    scripts/ldd-detect.sh runs every detect line over the bundle and writes
    hits.tsv, hits-all.tsv and counts.tsv, with the suppression scan as a row;
    two runs over one tree write identical counts. Every falsifying question in
    rules/R1 to R12 carries a detect line beside its prose — a grep pattern over
    .ts and .tsx files, a path pattern over their paths, a reference to one of
    the R9 gate's questions, or the word judgment for 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
    with mutate naming leaf modules only, never pages, hooks or the whole src/
    tree — and every survivor is triaged as a missing it.each row, dead logic or a
    recorded equivalent mutant. The workflow's pre-flight discovers a mutate or
    stryker target 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 from core/handbook/ and lang/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's docs/language-residue.md: undefined is the declared
    absence and null stops 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
    readonly fields after; the JSDoc summary line is the contract; the kept switch
    is over a discriminated union closed by assertNever; 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 in main.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 and vi.mock of an internal module is R6's seam.
  • Linter routing keyed by ESLint rule ids. The SonarJS complexity family and
    react/no-unstable-nested-components route to R3, max-params to R1,
    sonarjs/max-lines and react/no-multi-comp to 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-exports to R8, no-param-reassign and
    sonarjs/prefer-read-only-props to R12. Every suppression form —
    eslint-disable in 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-critic and
    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-status and
    /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;
    a package.json directory outside node_modules marks a sub-project.
  • The six case studies under examples/, in TypeScript. The over-abstraction
    rejection is a readonly config against a CIDRPresence wrapper; the storify
    case extracts an IPConfig leaf from a settings hook; the anti-if case dispatches
    through a Record<Channel, …> and a switch closed by assertNever; the
    switch-to-polymorphism case moves fillUpdate onto the patch kinds; dependency
    rejection replaces import.meta.env reads with one AppConfig built 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.md and
    examples.md files 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.tsx files on its own.
  • The accessibility review checklist. Accessibility is enforced in the linter
    phase through the repository's jsx-a11y configuration, 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.mock of 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:line citation and phantom symbol, the unwired CLAUDE.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's jsx-a11y rules, 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 reach components/, 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-tenant lastSeen key, a score recomputed by hand
    and drifting, NaN passing a port check).
  • 2.0 weaknesses the run exposed: it asserted a test file was missing that exist...
Read more

go-linter-driven-development v2.9.1 — visibility default: private symbols get no comment

Choose a tag to compare

@buzzdan buzzdan released this 23 Jul 20:26
19f54c1

A real 143-line file surfaced the gap v2.9.0 left open: every one of its nine unexported symbols carried a comment — one of them 22 prose lines — because the tier budget caps a comment's size but nothing decided whether it should exist.

Added

  • Visibility default (R9) — unexported symbols get no comment. The name is the documentation; a name that needs a comment wants a rename or an extraction (R3) first. The special case is one line carrying a very high-value toolbox item: an ordering constraint, an external library quirk, the WHY of a magic number, the package's one real policy. Anything more moves to the exported caller, the package doc, or the feature doc. The tier table now explicitly prices exported API only.
  • New case file examples/private-comment-noise.md — the nine-helper file with per-symbol verdicts (four one-liners survive, five comments deleted; ~68 comment lines become 4) and the full "after". Rides in the comment-critic's spawn payload from both @pre-commit-review and @documentation.
  • New anti-toolbox entry: review-defense narration — the writer arguing with an imagined reviewer ("bounds-checked: it never indexes an empty slice", "deliberately narrow — not a generalized table"). The code shows its own safety; a design choice worth defending is defended in the feature doc.
  • Critic bias for unexported symbols — the question is existence, not size: default verdict DELETE; TRIM down to the one high-value line only when it already exists; never grow a private comment.
  • @documentation writes accordingly — FEATURE step 3 writes godocs for exported symbols only by default, so the noise is not written in the first place.

Field test

Run without the answer key (case file withheld from the payload): 9 comments — 0 KEEP / 3 TRIM / 2 REWRITE / 4 DELETE, matching the case file on 8 of 9 verdicts. The critic also routed the one over-budget-but-genuine WHY up to the exported caller instead of deleting the knowledge.

Full details in CHANGELOG.md.

go-linter-driven-development v2.9.0 — empathy test + when-in-Rome check

Choose a tag to compare

@buzzdan buzzdan released this 23 Jul 08:43
b10655b

Lessons from a repo owner's hard review of a large generated PR: the code was mergeable, but "could not reasonably ask another human to maintain the result".

Added

  • Empathy test — R9's test 3 (plain-English) grows teeth: write for a fresh graduate whose first language may not be English; unexplained acronyms and insider jargon fail, in comments and in the symbol names they document; and self-standing — a comment you can only understand after reading the code (or another comment) has negative value. The comment-critic now reads each comment before the surrounding code, and notes a rename recommendation when the jargon lives in the symbol name.
  • Decoder-ring references join the provenance anti-toolbox: plan/decision/test-plan IDs, requirement tags, spec section refs fail even when they resolve inside a repo doc — fact as plain prose, doc via one See-edge. Worked ❌/✅ example in the catalog.
  • Restated repo idiom is a new floor failure mode: a convention the repo applies everywhere is never re-justified at a use site, even though it is technically a WHY. The critic greps the repo for the pattern before crediting.
  • See-edge placement rule: the See docs/<feature>.md line is budget-free only as its own trailing line, never woven into the summary sentence.
  • When-in-Rome check (@pre-commit-review) + new 🟠 New Practice finding category: test mechanisms, dependencies, or conventions the host repo does not already use are adoption decisions for the repo owner — discussion or separate PR, never silent inclusion.
  • Two new maxims: "Empathy is a core engineering value" and "When in Rome, code as the Romans do".

Field test

The critic ran with the new payload against the reviewed PR's five comment-heaviest files: 49 comments — 7 KEEP / 19 TRIM / 19 REWRITE / 4 DELETE. It caught every comment the human reviewer flagged, plus ~20 more with the same problems. The one miss (jargon in a symbol name) became the rename-note addition.

Full details in CHANGELOG.md.

go-linter-driven-development v2.8.0 — Comment Value Toolbox + comment-critic

Choose a tag to compare

@buzzdan buzzdan released this 22 Jul 10:39
835383c

The comment-quality release: v2.7.0 + v2.8.0 together. Godoc comments get a hard tiered budget, a named value standard (the Comment Value Toolbox), and an adversarial reviewer — the comment-critic joins the hunter/skeptic review architecture. Field-tested against the real PR review that motivated it: 3/3 human-flagged comments caught, 0 false positives.

[2.8.0] - 2026-07-20

Added

  • Comment Value Toolbox + comment-critic — comments now have an adversarial
    reviewer.
    Reviewers reported ldd-written comments as noise: restated code,
    filled templates, no context. Root cause was architectural: @pre-commit-review
    runs in Phase 4, @documentation writes godocs in Phase 5 — comments were never
    adversarially reviewed, only self-checked by their writer.
    • The Comment Value Toolbox: a named, growable catalog of the ways a comment
      delivers value — WHY-not-WHAT, wider context, use cases/flows, boundary
      contract, guarantees, network edge. Normative kinds list in R9's comment
      policy; the catalog with worked examples lives in @documentation's
      reference.md and is designed to grow.
    • Three-test standard (normative in R9): toolbox-value (floor: a prose line
      delivering no toolbox value is cut; ceiling: the comment must carry the
      highest-value items for its symbol's tier — short-but-dodging fails too),
      tier budget (from v2.7.0), and plain English (everyday words, short
      sentences — not all readers are native speakers; applies to godocs AND
      feature docs). The floor names provenance a failure mode — PR numbers,
      review items, "the previous behavior" narration — under the 5-year reader
      lens: readers care how the product behaves now, not which review round
      produced it; history is rewritten as present-tense rationale, and
      incident/ticket refs survive only as rationale. Falsifying questions
      unchanged.
    • New comment-critic agent: read-only, single obsession — comment value.
      Judges every comment in the diff (godoc, in-body, test) against the three
      tests; verdicts KEEP / TRIM / REWRITE / DELETE with evidence; every rewrite
      names the toolbox item it delivers. In-body block-narration comments route to
      R3 (extraction candidates). Adversarial default: uncertain → fails.
    • @documentation closes the timing gap: write-time three-test gate in
      step 3, then a critique loop — spawn the critic on the full diff, auto-apply
      every non-KEEP verdict, re-critique once to confirm; report carries the delta
      (N deleted · M trimmed · K rewritten). Philosophy gains "plain words over
      clever words".
    • @pre-commit-review spawns the critic on the standalone/PR path whenever
      the diff contains comments; verdicts land as 🟡 Readability Debt, advisory.

Changed

  • Task → Agent tool rename across all skill and command frontmatter and
    prose: Claude Code renamed the subagent-spawning tool in v2.1.63; Task still
    works as a backward-compat alias, but the plugin now uses the canonical name.

[2.7.0] - 2026-07-20

Changed

  • Tiered godoc budget — R9's comment policy now has hard numbers. Generated
    godoc comments were verbose enough to slow human review; "menus, not forms" was
    guidance without a bound. R9's rung-1 comment policy is now a 1–5 prose-line
    budget scaled by the symbol's role
    : helpers 0–1 line, contract types (parsing
    constructors, self-validating types) 2–3, crossroads (entry points, orchestrators,
    feature front doors) up to 5. Blank // lines, the See docs/<feature>.md edge,
    and short inline examples (2–4 lines) are free; overflow moves to the feature
    doc — the placement rule made operational at write time. Two bounded escape
    hatches: a package that genuinely earns more moves its godoc to a dedicated
    doc.go (~20–30 lines), and a crossroads that deserves richer inline godoc gets
    an optional expand recommendation in @documentation's FEATURE report instead
    of extra lines — a human decides. Guidance-only: falsifying questions, hunters,
    and the skeptic are unchanged.
    • @documentation FEATURE step 3 applies the budget; its report format gains an
      optional Expand recommendations section.
    • reference.md godoc menus annotated with tier budgets; new doc.go hatch note,
      checklist budget items, and an over-budget → trimmed-to-tier worked example.
    • Root coding_rules.md Comments section aligned with the budget.

go-linter-driven-development v2.0.0 — rules as data

Choose a tag to compare

@buzzdan buzzdan released this 07 Jul 11:40
ede72a4

go-ldd v2 — the rules-as-data release. Each design principle now lives exactly once, as data in rules/R1–R9; skills are thin directional views over the rules, and review is done by parallel single-obsession hunters plus an over-abstraction skeptic.

⚠️ Breaking change

The quality-analyzer and go-code-reviewer agents were removed. If you invoked them directly (or reference them in your own CLAUDE.md / custom commands), migrate:

You used Use instead
quality-analyzer /go-ldd-analyze — read-only tests + lint + hunter/skeptic review, combined report
go-code-reviewer @pre-commit-review — the hunter/skeptic review

Everything else is a drop-in upgrade: plugin name, all six skill names, all five existing /go-ldd-* commands, auto-detection triggers, and zero-configuration discovery are unchanged.

Upgrade

/plugin update go-linter-driven-development@ai-coding-rules

What's new

  • rules/ R1–R9 — the single source of truth. Each rule ships its Principle, Why, canonical before/after, forward Design guidance, backward Fix pattern, and Falsifying questions with grep-able detection commands.
  • examples/ case law — deep worked studies the rules cite: storify-leaf-type, overabstraction-cidr, dependency-rejection.
  • Hunter/skeptic review — @pre-commit-review grep-prefilters the diff per rule, spawns one parallel rule-hunter per rule with hits (each fed a single rule file as its entire rulebook), then an overabstraction-skeptic that tries to kill every proposed extraction. Findings are categorized (🐛 Bugs / 🔴 Design Debt / 🟡 Readability / 🟢 Polish) and advisory — nothing blocks your commit.
  • Isolated lint-fixer agent — the full-repo lint-fix loop runs out-of-conversation; mechanical issues get fixed, design failures get escalated with a rule route.
  • Per-behavior TDD loop — the orchestrator now runs RED→GREEN→REFACTOR per behavior with package-scoped lint each cycle; full-repo lint happens once, in Phase 3.
  • New command /wire-repo-brain [path] — bootstrap the R9 documentation network on an existing repo in one pass (code→docs edges, index.md, CLAUDE.md wiring). Run it once to make a repo AI-navigable.
  • Composition-ladder testing — @testing now teaches testing each behavior at the lowest rung that contains it, with rung-tagged reusable patterns.

Full details in CHANGELOG.md and the plugin README.