testguard-cli 0.4.0__tar.gz → 0.6.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 (245) hide show
  1. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/scripts/sync-release-version.mjs +3 -0
  2. testguard_cli-0.6.0/.github/workflows/ci.yml +260 -0
  3. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.gitignore +2 -0
  4. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.pre-commit-hooks.yaml +9 -0
  5. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/AGENTS.md +4 -2
  6. testguard_cli-0.6.0/CHANGELOG.md +532 -0
  7. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/CONTRIBUTING.md +1 -1
  8. testguard_cli-0.6.0/PKG-INFO +552 -0
  9. testguard_cli-0.6.0/README.md +528 -0
  10. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/action.yml +19 -2
  11. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/bench/README.md +19 -0
  12. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/README.md +3 -0
  13. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/expected.json +12 -0
  14. testguard_cli-0.6.0/fixtures/known-answer/test/export-mocked.test.mjs +13 -0
  15. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/testguard.claims.json +69 -0
  16. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/expected.json +4 -0
  17. testguard_cli-0.6.0/fixtures/known-answer-jest/test/export-mocked.test.js +11 -0
  18. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/testguard.claims.json +27 -0
  19. testguard_cli-0.6.0/fixtures/known-answer-playwright/.gitignore +4 -0
  20. testguard_cli-0.6.0/fixtures/known-answer-playwright/README.md +30 -0
  21. testguard_cli-0.6.0/fixtures/known-answer-playwright/e2e/flaky.spec.mjs +16 -0
  22. testguard_cli-0.6.0/fixtures/known-answer-playwright/e2e/toggle.spec.mjs +16 -0
  23. testguard_cli-0.6.0/fixtures/known-answer-playwright/expected.json +31 -0
  24. testguard_cli-0.6.0/fixtures/known-answer-playwright/package-lock.json +1214 -0
  25. testguard_cli-0.6.0/fixtures/known-answer-playwright/package.json +12 -0
  26. testguard_cli-0.6.0/fixtures/known-answer-playwright/playwright.config.mjs +11 -0
  27. testguard_cli-0.6.0/fixtures/known-answer-playwright/src/toggle.mjs +15 -0
  28. testguard_cli-0.6.0/fixtures/known-answer-playwright/test/toggle.test.mjs +10 -0
  29. testguard_cli-0.6.0/fixtures/known-answer-playwright/test-results/.last-run.json +4 -0
  30. testguard_cli-0.6.0/fixtures/known-answer-playwright/testguard.claims.json +185 -0
  31. testguard_cli-0.6.0/fixtures/known-answer-playwright/vitest.config.mjs +1 -0
  32. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/package-lock.json +2 -2
  33. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/package.json +1 -1
  34. testguard_cli-0.6.0/packaging/gitlab/testguard.gitlab-ci.yml +120 -0
  35. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/packaging/homebrew/testguard.rb +1 -1
  36. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/pyproject.toml +1 -1
  37. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/GATE-SEMANTICS.md +109 -1
  38. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/README.md +4 -2
  39. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/claims.json +24 -0
  40. testguard_cli-0.6.0/spec/conformance/examples/evidence.json +579 -0
  41. testguard_cli-0.6.0/spec/conformance/examples/gate.json +38 -0
  42. testguard_cli-0.6.0/spec/conformance/examples/replay.json +59 -0
  43. testguard_cli-0.6.0/spec/conformance/invalid/evidence.annotated-signal-without-reason.json +548 -0
  44. testguard_cli-0.6.0/spec/conformance/invalid/evidence.byrunner-file-not-resolved.json +560 -0
  45. testguard_cli-0.6.0/spec/conformance/invalid/evidence.contention-without-runners.json +574 -0
  46. testguard_cli-0.6.0/spec/conformance/invalid/evidence.discovered-defender-mocks-subject.json +552 -0
  47. testguard_cli-0.4.0/spec/conformance/examples/evidence.json → testguard_cli-0.6.0/spec/conformance/invalid/evidence.ignored-dirty-on-snapshot.json +4 -1
  48. testguard_cli-0.6.0/spec/conformance/invalid/gate.counts-disagree.json +20 -0
  49. testguard_cli-0.6.0/spec/conformance/invalid/gate.exit-zero-with-uncovered.json +20 -0
  50. testguard_cli-0.6.0/spec/conformance/invalid/gate.ignore-cover-without-pattern.json +20 -0
  51. testguard_cli-0.6.0/spec/conformance/invalid/replay.blind-with-a-failing-run.json +20 -0
  52. testguard_cli-0.6.0/spec/conformance/invalid/replay.duplicate-patch-id.json +26 -0
  53. testguard_cli-0.6.0/spec/conformance/invalid/status.claim-without-file.json +29 -0
  54. testguard_cli-0.6.0/spec/conformance/invalid/status.unclaimed-hidden-behind-unproven.json +40 -0
  55. testguard_cli-0.6.0/spec/lib/validate.mjs +206 -0
  56. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/schemas/baseline.schema.json +8 -0
  57. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/schemas/brief.schema.json +11 -1
  58. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/schemas/common.schema.json +32 -1
  59. testguard_cli-0.6.0/spec/schemas/evidence.schema.json +549 -0
  60. testguard_cli-0.6.0/spec/schemas/gate.schema.json +52 -0
  61. testguard_cli-0.6.0/spec/schemas/replay.schema.json +85 -0
  62. testguard_cli-0.6.0/spec/schemas/status.schema.json +334 -0
  63. testguard_cli-0.6.0/src/admit/admit.mjs +17 -0
  64. testguard_cli-0.6.0/src/baseline/baseline.mjs +63 -0
  65. testguard_cli-0.6.0/src/brief/brief.mjs +177 -0
  66. testguard_cli-0.6.0/src/claims/removed.mjs +161 -0
  67. testguard_cli-0.6.0/src/cli.mjs +194 -0
  68. testguard_cli-0.6.0/src/commands/admit.mjs +116 -0
  69. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/commands/baseline.mjs +17 -3
  70. testguard_cli-0.6.0/src/commands/brief.mjs +48 -0
  71. testguard_cli-0.6.0/src/commands/claims.mjs +59 -0
  72. testguard_cli-0.6.0/src/commands/gate.mjs +47 -0
  73. testguard_cli-0.6.0/src/commands/init.mjs +28 -0
  74. testguard_cli-0.6.0/src/commands/mcp.mjs +12 -0
  75. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/commands/probe.mjs +12 -3
  76. testguard_cli-0.6.0/src/commands/replay.mjs +63 -0
  77. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/commands/status.mjs +4 -1
  78. testguard_cli-0.6.0/src/gate/changed.mjs +222 -0
  79. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/git.mjs +5 -0
  80. testguard_cli-0.6.0/src/init/init.mjs +235 -0
  81. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/init/templates/SKILL.md +21 -3
  82. testguard_cli-0.6.0/src/mcp/server.mjs +104 -0
  83. testguard_cli-0.6.0/src/mcp/tools.mjs +114 -0
  84. testguard_cli-0.6.0/src/probe/contention.mjs +60 -0
  85. testguard_cli-0.6.0/src/probe/discover.mjs +21 -0
  86. testguard_cli-0.6.0/src/probe/independence.mjs +59 -0
  87. testguard_cli-0.6.0/src/probe/mocks.mjs +120 -0
  88. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/probe.mjs +126 -18
  89. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/rank.mjs +73 -15
  90. testguard_cli-0.6.0/src/probe/runners/index.mjs +64 -0
  91. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/runners/jest.mjs +3 -3
  92. testguard_cli-0.6.0/src/probe/runners/playwright.mjs +133 -0
  93. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/runners/shared.mjs +70 -13
  94. testguard_cli-0.6.0/src/probe/runners/vitest.mjs +8 -0
  95. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/render.mjs +2 -2
  96. testguard_cli-0.6.0/src/replay/label.mjs +64 -0
  97. testguard_cli-0.6.0/src/replay/replay.mjs +309 -0
  98. testguard_cli-0.6.0/src/scaffold/producers.mjs +296 -0
  99. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/scaffold/scaffold.mjs +9 -3
  100. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/status/status.mjs +88 -7
  101. testguard_cli-0.6.0/test/admit.test.mjs +125 -0
  102. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/baseline.test.mjs +30 -1
  103. testguard_cli-0.6.0/test/brief.test.mjs +144 -0
  104. testguard_cli-0.6.0/test/claims-since.test.mjs +150 -0
  105. testguard_cli-0.6.0/test/contention.test.mjs +59 -0
  106. testguard_cli-0.6.0/test/discover.test.mjs +55 -0
  107. testguard_cli-0.6.0/test/gate.test.mjs +227 -0
  108. testguard_cli-0.6.0/test/gitlab-template.test.mjs +47 -0
  109. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/glob.test.mjs +15 -2
  110. testguard_cli-0.6.0/test/independence.test.mjs +100 -0
  111. testguard_cli-0.6.0/test/init.test.mjs +234 -0
  112. testguard_cli-0.6.0/test/mcp.test.mjs +222 -0
  113. testguard_cli-0.6.0/test/mocks.test.mjs +67 -0
  114. testguard_cli-0.6.0/test/probe-preconditions.test.mjs +63 -0
  115. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/probe.fixture.test.mjs +38 -6
  116. testguard_cli-0.6.0/test/probe.playwright.test.mjs +73 -0
  117. testguard_cli-0.6.0/test/release-sync.test.mjs +57 -0
  118. testguard_cli-0.6.0/test/replay.test.mjs +391 -0
  119. testguard_cli-0.6.0/test/runner-playwright.test.mjs +170 -0
  120. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/runner-vitest.test.mjs +53 -1
  121. testguard_cli-0.6.0/test/samples/playwright-report.json +295 -0
  122. testguard_cli-0.6.0/test/scaffold.test.mjs +300 -0
  123. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/status.test.mjs +91 -3
  124. testguard_cli-0.6.0/testguard.claims.json +1963 -0
  125. testguard_cli-0.6.0/testguard.ignore.json +41 -0
  126. testguard_cli-0.4.0/.github/workflows/ci.yml +0 -149
  127. testguard_cli-0.4.0/.testguard/baseline.json +0 -11
  128. testguard_cli-0.4.0/.testguard/status.json +0 -32
  129. testguard_cli-0.4.0/CHANGELOG.md +0 -241
  130. testguard_cli-0.4.0/PKG-INFO +0 -258
  131. testguard_cli-0.4.0/README.md +0 -234
  132. testguard_cli-0.4.0/spec/lib/validate.mjs +0 -132
  133. testguard_cli-0.4.0/spec/schemas/evidence.schema.json +0 -238
  134. testguard_cli-0.4.0/spec/schemas/status.schema.json +0 -110
  135. testguard_cli-0.4.0/src/baseline/baseline.mjs +0 -34
  136. testguard_cli-0.4.0/src/brief/brief.mjs +0 -89
  137. testguard_cli-0.4.0/src/cli.mjs +0 -137
  138. testguard_cli-0.4.0/src/commands/brief.mjs +0 -34
  139. testguard_cli-0.4.0/src/commands/claims.mjs +0 -30
  140. testguard_cli-0.4.0/src/commands/init.mjs +0 -15
  141. testguard_cli-0.4.0/src/init/init.mjs +0 -82
  142. testguard_cli-0.4.0/src/probe/discover.mjs +0 -12
  143. testguard_cli-0.4.0/src/probe/runners/index.mjs +0 -20
  144. testguard_cli-0.4.0/src/probe/runners/vitest.mjs +0 -7
  145. testguard_cli-0.4.0/src/scaffold/producers.mjs +0 -85
  146. testguard_cli-0.4.0/test/brief.test.mjs +0 -82
  147. testguard_cli-0.4.0/test/discover.test.mjs +0 -22
  148. testguard_cli-0.4.0/test/init.test.mjs +0 -57
  149. testguard_cli-0.4.0/test/probe-preconditions.test.mjs +0 -37
  150. testguard_cli-0.4.0/test/scaffold.test.mjs +0 -133
  151. testguard_cli-0.4.0/testguard.claims.json +0 -379
  152. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.codex/hooks.json +0 -0
  153. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.gitattributes +0 -0
  154. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  155. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  156. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  157. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/dependabot.yml +0 -0
  158. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/scripts/install-smoke.mjs +0 -0
  159. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/workflows/auto-merge.yml +0 -0
  160. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/workflows/release.yml +0 -0
  161. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/workflows/scheduled-release.yml +0 -0
  162. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.github/workflows/supply-chain.yml +0 -0
  163. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.npmignore +0 -0
  164. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/.npmrc +0 -0
  165. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/CLAUDE.md +0 -0
  166. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/CODE_OF_CONDUCT.md +0 -0
  167. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/LICENSE +0 -0
  168. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/PRIVACY.md +0 -0
  169. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/SECURITY.md +0 -0
  170. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/SUPPORT.md +0 -0
  171. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/cli/testguard.mjs +0 -0
  172. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/.gitignore +0 -0
  173. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/package.json +0 -0
  174. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/src/export.mjs +0 -0
  175. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/src/redact.mjs +0 -0
  176. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/test/flaky.test.mjs +0 -0
  177. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/test/redact.test.mjs +0 -0
  178. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer/vitest.config.mjs +0 -0
  179. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/.gitignore +0 -0
  180. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/README.md +0 -0
  181. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/jest.config.js +0 -0
  182. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/package.json +0 -0
  183. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/src/export.js +0 -0
  184. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/src/redact.js +0 -0
  185. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/test/flaky.test.js +0 -0
  186. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/fixtures/known-answer-jest/test/redact.test.js +0 -0
  187. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/baseline.json +0 -0
  188. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/brief.json +0 -0
  189. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/calibration.json +0 -0
  190. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/evidence-provisional.json +0 -0
  191. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/ignore.json +0 -0
  192. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/examples/status.json +0 -0
  193. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/baseline.bad-fingerprint-key.json +0 -0
  194. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/baseline.zero-count.json +0 -0
  195. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/brief.text-without-heading.json +0 -0
  196. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/brief.unknown-verdict-key.json +0 -0
  197. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/calibration.p-outside-ci.json +0 -0
  198. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/calibration.positives-exceed-n.json +0 -0
  199. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/claims.absolute-path.json +0 -0
  200. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/claims.duplicate-fault-id.json +0 -0
  201. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/claims.missing-provenance.json +0 -0
  202. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/claims.noop-fault.json +0 -0
  203. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/claims.occurrence-exceeds-hits.json +0 -0
  204. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/claims.parent-traversal.json +0 -0
  205. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.flaky-defender-without-flakiness.json +0 -0
  206. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.killed-by-non-assertion.json +0 -0
  207. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.killed-on-red-baseline.json +0 -0
  208. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.killed-without-n-runs.json +0 -0
  209. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.provisional-flag-on-confirmed-run.json +0 -0
  210. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.rank-extra-property.json +0 -0
  211. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.single-run-without-provisional.json +0 -0
  212. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.undeclared-killers-without-reason.json +0 -0
  213. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.unknown-verdict.json +0 -0
  214. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.unverifiable-without-reason.json +0 -0
  215. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/evidence.wrong-fingerprint.json +0 -0
  216. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/ignore.missing-reason.json +0 -0
  217. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/ignore.short-reason.json +0 -0
  218. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/status.clean-with-new-findings.json +0 -0
  219. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/invalid/status.write-test-without-target.json +0 -0
  220. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/conformance/schemas.test.mjs +0 -0
  221. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/lib/fingerprint.mjs +0 -0
  222. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/schemas/calibration.schema.json +0 -0
  223. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/schemas/claims.schema.json +0 -0
  224. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/spec/schemas/ignore.schema.json +0 -0
  225. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/claims/annotations.mjs +0 -0
  226. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/claims/load.mjs +0 -0
  227. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/commands/scaffold.mjs +0 -0
  228. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/evidence/writer.mjs +0 -0
  229. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/classify.mjs +0 -0
  230. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/inject.mjs +0 -0
  231. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/probe/worktree.mjs +0 -0
  232. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/util/glob.mjs +0 -0
  233. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/src/util/hash.mjs +0 -0
  234. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/annotations.test.mjs +0 -0
  235. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/classify.test.mjs +0 -0
  236. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/inject.test.mjs +0 -0
  237. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/probe.jest.test.mjs +0 -0
  238. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/rank-aliases.test.mjs +0 -0
  239. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/runner-command.test.mjs +0 -0
  240. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/snapshot.test.mjs +0 -0
  241. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/worktree.test.mjs +0 -0
  242. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/test/writer.test.mjs +0 -0
  243. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/testguard_cli/__init__.py +0 -0
  244. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/testguard_cli/wrapper.py +0 -0
  245. {testguard_cli-0.4.0 → testguard_cli-0.6.0}/vitest.config.mjs +0 -0
@@ -5,6 +5,7 @@
5
5
  * - pyproject.toml `version = "x.y.z"`
6
6
  * - action.yml default of the `version` input
7
7
  * - packaging/homebrew/*.rb the tarball URL (sha256 is set after publish)
8
+ * - packaging/gitlab/*.yml the include URL tag and the `version` input default
8
9
  *
9
10
  * `--check` verifies instead of writing (used by release.yml).
10
11
  */
@@ -21,6 +22,8 @@ const surfaces = [
21
22
  ['action.yml', /(\n version:\n description: [^\n]*\n required: false\n default: ')[^']*(')/, `$1${version}$2`],
22
23
  ['packaging/homebrew/testguard.rb', /testguard-cli-\d+\.\d+\.\d+\.tgz/g, `testguard-cli-${version}.tgz`],
23
24
  ['README.md', /raccioly\/testguard@v\d+\.\d+\.\d+/g, `raccioly/testguard@v${version}`],
25
+ ['packaging/gitlab/testguard.gitlab-ci.yml', /testguard\/v\d+\.\d+\.\d+\/packaging/g, `testguard/v${version}/packaging`],
26
+ ['packaging/gitlab/testguard.gitlab-ci.yml', /(\n version:\n description: [^\n]*\n default: ")\d+\.\d+\.\d+(")/, `$1${version}$2`],
24
27
  ];
25
28
 
26
29
  let drift = 0;
@@ -0,0 +1,260 @@
1
+ name: TestGuard CI
2
+
3
+ on:
4
+ workflow_dispatch: # manual recovery for pushes that don't auto-trigger (e.g. release PRs opened by GITHUB_TOKEN)
5
+ push:
6
+ branches: [main]
7
+ tags: ['v*'] # publish-check below runs on tags only
8
+ pull_request:
9
+ branches: [main]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ test:
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ matrix:
19
+ # 20 is the floor (node:util.parseArgs). 24 ships npm 11 — keep it so
20
+ # `npm ci` exercises the npm that treats some config as fatal where
21
+ # npm 10 is silent. Do not drop 24.
22
+ node-version: [20, 22, 24]
23
+
24
+ steps:
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26
+ with:
27
+ fetch-depth: 0 # probe builds a git worktree from HEAD; the self-probe below needs history
28
+
29
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
30
+ with:
31
+ node-version: ${{ matrix.node-version }}
32
+
33
+ - name: Install
34
+ run: npm ci
35
+
36
+ # ── Syntax-check EVERY source, not just what the entry point eagerly
37
+ # imports; a lazily loaded module's parse error would otherwise slip. ──
38
+ - name: Syntax-check all sources
39
+ run: find cli src spec -name '*.mjs' -print0 | xargs -0 -n1 node --check
40
+
41
+ # ── Install-from-tarball smoke: the package must run as INSTALLED, with
42
+ # production dependencies only. 0.1.0 shipped unrunnable because the
43
+ # schema validator's dependency was a devDependency; the suite, which
44
+ # runs from the checkout, could not see it. ──
45
+ - name: Install smoke (pack → install --omit=dev → run)
46
+ run: npm run test:install
47
+
48
+ - name: Python wrapper imports (PyPI surface)
49
+ run: python3 -c "import testguard_cli.wrapper; print('testguard_cli.wrapper OK')"
50
+
51
+ # ── Test suite with a RUNTIME BUDGET. A test that walks the wrong tree
52
+ # or probes far more than it should still passes — it just takes
53
+ # forever. Only a duration gate catches that class. Normal: ~15s
54
+ # locally, ~30–60s here. Budget is loose on purpose. ──
55
+ - name: Run tests (with runtime budget)
56
+ shell: bash
57
+ env:
58
+ TEST_BUDGET_MS: 240000
59
+ run: |
60
+ START=$(date +%s%3N)
61
+ npm test
62
+ DURATION=$(( $(date +%s%3N) - START ))
63
+ echo "Test suite duration: ${DURATION}ms (budget: ${TEST_BUDGET_MS}ms)"
64
+ if [ "$DURATION" -gt "$TEST_BUDGET_MS" ]; then
65
+ echo "::error::Test suite took ${DURATION}ms, over the ${TEST_BUDGET_MS}ms budget — something is probing far more than it should."
66
+ exit 1
67
+ fi
68
+
69
+ # ── Dogfood: the real binary against the known-answer fixture, as a
70
+ # user would run it (the suite drives main() in-process). ──
71
+ - name: CLI version
72
+ run: node cli/testguard.mjs --version
73
+
74
+ - name: claims — fixture lists cleanly, no drift
75
+ run: node cli/testguard.mjs claims fixtures/known-answer
76
+
77
+ - name: probe → baseline → probe → brief on the fixture (through the bin)
78
+ shell: bash
79
+ run: |
80
+ set -o pipefail
81
+ S=$(mktemp -d)
82
+ cp -R fixtures/known-answer/. "$S/"
83
+ rm -rf "$S/node_modules" "$S/.flake-counter" "$S/.testguard"
84
+ ln -s "$GITHUB_WORKSPACE/node_modules" "$S/node_modules"
85
+ git -C "$S" init -q
86
+ git -C "$S" -c user.email=ci@example.invalid -c user.name=ci add -A
87
+ git -C "$S" -c user.email=ci@example.invalid -c user.name=ci commit -qm fixture
88
+ B="$GITHUB_WORKSPACE/cli/testguard.mjs"
89
+ status=0; node "$B" probe "$S" --budget 60000 --quiet || status=$?
90
+ [ "$status" -eq 1 ] || { echo "::error::expected exit 1 (unproven claims), got $status"; exit 1; }
91
+ node "$B" baseline "$S"
92
+ status=0; node "$B" probe "$S" --budget 60000 --quiet || status=$?
93
+ [ "$status" -eq 0 ] || { echo "::error::expected exit 0 after baseline, got $status"; exit 1; }
94
+ node "$B" brief "$S" --text | head -12
95
+ # every verdict must appear exactly once per expected.json
96
+ node --input-type=module -e "
97
+ import { readFileSync } from 'node:fs';
98
+ const ev = JSON.parse(readFileSync('$S/.testguard/evidence.json','utf8'));
99
+ const exp = JSON.parse(readFileSync('fixtures/known-answer/expected.json','utf8')).expected;
100
+ const bad = ev.records.filter(r => exp[r.claim.id+'/'+r.subject.id].verdict !== r.verdict);
101
+ if (bad.length) { console.error('MISMATCH', bad.map(r => r.claim.id+'/'+r.subject.id+':'+r.verdict)); process.exit(1); }
102
+ console.log('fixture verdicts match expected.json:', ev.records.length);
103
+ "
104
+
105
+ - name: probe the jest fixture (through the bin, --runner jest)
106
+ shell: bash
107
+ run: |
108
+ S=$(mktemp -d)
109
+ cp -R fixtures/known-answer-jest/. "$S/"
110
+ rm -rf "$S/node_modules" "$S/.flake-counter" "$S/.testguard"
111
+ ln -s "$GITHUB_WORKSPACE/node_modules" "$S/node_modules"
112
+ git -C "$S" init -q && git -C "$S" -c user.email=ci@example.invalid -c user.name=ci add -A && git -C "$S" -c user.email=ci@example.invalid -c user.name=ci commit -qm fixture
113
+ status=0; node cli/testguard.mjs probe "$S" --runner jest --budget 60000 --quiet --no-escalate || status=$?
114
+ [ "$status" -eq 1 ] || { echo "::error::expected exit 1, got $status"; exit 1; }
115
+ node --input-type=module -e "
116
+ import { readFileSync } from 'node:fs';
117
+ const ev = JSON.parse(readFileSync('$S/.testguard/evidence.json','utf8'));
118
+ const exp = JSON.parse(readFileSync('fixtures/known-answer-jest/expected.json','utf8')).expected;
119
+ if (ev.run.runner.name !== 'jest') { console.error('runner was', ev.run.runner.name); process.exit(1); }
120
+ const bad = ev.records.filter(r => exp[r.claim.id+'/'+r.subject.id].verdict !== r.verdict);
121
+ if (bad.length) { console.error('MISMATCH', bad.map(r => r.claim.id+'/'+r.subject.id+':'+r.verdict)); process.exit(1); }
122
+ console.log('jest fixture verdicts match expected.json:', ev.records.length);
123
+ "
124
+
125
+ # ── The MCP server, driven as a client would: handshake, list, call.
126
+ # A harness-independent surface is only worth having if it actually
127
+ # speaks the protocol from a cold start. ──
128
+ - name: mcp — handshake, tools/list, tools/call over stdio
129
+ shell: bash
130
+ run: |
131
+ printf '%s\n' \
132
+ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
133
+ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
134
+ '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
135
+ '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"testguard_status","arguments":{"dir":"."}}}' \
136
+ | node cli/testguard.mjs mcp > "$RUNNER_TEMP/mcp.jsonl"
137
+ node --input-type=module -e "
138
+ import { readFileSync } from 'node:fs';
139
+ const msgs = readFileSync(process.env.RUNNER_TEMP + '/mcp.jsonl', 'utf8').trim().split('\n').map((l) => JSON.parse(l));
140
+ if (msgs.length !== 3) { console.error('expected 3 replies (the notification is never answered), got', msgs.length); process.exit(1); }
141
+ const [init, list, call] = msgs;
142
+ if (!init.result.protocolVersion) { console.error('no protocolVersion'); process.exit(1); }
143
+ if (list.result.tools.length !== 5) { console.error('expected 5 tools, got', list.result.tools.length); process.exit(1); }
144
+ if (!list.result.tools.every((t) => t.annotations.readOnlyHint)) { console.error('a tool is not marked read-only'); process.exit(1); }
145
+ if (call.result.isError) { console.error('status call failed:', call.result.content[0].text); process.exit(1); }
146
+ if (!call.result.structuredContent.next.action) { console.error('status carried no next action'); process.exit(1); }
147
+ console.log('mcp:', list.result.tools.map((t) => t.name).join(', '), '→ state', call.result.structuredContent.state);
148
+ "
149
+
150
+ # ── Every change needs a claim: the gate runs on this repository's own
151
+ # pull requests. A new source file without a claim (or an excusing
152
+ # ignore entry with a reason) turns the PR red. ──
153
+ # A claim that disappeared is invisible to every other check: `probe`
154
+ # verifies what is there, `gate` sees the file covered by another claim.
155
+ # Removal is allowed; it is never silent.
156
+ - name: claims — no claim or fault removed without a reason
157
+ if: github.event_name == 'pull_request'
158
+ run: node cli/testguard.mjs claims . --since "origin/${{ github.base_ref }}"
159
+
160
+ - name: gate — every changed source file carries a claim
161
+ if: github.event_name == 'pull_request'
162
+ run: node cli/testguard.mjs gate . --changed "origin/${{ github.base_ref }}"
163
+
164
+ # ── Self-verification: TestGuard is governed by the standard it defines.
165
+ # testguard.claims.json states invariants of the tool itself; every
166
+ # fault must be killed by the tool's own tests. Exit 0 = all defended. ──
167
+ # Runs on ONE Node leg: the verdicts do not depend on the Node minor,
168
+ # and each from-scratch probe is ~14 minutes. The previous run's
169
+ # evidence is restored from the cache so claims whose target and
170
+ # defenders did not change reuse their verdict (the tool's own
171
+ # reuse rule); only what changed is re-probed. No escalation in CI:
172
+ # a survivor here is a failure either way. ──
173
+ - name: Restore previous self-probe evidence (verdict reuse)
174
+ if: matrix.node-version == 22
175
+ uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
176
+ with:
177
+ path: .testguard/ci-self-evidence.json
178
+ key: self-evidence-${{ hashFiles('testguard.claims.json') }}-${{ github.sha }}
179
+ restore-keys: |
180
+ self-evidence-${{ hashFiles('testguard.claims.json') }}-
181
+ self-evidence-
182
+
183
+ - name: probe TestGuard's own claims
184
+ if: matrix.node-version == 22
185
+ run: node cli/testguard.mjs probe . --budget 180000 --no-escalate --out .testguard/ci-self-evidence.json
186
+
187
+ # A stable, branch-named artifact so a developer can fetch the evidence
188
+ # CI produced without knowing a run id (README: read CI's evidence
189
+ # locally). One Node leg is enough; the verdicts are identical.
190
+ - name: Upload evidence under a stable, branch-named artifact
191
+ if: always() && matrix.node-version == 22 && github.event_name == 'push'
192
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
193
+ with:
194
+ name: testguard-evidence-${{ github.ref_name }}
195
+ path: .testguard/ci-self-evidence.json
196
+ if-no-files-found: warn
197
+
198
+ - name: Upload self-probe evidence
199
+ if: always() && matrix.node-version == 22
200
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
201
+ with:
202
+ name: testguard-self-evidence
203
+ path: .testguard/ci-self-evidence.json
204
+ if-no-files-found: warn
205
+
206
+ # ── Playwright: the per-file runner is proven against its own browserless
207
+ # fixture, whose dependencies live in the fixture (never in the tool's
208
+ # package.json). Installed and run here only. ──
209
+ playwright:
210
+ runs-on: ubuntu-latest
211
+ steps:
212
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
213
+ with:
214
+ fetch-depth: 0
215
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
216
+ with:
217
+ node-version: 22
218
+ cache: npm
219
+ cache-dependency-path: |
220
+ package-lock.json
221
+ fixtures/known-answer-playwright/package-lock.json
222
+ - name: Install (tool + fixture)
223
+ run: |
224
+ npm ci
225
+ npm ci --prefix fixtures/known-answer-playwright
226
+ - name: Playwright adapter units + mixed-defender acceptance
227
+ run: npx vitest run test/runner-playwright.test.mjs test/probe.playwright.test.mjs
228
+ - name: probe the playwright fixture through the bin (mixed defenders, auto runner)
229
+ shell: bash
230
+ run: |
231
+ set -o pipefail
232
+ S=$(mktemp -d)
233
+ cp -R fixtures/known-answer-playwright/. "$S/"
234
+ rm -rf "$S/node_modules" "$S/.flake-counter" "$S/.testguard" "$S/test-results"
235
+ ln -s "$GITHUB_WORKSPACE/fixtures/known-answer-playwright/node_modules" "$S/node_modules"
236
+ git -C "$S" init -q && git -C "$S" -c user.email=ci@example.invalid -c user.name=ci add -A && git -C "$S" -c user.email=ci@example.invalid -c user.name=ci commit -qm fixture
237
+ status=0; node cli/testguard.mjs probe "$S" --budget 60000 --quiet --no-escalate || status=$?
238
+ [ "$status" -eq 1 ] || { echo "::error::expected exit 1, got $status"; exit 1; }
239
+ node --input-type=module -e "
240
+ import { readFileSync } from 'node:fs';
241
+ const ev = JSON.parse(readFileSync('$S/.testguard/evidence.json','utf8'));
242
+ const exp = JSON.parse(readFileSync('fixtures/known-answer-playwright/expected.json','utf8')).expected;
243
+ const names = (ev.run.runners ?? []).map(r => r.name).sort().join(',');
244
+ if (names !== 'playwright,vitest') { console.error('runners were', names); process.exit(1); }
245
+ const bad = ev.records.filter(r => exp[r.claim.id+'/'+r.subject.id].verdict !== r.verdict);
246
+ if (bad.length) { console.error('MISMATCH', bad.map(r => r.claim.id+'/'+r.subject.id+':'+r.verdict)); process.exit(1); }
247
+ console.log('playwright fixture verdicts match expected.json:', ev.records.length);
248
+ "
249
+
250
+ # ── npm publish dry-run on tags ──
251
+ publish-check:
252
+ runs-on: ubuntu-latest
253
+ if: startsWith(github.ref, 'refs/tags/v')
254
+ needs: test
255
+ steps:
256
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
257
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
258
+ with:
259
+ node-version: 24
260
+ - run: npm publish --dry-run
@@ -8,6 +8,8 @@ coverage/
8
8
  .testguard/evidence-provisional.json
9
9
  .testguard/evidence-partial.json
10
10
  .testguard/brief.json
11
+ .testguard/gate.json
12
+ .testguard/ci-self-evidence.json
11
13
  .testguard/scaffold-*.json
12
14
  # Local agent tooling — not part of the public project
13
15
  .wolf/
@@ -10,6 +10,7 @@
10
10
  # rev: v0.1.0
11
11
  # hooks:
12
12
  # - id: testguard-claims # fast: validates the claims file + drift
13
+ # - id: testguard-gate # fast: every changed source file must carry a claim
13
14
  # - id: testguard-probe # slow: pre-push stage, runs the faults
14
15
  #
15
16
  # # install the push-stage hook once per clone:
@@ -23,6 +24,14 @@
23
24
  pass_filenames: false
24
25
  always_run: true
25
26
 
27
+ - id: testguard-gate
28
+ name: TestGuard gate (every change needs a claim)
29
+ description: Fails when a source file in this commit carries no claim, does not defend one, and is not excused by testguard.ignore.json. Fast; runs no tests.
30
+ entry: testguard gate --changed HEAD --include-dirty --quiet
31
+ language: node
32
+ pass_filenames: false
33
+ always_run: true
34
+
26
35
  - id: testguard-probe
27
36
  name: TestGuard probe (pre-push)
28
37
  description: Injects every claim's faults and fails on any the tests miss. Gated by the committed baseline.
@@ -27,11 +27,13 @@ node cli/testguard.mjs scaffold src/probe/classify.mjs --json # what the produ
27
27
  - `spec/schemas/common.schema.json` — verdicts, fault classes, provenance. The closed sets.
28
28
  - `spec/lib/validate.mjs` — semantic rules (green baseline, N/N agreement, assertion-only kills, fingerprint derivation).
29
29
  - `src/probe/classify.mjs` — the verdict function. Pure. Its check order *is* `GATE-SEMANTICS.md`.
30
+ - `src/probe/mocks.mjs` — mock-awareness: which candidate tests mock the target (never defenders), and the `mocked-never-asserted` signal. `src/probe/rank.mjs` resolves aliases (tsconfig `paths` through `extends`/`references`, vite/vitest `resolve.alias`, package.json `imports`).
30
31
  - `src/probe/probe.mjs` — orchestrator: isolation → baseline (cached per defender set) → apply → probe → escalate → restore → classify → rank.
31
32
  - `fixtures/known-answer/expected.json` — the oracle. Never edit it to match output.
32
33
  - `testguard.claims.json` — claims about this codebase, probed in CI.
33
- - `src/scaffold/producers.mjs` — the five fault shapes. Deterministic line heuristics; no AST, no LLM. A new shape needs a synthetic-file test and a README row.
34
- - `src/probe/runners/` — one module per runner (`name`, `testGlobs`, `check`, `tests`, `run`) over `shared.mjs` (jest-compatible report parsing, budgeted process runner). A new runner needs its own fixture copy with the same `expected.json`.
34
+ - `src/scaffold/producers.mjs` — the nine fault shapes. Deterministic line heuristics; no AST, no LLM. A new shape needs a synthetic-file test and a README row.
35
+ - `src/probe/runners/` — one module per runner (`name`, `testGlobs`, `check`, `tests`, `run`, optionally `owns` for a per-file runner) over `shared.mjs` (jest-compatible report parsing, budgeted process runner, pluggable `parse`/`env`). `playwright.mjs` is a per-file runner: it owns the files under its `testDir`; `index.mjs` partitions defenders by runner and merges their runs pessimistically. A new runner needs its own fixture copy with its own `expected.json`, verified by hand.
36
+ - `src/gate/changed.mjs` — claim coverage of a change (`gate --changed`). File-level, delta-only; an uncovered file exits 1; every ignore reliance is reported. Its rules are a section of `GATE-SEMANTICS.md`.
35
37
  - `src/status/status.mjs` — the state machine every rendering derives from. A new state or action is a spec change (`status.schema.json`) and a skill-template change (`src/init/templates/SKILL.md`) in the same PR.
36
38
 
37
39
  ## Rules