testguard-cli 0.10.4__tar.gz → 0.12.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 (323) hide show
  1. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.docguard.json +2 -1
  2. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/CHANGELOG.md +85 -0
  3. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/PKG-INFO +131 -6
  4. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/README.md +130 -5
  5. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/action.yml +1 -1
  6. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs/testguard-explained.html +172 -11
  7. testguard_cli-0.12.0/docs/testguard-explained.pdf +0 -0
  8. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs-canonical/ARCHITECTURE.md +4 -1
  9. testguard_cli-0.12.0/docs-canonical/PRIOR-ART.md +160 -0
  10. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/package-lock.json +2 -2
  11. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/package.json +1 -1
  12. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/packaging/gitlab/testguard.gitlab-ci.yml +2 -2
  13. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/packaging/homebrew/testguard.rb +2 -2
  14. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/pyproject.toml +1 -1
  15. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/lib/validate.mjs +55 -1
  16. testguard_cli-0.12.0/spec/schemas/sweep.schema.json +310 -0
  17. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/cli.mjs +12 -1
  18. testguard_cli-0.12.0/src/commands/sweep.mjs +80 -0
  19. testguard_cli-0.12.0/src/supply/persistence.mjs +173 -0
  20. testguard_cli-0.12.0/src/supply/savepath.mjs +216 -0
  21. testguard_cli-0.12.0/src/supply/select.mjs +168 -0
  22. testguard_cli-0.12.0/src/sweep/sweep.mjs +302 -0
  23. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/util/glob.mjs +8 -0
  24. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/glob.test.mjs +5 -2
  25. testguard_cli-0.12.0/test/supply-persistence.test.mjs +108 -0
  26. testguard_cli-0.12.0/test/supply-savepath.test.mjs +165 -0
  27. testguard_cli-0.12.0/test/supply-select.test.mjs +128 -0
  28. testguard_cli-0.12.0/test/sweep.fixture.test.mjs +129 -0
  29. testguard_cli-0.12.0/test/sweep.test.mjs +227 -0
  30. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/testguard.claims.json +290 -1
  31. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/testguard.cost-budget.json +1 -1
  32. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/testguard.ignore.json +7 -0
  33. testguard_cli-0.10.4/docs/testguard-explained.pdf +0 -0
  34. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.agents/skills/testguard/SKILL.md +0 -0
  35. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.codex/hooks.json +0 -0
  36. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.docguardignore +0 -0
  37. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.gitattributes +0 -0
  38. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  39. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  40. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  41. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/dependabot.yml +0 -0
  42. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/approve-held-runs.sh +0 -0
  43. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/build-one-pager.mjs +0 -0
  44. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/check-cost-budget.mjs +0 -0
  45. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/check-python-fixture.mjs +0 -0
  46. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/install-smoke.mjs +0 -0
  47. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/publish-homebrew-tap.sh +0 -0
  48. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/scripts/sync-release-version.mjs +0 -0
  49. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/workflows/auto-merge.yml +0 -0
  50. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/workflows/ci.yml +0 -0
  51. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/workflows/release.yml +0 -0
  52. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/workflows/scheduled-release.yml +0 -0
  53. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.github/workflows/supply-chain.yml +0 -0
  54. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.gitignore +0 -0
  55. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.npmignore +0 -0
  56. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.npmrc +0 -0
  57. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.pre-commit-config.yaml +0 -0
  58. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/.pre-commit-hooks.yaml +0 -0
  59. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/AGENTS.md +0 -0
  60. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/CLAUDE.md +0 -0
  61. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/CODE_OF_CONDUCT.md +0 -0
  62. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/CONTRIBUTING.md +0 -0
  63. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/DRIFT-LOG.md +0 -0
  64. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/LICENSE +0 -0
  65. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/PRIVACY.md +0 -0
  66. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/SECURITY.md +0 -0
  67. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/SUPPORT.md +0 -0
  68. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/bench/README.md +0 -0
  69. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/cli/testguard.mjs +0 -0
  70. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs-canonical/DATA-MODEL.md +0 -0
  71. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs-canonical/ENVIRONMENT.md +0 -0
  72. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs-canonical/REQUIREMENTS.md +0 -0
  73. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs-canonical/SECURITY.md +0 -0
  74. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/docs-canonical/TEST-SPEC.md +0 -0
  75. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/.gitignore +0 -0
  76. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/README.md +0 -0
  77. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/expected.json +0 -0
  78. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/package.json +0 -0
  79. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/src/export.mjs +0 -0
  80. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/src/redact.mjs +0 -0
  81. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/test/export-mocked.test.mjs +0 -0
  82. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/test/flaky.test.mjs +0 -0
  83. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/test/redact.test.mjs +0 -0
  84. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/testguard.claims.json +0 -0
  85. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer/vitest.config.mjs +0 -0
  86. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/.gitignore +0 -0
  87. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/README.md +0 -0
  88. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/expected.json +0 -0
  89. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/jest.config.js +0 -0
  90. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/package.json +0 -0
  91. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/src/export.js +0 -0
  92. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/src/redact.js +0 -0
  93. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/test/export-mocked.test.js +0 -0
  94. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/test/flaky.test.js +0 -0
  95. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/test/redact.test.js +0 -0
  96. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-jest/testguard.claims.json +0 -0
  97. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/.gitignore +0 -0
  98. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/README.md +0 -0
  99. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/e2e/flaky.spec.mjs +0 -0
  100. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/e2e/toggle.spec.mjs +0 -0
  101. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/expected.json +0 -0
  102. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/package-lock.json +0 -0
  103. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/package.json +0 -0
  104. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/playwright.config.mjs +0 -0
  105. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/src/toggle.mjs +0 -0
  106. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/test/toggle.test.mjs +0 -0
  107. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/test-results/.last-run.json +0 -0
  108. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/testguard.claims.json +0 -0
  109. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-playwright/vitest.config.mjs +0 -0
  110. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/.gitignore +0 -0
  111. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/README.md +0 -0
  112. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/demo/__init__.py +0 -0
  113. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/demo/export.py +0 -0
  114. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/demo/orphan.py +0 -0
  115. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/demo/pipeline.py +0 -0
  116. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/demo/redact.py +0 -0
  117. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/expected.json +0 -0
  118. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/testguard.claims.json +0 -0
  119. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/tests/test_export_mocked.py +0 -0
  120. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/tests/test_flaky.py +0 -0
  121. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/tests/test_patched.py +0 -0
  122. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/fixtures/known-answer-python/tests/test_redact.py +0 -0
  123. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/GATE-SEMANTICS.md +0 -0
  124. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/README.md +0 -0
  125. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/baseline.json +0 -0
  126. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/brief.json +0 -0
  127. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/calibration-websec.json +0 -0
  128. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/calibration.json +0 -0
  129. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/claims-methods.json +0 -0
  130. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/claims.json +0 -0
  131. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/evidence-disturbed-run.json +0 -0
  132. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/evidence-negative-control.json +0 -0
  133. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/evidence-provisional.json +0 -0
  134. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/evidence-python.json +0 -0
  135. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/evidence-scan-method.json +0 -0
  136. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/evidence.json +0 -0
  137. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/gate.json +0 -0
  138. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/ignore.json +0 -0
  139. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/replay.json +0 -0
  140. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/examples/status.json +0 -0
  141. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/baseline.bad-fingerprint-key.json +0 -0
  142. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/baseline.zero-count.json +0 -0
  143. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/brief.text-without-heading.json +0 -0
  144. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/brief.unknown-verdict-key.json +0 -0
  145. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.backoff-cell-not-wilson.json +0 -0
  146. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.breakdown-does-not-sum-to-n.json +0 -0
  147. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.ci-not-wilson.json +0 -0
  148. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.compound-key-arity-mismatch.json +0 -0
  149. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.fallback-without-basis.json +0 -0
  150. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.p-not-positives-over-n.json +0 -0
  151. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.p-outside-ci.json +0 -0
  152. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/calibration.positives-exceed-n.json +0 -0
  153. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.absolute-path.json +0 -0
  154. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.duplicate-fault-id.json +0 -0
  155. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.fault-injection-without-a-substitution.json +0 -0
  156. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.method-detail-on-a-specified-method.json +0 -0
  157. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.missing-provenance.json +0 -0
  158. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.noop-fault.json +0 -0
  159. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.occurrence-exceeds-hits.json +0 -0
  160. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/claims.parent-traversal.json +0 -0
  161. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.annotated-signal-without-reason.json +0 -0
  162. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.attribute-signal-not-a-defender.json +0 -0
  163. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.attribute-signal-without-attributes.json +0 -0
  164. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.byrunner-file-not-resolved.json +0 -0
  165. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.contention-without-runners.json +0 -0
  166. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.discovered-defender-mocks-subject.json +0 -0
  167. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.fault-injection-without-its-evidence.json +0 -0
  168. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.flaky-defender-without-flakiness.json +0 -0
  169. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.ignored-dirty-on-snapshot.json +0 -0
  170. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.killed-by-non-assertion.json +0 -0
  171. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.killed-on-red-baseline.json +0 -0
  172. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.killed-without-n-runs.json +0 -0
  173. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.method-detail-on-an-injecting-run.json +0 -0
  174. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.negative-control-not-reached-but-survived.json +0 -0
  175. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.negative-control-reached-on-a-kill.json +0 -0
  176. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.probe-error-without-message.json +0 -0
  177. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.provisional-flag-on-confirmed-run.json +0 -0
  178. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.rank-extra-property.json +0 -0
  179. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.restore-skipped-in-place.json +0 -0
  180. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.single-run-without-provisional.json +0 -0
  181. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.target-not-imported-but-killed.json +0 -0
  182. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.undeclared-killers-without-reason.json +0 -0
  183. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.unknown-verdict.json +0 -0
  184. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.unverifiable-without-reason.json +0 -0
  185. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/evidence.wrong-fingerprint.json +0 -0
  186. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/gate.counts-disagree.json +0 -0
  187. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/gate.exit-zero-with-uncovered.json +0 -0
  188. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/gate.ignore-cover-without-pattern.json +0 -0
  189. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/ignore.missing-reason.json +0 -0
  190. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/ignore.short-reason.json +0 -0
  191. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/replay.blind-with-a-failing-run.json +0 -0
  192. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/replay.duplicate-patch-id.json +0 -0
  193. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.claim-without-file.json +0 -0
  194. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.clean-with-new-findings.json +0 -0
  195. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.invalid-anchor-hidden.json +0 -0
  196. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.partial-scope-counts-disagree.json +0 -0
  197. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.surface-counts-disagree.json +0 -0
  198. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.unclaimed-hidden-behind-unproven.json +0 -0
  199. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/invalid/status.write-test-without-target.json +0 -0
  200. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/conformance/schemas.test.mjs +0 -0
  201. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/lib/fingerprint.mjs +0 -0
  202. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/lib/wilson.mjs +0 -0
  203. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/baseline.schema.json +0 -0
  204. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/brief.schema.json +0 -0
  205. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/calibration.schema.json +0 -0
  206. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/claims.schema.json +0 -0
  207. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/common.schema.json +0 -0
  208. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/evidence.schema.json +0 -0
  209. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/gate.schema.json +0 -0
  210. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/ignore.schema.json +0 -0
  211. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/replay.schema.json +0 -0
  212. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/spec/schemas/status.schema.json +0 -0
  213. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/admit/admit.mjs +0 -0
  214. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/baseline/baseline.mjs +0 -0
  215. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/brief/brief.mjs +0 -0
  216. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/claims/anchors.mjs +0 -0
  217. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/claims/annotations.mjs +0 -0
  218. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/claims/load.mjs +0 -0
  219. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/claims/removed.mjs +0 -0
  220. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/admit.mjs +0 -0
  221. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/baseline.mjs +0 -0
  222. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/brief.mjs +0 -0
  223. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/claims.mjs +0 -0
  224. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/gate.mjs +0 -0
  225. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/init.mjs +0 -0
  226. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/mcp.mjs +0 -0
  227. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/probe.mjs +0 -0
  228. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/replay.mjs +0 -0
  229. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/scaffold.mjs +0 -0
  230. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/commands/status.mjs +0 -0
  231. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/evidence/writer.mjs +0 -0
  232. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/gate/changed.mjs +0 -0
  233. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/git.mjs +0 -0
  234. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/init/init.mjs +0 -0
  235. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/init/templates/SKILL.md +0 -0
  236. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/mcp/server.mjs +0 -0
  237. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/mcp/tools.mjs +0 -0
  238. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/attribution.mjs +0 -0
  239. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/classify.mjs +0 -0
  240. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/contention.mjs +0 -0
  241. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/cost.mjs +0 -0
  242. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/discover.mjs +0 -0
  243. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/independence.mjs +0 -0
  244. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/inject.mjs +0 -0
  245. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/mocks.mjs +0 -0
  246. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/probe.mjs +0 -0
  247. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/progress.mjs +0 -0
  248. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/pyimports.mjs +0 -0
  249. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/rank.mjs +0 -0
  250. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/index.mjs +0 -0
  251. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/jest.mjs +0 -0
  252. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/playwright.mjs +0 -0
  253. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/python/_testguard_pytest_plugin.py +0 -0
  254. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/python/_testguard_report.py +0 -0
  255. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/python/_testguard_unittest_main.py +0 -0
  256. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/python.mjs +0 -0
  257. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/shared.mjs +0 -0
  258. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/runners/vitest.mjs +0 -0
  259. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/probe/worktree.mjs +0 -0
  260. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/render.mjs +0 -0
  261. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/replay/label.mjs +0 -0
  262. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/replay/replay.mjs +0 -0
  263. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/scaffold/producers.mjs +0 -0
  264. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/scaffold/producers.python.mjs +0 -0
  265. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/scaffold/scaffold.mjs +0 -0
  266. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/status/status.mjs +0 -0
  267. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/status/surface.mjs +0 -0
  268. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/src/util/hash.mjs +0 -0
  269. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/admit.test.mjs +0 -0
  270. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/annotations.test.mjs +0 -0
  271. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/attribution.test.mjs +0 -0
  272. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/baseline.test.mjs +0 -0
  273. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/brief.test.mjs +0 -0
  274. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/calibration.test.mjs +0 -0
  275. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/claim-selection.test.mjs +0 -0
  276. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/claims-anchors.test.mjs +0 -0
  277. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/claims-since.test.mjs +0 -0
  278. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/classify.test.mjs +0 -0
  279. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/contention.test.mjs +0 -0
  280. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/cost.test.mjs +0 -0
  281. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/discover.test.mjs +0 -0
  282. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/gate.test.mjs +0 -0
  283. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/gitlab-template.test.mjs +0 -0
  284. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/independence.test.mjs +0 -0
  285. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/init.test.mjs +0 -0
  286. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/inject.test.mjs +0 -0
  287. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/label.test.mjs +0 -0
  288. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/mcp.test.mjs +0 -0
  289. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/mocks.test.mjs +0 -0
  290. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/negative-control.test.mjs +0 -0
  291. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/one-pager.test.mjs +0 -0
  292. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/probe-error.test.mjs +0 -0
  293. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/probe-preconditions.test.mjs +0 -0
  294. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/probe.fixture.test.mjs +0 -0
  295. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/probe.jest.test.mjs +0 -0
  296. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/probe.playwright.test.mjs +0 -0
  297. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/probe.python.test.mjs +0 -0
  298. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/progress.test.mjs +0 -0
  299. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/pyimports.test.mjs +0 -0
  300. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/rank-aliases.test.mjs +0 -0
  301. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/release-approval.test.mjs +0 -0
  302. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/release-sync.test.mjs +0 -0
  303. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/replay-verdict.test.mjs +0 -0
  304. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/replay.test.mjs +0 -0
  305. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/runner-argv.test.mjs +0 -0
  306. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/runner-command.test.mjs +0 -0
  307. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/runner-playwright.test.mjs +0 -0
  308. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/runner-python.test.mjs +0 -0
  309. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/runner-vitest.test.mjs +0 -0
  310. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/samples/playwright-report.json +0 -0
  311. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/samples/python-report-collect-error.json +0 -0
  312. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/samples/python-report.json +0 -0
  313. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/scaffold.python.test.mjs +0 -0
  314. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/scaffold.test.mjs +0 -0
  315. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/snapshot.test.mjs +0 -0
  316. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/status.test.mjs +0 -0
  317. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/surface.test.mjs +0 -0
  318. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/vitest-config.test.mjs +0 -0
  319. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/worktree.test.mjs +0 -0
  320. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/test/writer.test.mjs +0 -0
  321. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/testguard_cli/__init__.py +0 -0
  322. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/testguard_cli/wrapper.py +0 -0
  323. {testguard_cli-0.10.4 → testguard_cli-0.12.0}/vitest.config.mjs +0 -0
@@ -17,7 +17,8 @@
17
17
  "docs-canonical/SECURITY.md",
18
18
  "docs-canonical/TEST-SPEC.md",
19
19
  "docs-canonical/ENVIRONMENT.md",
20
- "docs-canonical/REQUIREMENTS.md"
20
+ "docs-canonical/REQUIREMENTS.md",
21
+ "docs-canonical/PRIOR-ART.md"
21
22
  ]
22
23
  },
23
24
  "validators": {
@@ -7,6 +7,91 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.12.0] - 2026-09-22
11
+
12
+ Automated weekly release — everything merged since `v0.11.0`.
13
+
14
+ ### Changed
15
+
16
+ - feat(sweep): --save-paths, and the denominator a save report is read against (#156)
17
+ - docs: make the brief describe what the tool actually does, and record the prior art (#155)
18
+ - chore(homebrew): sha256 for v0.11.0 (#153)
19
+
20
+
21
+ ### Added
22
+
23
+ - `sweep --save-paths` — sweep every file that writes to storage instead of the
24
+ diff, and report the surface as the denominator the findings are read
25
+ against. A diff cannot answer how many save paths exist, and a clean report
26
+ over an unstated denominator is a sample of unknown size. The sweep document
27
+ gains `scope.mode`, `scope.writeSites` and `scope.payloadFields`, and the
28
+ validator refuses a save-paths sweep that omits its surface.
29
+ - `src/supply/savepath.mjs` — the write-site enumerator: which calls put data
30
+ into storage, and which payload keys sit on their own line (the ones a
31
+ `field-dropped` fault can anchor to). Measured on a real AI-authored
32
+ application: 119 writes across 37 files carrying 226 payload fields.
33
+
34
+ ### Fixed
35
+
36
+ - `walk()` skipped `dist` and `coverage` but not `.next`, `build`, `out`,
37
+ `.svelte-kit`, `.turbo` and their siblings, while the claim above it already
38
+ promised that a build's test files cannot be picked up. A scan of a real
39
+ Next.js application counted 104 files instead of 32, because `.next/` carries
40
+ compiled copies of the application — its writes and its tests. The claim was
41
+ right; the list was short.
42
+
43
+ ### Added
44
+
45
+ - `docs-canonical/PRIOR-ART.md` — the canonical record of what was taken from
46
+ Google's and Meta's mutation-testing programmes, what was deliberately not
47
+ taken, the measured reason no model decides a verdict, and the known gaps in
48
+ what was borrowed. Registered with DocGuard.
49
+ - README prior-art section pointing at it.
50
+
51
+ ### Changed
52
+
53
+ - The technical brief now describes what the tool actually does. A new
54
+ *Starting from zero* page carries Field report C (the persistence-path
55
+ measurement: 12 of 26 faults survived a green suite, all of them a dropped
56
+ payload field) and the claim-supply ladder; prior art names Google and Meta
57
+ and what each solved; the decision-model result is stated as a measurement
58
+ rather than a design assertion; and a *what it deliberately is not* section
59
+ closes it. `sweep` added to the verb table. Six pages to eight, re-rendered.
60
+
61
+ ## [0.11.0] - 2026-09-21
62
+
63
+ Automated weekly release — everything merged since `v0.10.4`.
64
+
65
+ ### Changed
66
+
67
+ - feat(sweep): findings on a repository that has no claims yet (#151)
68
+ - chore(homebrew): sha256 for v0.10.4 (#149)
69
+
70
+
71
+ ### Added
72
+
73
+ - `testguard sweep [dir] --changed <ref>` — the cold start. Proposes faults for
74
+ the changed source files that carry no claim, probes a bounded selection, and
75
+ reports what a green suite did not notice. Never writes
76
+ `testguard.claims.json`; its evidence never replaces
77
+ `.testguard/evidence.json`; only `survived` and `nocover` exit 1, so a
78
+ proposal the tool could not anchor or compile is reported and never gates.
79
+ Offline, like every other verifying command.
80
+ - Selection follows Google's mutation service: at most 7 × |files| candidates,
81
+ spread round-robin across files, ordered on the measured productivity of the
82
+ fault class and shrunk toward a neutral prior so one observation never
83
+ dominates (`src/supply/select.mjs`).
84
+ - `persistence-payload-unasserted` — why a survivor on a write path was missed:
85
+ the defender mocks the persistence layer and the file's call assertions never
86
+ name an exact payload, so a field dropped from a write cannot fail them.
87
+ Descriptive, never predictive; attached only to a survivor on a write path
88
+ (`src/supply/persistence.mjs`).
89
+ - `urn:claimspec:v1:sweep` — the sweep document, with semantic rules that check
90
+ a cap never hides its own remainder.
91
+ - Five self-claims (8 faults) covering the cap arithmetic, the exit-code rule,
92
+ where the persistence signal may be attached, per-file cap fairness, and that
93
+ one assertion's arguments are read without reading the next one's.
94
+
10
95
  ## [0.10.4] - 2026-09-21
11
96
 
12
97
  Automated weekly release — everything merged since `v0.10.3`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: testguard-cli
3
- Version: 0.10.4
3
+ Version: 0.12.0
4
4
  Summary: Breaks your code on purpose and reports every promise your tests did not notice breaking. Mutation testing bound to the claims a project makes — vitest, jest, Playwright, pytest and unittest. Ships the Node.js CLI (requires Node.js 20+).
5
5
  Project-URL: Homepage, https://github.com/raccioly/testguard
6
6
  Project-URL: Documentation, https://github.com/raccioly/testguard#readme
@@ -151,9 +151,9 @@ raises coverage. TestGuard admits it because it fails when the claim is false.
151
151
  | npm | `npm i -D testguard-cli` then `npx testguard probe` |
152
152
  | pip | `pip install testguard-cli` then `testguard probe` (needs Node ≥ 20) |
153
153
  | Homebrew | `brew tap raccioly/tap && brew install testguard` |
154
- | GitHub Action | `uses: raccioly/testguard@v0.10.4` — see [`action.yml`](./action.yml) |
154
+ | GitHub Action | `uses: raccioly/testguard@v0.12.0` — see [`action.yml`](./action.yml) |
155
155
  | pre-commit | `repo: https://github.com/raccioly/testguard`, hooks `testguard-claims`, `testguard-probe` |
156
- | GitLab CI | `include: - remote: https://raw.githubusercontent.com/raccioly/testguard/v0.10.4/packaging/gitlab/testguard.gitlab-ci.yml` with `inputs:` — see [`packaging/gitlab/`](./packaging/gitlab/testguard.gitlab-ci.yml) |
156
+ | GitLab CI | `include: - remote: https://raw.githubusercontent.com/raccioly/testguard/v0.12.0/packaging/gitlab/testguard.gitlab-ci.yml` with `inputs:` — see [`packaging/gitlab/`](./packaging/gitlab/testguard.gitlab-ci.yml) |
157
157
 
158
158
  Projects that set `min-release-age` in `.npmrc` cannot see a version published
159
159
  less than that many days ago (`ENOVERSIONS`); install that one with
@@ -171,6 +171,7 @@ npx testguard-cli probe # try to falsify each claim; report
171
171
  npx testguard-cli admit test/auth.test.ts --claim AUTH-ADMIN # does this test satisfy the two-gate rule?
172
172
  npx testguard-cli baseline # freeze today's unproven findings; only new ones gate
173
173
  npx testguard-cli gate --changed origin/main # fail when a changed source file carries no claim
174
+ npx testguard-cli sweep --changed origin/main # no claims yet? propose faults for the changed files and report what nothing noticed
174
175
  npx testguard-cli brief --text # tell the agent where the suite is blind, before it writes
175
176
  npx testguard-cli replay --since v1.0..HEAD # would this suite have caught the bugs that escaped?
176
177
  npx testguard-cli mcp # serve the read-only loop over MCP, on stdio
@@ -424,6 +425,104 @@ on-demand helper, not a hook**: the session-start hook never touches the
424
425
  network, and the helper exits 0 with a message when the CLI or the artifact
425
426
  is missing. TestGuard itself still makes no network calls.
426
427
 
428
+ ### Starting from zero claims
429
+
430
+ `gate` names the changed files that carry no claim, and stops there —
431
+ correctly, because stating a claim is a human act. But a project adopting this
432
+ tool reads that list, has nothing to compare it against, and closes the tab.
433
+ The bottleneck was never verification; it is **oracle supply**.
434
+
435
+ `sweep` is the lowest rung of that supply. No claim, no concern, nothing
436
+ written by anybody:
437
+
438
+ ```bash
439
+ npx testguard-cli sweep --changed origin/main # propose, probe a bounded selection, report
440
+ npx testguard-cli sweep --changed HEAD --include-dirty --cap 20
441
+ ```
442
+
443
+ It takes the files `gate` just called uncovered, proposes faults with the same
444
+ mechanical producers `scaffold` uses, probes a bounded selection, and reports
445
+ what a green suite did not notice. A fault that survives needs no claim to be
446
+ alarming: something was deliberately broken and not one test failed.
447
+
448
+ ```
449
+ swept 13 of 14 unclaimed changed files against origin/main.
450
+ proposed 510 faults, probed 10 (cap 10), deferred 500.
451
+ The 500 deferred are not a verdict: raise --cap, or sweep a smaller change.
452
+
453
+ 9 findings — a deliberate break that no test noticed:
454
+
455
+ SURVIVED src/app/actions/register.ts:118 [write path]
456
+ [line 118] Field dropped: `password_hash` is no longer written.
457
+ src/tests/actions/register.test.ts mocks @/lib/prisma; 1 exact, 8 partial,
458
+ 31 argument-free call assertions in the file. A field dropped from the write
459
+ payload fails only against an assertion that names that field exactly.
460
+ Assert the whole object written by the call this fault changes, including
461
+ `password_hash` — or read the record back and assert on what was stored.
462
+ ```
463
+
464
+ Three rules make it safe to run on a repository that has never seen this tool:
465
+
466
+ - **It never writes `testguard.claims.json`**, and never will. A claim is a
467
+ sentence someone is willing to stand behind; a sentence nobody wrote is not
468
+ one. Its drafts land beside the evidence to keep or drop.
469
+ - **Its evidence never replaces `.testguard/evidence.json`.** A sweep probes
470
+ faults nobody stated, under TODO statements; folding that into the document
471
+ `status` and `baseline` read would corrupt the record of what the project
472
+ actually claims.
473
+ - **It does not fail on its own bad guess.** Only `survived` and `nocover`
474
+ exit 1. A proposal that would not compile, or an anchor that did not locate,
475
+ is reported and never gates — a tool that fails because its own guess was bad
476
+ is a tool people switch off.
477
+
478
+ The cap and the ordering are Google's: their mutation service surfaces at most
479
+ 7 × |files| mutants per change and orders candidates on the measured
480
+ productivity of their operator in similar context, which took their productive
481
+ rate from 15% to 89%
482
+ ([Petrović et al., *Practical Mutation Testing at Scale*, 2021](https://arxiv.org/abs/2102.11378)).
483
+ TestGuard's ordering prior is measured the same way — from probed faults on a
484
+ real AI-authored codebase — and shrunk toward a neutral value, so one
485
+ observation of a class surviving never dominates a sweep. The cap is spread
486
+ across files: a single file with many candidates cannot make the others look
487
+ clean.
488
+
489
+ A sweep is weaker evidence than a probe, and says so. Nobody stated that the
490
+ behaviour mattered. It is stronger than nothing, which is what a repository
491
+ with no claims has — and the survivors worth defending become the first claims.
492
+
493
+ #### Sweeping the save surface instead of the diff
494
+
495
+ A diff cannot answer *"when the user clicks save, does it actually save?"* — it
496
+ only knows what changed today. `--save-paths` points the same sweep at every
497
+ file that writes to storage:
498
+
499
+ ```bash
500
+ npx testguard-cli sweep --save-paths --cap 20
501
+ ```
502
+
503
+ ```
504
+ 119 writes to storage across 37 files, carrying 226 payload fields. Swept 36.
505
+ proposed 762 faults, probed 20 (cap 20), deferred 742.
506
+
507
+ SURVIVED src/app/actions/register.ts [write path]
508
+ [line 59] Field dropped: `password_hash` is no longer written.
509
+ src/tests/actions/register.test.ts mocks @/lib/prisma; 1 exact, 8 partial,
510
+ 31 argument-free call assertions in the file. A field dropped from the write
511
+ payload fails only against an assertion that names that field exactly.
512
+ ```
513
+
514
+ The first line is the point. A report that lists findings without saying how
515
+ much surface it looked at invites you to assume the rest is fine, so the
516
+ denominator comes first and the document carries `writeSites` and
517
+ `payloadFields` whether or not anything survived. Measured on a real
518
+ AI-authored application: **12 of 26 probed persistence faults survived a fully
519
+ green suite, and all 12 were a dropped payload field.**
520
+
521
+ This is a *sample* of the surface, and says so. It does not yet prove a write
522
+ reached storage — only that a test would notice if the payload changed.
523
+ Read-back oracles are the next rung
524
+ ([#154](https://github.com/raccioly/testguard/issues/154)).
525
+
427
526
  ### Every change needs a claim
428
527
 
429
528
  `probe` can only verify claims that exist. Every escaped defect in the field
@@ -505,12 +604,12 @@ detected base that does not resolve is a warning for `status` and `brief`
505
604
  # GitHub Actions
506
605
  - uses: actions/checkout@v4
507
606
  with: { fetch-depth: 0 }
508
- - uses: raccioly/testguard@v0.10.4
607
+ - uses: raccioly/testguard@v0.12.0
509
608
  with: { command: gate }
510
609
 
511
610
  # GitLab CI — the component-shaped template: gate + probe, brief as an artifact and, opted in, as a merge-request note
512
611
  include:
513
- - remote: 'https://raw.githubusercontent.com/raccioly/testguard/v0.10.4/packaging/gitlab/testguard.gitlab-ci.yml'
612
+ - remote: 'https://raw.githubusercontent.com/raccioly/testguard/v0.12.0/packaging/gitlab/testguard.gitlab-ci.yml'
514
613
  inputs: { dir: backend, post_note: true } # post_note needs TESTGUARD_GITLAB_TOKEN (api scope); one note, updated in place
515
614
  ```
516
615
 
@@ -538,6 +637,32 @@ talks to the network; only the job posts, and only when told to.
538
637
  toward green. The one pass is `killed`; everything else gates.
539
638
  - **One exact-pinned runtime dependency** (`ajv`), Node ≥ 20, MIT.
540
639
 
640
+ ### Prior art, and what was taken from where
641
+
642
+ Breaking code to test the tests is mutation testing, and it dates to the 1970s.
643
+ Two industrial programmes solved the parts that make it usable, and this tool
644
+ takes from both.
645
+
646
+ **Google** made it affordable: mutate only *changed* lines, cap what is
647
+ surfaced at seven per file, and order candidates by the measured productivity
648
+ of the operator in similar context — developer feedback took their productive
649
+ rate from 15% to 89%
650
+ ([Petrović et al., 2021](https://arxiv.org/abs/2102.11378)). `sweep`'s diff
651
+ scope, its cap and its ordering are theirs; the productivity prior here is
652
+ measured on real probed faults rather than assumed.
653
+
654
+ **Meta** made it specific: an engineer writes a *concern* in plain text, a
655
+ model drafts faults for it, and every step is gated by execution before a
656
+ human ever sees it — 73% of the resulting tests were accepted
657
+ ([Foster et al., FSE 2025](https://arxiv.org/abs/2501.12862)). The rule that
658
+ nothing a model proposes reaches the claims file without passing `probe` and a
659
+ human keep is theirs.
660
+
661
+ What neither does is bind a fault to a **stated promise**, which is what this
662
+ tool is for. The full record — including what was deliberately *not* taken, the
663
+ measured reason no model decides a verdict, and the gaps in what we borrowed —
664
+ is in [`docs-canonical/PRIOR-ART.md`](docs-canonical/PRIOR-ART.md).
665
+
541
666
  ### What TestGuard is not
542
667
 
543
668
  - **Not a test generator.** It judges a test the agent wrote (`admit`); the
@@ -848,7 +973,7 @@ verdicts.
848
973
  ## Status
849
974
 
850
975
  **v0.5.** Eleven commands (`status`, `init`, `claims`, `probe`, `admit`,
851
- `replay`, `baseline`, `brief`, `gate`, `scaffold`, `mcp`), vitest, jest,
976
+ `replay`, `baseline`, `brief`, `gate`, `scaffold`, `sweep`, `mcp`), vitest, jest,
852
977
  Playwright and Python (pytest / stdlib unittest) runners, hand-authored faults
853
978
  plus a mechanical scaffold for JavaScript and Python, an agent operating layer
854
979
  (`status`, `init`) and a change gate (`gate`). The contract spine — eight JSON
@@ -127,9 +127,9 @@ raises coverage. TestGuard admits it because it fails when the claim is false.
127
127
  | npm | `npm i -D testguard-cli` then `npx testguard probe` |
128
128
  | pip | `pip install testguard-cli` then `testguard probe` (needs Node ≥ 20) |
129
129
  | Homebrew | `brew tap raccioly/tap && brew install testguard` |
130
- | GitHub Action | `uses: raccioly/testguard@v0.10.4` — see [`action.yml`](./action.yml) |
130
+ | GitHub Action | `uses: raccioly/testguard@v0.12.0` — see [`action.yml`](./action.yml) |
131
131
  | pre-commit | `repo: https://github.com/raccioly/testguard`, hooks `testguard-claims`, `testguard-probe` |
132
- | GitLab CI | `include: - remote: https://raw.githubusercontent.com/raccioly/testguard/v0.10.4/packaging/gitlab/testguard.gitlab-ci.yml` with `inputs:` — see [`packaging/gitlab/`](./packaging/gitlab/testguard.gitlab-ci.yml) |
132
+ | GitLab CI | `include: - remote: https://raw.githubusercontent.com/raccioly/testguard/v0.12.0/packaging/gitlab/testguard.gitlab-ci.yml` with `inputs:` — see [`packaging/gitlab/`](./packaging/gitlab/testguard.gitlab-ci.yml) |
133
133
 
134
134
  Projects that set `min-release-age` in `.npmrc` cannot see a version published
135
135
  less than that many days ago (`ENOVERSIONS`); install that one with
@@ -147,6 +147,7 @@ npx testguard-cli probe # try to falsify each claim; report
147
147
  npx testguard-cli admit test/auth.test.ts --claim AUTH-ADMIN # does this test satisfy the two-gate rule?
148
148
  npx testguard-cli baseline # freeze today's unproven findings; only new ones gate
149
149
  npx testguard-cli gate --changed origin/main # fail when a changed source file carries no claim
150
+ npx testguard-cli sweep --changed origin/main # no claims yet? propose faults for the changed files and report what nothing noticed
150
151
  npx testguard-cli brief --text # tell the agent where the suite is blind, before it writes
151
152
  npx testguard-cli replay --since v1.0..HEAD # would this suite have caught the bugs that escaped?
152
153
  npx testguard-cli mcp # serve the read-only loop over MCP, on stdio
@@ -400,6 +401,104 @@ on-demand helper, not a hook**: the session-start hook never touches the
400
401
  network, and the helper exits 0 with a message when the CLI or the artifact
401
402
  is missing. TestGuard itself still makes no network calls.
402
403
 
404
+ ### Starting from zero claims
405
+
406
+ `gate` names the changed files that carry no claim, and stops there —
407
+ correctly, because stating a claim is a human act. But a project adopting this
408
+ tool reads that list, has nothing to compare it against, and closes the tab.
409
+ The bottleneck was never verification; it is **oracle supply**.
410
+
411
+ `sweep` is the lowest rung of that supply. No claim, no concern, nothing
412
+ written by anybody:
413
+
414
+ ```bash
415
+ npx testguard-cli sweep --changed origin/main # propose, probe a bounded selection, report
416
+ npx testguard-cli sweep --changed HEAD --include-dirty --cap 20
417
+ ```
418
+
419
+ It takes the files `gate` just called uncovered, proposes faults with the same
420
+ mechanical producers `scaffold` uses, probes a bounded selection, and reports
421
+ what a green suite did not notice. A fault that survives needs no claim to be
422
+ alarming: something was deliberately broken and not one test failed.
423
+
424
+ ```
425
+ swept 13 of 14 unclaimed changed files against origin/main.
426
+ proposed 510 faults, probed 10 (cap 10), deferred 500.
427
+ The 500 deferred are not a verdict: raise --cap, or sweep a smaller change.
428
+
429
+ 9 findings — a deliberate break that no test noticed:
430
+
431
+ SURVIVED src/app/actions/register.ts:118 [write path]
432
+ [line 118] Field dropped: `password_hash` is no longer written.
433
+ src/tests/actions/register.test.ts mocks @/lib/prisma; 1 exact, 8 partial,
434
+ 31 argument-free call assertions in the file. A field dropped from the write
435
+ payload fails only against an assertion that names that field exactly.
436
+ Assert the whole object written by the call this fault changes, including
437
+ `password_hash` — or read the record back and assert on what was stored.
438
+ ```
439
+
440
+ Three rules make it safe to run on a repository that has never seen this tool:
441
+
442
+ - **It never writes `testguard.claims.json`**, and never will. A claim is a
443
+ sentence someone is willing to stand behind; a sentence nobody wrote is not
444
+ one. Its drafts land beside the evidence to keep or drop.
445
+ - **Its evidence never replaces `.testguard/evidence.json`.** A sweep probes
446
+ faults nobody stated, under TODO statements; folding that into the document
447
+ `status` and `baseline` read would corrupt the record of what the project
448
+ actually claims.
449
+ - **It does not fail on its own bad guess.** Only `survived` and `nocover`
450
+ exit 1. A proposal that would not compile, or an anchor that did not locate,
451
+ is reported and never gates — a tool that fails because its own guess was bad
452
+ is a tool people switch off.
453
+
454
+ The cap and the ordering are Google's: their mutation service surfaces at most
455
+ 7 × |files| mutants per change and orders candidates on the measured
456
+ productivity of their operator in similar context, which took their productive
457
+ rate from 15% to 89%
458
+ ([Petrović et al., *Practical Mutation Testing at Scale*, 2021](https://arxiv.org/abs/2102.11378)).
459
+ TestGuard's ordering prior is measured the same way — from probed faults on a
460
+ real AI-authored codebase — and shrunk toward a neutral value, so one
461
+ observation of a class surviving never dominates a sweep. The cap is spread
462
+ across files: a single file with many candidates cannot make the others look
463
+ clean.
464
+
465
+ A sweep is weaker evidence than a probe, and says so. Nobody stated that the
466
+ behaviour mattered. It is stronger than nothing, which is what a repository
467
+ with no claims has — and the survivors worth defending become the first claims.
468
+
469
+ #### Sweeping the save surface instead of the diff
470
+
471
+ A diff cannot answer *"when the user clicks save, does it actually save?"* — it
472
+ only knows what changed today. `--save-paths` points the same sweep at every
473
+ file that writes to storage:
474
+
475
+ ```bash
476
+ npx testguard-cli sweep --save-paths --cap 20
477
+ ```
478
+
479
+ ```
480
+ 119 writes to storage across 37 files, carrying 226 payload fields. Swept 36.
481
+ proposed 762 faults, probed 20 (cap 20), deferred 742.
482
+
483
+ SURVIVED src/app/actions/register.ts [write path]
484
+ [line 59] Field dropped: `password_hash` is no longer written.
485
+ src/tests/actions/register.test.ts mocks @/lib/prisma; 1 exact, 8 partial,
486
+ 31 argument-free call assertions in the file. A field dropped from the write
487
+ payload fails only against an assertion that names that field exactly.
488
+ ```
489
+
490
+ The first line is the point. A report that lists findings without saying how
491
+ much surface it looked at invites you to assume the rest is fine, so the
492
+ denominator comes first and the document carries `writeSites` and
493
+ `payloadFields` whether or not anything survived. Measured on a real
494
+ AI-authored application: **12 of 26 probed persistence faults survived a fully
495
+ green suite, and all 12 were a dropped payload field.**
496
+
497
+ This is a *sample* of the surface, and says so. It does not yet prove a write
498
+ reached storage — only that a test would notice if the payload changed.
499
+ Read-back oracles are the next rung
500
+ ([#154](https://github.com/raccioly/testguard/issues/154)).
501
+
403
502
  ### Every change needs a claim
404
503
 
405
504
  `probe` can only verify claims that exist. Every escaped defect in the field
@@ -481,12 +580,12 @@ detected base that does not resolve is a warning for `status` and `brief`
481
580
  # GitHub Actions
482
581
  - uses: actions/checkout@v4
483
582
  with: { fetch-depth: 0 }
484
- - uses: raccioly/testguard@v0.10.4
583
+ - uses: raccioly/testguard@v0.12.0
485
584
  with: { command: gate }
486
585
 
487
586
  # GitLab CI — the component-shaped template: gate + probe, brief as an artifact and, opted in, as a merge-request note
488
587
  include:
489
- - remote: 'https://raw.githubusercontent.com/raccioly/testguard/v0.10.4/packaging/gitlab/testguard.gitlab-ci.yml'
588
+ - remote: 'https://raw.githubusercontent.com/raccioly/testguard/v0.12.0/packaging/gitlab/testguard.gitlab-ci.yml'
490
589
  inputs: { dir: backend, post_note: true } # post_note needs TESTGUARD_GITLAB_TOKEN (api scope); one note, updated in place
491
590
  ```
492
591
 
@@ -514,6 +613,32 @@ talks to the network; only the job posts, and only when told to.
514
613
  toward green. The one pass is `killed`; everything else gates.
515
614
  - **One exact-pinned runtime dependency** (`ajv`), Node ≥ 20, MIT.
516
615
 
616
+ ### Prior art, and what was taken from where
617
+
618
+ Breaking code to test the tests is mutation testing, and it dates to the 1970s.
619
+ Two industrial programmes solved the parts that make it usable, and this tool
620
+ takes from both.
621
+
622
+ **Google** made it affordable: mutate only *changed* lines, cap what is
623
+ surfaced at seven per file, and order candidates by the measured productivity
624
+ of the operator in similar context — developer feedback took their productive
625
+ rate from 15% to 89%
626
+ ([Petrović et al., 2021](https://arxiv.org/abs/2102.11378)). `sweep`'s diff
627
+ scope, its cap and its ordering are theirs; the productivity prior here is
628
+ measured on real probed faults rather than assumed.
629
+
630
+ **Meta** made it specific: an engineer writes a *concern* in plain text, a
631
+ model drafts faults for it, and every step is gated by execution before a
632
+ human ever sees it — 73% of the resulting tests were accepted
633
+ ([Foster et al., FSE 2025](https://arxiv.org/abs/2501.12862)). The rule that
634
+ nothing a model proposes reaches the claims file without passing `probe` and a
635
+ human keep is theirs.
636
+
637
+ What neither does is bind a fault to a **stated promise**, which is what this
638
+ tool is for. The full record — including what was deliberately *not* taken, the
639
+ measured reason no model decides a verdict, and the gaps in what we borrowed —
640
+ is in [`docs-canonical/PRIOR-ART.md`](docs-canonical/PRIOR-ART.md).
641
+
517
642
  ### What TestGuard is not
518
643
 
519
644
  - **Not a test generator.** It judges a test the agent wrote (`admit`); the
@@ -824,7 +949,7 @@ verdicts.
824
949
  ## Status
825
950
 
826
951
  **v0.5.** Eleven commands (`status`, `init`, `claims`, `probe`, `admit`,
827
- `replay`, `baseline`, `brief`, `gate`, `scaffold`, `mcp`), vitest, jest,
952
+ `replay`, `baseline`, `brief`, `gate`, `scaffold`, `sweep`, `mcp`), vitest, jest,
828
953
  Playwright and Python (pytest / stdlib unittest) runners, hand-authored faults
829
954
  plus a mechanical scaffold for JavaScript and Python, an agent operating layer
830
955
  (`status`, `init`) and a change gate (`gate`). The contract spine — eight JSON
@@ -46,7 +46,7 @@ inputs:
46
46
  version:
47
47
  description: 'testguard-cli version to run'
48
48
  required: false
49
- default: '0.10.4'
49
+ default: '0.12.0'
50
50
  node-version:
51
51
  description: 'Node.js version (20+)'
52
52
  required: false