Integrate Anti-IF + Fowler principles: R11, R12, PREPARE phase, and the maxims layer#17
Conversation
…TS dispatch patterns Go plugin (v2.2.0): - rules/R11-conditional-dispatch.md — a conditional that asks what a value IS may exist once; the second copy of a kind/type discriminator is a missing polymorphic type. Owns Interface Dispatch, Strategy Map, Null Object, Split Flag Argument, and the sanctioned Keep the Single Exhaustive Switch, with the inverse over-abstraction trap. - examples/anti-if-dispatch.md — case law: three-site channel switch to interface dispatch, strategy-map variant, and the worked rejection where the switch stays and goes exhaustive. - Wiring: refactoring routes `exhaustive` and discriminator-shaped `dupl` to R11; lint-fixer table kept consistent; code-designing dispatches R11 at design time; pre-commit-review hunts R11 and sends dispatch proposals to the skeptic with the new case file as payload. TS/React plugin (v1.1.0): - refactoring Pattern 8: lookup/component maps for duplicated discriminators, discriminated unions with never-exhaustiveness for the switch that stays; decision-tree and principles entries. - component-designing: one dispatch owner per variant family in principles and pre-code review questions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
anti-if-dispatch.md works the raw-discriminator disease (a kind string inspected at three sites). This second case file (real production code) works the type-switch instance: a value that is already polymorphic gets un-dispatched by a field-unpacking type switch, and the fix is a fill-style method on the interface the variants already implement. Unique content the first case file doesn't cover: - the tempting wrong fix: extract-per-case is the ceiling, not the cure - fill-don't-construct: the caller owns shared fields, variants fill their own - the earned AND sealed interface (unexported method) — R6 cross-wired - the dependency-direction rejection, orthogonal to Move 3's juiciness rejection: when the consumer owns the wire format, the dispatch move is physically unavailable and the switch stays as pure dispatch Wiring: R11 Q2 sharpened (own-interface switches violate at a single site; field-unpacking counts; boundary exemption scoped to foreign output formats), decide-once corollary + dispatch-requires-owning-the- output design bullets, fix-pattern citations, R6 earned-interface cross-ref, refactoring case-law list, README example table, changelog. Also restores the [2.1.0] heading the R11 commit accidentally deleted from the changelog (R10's release notes were floating inside 2.2.0). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Added It complements
Wiring: R11 Q2 sharpened (own-interface switches violate even at a single site; boundary exemption scoped to foreign output formats), two design-guidance bullets, fix-pattern + R6 earned-interface citations, refactoring case-law list, README, changelog. Also fixed in passing: the R11 commit had accidentally deleted the |
switch-to-polymorphism.md added the dependency-direction rejection axis; without it in the payload the skeptic can only refute R11 dispatch proposals on juiciness grounds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
… pipeline pattern Adopts the Refactoring (2nd ed.) ideas the rule set didn't already embody. Go plugin (v2.3.0): - rules/R12-mutation-discipline.md — the Mutable Data smell family with Go aliasing teeth: constructors copy collections in, queries copy (or iterate) out, query/modifier hybrids split, no setters around validating constructors, one variable per meaning; inverse trap for ceremony copies. - R3 gains the Split Phase move (parse phase → intermediate structure → compute phase; collapses into R2's ParseX when phase 1 validates). - R1 gains Introduce Parameter Object + a Data Clumps falsifying question. - R4 gains Move Method to the Envied Type + a Feature Envy question. - Wiring: pre-commit-review hunts R12 (Design Debt), code-designing dispatches it, refactoring pattern index owns its five moves; no routing-table row (no owning linter, R9 precedent). TS/React plugin (v1.2.0): - refactoring Pattern 9: Replace Loop with Pipeline (filter/map over accumulator loops), with guardrails against reduce abuse and async misuse; decision-tree entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
Fowler's "make the change easy, then make the easy change", encoded so autopilot never stops to ask: - Orchestrator Phase 1.5 PREPARE: after design approval, survey the plan's touch points with the existing rule detection greps; four mechanical gates decide per finding — MULTIPLY (only violations the plan would multiply qualify), SAFE (characterization tests first on uncovered paths), BOUNDED (S/M proceed, L defers to the Phase 4 advisory report), SKEPTICIZED (extractions judged by the over-abstraction skeptic against the plan in hand). Survivors are applied via @Refactoring and land as segregated prep commits before the first RED. The PREPARATION LOG is a record, not a question. - RED-friction escape hatch in Phase 2: a resisting test is a late prep signal — same gates, prep commit, re-enter RED. - @Refactoring <preparatory_mode>: plan-triggered (targets are usually lint-green), full suite green after every move, stopping criterion is landing shape (feature lands add-only), not lint status. - /go-ldd-prepare command for standalone use; autopilot/status commands and README flow updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
Rules are compiled judgment (detection + criterion + fix); maxims are the named questions that generate such rules where none anticipated the situation. maxims.md holds 17 of them (Tell-Don't-Ask, Law of Demeter, illegal-states-unrepresentable, parse-don't-validate, Metz's wrong-abstraction, YAGNI, three strikes, Pike's proverbs, Beck's change-easy, GOOS's listen-to-your-tests, Fowler's hurts-do-it-more, Knuth, once-and-only-once, depend-toward-stability) — each with the question it makes you ask and the rules that compile it, or uncompiled status. The contract — maxims propose, evidence disposes — wires them into the three judgment points and bans them from the evidence path: - code-designing gains <maxim_interrogation> (design has no diff to grep; questions are the only tool there) - refactoring escalations framed in maxim vocabulary - the skeptic cites Metz/Pike/YAGNI by name in verdicts - rule-hunter evidence protocol forbids maxim-justified findings Graduation path documented: a maxim that keeps convicting gets compiled into an R-file (R11 and R4's feature-envy question are graduates). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
The Fowler pair, compiled to what survives Tell-Don't-Ask: - R4 fix pattern gains two bullets: a message chain is a placement signal (move the behavior onto the chain's owner; only boundary egress keeps the chain, as a one-shot adapter mapping), and a type speaks for its parts only when it adds something (a pure-forward method is R1's ceremony verdict per method; domain-type embedding manufactures the smell in one line — embed only for genuine is-a). - maxims.md: Demeter entry updated to point at the new bullets; new house maxim "Every indirection must earn its keep" — the generalized juiciness test, one principle at six granularities (type/interface/method/dispatch/guard/copy), with the skeptic as its enforcement agent and the inverse traps as its retrospective form. No R13: after the behavior moves, nothing detectable remains, so the pair is guidance in the rule that owns placement, not a rule of its own. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
… review findings Hunters are single-obsession and blind to each other; findings from 2+ different rules converging on one anchor (same type, field, function) are independent confirmation of a missing domain concept. Fixing them member-by-member yields partial patches that undo each other. - pre-commit-review step 4 gains a cluster pass: convergent findings reported as first-class CLUSTER entries with a root-cause hypothesis and design-first routing note; members stay categorized, tagged. Clustering is reporting — the skill still never edits. - Orchestrator Phase 4 gains cluster routing: clusters go to code-designing in a new cluster-scoped mode (skips architecture scan and user-OK gate — acceptance inherited from the accepted findings; designs only the concept the cluster names), then refactoring implements the mini plan. Singletons route to refactoring unchanged. - quickfix Phase 4 follows the same routing; README hunter/skeptic section documents the convergence-as-evidence rationale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
There was a problem hiding this comment.
Pull request overview
This PR expands the rules-as-data architecture for the Go plugin to include Anti-IF conditional dispatch (R11), mutation discipline (R12), an autonomous PREPARE phase for preparatory refactoring, a maxims layer for design-time interrogation, and cluster-based routing when multiple rules converge on the same anchor. It also updates the TS/React plugin with new refactoring patterns and bumps both plugins’ versions.
Changes:
- Add Go rules R11 (conditional dispatch) and R12 (mutation discipline), plus supporting case-law examples and wiring across skills/agents/commands.
- Introduce PREPARE (Phase 1.5) and cluster-based review routing, and add
maxims.mdas a judgment-only layer. - Add TS/React refactoring patterns (tag-based conditional dispatch; loop → pipeline) and update plugin metadata/version references.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| ts-react-linter-driven-development/skills/refactoring/SKILL.md | Adds Pattern 8 (dispatch) and Pattern 9 (pipeline) and routes them in the decision tree. |
| ts-react-linter-driven-development/skills/component-designing/SKILL.md | Adds Anti-IF “one dispatch owner” guidance and a pre-code review question. |
| ts-react-linter-driven-development/.claude-plugin/plugin.json | Bumps TS/React plugin version to 1.2.0. |
| README.md | Updates top-level plugin versions and expands rules list to R1–R12. |
| go-linter-driven-development/skills/refactoring/SKILL.md | Wires R11/R12 and adds preparatory refactoring mode guidance and references. |
| go-linter-driven-development/skills/pre-commit-review/SKILL.md | Adds R11/R12 hunting, skeptic payload changes, and cluster reporting semantics. |
| go-linter-driven-development/skills/linter-driven-development/SKILL.md | Adds Phase 1.5 PREPARE and RED-friction escape hatch + cluster routing. |
| go-linter-driven-development/skills/code-designing/SKILL.md | Dispatches into R11/R12 design guidance and adds maxim interrogation + cluster-scoped mode. |
| go-linter-driven-development/rules/R6-test-only-interfaces.md | Cross-links earned interface case law and references R11 discipline. |
| go-linter-driven-development/rules/R4-helper-placement.md | Adds Feature Envy / Message Chains / Middle Man guidance and a new falsifying question. |
| go-linter-driven-development/rules/R3-storifying.md | Adds Fowler “Split Phase” move guidance. |
| go-linter-driven-development/rules/R12-mutation-discipline.md | New rule defining mutation discipline for Go (aliasing-safe collections, no query/modifier hybrids, etc.). |
| go-linter-driven-development/rules/R11-conditional-dispatch.md | New rule defining Anti-IF conditional dispatch (single owner of discriminator inspection) and fix patterns. |
| go-linter-driven-development/rules/R1-primitive-obsession.md | Adds Introduce Parameter Object and data clumps falsifying question, renumbers inverse question. |
| go-linter-driven-development/README.md | Updates Go plugin architecture docs for maxims, R11/R12, PREPARE, and clusters. |
| go-linter-driven-development/maxims.md | New maxims layer defining “maxims propose, evidence disposes” and compiled/uncompiled maxims list. |
| go-linter-driven-development/examples/switch-to-polymorphism.md | New case law for type-switch → polymorphism with dependency-direction rejection. |
| go-linter-driven-development/examples/anti-if-dispatch.md | New case law for duplicated discriminator switches → dispatch (plus rejection where switch stays exhaustive). |
| go-linter-driven-development/commands/go-ldd-status.md | Adds Phase 1.5 PREPARE to status output. |
| go-linter-driven-development/commands/go-ldd-quickfix.md | Adds cluster routing note to quickfix workflow docs. |
| go-linter-driven-development/commands/go-ldd-prepare.md | New standalone command for preparatory refactoring. |
| go-linter-driven-development/commands/go-ldd-autopilot.md | Updates autopilot command docs to include PREPARE step. |
| go-linter-driven-development/commands/go-ldd-analyze.md | Updates analyze command docs to prefilter R1–R12 and include R11/R12 in Design Debt. |
| go-linter-driven-development/CHANGELOG.md | Adds entries for 2.2.0–2.6.0 describing R11/R12, PREPARE, maxims, clusters, and links. |
| go-linter-driven-development/agents/rule-hunter.md | Forbids maxim-based findings (rules-only evidence). |
| go-linter-driven-development/agents/overabstraction-skeptic.md | Adds named maxim citations as doctrine for skeptic verdicts. |
| go-linter-driven-development/agents/lint-fixer.md | Routes discriminator-related dupl and exhaustive to R11. |
| go-linter-driven-development/.claude-plugin/plugin.json | Bumps Go plugin version to 2.6.0 and updates description for 12 rules. |
| .claude-plugin/marketplace.json | Updates marketplace description to reflect 12-rule Go plugin. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…S map typing - CHANGELOG: restore the [2.4.0] version header my 2.5.0 edit swallowed (PREPARE items were floating under 2.5.0; the bottom link had no section). - Orchestrator/autopilot/README: stop saying "all five phases" before a longer list — PREPARE is consistently framed as the autonomous sub-phase 1.5 of the five-phase workflow. - TS Pattern 8: the component map no longer widens every view to the union (which would fail against correctly-typed variant components or force internal re-narrowing). Entries are checked per-variant via `satisfies` a mapped type with Extract, with one localized, commented cast at the single dispatch site (correlated-union limitation). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
- TS plugin.json: description said six skills but listed five — the meta orchestrator was missing; now matches marketplace.json. - Root README: add /go-ldd-prepare to the Go plugin command inventory. - go-ldd-autopilot frontmatter: mention the PREPARE sub-phase so the command summary matches the body. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
…ventory - R12 canonical example: note that iter.Seq / slices.Values require Go 1.23+, with the version-agnostic walker form as the same move. - Plugin README directory tree: add prepare to the commands/ line so the overview inventory matches the commands table. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu
What
Five waves of principle integration, all following the rules-as-data architecture:
if, it is the duplicated kind-conditional.Go plugin → v2.6.0
New rule:
rules/R11-conditional-dispatch.md(Anti-IF) — a conditional that asks what a value is may exist once; the second copy is a missing polymorphic type. Owns: Replace Duplicated Switch with Interface Dispatch (decision moves to aParseXboundary constructor — R2's behavioral twin), Replace If-Chain with Strategy Map, Introduce Null Object, Split Flag Argument, and the sanctioned Keep the Single Exhaustive Switch (exhaustivelinter proves completeness). Inverse trap: dispatch that deletes no duplication is ceremony.New rule:
rules/R12-mutation-discipline.md(Fowler's Mutable Data, with Go aliasing teeth) — a validated value changes state only through methods that own its invariants. In Go,return g.permsreturns a mutable alias into the validated state — R2's validate-once guarantee is void the moment an internal slice escapes. Owns: Copy on the Way In, Copy on the Way Out / Encapsulate Collection (clones oriter.Seq), Separate Query from Modifier, Remove Setting Method, Split Variable. Inverse trap: ceremony copies of data that never escapes.New phase: 1.5 PREPARE — autonomous preparatory refactoring. After design approval, 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 segregated prep commits. Four mechanical gates decide — MULTIPLY / SAFE / BOUNDED / SKEPTICIZED — so the loop emits a PREPARATION LOG as a record, never a question. A RED-friction escape hatch catches what the survey missed. Plus
@refactoring<preparatory_mode>(stopping criterion: the feature lands add-only) and a standalone/go-ldd-preparecommand.New layer:
maxims.md. Rules are compiled judgment (detection + criterion + fix); maxims are the named questions that generate such rules where none anticipated the situation — 18 entries (Tell-Don't-Ask, Law of Demeter, illegal-states-unrepresentable, parse-don't-validate, Metz's wrong-abstraction, YAGNI, three strikes, Pike's Go proverbs, Beck's change-easy, GOOS's listen-to-your-tests, Fowler's hurts-do-it-more, Knuth, once-and-only-once, depend-toward-stability, and the house maxim "Every indirection must earn its keep" — the generalized juiciness test, one principle at six granularities). The contract — maxims propose, evidence disposes — wires them into the three judgment points (@code-designing<maxim_interrogation>,@refactoringescalation vocabulary, the skeptic's named citations) and bans them from hunters, with a documented graduation path (a maxim that keeps convicting becomes an R-file — R11 is a graduate).Finding clusters (review flow).
@pre-commit-review's merge step gains a cluster pass: findings from ≥2 different rules converging on one anchor (same type, field, function) are reported as first-class 🔗 CLUSTER entries with a root-cause hypothesis — hunters are single-obsession and blind to each other, so convergence is independent confirmation of a missing concept. The orchestrator routes clusters design-first:@code-designingin a new cluster-scoped mode (skips the architecture scan and user-OK gate — acceptance inherited; designs only the concept the cluster names), then@refactoringimplements the mini plan. Member-by-member fixing of clusters is explicitly forbidden — partial fixes undo each other.New case law:
examples/anti-if-dispatch.md— three-site channel switch (already drifted) → interface dispatch; the strategy-map variant; the worked juiciness rejection where the switch stays and goes exhaustive.examples/switch-to-polymorphism.md— the type-switch sibling (real production code): an already-polymorphic value un-dispatched by a field-unpacking type switch → fill-style interface method; the earned/sealed interface (R6); the dependency-direction rejection where the consumer owns the wire format and the switch stays as pure dispatch.Existing-rule sharpenings (Fowler):
ParseXwhen phase 1 validates)Wiring (one fact per fact):
@refactoringroutesexhaustive+ discriminator-shapedduplto R11 and indexes both rules' moves;lint-fixer's compact table kept consistent;@code-designingdispatches R11/R12 with checklist items;@pre-commit-reviewhunts both (🔴 Design Debt) and feeds R11 dispatch proposals to the skeptic with both case files as payload; README, CHANGELOG (2.2.0–2.6.0), manifests (10 → 12 rules).TS/React plugin → v1.2.0
@refactoringPattern 8: Replace Tag-Based Conditionals with Dispatch — config/lookup maps (Recordcompleteness), component maps over ternary chains in JSX, discriminated unions withneverexhaustiveness checks@refactoringPattern 9: Replace Loop with Pipeline — filter/map over accumulator loops, with guardrails againstreduceabuse and async misuse@component-designing: one-dispatch-owner principle + pre-code review questionNotes
python3 -c "json.load(...)".🤖 Generated with Claude Code
https://claude.ai/code/session_01LeLyATJFYTLwWRrB5Vatfu