RepoAudit (Multi-Dimensional Code Intelligence)
Role: Solo, end-to-end. Architecture, analysis engine, CLI, reporting
Tech Stack: Python 3.10+, Click, Tree-sitter, Anthropic/OpenAI/Gemini, Pydantic, Rich
Repository: Private. Demo available on request
Overview
RepoAudit is a multi-profile code analysis tool that scans repositories across six dimensions (AI maturity, security posture, architecture quality, documentation coverage, portfolio readiness, and auto-generated diagrams) and produces structured reports with optional LLM validation.
Most static analysis tools answer one question. RepoAudit answers six at once, and it does it deterministic-first: every analysis works without an API key. LLM validation is progressive enhancement, not a requirement. That means the tool runs just as reliably in CI/CD pipelines, air-gapped environments, and on local dev machines.
It operates in two modes: developer local (scan any directory) and CI/CD central (analyze multiple GitHub repositories on a schedule via GitHub Actions, up to 10 concurrent workers). Reports come out as Markdown, JSON, or interactive tabbed HTML dashboards.
I run it against its own codebase regularly. The most recent self-scan rated it S4/D4 (Well-Structured / Polished) on architecture, S3 (Solid) on security, and C4/Q4 (Comprehensive / Excellent) on documentation. Full 6-profile scan with LLM validation costs about $3.79 total.
System Architecture
RepoAudit follows a pipeline architecture with three main layers: Interfaces (CLI and local scanner for local analysis, Runner and GitHub client for remote repos), Core (scanner extracts signals using tree-sitter, classifier determines maturity levels, reporter generates outputs), and LLM (router selects models, validator confirms signals, analyzer provides reasoning). The scanner uses tree-sitter for syntax-aware pattern detection, and the LLM layer is entirely optional: deterministic classification works without it, but validation and deep analysis benefit from it.
graph TD
subgraph "Extraction Layer"
A[Target Repository] --> B{Tree-sitter Parser}
A --> C{Regex Fallback Scanner}
A --> S[Skeleton + Core Files]
B -->|AST-aware| D[Cognitive / Operational / Agentic Signals]
C --> D
end
subgraph "Validation Layer"
D --> F{Profile Filter}
F -->|Deterministic| G[Classification Engine]
F -->|LLM-Enabled| H[Batch Validator]
S --> P[Layered Prompt Cache: skeleton, core, rubric]
P -->|Anthropic/OpenAI/Gemini| H
H -->|Two-turn context requests| J[Validated Signals]
J --> G
end
subgraph "Fit Layer"
G --> K[Tri-Axis Levels C0-C5 / O0-O5 / A0-A5]
D --> I[Intent Drivers]
I --> Q[Intent Audit + Target Bands]
K --> V{Per-Axis Fit Verdict}
Q --> V
end
subgraph "Output Layer"
V -->|under-built / appropriate / over-built| L[Markdown Reports]
K --> L
K --> M[JSON Scores]
K --> N[HTML Dashboards]
V --> N
end
Components
- Profile System: six built-in analysis profiles (AI maturity, security, architecture, docs audit, portfolio, diagrams), each defined in YAML with signal filtering, classification overrides, and output customization. Custom profiles supported. Filtering happens at query selection time rather than post-processing, which means the scanner skips unnecessary AST traversal entirely for profiles that donât need it.
- Tree-sitter Extraction: 100+ language-specific queries across Python, JavaScript/TypeScript, and Java. Each query includes refinement callbacks that check AST context (e.g.,
is_llm_feedback_loopverifies while loops contain LLM calls with result-dependent exits). The system walks parent nodes to exclude matches inside string or comment AST nodes, and extracts full function bodies instead of just line snippets for proper context. Reduced false positive rate from ~40% (regex only) to <5%. - LLM Provider Abstraction: unified interface across Anthropic, OpenAI, and Gemini with a central model registry tracking pricing, context limits, and capabilities. Deterministic routing with configurable strategies (balanced_fallback, prefer_cheap, fixed) and fallback chains.
- Security Scanner: multi-phase async analysis with pattern detection, dependency CVE scanning (OSV API, free, no auth), endpoint/attack surface classification, and call-graph tracing to determine whether vulnerabilities are actually reachable from HTTP endpoints.
- Token Metering: budget enforcement at four scopes: per-call (prevent runaway single requests), per-repo (cap total spend on one analysis), per-run (cap a CI/CD batch job), and monthly (prevent surprise bills). Conservative pre-call estimation (char_count/4 * 1.15 safety factor) and authoritative post-call metering from provider responses. Every decision logged to JSON ledgers with reason codes.
Engineering Details
1. Tri-Axis AI Maturity Classification
Existing tools classify AI integration as binary: uses AI or doesnât. Real projects exist on a spectrum though, and a single-shot API call is fundamentally different from a self-healing agentic loop. Treating them as the same category isnât useful to anyone. So I designed a tri-axis classification model that evaluates AI sophistication across three independent dimensions.
Cognitive Axis (C0-C5): How the system thinks.
| Level | Name | Example |
|---|---|---|
| C0 | Deterministic | Pure logic, no AI |
| C1 | Reactive | Single-shot LLM call |
| C2 | Instrumental | Tool/function calling chains |
| C3 | Adaptive Planner | Feedback loops; output affects next input |
| C4 | Reflective Synthesizer | Self-critique and refinement cycles |
| C5 | Self-Evolving | Generates its own tools at runtime |
Operational Axis (O0-O5): How the system survives.
| Level | Name | Example |
|---|---|---|
| O0 | Ephemeral | Local/manual only |
| O1 | Scripted | Portable (Docker, requirements.txt) |
| O2 | Event-Driven | CI/CD integrated |
| O3 | Bounded Loops | Fault tolerance, retries, circuit breakers |
| O4 | Persistent | Durable state across runs |
| O5 | Governed | Budget enforcement, audit trails, permissions |
Agentic Axis (A0-A5): How the system acts.
| Level | Name | Example |
|---|---|---|
| A0 | Stateless | Single-shot call, result used or discarded |
| A1 | Responsive | Generates persistent artifacts for later use |
| A2 | Conversational | Multi-turn interactions with maintained context |
| A3 | Task-Oriented | Selects its own tools and strategies to hit a goal |
| A4 | Autonomous Agent | Self-directed loops, cross-session memory, planning |
| A5 | Self-Governing | Spawns sub-agents, manages its own budget |
High-level signals (C3+/O3+/A3+) require LLM validation because distinguishing real implementation from test fixtures, comments, or superficial patterns takes semantic understanding that pattern matching canât do. Deterministic analysis caps at C2/O2/A2, honest about what it can and canât prove.
The levels then get graded for fit, not just altitude. Deterministic intent drivers plus an LLM intent audit derive a target band per axis, and each axis gets a three-outcome verdict: under-built, appropriate, or over-built. A weekend script scoring C1/O1/A0 can be a better piece of engineering than a C4 system that never needed to be one, and the report says so.
2. Hybrid Signal Detection with Tree-sitter
Regex-based pattern matching for AI usage signals produced way too many false positives from code examples in comments, string literals, and test fixtures, making deterministic classification unreliable. So I implemented syntax-aware extraction using tree-sitter parsers with 100+ language-specific queries (Python, JavaScript/TypeScript, Java).
Each language has a dedicated query definition file with queries organized by signal type and confidence level. Each query includes refinement callbacks that check AST context, so the system can distinguish a real feedback loop from one mentioned in a docstring. The system walks parent nodes to exclude matches inside string or comment AST nodes and extracts full function bodies for proper context.
- Reduced false positive rate from ~40% to <5% based on validation against reference projects.
- Regex remains as fallback for unsupported languages, but for the three supported ones, tree-sitter is the primary extractor.
3. Iterative LLM Validation with Context Requests
Single-pass LLM validation often lacks sufficient context to confirm high-level signals. A C3+ feedback loop detection might match a code snippet that doesnât show the full pattern. So I built a two-turn validation system where the LLM can request additional context after initial analysis.
- Context extractors use language-specific AST traversal (Pythonâs stdlib
ast, JavaScript regex-based) to extract full function bodies, imports, and enclosing class context. - Signals are batched by file to minimize redundant file fetches, with parallel batch processing (max 3 concurrent batches).
- The LLM sees the initial signal, and if it needs more information, it can request specific functions, classes, or caller locations before making a determination.
Increased C3+ validation accuracy from 72% to 91% on reference projects. Reduced per-repo validation cost by 40% through batching and context reuse.
4. Multi-Phase Async Security Analysis
Security scanning spans multiple independent dimensions: code patterns, dependency vulnerabilities, architecture exposure, and endpoint reachability all matter, and none of them feed into each other. So I built a four-phase parallel pipeline with semaphore-based throttling.
- Phase 1 (Signal Validation): batched LLM validation of detected security patterns (SQL injection, XSS, path traversal, hardcoded secrets, insecure crypto). 50+ deterministic vulnerability patterns with OWASP/CWE mapping.
- Phase 2 (Dependency Scanning): parses manifests (requirements.txt, package.json, Cargo.toml, go.mod) and queries the OSV API for known CVEs. Free, no auth required.
- Phase 3 (Architectural Analysis): classifies code structure (MVC, event-driven, microservices) and analyzes security posture based on architecture patterns.
- Phase 4 (Rating Synthesis): aggregates findings with OWASP Top 10 and CWE mappings, severity ratings, and prioritized remediation recommendations.
The distinctive piece here is exposure classification. The scanner traces call graphs to determine whether a vulnerability is directly_exposed (reachable from an HTTP endpoint), indirectly_exposed, or internal. A SQL injection in a utility function called from nowhere is very different from one sitting behind a public API route, and I didnât want both showing up with the same severity.
Above the four phases sits a deep-verify jury that gates high-severity findings before they reach the report. Each candidate is re-examined with refute-first prompting: the model is instructed to argue the finding isnât real and to keep it only if it canât. For High and Critical severity I run several independent jurors and take consensus, enriching each candidate with on-demand data flow (resolving the enclosing function, class, and callers only for findings that reach this stage, not for every hit). This is what clears the false positives that survive pattern matching, the documentation examples, test fixtures, and already-mitigated patterns, without paying for deep analysis on low-severity noise. On the last self-scan it recalibrated or dismissed 7 findings that the earlier phases had flagged, including a Critical that was really a deliberate design choice.
5. Profile-Driven Analysis
Different stakeholders care about different things. A security team wants vulnerability findings. A hiring manager wants architecture quality. A tech lead wants documentation gaps. Rather than try to serve all of them at once, I built a YAML-based profile system where each profile controls the entire analysis pipeline.
name: security
display_name: Security Audit
analysis_mode: security
cognitive_filter:
min_confidence: 0.7
classification:
require_validation_for_c3_plus: true
- Profiles control which signals are extracted, how theyâre filtered, whether LLM validation is required, and what output format gets generated. Filtering at query selection time means portfolio scans complete in 2-3 seconds per repo (vs 15-20 seconds for full scans) by skipping C3+ queries entirely.
- The
full-scancommand runs all profiles in parallel viaThreadPoolExecutor, producing a tabbed HTML dashboard with each dimension as a separate view. Parallel repo analysis supports up to 10 concurrent workers. - Custom profiles can override any built-in behavior: signal thresholds, classification caps, output templates.
6. Central Model Registry and Cost Control
Supporting multiple LLM providers with different pricing, context limits, and capabilities is a maintenance burden, and cost tracking gets messy fast without a central source of truth. So I built a single-source-of-truth model registry with integrated budget enforcement.
- Every supported model (Claude, GPT, Gemini variants) is registered with pricing per million tokens, context window size, and capability flags.
- Token estimation uses a character-based heuristic with a 1.15x safety factor, fast enough for real-time budget checks without requiring a tokenizer. Authoritative post-call metering from provider responses for accurate cost tracking.
- Budgets enforce at four scopes: per-call, per-repo, per-run, and monthly. Monthly enforcement prevents surprise bills across multiple runs.
- Graceful degradation strategies are configurable:
skip_component,choose_cheaper, orfail_run. - All LLM interactions logged to JSON ledgers with reason codes for auditability.
The tool never surprises you with a bill.
7. Layered Prompt Caching
The LLM-first profiles (portfolio, architecture, docs, diagrams, security) all re-send the same repository skeleton and core files on every call. That is one large prefix paid for six times over. My first fix was to warm the cache with one profile, then fire the rest in parallel off that warm prefix. It fell apart on large repos, where the warm profile alone took longer than Anthropicâs 5-minute cache TTL, so the cache had already expired before the parallel calls started.
So I redesigned it as a three-layer cached prefix, skeleton then core then rubric, with byte-stable rendering so the prefix hashes identically on every call. The skeleton (file tree plus signatures) and the core (a set of high-centrality files) are built once, primed with cheap max_tokens=1 calls per model, then reused across every profile. Prime the shared layers once and burst, instead of warming through a whole profile first.
- Cut full-scan input cost by 22% on the self-scan, with 238K cache reads against 44K writes.
- Anthropic-specific, since the
cache_controlmechanism is provider-specific. OpenAI and Gemini get functional parity but pay full input price on repeated context.
Code Snippet: Security Exposure Classification
This is how the security scanner determines whether a detected vulnerability is actually reachable from an attack surface.
class ExposureClassifier:
"""Traces call graphs to classify vulnerability exposure."""
def classify(self, signal: SecuritySignal,
endpoints: list[Endpoint],
call_graph: CallGraph) -> ExposureLevel:
# Check if the signal's location is directly in an endpoint handler
if self._is_endpoint_handler(signal.file_path, signal.line, endpoints):
return ExposureLevel.DIRECTLY_EXPOSED
# Trace backwards through call graph from known endpoints
for endpoint in endpoints:
if call_graph.is_reachable(
source=endpoint.handler,
target=signal.function_name,
max_depth=5
):
return ExposureLevel.INDIRECTLY_EXPOSED
return ExposureLevel.INTERNAL
CLI Interface
RepoAudit provides both local and CI/CD modes through a Click-based CLI.
# Local developer mode - scan any directory
repoaudit scan ./my-repo # Default: AI maturity
repoaudit scan ./my-repo --profile security --validate # Security audit with LLM
repoaudit scan ./my-repo --profile architecture --validate # Architecture analysis
repoaudit scan ./my-repo --profile docs-audit --validate # Documentation gaps
repoaudit scan ./my-repo --profile diagrams --validate # Auto-generate Mermaid diagrams
repoaudit full-scan ./my-repo # All profiles in parallel
# CI/CD mode - analyze multiple repos via GitHub API
repoaudit central-run --config runner/config.yml
repoaudit status # Dashboard of all tracked repos
# Options
--model anthropic|openai|gemini # Choose LLM provider
--method treesitter|regex|both # Extraction method
--format json|markdown|both # Output format
--render-mode svg|js|both # Diagram rendering
Features
- Six Analysis Profiles - AI maturity, security, architecture, documentation, portfolio readiness, auto-generated diagrams
- Deterministic-First - full analysis without API keys; LLM validation is opt-in progressive enhancement
- Tri-Axis Classification - novel cognitive (C0-C5), operational (O0-O5), and agentic (A0-A5) maturity model for AI integration, graded for fit against intent-derived target bands (under-built / appropriate / over-built)
- Security Scanning - 50+ vulnerability patterns with OWASP/CWE mapping, exposure classification, dependency CVE scanning via OSV, and a deep-verify jury (refute-first prompting, multi-juror consensus) for high-severity findings
- Tree-sitter Extraction - 100+ AST-aware queries across Python, JavaScript, and Java with semantic refinement callbacks. <5% false positive rate.
- Iterative LLM Validation - two-turn system where the LLM can request additional context before confirming signals. 91% accuracy on C3+ signals.
- Multi-Provider LLM - unified interface across Anthropic, OpenAI, and Gemini with deterministic routing and fallback chains
- Cost Control - budget enforcement at four scopes (per-call, per-repo, per-run, monthly) with configurable degradation strategies
- Prompt Caching - layered cached prefixes (skeleton, core, rubric) with prime-then-burst scheduling; ~22% input-cost reduction on LLM-heavy scans
- Interactive Reports - tabbed HTML dashboards, Markdown narratives, structured JSON output
- CI/CD Integration - GitHub Actions workflow for scheduled multi-repo analysis with state tracking and change detection
- Parallel Analysis - up to 10 concurrent workers for batch repo scanning, with diff-based gating to minimize API calls
- Monorepo Support - automatic subdirectory discovery with parallel analysis
- Privacy - read-only, secret redaction, never modifies target repositories
Tech Stack
- Language: Python 3.10+
- CLI: Click 8.0+, Rich (terminal UI)
- Parsing: Tree-sitter (Python, JavaScript, Java), regex fallback
- AI/LLM: Anthropic Claude, OpenAI GPT, Google Gemini (provider-agnostic with central model registry)
- Validation: Pydantic (config schema), PyYAML (profiles)
- Security: OSV API (dependency CVEs), custom pattern detection, exposure classification
- GitHub: PyGithub (API integration), diff-based change gating
- Reporting: Markdown, JSON, HTML dashboards with Mermaid diagram generation
- Build: Hatchling (PEP 517), pip-installable