python-qv 0.1.0__tar.gz → 0.1.1__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 (132) hide show
  1. python_qv-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +73 -0
  2. python_qv-0.1.1/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. python_qv-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
  4. python_qv-0.1.1/.github/ISSUE_TEMPLATE/rule_proposal.yml +56 -0
  5. python_qv-0.1.1/.github/pull_request_template.md +32 -0
  6. python_qv-0.1.1/.github/workflows/ci.yml +65 -0
  7. {python_qv-0.1.0 → python_qv-0.1.1}/.github/workflows/publish.yml +57 -12
  8. {python_qv-0.1.0 → python_qv-0.1.1}/.gitignore +3 -0
  9. python_qv-0.1.1/.pre-commit-config.yaml +43 -0
  10. python_qv-0.1.1/.pre-commit-hooks.yaml +17 -0
  11. python_qv-0.1.1/.readthedocs.yaml +16 -0
  12. python_qv-0.1.1/CHANGELOG.md +44 -0
  13. python_qv-0.1.1/PKG-INFO +491 -0
  14. python_qv-0.1.1/README.md +452 -0
  15. python_qv-0.1.1/SECURITY.md +32 -0
  16. python_qv-0.1.1/action.yml +64 -0
  17. {python_qv-0.1.0 → python_qv-0.1.1}/docs/ci_integration.md +54 -2
  18. python_qv-0.1.1/docs/cli_reference.md +186 -0
  19. python_qv-0.1.1/docs/contributing.md +168 -0
  20. python_qv-0.1.1/docs/html_report.md +77 -0
  21. python_qv-0.1.1/docs/index.md +60 -0
  22. python_qv-0.1.1/docs/pre_commit.md +54 -0
  23. python_qv-0.1.1/docs/remediation.md +67 -0
  24. {python_qv-0.1.0 → python_qv-0.1.1}/docs/rules.md +10 -0
  25. python_qv-0.1.1/docs/tree.md +85 -0
  26. python_qv-0.1.1/docs/tui.md +91 -0
  27. python_qv-0.1.1/examples/README.md +102 -0
  28. python_qv-0.1.1/examples/all_in_one_unhealthy/Dockerfile +7 -0
  29. python_qv-0.1.1/examples/all_in_one_unhealthy/cycle_a.py +5 -0
  30. python_qv-0.1.1/examples/all_in_one_unhealthy/cycle_b.py +5 -0
  31. python_qv-0.1.1/examples/all_in_one_unhealthy/main.py +21 -0
  32. python_qv-0.1.1/examples/all_in_one_unhealthy/pyproject.toml +10 -0
  33. python_qv-0.1.1/examples/circular_imports/module_a.py +7 -0
  34. python_qv-0.1.1/examples/circular_imports/module_b.py +7 -0
  35. python_qv-0.1.1/examples/circular_imports/pyproject.toml +6 -0
  36. python_qv-0.1.1/examples/dead_modules/active_feature.py +5 -0
  37. python_qv-0.1.1/examples/dead_modules/main.py +11 -0
  38. python_qv-0.1.1/examples/dead_modules/pyproject.toml +6 -0
  39. python_qv-0.1.1/examples/dead_modules/unused_legacy_module.py +5 -0
  40. python_qv-0.1.1/examples/deprecated_stdlib/legacy_app.py +14 -0
  41. python_qv-0.1.1/examples/deprecated_stdlib/pyproject.toml +6 -0
  42. python_qv-0.1.1/examples/environment_drift/.github/workflows/ci.yml +19 -0
  43. python_qv-0.1.1/examples/environment_drift/Dockerfile +7 -0
  44. python_qv-0.1.1/examples/environment_drift/pyproject.toml +6 -0
  45. python_qv-0.1.1/examples/missing_dependencies/main.py +25 -0
  46. python_qv-0.1.1/examples/missing_dependencies/pyproject.toml +8 -0
  47. python_qv-0.1.1/examples/missing_metadata/pyproject.toml +5 -0
  48. python_qv-0.1.1/examples/unresolved_imports/pyproject.toml +6 -0
  49. python_qv-0.1.1/examples/unresolved_imports/service.py +9 -0
  50. python_qv-0.1.1/examples/unused_dependencies/app.py +12 -0
  51. python_qv-0.1.1/examples/unused_dependencies/pyproject.toml +10 -0
  52. python_qv-0.1.1/examples/vulnerable_dependencies/app.py +13 -0
  53. python_qv-0.1.1/examples/vulnerable_dependencies/pyproject.toml +8 -0
  54. python_qv-0.1.1/examples/vulnerable_dependencies/requirements.txt +1 -0
  55. python_qv-0.1.1/mkdocs.yml +68 -0
  56. {python_qv-0.1.0 → python_qv-0.1.1}/pyproject.toml +19 -2
  57. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/__init__.py +1 -1
  58. python_qv-0.1.1/src/qv/__main__.py +6 -0
  59. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/dependencies/analyzer.py +65 -4
  60. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/environment/drift.py +75 -6
  61. python_qv-0.1.1/src/qv/analyzers/imports/analyzer.py +375 -0
  62. python_qv-0.1.1/src/qv/analyzers/security/__init__.py +13 -0
  63. python_qv-0.1.1/src/qv/analyzers/security/analyzer.py +113 -0
  64. python_qv-0.1.1/src/qv/analyzers/security/lockfile_parser.py +173 -0
  65. python_qv-0.1.1/src/qv/analyzers/security/osv_client.py +137 -0
  66. python_qv-0.1.1/src/qv/cli/main.py +583 -0
  67. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/core/config.py +4 -1
  68. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/core/engine.py +2 -0
  69. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/core/models.py +16 -0
  70. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/core/project.py +111 -6
  71. python_qv-0.1.1/src/qv/remediation/__init__.py +6 -0
  72. python_qv-0.1.1/src/qv/remediation/engine.py +302 -0
  73. python_qv-0.1.1/src/qv/remediation/models.py +62 -0
  74. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/reporters/__init__.py +2 -0
  75. python_qv-0.1.1/src/qv/reporters/github_annotator.py +88 -0
  76. python_qv-0.1.1/src/qv/reporters/html_reporter.py +511 -0
  77. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/rules/registry.py +18 -0
  78. python_qv-0.1.1/src/qv/tui/__init__.py +5 -0
  79. python_qv-0.1.1/src/qv/tui/app.py +315 -0
  80. python_qv-0.1.1/src/qv/visualizers/__init__.py +5 -0
  81. python_qv-0.1.1/src/qv/visualizers/tree.py +209 -0
  82. python_qv-0.1.1/tests/analyzers/test_imports.py +175 -0
  83. python_qv-0.1.1/tests/analyzers/test_security.py +154 -0
  84. python_qv-0.1.1/tests/reporters/test_github_annotator.py +67 -0
  85. python_qv-0.1.1/tests/reporters/test_html.py +43 -0
  86. {python_qv-0.1.0 → python_qv-0.1.1}/tests/test_cli.py +2 -1
  87. python_qv-0.1.1/tests/test_examples.py +158 -0
  88. python_qv-0.1.1/tests/test_lockfile_parser.py +148 -0
  89. python_qv-0.1.1/tests/test_pre_commit_hooks.py +20 -0
  90. python_qv-0.1.1/tests/test_remediation.py +199 -0
  91. python_qv-0.1.1/tests/test_tree.py +68 -0
  92. python_qv-0.1.1/tests/test_tui.py +57 -0
  93. python_qv-0.1.1/tox.ini +43 -0
  94. python_qv-0.1.1/uv.lock +1353 -0
  95. python_qv-0.1.0/.github/workflows/ci.yml +0 -37
  96. python_qv-0.1.0/PKG-INFO +0 -281
  97. python_qv-0.1.0/README.md +0 -248
  98. python_qv-0.1.0/docs/cli_reference.md +0 -100
  99. python_qv-0.1.0/docs/contributing.md +0 -79
  100. python_qv-0.1.0/src/qv/analyzers/imports/analyzer.py +0 -160
  101. python_qv-0.1.0/src/qv/analyzers/security/__init__.py +0 -1
  102. python_qv-0.1.0/src/qv/cli/main.py +0 -253
  103. python_qv-0.1.0/tests/analyzers/test_imports.py +0 -69
  104. python_qv-0.1.0/uv.lock +0 -562
  105. {python_qv-0.1.0 → python_qv-0.1.1}/CONTRIBUTING.md +0 -0
  106. {python_qv-0.1.0 → python_qv-0.1.1}/docs/configuration.md +0 -0
  107. {python_qv-0.1.0 → python_qv-0.1.1}/docs/getting_started.md +0 -0
  108. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/__init__.py +0 -0
  109. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/ci/__init__.py +0 -0
  110. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/dependencies/__init__.py +0 -0
  111. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/docker/__init__.py +0 -0
  112. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/environment/__init__.py +0 -0
  113. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/imports/__init__.py +0 -0
  114. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/packaging/__init__.py +0 -0
  115. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/analyzers/packaging/analyzer.py +0 -0
  116. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/cli/__init__.py +0 -0
  117. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/core/analyzer.py +0 -0
  118. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/core/context.py +0 -0
  119. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/frameworks/__init__.py +0 -0
  120. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/integrations/__init__.py +0 -0
  121. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/reporters/base.py +0 -0
  122. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/reporters/json_reporter.py +0 -0
  123. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/reporters/sarif.py +0 -0
  124. {python_qv-0.1.0 → python_qv-0.1.1}/src/qv/reporters/terminal.py +0 -0
  125. {python_qv-0.1.0 → python_qv-0.1.1}/tests/analyzers/test_dependencies.py +0 -0
  126. {python_qv-0.1.0 → python_qv-0.1.1}/tests/analyzers/test_environment.py +0 -0
  127. {python_qv-0.1.0 → python_qv-0.1.1}/tests/analyzers/test_packaging.py +0 -0
  128. {python_qv-0.1.0 → python_qv-0.1.1}/tests/conftest.py +0 -0
  129. {python_qv-0.1.0 → python_qv-0.1.1}/tests/reporters/test_reporters.py +0 -0
  130. {python_qv-0.1.0 → python_qv-0.1.1}/tests/test_config.py +0 -0
  131. {python_qv-0.1.0 → python_qv-0.1.1}/tests/test_models.py +0 -0
  132. {python_qv-0.1.0 → python_qv-0.1.1}/tests/test_rules.py +0 -0
@@ -0,0 +1,73 @@
1
+ name: 🐛 Bug Report
2
+ description: Report unexpected behavior, inaccurate diagnostics, or crashes in qv.
3
+ title: "[Bug]: "
4
+ labels: ["bug", "triage"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for taking the time to report an issue! Please search existing issues before filing a duplicate.
10
+
11
+ - type: textarea
12
+ id: description
13
+ attributes:
14
+ label: Bug Description
15
+ description: A clear and concise description of what the bug is.
16
+ placeholder: Describe the problem...
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: reproduction
22
+ attributes:
23
+ label: Steps to Reproduce
24
+ description: Provide the command and minimal project layout to reproduce the issue.
25
+ placeholder: |
26
+ 1. Run `qv scan` on a project with ...
27
+ 2. Expected output: ...
28
+ 3. Actual output: ...
29
+ validations:
30
+ required: true
31
+
32
+ - type: textarea
33
+ id: command_output
34
+ attributes:
35
+ label: Command Output / Error Trace
36
+ description: Paste the output of `qv scan` or stack trace here.
37
+ render: text
38
+ validations:
39
+ required: false
40
+
41
+ - type: dropdown
42
+ id: package_manager
43
+ attributes:
44
+ label: Package Manager
45
+ description: Which package manager was used in the scanned project?
46
+ options:
47
+ - uv
48
+ - poetry
49
+ - pip / requirements.txt
50
+ - pdm
51
+ - pipenv
52
+ - Other / None
53
+ validations:
54
+ required: true
55
+
56
+ - type: input
57
+ id: environment
58
+ attributes:
59
+ label: Environment & Versions
60
+ description: Output of `qv version`, Python version, and OS.
61
+ placeholder: qv v0.1.0, Python 3.12.7, Ubuntu 24.04 / Windows 11 / macOS 14
62
+ validations:
63
+ required: true
64
+
65
+ - type: checkboxes
66
+ id: checkboxes
67
+ attributes:
68
+ label: Checklist
69
+ options:
70
+ - label: I have verified this is not a duplicate of an existing issue.
71
+ required: true
72
+ - label: I can reproduce this on the latest version of `qv`.
73
+ required: true
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: 📖 Documentation
4
+ url: https://qv.readthedocs.io/
5
+ about: Read the official documentation and guides.
6
+ - name: 💬 Discussions & Questions
7
+ url: https://github.com/inzamol/qv/discussions
8
+ about: Ask questions, share ideas, and discuss with the community.
@@ -0,0 +1,43 @@
1
+ name: 💡 Feature Request
2
+ description: Suggest a new capability, visualizer, reporter, or CLI option for qv.
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Have an idea to make `qv` better? Tell us about your proposal!
10
+
11
+ - type: textarea
12
+ id: problem
13
+ attributes:
14
+ label: Problem / Motivation
15
+ description: Is your feature request related to a specific pain point or workflow limitation?
16
+ placeholder: I'm always frustrated when...
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: proposed_solution
22
+ attributes:
23
+ label: Proposed Solution
24
+ description: Describe the solution or new command/flag you'd like to see.
25
+ placeholder: Add a `--watch` flag to `qv scan` that...
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: alternatives
31
+ attributes:
32
+ label: Considered Alternatives
33
+ description: Describe any alternative solutions or workarounds you've evaluated.
34
+ validations:
35
+ required: false
36
+
37
+ - type: checkboxes
38
+ id: willingness
39
+ attributes:
40
+ label: Contribution
41
+ options:
42
+ - label: I would be interested in submitting a Pull Request to implement this.
43
+ required: false
@@ -0,0 +1,56 @@
1
+ name: 📋 New Diagnostic Rule Proposal
2
+ description: Propose a new diagnostic check, code smell detection, or ecosystem drift rule.
3
+ title: "[Rule Proposal]: "
4
+ labels: ["rules", "enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Diagnostic rules in `qv` detect real ecosystem friction, configuration bugs, or runtime hazards.
10
+
11
+ - type: input
12
+ id: suggested_rule_id
13
+ attributes:
14
+ label: Proposed Rule Category & ID
15
+ description: e.g. `DEP-xxx` (Dependencies), `ENV-xxx` (Environment), `IMP-xxx` (Imports), `PKG-xxx` (Packaging)
16
+ placeholder: DEP-007
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: summary
22
+ attributes:
23
+ label: Rule Summary & Objective
24
+ description: What specific condition or bug does this rule identify?
25
+ placeholder: Detect when a requirement in pyproject.toml has an unpinned upper bound...
26
+ validations:
27
+ required: true
28
+
29
+ - type: dropdown
30
+ id: severity
31
+ attributes:
32
+ label: Default Severity
33
+ options:
34
+ - ERROR (Blocking hazard or broken project)
35
+ - WARNING (Sub-optimal or risky configuration)
36
+ - INFO (Advisory metric)
37
+ validations:
38
+ required: true
39
+
40
+ - type: textarea
41
+ id: evidence
42
+ attributes:
43
+ label: Deterministic Evidence Sources
44
+ description: Where does the evidence come from without making external network calls?
45
+ placeholder: AST import nodes, pyproject.toml table parsing, etc.
46
+ validations:
47
+ required: true
48
+
49
+ - type: textarea
50
+ id: remediation
51
+ attributes:
52
+ label: Remediation Strategy & Fix
53
+ description: What actionable command or edit will resolve the issue?
54
+ placeholder: Run `uv add ...` or update the manifest table.
55
+ validations:
56
+ required: true
@@ -0,0 +1,32 @@
1
+ ## 📝 Description
2
+
3
+ Briefly describe the changes introduced in this Pull Request, including the problem solved or feature added.
4
+
5
+ ---
6
+
7
+ ## 🔗 Related Issues
8
+
9
+ - Fixes #(issue)
10
+ - Closes #(issue)
11
+
12
+ ---
13
+
14
+ ## 🧪 Type of Change
15
+
16
+ - [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
17
+ - [ ] ✨ New feature / rule (non-breaking change which adds new diagnostic or visualizer)
18
+ - [ ] ⚡ Performance improvement
19
+ - [ ] 📖 Documentation update
20
+ - [ ] 🧹 Refactoring or code quality cleanup
21
+
22
+ ---
23
+
24
+ ## ✅ Quality Checklist
25
+
26
+ - [ ] I have read the [Contributing Guidelines](https://github.com/inzamol/qv/blob/main/docs/contributing.md).
27
+ - [ ] My code adheres to strict type annotations and passes `uv run pyright`.
28
+ - [ ] My code passes linting and formatting via `uv run ruff check .` and `uv run ruff format --check .`.
29
+ - [ ] I have added comprehensive unit tests covering positive and negative cases under `tests/`.
30
+ - [ ] All tests pass locally with `uv run pytest`.
31
+ - [ ] Multi-environment matrix passes locally with `uv run tox`.
32
+ - [ ] If adding a new rule or CLI option, I have updated the relevant documentation in `docs/` and `README.md`.
@@ -0,0 +1,65 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ name: Test Matrix (Python ${{ matrix.python-version }})
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v5
27
+ with:
28
+ version: "latest"
29
+
30
+ - name: Set up Python ${{ matrix.python-version }}
31
+ run: uv python install ${{ matrix.python-version }}
32
+
33
+ - name: Install all dependencies
34
+ run: uv sync --all-extras
35
+
36
+ - name: Lint with Ruff
37
+ run: |
38
+ uv run ruff check .
39
+ uv run ruff format --check .
40
+
41
+ - name: Static Type Checking with Pyright
42
+ run: uv run pyright
43
+
44
+ - name: Run Test Suite
45
+ run: uv run pytest --cov=src/qv --cov-report=term-missing
46
+
47
+ - name: Self Health Scan (Dogfooding qv)
48
+ run: uv run qv scan --strict --ci --github-annotations
49
+
50
+ docs:
51
+ name: Build Documentation
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+
56
+ - name: Install uv
57
+ uses: astral-sh/setup-uv@v5
58
+ with:
59
+ version: "latest"
60
+
61
+ - name: Install dependencies
62
+ run: uv sync --all-extras
63
+
64
+ - name: Build Docs in Strict Mode
65
+ run: uv run mkdocs build --strict
@@ -1,12 +1,12 @@
1
- name: Publish to PyPI
1
+ name: Publish to PyPI & GitHub Release
2
2
 
3
3
  on:
4
- release:
5
- types: [published]
6
4
  push:
7
5
  tags:
8
6
  - "v[0-9]+.[0-9]+.[0-9]+"
9
7
  - "v[0-9]+.[0-9]+.[0-9]+-*"
8
+ release:
9
+ types: [published]
10
10
  workflow_dispatch:
11
11
  inputs:
12
12
  target:
@@ -24,7 +24,7 @@ concurrency:
24
24
 
25
25
  jobs:
26
26
  validate:
27
- name: Run Test Suite (Pre-flight)
27
+ name: Validate Tag, Lint & Test Suite
28
28
  runs-on: ubuntu-latest
29
29
  strategy:
30
30
  fail-fast: false
@@ -42,23 +42,59 @@ jobs:
42
42
  - name: Set up Python ${{ matrix.python-version }}
43
43
  run: uv python install ${{ matrix.python-version }}
44
44
 
45
- - name: Install dependencies
46
- run: uv sync --all-extras --dev
45
+ - name: Install all dependencies
46
+ run: uv sync --all-extras
47
47
 
48
- - name: Lint and type check
48
+ - name: Validate Git Tag vs Package Version
49
+ if: startsWith(github.ref, 'refs/tags/v')
50
+ run: |
51
+ uv run python -c "
52
+ import os, sys
53
+ from pathlib import Path
54
+ try:
55
+ import tomllib
56
+ except ImportError:
57
+ import tomli as tomllib
58
+
59
+ tag = os.environ.get('GITHUB_REF_NAME', '')
60
+ if not tag.startswith('v'):
61
+ sys.exit(0)
62
+ tag_ver = tag.lstrip('v')
63
+ pyproject = tomllib.loads(Path('pyproject.toml').read_text(encoding='utf-8'))
64
+ toml_ver = pyproject.get('project', {}).get('version', '')
65
+
66
+ from qv import __version__ as code_ver
67
+
68
+ errors = []
69
+ if tag_ver != toml_ver:
70
+ errors.append(f'Git tag version ({tag_ver}) != pyproject.toml version ({toml_ver})')
71
+ if tag_ver != code_ver:
72
+ errors.append(f'Git tag version ({tag_ver}) != qv.__version__ ({code_ver})')
73
+
74
+ if errors:
75
+ for err in errors:
76
+ print(f'::error::{err}')
77
+ sys.exit(1)
78
+ print(f'✓ Tag {tag} strictly matches pyproject.toml and qv.__version__ ({tag_ver})')
79
+ "
80
+
81
+ - name: Lint and formatting checks
49
82
  run: |
50
83
  uv run ruff check .
51
84
  uv run ruff format --check .
52
85
 
53
- - name: Run test suite
54
- run: uv run pytest --cov=qv --cov-report=term-missing
86
+ - name: Static type checking
87
+ run: uv run pyright
88
+
89
+ - name: Run test suite with coverage
90
+ run: uv run pytest --cov=src/qv --cov-report=term-missing
55
91
 
56
92
  build:
57
- name: Build & Verify Distributions
93
+ name: Build, Attest & Release Assets
58
94
  needs: [validate]
59
95
  runs-on: ubuntu-latest
60
96
  permissions:
61
- contents: read
97
+ contents: write
62
98
  id-token: write
63
99
  attestations: write
64
100
 
@@ -88,10 +124,19 @@ jobs:
88
124
  path: dist/
89
125
  if-no-files-found: error
90
126
 
127
+ - name: Create or Update GitHub Release with Notes
128
+ if: startsWith(github.ref, 'refs/tags/v')
129
+ uses: softprops/action-gh-release@v2
130
+ with:
131
+ files: dist/*
132
+ generate_release_notes: true
133
+ draft: false
134
+ prerelease: contains(github.ref, '-')
135
+
91
136
  publish-to-pypi:
92
137
  name: Publish to PyPI
93
138
  needs: [build]
94
- if: (github.event_name == 'release' && github.event.action == 'published') || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'pypi')
139
+ if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'release' && github.event.action == 'published') || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'pypi')
95
140
  runs-on: ubuntu-latest
96
141
  environment:
97
142
  name: pypi
@@ -56,6 +56,9 @@ htmlcov/
56
56
  .DS_Store
57
57
  Thumbs.db
58
58
 
59
+ # Documentation builds
60
+ site/
61
+
59
62
  # Internal developer design docs
60
63
  dev_docs/
61
64
 
@@ -0,0 +1,43 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: ruff-check
5
+ name: ruff check & fix
6
+ entry: uv run ruff check --fix .
7
+ language: system
8
+ pass_filenames: false
9
+ always_run: true
10
+ stages: [pre-commit]
11
+
12
+ - id: ruff-format
13
+ name: ruff format
14
+ entry: uv run ruff format .
15
+ language: system
16
+ pass_filenames: false
17
+ always_run: true
18
+ stages: [pre-commit]
19
+
20
+ - id: qv-scan
21
+ name: qv health scan
22
+ entry: uv run qv scan
23
+ language: system
24
+ args: [--strict, --offline]
25
+ pass_filenames: false
26
+ always_run: true
27
+ stages: [pre-commit]
28
+
29
+ - id: pytest-check
30
+ name: pytest test suite
31
+ entry: uv run pytest
32
+ language: system
33
+ pass_filenames: false
34
+ always_run: true
35
+ stages: [pre-commit, pre-push]
36
+
37
+ - id: pyright-check
38
+ name: pyright typecheck
39
+ entry: uv run pyright
40
+ language: system
41
+ pass_filenames: false
42
+ always_run: true
43
+ stages: [pre-commit, pre-push]
@@ -0,0 +1,17 @@
1
+ - id: qv-scan
2
+ name: qv scan
3
+ description: Diagnose Python project health, dependencies, and environment consistency
4
+ entry: qv scan
5
+ language: python
6
+ types_or: [python, toml, yaml, dockerfile]
7
+ pass_filenames: false
8
+ always_run: true
9
+
10
+ - id: qv-fix
11
+ name: qv fix
12
+ description: Automatically remediate safe Python project health issues
13
+ entry: qv fix -y
14
+ language: python
15
+ types_or: [python, toml]
16
+ pass_filenames: false
17
+ always_run: true
@@ -0,0 +1,16 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-24.04
5
+ tools:
6
+ python: "3.12"
7
+ jobs:
8
+ post_create_environment:
9
+ # Install uv for fast dependency resolution
10
+ - pip install uv
11
+ post_install:
12
+ # Install docs dependencies using uv
13
+ - uv pip install --system -e ".[docs]"
14
+
15
+ mkdocs:
16
+ configuration: mkdocs.yml
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [0.1.0] - 2026-10-01
11
+
12
+ Initial public release of `qv` — the proactive health diagnostics and remediation platform for Python projects.
13
+
14
+ ### Added
15
+ - **Diagnostic Engine & Analyzers**:
16
+ - `DEP-001`: Dependency version constraint conflict detection.
17
+ - `DEP-002`: Missing undeclared package imports.
18
+ - `DEP-003`: Unused declared dependencies.
19
+ - `DEP-004`: Python target runtime incompatibility.
20
+ - `DEP-005`: Virtualenv vs declared pin drift.
21
+ - `DEP-006`: Known vulnerability/CVE reporting.
22
+ - `ENV-001`: Python interpreter version drift.
23
+ - `ENV-002`: Dockerfile base image Python version drift.
24
+ - `ENV-003`: CI matrix coverage drift.
25
+ - `IMP-001`: Circular import cycle detection with Tarjan's SCC algorithm.
26
+ - `IMP-002`: Unresolvable internal module imports.
27
+ - `IMP-003`: Orphan / dead internal modules.
28
+ - `IMP-004`: Deprecated / removed standard library modules (PEP 594).
29
+ - `PKG-001`: Missing PEP 621 packaging metadata.
30
+ - `PKG-002`: Invalid `pyproject.toml` syntax.
31
+ - **Reporting & Visualizers**:
32
+ - Interactive Terminal Explorer (TUI) with keyboard navigation (`qv inspect`, `qv ui`).
33
+ - Self-contained, single-file interactive HTML report generator (`qv scan --html`).
34
+ - Standard SARIF v2.1.0 report exporter (`qv scan --sarif`).
35
+ - Machine-readable JSON reporter (`qv scan --json`).
36
+ - Color-coded Rich terminal reporter with circular health score gauge.
37
+ - Dependency and import architecture visualizers (`qv tree`, `qv graph`).
38
+ - **Remediation**:
39
+ - Safe automated fix engine (`qv fix`) with dry-run previews, interactive confirmations, and package manager sync.
40
+ - **Ecosystem & CI/CD**:
41
+ - Native pre-commit hooks (`qv-scan`, `qv-fix`).
42
+ - Official GitHub Action (`action.yml`) with automated PR annotations and Step Summary markdown.
43
+ - Automated PyPI publishing workflow with SLSA build provenance attestations.
44
+ - Comprehensive documentation site built with MkDocs Material and configured for ReadTheDocs.