| name | linter-driven-development |
| description | META ORCHESTRATOR for any Go code change that should end in a commit (features, bug fixes, refactors).
WHEN: User requests Go code work (implement, fix, add, refactor), mentions "@ldd"/"ldd", or runs a /go-ldd-* command in a Go project.
Runs the five-phase workflow (PREPARE is an autonomous sub-phase, 1.5): DESIGN → PREPARE → IMPLEMENT (per-behavior TDD loop) → FULL LINT (lint-fixer agent) → REVIEW (per slice) → SHIP.
|
| allowed-tools | ["Skill(go-linter-driven-development:code-designing)","Skill(go-linter-driven-development:testing)","Skill(go-linter-driven-development:refactoring)","Skill(go-linter-driven-development:pre-commit-review)","Skill(go-linter-driven-development:documentation)","Task"] |
Top-level protocol for Go implementation work: five phases plus the autonomous
PREPARE sub-phase (1.5), where Phase 2 is a per-behavior TDD loop. Rule knowledge lives once in `../../rules/` — this skill never
restates it; it sequences the thin skills (which dispatch into the rules) and the
lint-fixer agent, at the cadence each check's economics demand.
- User requests Go code work (implement, fix, add, refactor, update, change) and the
project is Go (`go.mod` or `.go` files present)
- User mentions "ldd" or "@ldd"
- A `/go-ldd-*` command invokes this skill
On trigger, announce: **"Using go-ldd workflow for this Go code work"** and run pre-flight.
<skill_invocation>
"Invoke @skill-name" means: call the Skill tool. Never just mention the skill,
never read its file directly.
| 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 Task tool:
subagent_type: "go-linter-driven-development:lint-fixer".
</skill_invocation>
```
1 DESIGN @code-designing → DESIGN PLAN → user OK
1.5 PREPARE survey plan's touch points → four gates decide autonomously →
(@refactoring, preparatory mode) → prep commit(s) · PREPARATION LOG (record, no stop)
2 IMPLEMENT — per behavior:
┌─> RED one failing test, lowest rung (@testing)
│ test resists? → prep signal → @refactoring (preparatory) → re-enter RED
│ GREEN minimum code to pass — no design work
│ REFACTOR pkg-scoped lint + rule greps; hits → (@refactoring)
└── next behavior until all done
3 FULL LINT ONE run via lint-fixer agent (Task)
mechanical → FIXED · design → ESCALATED → back to 2's REFACTOR
4 REVIEW per completed slice: @pre-commit-review → fix → INCREMENTAL re-run
5 SHIP @documentation → commit summary → user commits
```
<pre_flight>
- Verify Go project:
go.mod in 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.
</pre_flight>
<phase_1_design>
Invoke @code-designing. It runs the architecture scan, scores candidate domain types,
records an R4 placement decision for every helper/type, and presents a DESIGN PLAN
for user OK. Do not start Phase 2 until the user approves the plan — the RED
tests target this designed public API, which is how the design reaches GREEN.
</phase_1_design>
<phase_1_5_prepare>
Preparatory refactoring (Fowler: "make the change easy, then make the easy change"):
reshape what the approved plan is about to touch, BEFORE the first RED, so the
feature lands as add-only. Runs autonomously — the four gates below decide;
this phase never asks the user.
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 -cover on 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 (Task; 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.
</phase_1_5_prepare>
<phase_2_implement>
One TDD cycle per behavior:
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*.md files 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.
</phase_2_implement>
<phase_3_full_lint>
Delegate ONE full lint run to the lint-fixer agent (Task, isolated context — the
fix loop's token noise stays out of this conversation). Full-repo lint catches what
package-scoped runs cannot: cross-package issues and whole-file/whole-package rules
(file-length-limit, package-size zones).
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.
</phase_3_full_lint>
<phase_4_review>
Per completed vertical slice (multi-slice work reviews each slice as it completes),
invoke @pre-commit-review — it orchestrates parallel rule hunters plus the
over-abstraction skeptic; it spawns agents and reports, never edits.
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.
</phase_4_review>
<phase_5_ship>
- Invoke @documentation (FEATURE mode): godoc + feature docs, wired into the
documentation network (index line, edges both directions, root import), plus its
R9 self-check over the diff.
- Present the ship summary: tests green (
go test ./...), lint green (Phase 3),
review delta (Phase 4), files changed, suggested commit message.
- User decides: commit as-is · fix deferred advisory findings first · defer.
</phase_5_ship>
<success_criteria>