| name | review |
| description | Use when the user explicitly asks for a validation-architecture review of Go code ("review with validation-architecture", "/validation-architecture-review:review"). Does NOT auto-trigger on `.go` files. Review-only and recommendations-only — never edits code or applies fixes unless the user explicitly asks after seeing the findings. Flags violations of opinionated best practices for validation in clean / onion / hexagonal architecture (shape vs. input vs. invariant, value objects, struct separation, error kinds, cross-aggregate rules). |
Validation Architecture Review
Opinionated code review skill for Go, based on best practices for validation in clean / onion / hexagonal architecture. Each rule maps to a detailed file under rules/.
Source synthesis: Alexis King's "Parse, don't validate", Vladimir Khorikov's always-valid domain model series, Microsoft's DDD validation guidance, Damiano Petrungaro's DDD-in-Go work, the verbosemode Go/parse-don't-validate notes, and Martin Fowler's value-object writing.
When to use
This skill is explicit-trigger only. It does not auto-activate on .go files.
Activate when:
- User explicitly types
/validation-architecture-review:review or says something like "review with validation-architecture"
- User asks about a specific rule — load that one file directly
Do not activate when:
- User simply asks to review
.go files in general (use go-proverbs-review, google-go-styleguide, or uber-go-styleguide for that)
- User hasn't asked for this lens specifically
Posture: review-only, recommendations-only
[!IMPORTANT]
This skill never edits code and never applies fixes. Output is a list of findings and recommendations, grouped by rule. If the user wants a fix after seeing the report, they must explicitly ask; at that point, treat the fix as a separate task outside this skill.
This is intentional: the rules are opinionated and some won't fit every codebase. The user is in the loop on every change.
How to use
Reviews run as a parallel fan-out of subagents, one per actionable rule. This keeps the main context small and each check focused on a single principle.
[!IMPORTANT]
Before any subagent fan-out, ASK the user which model to use for the per-rule subagents: opus (highest quality, slowest), sonnet (balanced), or haiku (cheapest, fastest). Wait for their answer — do not pick for them. Pass the chosen model name to every dispatched subagent via the Task tool's model parameter.
Skip this step only for the Single-rule question flow below — it loads one file directly in the main thread, no subagents.
Full review
- Identify the Go files in scope and hold only their paths in the main thread.
- For each
actionable rule in the index, dispatch a subagent with:
- The rule number, short title, and path to
rules/NN-*.md
- The list of
.go file paths to review
- Instruction: load only that one rule file, read the code, return findings in the format
<file>:<line> — <one-sentence observation> or the literal string no findings
- Instruction: do not edit any file; report only
- Dispatch all subagents in parallel (single message, multiple tool calls).
- For
tooling rules, dispatch a single subagent that verifies the tool is configured (e.g. a schema library is wired into every handler) and returns pass/fail — no code findings.
- Skip
philosophical rules entirely — they inform judgment, not findings.
- Aggregate all subagent results, group by rule, and produce the final report (see Output format).
Partial review
If the user asks to check against specific rules ("review for #2 and #4 only"), dispatch only those subagents. Same fan-out pattern, smaller set.
Single-rule question
If the user asks about one rule specifically ("explain #2" / "does this code violate #3?"), skip the subagent fan-out: load the single rule file directly in the main thread and answer.
Why this pattern
- Main context never holds more than one or two rule files at a time
- Each subagent reasons about exactly one principle — fewer false positives
- Parallel execution keeps wall-clock time low
- User can always ask for a partial review to narrow scope further
Categories
| Category | Meaning |
|---|
actionable | Generates findings during review |
tooling | Verify the schema/validator is wired up, don't flag code |
philosophical | Informs judgment, no findings emitted |
Rule index
| # | Rule | Category | Rule file |
|---|
| 1 | Each validation kind lives in its designated layer (shape → transport, input → use-case, invariants → domain) | actionable | rules/01-layer-placement.md |
| 2 | Value objects: unexported fields, New*/Parse* constructor, parse-don't-validate, trusted rehydration, exported constants | actionable | rules/02-value-objects.md |
| 3 | Separate DTO / domain / DB structs; no json:"..." or db:"..." tags on domain types; business rules not encoded in validate:"..." tags | actionable | rules/03-struct-separation.md |
| 4 | Invariant violations → panic/exception; input errors → error or Result | actionable | rules/04-error-kinds.md |
| 5 | Cross-aggregate rules (uniqueness, existence) live in a domain service or DB, never in a VO constructor | actionable | rules/05-cross-aggregate-rules.md |
| 6 | A shape-validation schema is present and wired on every HTTP handler (oapi-codegen / zog / ozzo / hand-rolled) | tooling | rules/06-shape-validation-wired.md |
| 7 | Layered validation is defence-in-depth — some duplication is acceptable | philosophical | rules/07-defence-in-depth.md |
Output format
Group findings under each violated rule:
### Rule #N — <short title>
- path/to/file.go:42 — <one-sentence finding>
- path/to/file.go:87 — <one-sentence finding>
See: rules/NN-<slug>.md
End the review with a summary line: total findings, number of distinct rules violated, files touched.
Conclude with an explicit note:
These are recommendations. No files have been modified. If you'd like me to apply any of these, tell me which rules / files and I'll do it as a separate task.