Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
{
"name": "go-linter-driven-development",
"source": "./go-linter-driven-development",
"description": "Rules-as-data linter-driven development workflow for Go: 10 single-source rule files, thin directional skills (design, TDD implementation, refactoring, testing, review, documentation), and a hunter/skeptic review architecture with parallel single-rule reviewers and an over-abstraction skeptic"
"description": "Rules-as-data linter-driven development workflow for Go: 12 single-source rule files, thin directional skills (design, TDD implementation, refactoring, testing, review, documentation), and a hunter/skeptic review architecture with parallel single-rule reviewers and an over-abstraction skeptic"
},
{
"name": "ts-react-linter-driven-development",
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ A [Claude Code](https://claude.ai/code) plugin marketplace for **linter-driven d

| | Plugin | Version | For |
|---|--------|---------|-----|
| 🐹 | [`go-linter-driven-development`](go-linter-driven-development/README.md) | 2.0.0 | Go |
| ⚛️ | [`ts-react-linter-driven-development`](ts-react-linter-driven-development/README.md) | 1.0.0 | TypeScript + React |
| 🐹 | [`go-linter-driven-development`](go-linter-driven-development/README.md) | 2.6.0 | Go |
| ⚛️ | [`ts-react-linter-driven-development`](ts-react-linter-driven-development/README.md) | 1.2.0 | TypeScript + React |

Plus the standalone rule documents the plugins grew out of:

Expand All @@ -18,10 +18,10 @@ Plus the standalone rule documents the plugins grew out of:

The organising idea: **the rule is the unit, not the phase.** Each design principle lives exactly once, as data:

- **`rules/` R1–R10** — single source of truth: primitive obsession, self-validating types, storifying, helper placement, vertical slices, test-only interfaces, test placement, no globals, repo-brain documentation, concurrency safety.
- **`rules/` R1–R12** — single source of truth: primitive obsession, self-validating types, storifying, helper placement, vertical slices, test-only interfaces, test placement, no globals, repo-brain documentation, concurrency safety, conditional dispatch (Anti-IF), mutation discipline (Fowler's Mutable Data).
- **`skills/`** — six thin directional views that sequence and route into the rules (orchestrator, design, testing, refactoring, review, documentation).
- **`agents/`** — payload-fed isolated workers: parallel single-obsession `rule-hunter`s, an `overabstraction-skeptic` that tries to kill proposed extractions, and a `lint-fixer` that keeps the lint loop out of your conversation.
- **`commands/`** — `/go-ldd-autopilot`, `/go-ldd-quickfix`, `/go-ldd-analyze`, `/go-ldd-review`, `/go-ldd-status`, `/wire-repo-brain`.
- **`commands/`** — `/go-ldd-autopilot`, `/go-ldd-quickfix`, `/go-ldd-prepare`, `/go-ldd-analyze`, `/go-ldd-review`, `/go-ldd-status`, `/wire-repo-brain`.

Full architecture, workflow, and usage: [plugin README](go-linter-driven-development/README.md) · what changed between versions: [CHANGELOG](go-linter-driven-development/CHANGELOG.md).

Expand Down
4 changes: 2 additions & 2 deletions go-linter-driven-development/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "go-linter-driven-development",
"version": "2.1.0",
"description": "Rules-as-data linter-driven development workflow for Go: 10 single-source rule files, thin directional skills (design, TDD implementation, refactoring, testing, review, documentation), and a hunter/skeptic review architecture with parallel single-rule reviewers and an over-abstraction skeptic",
"version": "2.6.0",
"description": "Rules-as-data linter-driven development workflow for Go: 12 single-source rule files, thin directional skills (design, TDD implementation, refactoring, testing, review, documentation), and a hunter/skeptic review architecture with parallel single-rule reviewers and an over-abstraction skeptic",
"author": {
"name": "Dan Mordechay"
},
Expand Down
163 changes: 163 additions & 0 deletions go-linter-driven-development/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,164 @@
All notable changes to the `go-linter-driven-development` plugin are documented here.
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow [Semantic Versioning](https://semver.org/).

## [2.6.0] - 2026-07-10

### Added

- **Finding clusters — design-first routing for related review findings.** Hunters
are single-obsession and blind to each other, so when findings from ≥2 different
rules converge on one anchor (the same type, field/discriminator, or function),
that independent convergence is evidence of a missing domain concept — a
juiciness scorecard that filled itself in. Fixing such findings member-by-member
produces partial patches that undo each other (R1 names an enum that R11's move
then replaces; R2 places validation that R11's move relocates).
- `@pre-commit-review` step 4 gains a **cluster pass**: convergent findings are
reported as first-class 🔗 CLUSTER entries with a root-cause hypothesis and a
design-first routing note; members stay in their categories, tagged. Clustering
is reporting — the skill still never edits.
- The orchestrator's Phase 4 gains **cluster routing**: clusters go to
`@code-designing` in a new **cluster-scoped mode** (skips the architecture scan
and user-OK gate — acceptance was inherited when the findings were accepted;
designs only the one concept the cluster names), then `@refactoring` implements
the mini plan; member findings resolve as consequences of one design.
Singletons route directly to `@refactoring`, unchanged.
- `/go-ldd-quickfix` Phase 4 follows the same routing.

## [2.5.0] - 2026-07-10

### Added

- **`maxims.md` — the uncompiled layer above the rules.** Rules are compiled
judgment (detection command + violation criterion + fix pattern); maxims are the
named questions that *generate* such rules in situations no rule anticipated:
"Tell, don't ask", the Law of Demeter, "Make illegal states unrepresentable",
"Parse, don't validate", "Duplication is far cheaper than the wrong abstraction",
"YAGNI", "Three strikes", "A little copying is better than a little dependency",
"The bigger the interface, the weaker the abstraction", "Make the zero value
useful" (held in explicit tension with R2), "Make the change easy…", "If a test
is hard to write, the design is wrong", "If it hurts, do it more often",
"Premature optimization…", "Clear is better than clever", "Once and only once",
"Depend in the direction of stability". Each entry: the quote, attribution, the
question it makes you ask, and the rules that compile it (or *uncompiled* status).
- **The contract: maxims propose, evidence disposes.** Maxims are wired into the
three judgment points and banned from the evidence path:
- @code-designing gains `<maxim_interrogation>` — the plan is questioned with the
maxims before types are committed (design has no diff to grep; questions are
the only tool there)
- @refactoring's escalation now frames *why code resists* in maxim vocabulary
- the `overabstraction-skeptic` cites Metz/Pike/YAGNI by name in verdicts — a
named principle is an argument, "feels unnecessary" is not
- the `rule-hunter` evidence protocol explicitly forbids maxim-justified findings
- **Graduation path**: a maxim that keeps generating findings no rule can express
gets compiled into an R-file — R11 and R4's feature-envy question are graduates
of exactly this path.
- **The Message Chains ↔ Middle Man pair** (Fowler's opposing smells), compiled to
its post-Tell-Don't-Ask residue as two R4 fix-pattern bullets: a chain is a
placement signal (move the behavior; only boundary egress keeps the chain, inside
the adapter), and a pure-forward method is R1's ceremony verdict applied per
method (delete forwards that own no rule; domain-type embedding manufactures the
smell in one line). No R13 — after the behavior moves, nothing detectable
remains, so the pair is guidance, not a rule.
- **House maxim: "Every indirection must earn its keep"** — the generalized
juiciness test, named as the plugin's own synthesis: one principle at six
granularities (type/interface/method/dispatch/guard/copy), enforcement agent the
`overabstraction-skeptic`; each rule's inverse trap is its retrospective form.

## [2.4.0] - 2026-07-10

### Added

- **Phase 1.5 PREPARE — autonomous preparatory refactoring** (Fowler: "make the
change easy, then make the easy change"). After the user approves the design plan,
the orchestrator surveys the plan's touch points with the existing rule detection
greps and reshapes what the change is about to hit — before the first RED, in its
own commit(s). Decisions are made by four mechanical gates, never by stopping to
ask: **MULTIPLY** (only violations the plan would multiply qualify), **SAFE**
(characterization tests first on uncovered paths), **BOUNDED** (S/M efforts
proceed, L defers to the Phase 4 report), **SKEPTICIZED** (any extraction is
judged by the over-abstraction skeptic, scored against the plan in hand).
Autopilot never pauses; the PREPARATION LOG is a record, not a question.
- **RED-friction escape hatch** (Phase 2): a RED test that resists — fixture
surgery, global mutation, driving layers to reach a seam — is a prep signal the
survey missed; suspend the cycle, run the same gates, land the prep commit,
re-enter RED.
- **`@refactoring` `<preparatory_mode>`**: same routing table and moves, different
trigger (the plan, not the linter — targets are usually lint-green) and different
stopping criterion: not "linter green" but "the feature now lands add-only";
full suite green after every move; prep commits segregated from feature commits.
- **`/go-ldd-prepare <change> [files]`** — standalone entry: describe the impending
change, get the survey + gates + reshaping without the full five-phase workflow.

## [2.3.0] - 2026-07-10

The Fowler wave — adopting the *Refactoring* (2nd ed.) ideas the rule set didn't
already embody. (Much of the catalog was already here under other names: Extract
Function → R3, Replace Primitive with Object → R1, Repeated Switches → R11,
Speculative Generality → the over-abstraction skeptic, the Two Hats → the
RED→GREEN→REFACTOR loop.)

### Added

- **`rules/R12-mutation-discipline.md`** — Fowler's Mutable Data smell family with
Go aliasing teeth: a validated value changes state only through methods that own
its invariants. In Go, `return g.perms` returns a mutable alias into the
"validated" state — R2's validate-once guarantee is void the moment an internal
slice escapes. R12 owns:
- Copy on the Way In — constructors clone slice/map arguments (or build fresh)
- Copy on the Way Out / Encapsulate Collection — queries return clones or `iter.Seq` iterators, never internal references
- Separate Query from Modifier — split hybrids; pure naming cases stay with R3's Honest Rename
- Remove Setting Method — no unvalidated mutation paths around a validating constructor (construction itself stays R2's)
- Split Variable — one assignment per meaning
- the inverse trap: ceremony copies of data that never escapes, mirroring R1's over-abstraction symmetry
- **Split Phase move in R3** (Fowler's opening example): a function interleaving
parsing with computation splits into phase 1 producing an intermediate domain
structure and phase 2 consuming it — distinct from Extract Function because it
introduces a data structure *between* the steps; collapses into R2's `ParseX`
when phase 1 validates.
- **Data Clumps question in R1** (Introduce Parameter Object / Preserve Whole
Object): the same parameter group in ≥2 signatures is a type asking to exist —
the scorecard already rewarded grouping; now a falsifying question hunts it.
- **Feature Envy in R4** (Move Function): a new fix pattern (Move Method to the
Envied Type) and falsifying question — a function reading a foreign type's data
more than its own moves onto that type, then re-places via the ladder.
- Wiring: pre-commit-review hunts R12 (🔴 Design Debt), code-designing dispatches
R12 at design time (closed mutation surface in the checklist), refactoring's
pattern index owns the five R12 moves. R12 has no owning linter (like R9) — no
routing-table row.



## [2.2.0] - 2026-07-10

### Added

- **`rules/R11-conditional-dispatch.md`** — the Anti-IF rule, adapting the Anti-IF
movement's core insight (Cirillo, 2007) to the rules-as-data architecture: a
conditional that asks what a value *is* may exist once; the second copy of a
kind/type discriminator is a missing polymorphic type. R11 owns:
- Replace Duplicated Switch with Interface Dispatch — variants become leaf types, the decision moves to a `ParseX` boundary constructor (R2's behavioral twin: *decide* once at the edge)
- Replace If-Chain with Strategy Map — single-behavior variance dispatches through a map, comma-ok at the boundary only
- Introduce Null Object and Split Flag Argument
- the sanctioned form: Keep the Single Exhaustive Switch — one site over a closed enum stays, named per R1 and proven complete by the `exhaustive` linter
- the inverse trap: dispatch abstractions that delete no duplication are ceremony — one switching site with trivial variance keeps its switch (mirroring R1's over-abstraction symmetry and R6's earned-interface test)
- **`examples/anti-if-dispatch.md`** — case law: a three-site channel switch (already
drifted) collapsed to interface dispatch, the strategy-map variant, and the worked
rejection where the skeptic kills the extraction and the switch goes exhaustive
instead. Pasted to the skeptic alongside R11 dispatch proposals.
- **`examples/switch-to-polymorphism.md`** — second R11 case file (real production
code), the type-switch sibling of anti-if-dispatch: an already-polymorphic value
un-dispatched by a field-unpacking type switch becomes a fill-style interface
method. Covers the tempting wrong fix (extract-per-case as ceiling, not cure),
fill-don't-construct ownership, the earned + sealed interface (R6), and the
dependency-direction rejection — orthogonal to the juiciness rejection — where
the consumer owns the wire format and the switch legitimately stays as pure
dispatch.
- Wiring: pre-commit-review hunts R11 (🔴 Design Debt), its dispatch proposals face
the over-abstraction skeptic with the new case file as payload, code-designing
dispatches R11 at design time (one dispatch owner per variant family in the
checklist), refactoring + lint-fixer route `exhaustive` failures and
discriminator-shaped `dupl` hits to it.

## [2.1.0] - 2026-07-07

### Added
Expand Down Expand Up @@ -58,6 +216,11 @@ Initial release as a Claude Code plugin: five-phase linter-driven workflow (desi

Notable unversioned improvements between 1.0.0 and 2.0.0: auto-pilot mode and review agent commands, evidence-based review with test-only interface detection, self-validation ownership rule, improved lint-failure flow, and making the package-size hook opt-in.

[2.6.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.6.0
[2.5.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.5.0
[2.4.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.4.0
[2.3.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.3.0
[2.2.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.2.0
[2.1.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.1.0
[2.0.0]: https://github.com/buzzdan/ai-coding-rules/releases/tag/go-ldd-v2.0.0
[1.0.0]: https://github.com/buzzdan/ai-coding-rules/commit/746ae7d
Loading