Architecture & Internal Design
stackvet is built as an offline-first, modular diagnostic engine designed to analyze Python project ecosystems in sub-second execution time.
1. System Overview
Traditional linters inspect only individual source files (AST), while package managers typically only inspect lockfiles. stackvet bridges this gap by unifying four distinct layers of the Python ecosystem into an immutable diagnostic model:
- Manifests:
pyproject.toml,requirements.txt,setup.cfg,Pipfile. - Active Environment:
sys.executable,site-packages,importlib.metadatadistributions, and installed version constraints. - Source Code AST: Module import references, circular call loops, and orphan files.
- Runtime & Infrastructure:
Dockerfile,docker-compose.yml, and.github/workflows/CI matrices.
CLI / TUI (click + rich)
│
Project Discovery
│
ProjectContext (Immutable)
│
┌───────────────┬──────────────┴───────────────┬────────────────┐
Dependencies Environment Imports Packaging
Analyzer Analyzer Analyzer Analyzer
└───────────────┼──────────────────────────────┴────────────────┘
│
AnalysisEngine
│
Diagnostic Model
│
Root Cause Correlator
│
┌──────────────┬─────────────┼─────────────┬──────────────┬──────────────┐
Terminal JSON SARIF HTML GitHub Actions Interactive
Reporter Reporter Reporter Reporter Annotator TUI Dashboard
2. End-to-End Diagnostic Pipeline
The diagram below illustrates the complete lifecycle from project path discovery through multi-channel report generation:
flowchart TD
subgraph Discovery["1. Discovery & Context Ingestion"]
A["<b>File System Scanner</b><br/>Walks project root, excludes ignored paths"]
B["<b>Manifest Parser</b><br/>Parses PEP 621, Poetry, Flit, setuptools, requirements"]
C["<b>Environment Inspector</b><br/>Inspects active virtualenv & installed distributions"]
D["<b>AST Module Parser</b><br/>Extracts import statements & relative import trees"]
E["<b>Infrastructure Parser</b><br/>Extracts Docker base images & CI matrix versions"]
end
subgraph Context["2. Immutable Context"]
CTX["<b>ProjectContext</b><br/>Frozen snapshot of project metadata, AST, and environment"]
end
subgraph Analyzers["3. Subsystem Analyzers"]
F1["<b>Dependencies Analyzer</b><br/>Conflict resolution, undeclared/unused packages"]
F2["<b>Environment Analyzer</b><br/>Python interpreter, Docker, and CI drift"]
F3["<b>Imports Analyzer</b><br/>Tarjan's cycle algorithm & unresolvable modules"]
F4["<b>Packaging Analyzer</b><br/>PEP 621 compliance & schema validation"]
end
subgraph Correlation["4. Correlation & Scoring"]
G["<b>Analysis Engine & Correlator</b><br/>Aggregates findings, deduplicates evidence"]
H["<b>Health Score Calculator</b><br/>Applies severity penalties (0–100 score)"]
end
subgraph Reporters["5. Reporting & Remediation"]
R1["<b>Terminal Reporter</b><br/>Colorized Rich tables & boxes"]
R2["<b>Interactive TUI</b><br/>Live dashboard with keyboard navigation"]
R3["<b>Self-Contained HTML</b><br/>Single-file interactive report with SVG gauges"]
R4["<b>SARIF v2.1.0 & JSON</b><br/>GitHub Security & CI integration"]
R5["<b>Remediation Engine</b><br/>Safe diff generator & sync coordinator"]
end
Discovery --> CTX
CTX --> Analyzers
Analyzers --> Correlation
Correlation --> Reporters
3. Subsystem Analyzers
All diagnostic checks are implemented as independent analyzers under src/stackvet/analyzers/. Each analyzer accepts the immutable ProjectContext and yields structured Diagnostic instances.
3.1 Dependencies Analyzer (src/stackvet/analyzers/dependencies/)
- Constraint Conflict Engine: Validates installed package versions against declared PEP 508 version specifiers.
- Missing Dependency Detection: Identifies third-party packages imported in source code that are missing from
pyproject.tomlor requirements files. - Unused Dependency Detection: Pinpoints direct declared dependencies that are never referenced across project source files.
- Standard Library Awareness: Includes exhaustive Python 3.10–3.13 stdlib catalogs (accounting for PEP 594 removals).
3.2 Environment & Drift Analyzer (src/stackvet/analyzers/environment/)
- Python Version Drift: Compares the active virtualenv interpreter version against
requires-pythonor target runtime. - Container Drift: Scans
Dockerfileandcompose.ymlfor base image Python version tags that diverge from project targets. - CI Matrix Drift: Verifies that GitHub Actions matrix definitions cover the Python versions declared in project manifests.
3.3 Imports & AST Analyzer (src/stackvet/analyzers/imports/)
- Circular Import Cycle Detection (
IMP-001): Constructs a directed module dependency graph and uses Tarjan's Strongly Connected Components (SCC) algorithm to identify recursive import loops. - Unresolved Local Imports (
IMP-002): Flags imports that reference non-existent local packages or missing__init__.pyfiles. - Orphan / Dead File Detection (
IMP-003): Identifies Python modules that are never imported by any other module, test file, or console script entry point. - Architecture Layer Violation Detection (
ARC-001): Identifies downward layer skipping (e.g., API directly importing Database bypassing intermediate Services) and upward inverted dependencies. - Circular Component Cycles (
ARC-002): Traces cyclic dependencies between high-level architectural layers (e.g. Services → Utils → Services).
3.4 Packaging Analyzer (src/stackvet/analyzers/packaging/)
- PEP 621 Schema Validation: Ensures required tables (
[project],name,version) are present and syntactically valid. - Build Backend Consistency: Verifies configuration compatibility with standard build tools (
setuptools,flit_core,hatchling,poetry.core,pdm.backend).
4. Immutable Core Models
All state within stackvet flows through immutable, strictly typed dataclasses defined in src/stackvet/core/:
4.1 ProjectContext
A frozen snapshot of discovered project assets:
- root_dir: Absolute project path.
- manifest: Parsed pyproject.toml or requirements metadata.
- environment: Active Python interpreter version, virtualenv path, and installed distributions.
- source_files: Parsed AST trees and imported module sets.
- config: User configuration loaded from [tool.stackvet].
4.2 Diagnostic
A structured diagnostic finding:
- rule_id: Stable identifier (e.g. DEP-001, IMP-001).
- title: Short human-readable summary.
- severity: ERROR, WARNING, INFO.
- message: Specific description of the root cause.
- location: Optional file path and line number.
- evidence: Bulleted list of facts discovered during analysis.
- suggestions: Recommended CLI commands or code modifications.
- fix_action: Optional automated remediation plan.
5. Root Cause Engine & Health Scoring
stackvet computes an objective, deterministic project health score on a scale from 0 to 100:
$$\text{Health Score} = \max\left(0, 100 - \sum_{d \in \text{Unique Findings}} \text{SeverityPenalty}(d)\right)$$
5.1 Severity Scoring Weights
Every unique finding deducts points based on its severity level:
| Finding Severity | Penalty Points | Rationale & Description | Behavior in CI Mode (stackvet check) |
|---|---|---|---|
CRITICAL |
-20 points | Catastrophic system failures, event-loop blocking calls in async handlers, fatal runtime breaks. | Fails scan immediately (exit code 1). |
ERROR |
-8 points | Definite runtime breakages, missing package declarations, unresolved imports, cyclic architecture dependencies. | Fails scan immediately (exit code 1). |
WARNING |
-2 points | Transitive dependency risks, unpinned versions, lockfile drift, framework anti-patterns. | Fails scan if --strict is enabled. |
INFO |
0 points | Informational observations and architecture insights; non-penalizing. | Advisory only. |
HINT |
0 points | Contextual suggestions and best-practice recommendations; non-penalizing. | Advisory only. |
5.2 Letter Grade Scale
The numerical health score translates directly into four clear letter grades:
| Score Bracket | Grade Label | Status | Description |
|---|---|---|---|
| 90 – 100 | Grade A | A (Healthy) |
Pristine or near-pristine codebase; zero critical issues and minimal non-blocking warnings. |
| 75 – 89 | Grade B | B (Fair) |
Functioning project with minor lockfile drift, unpinned versions, or unused dependencies. |
| 50 – 74 | Grade C | C (Degraded) |
Multiple missing dependencies or framework anti-patterns that need remediation. |
| 0 – 49 | Grade F | F (Critical Issues) |
Severe architectural defects, blocking synchronous calls, or missing direct dependencies. |
5.3 Deterministic Scoring & Zero-Distortion Deduplication
To ensure that repeated scans produce consistent results without score drift:
- Deterministic Discovery & Analysis: All discovered source files, manifests, and Dockerfiles are sorted lexicographically prior to AST and dependency traversal. Analyzers iterate through dependency maps via ordered trees (
BTreeMap), eliminating random hash iteration variances. - Finding Deduplication: Diagnostics are deduplicated by composite key
(rule_id, file_path, line, message). If multiple analyzers or repeated passes flag the same underlying finding, duplicate occurrences are suppressed and recorded as ignored duplicates, preventing redundant penalties from distorting the health score. - Total Deterministic Diagnostic Ordering: All emitted diagnostics are sorted by:
- Primary:
severitydescending (CRITICAL>ERROR>WARN>INFO>HINT) - Secondary:
rule_idascending - Tertiary:
file_pathascending - Quaternary:
lineascending - Quinary:
messageascending
5.4 Score Explainability & Attribution
stackvet provides full transparency into how the health score is derived:
- CLI Breakdown (
stackvet doctor --explain): Emits a formatted attribution scorecard listing the exact deductions per rule and an itemized table of contributing diagnostics. - Structured JSON (
--json): Includes the completescore_breakdownobject (HealthScoreExplanation), detailingbase_score,final_score,total_deductions,unique_findings_count,duplicate_findings_ignored,rule_contributions, and itemizeddiagnostic_details. - HTML Dashboard (
--html): Embeds deduction metrics and deduplication summary directly into the health score gauge card.
6. Safe Automated Remediation Engine
The remediation engine (src/stackvet/remediation/) adheres to strict safety guarantees:
- Non-Destructive AST/TOML Editing: Modifications to
pyproject.tomlpreserve existing formatting, comments, and unrelated tables. - Dry-Run Diff Generation: All proposed fixes can be inspected in advance via
stackvet fix --dry-run. - Reversible Fix Actions: Fixes are scoped to specific files with atomic writes.
- Package Manager Auto-Sync: When
--syncis passed,stackvetautomatically invokes the project's native tool (uv sync,poetry install,pip install) to update the virtualenv.
7. Multi-Channel Reporting Pipeline
Diagnostics can be formatted and routed to multiple consumers:
- Terminal Reporter: Human-readable colorized output with evidence boxes and suggestion snippets.
- Interactive TUI Dashboard (
stackvet inspect): Rich terminal interface with dual panes, scrolling, keyboard shortcuts, and live dependency tree toggling. - Standalone HTML Report (
stackvet scan --html): Single-file HTML dashboard with SVG health score meters, real-time client-side search, severity filters, and light/dark theme toggle. - SARIF v2.1.0 Reporter: Standard OASIS SARIF format for GitHub Advanced Security and Code Scanning alerts.
- JSON Reporter: Machine-readable output for custom scripts and dashboard ingestion.
8. Codebase Directory Map
src/stackvet/
├── __init__.py # Package version and public exports
├── cli.py # Click CLI entry point and subcommands
├── core/
│ ├── config.py # [tool.stackvet] configuration loader
│ ├── context.py # ProjectContext discovery & data ingestion
│ ├── models.py # Diagnostic, Severity, ScanResult dataclasses
│ └── rules.py # RuleCatalog registry
├── analyzers/
│ ├── dependencies/ # DEP-001 through DEP-007 analyzers
│ ├── environment/ # ENV-001 through ENV-003 analyzers
│ ├── imports/ # IMP-001 through IMP-004 analyzers
│ └── packaging/ # PKG-001 and PKG-002 analyzers
├── remediation/
│ ├── engine.py # Remediation planner and fix executor
│ └── actions.py # Atomic manifest & TOML fix handlers
├── reporters/
│ ├── terminal.py # Rich console output formatting
│ ├── html.py # Standalone HTML report generator
│ ├── sarif.py # SARIF v2.1.0 generator
│ ├── json.py # JSON exporter
│ └── github.py # GitHub Actions PR annotation emitter
├── tui/
│ └── app.py # Interactive Rich terminal explorer
└── visualizers/
├── architecture.py # Architectural layer map, ASCII flow, and Mermaid exporter
├── risk_graph.py # Dependency risk & blast radius graph
└── tree.py # Dependency & circular import visualizer