Imported from leocosta/octopus (
skills/audit-style/SKILL.md). Install upstream withnpx skills add leocosta/octopus --skill audit-style. Copyright stays with the author.
Design-Rules Style Audit
Overview
A formatter, a type checker, and a secret scanner judge syntax — and
the native simplify applies generic taste. Neither knows the team's
opinionated rules: that a custom exception must clear a gate before it
earns its existence, that an expected failure should be a typed result and
not a throw, that a boolean parameter wants an options object, that
abstraction is a cost to be paid only at the third occurrence. Those are
the rules a human agreed to and wrote down; the only thing that can judge
conformance is a reader holding the rules in one hand and the diff in the
other.
audit-style is that reader. It loads the design rules the repo already
ships and confronts the diff against them, emitting two kinds of finding:
rule-violation— a construct the diff introduces that contradicts a stated rule: a custom exception that fails the gate, a throw where a typed result is called for, a boolean parameter, a magic number, a missing guard clause, business logic leaking into a repository, a swallowed exception.over-engineering— abstraction the rules explicitly call a cost: premature abstraction, a speculative subtype hierarchy "for the future", DRY applied before three occurrences, an indirection layer for a problem that does not exist yet. This is the dimension the nativesimplifystructurally cannot produce — it optimizes for less code and may itself introduce the abstraction the rules forbid.audit-styleis the reader that knows when not to simplify.rigidity— the opposite failure, invisible to the rules alone: a concept spread across several files, so every extension edits all of them. Never a judgment call — emitted only on measured evidence fromoctopus git-signals(co-change over real git history).
The last two are one ruler: abstraction without co-change is premature abstraction; co-change without abstraction is rigidity. One measurement decides both, which keeps the audit from arguing taste against taste.
The skill is signal-only: it never blocks a commit, a task, or a merge. A design verdict is a judgment call, and blocking on a judgment call is worse than the problem it solves. It reports; the human decides.
When to Engage
Engage when:
- A review flow invokes it —
codereview,pr-review, or theimplementsimplify pass — to check the diff against the house rules before merge. - A reviewer wants a rules-grounded second read that the generic
simplifycannot give, especially to catch over-engineering.
Do not engage for:
- Syntactic concerns — formatting, type errors, secrets. Those are the
guardrailsbundle's job (pre-commit + loop-level hooks) and they block; this skill does not duplicate them. - The domain source of truth — invented conventions and unsupported domain
facts are
audit-grounding's job.audit-stylejudges the diff against the coding rules, not the domain. - Generic, rule-agnostic cleanup — that is the native
simplify. This skill adds the house-rules layer on top; it does not replace it.
The Source of Truth
Load, in order, and degrade gracefully when an artifact is absent:
exceptions.md— the custom-exception gate (the default-to-stdlib rule, the G1/G2/G3 justification gate, the forbidden smells) and the "delete the class when the last catch site goes" rule. The primary reference for exception-relatedrule-violationfindings.rules/common/patterns.md— the architecture conventions: Result pattern for expected failures, repository/service separation, guard clauses, event-handling idioms.rules/common/coding-style.md— naming, code-structure, and the anti-pattern catalogue (god functions, magic numbers, boolean parameters, premature abstraction, copy-paste).- The active stack rules — any
rules/<stack>/*.md(e.g.rules/csharp/error-handling.md) matching the languages the diff touches, plus a project-local*.local.mdoverride where present.
When a rules file is missing, fall back to the ones present and report the
absence as an info note so the team knows the audit was partial.
Protocol
-
Scope the diff. Use the same ref discovery the other
audit-*skills use (working tree, a branch, or a PR ref). Restrict attention to changed lines and the files they touch. -
Load the rules in the order above, selecting the stack rules that match the changed files' languages.
-
Hunt rule violations. For each construct the diff introduces, check it against the rules. A new
class XExceptionis checked against the exceptions gate (is there a catch site of this type? a structured field an operator reads? does a stdlib type fail to express it?); a throw on an expected failure against the Result-pattern rule; a boolean parameter, a magic number, a deeply nested conditional, business logic in a repository againstcoding-style.md/patterns.md. Emit arule-violationfinding citing the diff location and the exact rule it breaks. -
Hunt over-engineering. For each abstraction the diff adds — a new interface with one implementation, a subtype hierarchy with empty members, an extraction at the second occurrence, an indirection with no present caller — check it against the YAGNI / "three occurrences before extracting" / "speculative hierarchy is forbidden" rules. Emit an
over-engineeringfinding. When in doubt, prefer flagging the abstraction over flagging its absence — the rules treat abstraction as the cost. -
Measure rigidity. Run
octopus git-signals --base <base> --ref <ref>— deterministic, git-only, ~0 tokens. For each cluster returned, emit onerigidityfinding carrying evidence only: the cluster members with their churn, which of them the diff touched,support,cohesion,window_days, andenlarges.Anchor on one real diff line — the outsider path that enlarges the cluster, or the touched member with the highest churn — and carry the other members as evidence text;
pr-reviewPhase 4.5 demotes what it cannot anchor. Do not name a principle or a pattern here — that isarchitect's job (see Model tier). Ifstatus:is notok, emit oneinfonote naming the reason and no finding: absence of evidence is never reported as zero. -
Report. Emit findings in the same severity-tiered shape as
audit-all, but capped atwarn/info— neverblock. State explicitly in the report header that the audit is signal-only.
Report Shape
Mirror audit-all's tiered report, with the blocking tier disabled:
warn— a clear divergence from a stated rule the human should resolve before merge (an exception that fails the gate; a speculative hierarchy; a swallowed exception).info— a weaker signal or a partial-rules note (a borderline abstraction that may be justified; a magic number in throwaway code; a rules file missing).
Each finding names the diff location, the finding type (rule-violation /
over-engineering / rigidity), the rule it was checked against (file + the
specific clause) or, for rigidity, the measured evidence line, and a one-line
"what to change". End with a trailer line:
audit-style: 0 block, N warn, N info. The audit emits no block tier by
design — including for rigidity, whose merge verdict belongs to architect.
A rigidity finding reads:
warn · rigidity · payments/providers/pix.ts:14
cluster: 3 files, support:8 cohesion:0.86 window:90d enlarges:true
payments/providers/index.ts churn:47 touched
payments/config/registry.ts churn:39 touched
payments/providers/boleto.ts churn:31
This diff touches 2 members of the cluster and adds a third path to it.
Rigidity configuration
The rigidity evidence comes from octopus git-signals, which needs no config
to run — every value below has a built-in default. Tune per repo in
.octopus.yml, with the same layering as code_metrics:
(workspace < personal < project; the committed repo state wins):
git_signals:
cochange:
window_days: 90 # git history lookback
min_support: 5 # a pair must co-occur at least this often
min_cohesion: 0.6 # Jaccard: support / (commits(a)+commits(b)-support)
min_cluster: 3 # a pair is not a cluster; three files are
max_files_per_commit: 25 # wider commits are mass renames, not evidence
max_findings: 1 # findings about THIS change, not ambient debt
max_findings is the noise control: clusters rank enlarges first, then
support, then size, and only the top N are reported. Raising it is how this
audit becomes a wall of ambient debt nobody reads.
Anti-Patterns
- Blocking on a finding — forbidden; this skill is signal-only.
- Flagging syntactic issues the
guardrailsbundle already blocks, or domain divergencesaudit-groundingowns. - Re-applying generic taste the native
simplifyalready covers — only surface what a rule actually says. - Manufacturing a violation when the rules do not cover the construct — say
"not covered" (
info), do not invent awarn. - Recommending an abstraction the rules call premature — this skill exists
partly to push back on over-abstraction, not to add it. A
rigidityfinding is not an exception: it reports measured co-change, it does not prescribe a pattern. - Emitting a
rigidityfinding without agit-signalscluster behind it, or reporting "no rigidity" whenstatus:was notok. - Editing the rules or the diff — the skill is read-only.
Integration with Other Skills
- native
simplify— applies generic, rule-agnostic taste and edits the code.audit-styleruns the house-rules layer on top and only signals. Division of labour, not competition. audit-grounding— sibling signal-only audit; it judges the diff against the domain source of truth, this one against the coding rules. Same report shape, same never-block discipline.refactor-deepen— deepens design (improves architecture);audit-stylesignals where the diff diverges from the rules.codereview/pr-review/implement— the orchestrators that invoke this skill; it has no Stop hook of its own.continuous-learning/review-proposals— recurringaudit-stylefindings feed the existing knowledge loop as rule / CLAUDE.md candidates, so a violation the team keeps making is promoted into a rule rather than re-flagged forever.guardrailsbundle — owns the syntactic, blocking layer this skill deliberately does not duplicate.
Model tier
This audit is mechanical — it pattern-matches a diff against a fixed
checklist, not deep reasoning. Run it on the cheapest model tier
(--model haiku / each assistant's cheapest). Reserve frontier models
for the architect/dba/security roles that adjudicate the findings
(RM-130).
That split is why rigidity findings carry evidence and no vocabulary: naming
the SOLID principle and the pattern is domain reasoning, so it belongs to
architect on the frontier tier — which also stops the cheapest tier from
inventing a pattern name that only loosely fits.