pytest-gpu-proof 0.3.0__tar.gz → 0.4.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 (125) hide show
  1. pytest_gpu_proof-0.4.1/.github/workflows/ci.yml +68 -0
  2. pytest_gpu_proof-0.4.1/.github/workflows/docs.yml +69 -0
  3. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/.gitignore +3 -1
  4. pytest_gpu_proof-0.4.1/AGENTS.md +29 -0
  5. pytest_gpu_proof-0.4.1/CHANGELOG.md +180 -0
  6. pytest_gpu_proof-0.4.1/CLAUDE.md +14 -0
  7. pytest_gpu_proof-0.4.1/CONTRIBUTING.md +41 -0
  8. pytest_gpu_proof-0.4.1/PKG-INFO +353 -0
  9. pytest_gpu_proof-0.4.1/README.md +315 -0
  10. pytest_gpu_proof-0.4.1/ROADMAP.md +15 -0
  11. pytest_gpu_proof-0.4.1/SECURITY.md +33 -0
  12. pytest_gpu_proof-0.4.1/docs/architecture.md +99 -0
  13. pytest_gpu_proof-0.4.1/docs/ci_gpu_mode.md +64 -0
  14. pytest_gpu_proof-0.4.1/docs/index.md +40 -0
  15. pytest_gpu_proof-0.4.1/docs/local_mode.md +87 -0
  16. pytest_gpu_proof-0.4.1/docs/policy.md +91 -0
  17. pytest_gpu_proof-0.4.1/docs/quickstart.md +101 -0
  18. pytest_gpu_proof-0.4.1/docs/security_model.md +115 -0
  19. pytest_gpu_proof-0.4.1/docs/sharding.md +91 -0
  20. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/mkdocs.yml +3 -0
  21. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/pyproject.toml +27 -9
  22. pytest_gpu_proof-0.4.1/requirements-dev.txt +8 -0
  23. pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/__init__.py +1 -0
  24. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/cli.py +110 -2
  25. pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/compare.py +68 -0
  26. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/config.py +53 -7
  27. pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/fingerprint.py +166 -0
  28. pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/gitutils.py +176 -0
  29. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/merge.py +173 -24
  30. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/plugin.py +168 -80
  31. pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/receipt.py +270 -0
  32. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/signers/ed25519.py +47 -18
  33. pytest_gpu_proof-0.4.1/src/pytest_gpu_proof/verify.py +591 -0
  34. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/tests/conftest.py +27 -0
  35. pytest_gpu_proof-0.4.1/tests/test_cli.py +82 -0
  36. pytest_gpu_proof-0.4.1/tests/test_compare.py +118 -0
  37. pytest_gpu_proof-0.4.1/tests/test_config.py +123 -0
  38. pytest_gpu_proof-0.4.1/tests/test_fingerprint.py +209 -0
  39. pytest_gpu_proof-0.4.1/tests/test_gitutils.py +161 -0
  40. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/tests/test_merge.py +85 -5
  41. pytest_gpu_proof-0.4.1/tests/test_plugin_capture.py +653 -0
  42. pytest_gpu_proof-0.4.1/tests/test_receipt.py +341 -0
  43. pytest_gpu_proof-0.4.1/tests/test_sharding.py +697 -0
  44. pytest_gpu_proof-0.4.1/tests/test_signing.py +272 -0
  45. pytest_gpu_proof-0.4.1/tests/test_verifier.py +956 -0
  46. pytest_gpu_proof-0.4.1/website/README.md +85 -0
  47. pytest_gpu_proof-0.4.1/website/build_site.py +82 -0
  48. pytest_gpu_proof-0.4.1/website/check_site.py +90 -0
  49. pytest_gpu_proof-0.4.1/website/favicon.svg +1 -0
  50. pytest_gpu_proof-0.4.1/website/index.html +127 -0
  51. pytest_gpu_proof-0.4.1/website/main.js +17 -0
  52. pytest_gpu_proof-0.4.1/website/overrides/main.html +4 -0
  53. pytest_gpu_proof-0.4.1/website/provenance.json +10 -0
  54. pytest_gpu_proof-0.4.1/website/requirements.txt +2 -0
  55. pytest_gpu_proof-0.4.1/website/style.css +67 -0
  56. pytest_gpu_proof-0.4.1/website/test_site.py +89 -0
  57. pytest_gpu_proof-0.4.1/website/workflow-mobile.svg +32 -0
  58. pytest_gpu_proof-0.4.1/website/workflow.svg +35 -0
  59. pytest_gpu_proof-0.3.0/.github/workflows/ci.yml +0 -27
  60. pytest_gpu_proof-0.3.0/.github/workflows/docs.yml +0 -29
  61. pytest_gpu_proof-0.3.0/CHANGELOG.md +0 -66
  62. pytest_gpu_proof-0.3.0/CLAUDE.md +0 -73
  63. pytest_gpu_proof-0.3.0/PKG-INFO +0 -400
  64. pytest_gpu_proof-0.3.0/README.md +0 -367
  65. pytest_gpu_proof-0.3.0/ROADMAP.md +0 -11
  66. pytest_gpu_proof-0.3.0/docs/architecture.md +0 -92
  67. pytest_gpu_proof-0.3.0/docs/ci_gpu_mode.md +0 -100
  68. pytest_gpu_proof-0.3.0/docs/index.md +0 -33
  69. pytest_gpu_proof-0.3.0/docs/local_mode.md +0 -136
  70. pytest_gpu_proof-0.3.0/docs/quickstart.md +0 -377
  71. pytest_gpu_proof-0.3.0/docs/security_model.md +0 -87
  72. pytest_gpu_proof-0.3.0/docs/sharding.md +0 -109
  73. pytest_gpu_proof-0.3.0/requirements-dev.txt +0 -3
  74. pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/__init__.py +0 -1
  75. pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/compare.py +0 -49
  76. pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/fingerprint.py +0 -38
  77. pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/gitutils.py +0 -112
  78. pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/receipt.py +0 -166
  79. pytest_gpu_proof-0.3.0/src/pytest_gpu_proof/verify.py +0 -412
  80. pytest_gpu_proof-0.3.0/tests/test_compare.py +0 -64
  81. pytest_gpu_proof-0.3.0/tests/test_fingerprint.py +0 -40
  82. pytest_gpu_proof-0.3.0/tests/test_gitutils.py +0 -69
  83. pytest_gpu_proof-0.3.0/tests/test_plugin_capture.py +0 -307
  84. pytest_gpu_proof-0.3.0/tests/test_receipt.py +0 -142
  85. pytest_gpu_proof-0.3.0/tests/test_sharding.py +0 -282
  86. pytest_gpu_proof-0.3.0/tests/test_signing.py +0 -96
  87. pytest_gpu_proof-0.3.0/tests/test_verifier.py +0 -363
  88. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/.github/workflows/publish-testpypi.yml +0 -0
  89. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/.github/workflows/publish.yml +0 -0
  90. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/LICENSE +0 -0
  91. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/RELEASING.md +0 -0
  92. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/docs/landscape.md +0 -0
  93. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/Makefile +0 -0
  94. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/README.md +0 -0
  95. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/cuda_ctypes_matmul.py +0 -0
  96. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/matmul_kernel.cu +0 -0
  97. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_ctypes_matmul/test_cuda_ctypes_matmul.py +0 -0
  98. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/CMakeLists.txt +0 -0
  99. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/README.md +0 -0
  100. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/src/bindings.cpp +0 -0
  101. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/src/matmul_cuda.h +0 -0
  102. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/src/matmul_kernel.cu +0 -0
  103. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_nanobind_matmul/test_cuda_nanobind_matmul.py +0 -0
  104. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/CMakeLists.txt +0 -0
  105. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/README.md +0 -0
  106. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/src/bindings.cpp +0 -0
  107. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/src/matmul_cuda.h +0 -0
  108. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/src/matmul_kernel.cu +0 -0
  109. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/cuda_pybind11_matmul/test_cuda_pybind11_matmul.py +0 -0
  110. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/github_gpu_runner/.github/workflows/gpu-test.yml +0 -0
  111. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/CMakeLists.txt +0 -0
  112. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/README.md +0 -0
  113. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/jax_ffi_matmul.py +0 -0
  114. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/src/matmul_ffi.cu +0 -0
  115. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/jax_ffi_cuda_matmul/test_jax_ffi_cuda_matmul.py +0 -0
  116. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/local_receipt_verify/.github/workflows/verify.yml +0 -0
  117. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/minimal_python_only/conftest.py +0 -0
  118. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/minimal_python_only/test_minimal.py +0 -0
  119. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/wrapped_cuda_ctypes/fake_cuda_lib.py +0 -0
  120. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/examples/wrapped_cuda_ctypes/test_cuda_wrapper.py +0 -0
  121. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/install.sh +0 -0
  122. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/requirements.txt +0 -0
  123. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/__main__.py +0 -0
  124. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/signers/__init__.py +0 -0
  125. {pytest_gpu_proof-0.3.0 → pytest_gpu_proof-0.4.1}/src/pytest_gpu_proof/signers/base.py +0 -0
@@ -0,0 +1,68 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+
23
+ - name: Install package with dev extras
24
+ run: pip install -e ".[dev]"
25
+
26
+ - name: Run test suite (CPU-only)
27
+ run: python -m pytest tests/ -q
28
+
29
+ coverage:
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ - uses: actions/setup-python@v5
34
+ with:
35
+ python-version: "3.12"
36
+ - name: Install package with dev extras
37
+ run: pip install -e ".[dev]"
38
+ - name: Enforce 100% line and branch coverage
39
+ run: |
40
+ coverage run -m pytest tests/ -q
41
+ coverage report --fail-under=100
42
+ coverage xml
43
+ - uses: actions/upload-artifact@v4
44
+ with:
45
+ name: coverage-xml
46
+ path: coverage.xml
47
+
48
+ docs-and-package:
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: actions/setup-python@v5
53
+ with:
54
+ python-version: "3.12"
55
+ - name: Install package with dev extras
56
+ run: pip install -e ".[dev]"
57
+ - name: Build documentation strictly
58
+ run: mkdocs build --strict
59
+ - name: Build and inspect distributions
60
+ run: |
61
+ python -m build
62
+ python -m twine check --strict dist/*
63
+ - name: Smoke-test the wheel
64
+ run: |
65
+ python -m venv /tmp/wheeltest
66
+ /tmp/wheeltest/bin/pip install -q dist/*.whl
67
+ /tmp/wheeltest/bin/gpu-proof --help
68
+ /tmp/wheeltest/bin/python -m pytest -p pytest_gpu_proof --version
@@ -0,0 +1,69 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ paths:
8
+ - 'docs/**'
9
+ - 'website/**'
10
+ - 'mkdocs.yml'
11
+ - '.github/workflows/docs.yml'
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ concurrency:
17
+ group: docs-${{ github.ref }}
18
+ cancel-in-progress: false
19
+
20
+ jobs:
21
+ build:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+
26
+ - uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+
30
+ - name: Install website dependencies
31
+ run: pip install -r website/requirements.txt
32
+
33
+ - name: Build and check the complete website
34
+ run: python website/build_site.py
35
+
36
+ - name: Test website checks
37
+ run: python -m unittest discover -s website -p 'test_*.py'
38
+
39
+ - uses: actions/upload-artifact@v4
40
+ with:
41
+ name: website-preview
42
+ path: build/website
43
+ include-hidden-files: true
44
+
45
+ deploy:
46
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
47
+ needs: build
48
+ runs-on: ubuntu-latest
49
+ permissions:
50
+ contents: write
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ with:
54
+ fetch-depth: 0
55
+ - uses: actions/setup-python@v5
56
+ with:
57
+ python-version: "3.12"
58
+ - run: pip install -r website/requirements.txt
59
+ - uses: actions/download-artifact@v4
60
+ with:
61
+ name: website-preview
62
+ path: build/website
63
+ - name: Configure git author
64
+ run: |
65
+ git config user.name "github-actions[bot]"
66
+ git config user.email "github-actions[bot]@users.noreply.github.com"
67
+
68
+ - name: Deploy to gh-pages
69
+ run: ghp-import --no-jekyll --push --branch gh-pages build/website
@@ -299,4 +299,6 @@ Testing/
299
299
  *.fatbin
300
300
 
301
301
  # Specifics
302
- gpu-proof.json
302
+ gpu-proof.json
303
+ # Local working notes (never committed)
304
+ docs/open-tasks/
@@ -0,0 +1,29 @@
1
+ # Agent guide
2
+
3
+ This repository is a security-sensitive pytest plugin. Preserve fail-closed
4
+ behavior and treat receipt, fingerprint, signature, Git, merge, and policy code
5
+ as trust boundaries.
6
+
7
+ Before changing behavior, read:
8
+
9
+ - `README.md`
10
+ - `docs/architecture.md`
11
+ - `docs/security_model.md`
12
+ - `docs/policy.md`
13
+ - `CONTRIBUTING.md`
14
+
15
+ Implementation rules:
16
+
17
+ - New receipts are schema 3; keep explicit legacy verification isolated.
18
+ - Signer metadata belongs inside the signed payload.
19
+ - Default fingerprint scope is the full tracked repository; generated inputs
20
+ require explicit extra paths.
21
+ - Never turn receipt-emission failures into success unless the caller selected
22
+ `best_effort`.
23
+ - Never accept unknown policy fields or malformed receipt structure.
24
+ - Keep tests hermetic: mock GitHub key lookup and local identity.
25
+ - Maintain 100% line and branch coverage. Add adversarial cases for new trust
26
+ branches.
27
+ - Do not edit generated `site/` or release artifacts in `dist/`.
28
+
29
+ Run the complete check list from `CONTRIBUTING.md` before proposing a PR.
@@ -0,0 +1,180 @@
1
+ # Changelog
2
+
3
+ All notable changes to pytest-gpu-proof are documented here. The format is
4
+ based on [Keep a Changelog](https://keepachangelog.com/); versions follow
5
+ [SemVer](https://semver.org/) (pre-1.0: minor bumps may break).
6
+
7
+ ## [0.4.1] — 2026-10-12
8
+
9
+ ### Fixed
10
+
11
+ - Shard entries record `dirty` (the recording tree's state); merge ORs shard
12
+ flags into the merged `repo.dirty`, carry-forward refuses a dirty shard, and
13
+ verification refuses any dirty shard unless `allow_dirty` is set.
14
+ - `gpu-proof merge --carry-from` refuses a source receipt recorded with a dirty
15
+ working tree. The merged `repo.dirty` is OR-ed over the fresh inputs only, so a
16
+ carried shard from a dirty recording was laundered into a clean-looking merged
17
+ receipt (found by GRiD's split driver, 2026-10-10). Carried shards now record
18
+ `carried.original_dirty`, and verification refuses a carried shard recorded
19
+ dirty unless `allow_dirty` is set.
20
+
21
+ - The expected-skips mismatch names the delta (unexpected skips and stale
22
+ baseline entries) instead of only reporting that the sets differ.
23
+ - The receipt's `environment.gpu_info` falls back to the same torch probe the
24
+ `gpu_required` marker uses when nvidia-smi is absent or fails (`source`
25
+ records which probe answered), so a torch-only box no longer records
26
+ `gpu_info: null` and then fails a `require_gpu` policy.
27
+
28
+ - Verification refuses a receipt whose session started more than five
29
+ minutes before its commit existed (committer time): a cheap replay and
30
+ forgery guard that needs no nonce.
31
+
32
+ - `mode: ci-gpu` is now bound to the signing key: a ci-gpu receipt verifies
33
+ only when the policy lists `allowed_key_fingerprints` and the receipt was
34
+ signed by one of them (previously the mode was an unverified label).
35
+ - Without an explicit `carried_max_age_days`, a carried shard's original run
36
+ may not be older than the receipt's `max_age_days` (was a fixed 30 days).
37
+
38
+ ### Added
39
+
40
+ - `gpu-proof merge --verify-inputs`: authenticate every input shard against
41
+ its signer's current GitHub keys before merging (unsigned or tampered inputs
42
+ are refused).
43
+ - `gpu-proof status PATH...`: one-line summaries of receipt files or
44
+ directories (commit, dirty, signed, outcome, counts, shards, carried).
45
+ - `gpu-proof durations RECEIPT... --out map.json`: fold per-test durations
46
+ into a JSON map for shard bin-packing.
47
+ - Command-line equivalents for the toml-only options:
48
+ `--gpu-proof-no-gpu-uuid`, `--gpu-proof-require-gpu`,
49
+ `--gpu-proof-max-age-days N`.
50
+ - `gpu-proof plan --receipt OLD [--repo .] [--json]`: a dry run of the
51
+ carry-forward conditions against the current tree, reporting per shard
52
+ whether it could be carried or must be re-run (and why). Drivers that plan
53
+ partial re-runs no longer reimplement the checks.
54
+ - `record_gpu_uuid` (`[tool.gpu_proof]`, default `true`): set `false` to omit each GPU's
55
+ nvidia-smi UUID from the receipt environment while keeping name, driver, memory and
56
+ compute capability. Verification does not read the UUID.
57
+
58
+ ## [0.4.0] — 2026-08-17
59
+
60
+ ### Added
61
+
62
+ - Schema `"3"`: signer username, key fingerprint, key algorithm, exact test
63
+ collection, session outcome, pytest arguments, and per-shard environment/time
64
+ are included in the signed payload.
65
+ - Open contributor and restricted signer policies. Restricted mode supports
66
+ username and exact SSH-key-fingerprint allowlists.
67
+ - Policy pinning for mode, global tracked/extra fingerprint scope, exact test
68
+ manifest, shard names, and per-shard tracked/extra scope.
69
+ - Explicit fingerprint paths for ignored/generated inputs and manifest support
70
+ for symlinks and submodule gitlinks.
71
+ - Explicit receipt-artifact exclusions avoid self-referential whole-tree
72
+ fingerprints and can be pinned by verification policy.
73
+ - `--gpu-proof-best-effort` as an explicit development escape hatch.
74
+ - `min_schema` policy field to refuse legacy schema-1/2 receipts.
75
+ - Python 3.13 CI, strict docs/package jobs, and enforced 100% line and branch
76
+ coverage.
77
+
78
+ ### Changed
79
+
80
+ - The default fingerprint scope is the entire Git-tracked repository instead
81
+ of `src,tests`.
82
+ - Receipt creation now fails pytest on Git, fingerprint, key, serialization, or
83
+ write errors; it also removes stale output at session start.
84
+ - Schema-3 verification rejects dirty recording and verification trees by
85
+ default and accepts receipt commits only at the current commit or an ancestor.
86
+ - Setup/teardown failures, missing terminal reports, comparison exceptions,
87
+ skipped tests, and overall session failure are represented and verified.
88
+ - GPU metadata records all devices reported by `nvidia-smi`.
89
+ - Array comparison is shape-safe, uses tolerance only for float/complex data,
90
+ and uses exact equality for other dtypes.
91
+ - Receipt writes are atomic and strict JSON forbids NaN/non-JSON values.
92
+ - Receipt generation rejects xdist workers; use separate shard processes.
93
+ - Legacy schema-1/2 verification derives the policy-checked key fingerprint
94
+ from the key that actually verified the signature; an asserted
95
+ `signature.key_fingerprint` that disagrees is rejected.
96
+ - `signer_mode: restricted` policies reject unsigned receipts even with
97
+ `--allow-unsigned`, and `--github-user` must match the signed schema-3
98
+ identity.
99
+ - The receipt under verification is excluded from the verification-tree dirty
100
+ check, so an untracked just-generated receipt verifies without gitignoring.
101
+ - Passphrase-protected SSH keys prompt correctly on current cryptography
102
+ releases (`ValueError` as well as `TypeError`) and fail closed with an
103
+ actionable message when no terminal is available.
104
+ - Uninitialized submodule checkouts fingerprint their index gitlink commit
105
+ instead of accidentally recording the parent repository's HEAD.
106
+ - Receipt/shard age limits are enforced to the exact day boundary.
107
+ - GitHub usernames are validated before key fetches and key responses are
108
+ size-capped.
109
+ - A stale receipt that cannot be cleared at session start raises a pytest
110
+ usage error (an exit-status write that early would be silently overwritten).
111
+ - Merging receipts without session timestamps is refused with a clear error.
112
+
113
+ ### Fixed
114
+
115
+ - Carry-forward now recomputes the stored fingerprint algorithm and preserves
116
+ explicit generated/ignored shard inputs.
117
+ - Signed identity and algorithm substitution are rejected.
118
+ - Empty source scope, unmerged index entries, malformed policies, incomplete
119
+ collections, and stale success artifacts fail closed.
120
+
121
+ ## [0.3.0] — 2026-08-08
122
+
123
+ ### Added
124
+ - Schema `"2"` sharded receipts: `--gpu-proof-shard NAME` +
125
+ `--gpu-proof-shard-fingerprint-paths` emit a per-shard narrow fingerprint;
126
+ `gpu-proof merge` unions schema-2 shards (unique names enforced).
127
+ - Verifiable carry-forward: `gpu-proof merge --carry-from OLD` grafts shards
128
+ absent from the fresh inputs iff the old commit is an ancestor AND the
129
+ shard's narrow fingerprint recomputes clean; grafted shards are marked
130
+ `carried` and the verifier rejects them unless the policy sets
131
+ `allow_carried: true` (bounded by `carried_max_age_days`, default 30).
132
+ - Verifier: schema-2 checks (per-shard fingerprint recompute, membership
133
+ partition of `tests[]`, carried-shard policy gate). Schema-1 receipts are
134
+ unchanged and a schema-1 receipt carrying a `shards` block is rejected.
135
+
136
+ ## [0.2.0] — 2026-08-07
137
+
138
+ ### Added
139
+ - `gpu-proof merge`: union N shard receipts from one commit into a single
140
+ re-signed receipt (per-module crash isolation / machine sharding). Refuses
141
+ shards that disagree on schema, commit SHA, fingerprint, mode, or
142
+ environment; duplicate node IDs across shards are a hard error. Records
143
+ per-shard provenance under `session.shards` (additive — the verifier is
144
+ unchanged). `repo.dirty` is OR-ed; `gpu_info` survives CPU-only shards.
145
+ Docs: `docs/sharding.md`.
146
+
147
+ ### Fixed
148
+ - Explicit CLI values equal to their built-in defaults are no longer silently
149
+ ignored in favor of `[tool.gpu_proof]` (value-taking options now register a
150
+ `None` sentinel; `--gpu-proof-fail-on-skip` ORs with the toml value since a
151
+ store_true flag can only turn it on).
152
+
153
+ ## [0.1.0] — 2026-07-07
154
+
155
+ First public release.
156
+
157
+ ### Added
158
+ - pytest plugin (`-p` auto-loaded via the `pytest11` entry point): captures
159
+ per-test outcomes and skips, git SHA, a SHA-256 source fingerprint over
160
+ configured paths, and self-reported GPU info; emits a signed JSON receipt at
161
+ session end (`--gpu-proof-enable`).
162
+ - Ed25519 SSH-key signing; signature covers the canonical (compact,
163
+ sorted-key) JSON without the signature block. `none` backend for unsigned
164
+ receipts.
165
+ - CPU-only verifier `gpu-proof verify`: signature against the signer's public
166
+ `github.com/<user>.keys`, fingerprint match, commit SHA, outcome + skip
167
+ policy, `--require-gpu`, freshness (`--max-age-days`, `0` = today only),
168
+ dirty policy.
169
+ - Skip policies: `--allow-skipped` (any) or `--expected-skips FILE` (exact-set
170
+ baseline — unexpected AND stale entries both fail); mutually exclusive.
171
+ Also `[tool.gpu_proof] expected_skips`.
172
+ - Signer resolution: explicit flag/config → `gh` CLI login (keyholder) →
173
+ origin-remote owner with a printed warning (org remotes have no SSH keys).
174
+ - `is_dirty` ignores untracked content inside submodules (pin moves and
175
+ tracked edits still count).
176
+ - Receipt diffing (`compare.py`), `[tool.gpu_proof]` pyproject configuration,
177
+ docs site (mkdocs), honest trust-model statement in
178
+ `docs/security_model.md`.
179
+
180
+ [0.1.0]: https://github.com/A2R-Lab/pytest-gpu-proof/releases/tag/v0.1.0
@@ -0,0 +1,14 @@
1
+ # Claude orientation
2
+
3
+ Use [AGENTS.md](AGENTS.md) as the canonical agent guide. In particular:
4
+
5
+ - a receipt is signer attestation, not proof of GPU execution;
6
+ - receipt, fingerprint, signature, Git, merge, and policy code fail closed;
7
+ - new recordings use schema 3 and bind signer metadata inside the signature;
8
+ - the default manifest covers the full tracked repository;
9
+ - tests are hermetic and maintain 100% line and branch coverage;
10
+ - generated `site/`, `dist/`, coverage output, real keys, and local receipts are
11
+ not source changes.
12
+
13
+ Before implementation work, read `docs/architecture.md`,
14
+ `docs/security_model.md`, `docs/policy.md`, and `CONTRIBUTING.md`.
@@ -0,0 +1,41 @@
1
+ # Contributing
2
+
3
+ ## Development setup
4
+
5
+ ```bash
6
+ python -m venv .venv
7
+ source .venv/bin/activate
8
+ python -m pip install -e ".[dev]"
9
+ ```
10
+
11
+ ## Required checks
12
+
13
+ ```bash
14
+ python -m pytest tests -q
15
+ coverage run -m pytest tests -q
16
+ coverage report --fail-under=100
17
+ mkdocs build --strict
18
+ python -m build
19
+ python -m twine check --strict dist/*
20
+ ```
21
+
22
+ CI runs the test suite on Python 3.11, 3.12, and 3.13, independently enforces
23
+ 100% line and branch coverage, builds docs strictly, and smoke-tests the wheel.
24
+
25
+ ## Change expectations
26
+
27
+ - Add adversarial tests for trust-boundary changes, not only happy paths.
28
+ - Keep receipt generation and verification fail-closed by default.
29
+ - Treat schema and policy changes as compatibility decisions; document them in
30
+ `CHANGELOG.md` and the relevant guide.
31
+ - Keep Git and network tests hermetic. Never depend on a developer's actual
32
+ GitHub login, SSH keys, GPU, or global Git configuration.
33
+ - Use separate pytest processes for shards. Receipt generation does not support
34
+ xdist workers.
35
+ - Do not commit generated `site/`, coverage files, caches, or local receipts.
36
+
37
+ ## Pull requests
38
+
39
+ Describe the trust claim before and after the change, migration implications,
40
+ and the exact checks run. Small, reviewable commits are preferred. Security
41
+ reports should follow [SECURITY.md](SECURITY.md), not a public issue.