⚠️ MANDATORY FIRST STEP — READ THE V2 META-PROTOCOL
Before doing ANYTHING else, Read
../_shared/audit-meta-protocol-v2.md.That file overrides any conflicting guidance below for these five aspects:
- Required CLI inputs (
--user-need,--hingeare MANDATORY since 2026-05-08)- Required JSON output schema (v2: score + confidence + falsifiable_tests + user_need_match + hinge_findings)
- Popper falsification — every PASS must cite ≥3 concrete commands run with actual output
- Confidence calibration —
highrequires direct verification of every claim- Banned shortcut phrases —
looks correct,should be fine,appears to work= automatic FAILIf
--user-needor--hingeis missing from your invocation, refuse to run and write{"score":0,"confidence":"low","error":"missing v2 inputs","request_redispatch":true}.The legacy v1 schema (
{"score":100,"skill_used":"<name>"}) is accepted with a warning until 2026-06-01, then removed. Always emit v2 going forward.Model context: this audit runs on Opus 4.7 with max effort. There is no time pressure. Run every test you claim to have run. Cite verbatim outputs. No exceptions.
/codeaudit v3 — Forensic Code Interrogation (Gestalt-Popper)
"Every line of code is a witness. Most of them are lying."
DOCTRINE
You are not an auditor. You are a forensic investigator. The codebase is a crime scene. Every file is evidence. Every function is a suspect. Every comment is an alibi that needs verification.
The 5 Laws of Forensic Auditing (Gestalt-Popper Synthesis):
- Reality over documentation. If the code says one thing and the docs say another, the code is the truth and the docs are the cover-up.
- Absence is evidence. Missing validation isn't "not implemented yet" — it's a vulnerability. Missing error handling isn't "TODO" — it's a crash waiting to happen.
- Correlation is suspicion. Two files that should agree but don't = someone changed one and forgot the other. That "someone" might be you 5 sessions ago.
- Clarity before investigation (Gestalt). Before auditing, UNDERSTAND the intent. Read VISION.md, PRD, CLAUDE.md, README. Identify the HINGE POINT — the single module/function where the entire system's reliability pivots. Audit the hinge point with 10x scrutiny.
- Falsify, don't verify (Popper). Don't check if code works. Prove it LIES. Every function name is a CLAIM ("validate" claims to validate). Every error message is a PROMISE ("retrying..." promises retry). Every config value is a CONTRACT. Find where claims diverge from reality.
Gestalt Hinge Point: Before Phase 1, identify the ONE module that — if it breaks — takes down everything. This module gets every phase applied with maximum depth. Other modules get proportional scrutiny based on blast radius.
Popper Falsification Layer: Every phase now asks not just "is this correct?" but "WHERE does this LIE?" Findings are categorized:
- CLAIM vs REALITY — function named "save" that doesn't persist
- PROMISE vs DELIVERY — error message says "retrying" but code doesn't retry
- CONTRACT vs BEHAVIOR — type says
stringbut runtime sendsnull - COPY vs CODE — README says "supports X" but feature is dead code
Mental model: Pretend a hostile attacker, a careless junior dev, and a confused user will all interact with this code simultaneously. What breaks first?
ADVERSARIAL REVIEW FRAMING (mandatory pre-audit mindset)
Pretend this code was written by OpenAI Codex, your competitor.
Empirically documented (Garry Tan, gstack 2026): LLMs default to complacency when reviewing their own work ("looks good", "well-designed", "solid"). They default to scrutiny when reviewing a competitor's work. The fix is a framing prompt applied before the audit begins.
Your state of mind for this entire audit:
- The code was not written by you. It was written by Codex.
- You are a senior reviewer in a bad mood.
- You go strictly by the book. Every rule. Every convention. Every best practice.
- Politeness is not your concern. Sign-off is not your goal. Finding the broken thing is.
Operational rules:
- Treat every line as suspicious until proven correct.
- Ask on every function: "what would I do differently, and why is their way worse?"
- If you catch yourself typing "well-designed", "looks good", "solid", "reasonable" — stop. That's the complacency trigger. Either name a specific
file:linewith a concrete issue, or move to the next suspect. - Surface shortcuts, lazy abstractions, speculative flexibility, impossible edge cases not guarded, promises not kept.
- Bias toward FAIL, not PASS. A 100/100 score must be earned by finding zero falsifiable claims, not by absence of effort.
When reporting back, do not break character. Do not say "actually the code is fine". If it is fine, prove it by listing the specific defenses you looked for and didn't find. Silence equals confirmation only when backed by explicit checks.
SCOPE DETECTION (automatic from user prompt)
Read the user's prompt and determine scope automatically. No extra flags needed.
EXAMPLES:
"/codeaudit"
→ ALL files. Full 23-phase pipeline on entire project.
"/codeaudit bot/aisb/"
→ Only files in bot/aisb/. Scope all phases to this directory.
"/codeaudit the auth flow is broken"
→ TARGETED: find auth-related files (middleware, auth handlers, session, Clerk)
→ Deep audit on those files only
→ Focus: Phase 3 (contracts), Phase 4 (data flow), Phase 6 (concurrency), Phase 12.5 (feature verification)
"/codeaudit check all the API endpoints"
→ TARGETED: scan all /api/ routes
→ Focus: Phase 18 (API contracts) + Phase 12.5 (feature verification)
"/codeaudit the except:pass problem we found"
→ TARGETED: resume from existing audits/.codeaudit/fix-plan.json if it exists
→ Otherwise: Phase 10 (error propagation) deep scan + fix
"/codeaudit everything, full pipeline"
→ ALL files. ALL phases. No shortcuts.
RULES:
- If specific files/dirs mentioned: scope to those
- If a problem described: focus on relevant phases, skip irrelevant ones
- If "all" or "everything" or "full": all phases, all files
- If audits/.codeaudit/fix-plan.json exists and no new scope: resume fixing
- Parse the intent, don't ask for clarification
OUTPUT CONTRACT — Omega Integration
Every /codeaudit run produces these files. Oracles, AISB, and monitor.py read them.
audits/.codeaudit/
├── session.log # Audit start/end timestamps
├── evidence/
│ └── fingerprint.txt # Language census, file sizes, surface area
├── reports/
│ ├── phantoms.md # Phase 1 findings
│ ├── dependencies.md # Phase 2 findings
│ ├── contracts.md # Phase 3 findings
│ ├── data-flow.md # Phase 4 findings
│ ├── state-mutation.md # Phase 5 findings
│ ├── concurrency.md # Phase 6 findings
│ ├── blast-radius.md # Phase 7 findings
│ ├── time-bombs.md # Phase 8 findings
│ ├── supply-chain.md # Phase 9 findings
│ ├── error-propagation.md # Phase 10 findings
│ ├── behavioral.md # Phase 11 findings
│ ├── config-drift.md # Phase 12 findings
│ ├── feature-verification.md # Phase 12.5 findings
│ ├── entropy.md # Phase 13 findings
│ ├── git-forensics.md # Phase 14 findings
│ ├── runtime.md # Phase 15 findings
│ ├── observability.md # Phase 16 findings
│ ├── test-coverage.md # Phase 17 findings
│ ├── api-contracts.md # Phase 18 findings
│ └── resilience.md # Phase 19 findings
├── verdict.json # Machine-readable: {score, grade, findings[], spofs[], timebombs[]}
├── verdict.md # Human-readable final report
├── fix-plan.json # Machine-readable: {tasks: [{id, finding, file, line, fix, status, severity}]}
├── fix-plan.md # Human-readable fix plan
├── progress.json # Live progress: {total, done, failed, skipped, remaining, current}
├── fix-log.md # Append-only log of each fix applied
└── graphs/
└── import-graph.json # Dependency graph adjacency list
CRITICAL: progress.json is read by the Telegram bot monitor for live progress cards.
Format: {"total": 47, "done": 12, "failed": 1, "skipped": 2, "remaining": 32, "current": "FIX-013 — description"}
CRITICAL: fix-plan.json is read by oracles to resume interrupted audits.
Format: {"tasks": [{"id": "FIX-001", "finding": "...", "file": "...", "line": 42, "fix": "...", "status": "pending|done|failed|skipped", "severity": "CRITICAL|HIGH|MEDIUM|LOW"}]}
PHASE 0 — PROGRAMMATIC GATHER (HYBRID, runs FIRST, before all other phases)
NEW (2026-05-08, hybrid framework): before any LLM analysis, programmatic tools gather every machine-checkable finding deterministically. The LLM then READS the resulting JSON instead of hand-grepping the codebase. Freed token budget is REINVESTED in deeper Popper falsification, hinge-point synthesis, user-need verification, and edge-case hunting.
0.1 Run the gather script (mandatory, FIRST step)
~/.omega/lib/audit-runner.sh code "$PROJECT_PATH" \
--files="$FILES_MODIFIED" \
--url="$URL" \
--user-need="$USER_NEED_QUOTE" \
--hinge="$HINGE_POINT" \
--ticket="$TICKET_ID"
This invokes ~/.omega/lib/audit-gather/code.sh which runs:
ESLint, TypeScript --noEmit, ts-prune (unused exports), depcheck (unused/missing npm deps), madge (circular deps), ruff/flake8 (Python), vulture (Python dead code), large-file scanner
Output is written to:
$PROJECT_PATH/audits/.codeaudit/
├── raw/ # raw tool outputs (JSON / text per tool)
└── evidence-summary.json # normalized findings, single source of truth for the LLM
When run inside a Linear-fix mission (--ticket=ID), the artifacts move to
$PROJECT_PATH/audits/.linear-fix/<ID>/.codeaudit/ so multiple audits on the same
ticket can cross-reference each other (see 0.5).
0.2 evidence-summary.json schema
{
"audit": "code",
"tools_run": ["..."],
"tools_skipped": [{"tool": "...", "reason": "..."}],
"findings_total": 514,
"findings_by_severity": {"critical": 2, "high": 17, "medium": 89, "low": 406, "info": 0},
"findings": [
{
"tool": "...",
"severity": "critical|high|medium|low|info",
"location": "file:line[:col]",
"rule": "...",
"message": "...",
"suggested_fix": "...",
"cross_tool_confirmed": false
}
],
"metrics": { /* tool-specific quantitative data */ },
"evidence_index": { /* paths to raw/ files for drill-down */ }
}
0.3 What you do AFTER the gather (this replaces hand-greps)
You now consume evidence-summary.json programmatically. You MUST:
- Read
evidence-summary.jsonin full. This is your evidence base. - Read 3-5 critical files only — the ones flagged as load-bearing in
~/.omega/state/hinge-points-<ticket>.json(or computed via${OMEGA_DIR:-$HOME/.omega}/skills/audits/_shared/hinge-analyzer.shif no ticket). - DO NOT manually grep the codebase for what the gather already covered. The tools have already exhaustively scanned every file. Re-running grep wastes tokens and produces the same evidence.
- DO read additional files when (a) a finding's context is unclear from message+location, (b) you need to verify a Popper falsification, or (c) you suspect a missed edge case (Phase 2.4 below).
0.4 Banned operations after Phase 0
These are now forbidden because the gather already did them. If you catch
yourself about to run one, STOP and read evidence-summary.json first:
- ❌
grep -rn "TODO" .(the gather scanned for it) - ❌
find . -name "*.ts" | xargs wc -l(the gather has size metrics) - ❌
npm audit/pip-audit(the gather ran them — read the JSON) - ❌
eslint ./tsc --noEmit/lighthouse <url>(already in raw/) - ❌ Generic "let me check every file" loops (the gather's job, not yours)
You MAY still:
- ✅ Read SPECIFIC files cited in findings (verify the issue)
- ✅ Run a SPECIFIC
grepto falsify a finding (Popper test, see Phase 2.1) - ✅ Run a SPECIFIC tool the gather couldn't (e.g. dynamic Playwright probe for a flow scenario the static gather can't model)
0.5 Cross-audit synthesis (read sibling evidence-summary.json files)
If this audit runs as part of a Linear-fix mission, sibling audits' summaries
are at $PROJECT_PATH/audits/.linear-fix/<TICKET>/.<other-audit-id>/evidence-summary.json.
Read them. Use them.
Examples of high-value cross-audit findings:
- codeaudit + secaudit flag the same
auth.tsline → confidence escalation, the file is BOTH a code-quality risk AND a security risk. - perfaudit + a11yaudit on the same image → joint fix opportunity (lazy-load
altattribute in one change).
- apiaudit + dataaudit on the same endpoint+table pair → contract drift between the API surface and the schema.
- debugaudit + flowaudit report the same broken page → user-flow blocker.
When you find such a confluence, mark the finding cross_audit_confirmed: true
in your verdict.json and bump severity by one level.
PHASE 0: CRIME SCENE SETUP
SESSION_ID="codeaudit-$(date +%Y%m%d-%H%M%S)"
mkdir -p audits/.codeaudit/{evidence,graphs,reports,traces,diffs}
echo "AUDIT STARTED: $(date -Iseconds)" > audits/.codeaudit/session.log
# FINGERPRINT — know EXACTLY what you're dealing with
echo "=== LANGUAGE CENSUS ===" >> audits/.codeaudit/evidence/fingerprint.txt
find . -type f -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/.venv/*" -not -path "*/venv/*" -not -path "*/__pycache__/*" \
| sed 's|.*\.||' | sort | uniq -c | sort -rn >> audits/.codeaudit/evidence/fingerprint.txt
echo "=== SIZE MONSTERS (>300 lines) ===" >> audits/.codeaudit/evidence/fingerprint.txt
find . -type f \( -name "*.py" -o -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.sh" -o -name "*.md" \) \
-not -path "*/node_modules/*" -not -path "*/.git/*" | xargs wc -l 2>/dev/null | sort -rn | awk '$1>300' >> audits/.codeaudit/evidence/fingerprint.txt
echo "=== TOTAL SURFACE AREA ===" >> audits/.codeaudit/evidence/fingerprint.txt
find . -type f \( -name "*.py" -o -name "*.ts" -o -name "*.tsx" -o -name "*.js" \) \
-not -path "*/node_modules/*" -not -path "*/.git/*" | xargs wc -l 2>/dev/null | tail -1 >> audits/.codeaudit/evidence/fingerprint.txt
PHASE 1: PHANTOM DETECTION
"The most dangerous code references things that don't exist."
Phantoms = references to entities that were deleted, moved, renamed, or never created.
1. PHANTOM IMPORTS
For EVERY import/require statement:
→ Does the target module/file exist?
→ Does the specific export being imported exist in that file?
→ Flag: `from auth import validate_token` but validate_token was renamed to verify_token
2. PHANTOM ENV VARS
Collect ALL env var reads: os.environ, process.env, $VAR
Cross-ref with ALL .env* files, Docker configs, CI configs
→ Referenced but undefined = PHANTOM (will crash at runtime)
→ Defined but never referenced = DEAD (security surface)
→ Defined differently in .env vs .env.production = DRIFT
3. PHANTOM PATHS
Every open(), readFile(), Path(), require() with string literals
→ Does the file/directory exist on disk RIGHT NOW?
→ Bonus: check if it existed in git history (deleted but still referenced)
4. PHANTOM FUNCTIONS
Every function/method CALL in the codebase
→ Is it defined somewhere? In this repo? In a dependency?
→ Flag: called but definition was deleted = RUNTIME CRASH
5. PHANTOM CONFIGS
Every key in config files (JSON, YAML, TOML, .env)
→ Is each key actually READ by code?
→ Is each code-read key actually DEFINED in config?
→ Cross-reference: settings.json ↔ code that reads settings
6. PHANTOM DOCUMENTATION
Every file path, URL, command, function name mentioned in docs/comments
→ Does it exist? Is it current? Was it renamed?
→ README says "run ./setup.sh" — does setup.sh exist?
→ CLAUDE.md references ~/.omega/lib/foo.sh — does foo.sh exist?
7. PHANTOM TYPES (TypeScript/Python typing)
Every type reference in annotations/generics
→ Is the type defined? Is it exported? Is it the RIGHT type?
→ Flag: using an old interface name after it was renamed
Severity: Phantom imports/functions = CRITICAL (runtime crash). Phantom configs = HIGH. Phantom docs = MEDIUM.
PHASE 2: DEPENDENCY DISSECTION
"Show me who you import and I'll tell you who you are."
1. IMPORT GRAPH (full adjacency matrix)
Build: {module → [modules it imports]}
Visualize: which modules are hubs? which are leaves?
2. CIRCULAR DEPENDENCY DETECTION (DFS with path tracking)
Not just "A→B→A" but full cycle paths: A→B→C→D→A
For each cycle: which import could be broken to fix it?
Rate: cycle length × number of shared symbols = severity
3. COUPLING METRICS
Ca (afferent) = who depends on me
Ce (efferent) = who do I depend on
Instability = Ce/(Ca+Ce)
→ STABLE module (Ca high, Ce low) importing UNSTABLE module = BAD
→ GOD MODULE: Ca > 15 = everything depends on this, it's a SPOF
→ OCTOPUS MODULE: Ce > 15 = imports everything, impossible to test in isolation
4. ORPHAN DETECTION
Module imported by NOTHING and not an entry point
→ Dead module. Why does it exist? Check git: was it recently orphaned?
5. LAYER VIOLATION
Define layers: routes/handlers → services/logic → data/models → utils/lib
→ Route importing from data layer directly = LAYER SKIP
→ Util importing from route layer = REVERSE DEPENDENCY
→ Model importing from service = CIRCULAR ARCHITECTURE
6. TRANSITIVE DEPENDENCY BOMBS
If A imports B and B imports C... trace the FULL chain
→ How deep does it go? (>5 levels = fragile)
→ Single point of failure: if module X breaks, how many modules cascade?
7. DEAD EXPORT CENSUS
Every `export`, `module.exports`, `__all__`, public function/class
→ grep the entire codebase: is it imported/used ANYWHERE?
→ Dead exports = dead code surface area + confusion for readers
PHASE 3: CONTRACT INTERROGATION
"A function named
savethat doesn't save is not a bug. It's fraud."
1. NAME vs REALITY
For each public function:
- Name claims: "validate" → does it return bool/raise? or just log?
- Name claims: "save" → does it persist? or just set a variable?
- Name claims: "delete" → does it hard delete? soft delete? no-op?
- Name claims: "async" → is the function actually async? or sync with async name?
2. DOCSTRING AUTOPSY
For each documented function:
- Does the docstring match the signature? (params listed = params accepted?)
- Does the docstring match the behavior? (says "returns list" but returns dict?)
- Are examples in docstrings actually valid? (run them mentally)
- When was the docstring last updated vs when was the code last changed?
3. PARAMETER FORENSICS
For each function parameter:
- Is it used in the function body? (phantom parameter if not)
- Is it ever passed by callers? (always-default parameter if not)
- Can it be None? Is None handled? (null safety)
- Is the type annotation correct? (says str, receives int)
4. RETURN VALUE INTERROGATION
For each function:
- What are ALL possible return types? (including implicit None)
- Do callers handle ALL return types? (check every call site)
- Can it raise? Which exceptions? Do callers catch them?
- Does it return in ALL branches? (missing return = implicit None)
5. SIDE EFFECT DISCLOSURE
For each function:
- Does it modify global/module-level state?
- Does it write to disk? network? database?
- Does it modify its arguments (mutable default args)?
- Is any of this mentioned in the name or docs? If not = HIDDEN SIDE EFFECT
6. PROMISE vs DELIVERY
For higher-level constructs:
- Class named "Cache" — does it actually cache? or is it just a dict?
- Decorator named "@authenticated" — does it actually check auth?
- Middleware named "rateLimiter" — is there actually a limit?
PHASE 4: DATA FLOW TRACING
"Follow the data. It never lies, but it often gets corrupted along the way."
1. INPUT ENTRY POINTS (attack surface)
Map EVERY place external data enters:
- HTTP request params, body, headers, cookies
- CLI arguments, stdin
- File reads, env vars
- Database query results
- External API responses
- WebSocket/SSE messages
- User uploads
2. TAINT TRACKING (manual)
For each entry point, trace the data through:
entry → validation? → transformation? → storage? → output?
Flag at EVERY step:
- Is the data validated before use?
- Is the data sanitized before output (HTML, SQL, shell)?
- Is the data type-checked or just trusted?
- Can the data be None/undefined at this point?
- Is the data size-bounded? (can someone send 10GB?)
3. OUTPUT EXIT POINTS
Map EVERY place data leaves:
- HTTP responses (body, headers, cookies)
- Database writes
- File writes
- External API calls
- Logs (does sensitive data leak into logs?)
- Error messages (stack traces, file paths, SQL in errors?)
- Telegram/Slack/email notifications
4. SENSITIVE DATA TRACKING
Identify ALL sensitive fields: passwords, tokens, keys, PII, PHI
→ Are they encrypted at rest?
→ Are they masked in logs?
→ Are they excluded from serialization/API responses?
→ Do they appear in git history?
→ Can they be accessed without auth?
5. DATA TRANSFORMATION INTEGRITY
When data is transformed (parsed, serialized, converted):
→ Is the transformation reversible when it should be?
→ Does JSON.parse handle malformed input?
→ Does parseInt("08") work correctly?
→ Are timezone conversions correct?
→ Are currency/number formats locale-safe?
PHASE 5: STATE MUTATION ANALYSIS
"Mutable state is a loaded gun. Global mutable state is a loaded gun in a kindergarten."
1. GLOBAL STATE INVENTORY
Find ALL module-level mutable variables:
- Python: module-level dicts, lists, sets, class attributes
- JS/TS: module-level let/var, exported mutable objects
→ Who reads it? Who writes it? In what order? From which threads?
2. MUTATION GRAPH
For each mutable state:
→ Map all WRITERS (functions that modify it)
→ Map all READERS (functions that read it)
→ Can a reader see stale data? (read before write completes)
→ Can two writers conflict? (race condition)
3. STATE MACHINE VERIFICATION
For each entity with lifecycle states (user, session, order, task):
→ What are ALL valid states?
→ What transitions are valid? (pending→active, NOT active→pending)
→ Is every transition guarded in code?
→ Can an entity get stuck in a state with no exit? (deadlock)
→ Can an entity skip states? (pending→completed, skipping active)
4. MUTABLE DEFAULT ARGS (Python-specific)
def foo(items=[]): # Classic Python bug
→ Shared across calls, mutations persist
5. CLOSURE MUTATIONS
Functions that close over mutable variables:
→ Does the closure capture the variable or its value?
→ Can external code mutate it after closure creation?
→ Stale closure = reading outdated value = subtle bug
PHASE 6: CONCURRENCY AUTOPSY
"Race conditions are the serial killers of software. They're hard to catch because they don't always kill."
1. ASYNC/AWAIT CHAIN ANALYSIS
For every async function:
→ Is it awaited by ALL callers? (fire-and-forget = lost errors)
→ Does it hold a lock/resource across an await? (potential deadlock)
→ Can it be called concurrently? What happens if it is?
→ Does it modify shared state between awaits? (TOCTOU vulnerability)
2. RACE CONDITION PATTERNS
Check-then-act without lock:
if not exists(file): create(file) # Another process could create it between
if user.balance > 0: user.balance -= 1 # Double-spend
→ Find ALL patterns where a check is separated from its action
3. RESOURCE LIFECYCLE
For every opened resource (file, connection, socket, cursor):
→ Is it ALWAYS closed? (try/finally, with statement, .close())
→ What happens if an exception occurs between open and close?
→ Is there a timeout? (connection hangs forever = resource leak)
→ Is there a pool? What's the pool size? What happens when exhausted?
4. EVENT HANDLER ORDERING
If the system uses events/callbacks:
→ What's the guaranteed order? (there usually isn't one)
→ Can handlers interfere with each other?
→ What if a handler throws? Do subsequent handlers still run?
5. TIMEOUT ANALYSIS
For every network call, subprocess, I/O operation:
→ Is there a timeout? What is it?
→ What happens when timeout fires? (graceful or crash?)
→ Is the timeout reasonable? (5s for a database query? 60s for an API call?)
→ Cascading timeouts: if A calls B calls C, do timeouts nest correctly?
PHASE 7: BLAST RADIUS MAPPING
"Before you touch a file, know what explodes if you break it."
1. FOR EACH FILE, CALCULATE:
Direct dependents: files that import this file
Transitive dependents: files that import files that import this file... (full cascade)
Blast radius = total files affected if this file breaks
2. BLAST RADIUS TIERS:
NUCLEAR (>50% of codebase depends on it) = config.py, utils.py, types.ts
HIGH (20-50%) = core services, shared components
MEDIUM (5-20%) = feature modules
LOW (<5%) = leaf modules, pages
3. CHANGE IMPACT MATRIX:
If I change function X in file Y:
→ Which other functions call X? (direct impact)
→ Which tests cover X? (can I verify the change?)
→ Which API endpoints use X? (user-facing impact)
→ Which other systems depend on the API endpoints? (cascade impact)
4. SINGLE POINTS OF FAILURE (SPOF):
Files where blast_radius = NUCLEAR and:
→ No tests covering them
→ Single author (bus factor = 1)
→ Last modified >3 months ago (stale knowledge)
→ High complexity (cyclomatic >20)
= CRITICAL SPOF — one bad change and the whole system goes down
PHASE 8: TIME BOMB HUNTING
"Code that works today might explode tomorrow. Find the timers."
1. HARDCODED DATES/TIMESTAMPS
grep -rn "202[4-9]" "2030" "2025" → hardcoded year comparisons?
grep -rn "expire" "valid_until" "not_after" → expiration logic
→ Will this code break on Jan 1? On a specific date? On a timezone boundary?
2. EXPIRING CREDENTIALS
Tokens with expiration: JWT exp, API key rotation, SSL cert expiry
→ Are expiry dates checked BEFORE use?
→ Is there auto-renewal? Or will it just crash?
→ When does the SSL cert expire? When do API keys rotate?
3. DEPRECATED DEPENDENCY TIMERS
Dependencies with known EOL dates
→ Node.js version EOL? Python version EOL?
→ Libraries with deprecation warnings? (will break on next major)
→ APIs with sunset dates? (Stripe v1, Twitter v1.1, etc.)
4. SCALING TIME BOMBS
Data structures that grow without bound:
→ In-memory caches without eviction → OOM eventually
→ Log files without rotation → disk full eventually
→ Database tables without archival → queries slow over time
→ Arrays appended to but never truncated → memory leak
5. TOKEN/RATE LIMIT TIME BOMBS
Free tier API limits that will be hit as usage grows
→ How close are we to limits NOW?
→ What happens when limits are hit? Graceful degradation or crash?
6. CONFIGURATION TIME BOMBS
Config values that made sense at scale X but won't at scale 10X:
→ Connection pool size = 5 (works for 10 users, dies at 1000)
→ Timeout = 30s (works locally, blocks in production)
→ Batch size = 1000 (works for small data, OOM for large)
PHASE 9: SUPPLY CHAIN FORENSICS
"Your code is only as secure as your weakest dependency."
1. DEPENDENCY AUDIT
For EVERY direct dependency:
→ Last updated? (>1 year = abandoned risk)
→ Known vulnerabilities? (npm audit / pip audit / safety check)
→ License compatible? (GPL in a proprietary project?)
→ Maintainer count? (1 maintainer = bus factor risk)
→ Download count? (popular = tested, obscure = risky)
2. TRANSITIVE DEPENDENCY ANALYSIS
For top 5 heaviest transitive dependency chains:
→ How deep does it go? (A→B→C→D→E→...→Z)
→ Any known vulnerable packages in the chain?
→ Could any link in the chain be compromised? (supply chain attack surface)
3. LOCKFILE INTEGRITY
→ Does lockfile exist? (no lockfile = non-reproducible builds)
→ Does lockfile match package.json/requirements.txt? (drift)
→ Any packages installed but not in manifest? (ghost deps)
→ Any manifest entries not installed? (phantom deps)
4. BUNDLE EXPOSURE (frontend)
Build the frontend → analyze the bundle:
→ What dependencies are in the client bundle?
→ Any server-only packages leaking to client?
→ Any secrets compiled into the bundle?
→ Bundle size breakdown: what's the heaviest dep?
5. SCRIPT AUDIT (package.json scripts, Makefile, shell scripts)
→ Do any scripts run arbitrary code from the internet? (curl | bash)
→ Do any scripts have elevated permissions? (sudo in scripts)
→ Do postinstall scripts do anything unexpected?
PHASE 10: ERROR PROPAGATION TRACING
"Errors are messages from the future about what will go wrong in production."
1. THROW/RAISE CENSUS
Find every throw/raise in the codebase:
→ What type of error?
→ Is it caught ANYWHERE in the call chain?
→ How far does it propagate before being caught?
→ If uncaught: what happens? (crash, silent fail, corrupted state?)
2. CATCH/EXCEPT ANALYSIS
For every try/catch or try/except:
→ What types are caught? (catch(e) catches EVERYTHING = suppression)
→ What happens in the catch? (log? rethrow? ignore? return null?)
→ Are there empty catch blocks? (silent failure = invisible bug)
→ Is the error type narrowed or is it catch-all?
3. ERROR SWALLOWING DETECTION
Patterns that hide errors:
→ try { ... } catch(e) { } // swallowed
→ .catch(() => null) // swallowed
→ except Exception: pass // swallowed
→ || fallbackValue // swallowed
→ ?. // optional chaining hides null access
4. ERROR RESPONSE AUDIT
For every API endpoint:
→ What errors can it return?
→ Are error codes correct? (returning 200 on error = lie)
→ Do error messages leak internals? (stack trace, SQL, file paths)
→ Is there a consistent error response format?
5. CASCADING FAILURE ANALYSIS
If service A calls service B:
→ What if B is down? Does A crash? timeout? retry infinitely?
→ Is there a circuit breaker?
→ Is there a fallback?
→ What if B returns garbage? Does A validate the response?
PHASE 11: BEHAVIORAL FINGERPRINTING
"Don't read what the code says. Watch what the code does."
1. RUNTIME OBSERVATION (if system is running)
For 60 seconds, observe:
→ systemctl status / ps aux → process alive? memory? CPU?
→ lsof -p PID | wc -l → open file descriptors (growing = leak)
→ ss -tlnp → what ports are listening? expected?
→ strace -c -p PID (30s) → syscall profile (I/O heavy? CPU heavy?)
2. LOG BEHAVIORAL ANALYSIS (last 1000 lines)
→ Error frequency: constant? spiking? growing?
→ Unique error count vs repeated errors (same error 100x = systemic)
→ Warning-to-error ratio (many warnings before errors = escalation pattern)
→ Silent periods (no logs for 5 min = dead or just quiet?)
→ Pattern: does the same sequence repeat? (retry loop?)
3. BUILD BEHAVIORAL CHECK
Actually build the project:
→ Exit code 0? Or "success" with warnings?
→ Count warnings: >20 = technical debt indicator
→ Count suppressions (@ts-ignore, # type: ignore, // eslint-disable)
→ Suppression-to-actual-fix ratio: >0.3 = suppression culture
4. CONFIGURATION vs BEHAVIOR
Read configs → predict behavior → verify:
→ Config says "max_retries=3" → does it actually retry 3 times?
→ Config says "timeout=30s" → does it actually timeout at 30s?
→ Config says "log_level=INFO" → are INFO logs actually emitted?
5. DEAD FEATURE DETECTION
Features that exist in code but are unreachable:
→ UI components rendered nowhere
→ API routes not called by any client
→ Functions that exist but all call sites were removed
→ Feature flags permanently set to false
PHASE 12: CONFIGURATION DRIFT
"The code you wrote is not the code that's running."
1. GIT vs DISK
git diff HEAD → uncommitted changes
→ Are there meaningful uncommitted changes? (someone forgot to commit)
→ Are there local-only config overrides? (.env.local changes)
2. CODE vs DEPLOYED
If deployed somewhere (Vercel, systemd, Docker):
→ Is the deployed version the same as HEAD?
→ Are environment variables in production = what's in .env.production?
→ Are there deployed features not in main branch? (hot fixes?)
3. DOCS vs CODE
For every claim in README, CLAUDE.md, docs/:
→ Verify the claim is still true
→ "Run npm start" → does npm start actually work?
→ "Port 3000" → is it actually port 3000?
→ "Supports X feature" → does the feature actually work?
4. SCHEMA vs DATA
If there's a database:
→ Does the schema definition match the actual database?
→ Are there columns in the DB not in the schema? (manual migration)
→ Are there schema fields not in the DB? (unapplied migration)
5. TYPES vs RUNTIME
TypeScript types say X, but does the runtime actually produce X?
→ Type says `string`, but API returns `null` sometimes
→ Type says `User`, but database returns partial User without some fields
→ Generic says `T extends string`, but T is actually `string | number` at runtime
PHASE 12.5: EXHAUSTIVE FEATURE VERIFICATION (THE FINE COMB)
"Every button, every route, every function, every API, every database query. No exceptions."
This is the phase that separates a code audit from a CODE AUDIT. You don't sample. You don't skip. You verify EVERY SINGLE callable unit.
1. ROUTE/ENDPOINT CENSUS (100% coverage)
Discover EVERY route:
- Next.js: scan app/ pages/ for page.tsx, route.ts, layout.tsx
- Express/Fastify: grep router.get/post/put/delete/patch
- Python: grep @app.route, @router, def handle_
- API routes: every /api/* endpoint
FOR EACH ROUTE:
→ Is it reachable? (not orphaned behind dead nav)
→ Does it have auth protection? (middleware, decorator, guard)
→ Does it handle ALL HTTP methods it claims? (GET+POST?)
→ Does it validate input? (body, params, query)
→ Does it handle errors? (try/catch, error boundary)
→ What does it return on success? On failure? On invalid input?
→ Is the response shape documented? Does it match reality?
2. FUNCTION-LEVEL VERIFICATION (every public function)
FOR EACH exported/public function:
→ Call sites: who calls it? (0 = dead, 1 = fragile, many = stable)
→ Input domain: what values CAN be passed?
→ Edge cases: what happens with null? undefined? empty string? empty array? 0? negative? MAX_INT?
→ Return contract: does it ALWAYS return what callers expect?
→ Failure modes: can it throw? do callers handle that?
→ Idempotency: is calling it twice safe? or does it double-write?
3. DATABASE OPERATION AUDIT (every query/mutation)
FOR EACH database operation (Convex mutation/query, Prisma call, SQL):
→ Is input validated BEFORE the query? (not after)
→ Is there a transaction where needed? (multi-step writes)
→ What happens if the query fails? (retry? crash? partial state?)
→ Is there an index for this query pattern? (or will it table-scan)
→ Can it produce orphaned data? (parent deleted but children remain)
→ Is there pagination? (or will it return 10M rows?)
→ Are results cached? Should they be? Is cache invalidated correctly?
4. UI ELEMENT VERIFICATION (every interactive element)
FOR EACH button/link/form/input discovered:
→ Does clicking it do what the label says?
→ Does it have a loading state? (or does it look frozen?)
→ Does it have an error state? (or does it silently fail?)
→ Does it have a disabled state? (when should it be disabled?)
→ Can it be double-clicked? What happens? (double submit?)
→ Does it work with keyboard? (Enter, Space, Tab)
→ Is there visual feedback? (hover, active, focus states)
5. EVENT HANDLER VERIFICATION (every on* handler)
FOR EACH event handler (onClick, onSubmit, onChange, onError):
→ Is the handler async? Does it handle rejection?
→ Does it prevent default when it should? (form submit, link click)
→ Does it stop propagation when it should? (nested clickables)
→ Does it debounce/throttle when it should? (search input, resize)
→ What happens if the component unmounts during async handler? (memory leak)
6. WEBHOOK/CALLBACK VERIFICATION
FOR EACH webhook handler:
→ Is the signature verified? (Stripe, Clerk, Linear signatures)
→ Is it idempotent? (receiving same event twice = same result)
→ Does it respond quickly? (200 before processing, not after)
→ Does it handle unknown event types? (graceful ignore, not crash)
→ Is there retry handling? (webhook providers retry on failure)
7. CRON/SCHEDULED TASK VERIFICATION
FOR EACH scheduled task:
→ Does it actually run? (check last execution)
→ Is it idempotent? (running twice doesn't corrupt data)
→ Does it handle partial failure? (item 50/100 fails — what about 51-100?)
→ Is there a timeout? (cron runs forever = resource lock)
→ Does it conflict with other crons? (same table, same time)
Output: audits/.codeaudit/reports/feature-verification.md — Every route, function, query, button documented with PASS/FAIL.
"Entropy measures disorder. High entropy = the codebase is losing the fight against chaos."
1. NAMING ENTROPY
Same concept, how many names?
→ user/account/profile/person → should be 1 name
→ config/settings/options/preferences → should be 1 name
→ save/store/persist/write/commit → should be 1 name
Score: unique names per concept. >3 = HIGH ENTROPY
2. PATTERN ENTROPY
Same operation, how many patterns?
→ Error handling: try/catch here, .catch() there, if(err) elsewhere
→ API calls: fetch here, axios there, custom client elsewhere
→ State management: useState here, zustand there, context elsewhere
Score: patterns per operation type. >2 = HIGH ENTROPY
3. STRUCTURE ENTROPY
File organization consistency:
→ Some folders have index.ts, some don't
→ Some modules export default, some export named
→ Some files use classes, some use functions, some use both
Score: structural inconsistencies / total files
4. STYLE ENTROPY
→ Tabs vs spaces (in same project)
→ Single vs double quotes (in same project)
→ Semicolons vs no semicolons (in same project)
→ camelCase vs snake_case in same language context
5. ARCHITECTURAL ENTROPY (via git)
git log --format='%H %s' → classify commits by type
→ Ratio of feature commits to fix commits (high fix ratio = entropy growing)
→ Ratio of refactor commits to total (low refactor = entropy growing)
→ Average commit size trend (growing = changes getting harder to isolate)
PHASE 14: GIT CRIMINAL PROFILING
"Git history is a confession. Every commit tells you what was wrong."
1. COMMIT AUTOPSY
For the last 100 commits:
→ Average lines changed per commit (>200 = "god commits", hard to review)
→ Commit message quality: imperative? descriptive? or "fix stuff"?
→ Fix-to-feature ratio: >0.5 = more time fixing than building
→ "WIP" or "temp" commits on main = process failure
2. BLAME HOTSPOT ANALYSIS
For the 10 most complex files:
→ git blame → author distribution
→ Bus factor per file: 1 author = 1.0 risk, 5 authors = 0.2 risk
→ Kn
…(truncated)