python-qv 0.1.1__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. python_qv-0.1.3/.github/workflows/docs.yml +55 -0
  2. python_qv-0.1.3/.readthedocs.yaml +18 -0
  3. {python_qv-0.1.1 → python_qv-0.1.3}/PKG-INFO +11 -3
  4. {python_qv-0.1.1 → python_qv-0.1.3}/README.md +8 -1
  5. python_qv-0.1.3/docs/architecture.md +211 -0
  6. python_qv-0.1.3/docs/assets/favicon.svg +10 -0
  7. python_qv-0.1.3/docs/assets/logo.svg +17 -0
  8. {python_qv-0.1.1 → python_qv-0.1.3}/docs/ci_integration.md +7 -7
  9. {python_qv-0.1.1 → python_qv-0.1.3}/docs/cli_reference.md +61 -26
  10. {python_qv-0.1.1 → python_qv-0.1.3}/docs/configuration.md +4 -4
  11. {python_qv-0.1.1 → python_qv-0.1.3}/docs/contributing.md +17 -16
  12. {python_qv-0.1.1 → python_qv-0.1.3}/docs/getting_started.md +58 -22
  13. {python_qv-0.1.1 → python_qv-0.1.3}/docs/html_report.md +10 -10
  14. python_qv-0.1.3/docs/index.md +249 -0
  15. {python_qv-0.1.1 → python_qv-0.1.3}/docs/pre_commit.md +6 -6
  16. {python_qv-0.1.1 → python_qv-0.1.3}/docs/remediation.md +5 -5
  17. python_qv-0.1.3/docs/requirements.txt +3 -0
  18. python_qv-0.1.3/docs/rules.md +444 -0
  19. {python_qv-0.1.1 → python_qv-0.1.3}/docs/tree.md +6 -6
  20. {python_qv-0.1.1 → python_qv-0.1.3}/docs/tui.md +9 -8
  21. python_qv-0.1.3/examples/fastapi_issues/main.py +61 -0
  22. python_qv-0.1.3/examples/fastapi_issues/pyproject.toml +9 -0
  23. {python_qv-0.1.1 → python_qv-0.1.3}/mkdocs.yml +32 -13
  24. {python_qv-0.1.1 → python_qv-0.1.3}/pyproject.toml +3 -2
  25. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/__init__.py +1 -1
  26. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/cli/main.py +84 -0
  27. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/core/engine.py +4 -0
  28. python_qv-0.1.3/src/qv/frameworks/__init__.py +19 -0
  29. python_qv-0.1.3/src/qv/frameworks/base.py +25 -0
  30. python_qv-0.1.3/src/qv/frameworks/fastapi.py +2219 -0
  31. python_qv-0.1.3/src/qv/frameworks/sqlalchemy.py +1580 -0
  32. python_qv-0.1.3/src/qv/rules/registry.py +783 -0
  33. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_cli.py +50 -0
  34. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_examples.py +17 -0
  35. python_qv-0.1.3/tests/test_fastapi.py +960 -0
  36. python_qv-0.1.3/tests/test_sqlalchemy.py +636 -0
  37. {python_qv-0.1.1 → python_qv-0.1.3}/uv.lock +741 -737
  38. python_qv-0.1.1/.readthedocs.yaml +0 -16
  39. python_qv-0.1.1/docs/index.md +0 -60
  40. python_qv-0.1.1/docs/rules.md +0 -94
  41. python_qv-0.1.1/src/qv/frameworks/__init__.py +0 -1
  42. python_qv-0.1.1/src/qv/rules/registry.py +0 -169
  43. {python_qv-0.1.1 → python_qv-0.1.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  44. {python_qv-0.1.1 → python_qv-0.1.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  45. {python_qv-0.1.1 → python_qv-0.1.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  46. {python_qv-0.1.1 → python_qv-0.1.3}/.github/ISSUE_TEMPLATE/rule_proposal.yml +0 -0
  47. {python_qv-0.1.1 → python_qv-0.1.3}/.github/pull_request_template.md +0 -0
  48. {python_qv-0.1.1 → python_qv-0.1.3}/.github/workflows/ci.yml +0 -0
  49. {python_qv-0.1.1 → python_qv-0.1.3}/.github/workflows/publish.yml +0 -0
  50. {python_qv-0.1.1 → python_qv-0.1.3}/.gitignore +0 -0
  51. {python_qv-0.1.1 → python_qv-0.1.3}/.pre-commit-config.yaml +0 -0
  52. {python_qv-0.1.1 → python_qv-0.1.3}/.pre-commit-hooks.yaml +0 -0
  53. {python_qv-0.1.1 → python_qv-0.1.3}/CHANGELOG.md +0 -0
  54. {python_qv-0.1.1 → python_qv-0.1.3}/CONTRIBUTING.md +0 -0
  55. {python_qv-0.1.1 → python_qv-0.1.3}/SECURITY.md +0 -0
  56. {python_qv-0.1.1 → python_qv-0.1.3}/action.yml +0 -0
  57. {python_qv-0.1.1 → python_qv-0.1.3}/examples/README.md +0 -0
  58. {python_qv-0.1.1 → python_qv-0.1.3}/examples/all_in_one_unhealthy/Dockerfile +0 -0
  59. {python_qv-0.1.1 → python_qv-0.1.3}/examples/all_in_one_unhealthy/cycle_a.py +0 -0
  60. {python_qv-0.1.1 → python_qv-0.1.3}/examples/all_in_one_unhealthy/cycle_b.py +0 -0
  61. {python_qv-0.1.1 → python_qv-0.1.3}/examples/all_in_one_unhealthy/main.py +0 -0
  62. {python_qv-0.1.1 → python_qv-0.1.3}/examples/all_in_one_unhealthy/pyproject.toml +0 -0
  63. {python_qv-0.1.1 → python_qv-0.1.3}/examples/circular_imports/module_a.py +0 -0
  64. {python_qv-0.1.1 → python_qv-0.1.3}/examples/circular_imports/module_b.py +0 -0
  65. {python_qv-0.1.1 → python_qv-0.1.3}/examples/circular_imports/pyproject.toml +0 -0
  66. {python_qv-0.1.1 → python_qv-0.1.3}/examples/dead_modules/active_feature.py +0 -0
  67. {python_qv-0.1.1 → python_qv-0.1.3}/examples/dead_modules/main.py +0 -0
  68. {python_qv-0.1.1 → python_qv-0.1.3}/examples/dead_modules/pyproject.toml +0 -0
  69. {python_qv-0.1.1 → python_qv-0.1.3}/examples/dead_modules/unused_legacy_module.py +0 -0
  70. {python_qv-0.1.1 → python_qv-0.1.3}/examples/deprecated_stdlib/legacy_app.py +0 -0
  71. {python_qv-0.1.1 → python_qv-0.1.3}/examples/deprecated_stdlib/pyproject.toml +0 -0
  72. {python_qv-0.1.1 → python_qv-0.1.3}/examples/environment_drift/.github/workflows/ci.yml +0 -0
  73. {python_qv-0.1.1 → python_qv-0.1.3}/examples/environment_drift/Dockerfile +0 -0
  74. {python_qv-0.1.1 → python_qv-0.1.3}/examples/environment_drift/pyproject.toml +0 -0
  75. {python_qv-0.1.1 → python_qv-0.1.3}/examples/missing_dependencies/main.py +0 -0
  76. {python_qv-0.1.1 → python_qv-0.1.3}/examples/missing_dependencies/pyproject.toml +0 -0
  77. {python_qv-0.1.1 → python_qv-0.1.3}/examples/missing_metadata/pyproject.toml +0 -0
  78. {python_qv-0.1.1 → python_qv-0.1.3}/examples/unresolved_imports/pyproject.toml +0 -0
  79. {python_qv-0.1.1 → python_qv-0.1.3}/examples/unresolved_imports/service.py +0 -0
  80. {python_qv-0.1.1 → python_qv-0.1.3}/examples/unused_dependencies/app.py +0 -0
  81. {python_qv-0.1.1 → python_qv-0.1.3}/examples/unused_dependencies/pyproject.toml +0 -0
  82. {python_qv-0.1.1 → python_qv-0.1.3}/examples/vulnerable_dependencies/app.py +0 -0
  83. {python_qv-0.1.1 → python_qv-0.1.3}/examples/vulnerable_dependencies/pyproject.toml +0 -0
  84. {python_qv-0.1.1 → python_qv-0.1.3}/examples/vulnerable_dependencies/requirements.txt +0 -0
  85. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/__main__.py +0 -0
  86. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/__init__.py +0 -0
  87. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/ci/__init__.py +0 -0
  88. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/dependencies/__init__.py +0 -0
  89. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/dependencies/analyzer.py +0 -0
  90. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/docker/__init__.py +0 -0
  91. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/environment/__init__.py +0 -0
  92. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/environment/drift.py +0 -0
  93. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/imports/__init__.py +0 -0
  94. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/imports/analyzer.py +0 -0
  95. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/packaging/__init__.py +0 -0
  96. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/packaging/analyzer.py +0 -0
  97. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/security/__init__.py +0 -0
  98. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/security/analyzer.py +0 -0
  99. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/security/lockfile_parser.py +0 -0
  100. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/analyzers/security/osv_client.py +0 -0
  101. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/cli/__init__.py +0 -0
  102. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/core/analyzer.py +0 -0
  103. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/core/config.py +0 -0
  104. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/core/context.py +0 -0
  105. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/core/models.py +0 -0
  106. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/core/project.py +0 -0
  107. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/integrations/__init__.py +0 -0
  108. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/remediation/__init__.py +0 -0
  109. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/remediation/engine.py +0 -0
  110. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/remediation/models.py +0 -0
  111. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/__init__.py +0 -0
  112. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/base.py +0 -0
  113. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/github_annotator.py +0 -0
  114. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/html_reporter.py +0 -0
  115. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/json_reporter.py +0 -0
  116. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/sarif.py +0 -0
  117. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/reporters/terminal.py +0 -0
  118. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/tui/__init__.py +0 -0
  119. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/tui/app.py +0 -0
  120. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/visualizers/__init__.py +0 -0
  121. {python_qv-0.1.1 → python_qv-0.1.3}/src/qv/visualizers/tree.py +0 -0
  122. {python_qv-0.1.1 → python_qv-0.1.3}/tests/analyzers/test_dependencies.py +0 -0
  123. {python_qv-0.1.1 → python_qv-0.1.3}/tests/analyzers/test_environment.py +0 -0
  124. {python_qv-0.1.1 → python_qv-0.1.3}/tests/analyzers/test_imports.py +0 -0
  125. {python_qv-0.1.1 → python_qv-0.1.3}/tests/analyzers/test_packaging.py +0 -0
  126. {python_qv-0.1.1 → python_qv-0.1.3}/tests/analyzers/test_security.py +0 -0
  127. {python_qv-0.1.1 → python_qv-0.1.3}/tests/conftest.py +0 -0
  128. {python_qv-0.1.1 → python_qv-0.1.3}/tests/reporters/test_github_annotator.py +0 -0
  129. {python_qv-0.1.1 → python_qv-0.1.3}/tests/reporters/test_html.py +0 -0
  130. {python_qv-0.1.1 → python_qv-0.1.3}/tests/reporters/test_reporters.py +0 -0
  131. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_config.py +0 -0
  132. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_lockfile_parser.py +0 -0
  133. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_models.py +0 -0
  134. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_pre_commit_hooks.py +0 -0
  135. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_remediation.py +0 -0
  136. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_rules.py +0 -0
  137. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_tree.py +0 -0
  138. {python_qv-0.1.1 → python_qv-0.1.3}/tests/test_tui.py +0 -0
  139. {python_qv-0.1.1 → python_qv-0.1.3}/tox.ini +0 -0
@@ -0,0 +1,55 @@
1
+ name: Deploy Documentation
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ pages: write
12
+ id-token: write
13
+
14
+ concurrency:
15
+ group: pages
16
+ cancel-in-progress: false
17
+
18
+ jobs:
19
+ build:
20
+ name: Build Documentation
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - name: Checkout repository
24
+ uses: actions/checkout@v4
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v5
28
+ with:
29
+ version: "latest"
30
+
31
+ - name: Set up Python 3.12
32
+ run: uv python install 3.12
33
+
34
+ - name: Install dependencies
35
+ run: uv sync --all-extras
36
+
37
+ - name: Build MkDocs Site in Strict Mode
38
+ run: uv run mkdocs build --strict
39
+
40
+ - name: Upload artifact for GitHub Pages
41
+ uses: actions/upload-pages-artifact@v3
42
+ with:
43
+ path: site
44
+
45
+ deploy:
46
+ name: Deploy to GitHub Pages
47
+ environment:
48
+ name: github-pages
49
+ url: ${{ steps.deployment.outputs.page_url }}
50
+ runs-on: ubuntu-latest
51
+ needs: build
52
+ steps:
53
+ - name: Deploy to GitHub Pages
54
+ id: deployment
55
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,18 @@
1
+ # Read the Docs configuration file
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ version: 2
5
+
6
+ build:
7
+ os: ubuntu-24.04
8
+ tools:
9
+ python: "3.12"
10
+
11
+ # Build documentation using MkDocs
12
+ mkdocs:
13
+ configuration: mkdocs.yml
14
+
15
+ # Install docs dependencies
16
+ python:
17
+ install:
18
+ - requirements: docs/requirements.txt
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-qv
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Diagnose why a Python project is unhealthy — explain root cause and suggest safe fixes.
5
5
  Project-URL: Homepage, https://github.com/inzamol/qv
6
6
  Project-URL: Repository, https://github.com/inzamol/qv
7
- Project-URL: Documentation, https://qv.readthedocs.io/
7
+ Project-URL: Documentation, https://inzamol.github.io/qv/
8
8
  Project-URL: Issues, https://github.com/inzamol/qv/issues
9
9
  Author: Inzamul Hoque
10
10
  License-Expression: MIT
@@ -34,6 +34,7 @@ Requires-Dist: tox-uv>=1.7.0; extra == 'dev'
34
34
  Requires-Dist: tox>=4.15.0; extra == 'dev'
35
35
  Provides-Extra: docs
36
36
  Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
37
+ Requires-Dist: mkdocs<2.0.0,>=1.6.0; extra == 'docs'
37
38
  Requires-Dist: pymdown-extensions>=10.7.0; extra == 'docs'
38
39
  Description-Content-Type: text/markdown
39
40
 
@@ -198,8 +199,10 @@ Run `qv inspect` (or `qv ui`) for a full terminal dashboard:
198
199
  | | `IMP-002` | Unresolved relative or internal module imports | `ERROR` |
199
200
  | **Packaging** | `PKG-001` | Missing PEP 621 metadata (name, version, etc.) | `WARNING` |
200
201
  | | `PKG-002` | Invalid syntax or malformed keys in `pyproject.toml` | `ERROR` |
202
+ | **FastAPI Doctor** | `FAP-001`–`FAP-038` | Async blocking calls, CPU starvation in endpoints, insecure CORS, missing timeouts, lifecycle anti-patterns, Pydantic v2 migrations | `ERROR` / `WARNING` |
203
+ | **SQL & Database** | `SQL-001`–`SQL-030` | N+1 queries in loops, session leaks, SQL injection, sync DB in async loop, missing eager loading, pool starvation, 2.0 syntax | `ERROR` / `WARNING` |
201
204
 
202
- 👉 *See full explanations and remediation steps in the [Rules Catalog](docs/rules.md).*
205
+ 👉 *See all 80+ rules and remediation steps in the [Rules Catalog](docs/rules.md).*
203
206
 
204
207
  ---
205
208
 
@@ -330,6 +333,11 @@ qv environment
330
333
 
331
334
  # Check AST & imports only (circular import loops, unresolvable modules)
332
335
  qv architecture
336
+
337
+ # Check framework-specific issues (FastAPI, SQLAlchemy, SQLModel)
338
+ qv framework
339
+ qv framework --name fastapi
340
+ qv framework --name sqlalchemy
333
341
  ```
334
342
 
335
343
  ---
@@ -159,8 +159,10 @@ Run `qv inspect` (or `qv ui`) for a full terminal dashboard:
159
159
  | | `IMP-002` | Unresolved relative or internal module imports | `ERROR` |
160
160
  | **Packaging** | `PKG-001` | Missing PEP 621 metadata (name, version, etc.) | `WARNING` |
161
161
  | | `PKG-002` | Invalid syntax or malformed keys in `pyproject.toml` | `ERROR` |
162
+ | **FastAPI Doctor** | `FAP-001`–`FAP-038` | Async blocking calls, CPU starvation in endpoints, insecure CORS, missing timeouts, lifecycle anti-patterns, Pydantic v2 migrations | `ERROR` / `WARNING` |
163
+ | **SQL & Database** | `SQL-001`–`SQL-030` | N+1 queries in loops, session leaks, SQL injection, sync DB in async loop, missing eager loading, pool starvation, 2.0 syntax | `ERROR` / `WARNING` |
162
164
 
163
- 👉 *See full explanations and remediation steps in the [Rules Catalog](docs/rules.md).*
165
+ 👉 *See all 80+ rules and remediation steps in the [Rules Catalog](docs/rules.md).*
164
166
 
165
167
  ---
166
168
 
@@ -291,6 +293,11 @@ qv environment
291
293
 
292
294
  # Check AST & imports only (circular import loops, unresolvable modules)
293
295
  qv architecture
296
+
297
+ # Check framework-specific issues (FastAPI, SQLAlchemy, SQLModel)
298
+ qv framework
299
+ qv framework --name fastapi
300
+ qv framework --name sqlalchemy
294
301
  ```
295
302
 
296
303
  ---
@@ -0,0 +1,211 @@
1
+ # Architecture & Internal Design
2
+
3
+ `qv` is built as an offline-first, modular diagnostic engine designed to analyze Python project ecosystems in sub-second execution time.
4
+
5
+ ---
6
+
7
+ ## 1. System Overview
8
+
9
+ 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:
10
+
11
+ 1. **Manifests**: `pyproject.toml`, `requirements.txt`, `setup.cfg`, `Pipfile`.
12
+ 2. **Active Environment**: `sys.executable`, `site-packages`, `importlib.metadata` distributions, and installed version constraints.
13
+ 3. **Source Code AST**: Module import references, circular call loops, and orphan files.
14
+ 4. **Runtime & Infrastructure**: `Dockerfile`, `docker-compose.yml`, and `.github/workflows/` CI matrices.
15
+
16
+ ```text
17
+ CLI / TUI (click + rich)
18
+ │
19
+ Project Discovery
20
+ │
21
+ ProjectContext (Immutable)
22
+ │
23
+ ┌───────────────┬──────────────┴───────────────┬────────────────┐
24
+ Dependencies Environment Imports Packaging
25
+ Analyzer Analyzer Analyzer Analyzer
26
+ └───────────────┼──────────────────────────────┴────────────────┘
27
+ │
28
+ AnalysisEngine
29
+ │
30
+ Diagnostic Model
31
+ │
32
+ Root Cause Correlator
33
+ │
34
+ ┌──────────────┬─────────────┼─────────────┬──────────────┬──────────────┐
35
+ Terminal JSON SARIF HTML GitHub Actions Interactive
36
+ Reporter Reporter Reporter Reporter Annotator TUI Dashboard
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 2. End-to-End Diagnostic Pipeline
42
+
43
+ The diagram below illustrates the complete lifecycle from project path discovery through multi-channel report generation:
44
+
45
+ ```mermaid
46
+ flowchart TD
47
+ subgraph Discovery["1. Discovery & Context Ingestion"]
48
+ A["<b>File System Scanner</b><br/>Walks project root, excludes ignored paths"]
49
+ B["<b>Manifest Parser</b><br/>Parses PEP 621, Poetry, Flit, setuptools, requirements"]
50
+ C["<b>Environment Inspector</b><br/>Inspects active virtualenv & installed distributions"]
51
+ D["<b>AST Module Parser</b><br/>Extracts import statements & relative import trees"]
52
+ E["<b>Infrastructure Parser</b><br/>Extracts Docker base images & CI matrix versions"]
53
+ end
54
+
55
+ subgraph Context["2. Immutable Context"]
56
+ CTX["<b>ProjectContext</b><br/>Frozen snapshot of project metadata, AST, and environment"]
57
+ end
58
+
59
+ subgraph Analyzers["3. Subsystem Analyzers"]
60
+ F1["<b>Dependencies Analyzer</b><br/>Conflict resolution, undeclared/unused packages"]
61
+ F2["<b>Environment Analyzer</b><br/>Python interpreter, Docker, and CI drift"]
62
+ F3["<b>Imports Analyzer</b><br/>Tarjan's cycle algorithm & unresolvable modules"]
63
+ F4["<b>Packaging Analyzer</b><br/>PEP 621 compliance & schema validation"]
64
+ end
65
+
66
+ subgraph Correlation["4. Correlation & Scoring"]
67
+ G["<b>Analysis Engine & Correlator</b><br/>Aggregates findings, deduplicates evidence"]
68
+ H["<b>Health Score Calculator</b><br/>Applies severity penalties (0–100 score)"]
69
+ end
70
+
71
+ subgraph Reporters["5. Reporting & Remediation"]
72
+ R1["<b>Terminal Reporter</b><br/>Colorized Rich tables & boxes"]
73
+ R2["<b>Interactive TUI</b><br/>Live dashboard with keyboard navigation"]
74
+ R3["<b>Self-Contained HTML</b><br/>Single-file interactive report with SVG gauges"]
75
+ R4["<b>SARIF v2.1.0 & JSON</b><br/>GitHub Security & CI integration"]
76
+ R5["<b>Remediation Engine</b><br/>Safe diff generator & sync coordinator"]
77
+ end
78
+
79
+ Discovery --> CTX
80
+ CTX --> Analyzers
81
+ Analyzers --> Correlation
82
+ Correlation --> Reporters
83
+ ```
84
+
85
+ ---
86
+
87
+ ## 3. Subsystem Analyzers
88
+
89
+ All diagnostic checks are implemented as independent analyzers under `src/qv/analyzers/`. Each analyzer accepts the immutable `ProjectContext` and yields structured `Diagnostic` instances.
90
+
91
+ ### 3.1 Dependencies Analyzer (`src/qv/analyzers/dependencies/`)
92
+ - **Constraint Conflict Engine**: Validates installed package versions against declared PEP 508 version specifiers.
93
+ - **Missing Dependency Detection**: Identifies third-party packages imported in source code that are missing from `pyproject.toml` or requirements files.
94
+ - **Unused Dependency Detection**: Pinpoints direct declared dependencies that are never referenced across project source files.
95
+ - **Standard Library Awareness**: Includes exhaustive Python 3.10–3.13 stdlib catalogs (accounting for PEP 594 removals).
96
+
97
+ ### 3.2 Environment & Drift Analyzer (`src/qv/analyzers/environment/`)
98
+ - **Python Version Drift**: Compares the active virtualenv interpreter version against `requires-python` or target runtime.
99
+ - **Container Drift**: Scans `Dockerfile` and `compose.yml` for base image Python version tags that diverge from project targets.
100
+ - **CI Matrix Drift**: Verifies that GitHub Actions matrix definitions cover the Python versions declared in project manifests.
101
+
102
+ ### 3.3 Imports & AST Analyzer (`src/qv/analyzers/imports/`)
103
+ - **Circular Import Cycle Detection**: Constructs a directed module dependency graph and uses **Tarjan's Strongly Connected Components (SCC)** algorithm to identify recursive import loops.
104
+ - **Unresolved Local Imports**: Flags imports that reference non-existent local packages or missing `__init__.py` files.
105
+ - **Orphan / Dead File Detection**: Identifies Python modules that are never imported by any other module, test file, or console script entry point.
106
+
107
+ ### 3.4 Packaging Analyzer (`src/qv/analyzers/packaging/`)
108
+ - **PEP 621 Schema Validation**: Ensures required tables (`[project]`, `name`, `version`) are present and syntactically valid.
109
+ - **Build Backend Consistency**: Verifies configuration compatibility with standard build tools (`setuptools`, `flit_core`, `hatchling`, `poetry.core`, `pdm.backend`).
110
+
111
+ ---
112
+
113
+ ## 4. Immutable Core Models
114
+
115
+ All state within `qv` flows through immutable, strictly typed dataclasses defined in `src/qv/core/`:
116
+
117
+ ### 4.1 `ProjectContext`
118
+ A frozen snapshot of discovered project assets:
119
+ - `root_dir`: Absolute project path.
120
+ - `manifest`: Parsed `pyproject.toml` or requirements metadata.
121
+ - `environment`: Active Python interpreter version, virtualenv path, and installed distributions.
122
+ - `source_files`: Parsed AST trees and imported module sets.
123
+ - `config`: User configuration loaded from `[tool.qv]`.
124
+
125
+ ### 4.2 `Diagnostic`
126
+ A structured diagnostic finding:
127
+ - `rule_id`: Stable identifier (e.g. `DEP-001`, `IMP-001`).
128
+ - `title`: Short human-readable summary.
129
+ - `severity`: `ERROR`, `WARNING`, `INFO`.
130
+ - `message`: Specific description of the root cause.
131
+ - `location`: Optional file path and line number.
132
+ - `evidence`: Bulleted list of facts discovered during analysis.
133
+ - `suggestions`: Recommended CLI commands or code modifications.
134
+ - `fix_action`: Optional automated remediation plan.
135
+
136
+ ---
137
+
138
+ ## 5. Root Cause Engine & Health Scoring
139
+
140
+ `qv` scores project health on a scale from **0 to 100**:
141
+
142
+ $$\text{Health Score} = \max\left(0, 100 - \sum \text{Severity Penalties}\right)$$
143
+
144
+ ### 5.1 Severity Penalties
145
+
146
+ | Finding Severity | Base Penalty | Behavior in Strict / CI Mode |
147
+ |---|---|---|
148
+ | **`ERROR`** | **-15 points** | Fails scan immediately (exit code 1). |
149
+ | **`WARNING`** | **-5 points** | Fails scan if `--strict` or `--ci` is enabled. |
150
+ | **`INFO`** | **-1 point** | Non-blocking advisory finding. |
151
+
152
+ ### 5.2 Score Color Thresholds
153
+ - **Green (Healthy)**: $80 \le \text{Score} \le 100$
154
+ - **Yellow (Degraded)**: $50 \le \text{Score} \le 79$
155
+ - **Red (Critical)**: $0 \le \text{Score} \le 49$
156
+
157
+ ---
158
+
159
+ ## 6. Safe Automated Remediation Engine
160
+
161
+ The remediation engine (`src/qv/remediation/`) adheres to strict safety guarantees:
162
+
163
+ 1. **Non-Destructive AST/TOML Editing**: Modifications to `pyproject.toml` preserve existing formatting, comments, and unrelated tables.
164
+ 2. **Dry-Run Diff Generation**: All proposed fixes can be inspected in advance via `qv fix --dry-run`.
165
+ 3. **Reversible Fix Actions**: Fixes are scoped to specific files with atomic writes.
166
+ 4. **Package Manager Auto-Sync**: When `--sync` is passed, `qv` automatically invokes the project's native tool (`uv sync`, `poetry install`, `pip install`) to update the virtualenv.
167
+
168
+ ---
169
+
170
+ ## 7. Multi-Channel Reporting Pipeline
171
+
172
+ Diagnostics can be formatted and routed to multiple consumers:
173
+
174
+ - **Terminal Reporter**: Human-readable colorized output with evidence boxes and suggestion snippets.
175
+ - **Interactive TUI Dashboard (`qv inspect`)**: Rich terminal interface with dual panes, scrolling, keyboard shortcuts, and live dependency tree toggling.
176
+ - **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.
177
+ - **SARIF v2.1.0 Reporter**: Standard OASIS SARIF format for GitHub Advanced Security and Code Scanning alerts.
178
+ - **JSON Reporter**: Machine-readable output for custom scripts and dashboard ingestion.
179
+
180
+ ---
181
+
182
+ ## 8. Codebase Directory Map
183
+
184
+ ```text
185
+ src/qv/
186
+ ├── __init__.py # Package version and public exports
187
+ ├── cli.py # Click CLI entry point and subcommands
188
+ ├── core/
189
+ │ ├── config.py # [tool.qv] configuration loader
190
+ │ ├── context.py # ProjectContext discovery & data ingestion
191
+ │ ├── models.py # Diagnostic, Severity, ScanResult dataclasses
192
+ │ └── rules.py # RuleCatalog registry
193
+ ├── analyzers/
194
+ │ ├── dependencies/ # DEP-001 through DEP-006 analyzers
195
+ │ ├── environment/ # ENV-001 through ENV-003 analyzers
196
+ │ ├── imports/ # IMP-001 through IMP-004 analyzers
197
+ │ └── packaging/ # PKG-001 and PKG-002 analyzers
198
+ ├── remediation/
199
+ │ ├── engine.py # Remediation planner and fix executor
200
+ │ └── actions.py # Atomic manifest & TOML fix handlers
201
+ ├── reporters/
202
+ │ ├── terminal.py # Rich console output formatting
203
+ │ ├── html.py # Standalone HTML report generator
204
+ │ ├── sarif.py # SARIF v2.1.0 generator
205
+ │ ├── json.py # JSON exporter
206
+ │ └── github.py # GitHub Actions PR annotation emitter
207
+ ├── tui/
208
+ │ └── dashboard.py # Interactive Rich terminal explorer
209
+ └── visualizers/
210
+ └── tree.py # Dependency & circular import visualizer
211
+ ```
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
2
+ <rect width="64" height="64" rx="14" fill="#09090B" stroke="#27272A" stroke-width="1.5" />
3
+
4
+ <!-- 'q' glyph -->
5
+ <circle cx="23" cy="29" r="9" fill="none" stroke="#FFFFFF" stroke-width="4.2" />
6
+ <path d="M32 20 L32 44" stroke="#FFFFFF" stroke-width="4.2" stroke-linecap="round" />
7
+
8
+ <!-- 'v' glyph -->
9
+ <path d="M37 23 L44 39 L51 23" fill="none" stroke="#E4E4E7" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round" />
10
+ </svg>
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" width="100%" height="100%">
2
+ <!-- Background Badge / Squircle -->
3
+ <rect x="8" y="8" width="104" height="104" rx="26" fill="#09090B" stroke="#27272A" stroke-width="2" />
4
+
5
+ <!-- Subtle inner ambient frame -->
6
+ <rect x="14" y="14" width="92" height="92" rx="20" fill="none" stroke="#18181B" stroke-width="1" />
7
+
8
+ <!-- 'q' glyph -->
9
+ <circle cx="44" cy="54" r="16" fill="none" stroke="#FFFFFF" stroke-width="7" />
10
+ <path d="M60 38 L60 80" stroke="#FFFFFF" stroke-width="7" stroke-linecap="round" />
11
+
12
+ <!-- 'v' glyph -->
13
+ <path d="M68 42 L80 72 L92 42" fill="none" stroke="#E4E4E7" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" />
14
+
15
+ <!-- Diagnostic focal dot -->
16
+ <circle cx="94" cy="34" r="3" fill="#A1A1AA" />
17
+ </svg>
@@ -4,7 +4,7 @@
4
4
 
5
5
  ---
6
6
 
7
- ## Official GitHub Action (`inzamol/qv`)
7
+ ## 1. Official GitHub Action (`inzamol/qv`)
8
8
 
9
9
  Use the official composite GitHub Action to run `qv` with automated PR annotations and step summaries:
10
10
 
@@ -28,9 +28,9 @@ jobs:
28
28
 
29
29
  ---
30
30
 
31
- ## Custom CI Configuration
31
+ ## 2. Custom CI Configuration
32
32
 
33
- ### Basic CI Check
33
+ ### 2.1 Basic CI Check
34
34
 
35
35
  Add a step to your `.github/workflows/ci.yml`:
36
36
 
@@ -52,7 +52,7 @@ jobs:
52
52
 
53
53
  ---
54
54
 
55
- ### GitHub Code Scanning with SARIF
55
+ ### 2.2 GitHub Code Scanning with SARIF
56
56
 
57
57
  `qv` supports emitting findings in **SARIF v2.1.0** format for GitHub Advanced Security and Code Scanning:
58
58
 
@@ -84,7 +84,7 @@ jobs:
84
84
 
85
85
  ---
86
86
 
87
- ## Pre-commit Integration
87
+ ## 3. Pre-commit Integration
88
88
 
89
89
  `qv` provides native pre-commit hooks via `.pre-commit-hooks.yaml`.
90
90
 
@@ -103,7 +103,7 @@ repos:
103
103
  # - id: qv-fix
104
104
  ```
105
105
 
106
- ### Available Hooks
106
+ ### 3.1 Available Hooks
107
107
 
108
108
  | Hook ID | Description | Default Command |
109
109
  |---|---|---|
@@ -112,7 +112,7 @@ repos:
112
112
 
113
113
  ---
114
114
 
115
- ## Exit Codes for CI Pipelines
115
+ ## 4. Exit Codes for CI Pipelines
116
116
 
117
117
  - `0`: Success — no blocking findings.
118
118
  - `1`: Failure — errors found (or warnings in `--strict` / `--ci` mode).
@@ -4,7 +4,7 @@
4
4
 
5
5
  ---
6
6
 
7
- ## Global Options
7
+ ## 1. Global Options
8
8
 
9
9
  ```bash
10
10
  qv --help
@@ -13,7 +13,27 @@ qv --version
13
13
 
14
14
  ---
15
15
 
16
- ## `qv scan`
16
+ ## 2. `qv init`
17
+
18
+ Generates or updates the `[tool.qv]` configuration block in your `pyproject.toml` without overwriting existing settings.
19
+
20
+ ```bash
21
+ qv init [PATH]
22
+ ```
23
+
24
+ Example:
25
+
26
+ ```bash
27
+ # Initialize [tool.qv] in current directory
28
+ qv init
29
+
30
+ # Initialize in a specific project path
31
+ qv init ./services/backend
32
+ ```
33
+
34
+ ---
35
+
36
+ ## 3. `qv scan`
17
37
 
18
38
  Runs full diagnostic analysis on the specified directory.
19
39
 
@@ -21,13 +41,13 @@ Runs full diagnostic analysis on the specified directory.
21
41
  qv scan [PATH] [OPTIONS]
22
42
  ```
23
43
 
24
- ### Arguments
44
+ ### 3.1 Arguments
25
45
 
26
46
  | Argument | Description | Default |
27
47
  |---|---|---|
28
48
  | `PATH` | Path to the project root directory | `.` (current directory) |
29
49
 
30
- ### Options
50
+ ### 3.2 Options
31
51
 
32
52
  | Option | Description |
33
53
  |---|---|
@@ -40,7 +60,7 @@ qv scan [PATH] [OPTIONS]
40
60
  | `--offline` | Disables remote vulnerability/CVE queries (airgapped mode) |
41
61
  | `--output`, `-o <FILE>` | Writes output directly to a file |
42
62
 
43
- ### Exit Codes
63
+ ### 3.3 Exit Codes
44
64
 
45
65
  | Exit Code | Meaning |
46
66
  |---|---|
@@ -51,7 +71,7 @@ qv scan [PATH] [OPTIONS]
51
71
 
52
72
  ---
53
73
 
54
- ## `qv inspect` (alias: `qv ui`)
74
+ ## 4. `qv inspect` (alias: `qv ui`)
55
75
 
56
76
  Launches an interactive terminal dashboard (TUI) to navigate findings, expand evidence, view dependency trees, and apply fixes interactively with keyboard shortcuts.
57
77
 
@@ -60,7 +80,7 @@ qv inspect [PATH] [OPTIONS]
60
80
  qv ui [PATH] [OPTIONS]
61
81
  ```
62
82
 
63
- ### Controls
83
+ ### 4.1 Controls
64
84
 
65
85
  | Key | Action |
66
86
  |---|---|
@@ -73,7 +93,7 @@ qv ui [PATH] [OPTIONS]
73
93
 
74
94
  ---
75
95
 
76
- ## `qv fix`
96
+ ## 5. `qv fix`
77
97
 
78
98
  Safely and automatically fixes detectable diagnostic health issues (e.g., adding missing dependencies to `pyproject.toml`, removing unused dependencies, initializing packaging metadata).
79
99
 
@@ -81,7 +101,7 @@ Safely and automatically fixes detectable diagnostic health issues (e.g., adding
81
101
  qv fix [PATH] [OPTIONS]
82
102
  ```
83
103
 
84
- ### Options
104
+ ### 5.1 Options
85
105
 
86
106
  | Option | Description |
87
107
  |---|---|
@@ -102,7 +122,7 @@ qv fix -y
102
122
 
103
123
  ---
104
124
 
105
- ## `qv tree` / `qv graph`
125
+ ## 6. `qv tree` / `qv graph`
106
126
 
107
127
  Visualizes direct vs transitive package dependencies and internal source module import architecture (with circular import cycles highlighted).
108
128
 
@@ -110,7 +130,7 @@ Visualizes direct vs transitive package dependencies and internal source module
110
130
  qv tree [PATH] [OPTIONS]
111
131
  ```
112
132
 
113
- ### Options
133
+ ### 6.1 Options
114
134
 
115
135
  | Option | Description |
116
136
  |---|---|
@@ -134,7 +154,7 @@ qv tree -d -L 2
134
154
 
135
155
  ---
136
156
 
137
- ## `qv explain`
157
+ ## 7. `qv explain`
138
158
 
139
159
  Displays detailed explanations, evidence requirements, and remediation instructions for a rule.
140
160
 
@@ -150,37 +170,52 @@ qv explain DEP-002
150
170
 
151
171
  ---
152
172
 
153
- ## `qv init`
154
-
155
- Generates or updates the `[tool.qv]` configuration block in your `pyproject.toml`.
156
-
157
- ```bash
158
- qv init [PATH]
159
- ```
160
-
161
- ---
162
-
163
- ## Targeted Subsystem Commands
173
+ ## 8. Targeted Subsystem Commands
164
174
 
165
175
  Run focused checks on specific areas without executing the full scan:
166
176
 
167
- ### `qv dependency`
177
+ ### 8.1 `qv dependency`
168
178
  Scans for dependency conflicts, missing imports, unused packages, and version mismatches.
169
179
 
170
180
  ```bash
171
181
  qv dependency [PATH]
172
182
  ```
173
183
 
174
- ### `qv environment`
184
+ ### 8.2 `qv environment`
175
185
  Checks for Python runtime drift between local environment, Dockerfiles, and CI matrices.
176
186
 
177
187
  ```bash
178
188
  qv environment [PATH]
179
189
  ```
180
190
 
181
- ### `qv architecture`
191
+ ### 8.3 `qv architecture`
182
192
  Scans source code for circular imports and unresolved internal modules.
183
193
 
184
194
  ```bash
185
195
  qv architecture [PATH]
186
196
  ```
197
+
198
+ ### 8.4 `qv framework` (alias: `qv frameworks`)
199
+ Runs framework-specific diagnostic rules (e.g. FastAPI async blocking calls, SQLAlchemy N+1 queries, unclosed sessions, SQL injection, pool leaks).
200
+
201
+ ```bash
202
+ qv framework [PATH] [OPTIONS]
203
+ ```
204
+
205
+ Options:
206
+ - `-n, --name [fastapi|sqlalchemy|sql|all]`: Filter analysis to a specific framework (default: all detected frameworks).
207
+ - `--json`: Output framework scan results as structured JSON.
208
+ - `--sarif`: Output framework scan results in SARIF v2.1.0 format.
209
+
210
+ Example:
211
+ ```bash
212
+ # Scan current project for all framework issues
213
+ qv framework
214
+
215
+ # Scan specifically for FastAPI issues
216
+ qv framework --name fastapi
217
+
218
+ # Scan specifically for SQLAlchemy / SQL database issues
219
+ qv framework --name sqlalchemy
220
+ ```
221
+
@@ -4,7 +4,7 @@
4
4
 
5
5
  ---
6
6
 
7
- ## Example `pyproject.toml`
7
+ ## 1. Example `pyproject.toml`
8
8
 
9
9
  ```toml
10
10
  [tool.qv]
@@ -38,7 +38,7 @@ python = "3.12"
38
38
 
39
39
  ---
40
40
 
41
- ## Severity Overrides
41
+ ## 2. Severity Overrides
42
42
 
43
43
  You can adjust how strictly any rule is treated:
44
44
 
@@ -51,7 +51,7 @@ You can adjust how strictly any rule is treated:
51
51
 
52
52
  ---
53
53
 
54
- ## Ignore Rules
54
+ ## 3. Ignore Rules
55
55
 
56
56
  To suppress rules that are not applicable to your workflow, list them under `[tool.qv.ignore]`:
57
57
 
@@ -62,7 +62,7 @@ rules = ["DEP-003", "ENV-002"]
62
62
 
63
63
  ---
64
64
 
65
- ## Precedence Order
65
+ ## 4. Precedence Order
66
66
 
67
67
  When resolving configuration, `qv` follows this precedence:
68
68