agentleFS
jamestexasjamestexas/agents/skills/self-audit/SKILL.md

self-audit

Skill2 starsChanged 6 months agoApache-2.0View on GitHub

Pre-review self-audit of a PR branch: dead struct fields, rotting comments, duplicate types, scope drift — what a human catches but a compiler won't — then dispatches an adversarial agent for deeper design flaws. Use before tagging a reviewer, or after a self-directed refactor.

6 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

11 rules. 0 are common, 10 are distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 6 edited versions we read keep these.

  • 10

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Check your own PR like a grumpy reviewer would, before one sees it.

    line 14
  2. Distinctive:

    After addressing review feedback, before asking a reviewer to look again.

    line 21
  3. Distinctive:

    After a significant self-directed refactor, before creating the PR.

    line 22
  4. Distinctive:

    Read the list. For every file, ask: *did I intend to change this?* If anything looks surprising — generated files, unrelated packages, …

    line 37
  5. Distinctive:

    Delete the field, its extractor, and that test.

    line 56
  6. Distinctive:

    Subtests vs table-driven: test preferences.

    line 139
  7. Distinctive:

    If your org runs a policy bot in CI that checks project-specific rules, the CLAUDE.md / convention docs are the local source of truth the …

    line 141
  8. Distinctive:

    Running the audit, finding nothing, and declaring victory: If the adversarial agent in step 7 also says clean, that's fine.

    line 179
  9. Very specific:

    If ~/.claude/skills/self-audit/extensions.md exists, read and follow it at the start of Step 6 (project convention check).

    line 197
  10. Distinctive:

    Never at risk of being committed to a public skills repo.

    line 205
  11. Distinctive:

    If the extensions file is absent, step 6 is just the generic convention review — the skill degrades gracefully.

    line 210

“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

self-audit — Pre-review quality pass

Check your own PR like a grumpy reviewer would, before one sees it.

Your compiler or type-checker and your linter catch the easy stuff. This skill catches the grown-up stuff that slips past both of them.

When to use

  • After addressing review feedback, before asking a reviewer to look again.
  • After a significant self-directed refactor, before creating the PR.
  • Any time you feel "done" but want a second opinion that isn't a human.

Arguments

$ARGUMENTS — optional base branch name. Defaults to main.


Step 1 — Scope sanity

git diff --stat <base>...HEAD

Read the list. For every file, ask: did I intend to change this? If anything looks surprising — generated files, unrelated packages, formatter drift — stop and investigate before continuing. The rest of this audit is wasted effort if scope is wrong.

Step 2 — Dead struct fields

A field that is written but never read is dead code, and unused-symbol linters do not catch it — golangci-lint unused counts a field as used as long as it appears on either side of an =, and most other languages' equivalents behave the same way.

For every struct field you added, confirm there is a read site outside the place it is written. If the only references are:

  • the extractor/constructor that populates it, and
  • a test that asserts "this field is non-empty",

...that is circular — the test verifies the field exists, and nothing else cares. Delete the field, its extractor, and that test.

# Rough heuristic — greps for every .FieldName use:
rg '\.FieldName\b' --stats

A real non-test, non-self reader is required.

Step 3 — Comments that rot

Comments die when they reference context that fades. Scan for patterns that will be meaningless in six months:

rg -n '@\w+|comment #|round \d+|per the review|commit [0-9a-f]{7,}|\.\w+:\d+|renamed from|formerly|was previously|intentionally|rather than' <changed-files>

For each hit ask: will this comment make sense to someone who never saw the PR thread? If no, rewrite. State what the code does, not how it got this way.

Worst offenders, in order of how badly they age:

  • Reviewer names in comments ("added per X's suggestion"). People rotate; comments survive.
  • Cross-file line numbers ("covers foo.go:123"). Rot the moment anything moves.
  • Historical framings ("renamed from X", "formerly Y", "not Z anymore"). Description by negation tells a future reader about a past they don't have.
  • "Intentionally" / "deliberately" as defensive filler. If the reason is worth saying, say the reason without the hedge.
  • "X rather than Y" where Y never existed in the repo. Compare to alternatives that were actually considered, not to everything you didn't do.

Step 4 — Duplicate or parallel types

# Types with identical field sets (Go shown — swap in your language's
# declaration syntax: class/interface/dataclass/type):
rg -U 'type \w+ struct \{[^}]+\}' <pkg> | sort | uniq -c | awk '$1 > 1'

Weaker heuristic that catches more: any time you have an exported and an unexported type with the same shape in the same package, ask "what does exporting buy me that an accessor method wouldn't?" If the answer is nothing, merge them.

Step 5 — Test-only exports

Exported API that only has test callers is either dead or wishful.

For each exported function/method/type added:

# Callers outside test files AND outside the defining file
# (adjust the test-file pattern to your language's convention):
rg -l '\bFunctionName\b' | rg -v '(_test\.go|_test\.py|test_.*\.py|\.(test|spec)\.[jt]sx?)$' | rg -v '<defining-file>'

Zero results → it's exported for future use that may never come. Make it unexported unless the future use is imminent.

Step 6 — Project convention check

Most repos state conventions outside the linter config — CLAUDE.md, AGENTS.md, CONTRIBUTING.md, .cursorrules, team memory files. Generic linters catch what's universal; these files catch what's local. Read them and check your diff against them.

# Skim project conventions before checking:
head -200 CLAUDE.md AGENTS.md CONTRIBUTING.md .cursorrules 2>/dev/null

Classes of convention that generic linters miss:

  • Test idioms tied to the Go/language version (e.g. t.Context() over context.Background() in Go 1.24+ repos).
  • Error wrapping conventions (%w vs %v; when to wrap).
  • Log framework preferences (project-specific choice of slog / zerolog / internal logger).
  • Import-grouping rules beyond what goimports enforces.
  • Private-type + exported-interface return patterns.
  • Subtests vs table-driven test preferences.

If your org runs a policy bot in CI that checks project-specific rules, the CLAUDE.md / convention docs are the local source of truth the bot is mirroring. A hit here saves a CI round-trip.

Step 7 — Adversarial agent pass

This is the highest-leverage step and the one you will most want to skip. Don't skip it.

Dispatch an adversarial agent on the diff. A prompt that works:

Here is the diff for branch <branch> against <base>. Find the fatal disconnect between what the commits claim and what the code actually does. Be mean. Do not give me a sandwich review. If you find nothing, say "clean" — do not manufacture concerns.

Agents worth using for this:

  • paradigm-assessor — pure adversarial greybeard. Best default.
  • production-readiness-reviewer — framed around ship-blockers.
  • A general-purpose subagent with the prompt above.

The agent will either:

  • Find something you missed → fix it.
  • Say clean → push with confidence.
  • Raise something wrong → defend your position clearly in writing. That rehearsal is worth more than the finding itself, because you will use it verbatim when the real reviewer asks the same question.

Outputs

This skill produces no artifacts. Findings go straight into commits that fix them, or are explicitly waived (with reasoning) before pushing. Do not write a "self-audit report" file — the commits are the report.

Anti-patterns to avoid

  • Running the audit, finding nothing, and declaring victory. If the adversarial agent in step 7 also says clean, that's fine. If you skipped step 7 because steps 1-6 looked good, you have not actually audited.
  • Amending previous commits to fold findings in. The stack should still be readable as a sequence of decisions. New commit per finding.
  • Hiding the audit in a side branch and squashing away the evidence. The fact that you caught and fixed something is information for the next person (including future you).

Project-specific extensions (optional)

The steps above are deliberately generic so this skill works in any repo. For invocations tied to a specific work environment — internal style bots, generated-code verifiers, API-compatibility checkers, policy gates — keep them out of this SKILL.md and in a private extension file.

Convention

If ~/.claude/skills/self-audit/extensions.md exists, read and follow it at the start of Step 6 (project convention check). The extensions file layers environment-specific checks on top of the generic convention review.

Why this path:

  • Lives in the user's personal Claude config, not in any git repo.
  • Never at risk of being committed to a public skills repo.
  • Survives re-clones and migrations of the agents repo.
  • Mirrors the skills/<name>/ structure so multiple skills can each have their own extensions file without collision.

If the extensions file is absent, step 6 is just the generic convention review — the skill degrades gracefully.

Example extension hooks worth adding

  • A local runner for a CI-side policy bot (so you catch issues before push).
  • A diff-vs-memory comparison (check your diff against rules stated in repo-level CLAUDE.md or team memory files).
  • Repo-specific dead-code detectors (e.g. proto field usage scanners, Terraform variable reachability checks).
  • Credential/secret sweeps specific to the org's token shapes.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.