| Notation | Skill Tool Call |
|---|---|
| @code-designing | Skill(go-linter-driven-development:code-designing) |
| @testing | Skill(go-linter-driven-development:testing) |
| @refactoring | Skill(go-linter-driven-development:refactoring) |
| @pre-commit-review | Skill(go-linter-driven-development:pre-commit-review) |
| @documentation | Skill(go-linter-driven-development:documentation) |
The lint-fixer agent is spawned with the Agent tool:
subagent_type: "go-linter-driven-development:lint-fixer".
- Verify Go project:
go.modin root or parent directories. - Discover commands (README.md, CLAUDE.md, Makefile, Taskfile.yaml, in that
order): test + lint commands. Fallbacks:
go test ./...,golangci-lint run --fix. - List the behaviors this change delivers — each becomes one Phase 2 TDD cycle. No plan or unclear scope → Phase 1 produces the plan; unclear intent → ask.
Survey: for each file/package the DESIGN PLAN touches (integration points,
functions it extends, packages receiving new code), run the rule detection greps from
the ../../rules/R*.md Falsifying questions, scoped to those files only. Same
commands as the REFACTOR step, different premise: this code is probably lint-green
and can still be hostile to the plan.
Four gates per finding — all mechanical, no user questions:
- MULTIPLY — would landing the plan add an instance of this violation or force a workaround (a new case in an already-duplicated switch, R11; new behavior on a raw primitive, R1; a new step in an at-limit function, R3; new code testable only by mutating a global, R8)? No → not preparation; leave it for Phase 4's advisory report.
- SAFE — are the paths to reshape covered (
go test -coveron the touched packages)? Uncovered → write characterization tests through the public API first (@testing); they are the move's safety net and keep their value after. When the missing test seam IS the finding (globals block testing), the prep move creates the seam — R8's Extract Clean Island exists for exactly this. - BOUNDED — effort S/M (hunter scale) → proceed. L → defer to Phase 4's report
as
PREP-DEFERRED, UNLESS gate 2 showed the feature cannot be tested at all without it — then it is not preparation but a design-plan gap: return to Phase 1. - SKEPTICIZED — any prep move that creates a type/interface/package is judged by
the
overabstraction-skeptic(Agent tool; payload per @pre-commit-review step 3), with one sharpening in the spawn prompt: the justification is the approved plan in hand, not an imagined future — score the extraction as if the feature already existed. REFUTED → apply the cheaper alternative or defer.
Apply the survivors via @refactoring (<preparatory_mode>); full test suite and
lint green after every move; land the prep work as its own commit(s) before the first
RED — the Two Hats at commit granularity, and the reviewer sees reshaping and feature
separately.
Emit a PREPARATION LOG — a record, not a question; the loop continues:
PREPARATION LOG
Touch points surveyed: [files] · findings: N
Applied: [rule → move → commit] (gates: multiply ✓ safe ✓ bounded ✓ skeptic ✓/n-a)
Deferred to Phase 4: [finding — failed gate]
Feature landing shape after prep: [add-only / near-add-only / unchanged]
Zero findings passing the gates is the common case — say so in one line and move on.
Inverse trap: reshaping files the plan does not touch is litter-pickup wearing prep's clothes — a different activity on a different budget; pre-building abstractions this plan does not need is speculative generality — gate 4 exists to kill it.
RED — write ONE failing test for the behavior. Place it by the composition
ladder — the lowest rung that contains the behavior (@testing,
<composition_ladder>). Run it; confirm it fails for the right reason.
If the test resists — fixture surgery, mutating globals to reach the behavior,
driving three layers to observe one seam — do not force it: that friction is a prep
signal Phase 1.5's survey missed. Suspend the cycle, route the friction through the
same four PREPARE gates, apply via @refactoring (<preparatory_mode>), land the prep
commit, re-enter RED. Autonomous, like Phase 1.5 — no user question.
GREEN — minimum code to pass. Explicitly allowed to be ugly; no design polish in this step. Never invoke @code-designing from GREEN: the design already happened in Phase 1 and reaches GREEN through the RED test's shape. If GREEN reveals the design is wrong (a type doesn't fit, a hidden concept emerges): finish the cycle, then route through REFACTOR → @refactoring → its escalation to @code-designing. Design revision is a deliberate checkpoint, never a mid-GREEN detour.
REFACTOR (linter-driven) — on the code just written:
- Package-scoped lint (fast):
golangci-lint run ./<pkg>/... - Cheap rule greps: run the detection commands from the Falsifying questions
sections of the
../../rules/R*.mdfiles relevant to what was written. Any hit → invoke @refactoring: its<routing_table>routes each failure to the owning rule's Fix pattern. The linter says WHAT to refactor; the rules say HOW. Fix now — these findings are mechanical and local: cheapest at this moment, compounding if deferred.
Loop to the next behavior until all behaviors are done.
The agent returns FIXED (mechanical — done) and ESCALATED (design-level, each
with a rule route from its embedded routing table). Route every escalation back
through the Phase 2 REFACTOR step — invoke @refactoring with the routes; never
auto-redesign here. Package-size escalations follow @refactoring
<package_decomposition> (decomposition lands in its own commit). Repeat Phase 3
until the agent reports LINT STATUS: green.
NOT mid-implementation (its <timing> contract): GREEN-step code is supposed to
look under-designed, so reviewing it produces false positives — and the hunters'
fresh-context value only pays on finished work. The REFACTOR-step greps are the
mid-implementation net; this pass is the verification net.
Findings return categorized (Bugs / Design Debt / Readability Debt / Polish), all advisory. Fix bugs and user-accepted findings via @refactoring — except accepted R9 (documentation-network) findings, whose fixer is @documentation — then re-invoke @pre-commit-review in INCREMENTAL mode until the delta reports clean.
Cluster routing: report entries marked 🔗 CLUSTER (≥2 hunters converging on one anchor) are fixed design-first, never member-by-member — partial fixes undo each other (R1 names an enum that R11's move then replaces; R2 places validation that R11's move relocates). Invoke @code-designing in cluster-scoped mode (it skips the architecture scan and the user-OK gate — acceptance was inherited when the cluster's findings were accepted; output is a mini DESIGN PLAN for the one concept the cluster names), then @refactoring implements that plan; the member findings resolve as consequences of one design. Singleton findings route directly to @refactoring as before.