Architecture & Internal Design
qv 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. qv 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/qv/analyzers/. Each analyzer accepts the immutable ProjectContext and yields structured Diagnostic instances.
3.1 Dependencies Analyzer (src/qv/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/qv/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/qv/analyzers/imports/)
- Circular Import Cycle Detection: Constructs a directed module dependency graph and uses Tarjan's Strongly Connected Components (SCC) algorithm to identify recursive import loops.
- Unresolved Local Imports: Flags imports that reference non-existent local packages or missing
__init__.pyfiles. - Orphan / Dead File Detection: Identifies Python modules that are never imported by any other module, test file, or console script entry point.
3.4 Packaging Analyzer (src/qv/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 qv flows through immutable, strictly typed dataclasses defined in src/qv/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.qv].
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
qv scores project health on a scale from 0 to 100:
$$\text{Health Score} = \max\left(0, 100 - \sum \text{Severity Penalties}\right)$$
5.1 Severity Penalties
| Finding Severity | Base Penalty | Behavior in Strict / CI Mode |
|---|---|---|
ERROR |
-15 points | Fails scan immediately (exit code 1). |
WARNING |
-5 points | Fails scan if --strict or --ci is enabled. |
INFO |
-1 point | Non-blocking advisory finding. |
5.2 Score Color Thresholds
- Green (Healthy): $80 \le \text{Score} \le 100$
- Yellow (Degraded): $50 \le \text{Score} \le 79$
- Red (Critical): $0 \le \text{Score} \le 49$
6. Safe Automated Remediation Engine
The remediation engine (src/qv/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
qv fix --dry-run. - Reversible Fix Actions: Fixes are scoped to specific files with atomic writes.
- Package Manager Auto-Sync: When
--syncis passed,qvautomatically 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 (
qv inspect): Rich terminal interface with dual panes, scrolling, keyboard shortcuts, and live dependency tree toggling. - Standalone HTML Report (
qv 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/qv/
├── __init__.py # Package version and public exports
├── cli.py # Click CLI entry point and subcommands
├── core/
│ ├── config.py # [tool.qv] configuration loader
│ ├── context.py # ProjectContext discovery & data ingestion
│ ├── models.py # Diagnostic, Severity, ScanResult dataclasses
│ └── rules.py # RuleCatalog registry
├── analyzers/
│ ├── dependencies/ # DEP-001 through DEP-006 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/
│ └── dashboard.py # Interactive Rich terminal explorer
└── visualizers/
└── tree.py # Dependency & circular import visualizer