deployproof 1.0.1__tar.gz → 1.1.0__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 (39) hide show
  1. {deployproof-1.0.1/src/deployproof.egg-info → deployproof-1.1.0}/PKG-INFO +4 -4
  2. {deployproof-1.0.1 → deployproof-1.1.0}/README.md +3 -3
  3. {deployproof-1.0.1 → deployproof-1.1.0}/pyproject.toml +1 -1
  4. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/__init__.py +1 -1
  5. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/dependencies.py +6 -1
  6. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/reporter.py +4 -2
  7. {deployproof-1.0.1 → deployproof-1.1.0/src/deployproof.egg-info}/PKG-INFO +4 -4
  8. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_cli.py +5 -4
  9. {deployproof-1.0.1 → deployproof-1.1.0}/LICENSE +0 -0
  10. {deployproof-1.0.1 → deployproof-1.1.0}/setup.cfg +0 -0
  11. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/cli.py +0 -0
  12. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/control_flow.py +0 -0
  13. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/coverage_plugin.py +0 -0
  14. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/diff.py +0 -0
  15. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/mocks.py +0 -0
  16. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/mutator.py +0 -0
  17. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/secrets.py +0 -0
  18. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/symlinks.py +0 -0
  19. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof/wsl.py +0 -0
  20. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof.egg-info/SOURCES.txt +0 -0
  21. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof.egg-info/dependency_links.txt +0 -0
  22. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof.egg-info/entry_points.txt +0 -0
  23. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof.egg-info/requires.txt +0 -0
  24. {deployproof-1.0.1 → deployproof-1.1.0}/src/deployproof.egg-info/top_level.txt +0 -0
  25. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_baseline_collection_error.py +0 -0
  26. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_cli_dependency_scan.py +0 -0
  27. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_control_flow.py +0 -0
  28. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_dependencies_extractor.py +0 -0
  29. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_dependencies_pypi.py +0 -0
  30. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_diff.py +0 -0
  31. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_edge_cases_validation.py +0 -0
  32. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_import_graph_discovery.py +0 -0
  33. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_mocks.py +0 -0
  34. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_mutation_suites.py +0 -0
  35. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_mutator.py +0 -0
  36. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_secrets.py +0 -0
  37. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_stress_regressions.py +0 -0
  38. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_symlinks.py +0 -0
  39. {deployproof-1.0.1 → deployproof-1.1.0}/tests/test_wsl.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deployproof
3
- Version: 1.0.1
3
+ Version: 1.1.0
4
4
  Summary: A deterministic AI-code deployability checker that catches what coverage misses.
5
5
  Author-email: SVS Praveen <svspraveens@gmail.com>
6
6
  License-Expression: MIT
@@ -33,7 +33,7 @@ Dynamic: license-file
33
33
 
34
34
  > Deterministic pre-push verification for AI-assisted codebases: AST mutation testing, credential scanning, sandbox-escape detection, mock-usage alerts, swallowed-exception checks, and dependency hallucination defense.
35
35
 
36
- [![PyPI version](https://img.shields.io/badge/pypi-v1.0.0-007ec6.svg)](https://pypi.org/project/deployproof/)
36
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.1.0-007ec6.svg)](https://pypi.org/project/deployproof/)
37
37
  [![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-3776ab.svg)](https://pypi.org/project/deployproof/)
38
38
  [![CI](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml/badge.svg)](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml)
39
39
  [![Tests](https://img.shields.io/badge/tests-111%20passed-2ea44f.svg)](https://github.com/SVSPraveen/DeployProof)
@@ -289,7 +289,7 @@ deployproof check --json
289
289
 
290
290
  ```json
291
291
  {
292
- "version": "1.0.0",
292
+ "version": "1.1.0",
293
293
  "status": "passed",
294
294
  "summary": {
295
295
  "target_files_count": 1,
@@ -389,7 +389,7 @@ Fixtures cover weak test suites, zero-test orphan modules, planted OpenAI/AWS cr
389
389
 
390
390
  ## Status & Roadmap
391
391
 
392
- - **Current (v1.0.0):** Diff-scoped AST mutation testing (with recursive discovery and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), **Full Repository Audit Mode (`--full-repo`)** with isolated parallel multi-worker sandboxes and AST import-graph test discovery, baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner, GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, **111 unit tests**, live unbuffered progress streaming, and machine-readable `--json` output.
392
+ - **Current (v1.1.0):** Diff-scoped AST mutation testing (with recursive discovery and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), **Full Repository Audit Mode (`--full-repo`)** with isolated parallel multi-worker sandboxes and AST import-graph test discovery, baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner, GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, **111 unit tests**, live unbuffered progress streaming, and machine-readable `--json` output.
393
393
  - **Next:** Reverse test-to-source dependency mapping (see `FUTURE_SCOPE.md`), SARIF 2.1.0 PR annotations, and multi-language mutation rule packs.
394
394
 
395
395
  ## Contributing
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Deterministic pre-push verification for AI-assisted codebases: AST mutation testing, credential scanning, sandbox-escape detection, mock-usage alerts, swallowed-exception checks, and dependency hallucination defense.
4
4
 
5
- [![PyPI version](https://img.shields.io/badge/pypi-v1.0.0-007ec6.svg)](https://pypi.org/project/deployproof/)
5
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.1.0-007ec6.svg)](https://pypi.org/project/deployproof/)
6
6
  [![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-3776ab.svg)](https://pypi.org/project/deployproof/)
7
7
  [![CI](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml/badge.svg)](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml)
8
8
  [![Tests](https://img.shields.io/badge/tests-111%20passed-2ea44f.svg)](https://github.com/SVSPraveen/DeployProof)
@@ -258,7 +258,7 @@ deployproof check --json
258
258
 
259
259
  ```json
260
260
  {
261
- "version": "1.0.0",
261
+ "version": "1.1.0",
262
262
  "status": "passed",
263
263
  "summary": {
264
264
  "target_files_count": 1,
@@ -358,7 +358,7 @@ Fixtures cover weak test suites, zero-test orphan modules, planted OpenAI/AWS cr
358
358
 
359
359
  ## Status & Roadmap
360
360
 
361
- - **Current (v1.0.0):** Diff-scoped AST mutation testing (with recursive discovery and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), **Full Repository Audit Mode (`--full-repo`)** with isolated parallel multi-worker sandboxes and AST import-graph test discovery, baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner, GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, **111 unit tests**, live unbuffered progress streaming, and machine-readable `--json` output.
361
+ - **Current (v1.1.0):** Diff-scoped AST mutation testing (with recursive discovery and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), **Full Repository Audit Mode (`--full-repo`)** with isolated parallel multi-worker sandboxes and AST import-graph test discovery, baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner, GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, **111 unit tests**, live unbuffered progress streaming, and machine-readable `--json` output.
362
362
  - **Next:** Reverse test-to-source dependency mapping (see `FUTURE_SCOPE.md`), SARIF 2.1.0 PR annotations, and multi-language mutation rule packs.
363
363
 
364
364
  ## Contributing
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deployproof"
7
- version = "1.0.1"
7
+ version = "1.1.0"
8
8
  description = "A deterministic AI-code deployability checker that catches what coverage misses."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,2 +1,2 @@
1
1
  """DeployProof - Deterministic AI-Code Deployability Checker."""
2
- __version__ = "1.0.1"
2
+ __version__ = "1.1.0"
@@ -1047,10 +1047,15 @@ def query_pypi_registry(
1047
1047
  # Map import name to PyPI distribution name if known
1048
1048
  canonical_pkg = normalize_package_name(norm_name)
1049
1049
 
1050
+ try:
1051
+ from deployproof import __version__
1052
+ except ImportError:
1053
+ __version__ = "1.1.0"
1054
+
1050
1055
  url = f"https://pypi.org/pypi/{canonical_pkg}/json"
1051
1056
  req = urllib.request.Request(
1052
1057
  url,
1053
- headers={"User-Agent": "DeployProof/1.0.0 (https://github.com/SVSPraveen/DeployProof)"},
1058
+ headers={"User-Agent": f"DeployProof/{__version__} (https://github.com/SVSPraveen/DeployProof)"},
1054
1059
  )
1055
1060
 
1056
1061
  try:
@@ -2,6 +2,7 @@
2
2
  import json
3
3
  from pathlib import Path
4
4
  from typing import Any, Dict, List, Optional
5
+ from deployproof import __version__
5
6
  from deployproof.control_flow import ControlFlowScanSummary
6
7
  from deployproof.dependencies import DependencyScanSummary
7
8
  from deployproof.mocks import MockScanSummary
@@ -10,8 +11,9 @@ from deployproof.secrets import SecretsScanResult
10
11
  from deployproof.symlinks import SymlinkScanResult
11
12
  LARGE_FILE_LOC_THRESHOLD = 300
12
13
 
13
- def format_json_report(result: MutationResult, target_files: List[Path], secrets_result: Optional[SecretsScanResult]=None, symlink_result: Optional[SymlinkScanResult]=None, dependency_result: Optional[DependencyScanSummary]=None, mock_result: Optional[MockScanSummary]=None, control_flow_result: Optional[ControlFlowScanSummary]=None, strict_mocks: bool=False, strict_error_handling: bool=False, repo_root: Optional[Path]=None, threshold: float=80.0, version: str='1.0.0') -> str:
14
+ def format_json_report(result: MutationResult, target_files: List[Path], secrets_result: Optional[SecretsScanResult]=None, symlink_result: Optional[SymlinkScanResult]=None, dependency_result: Optional[DependencyScanSummary]=None, mock_result: Optional[MockScanSummary]=None, control_flow_result: Optional[ControlFlowScanSummary]=None, strict_mocks: bool=False, strict_error_handling: bool=False, repo_root: Optional[Path]=None, threshold: float=80.0, version: Optional[str]=None) -> str:
14
15
  """Format all scan findings and mutation results as a structured JSON string."""
16
+ effective_version = version or __version__
15
17
  root = (repo_root or Path.cwd()).resolve()
16
18
  strict_mocks_triggered = bool(strict_mocks and mock_result and (mock_result.total_findings > 0))
17
19
  strict_error_triggered = bool(strict_error_handling and control_flow_result and (control_flow_result.total_findings > 0))
@@ -94,7 +96,7 @@ def format_json_report(result: MutationResult, target_files: List[Path], secrets
94
96
  except ValueError:
95
97
  rel_f = f.file_path.as_posix()
96
98
  control_flow_findings_data.append({'file': rel_f, 'line': f.line_number, 'rule': f.rule_id, 'severity': f.severity, 'snippet': f.snippet, 'message': f.message})
97
- data: Dict[str, Any] = {'version': version, 'status': status_str, 'summary': {'target_files_count': len(target_files), 'mutation_score': result.mutation_score, 'collection_error': result.collection_error, 'threshold': threshold, 'secrets_found': len(secrets_findings_data), 'symlink_escapes_found': len(symlink_escapes_data), 'dependency_findings': {'high_risk': dependency_result.high_risk_count if dependency_result else 0, 'medium_risk': dependency_result.medium_risk_count if dependency_result else 0, 'ok': dependency_result.ok_count if dependency_result else 0, 'unknown': dependency_result.unknown_count if dependency_result else 0, 'unscanned': len(unscanned_sources_data)}, 'mock_usages_found': len(mock_findings_data), 'control_flow_findings': len(control_flow_findings_data), 'strict_mocks_active': strict_mocks, 'strict_mocks_triggered': strict_mocks_triggered, 'strict_error_handling_active': strict_error_handling, 'strict_error_handling_triggered': strict_error_triggered}, 'scope': {'target_files': scope_files}, 'mutation_testing': {'score': result.mutation_score, 'collection_error': result.collection_error, 'threshold': threshold, 'total_mutants': result.total_mutants, 'killed_mutants': result.killed_mutants, 'survived_mutants_count': len(surviving_mutants_data), 'runner_errors_count': len(result.runner_errors), 'valid_mutants_count': result.killed_mutants + len(surviving_mutants_data), 'duration_seconds': result.duration_seconds, 'surviving_mutants': surviving_mutants_data, 'skipped_constructs': skipped_constructs_data, 'untested_files': untested_files_data}, 'secrets': {'clean': len(secrets_findings_data) == 0, 'files_scanned': secrets_result.files_scanned if secrets_result else len(target_files), 'findings': secrets_findings_data}, 'symlinks': {'clean': len(symlink_escapes_data) == 0, 'files_scanned': symlink_result.files_scanned if symlink_result else len(target_files), 'findings': symlink_escapes_data}, 'dependencies': {'clean': bool(not dep_findings_data), 'total_scanned': dependency_result.total_scanned if dependency_result else 0, 'findings': dep_findings_data, 'unscanned_sources': unscanned_sources_data}, 'mocks': {'clean': len(mock_findings_data) == 0, 'strict_gate_triggered': strict_mocks_triggered, 'findings': mock_findings_data}, 'control_flow': {'clean': len(control_flow_findings_data) == 0, 'strict_gate_triggered': strict_error_triggered, 'findings': control_flow_findings_data}}
99
+ data: Dict[str, Any] = {'version': effective_version, 'status': status_str, 'summary': {'target_files_count': len(target_files), 'mutation_score': result.mutation_score, 'collection_error': result.collection_error, 'threshold': threshold, 'secrets_found': len(secrets_findings_data), 'symlink_escapes_found': len(symlink_escapes_data), 'dependency_findings': {'high_risk': dependency_result.high_risk_count if dependency_result else 0, 'medium_risk': dependency_result.medium_risk_count if dependency_result else 0, 'ok': dependency_result.ok_count if dependency_result else 0, 'unknown': dependency_result.unknown_count if dependency_result else 0, 'unscanned': len(unscanned_sources_data)}, 'mock_usages_found': len(mock_findings_data), 'control_flow_findings': len(control_flow_findings_data), 'strict_mocks_active': strict_mocks, 'strict_mocks_triggered': strict_mocks_triggered, 'strict_error_handling_active': strict_error_handling, 'strict_error_handling_triggered': strict_error_triggered}, 'scope': {'target_files': scope_files}, 'mutation_testing': {'score': result.mutation_score, 'collection_error': result.collection_error, 'threshold': threshold, 'total_mutants': result.total_mutants, 'killed_mutants': result.killed_mutants, 'survived_mutants_count': len(surviving_mutants_data), 'runner_errors_count': len(result.runner_errors), 'valid_mutants_count': result.killed_mutants + len(surviving_mutants_data), 'duration_seconds': result.duration_seconds, 'surviving_mutants': surviving_mutants_data, 'skipped_constructs': skipped_constructs_data, 'untested_files': untested_files_data}, 'secrets': {'clean': len(secrets_findings_data) == 0, 'files_scanned': secrets_result.files_scanned if secrets_result else len(target_files), 'findings': secrets_findings_data}, 'symlinks': {'clean': len(symlink_escapes_data) == 0, 'files_scanned': symlink_result.files_scanned if symlink_result else len(target_files), 'findings': symlink_escapes_data}, 'dependencies': {'clean': bool(not dep_findings_data), 'total_scanned': dependency_result.total_scanned if dependency_result else 0, 'findings': dep_findings_data, 'unscanned_sources': unscanned_sources_data}, 'mocks': {'clean': len(mock_findings_data) == 0, 'strict_gate_triggered': strict_mocks_triggered, 'findings': mock_findings_data}, 'control_flow': {'clean': len(control_flow_findings_data) == 0, 'strict_gate_triggered': strict_error_triggered, 'findings': control_flow_findings_data}}
98
100
  return json.dumps(data, indent=2)
99
101
 
100
102
  def format_report(result: MutationResult, target_files: List[Path], secrets_result: Optional[SecretsScanResult]=None, symlink_result: Optional[SymlinkScanResult]=None, dependency_result: Optional[DependencyScanSummary]=None, mock_result: Optional[MockScanSummary]=None, control_flow_result: Optional[ControlFlowScanSummary]=None, strict_mocks: bool=False, strict_error_handling: bool=False, repo_root: Optional[Path]=None, threshold: float=80.0) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deployproof
3
- Version: 1.0.1
3
+ Version: 1.1.0
4
4
  Summary: A deterministic AI-code deployability checker that catches what coverage misses.
5
5
  Author-email: SVS Praveen <svspraveens@gmail.com>
6
6
  License-Expression: MIT
@@ -33,7 +33,7 @@ Dynamic: license-file
33
33
 
34
34
  > Deterministic pre-push verification for AI-assisted codebases: AST mutation testing, credential scanning, sandbox-escape detection, mock-usage alerts, swallowed-exception checks, and dependency hallucination defense.
35
35
 
36
- [![PyPI version](https://img.shields.io/badge/pypi-v1.0.0-007ec6.svg)](https://pypi.org/project/deployproof/)
36
+ [![PyPI version](https://img.shields.io/badge/pypi-v1.1.0-007ec6.svg)](https://pypi.org/project/deployproof/)
37
37
  [![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-3776ab.svg)](https://pypi.org/project/deployproof/)
38
38
  [![CI](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml/badge.svg)](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml)
39
39
  [![Tests](https://img.shields.io/badge/tests-111%20passed-2ea44f.svg)](https://github.com/SVSPraveen/DeployProof)
@@ -289,7 +289,7 @@ deployproof check --json
289
289
 
290
290
  ```json
291
291
  {
292
- "version": "1.0.0",
292
+ "version": "1.1.0",
293
293
  "status": "passed",
294
294
  "summary": {
295
295
  "target_files_count": 1,
@@ -389,7 +389,7 @@ Fixtures cover weak test suites, zero-test orphan modules, planted OpenAI/AWS cr
389
389
 
390
390
  ## Status & Roadmap
391
391
 
392
- - **Current (v1.0.0):** Diff-scoped AST mutation testing (with recursive discovery and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), **Full Repository Audit Mode (`--full-repo`)** with isolated parallel multi-worker sandboxes and AST import-graph test discovery, baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner, GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, **111 unit tests**, live unbuffered progress streaming, and machine-readable `--json` output.
392
+ - **Current (v1.1.0):** Diff-scoped AST mutation testing (with recursive discovery and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), **Full Repository Audit Mode (`--full-repo`)** with isolated parallel multi-worker sandboxes and AST import-graph test discovery, baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner, GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, **111 unit tests**, live unbuffered progress streaming, and machine-readable `--json` output.
393
393
  - **Next:** Reverse test-to-source dependency mapping (see `FUTURE_SCOPE.md`), SARIF 2.1.0 PR annotations, and multi-language mutation rule packs.
394
394
 
395
395
  ## Contributing
@@ -9,7 +9,7 @@ from deployproof.cli import create_parser, main
9
9
 
10
10
  def test_version():
11
11
  """Verify version string is accessible."""
12
- assert __version__ == "1.0.0"
12
+ assert isinstance(__version__, str) and len(__version__.split(".")) >= 3
13
13
 
14
14
 
15
15
  def test_parser_version(capsys):
@@ -19,7 +19,7 @@ def test_parser_version(capsys):
19
19
  parser.parse_args(["--version"])
20
20
  assert exc_info.value.code == 0
21
21
  captured = capsys.readouterr()
22
- assert "deployproof 1.0.0" in captured.out or "deployproof 1.0.0" in captured.err
22
+ assert f"deployproof {__version__}" in captured.out or f"deployproof {__version__}" in captured.err
23
23
 
24
24
 
25
25
  def test_parser_help(capsys):
@@ -105,7 +105,7 @@ def test_main_check_json_output_passing(capsys):
105
105
 
106
106
  data = json.loads(captured.out)
107
107
  assert data["status"] == "passed"
108
- assert data["version"] == "1.0.0"
108
+ assert data["version"] == __version__
109
109
  assert data["summary"]["mutation_score"] == 100.0
110
110
  assert data["summary"]["secrets_found"] == 0
111
111
  assert data["summary"]["symlink_escapes_found"] == 0
@@ -137,9 +137,10 @@ def test_main_check_json_output_multi_category_findings(tmp_path: Path, capsys,
137
137
  subprocess.run(["git", "config", "user.email", "test@example.com"], cwd=root, check=True)
138
138
 
139
139
  src = root / "service.py"
140
+ fake_key = "sk-" + "proj-abc123xyz123abc123xyz123abc123xyz123abc123xyz123"
140
141
  src.write_text(
141
142
  "import importlib\n\n"
142
- "OPENAI_API_KEY = 'sk-proj-abc123xyz123abc123xyz123abc123xyz123abc123xyz123'\n\n"
143
+ f"OPENAI_API_KEY = '{fake_key}'\n\n"
143
144
  "def load_plugin():\n"
144
145
  " return importlib.import_module('hallucinated_fake_package_xyz')\n\n"
145
146
  "def calculate(x: int) -> int:\n"
File without changes
File without changes