Aposd audit
Strategic software design guidelines for AI coding agents. 15 behavioral rules + critique/audit commands based on A Philosophy of Software Design by John Ousterhout.
npx -y skills add mhenke/john-ousterhout-skills --skill aposd-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Quantitative design audit. Counts pass-throughs, duplication, doc gaps, naming issues, and exceptions across 5 dimensions, scored 0-4.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
17.3 KB, as published. Nobody here has run it
aposd audit — Design Quality Audit
Run systematic design quality checks and generate a comprehensive report. Don't fix issues; document them for review.
This is a code-level design audit — check what's measurable and verifiable in the implementation. Every dimension is scored by counting concrete, observable constructs. Fix the count → score goes up, every time.
Follows the impeccable audit convention: measure what's objectively countable, not what's interpretive.
Scoring rubric: Score each dimension 0-4. Total /20. Rating bands: 18-20 Excellent, 14-17 Good, 10-13 Acceptable, 6-9 Poor, 0-5 Critical.
Quick Start
aposd audit src/ # audit a directory
aposd audit src/services/order-service.js # audit a single file
aposd audit # defaults to workspace root
The report is printed to stdout.
Scope
This skill audits a single codebase target per invocation. It measures 5 design dimensions by counting observable constructs — pass-throughs, duplication, documentation gaps, naming issues, and exception patterns. It does not evaluate functional correctness, runtime performance, or test coverage. Each dimension is scored 0-4 from concrete evidence only.
What this skill does NOT cover:
- Functional correctness — does the code produce the right output?
- Runtime performance — how fast does it execute?
- Test coverage — are there enough tests?
- Security vulnerabilities — are there injection flaws or auth gaps?
- Code style / formatting — does it follow lint rules?
- Architectural fitness — are you using the right pattern for the job?
- Business logic completeness — are all requirements implemented?
Setup
Resolve the target to a concrete file path, directory, or module name. If no target is specified, default to the current workspace root directory.
Full scan: Scan all files in the target — no sampling. For large targets (>50 files), use sub-agents to parallelize the scan across directory groups.
Input / Output
- Input — A file path, directory, or module name to audit. Defaults to workspace root if omitted.
- Output — A structured Design Health Score (/20) across 5 dimensions, with per-finding evidence counts and P0-P3 severity tags.
Quick Reference
| Dimension | Counts | Score 0-4 |
|---|---|---|
| Pass-Through Proliferation | Pass-through methods + variable chains | 4=0, 3=1-2, 2=3-5, 1=6-10, 0=10+ |
| Information Duplication | Same knowledge in multiple modules | 4=0, 3=1-2, 2=3-4, 1=5-7, 0=8+ |
| Interface Documentation | % of public methods documented | 4=90%+, 3=70-89%, 2=40-69%, 1=10-39%, 0=<10% |
| Naming Quality | Vague names + convention violations | 4=0, 3=1-2, 2=3-5, 1=6-10, 0=10+ |
| Exception Discipline | Custom exceptions + catch-and-rethrow | 4=0 custom, 3=1-2, 2=3-5, 1=6-10, 0=10+ |
Audit discipline
- Count only concrete, observable constructs. If you cannot point to file:line:pattern, do not count it.
- For each score, explain why the count maps to the rubric and what design debt the count represents.
- When the target is large (>50 files), use sub-agents to parallelize scanning across directory groups. Report total files scanned.
- Prefer clustered root causes over scattered one-offs when they are the same design decision repeated.
- Keep the report objective: the point is to measure design quality, not to narrate an opinion.
When Not to Use
- For qualitative design philosophy questions — use
aposd critiqueinstead - For code review (bugs, style, typos) — audit measures design metrics, not correctness
- For codebases you can't modify — the value is in tracking improvement over time
- For runtime performance analysis — use a profiler, not a static design audit
- For one-off scripts under 50 lines — design patterns haven't had time to accumulate
Diagnostic Scan
Run comprehensive checks across 5 dimensions. Score each dimension 0-4 by counting concrete, observable constructs.
1. Pass-Through Proliferation
Count: Pass-through methods (method body only delegates to another method with the same signature) + pass-through variable chains (context/config threaded through methods that don't use it).
Score 0-4:
- 4: 0 pass-through constructs found
- 3: 1-2 isolated pass-through methods
- 2: 3-5 pass-through methods OR 1 pass-through variable chain
- 1: 6-10 pass-through methods OR 2+ variable chains
- 0: 10+ pass-through methods OR any pass-through chain (A→B→C)
Calibration:
- ✓ Counts:
getUser()body is exactlyreturn this.db.fetchUser(id) - ✓ Counts:
handleClick(e)body isthis.onClick(e)with nothing else - ✓ Counts:
processData()→transformData()→applyRules()where middle just calls the next - ✓ Counts:
configthreaded through 5 methods that only pass it to a 6th that uses it - ✗ Doesn't count: method adds validation, logging, or error handling around the delegate
- ✗ Doesn't count: method transforms args (e.g.,
return this.db.query(normalize(id))) - ✗ Doesn't count: method combines multiple delegates (e.g.,
a(x); return b(y))
2. Information Duplication
Count: Instances where the same design knowledge (URL paths, schema fields, business rules, configuration keys, magic strings/numbers) appears in multiple independent modules. Count each distinct piece of knowledge that's duplicated.
Score 0-4:
- 4: 0 instances of duplicated knowledge
- 3: 1-2 isolated instances
- 2: 3-4 instances
- 1: 5-7 instances
- 0: 8+ instances or a systemic pattern (same rule in 5+ files)
Calibration:
- ✓ Counts:
"SELECT * FROM orders WHERE status = 'active'"in user-service.js and order-service.js - ✓ Counts:
MAX_RETRIES = 3defined in retry.js and again in network-client.js - ✓ Counts:
"orders_expire_after_days": 30in both config schema and validation logic - ✗ Doesn't count: common import (
import React from "react") — that's a dependency, not leakage - ✗ Doesn't count: function
formatDate()called from multiple modules — that's normal usage - ✗ Doesn't count: same error message string used in a try/catch and a test assertion
- ✗ Deduplicate: only count each distinct piece of knowledge once, even if spread across 5+ files
3. Interface Documentation
Count: Number of public methods/functions without interface comments. Report as both count and percentage of total public methods.
Score 0-4:
- 4: ≥90% of public methods documented
- 3: 70-89% documented
- 2: 40-69% documented
- 1: 10-39% documented
- 0: <10% documented
Calibration:
- ✓ Counts as documented: has a JSDoc/comment block describing what the method does, its parameters, or its return value
- ✓ Counts as undocumented: public method with only a
// TODOor inline comment, or no comment at all - ✗ Doesn't count: private/internal methods — only public/protected interface
- ✗ Doesn't count: getters/setters that only read/write a field — skip these from the total
- ✗ Doesn't count: comments that only repeat the method name (
/** Get user */ getUser())
4. Naming Quality
Count: Identifiers matching the vague names blocklist — data, info, tmp, handle, process, util, helper, manager, stuff, thing. Also count violations of project naming conventions (inconsistent casing, mixed patterns).
Score 0-4:
- 4: 0 vague names, consistent conventions
- 3: 1-2 vague names, minor inconsistency
- 2: 3-5 vague names or inconsistent conventions
- 1: 6-10 vague names or project-wide naming inconsistency
- 0: 10+ vague names or no discernible naming convention
Calibration:
- ✓ Counts:
data,info,tmp,handle,process,util,helper,manager,stuff,thingused as function names, class names, or variable names - ✓ Counts:
camelCaseandsnake_casemixed in the same module - ✓ Counts:
UserServiceanduser_servicereferring to the same concept - ✗ Doesn't count:
dataas a parameter in a generic utility (e.g.,JSON.parse(data)) — context matters - ✗ Doesn't count:
tmpin a 3-line test helper scoped to a single function
5. Exception Discipline
Count: Custom exception/error classes defined (not standard library types). Count catch blocks that only re-throw, log, or swallow the same exception type.
Score 0-4:
- 4: 0 custom exception types, clean handling
- 3: 1-2 custom exceptions, no catch-and-rethrow patterns
- 2: 3-5 custom exceptions or 1-2 catch-and-rethrow
- 1: 6-10 custom exceptions or 3-5 catch-and-rethrow
- 0: 10+ custom exceptions or 5+ catch-and-rethrow
Calibration:
- ✓ Counts:
class UserNotFoundError extends Error {}— custom exception class - ✓ Counts:
class PaymentError extends Error { constructor(code, msg) { super(msg); this.code = code; } }— custom with extra fields - ✓ Counts:
try { ... } catch (e) { throw new ApiError(e.message); }— catch-and-rethrow - ✓ Counts:
try { ... } catch (e) { log(e); throw e; }— log-and-rethrow - ✗ Doesn't count: using built-in
Error,TypeError,RangeErrordirectly — only count custom subclasses - ✗ Doesn't count:
try { ... } catch (e) { return defaultValue; }— that's masking, not rethrowing - ✗ Doesn't count: catch block at module boundary that transforms for the caller (
catch (e) { throw new ApiError(500, e.message); }) — that's proper masking
Generate Report
Design Health Score
Score each dimension 0-4. Every score must cite both the rubric criterion and the code evidence:
| # | Dimension | Score | Key Finding | Evidence |
|---|---|---|---|---|
| 1 | Pass-Through Proliferation | ? | Count found | File:line:pattern cited |
| 2 | Information Duplication | ? | Count found | File:line:pattern cited |
| 3 | Interface Documentation | ? | % documented | File:line:pattern cited |
| 4 | Naming Quality | ? | Count found | File:line:pattern cited |
| 5 | Exception Discipline | ? | Count found | File:line:pattern cited |
| Total | ??/20 | [Rating band] |
Tactical Tornado Risk
Assess based on red flag counts found across the 5 dimensions:
- Low: 0-1 dimensions scored ≤2, no systemic patterns
- Medium: 2-3 dimensions scored ≤2, or 1-2 systemic patterns
- High: 4+ dimensions scored ≤2, or pervasive pass-throughs/leakage
Executive Summary
- Design Health Score: ??/20 ([rating band])
- Tactical Tornado Risk: [Low / Medium / High]
- Total issues found (count by severity: P0/P1/P2/P3)
- Top 3-5 critical issues
- Recommended next steps
Detailed Findings by Severity
Every finding must pass the Specificity Validation Gate. Tag with P0-P3 severity:
- P0 Blocking: Prevents task completion. Fix immediately
- P1 Major: Significant complexity increase. Fix before next milestone
- P2 Minor: Notable but local. Fix when in the area
- P3 Polish: Worth fixing, no urgency
For each issue, document:
- [P0/P1/P2/P3] Issue name
- Location: Component, file, line
- Dimension: Pass-Through / Duplication / Documentation / Naming / Exceptions
- Count: How many instances found
- Impact: How it affects future development
- Recommendation: Concrete action (not "consider refactoring")
Patterns & Systemic Issues
Identify recurring problems that indicate systemic gaps rather than one-off mistakes:
- "Pass-through methods appear in every service layer class — 14 total across 6 files"
- "The business rule 'orders expire after 30 days' is embedded in 5 different modules"
Positive Findings
Note what's working well: dimensions scoring ≥3, clean patterns that prevent complexity. Be objective — explain precisely why they reduce change amplification or cognitive load.
Worked Example — OrderService Module
Given a target at src/services/, the audit report would look like:
| # | Dimension | Score | Key Finding |
|---|-----------|-------|-------------|
| 1 | Pass-Through Proliferation | 2 | 4 pass-through methods found (findById→repo.findById, etc.) |
| 2 | Information Duplication | 1 | "expired_at" threshold defined in 3 places |
| 3 | Interface Documentation | 3 | 70% of public methods documented |
| 4 | Naming Quality | 3 | 2 vague names ("data", "helper") |
| 5 | Exception Discipline | 4 | 0 custom exceptions, no catch-and-rethrow |
| **Total** | | **13/20** | **Acceptable** |
**Tactical Tornado Risk:** Medium — pass-through proliferation across service layer is a systemic pattern.
This is illustrative. Your output will follow this structure but reflect the actual target's counts.
Copy-Paste-Ready Audit Template
See scripts/audit-report-template.md for the standalone template that can be reused programmatically. Copy it and fill in your findings — each ?, __, [ ] placeholder maps to your actual counts.
Specificity Validation Gate
Before reporting any finding, self-validate:
□ File path (absolute or relative to target)
□ Line number(s)
□ Code pattern (exact snippet, 1-3 lines)
□ Dimension (Pass-Through / Duplication / Documentation / Naming / Exceptions)
□ Count (how many instances)
□ Recommendation (concrete action)
Missing any field → finding is discarded.
No rubber-stamps. A score of 20/20 with no evidence counts per dimension is not a valid audit. Every score must cite the count behind it. If you catch yourself writing a score without evidence, stop and restart the gate check.
Stop-and-return. If you find yourself writing a finding without a file:line:pattern or count, do not continue. Stop. Restart the validation gate for that finding. An unverifiable finding is noise, not signal.
Passing example:
□ File path: src/services/user-service.js
□ Line number(s): 42-48
□ Code pattern: "SELECT * FROM orders WHERE user_id = ?" built inline, same query in order-service.js:87
□ Dimension: Information Duplication
□ Count: 2 instances of the same SQL pattern
□ Recommendation: Extract into OrderRepository.findByUserId(userId)
Recommended Actions
List recommended actions in priority order (P0 first, then P1, then P2):
- [P0/P1/P2/P3]: Brief description with file:line:pattern (specific context from audit findings)
- ...
After presenting the summary, tell the user:
To fix using APOSD design principles, load the
aposdskill. It applies the 15 APOSD behavioral rules during implementation. Address findings in the priority order above. Each finding is tagged with its affected dimension so you can focus on one area at a time.Re-run
aposd auditafter fixes to see your score improve.
IMPORTANT: Be thorough but actionable. Too many P3 issues creates noise. Focus on what actually matters.
Troubleshooting
See references/troubleshooting.md for a comprehensive troubleshooting guide covering common problems, recovery procedures, error handling patterns, and edge cases.
Common Mistakes
See references/troubleshooting.md for common audit mistakes and how to avoid them.
Red Flags — STOP and Start Over
- Scoring a dimension without citing a count
- Reporting a finding without file:line:pattern
- Tagging everything as P0
- Reporting a finding that hasn't passed the Specificity Validation Gate
- Leaving a dimension unscored or marked "N/A"
- Recommending "consider refactoring" instead of a concrete action
- Judging design quality instead of counting measurable constructs
NEVER:
- Report issues without a count (how many instances?)
- Provide generic recommendations (be specific and actionable)
- Skip positive findings (document objective strengths)
- Forget to prioritize (everything can't be P0)
- Report false positives without verification
Code Templates
Full Audit Workflow
See examples/full-audit-workflow.sh for a copy-paste-ready bash script that runs the complete audit pipeline.
Python: Parse Audit JSON Output
import json, sys
with open(sys.argv[1]) as f:
report = json.load(f)
dimensions = report.get("dimensions", {})
total = sum(d["score"] for d in dimensions.values())
print(f"Design Health Score: {total}/20")
for name, dim in dimensions.items():
grade = "Excellent" if dim["score"] >= 4 else "Good" if dim["score"] >= 3 else "Acceptable" if dim["score"] >= 2 else "Poor"
print(f" {name}: {dim['score']}/4 ({grade}) — {dim['count']} instances at {dim['locations'][0] if dim['locations'] else 'N/A'}")
Copy this script, point it at the JSON output of aposd audit --output json, and it prints a summary.
Example Report
See examples/example-audit-report.md for a complete, filled-in audit report showing all sections with real findings, severity classifications, and recommendations.
Related
- aposd — Always-on behavioral rules
- aposd-critique — Design critique command
- references/ — Extended troubleshooting, common mistakes, edge cases
- scripts/ — Audit report template
- examples/ — Copy-paste-ready workflow scripts and example reports