Edge Auditor
Systematic edge case discovery and verification. Finds what the tests missed.
Important
- NEVER write files into the project being audited. Tests, reports, and captured output all live under
~/.claude/edge-audits/<project>-<timestamp>/. This rule is non-negotiable — the audited repo must stay clean (git status unchanged after a run).
- Take your time with each phase. Thoroughness is more important than speed.
- Do not skip the test-writing step. Every P0/P1 finding must have a test that proves it (Python) or an embedded test stub in the report (other languages).
- Use the risk scoring framework from
references/risk-scoring.md for every finding.
- Consult
references/edge-case-catalog.md as a checklist during analysis — do not rely solely on intuition.
- Never modify production code. Write tests only. Flag fixes in the report for the user to implement.
- Launch research subagents in parallel when exploring independent modules.
Instructions
Step 1: Scope and Research
- If
$ARGUMENTS is provided, use it to narrow the audit scope (e.g., a specific module, file, or feature area). Otherwise, audit the entire project.
- Read the project's
CLAUDE.md, README.md, or equivalent to understand architecture, key files, and domain.
- Use the Explore agent to map the codebase structure:
- Identify all source modules and their responsibilities
- Find existing test files and assess coverage gaps
- Locate configuration, entry points, and external integrations
- Read key source files to understand the data flow, state management, and error handling patterns.
- Produce a brief Scope Summary: what is being audited, what is excluded, and why.
Step 2: Identify High-Risk Areas
Analyze the codebase for structural risk indicators. Prioritize areas with:
- External boundaries: API calls, file I/O, user input parsing, network operations
- State mutations: Anything that modifies shared state, databases, files, or caches
- Arithmetic: Financial calculations, aggregations, averages, percentages
- Type conversions: String-to-number, JSON parsing, serialization/deserialization
- Conditional logic: Complex if/else trees, boolean combinations, early returns
- Loop boundaries: Iteration over collections, pagination, retry loops
- Error handling: Bare excepts, swallowed errors, missing finally blocks
- Configuration: Default values, environment variable parsing, missing keys
- Concurrency: Shared resources, race conditions, timeout handling
Produce a Risk Map: a ranked list of modules/functions from highest to lowest risk, with 1-line justification for each.
Step 3: Enumerate Edge Cases
For each high-risk area identified in Step 2:
- Open
references/edge-case-catalog.md and systematically check every relevant category against the code.
- For each potential edge case found:
- Describe the specific scenario (not generic — reference actual variable names, functions, and line numbers)
- Assess whether existing code handles it (guard clause, try/except, validation, etc.)
- If unhandled, score it using
references/risk-scoring.md (Severity x Likelihood = Risk Score)
- Group findings by module/file for readability.
Step 4: Set Up Scratch Directory and Write Tests
NEVER write files into the project being audited. All artifacts live under ~/.claude/edge-audits/.
Resolve the project root and create a per-run scratch directory. Run this before writing any tests or the report:
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
PROJECT_SLUG="$(basename "$PROJECT_ROOT" | tr '[:upper:] _' '[:lower:]--')"
AUDIT_DIR="$HOME/.claude/edge-audits/${PROJECT_SLUG}-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$AUDIT_DIR/tests"
echo "$AUDIT_DIR"
Remember $AUDIT_DIR and $PROJECT_ROOT for the rest of the run.
Python projects only: For every P0/P1 finding, write a focused test named test_[function]_[edge_case] into $AUDIT_DIR/tests/test_edge_audit.py. The file MUST start with a sys.path injection so it can import the project from outside the repo — substitute the literal absolute value of $PROJECT_ROOT (not the shell variable name, not a placeholder):
import sys
sys.path.insert(0, "/absolute/path/to/project") # <-- literal $PROJECT_ROOT
Each test should set up the edge case input, call the function under test, and assert the current (possibly broken) behavior — document the correct behavior in a comment.
Python projects only: Run the suite from outside the repo, capturing output to the scratch dir:
PYTHONPATH="$PROJECT_ROOT" python -m pytest \
"$AUDIT_DIR/tests/test_edge_audit.py" -v \
2>&1 | tee "$AUDIT_DIR/pytest-output.txt"
Record which tests pass (already handled) and which fail (confirmed bug). If a test unexpectedly passes, re-examine — either the case was already handled or the test is wrong.
Non-Python projects (JS/TS, Go, Rust, Java, etc.): Do NOT write a runnable test file anywhere — running it would require touching the repo or its toolchain config. Instead, embed each P0/P1 test as a fenced code block in the report's ## Suggested Tests section (see Step 5). Mark these findings as "unverified — manual run required" in the report. This is a deliberate tradeoff to honor the no-repo-writes rule.
For P2/P3 findings, skip test writing entirely; document them in the report.
Step 5: Generate Report
Write the report to $AUDIT_DIR/EDGE-AUDIT-REPORT.md. NEVER write it to the project being audited.
# Edge Audit Report
**Project**: [name]
**Audit directory**: [absolute $AUDIT_DIR]
**Date**: [date]
**Scope**: [what was audited]
**Auditor**: Claude Code (edge-auditor skill)
## Executive Summary
- **Total findings**: [N]
- **P0 (Critical)**: [N] — [1-line summary of worst finding]
- **P1 (High)**: [N]
- **P2 (Medium)**: [N]
- **P3 (Low)**: [N]
- **Tests written**: [N] | **Passing**: [N] | **Failing (confirmed bugs)**: [N]
## Risk Map
[Ranked list of modules from Step 2]
## Findings
### P0 — Critical
[Each finding using the format from references/risk-scoring.md]
### P1 — High
[...]
### P2 — Medium
[...]
### P3 — Low/Info
[...]
## Test Results
[pytest output or summary table — or "unverified — manual run required" for non-Python projects]
## Suggested Tests
[For non-Python projects: embedded fenced code blocks for each P0/P1 finding
that the user can paste into their own test suite. Omit this section for
Python projects where tests were actually executed.]
## Recommendations
[Top 3-5 prioritized actions to improve robustness]
Print the executive summary inline to the user. Always print the absolute path of $AUDIT_DIR so the user can open the full report and any captured test output. Do not ask whether to save to file — the file is the deliverable and already lives in the scratch directory.
Error Handling
- No test framework installed: Check for pytest in the active Python environment before writing tests. If missing, note in report and write tests anyway (user can install later). Do not install dependencies without asking.
- Tests fail to import: If test imports fail due to project structure, adjust the
sys.path.insert line at the top of $AUDIT_DIR/tests/test_edge_audit.py (e.g. add a src/ subdirectory) and document the workaround in the test file header.
- Scope too large: If the project has 50+ source files, focus on the top 10 highest-risk modules. Note excluded modules in the Scope Summary.
- No existing tests: Flag this as a P1 finding itself ("no test coverage"). Still write edge case tests.
- Read-only or generated files: Skip generated code (protobuf, migrations, etc.) — note exclusion in scope.
- Non-writable
~/.claude/edge-audits/: If the scratch directory cannot be created (permissions, full disk), fall back to $TMPDIR/edge-audits/ and warn the user in the inline summary. NEVER fall back to writing inside the project being audited.
- Pytest config does not apply: Running pytest from outside the repo means project-level
conftest.py, pyproject.toml [tool.pytest.ini_options], and fixtures are not picked up. Keep edge case tests self-contained (no fixture dependencies). If a test needs project fixtures, document it in the report's Suggested Tests section instead of running it.
Examples
Example 1: Audit a financial calculation module (Python)
Input: /code-edges risk management module
Output: Researches risk.py, finds daily loss calculation uses float arithmetic (P0), inventory limits don't account for partial fills (P1), circuit breaker has no test for exactly-at-limit (P2). Writes 5 tests to ~/.claude/edge-audits/myproject-20260101-120000/tests/test_edge_audit.py, 2 fail. Report at ~/.claude/edge-audits/myproject-20260101-120000/EDGE-AUDIT-REPORT.md. Prints executive summary inline with the audit directory path. git status in the audited repo is unchanged.
Example 2: Full project audit (Python)
Input: /code-edges
Output: Scans all modules, identifies API client as highest risk (external boundary + error handling). Finds unhandled 429 rate limit response (P0), JSON parse on empty body (P1), missing timeout on REST calls (P1). Writes 8 tests to ~/.claude/edge-audits/<project>-<timestamp>/tests/test_edge_audit.py, 3 fail. Report with 15 total findings at ~/.claude/edge-audits/<project>-<timestamp>/EDGE-AUDIT-REPORT.md.
Example 3: Scope narrowing (Python)
Input: /code-edges config parsing
Output: Focuses on config.py. Finds missing env var raises KeyError instead of helpful message (P1), boolean config parsed as string (P2), default values shadow env vars (P3). Writes 3 tests to the scratch directory. Report saved outside the repo.
Example 4: Non-Python project (TypeScript)
Input: /code-edges auth middleware
Output: Researches src/middleware/auth.ts. Finds JWT verification allows alg:none (P0), token expiry check uses <= instead of < (P1). Does NOT write any runnable test files anywhere. Embeds both test cases as fenced ts code blocks in the report's ## Suggested Tests section at ~/.claude/edge-audits/<project>-<timestamp>/EDGE-AUDIT-REPORT.md. Inline summary flags findings as "unverified — manual run required" and prints the report path. Repo is untouched.
1---2name: code-edges3description: Audit a project for edge cases, error-prone code paths, and unhandled failure modes. Researches the codebase, identifies the highest-risk areas, enumerates specific edge cases from a comprehensive catalog, writes and runs tests to prove them, then produces a prioritized risk report. Use when user says 'edge audit', 'find edge cases', 'what could break', 'edge case review', 'audit for edge cases', 'stress test this code', 'what am I missing', 'failure modes', 'where will this break', 'robustness check', or 'error path audit'. Do NOT use for security scanning or dead code detection (use code-security for that). Do NOT use for code quality review of specific PRs (use code-review for that). Do NOT use for running existing test suites (use code-preflight for that).4---56# Edge Auditor78Systematic edge case discovery and verification. Finds what the tests missed.910## Important1112- NEVER write files into the project being audited. Tests, reports, and captured output all live under `~/.claude/edge-audits/<project>-<timestamp>/`. This rule is non-negotiable — the audited repo must stay clean (`git status` unchanged after a run).13- Take your time with each phase. Thoroughness is more important than speed.14- Do not skip the test-writing step. Every P0/P1 finding must have a test that proves it (Python) or an embedded test stub in the report (other languages).15- Use the risk scoring framework from `references/risk-scoring.md` for every finding.16- Consult `references/edge-case-catalog.md` as a checklist during analysis — do not rely solely on intuition.17- Never modify production code. Write tests only. Flag fixes in the report for the user to implement.18- Launch research subagents in parallel when exploring independent modules.1920## Instructions2122### Step 1: Scope and Research23241. If `$ARGUMENTS` is provided, use it to narrow the audit scope (e.g., a specific module, file, or feature area). Otherwise, audit the entire project.252. Read the project's `CLAUDE.md`, `README.md`, or equivalent to understand architecture, key files, and domain.263. Use the Explore agent to map the codebase structure:27 - Identify all source modules and their responsibilities28 - Find existing test files and assess coverage gaps29 - Locate configuration, entry points, and external integrations304. Read key source files to understand the data flow, state management, and error handling patterns.315. Produce a brief **Scope Summary**: what is being audited, what is excluded, and why.3233### Step 2: Identify High-Risk Areas3435Analyze the codebase for structural risk indicators. Prioritize areas with:3637- **External boundaries**: API calls, file I/O, user input parsing, network operations38- **State mutations**: Anything that modifies shared state, databases, files, or caches39- **Arithmetic**: Financial calculations, aggregations, averages, percentages40- **Type conversions**: String-to-number, JSON parsing, serialization/deserialization41- **Conditional logic**: Complex if/else trees, boolean combinations, early returns42- **Loop boundaries**: Iteration over collections, pagination, retry loops43- **Error handling**: Bare excepts, swallowed errors, missing finally blocks44- **Configuration**: Default values, environment variable parsing, missing keys45- **Concurrency**: Shared resources, race conditions, timeout handling4647Produce a **Risk Map**: a ranked list of modules/functions from highest to lowest risk, with 1-line justification for each.4849### Step 3: Enumerate Edge Cases5051For each high-risk area identified in Step 2:52531. Open `references/edge-case-catalog.md` and systematically check every relevant category against the code.542. For each potential edge case found:55 - Describe the specific scenario (not generic — reference actual variable names, functions, and line numbers)56 - Assess whether existing code handles it (guard clause, try/except, validation, etc.)57 - If unhandled, score it using `references/risk-scoring.md` (Severity x Likelihood = Risk Score)583. Group findings by module/file for readability.5960### Step 4: Set Up Scratch Directory and Write Tests6162NEVER write files into the project being audited. All artifacts live under `~/.claude/edge-audits/`.63641. Resolve the project root and create a per-run scratch directory. Run this before writing any tests or the report:65 ```bash66 PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"67 PROJECT_SLUG="$(basename "$PROJECT_ROOT" | tr '[:upper:] _' '[:lower:]--')"68 AUDIT_DIR="$HOME/.claude/edge-audits/${PROJECT_SLUG}-$(date +%Y%m%d-%H%M%S)"69 mkdir -p "$AUDIT_DIR/tests"70 echo "$AUDIT_DIR"71 ```72 Remember `$AUDIT_DIR` and `$PROJECT_ROOT` for the rest of the run.73742. **Python projects only**: For every P0/P1 finding, write a focused test named `test_[function]_[edge_case]` into `$AUDIT_DIR/tests/test_edge_audit.py`. The file MUST start with a `sys.path` injection so it can import the project from outside the repo — substitute the literal absolute value of `$PROJECT_ROOT` (not the shell variable name, not a placeholder):75 ```python76 import sys77 sys.path.insert(0, "/absolute/path/to/project") # <-- literal $PROJECT_ROOT78 ```79 Each test should set up the edge case input, call the function under test, and assert the current (possibly broken) behavior — document the correct behavior in a comment.80813. **Python projects only**: Run the suite from outside the repo, capturing output to the scratch dir:82 ```bash83 PYTHONPATH="$PROJECT_ROOT" python -m pytest \84 "$AUDIT_DIR/tests/test_edge_audit.py" -v \85 2>&1 | tee "$AUDIT_DIR/pytest-output.txt"86 ```87 Record which tests pass (already handled) and which fail (confirmed bug). If a test unexpectedly passes, re-examine — either the case was already handled or the test is wrong.88894. **Non-Python projects (JS/TS, Go, Rust, Java, etc.)**: Do NOT write a runnable test file anywhere — running it would require touching the repo or its toolchain config. Instead, embed each P0/P1 test as a fenced code block in the report's `## Suggested Tests` section (see Step 5). Mark these findings as "unverified — manual run required" in the report. This is a deliberate tradeoff to honor the no-repo-writes rule.9091For P2/P3 findings, skip test writing entirely; document them in the report.9293### Step 5: Generate Report9495Write the report to `$AUDIT_DIR/EDGE-AUDIT-REPORT.md`. NEVER write it to the project being audited.9697```markdown98# Edge Audit Report99100**Project**: [name]101**Audit directory**: [absolute $AUDIT_DIR]102**Date**: [date]103**Scope**: [what was audited]104**Auditor**: Claude Code (edge-auditor skill)105106## Executive Summary107108- **Total findings**: [N]109- **P0 (Critical)**: [N] — [1-line summary of worst finding]110- **P1 (High)**: [N]111- **P2 (Medium)**: [N]112- **P3 (Low)**: [N]113- **Tests written**: [N] | **Passing**: [N] | **Failing (confirmed bugs)**: [N]114115## Risk Map116117[Ranked list of modules from Step 2]118119## Findings120121### P0 — Critical122123[Each finding using the format from references/risk-scoring.md]124125### P1 — High126127[...]128129### P2 — Medium130131[...]132133### P3 — Low/Info134135[...]136137## Test Results138139[pytest output or summary table — or "unverified — manual run required" for non-Python projects]140141## Suggested Tests142143[For non-Python projects: embedded fenced code blocks for each P0/P1 finding144that the user can paste into their own test suite. Omit this section for145Python projects where tests were actually executed.]146147## Recommendations148149[Top 3-5 prioritized actions to improve robustness]150```151152Print the executive summary inline to the user. Always print the absolute path of `$AUDIT_DIR` so the user can open the full report and any captured test output. Do not ask whether to save to file — the file is the deliverable and already lives in the scratch directory.153154## Error Handling1551561. **No test framework installed**: Check for pytest in the active Python environment before writing tests. If missing, note in report and write tests anyway (user can install later). Do not install dependencies without asking.1572. **Tests fail to import**: If test imports fail due to project structure, adjust the `sys.path.insert` line at the top of `$AUDIT_DIR/tests/test_edge_audit.py` (e.g. add a `src/` subdirectory) and document the workaround in the test file header.1583. **Scope too large**: If the project has 50+ source files, focus on the top 10 highest-risk modules. Note excluded modules in the Scope Summary.1594. **No existing tests**: Flag this as a P1 finding itself ("no test coverage"). Still write edge case tests.1605. **Read-only or generated files**: Skip generated code (protobuf, migrations, etc.) — note exclusion in scope.1616. **Non-writable `~/.claude/edge-audits/`**: If the scratch directory cannot be created (permissions, full disk), fall back to `$TMPDIR/edge-audits/` and warn the user in the inline summary. NEVER fall back to writing inside the project being audited.1627. **Pytest config does not apply**: Running pytest from outside the repo means project-level `conftest.py`, `pyproject.toml` `[tool.pytest.ini_options]`, and fixtures are not picked up. Keep edge case tests self-contained (no fixture dependencies). If a test needs project fixtures, document it in the report's Suggested Tests section instead of running it.163164## Examples165166### Example 1: Audit a financial calculation module (Python)167168**Input**: `/code-edges risk management module`169170**Output**: Researches `risk.py`, finds daily loss calculation uses float arithmetic (P0), inventory limits don't account for partial fills (P1), circuit breaker has no test for exactly-at-limit (P2). Writes 5 tests to `~/.claude/edge-audits/myproject-20260101-120000/tests/test_edge_audit.py`, 2 fail. Report at `~/.claude/edge-audits/myproject-20260101-120000/EDGE-AUDIT-REPORT.md`. Prints executive summary inline with the audit directory path. `git status` in the audited repo is unchanged.171172### Example 2: Full project audit (Python)173174**Input**: `/code-edges`175176**Output**: Scans all modules, identifies API client as highest risk (external boundary + error handling). Finds unhandled 429 rate limit response (P0), JSON parse on empty body (P1), missing timeout on REST calls (P1). Writes 8 tests to `~/.claude/edge-audits/<project>-<timestamp>/tests/test_edge_audit.py`, 3 fail. Report with 15 total findings at `~/.claude/edge-audits/<project>-<timestamp>/EDGE-AUDIT-REPORT.md`.177178### Example 3: Scope narrowing (Python)179180**Input**: `/code-edges config parsing`181182**Output**: Focuses on `config.py`. Finds missing env var raises KeyError instead of helpful message (P1), boolean config parsed as string (P2), default values shadow env vars (P3). Writes 3 tests to the scratch directory. Report saved outside the repo.183184### Example 4: Non-Python project (TypeScript)185186**Input**: `/code-edges auth middleware`187188**Output**: Researches `src/middleware/auth.ts`. Finds JWT verification allows `alg:none` (P0), token expiry check uses `<=` instead of `<` (P1). Does NOT write any runnable test files anywhere. Embeds both test cases as fenced `ts` code blocks in the report's `## Suggested Tests` section at `~/.claude/edge-audits/<project>-<timestamp>/EDGE-AUDIT-REPORT.md`. Inline summary flags findings as "unverified — manual run required" and prints the report path. Repo is untouched.