jev-mcp-python 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (591) hide show
  1. jev_mcp_python-0.1.0/.github/workflows/ci.yml +98 -0
  2. jev_mcp_python-0.1.0/.github/workflows/release.yml +158 -0
  3. jev_mcp_python-0.1.0/.gitignore +23 -0
  4. jev_mcp_python-0.1.0/.python-version +1 -0
  5. jev_mcp_python-0.1.0/.release-please-manifest.json +3 -0
  6. jev_mcp_python-0.1.0/CHANGELOG.md +8 -0
  7. jev_mcp_python-0.1.0/CONTEXT.md +125 -0
  8. jev_mcp_python-0.1.0/CONTRIBUTING.md +82 -0
  9. jev_mcp_python-0.1.0/LICENSE +21 -0
  10. jev_mcp_python-0.1.0/Makefile +93 -0
  11. jev_mcp_python-0.1.0/PKG-INFO +18 -0
  12. jev_mcp_python-0.1.0/README.md +99 -0
  13. jev_mcp_python-0.1.0/ROADMAP.md +205 -0
  14. jev_mcp_python-0.1.0/docs/adr/0001-behavior-compatible-rewrite-against-frozen-ts-reference.md +11 -0
  15. jev_mcp_python-0.1.0/docs/adr/0002-model-judges-policy-decides.md +42 -0
  16. jev_mcp_python-0.1.0/docs/adr/0003-uniform-envelope-validation-across-providers.md +11 -0
  17. jev_mcp_python-0.1.0/docs/adr/0004-extract-regex-dialect-and-isolation.md +34 -0
  18. jev_mcp_python-0.1.0/docs/adr/0005-lengths-measured-in-utf16-code-units.md +12 -0
  19. jev_mcp_python-0.1.0/docs/adr/0006-js-compatible-result-serialization.md +14 -0
  20. jev_mcp_python-0.1.0/docs/adr/0007-vercel-provider-reserved-not-emulated.md +11 -0
  21. jev_mcp_python-0.1.0/docs/adr/0008-provider-endpoints-and-credentials-are-process-config-only.md +11 -0
  22. jev_mcp_python-0.1.0/docs/adr/0009-distribution-name-jev-mcp-python.md +11 -0
  23. jev_mcp_python-0.1.0/docs/adr/0010-python-312-and-mcp-sdk-v2.md +12 -0
  24. jev_mcp_python-0.1.0/docs/adr/0011-propagate-mcp-cancellation-to-providers.md +12 -0
  25. jev_mcp_python-0.1.0/docs/adr/0012-keep-reference-validation-quirks.md +22 -0
  26. jev_mcp_python-0.1.0/docs/adr/0013-one-registry-one-execution-kernel-ten-tool-definitions.md +63 -0
  27. jev_mcp_python-0.1.0/docs/adr/0014-cap-values-measurement-and-enforcement-are-separate.md +48 -0
  28. jev_mcp_python-0.1.0/docs/adr/0015-one-python-parity-fixture-loader.md +21 -0
  29. jev_mcp_python-0.1.0/docs/adr/0016-extract-dialect-translates-executors-execute.md +52 -0
  30. jev_mcp_python-0.1.0/docs/adr/0017-redaction-secret-set-derives-from-settings-schema.md +17 -0
  31. jev_mcp_python-0.1.0/docs/adr/0018-extract-runs-on-stdlib-re-with-a-narrower-subset.md +32 -0
  32. jev_mcp_python-0.1.0/docs/adr/0019-parsed-json-value-shape-primitives-live-in-domain.md +17 -0
  33. jev_mcp_python-0.1.0/docs/adr/0020-divergence-registry-single-source-of-truth.md +38 -0
  34. jev_mcp_python-0.1.0/docs/adr/0021-stdio-is-the-product-transport-http-is-tier-b.md +27 -0
  35. jev_mcp_python-0.1.0/docs/adr/0022-schemas-are-validated-faithful-at-construction.md +78 -0
  36. jev_mcp_python-0.1.0/docs/adr/0023-same-origin-redirects-only.md +35 -0
  37. jev_mcp_python-0.1.0/docs/adr/0024-record-non-fixture-divergences.md +46 -0
  38. jev_mcp_python-0.1.0/docs/adr/0025-extract-pool-saturation-has-its-own-reason.md +26 -0
  39. jev_mcp_python-0.1.0/docs/adr/0026-paid-eval-harness-shares-one-agent-run-one-relay-one-ledger.md +124 -0
  40. jev_mcp_python-0.1.0/docs/adr/0027-one-contract-test-guards-every-paid-path.md +53 -0
  41. jev_mcp_python-0.1.0/docs/adr/0028-scorers-expose-judgments-pinned-to-real-output.md +46 -0
  42. jev_mcp_python-0.1.0/docs/adr/0029-openrouter-referer-names-this-repo.md +16 -0
  43. jev_mcp_python-0.1.0/docs/architecture.html +15078 -0
  44. jev_mcp_python-0.1.0/docs/architecture.json +467 -0
  45. jev_mcp_python-0.1.0/docs/jev_docs/README.md +16 -0
  46. jev_mcp_python-0.1.0/docs/jev_docs/SOURCES.md +37 -0
  47. jev_mcp_python-0.1.0/docs/jev_docs/api.md +89 -0
  48. jev_mcp_python-0.1.0/docs/jev_docs/models.md +50 -0
  49. jev_mcp_python-0.1.0/docs/jev_docs/patterns.md +50 -0
  50. jev_mcp_python-0.1.0/docs/jev_docs/primitives.md +50 -0
  51. jev_mcp_python-0.1.0/docs/readme/badges.svg +14 -0
  52. jev_mcp_python-0.1.0/docs/readme/banner.svg +7 -0
  53. jev_mcp_python-0.1.0/docs/readme/bench-speed.svg +9 -0
  54. jev_mcp_python-0.1.0/docs/readme/bench-time.svg +9 -0
  55. jev_mcp_python-0.1.0/docs/reference/divergences.json +212 -0
  56. jev_mcp_python-0.1.0/docs/reference/parity-manifest.json +342 -0
  57. jev_mcp_python-0.1.0/docs/reference/ts-0.5.0-tools-list.json +699 -0
  58. jev_mcp_python-0.1.0/evals/README.md +162 -0
  59. jev_mcp_python-0.1.0/evals/__init__.py +1 -0
  60. jev_mcp_python-0.1.0/evals/ab/__init__.py +1 -0
  61. jev_mcp_python-0.1.0/evals/ab/arms.py +121 -0
  62. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/README.md +7 -0
  63. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/durations.py +11 -0
  64. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/pricing.py +20 -0
  65. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/__init__.py +0 -0
  66. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_durations.py +15 -0
  67. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_legacy.py +14 -0
  68. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_pricing.py +18 -0
  69. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_textutils.py +14 -0
  70. jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/textutils.py +13 -0
  71. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t1-bulk-boundary/acceptance_test.py +17 -0
  72. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t1-bulk-boundary/prompt.md +1 -0
  73. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t1-bulk-boundary/reference/pricing.py +20 -0
  74. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t2-slugify/acceptance_test.py +34 -0
  75. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t2-slugify/prompt.md +7 -0
  76. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t2-slugify/reference/textutils.py +25 -0
  77. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/acceptance_test.py +19 -0
  78. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/overlay/ISSUE.md +14 -0
  79. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/prompt.md +1 -0
  80. jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/reference/durations.py +16 -0
  81. jev_mcp_python-0.1.0/evals/ab/grade.py +118 -0
  82. jev_mcp_python-0.1.0/evals/ab/ledger.py +21 -0
  83. jev_mcp_python-0.1.0/evals/ab/pilot.py +338 -0
  84. jev_mcp_python-0.1.0/evals/ab/proxy.py +58 -0
  85. jev_mcp_python-0.1.0/evals/ab/report.py +159 -0
  86. jev_mcp_python-0.1.0/evals/ab/review_server.py +22 -0
  87. jev_mcp_python-0.1.0/evals/ab/stream.py +80 -0
  88. jev_mcp_python-0.1.0/evals/ab/tasks.py +68 -0
  89. jev_mcp_python-0.1.0/evals/ab/unsafe.py +57 -0
  90. jev_mcp_python-0.1.0/evals/agent.py +139 -0
  91. jev_mcp_python-0.1.0/evals/baselines/__init__.py +1 -0
  92. jev_mcp_python-0.1.0/evals/baselines/ranking.py +64 -0
  93. jev_mcp_python-0.1.0/evals/bench/__init__.py +1 -0
  94. jev_mcp_python-0.1.0/evals/bench/analysis.py +101 -0
  95. jev_mcp_python-0.1.0/evals/bench/answer.py +98 -0
  96. jev_mcp_python-0.1.0/evals/bench/chart.py +254 -0
  97. jev_mcp_python-0.1.0/evals/bench/gate.py +83 -0
  98. jev_mcp_python-0.1.0/evals/bench/items.py +113 -0
  99. jev_mcp_python-0.1.0/evals/bench/ledger.py +19 -0
  100. jev_mcp_python-0.1.0/evals/bench/pi.py +183 -0
  101. jev_mcp_python-0.1.0/evals/bench/prompt.py +163 -0
  102. jev_mcp_python-0.1.0/evals/bench/proxy.py +136 -0
  103. jev_mcp_python-0.1.0/evals/bench/run.py +355 -0
  104. jev_mcp_python-0.1.0/evals/bench/spans.py +80 -0
  105. jev_mcp_python-0.1.0/evals/bench/stats.py +27 -0
  106. jev_mcp_python-0.1.0/evals/calibration/__init__.py +1 -0
  107. jev_mcp_python-0.1.0/evals/calibration/bounds.py +68 -0
  108. jev_mcp_python-0.1.0/evals/calibration/flips.py +24 -0
  109. jev_mcp_python-0.1.0/evals/calibration/rows.py +24 -0
  110. jev_mcp_python-0.1.0/evals/calibration/split.py +31 -0
  111. jev_mcp_python-0.1.0/evals/calibration/targets.py +22 -0
  112. jev_mcp_python-0.1.0/evals/calibration/threshold.py +46 -0
  113. jev_mcp_python-0.1.0/evals/datasets/bench150/items.jsonl +150 -0
  114. jev_mcp_python-0.1.0/evals/datasets/synthetic/classify.jsonl +10 -0
  115. jev_mcp_python-0.1.0/evals/datasets/synthetic/classify.outputs.jsonl +10 -0
  116. jev_mcp_python-0.1.0/evals/datasets/synthetic/live-classify.jsonl +3 -0
  117. jev_mcp_python-0.1.0/evals/datasets/synthetic/live-verify.jsonl +3 -0
  118. jev_mcp_python-0.1.0/evals/manifests/live-classify.json +7 -0
  119. jev_mcp_python-0.1.0/evals/manifests/live-verify.json +7 -0
  120. jev_mcp_python-0.1.0/evals/manifests/synthetic-classify.json +7 -0
  121. jev_mcp_python-0.1.0/evals/relay.py +167 -0
  122. jev_mcp_python-0.1.0/evals/reports/.gitkeep +0 -0
  123. jev_mcp_python-0.1.0/evals/reports/bench150-sample.html +15 -0
  124. jev_mcp_python-0.1.0/evals/reports/bench150.html +15 -0
  125. jev_mcp_python-0.1.0/evals/reports/bench150.md +16 -0
  126. jev_mcp_python-0.1.0/evals/reports/p8-pilot.md +78 -0
  127. jev_mcp_python-0.1.0/evals/runners/__init__.py +1 -0
  128. jev_mcp_python-0.1.0/evals/runners/live.py +102 -0
  129. jev_mcp_python-0.1.0/evals/runners/manifest.py +95 -0
  130. jev_mcp_python-0.1.0/evals/runners/score.py +93 -0
  131. jev_mcp_python-0.1.0/evals/scorers/__init__.py +1 -0
  132. jev_mcp_python-0.1.0/evals/scorers/fields.py +31 -0
  133. jev_mcp_python-0.1.0/evals/scorers/metrics.py +171 -0
  134. jev_mcp_python-0.1.0/evals/scorers/tools.py +601 -0
  135. jev_mcp_python-0.1.0/evals/spend.py +89 -0
  136. jev_mcp_python-0.1.0/pyproject.toml +79 -0
  137. jev_mcp_python-0.1.0/release-please-config.json +20 -0
  138. jev_mcp_python-0.1.0/scripts/check_release_version.py +106 -0
  139. jev_mcp_python-0.1.0/src/jev_mcp/__init__.py +1 -0
  140. jev_mcp_python-0.1.0/src/jev_mcp/__main__.py +3 -0
  141. jev_mcp_python-0.1.0/src/jev_mcp/domain/__init__.py +32 -0
  142. jev_mcp_python-0.1.0/src/jev_mcp/domain/answers.py +25 -0
  143. jev_mcp_python-0.1.0/src/jev_mcp/domain/json.py +49 -0
  144. jev_mcp_python-0.1.0/src/jev_mcp/domain/questions.py +75 -0
  145. jev_mcp_python-0.1.0/src/jev_mcp/domain/usage.py +16 -0
  146. jev_mcp_python-0.1.0/src/jev_mcp/errors.py +59 -0
  147. jev_mcp_python-0.1.0/src/jev_mcp/extract/__init__.py +1 -0
  148. jev_mcp_python-0.1.0/src/jev_mcp/extract/candidates.py +75 -0
  149. jev_mcp_python-0.1.0/src/jev_mcp/extract/dialect.py +400 -0
  150. jev_mcp_python-0.1.0/src/jev_mcp/extract/executor.py +118 -0
  151. jev_mcp_python-0.1.0/src/jev_mcp/extract/worker.py +198 -0
  152. jev_mcp_python-0.1.0/src/jev_mcp/ids.py +49 -0
  153. jev_mcp_python-0.1.0/src/jev_mcp/limits.py +218 -0
  154. jev_mcp_python-0.1.0/src/jev_mcp/policy/__init__.py +98 -0
  155. jev_mcp_python-0.1.0/src/jev_mcp/policy/actions.py +41 -0
  156. jev_mcp_python-0.1.0/src/jev_mcp/policy/claims.py +103 -0
  157. jev_mcp_python-0.1.0/src/jev_mcp/policy/extract.py +73 -0
  158. jev_mcp_python-0.1.0/src/jev_mcp/policy/ranking.py +41 -0
  159. jev_mcp_python-0.1.0/src/jev_mcp/policy/review.py +73 -0
  160. jev_mcp_python-0.1.0/src/jev_mcp/policy/screen.py +48 -0
  161. jev_mcp_python-0.1.0/src/jev_mcp/policy/thresholds.py +74 -0
  162. jev_mcp_python-0.1.0/src/jev_mcp/providers/__init__.py +26 -0
  163. jev_mcp_python-0.1.0/src/jev_mcp/providers/base.py +236 -0
  164. jev_mcp_python-0.1.0/src/jev_mcp/providers/cloudflare.py +59 -0
  165. jev_mcp_python-0.1.0/src/jev_mcp/providers/compatible.py +43 -0
  166. jev_mcp_python-0.1.0/src/jev_mcp/providers/openrouter.py +47 -0
  167. jev_mcp_python-0.1.0/src/jev_mcp/providers/resolver.py +106 -0
  168. jev_mcp_python-0.1.0/src/jev_mcp/providers/typesafe.py +127 -0
  169. jev_mcp_python-0.1.0/src/jev_mcp/py.typed +0 -0
  170. jev_mcp_python-0.1.0/src/jev_mcp/serialize.py +199 -0
  171. jev_mcp_python-0.1.0/src/jev_mcp/server.py +176 -0
  172. jev_mcp_python-0.1.0/src/jev_mcp/settings.py +73 -0
  173. jev_mcp_python-0.1.0/src/jev_mcp/stdio.py +99 -0
  174. jev_mcp_python-0.1.0/src/jev_mcp/telemetry.py +223 -0
  175. jev_mcp_python-0.1.0/src/jev_mcp/text.py +42 -0
  176. jev_mcp_python-0.1.0/src/jev_mcp/tools/__init__.py +20 -0
  177. jev_mcp_python-0.1.0/src/jev_mcp/tools/arguments.py +447 -0
  178. jev_mcp_python-0.1.0/src/jev_mcp/tools/base.py +153 -0
  179. jev_mcp_python-0.1.0/src/jev_mcp/tools/classify.py +187 -0
  180. jev_mcp_python-0.1.0/src/jev_mcp/tools/common.py +96 -0
  181. jev_mcp_python-0.1.0/src/jev_mcp/tools/compare.py +143 -0
  182. jev_mcp_python-0.1.0/src/jev_mcp/tools/decide.py +206 -0
  183. jev_mcp_python-0.1.0/src/jev_mcp/tools/extract.py +262 -0
  184. jev_mcp_python-0.1.0/src/jev_mcp/tools/find.py +113 -0
  185. jev_mcp_python-0.1.0/src/jev_mcp/tools/gate.py +236 -0
  186. jev_mcp_python-0.1.0/src/jev_mcp/tools/observed.py +69 -0
  187. jev_mcp_python-0.1.0/src/jev_mcp/tools/rerank.py +139 -0
  188. jev_mcp_python-0.1.0/src/jev_mcp/tools/review.py +236 -0
  189. jev_mcp_python-0.1.0/src/jev_mcp/tools/screen.py +126 -0
  190. jev_mcp_python-0.1.0/src/jev_mcp/tools/toolset.py +92 -0
  191. jev_mcp_python-0.1.0/src/jev_mcp/tools/verify.py +141 -0
  192. jev_mcp_python-0.1.0/src/jev_mcp/validation/__init__.py +25 -0
  193. jev_mcp_python-0.1.0/src/jev_mcp/validation/caps.py +93 -0
  194. jev_mcp_python-0.1.0/src/jev_mcp/validation/choice.py +65 -0
  195. jev_mcp_python-0.1.0/src/jev_mcp/validation/extract.py +48 -0
  196. jev_mcp_python-0.1.0/src/jev_mcp/validation/noul.py +15 -0
  197. jev_mcp_python-0.1.0/src/jev_mcp/validation/numbers.py +21 -0
  198. jev_mcp_python-0.1.0/src/jev_mcp/validation/score.py +20 -0
  199. jev_mcp_python-0.1.0/tasks/p1-foundation-notes.md +14 -0
  200. jev_mcp_python-0.1.0/tasks/p5-tools-notes.md +14 -0
  201. jev_mcp_python-0.1.0/tasks/p6-security-notes.md +67 -0
  202. jev_mcp_python-0.1.0/tasks/p9-observe-notes.md +93 -0
  203. jev_mcp_python-0.1.0/tests/__init__.py +0 -0
  204. jev_mcp_python-0.1.0/tests/contract/__init__.py +0 -0
  205. jev_mcp_python-0.1.0/tests/contract/test_divergence_registry.py +64 -0
  206. jev_mcp_python-0.1.0/tests/contract/test_extract.py +241 -0
  207. jev_mcp_python-0.1.0/tests/contract/test_fail_closed.py +329 -0
  208. jev_mcp_python-0.1.0/tests/contract/test_limits.py +163 -0
  209. jev_mcp_python-0.1.0/tests/contract/test_paid_gates.py +169 -0
  210. jev_mcp_python-0.1.0/tests/contract/test_providers.py +578 -0
  211. jev_mcp_python-0.1.0/tests/contract/test_regex_executor.py +85 -0
  212. jev_mcp_python-0.1.0/tests/contract/test_tools_list.py +136 -0
  213. jev_mcp_python-0.1.0/tests/evals/__init__.py +0 -0
  214. jev_mcp_python-0.1.0/tests/evals/data/bench-dryrun.jsonl +2 -0
  215. jev_mcp_python-0.1.0/tests/evals/data/claude-stream-json-sample.jsonl +12 -0
  216. jev_mcp_python-0.1.0/tests/evals/test_ab_harness.py +356 -0
  217. jev_mcp_python-0.1.0/tests/evals/test_agent.py +288 -0
  218. jev_mcp_python-0.1.0/tests/evals/test_bench.py +597 -0
  219. jev_mcp_python-0.1.0/tests/evals/test_bench_dryrun.py +270 -0
  220. jev_mcp_python-0.1.0/tests/evals/test_bench_pi.py +178 -0
  221. jev_mcp_python-0.1.0/tests/evals/test_calibration.py +145 -0
  222. jev_mcp_python-0.1.0/tests/evals/test_live_typesafe.py +50 -0
  223. jev_mcp_python-0.1.0/tests/evals/test_metrics.py +119 -0
  224. jev_mcp_python-0.1.0/tests/evals/test_real_output.py +181 -0
  225. jev_mcp_python-0.1.0/tests/evals/test_relay.py +221 -0
  226. jev_mcp_python-0.1.0/tests/evals/test_runners.py +145 -0
  227. jev_mcp_python-0.1.0/tests/evals/test_scorer_contract.py +192 -0
  228. jev_mcp_python-0.1.0/tests/evals/test_tool_scorers.py +221 -0
  229. jev_mcp_python-0.1.0/tests/integration/__init__.py +0 -0
  230. jev_mcp_python-0.1.0/tests/integration/test_http.py +71 -0
  231. jev_mcp_python-0.1.0/tests/integration/test_stdio.py +94 -0
  232. jev_mcp_python-0.1.0/tests/integration/test_tools_stdio.py +134 -0
  233. jev_mcp_python-0.1.0/tests/integration/test_uvx_smoke.py +20 -0
  234. jev_mcp_python-0.1.0/tests/load/__init__.py +0 -0
  235. jev_mcp_python-0.1.0/tests/load/test_overhead.py +128 -0
  236. jev_mcp_python-0.1.0/tests/parity/README.md +72 -0
  237. jev_mcp_python-0.1.0/tests/parity/__init__.py +0 -0
  238. jev_mcp_python-0.1.0/tests/parity/cases/_helpers.mjs +53 -0
  239. jev_mcp_python-0.1.0/tests/parity/cases/boundary.mjs +265 -0
  240. jev_mcp_python-0.1.0/tests/parity/cases/extract.mjs +112 -0
  241. jev_mcp_python-0.1.0/tests/parity/cases/judgments.mjs +304 -0
  242. jev_mcp_python-0.1.0/tests/parity/cases/malformed.mjs +175 -0
  243. jev_mcp_python-0.1.0/tests/parity/cases/normal.mjs +193 -0
  244. jev_mcp_python-0.1.0/tests/parity/cases/provider.mjs +98 -0
  245. jev_mcp_python-0.1.0/tests/parity/cases/text.mjs +268 -0
  246. jev_mcp_python-0.1.0/tests/parity/cases/truncated.mjs +70 -0
  247. jev_mcp_python-0.1.0/tests/parity/divergences.py +124 -0
  248. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/classify-at-thresholds-js-number-format.json +124 -0
  249. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/classify-items-x-classes-over-budget.json +797 -0
  250. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/compare-aspect-count-over-cap.json +48 -0
  251. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/compare-margin-single-key-choice.json +67 -0
  252. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/compare-out-of-range-confidence-is-null.json +67 -0
  253. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/decide-candidate-id-pattern-rejected.json +46 -0
  254. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-aggregate-preview-over-budget.json +46 -0
  255. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-candidate-at-2000-kept-2001-skipped.json +77 -0
  256. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-flags-normalized.json +79 -0
  257. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-only-overlong-matches.json +40 -0
  258. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/find-exists-at-absent-floor.json +91 -0
  259. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/find-exists-at-found-tiny-probabilities.json +108 -0
  260. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/gate-threshold-default-review-at-follows-auto-accept.json +125 -0
  261. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/rerank-aggregate-over-budget.json +240 -0
  262. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/review-composite-at-floor.json +102 -0
  263. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/review-fractional-scores-clamped-composite.json +103 -0
  264. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/review-threshold-invariant-violated.json +38 -0
  265. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-injection-at-block-at.json +70 -0
  266. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-injection-at-custom-review-at.json +72 -0
  267. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-substance-at-skip-floor-relevance-below.json +80 -0
  268. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-tofixed-half-rounds-up.json +71 -0
  269. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/verify-confidence-at-auto-accept.json +91 -0
  270. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/compare-contradicts-auto.json +66 -0
  271. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/decide-requirements-contradicted-plural.json +150 -0
  272. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/decide-single-requirement-contradicted.json +112 -0
  273. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/gate-contradicted-below-auto-accept.json +149 -0
  274. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/verify-contradicted-auto.json +91 -0
  275. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/classify-duplicate-class-id.json +48 -0
  276. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/classify-duplicate-item-id.json +52 -0
  277. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/classify-omitted-ids-get-positional-fallbacks.json +109 -0
  278. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/decide-candidate-collides-with-escape-hatch.json +45 -0
  279. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/decide-duplicate-candidate-id.json +45 -0
  280. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/decide-hatch-name-allowed-without-hatches.json +87 -0
  281. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/extract-duplicate-field-id.json +45 -0
  282. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/find-ids-sanitized-and-suffixed.json +108 -0
  283. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/rerank-duplicate-id.json +43 -0
  284. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/rerank-fallback-avoids-supplied-ids.json +90 -0
  285. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/verify-duplicate-evidence-ids-suffixed.json +107 -0
  286. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-multiline-flag.json +81 -0
  287. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-named-group.json +80 -0
  288. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-syntax-error.json +85 -0
  289. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-unicode-flag.json +81 -0
  290. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-unknown-flag.json +42 -0
  291. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-variable-lookbehind.json +80 -0
  292. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/classify-low-margin.json +93 -0
  293. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/compare-below-auto-accept.json +68 -0
  294. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/extract-none-matched-ambiguous.json +77 -0
  295. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/extract-none-matched-confident.json +78 -0
  296. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/gate-claim-confidence-tiers.json +149 -0
  297. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/review-min-confidence-below-review-at.json +102 -0
  298. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/review-safe-to-apply-review-tier.json +102 -0
  299. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/screen-injection-review-tier.json +70 -0
  300. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/verify-low-and-null-confidence.json +91 -0
  301. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/classify-extra-probability-key.json +111 -0
  302. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/compare-invalid-overall-and-aspect.json +92 -0
  303. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/decide-invalid-check-kept-silent.json +133 -0
  304. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/decide-invalid-recommendation.json +133 -0
  305. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-body-array.json +71 -0
  306. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-body-not-json.json +78 -0
  307. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-usage-infinite.json +72 -0
  308. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-usage-null-model-absent.json +71 -0
  309. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/extract-choice-not-argmax.json +77 -0
  310. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/extract-sum-0-99-rejected.json +78 -0
  311. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/gate-rubric-confidence-out-of-range.json +125 -0
  312. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/rerank-missing-noul.json +88 -0
  313. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/rerank-out-of-range-noul.json +79 -0
  314. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/verify-claim-choice-inherited-key.json +77 -0
  315. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/classify-batch-with-context.json +164 -0
  316. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/compare-with-aspects.json +92 -0
  317. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/decide-with-requirements.json +159 -0
  318. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/extract-two-fields.json +97 -0
  319. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/find-ranked-top-k.json +99 -0
  320. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/gate-accepted.json +148 -0
  321. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/rerank-top-k.json +104 -0
  322. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/review-auto-env-model.json +104 -0
  323. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/screen-with-purpose-pass.json +79 -0
  324. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/verify-multi-evidence-model-override.json +123 -0
  325. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-200-control.json +77 -0
  326. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-401-after-regex.json +78 -0
  327. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-429-echoes-key-redacted.json +95 -0
  328. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-500-text.json +78 -0
  329. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-502-empty-body.json +124 -0
  330. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-503-body-sliced-at-200.json +71 -0
  331. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/regex-timeout/extract-catastrophic-then-valid-field.json +83 -0
  332. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/regex-timeout/extract-only-field-times-out.json +39 -0
  333. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-cloudflare-token-without-account.json +34 -0
  334. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-compatible-key-without-url.json +34 -0
  335. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-no-credentials.json +32 -0
  336. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-openrouter-key-not-sk-or.json +34 -0
  337. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-unknown-provider-name.json +35 -0
  338. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-cloudflare-account-without-token.json +35 -0
  339. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-cloudflare-unset.json +34 -0
  340. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-both-unset.json +34 -0
  341. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-key-unset.json +35 -0
  342. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-other-tool.json +32 -0
  343. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-url-unset.json +35 -0
  344. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-openrouter-not-sk-or.json +35 -0
  345. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-openrouter-unset.json +34 -0
  346. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-typesafe-unset.json +34 -0
  347. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-typesafe-uppercase-unset.json +35 -0
  348. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-vercel-unset.json +37 -0
  349. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/extract-zero-match-never-resolves.json +36 -0
  350. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/compare-margin-zero.json +66 -0
  351. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/decide-candidate-tied-with-escape-hatch.json +89 -0
  352. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/extract-tie-picks-second.json +77 -0
  353. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/find-tie-keeps-caller-order.json +99 -0
  354. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/rerank-equal-scores-stable.json +103 -0
  355. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/classify-item-and-class-text-over-cap.json +93 -0
  356. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/find-candidate-text-over-cap.json +90 -0
  357. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/gate-claim-over-cap.json +125 -0
  358. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/gate-evidence-item-over-cap.json +137 -0
  359. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/review-request-exactly-at-cap.json +103 -0
  360. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/review-tests-over-cap.json +102 -0
  361. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/classify-astral-ids-preserved.json +93 -0
  362. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/compare-aspect-200-units-astral.json +81 -0
  363. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/compare-aspect-201-units-astral-rejected.json +38 -0
  364. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/extract-dot-matches-single-units.json +80 -0
  365. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/extract-quantifier-counts-units.json +78 -0
  366. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/extract-whitespace-class.json +78 -0
  367. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/find-truncation-splits-surrogate-pair.json +92 -0
  368. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/gate-claim-truncation-splits-surrogate.json +127 -0
  369. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/screen-purpose-quoted-in-instruction.json +79 -0
  370. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/verify-astral-rtl-combining-text.json +106 -0
  371. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/decide-escape-none.json +89 -0
  372. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/find-exists-absent.json +89 -0
  373. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/gate-unsupported-confident.json +148 -0
  374. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/verify-says-nothing-source-none.json +99 -0
  375. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/zero-match/extract-no-matches-no-provider-call.json +40 -0
  376. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/zero-match/extract-one-field-matches.json +83 -0
  377. jev_mcp_python-0.1.0/tests/parity/fixtures/classes/zero-match/extract-zero-length-matches-dropped.json +40 -0
  378. jev_mcp_python-0.1.0/tests/parity/fixtures/index.json +3730 -0
  379. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/001-compatible-provider-sends-the-standard-request-to-the-configured-endpoint.json +80 -0
  380. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/002-compatible-provider-parses-verdicts-and-reports-the-endpoint-usage-and-default-m.json +79 -0
  381. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/003-compatible-provider-auto-selects-when-it-is-the-only-configured-provider.json +81 -0
  382. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/004-compatible-provider-rejects-a-malformed-response.json +80 -0
  383. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/005-compatible-provider-reports-non-2xx-status-with-the-body-redacted.json +80 -0
  384. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/006-compatible-provider-rejects-a-non-object-answers-envelope-and-fails-closed-on-an.json +145 -0
  385. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/007-compatible-provider-fails-closed-in-the-tool-when-an-answer-is-missing.json +72 -0
  386. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/008-compatible-provider-fails-closed-in-the-tools-for-answers-malformed-per-question.json +318 -0
  387. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/009-compatible-provider-rejects-malformed-or-incomplete-usage.json +278 -0
  388. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/010-compatible-provider-tolerates-an-absent-usage-block-and-reports-zeros.json +79 -0
  389. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/011-compatible-provider-reports-missing-configuration-before-making-a-request.json +38 -0
  390. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/012-compatible-provider-names-jev-api-base-url-alone-when-only-it-is-missing.json +38 -0
  391. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/013-jev-classify-preserves-valid-argmax-outputs-and-auto-review-decisions.json +123 -0
  392. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/014-jev-classify-rejects-a-choice-that-is-not-the-argmax.json +104 -0
  393. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/015-jev-classify-accepts-either-tied-maximum.json +123 -0
  394. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/016-jev-classify-handles-invalid-and-valid-items-independently.json +123 -0
  395. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/017-jev-classify-applies-the-1e-9-argmax-tolerance.json +123 -0
  396. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/018-jev-extract-sends-only-eligible-matches-when-overlong-ones-would-fill-the-cap.json +78 -0
  397. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/019-jev-extract-turns-a-confident-none-of-them-from-a-truncated-universe-into-review.json +97 -0
  398. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/020-jev-extract-keeps-a-positive-pick-from-a-truncated-universe-provisional-not-auto.json +97 -0
  399. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/021-jev-decide-recommendation-that-is-not-the-argmax-is-invalid-response.json +114 -0
  400. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/022-jev-decide-requirement-check-that-is-not-the-argmax-is-invalid-response.json +114 -0
  401. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/023-jev-decide-normalizes-non-finite-confidence-to-null-without-discarding-the-pick.json +114 -0
  402. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/024-jev-decide-accepts-a-candidate-id-named-constructor.json +114 -0
  403. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/025-jev-review-returns-auto-on-a-strong-patch-and-sends-anti-injection-framing.json +104 -0
  404. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/026-jev-review-demotes-auto-when-the-diff-is-truncated-at-the-document-cap.json +104 -0
  405. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/027-jev-review-escalates-with-invalid-response-when-a-score-answer-is-malformed.json +104 -0
  406. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/028-jev-review-respects-composite-floor-as-a-parameter.json +105 -0
  407. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/029-jev-gate-accepts-only-when-review-passes-and-every-claim-verifies.json +131 -0
  408. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/030-jev-gate-escalates-on-a-confidently-contradicted-claim.json +131 -0
  409. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/031-jev-gate-marks-invalid-claim-answers-as-invalid-response-and-escalates.json +131 -0
  410. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/032-jev-gate-rejects-evidence-with-no-non-empty-text-before-calling-jev.json +46 -0
  411. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/033-jev-review-escalates-on-unknown-rubric-confidence-even-at-zero-thresholds.json +107 -0
  412. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/034-jev-gate-escalates-on-unknown-claim-confidence-even-at-zero-thresholds.json +134 -0
  413. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/035-jev-review-escalates-with-invalid-response-when-safe-to-apply-is-malformed.json +104 -0
  414. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/036-jev-review-treats-an-out-of-range-score-as-invalid-response.json +104 -0
  415. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/037-jev-gate-rejects-claim-answers-whose-probabilities-do-not-sum-to-one.json +131 -0
  416. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/038-jev-gate-rejects-claim-answers-with-out-of-range-or-non-argmax-probabilities.json +365 -0
  417. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/039-jev-gate-demotes-auto-to-review-and-records-incomplete-context-when-the-diff-is.json +131 -0
  418. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/040-jev-gate-requires-review-for-an-unsupported-claim-and-flags-below-auto-confidenc.json +142 -0
  419. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/041-jev-gate-rejects-evidence-over-the-item-cap-before-calling-jev.json +110 -0
  420. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/042-jev-gate-rejects-evidence-over-the-aggregate-character-budget-before-calling-jev.json +62 -0
  421. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/043-jev-gate-makes-one-request-keeps-injected-directives-in-state-and-frames-every-q.json +142 -0
  422. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/044-jev-screen-invalid-response-when-answers-are-missing-instead-of-defaulting-to-pa.json +81 -0
  423. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/045-jev-screen-still-passes-on-complete-benign-answers.json +83 -0
  424. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/046-jev-find-invalid-response-when-exists-or-best-answers-are-missing.json +91 -0
  425. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/047-jev-find-still-ranks-candidates-on-complete-answers.json +93 -0
  426. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/048-jev-verify-marks-a-claim-invalid-response-when-the-relation-answer-is-missing.json +79 -0
  427. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/049-jev-verify-still-returns-verified-verdicts-on-a-complete-response.json +81 -0
  428. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/050-jev-screen-rejects-injection-undefined-with-purpose-undefined.json +72 -0
  429. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/051-jev-screen-rejects-injection-null-with-purpose-undefined.json +72 -0
  430. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/052-jev-screen-rejects-injection-0-1-with-purpose-undefined.json +72 -0
  431. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/053-jev-screen-rejects-injection-0-1-with-purpose-undefined.json +72 -0
  432. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/054-jev-screen-rejects-injection-1-1-with-purpose-undefined.json +72 -0
  433. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/055-jev-screen-rejects-injection-true-with-purpose-undefined.json +72 -0
  434. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/056-jev-screen-rejects-substance-undefined-with-purpose-undefined.json +72 -0
  435. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/057-jev-screen-rejects-substance-null-with-purpose-undefined.json +72 -0
  436. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/058-jev-screen-rejects-substance-0-1-with-purpose-undefined.json +72 -0
  437. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/059-jev-screen-rejects-substance-0-1-with-purpose-undefined.json +72 -0
  438. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/060-jev-screen-rejects-substance-1-1-with-purpose-undefined.json +72 -0
  439. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/061-jev-screen-rejects-substance-true-with-purpose-undefined.json +72 -0
  440. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/062-jev-screen-rejects-injection-undefined-with-purpose-check-the-homepage-for-error.json +81 -0
  441. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/063-jev-screen-rejects-injection-null-with-purpose-check-the-homepage-for-errors.json +81 -0
  442. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/064-jev-screen-rejects-injection-0-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  443. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/065-jev-screen-rejects-injection-0-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  444. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/066-jev-screen-rejects-injection-1-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  445. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/067-jev-screen-rejects-injection-true-with-purpose-check-the-homepage-for-errors.json +81 -0
  446. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/068-jev-screen-rejects-substance-undefined-with-purpose-check-the-homepage-for-error.json +81 -0
  447. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/069-jev-screen-rejects-substance-null-with-purpose-check-the-homepage-for-errors.json +81 -0
  448. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/070-jev-screen-rejects-substance-0-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  449. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/071-jev-screen-rejects-substance-0-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  450. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/072-jev-screen-rejects-substance-1-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  451. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/073-jev-screen-rejects-substance-true-with-purpose-check-the-homepage-for-errors.json +81 -0
  452. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/074-jev-screen-rejects-relevance-undefined-with-purpose-check-the-homepage-for-error.json +81 -0
  453. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/075-jev-screen-rejects-relevance-null-with-purpose-check-the-homepage-for-errors.json +81 -0
  454. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/076-jev-screen-rejects-relevance-0-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  455. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/077-jev-screen-rejects-relevance-0-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  456. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/078-jev-screen-rejects-relevance-1-1-with-purpose-check-the-homepage-for-errors.json +81 -0
  457. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/079-jev-screen-rejects-relevance-true-with-purpose-check-the-homepage-for-errors.json +81 -0
  458. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/080-jev-screen-accepts-zero-probabilities-and-does-not-require-unrequested-relevance.json +332 -0
  459. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/081-jev-find-rejects-malformed-best-case-0.json +91 -0
  460. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/082-jev-find-rejects-malformed-best-case-1.json +91 -0
  461. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/083-jev-find-rejects-malformed-best-case-2.json +91 -0
  462. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/084-jev-find-rejects-malformed-best-case-3.json +91 -0
  463. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/085-jev-find-rejects-malformed-best-case-4.json +91 -0
  464. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/086-jev-find-rejects-malformed-best-case-5.json +91 -0
  465. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/087-jev-find-rejects-malformed-best-case-6.json +91 -0
  466. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/088-jev-find-rejects-malformed-best-case-7.json +91 -0
  467. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/089-jev-find-rejects-malformed-best-case-8.json +91 -0
  468. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/090-jev-find-rejects-malformed-best-case-9.json +91 -0
  469. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/091-jev-find-rejects-malformed-best-case-10.json +91 -0
  470. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/092-jev-find-rejects-malformed-best-case-11.json +91 -0
  471. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/093-jev-find-rejects-malformed-best-case-12.json +91 -0
  472. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/094-jev-find-rejects-malformed-best-case-13.json +91 -0
  473. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/095-jev-find-rejects-malformed-best-case-14.json +91 -0
  474. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/096-jev-find-rejects-malformed-best-case-15.json +91 -0
  475. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/097-jev-find-rejects-malformed-best-case-16.json +91 -0
  476. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/098-jev-find-rejects-malformed-best-case-17.json +91 -0
  477. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/099-jev-find-rejects-malformed-best-case-18.json +91 -0
  478. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/100-jev-find-rejects-malformed-best-case-19.json +91 -0
  479. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/101-jev-find-rejects-malformed-best-case-20.json +91 -0
  480. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/102-jev-find-rejects-exists-undefined.json +91 -0
  481. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/103-jev-find-rejects-exists-null.json +91 -0
  482. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/104-jev-find-rejects-exists-0.json +91 -0
  483. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/105-jev-find-rejects-exists-1.json +91 -0
  484. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/106-jev-find-rejects-exists-2.json +91 -0
  485. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/107-jev-find-rejects-exists-false.json +91 -0
  486. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/108-jev-find-accepts-exists-0-as-absent-and-tied-maximum-choices.json +91 -0
  487. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/109-jev-verify-rejects-malformed-relation-case-0-without-affecting-other-claims.json +93 -0
  488. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/110-jev-verify-rejects-malformed-relation-case-1-without-affecting-other-claims.json +93 -0
  489. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/111-jev-verify-rejects-malformed-relation-case-2-without-affecting-other-claims.json +93 -0
  490. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/112-jev-verify-rejects-malformed-relation-case-3-without-affecting-other-claims.json +93 -0
  491. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/113-jev-verify-rejects-malformed-relation-case-4-without-affecting-other-claims.json +93 -0
  492. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/114-jev-verify-rejects-malformed-relation-case-5-without-affecting-other-claims.json +93 -0
  493. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/115-jev-verify-rejects-malformed-relation-case-6-without-affecting-other-claims.json +93 -0
  494. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/116-jev-verify-rejects-malformed-relation-case-7-without-affecting-other-claims.json +93 -0
  495. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/117-jev-verify-rejects-malformed-relation-case-8-without-affecting-other-claims.json +93 -0
  496. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/118-jev-verify-rejects-malformed-relation-case-9-without-affecting-other-claims.json +93 -0
  497. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/119-jev-verify-rejects-malformed-relation-case-10-without-affecting-other-claims.json +93 -0
  498. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/120-jev-verify-rejects-malformed-relation-case-11-without-affecting-other-claims.json +93 -0
  499. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/121-jev-verify-rejects-malformed-relation-case-12-without-affecting-other-claims.json +93 -0
  500. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/122-jev-verify-rejects-malformed-relation-case-13-without-affecting-other-claims.json +93 -0
  501. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/123-jev-verify-rejects-malformed-relation-case-14-without-affecting-other-claims.json +93 -0
  502. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/124-jev-verify-rejects-malformed-relation-case-15-without-affecting-other-claims.json +93 -0
  503. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/125-jev-verify-rejects-malformed-relation-case-16-without-affecting-other-claims.json +93 -0
  504. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/126-jev-verify-rejects-malformed-relation-case-17-without-affecting-other-claims.json +93 -0
  505. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/127-jev-verify-rejects-malformed-relation-case-18-without-affecting-other-claims.json +93 -0
  506. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/128-jev-verify-rejects-malformed-relation-case-19-without-affecting-other-claims.json +93 -0
  507. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/129-jev-verify-rejects-malformed-relation-case-20-without-affecting-other-claims.json +93 -0
  508. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/130-jev-verify-rejects-malformed-relation-case-21-without-affecting-other-claims.json +93 -0
  509. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/131-jev-verify-rejects-malformed-relation-case-22-without-affecting-other-claims.json +93 -0
  510. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/132-jev-verify-rejects-malformed-relation-case-23-without-affecting-other-claims.json +93 -0
  511. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/133-jev-verify-rejects-malformed-relation-case-24-without-affecting-other-claims.json +93 -0
  512. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/134-jev-verify-rejects-malformed-relation-case-25-without-affecting-other-claims.json +93 -0
  513. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/135-jev-verify-rejects-malformed-relation-case-26-without-affecting-other-claims.json +93 -0
  514. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/136-jev-verify-rejects-malformed-relation-case-27-without-affecting-other-claims.json +93 -0
  515. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/137-jev-verify-rejects-malformed-relation-case-28-without-affecting-other-claims.json +93 -0
  516. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/138-jev-verify-rejects-malformed-relation-case-29-without-affecting-other-claims.json +93 -0
  517. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/139-jev-verify-rejects-malformed-relation-case-30-without-affecting-other-claims.json +93 -0
  518. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/140-jev-verify-rejects-malformed-relation-case-31-without-affecting-other-claims.json +93 -0
  519. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/141-jev-verify-preserves-valid-relation-with-confidence-undefined.json +146 -0
  520. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/142-jev-verify-preserves-valid-relation-with-confidence-null.json +146 -0
  521. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/143-jev-verify-preserves-valid-relation-with-confidence-0.json +146 -0
  522. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/144-jev-verify-accepts-tied-argmax-and-optional-missing-source-answers-for-multiple.json +101 -0
  523. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/145-all-three-tools-fail-closed-for-answers-undefined.json +233 -0
  524. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/146-all-three-tools-fail-closed-for-answers-null.json +233 -0
  525. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/147-all-three-tools-fail-closed-for-answers.json +233 -0
  526. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/148-all-three-tools-fail-closed-for-answers-bad.json +233 -0
  527. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/149-all-three-tools-fail-closed-for-answers-0.json +233 -0
  528. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/150-all-three-tools-fail-closed-for-answers-true.json +233 -0
  529. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/151-jev-verify-validates-source-answers-against-supplied-evidence-ids.json +1058 -0
  530. jev_mcp_python-0.1.0/tests/parity/fixtures/mock/152-mathematically-exact-0-01-sum-deltas-survive-float-comparison.json +169 -0
  531. jev_mcp_python-0.1.0/tests/parity/harness/js_oracle.mjs +24 -0
  532. jev_mcp_python-0.1.0/tests/parity/harness/lib.mjs +131 -0
  533. jev_mcp_python-0.1.0/tests/parity/harness/mock-hooks.mjs +120 -0
  534. jev_mcp_python-0.1.0/tests/parity/harness/record.mjs +186 -0
  535. jev_mcp_python-0.1.0/tests/parity/harness/reference.sh +37 -0
  536. jev_mcp_python-0.1.0/tests/parity/harness/regex_oracle.mjs +32 -0
  537. jev_mcp_python-0.1.0/tests/parity/harness/replay.mjs +64 -0
  538. jev_mcp_python-0.1.0/tests/parity/test_extract_differential.py +227 -0
  539. jev_mcp_python-0.1.0/tests/parity/test_policy_fixtures.py +253 -0
  540. jev_mcp_python-0.1.0/tests/parity/test_provider_fixtures.py +117 -0
  541. jev_mcp_python-0.1.0/tests/parity/test_serialize_differential.py +193 -0
  542. jev_mcp_python-0.1.0/tests/parity/test_serialize_fixtures.py +27 -0
  543. jev_mcp_python-0.1.0/tests/parity/test_tool_fixtures.py +72 -0
  544. jev_mcp_python-0.1.0/tests/property/__init__.py +0 -0
  545. jev_mcp_python-0.1.0/tests/property/test_argument_schema_properties.py +259 -0
  546. jev_mcp_python-0.1.0/tests/property/test_policy_properties.py +194 -0
  547. jev_mcp_python-0.1.0/tests/property/test_text_ids_serialize_properties.py +104 -0
  548. jev_mcp_python-0.1.0/tests/property/test_validation_properties.py +116 -0
  549. jev_mcp_python-0.1.0/tests/security/__init__.py +0 -0
  550. jev_mcp_python-0.1.0/tests/security/test_gates.py +16 -0
  551. jev_mcp_python-0.1.0/tests/security/test_injection.py +132 -0
  552. jev_mcp_python-0.1.0/tests/security/test_inputs.py +331 -0
  553. jev_mcp_python-0.1.0/tests/security/test_live_typesafe.py +200 -0
  554. jev_mcp_python-0.1.0/tests/security/test_redos.py +127 -0
  555. jev_mcp_python-0.1.0/tests/security/test_wire.py +303 -0
  556. jev_mcp_python-0.1.0/tests/security/tools.py +262 -0
  557. jev_mcp_python-0.1.0/tests/support/__init__.py +0 -0
  558. jev_mcp_python-0.1.0/tests/support/bench_agent.py +123 -0
  559. jev_mcp_python-0.1.0/tests/support/bench_provider.py +81 -0
  560. jev_mcp_python-0.1.0/tests/support/fake_mcp_server.py +69 -0
  561. jev_mcp_python-0.1.0/tests/support/fixtures.py +98 -0
  562. jev_mcp_python-0.1.0/tests/support/jev.py +64 -0
  563. jev_mcp_python-0.1.0/tests/support/node.py +58 -0
  564. jev_mcp_python-0.1.0/tests/support/peer.py +132 -0
  565. jev_mcp_python-0.1.0/tests/support/replay.py +87 -0
  566. jev_mcp_python-0.1.0/tests/support/secrets.py +46 -0
  567. jev_mcp_python-0.1.0/tests/support/stdio.py +139 -0
  568. jev_mcp_python-0.1.0/tests/support/tools_list.py +60 -0
  569. jev_mcp_python-0.1.0/tests/unit/__init__.py +0 -0
  570. jev_mcp_python-0.1.0/tests/unit/test_arguments.py +120 -0
  571. jev_mcp_python-0.1.0/tests/unit/test_dependencies.py +37 -0
  572. jev_mcp_python-0.1.0/tests/unit/test_domain.py +82 -0
  573. jev_mcp_python-0.1.0/tests/unit/test_extract_candidates.py +72 -0
  574. jev_mcp_python-0.1.0/tests/unit/test_extract_dialect.py +111 -0
  575. jev_mcp_python-0.1.0/tests/unit/test_frame.py +49 -0
  576. jev_mcp_python-0.1.0/tests/unit/test_ids.py +68 -0
  577. jev_mcp_python-0.1.0/tests/unit/test_policy.py +444 -0
  578. jev_mcp_python-0.1.0/tests/unit/test_providers.py +417 -0
  579. jev_mcp_python-0.1.0/tests/unit/test_release_version.py +98 -0
  580. jev_mcp_python-0.1.0/tests/unit/test_resolver.py +152 -0
  581. jev_mcp_python-0.1.0/tests/unit/test_runtime.py +66 -0
  582. jev_mcp_python-0.1.0/tests/unit/test_schema_compile.py +119 -0
  583. jev_mcp_python-0.1.0/tests/unit/test_serialize.py +183 -0
  584. jev_mcp_python-0.1.0/tests/unit/test_settings.py +119 -0
  585. jev_mcp_python-0.1.0/tests/unit/test_stdio.py +42 -0
  586. jev_mcp_python-0.1.0/tests/unit/test_telemetry.py +377 -0
  587. jev_mcp_python-0.1.0/tests/unit/test_text.py +113 -0
  588. jev_mcp_python-0.1.0/tests/unit/test_tool_boundaries.py +74 -0
  589. jev_mcp_python-0.1.0/tests/unit/test_validation_choice.py +296 -0
  590. jev_mcp_python-0.1.0/tests/unit/test_validation_noul_score.py +85 -0
  591. jev_mcp_python-0.1.0/uv.lock +1149 -0
@@ -0,0 +1,98 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ # ruff -> pyright -> unit -> property -> contract -> parity -> security -> build -> MCP smoke (ROADMAP CI).
11
+ jobs:
12
+ ruff:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v6
17
+ - run: uv sync --locked --all-extras
18
+ - run: make lint
19
+
20
+ pyright:
21
+ needs: ruff
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: astral-sh/setup-uv@v6
26
+ - run: uv sync --locked --all-extras
27
+ - run: make typecheck
28
+
29
+ unit:
30
+ needs: pyright
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ - uses: astral-sh/setup-uv@v6
35
+ - run: uv sync --locked --all-extras
36
+ - run: make unit
37
+
38
+ property:
39
+ needs: unit
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - uses: astral-sh/setup-uv@v6
44
+ - run: uv sync --locked --all-extras
45
+ - run: make property
46
+ - run: make policy-coverage
47
+
48
+ contract:
49
+ needs: property
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ - uses: astral-sh/setup-uv@v6
54
+ - run: uv sync --locked --all-extras
55
+ - run: make contract
56
+
57
+ parity:
58
+ needs: contract
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+ - uses: astral-sh/setup-uv@v6
63
+ # Node 24 for fixture replay and the serializer differential tests (P0/P2).
64
+ - uses: actions/setup-node@v4
65
+ with:
66
+ node-version: "24"
67
+ - run: uv sync --locked --all-extras
68
+ - run: make parity
69
+
70
+ security:
71
+ needs: parity
72
+ runs-on: ubuntu-latest
73
+ steps:
74
+ - uses: actions/checkout@v4
75
+ - uses: astral-sh/setup-uv@v6
76
+ - run: uv sync --locked --all-extras
77
+ - run: make security
78
+
79
+ build:
80
+ needs: security
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ - uses: astral-sh/setup-uv@v6
85
+ - run: make build
86
+ - uses: actions/upload-artifact@v4
87
+ with:
88
+ name: dist
89
+ path: dist/
90
+
91
+ smoke:
92
+ needs: build
93
+ runs-on: ubuntu-latest
94
+ steps:
95
+ - uses: actions/checkout@v4
96
+ - uses: astral-sh/setup-uv@v6
97
+ - run: uv sync --locked --all-extras
98
+ - run: make smoke
@@ -0,0 +1,158 @@
1
+ name: Release
2
+
3
+ # Conventional Commits on main -> a release pull request. Merging it -> a draft GitHub Release with its
4
+ # tag (release-please-config.json: draft + force-tag-creation). The tagged commit is then built, its
5
+ # assets and checksums uploaded, re-downloaded, installed into a fresh venv, and checked; only then is
6
+ # the release published, and the verified wheel and sdist are uploaded to PyPI through trusted
7
+ # publishing (OIDC, no stored token). Any failure leaves the release a draft.
8
+ on:
9
+ push:
10
+ branches: [main]
11
+ workflow_dispatch:
12
+
13
+ permissions: {}
14
+
15
+ # One release at a time; a queued run waits instead of cancelling one mid-release.
16
+ concurrency:
17
+ group: release
18
+ cancel-in-progress: false
19
+
20
+ defaults:
21
+ run:
22
+ shell: bash
23
+
24
+ jobs:
25
+ version:
26
+ name: Version
27
+ if: github.ref == 'refs/heads/main'
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ contents: write # release commits, tags, draft releases
31
+ pull-requests: write # the release pull request
32
+ issues: write # its autorelease labels (the action's documented minimum)
33
+ outputs:
34
+ release_created: ${{ steps.releaser.outputs.release_created }}
35
+ tag_name: ${{ steps.releaser.outputs.tag_name }}
36
+ sha: ${{ steps.releaser.outputs.sha }}
37
+ steps:
38
+ # Config and manifest only: a `release-type` input would bypass both and drop `draft`.
39
+ - id: releaser
40
+ uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
41
+ with:
42
+ token: ${{ github.token }}
43
+ config-file: release-please-config.json
44
+ manifest-file: .release-please-manifest.json
45
+
46
+ build:
47
+ name: Build
48
+ needs: version
49
+ if: needs.version.outputs.release_created == 'true'
50
+ runs-on: ubuntu-latest
51
+ permissions:
52
+ contents: write # upload assets onto the draft release
53
+ env:
54
+ TAG: ${{ needs.version.outputs.tag_name }}
55
+ TAG_SHA: ${{ needs.version.outputs.sha }}
56
+ GH_TOKEN: ${{ github.token }}
57
+ GH_REPO: ${{ github.repository }}
58
+ steps:
59
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
60
+ with:
61
+ ref: refs/tags/${{ needs.version.outputs.tag_name }}
62
+ persist-credentials: false
63
+ - name: Confirm the tagged commit and a draft release
64
+ run: |
65
+ set -euo pipefail
66
+ test "$(git rev-parse HEAD)" = "$TAG_SHA"
67
+ test "$(gh release view "$TAG" --json isDraft --jq .isDraft)" = true
68
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
69
+ with:
70
+ enable-cache: false
71
+ - name: Build one wheel and one sdist at the tag version
72
+ run: |
73
+ set -euo pipefail
74
+ rm -rf dist
75
+ uv build
76
+ uv run --no-project scripts/check_release_version.py dist dist "$TAG"
77
+ - name: Write checksums
78
+ working-directory: dist
79
+ run: |
80
+ set -euo pipefail
81
+ sha256sum -- *.whl *.tar.gz > SHA256SUMS.txt
82
+ cat SHA256SUMS.txt
83
+ - name: Upload onto the draft release
84
+ run: |
85
+ set -euo pipefail
86
+ gh release upload "$TAG" dist/*.whl dist/*.tar.gz dist/SHA256SUMS.txt --clobber
87
+
88
+ verify:
89
+ name: Verify and publish
90
+ needs: [version, build]
91
+ runs-on: ubuntu-latest
92
+ permissions:
93
+ contents: write # drafts and their assets are visible only with write; also the final undraft
94
+ env:
95
+ TAG: ${{ needs.version.outputs.tag_name }}
96
+ GH_TOKEN: ${{ github.token }}
97
+ GH_REPO: ${{ github.repository }}
98
+ steps:
99
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
100
+ with:
101
+ ref: refs/tags/${{ needs.version.outputs.tag_name }}
102
+ persist-credentials: false
103
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
104
+ with:
105
+ enable-cache: false
106
+ - name: Download the release assets and check their sums
107
+ run: |
108
+ set -euo pipefail
109
+ assets="$RUNNER_TEMP/assets"
110
+ gh release download "$TAG" --dir "$assets"
111
+ cd "$assets"
112
+ test "$(wc -l < SHA256SUMS.txt)" -eq 2
113
+ sha256sum --check --strict SHA256SUMS.txt
114
+ uv run --no-project "$GITHUB_WORKSPACE/scripts/check_release_version.py" dist . "$TAG"
115
+ - name: Install the wheel into a fresh venv and check the installed version
116
+ run: |
117
+ set -euo pipefail
118
+ venv="$RUNNER_TEMP/verify-venv"
119
+ uv venv --python "$(cat .python-version)" "$venv"
120
+ uv pip install --python "$venv/bin/python" "$RUNNER_TEMP"/assets/*.whl
121
+ # -I: no checkout, script directory, or PYTHONPATH on sys.path; jev_mcp must come from the wheel.
122
+ cd "$RUNNER_TEMP"
123
+ "$venv/bin/python" -I "$GITHUB_WORKSPACE/scripts/check_release_version.py" installed "$TAG"
124
+ - name: Publish the release
125
+ run: |
126
+ set -euo pipefail
127
+ test "$(gh release view "$TAG" --json isDraft --jq .isDraft)" = true
128
+ gh release edit "$TAG" --draft=false
129
+
130
+ pypi:
131
+ name: Publish to PyPI
132
+ needs: [version, build, verify]
133
+ if: needs.version.outputs.release_created == 'true'
134
+ runs-on: ubuntu-latest
135
+ permissions:
136
+ contents: read
137
+ id-token: write # PyPI trusted publishing (OIDC); no stored token
138
+ environment: pypi
139
+ env:
140
+ TAG: ${{ needs.version.outputs.tag_name }}
141
+ GH_TOKEN: ${{ github.token }}
142
+ GH_REPO: ${{ github.repository }}
143
+ steps:
144
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
145
+ with:
146
+ ref: refs/tags/${{ needs.version.outputs.tag_name }}
147
+ persist-credentials: false
148
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
149
+ with:
150
+ enable-cache: false
151
+ - name: Download the verified wheel and sdist from the release
152
+ run: |
153
+ set -euo pipefail
154
+ assets="$RUNNER_TEMP/assets"
155
+ gh release download "$TAG" --dir "$assets"
156
+ test "$(ls "$assets"/*.whl "$assets"/*.tar.gz | wc -l)" -eq 2
157
+ - name: Upload to PyPI through trusted publishing
158
+ run: uv publish --trusted-publishing always --no-attestations "$RUNNER_TEMP/assets"
@@ -0,0 +1,23 @@
1
+ *.pyc
2
+ __pycache__/
3
+ .venv/
4
+ dist/
5
+ .coverage
6
+ coverage.xml
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .hypothesis/
10
+ .benchmarks/
11
+ tests/parity/reference/
12
+ docs/architecture.visual-check.*
13
+ evals/reports/*
14
+ !evals/reports/.gitkeep
15
+ !evals/reports/p8-pilot.md
16
+ !evals/reports/bench150-sample.html
17
+ !evals/reports/bench150.html
18
+ !evals/reports/bench150.md
19
+ .DS_Store
20
+ .treehouse/
21
+ AGENTS.md
22
+ CLAUDE.md
23
+ improvment.md
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.1.0"
3
+ }
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-09-22)
4
+
5
+
6
+ ### Features
7
+
8
+ * initial release of jev-mcp-python 0.1.0 ([c31bae5](https://github.com/PyModel/jev-mcp/commit/c31bae5bdbcc928be99dfb908b2dafcfb3b11179))
@@ -0,0 +1,125 @@
1
+ # Jev MCP
2
+
3
+ An MCP server that turns TypeSafe's Jev model into purpose-built judgment tools for agents. Jev returns typed probabilities, not text; this server designs the questions and turns the answers into actions an agent can safely act on.
4
+
5
+ ## Language
6
+
7
+ ### Judgments
8
+
9
+ **Jev**:
10
+ TypeSafe's System One model: it answers typed questions about a state with probability distributions instead of generated text.
11
+ _Avoid_: the LLM, the model (when the host agent's model could be meant)
12
+
13
+ **State**:
14
+ The observed material a judgment is made about (claims, evidence, candidates, a diff). State is evidence to evaluate, never instructions to follow.
15
+ _Avoid_: context, prompt, input
16
+
17
+ **Question**:
18
+ One narrow typed ask about the state, of kind Choice, Noul, or Score. Questions in one request cannot see each other's answers.
19
+ _Avoid_: prompt, query (query is a find/rerank input field)
20
+
21
+ **Choice**:
22
+ A question whose answer is one option from a named set, with a probability for every option.
23
+ _Avoid_: enum, select, multiple-choice
24
+
25
+ **Noul**:
26
+ A question whose answer is the probability that a yes/no condition holds. A value near 0.5 means uncertain, not "medium".
27
+ _Avoid_: boolean (Vercel's wire name for it), yes/no
28
+
29
+ **Score**:
30
+ A question whose answer is a probability-weighted position on an ordered list of concrete levels, 0-indexed.
31
+ _Avoid_: rating, grade
32
+
33
+ **Answer**:
34
+ Jev's raw reply to one question, before validation.
35
+ _Avoid_: result, response (response means the whole provider reply)
36
+
37
+ **Confidence**:
38
+ How concentrated an answer's distribution is. It is not correctness, and unknown confidence never satisfies a threshold.
39
+ _Avoid_: certainty, accuracy
40
+
41
+ **Margin**:
42
+ The gap between the top and runner-up probabilities of a Choice answer.
43
+ _Avoid_: lead, spread
44
+
45
+ ### Deciding
46
+
47
+ **Action**:
48
+ What the caller may do with a judgment: `auto` (stands alone), `review` (a human or stronger check should confirm), or `escalate` (must not proceed as is).
49
+ _Avoid_: decision, status, verdict
50
+
51
+ **Verdict**:
52
+ A tool's semantic conclusion about one item, such as verified / contradicted / unsupported or answered / partial / absent. A verdict is not an action.
53
+ _Avoid_: label, result
54
+
55
+ **Policy**:
56
+ The deterministic rules that turn validated answers and thresholds into actions. The model judges; policy decides.
57
+ _Avoid_: rules engine, heuristics
58
+
59
+ **Threshold**:
60
+ A caller-tunable probability or confidence boundary a policy compares against, such as auto_accept or review_at.
61
+ _Avoid_: cutoff, limit (limit means a Cap)
62
+
63
+ **Fail Closed**:
64
+ The rule that a missing, malformed, or out-of-bounds answer produces `invalid_response` and a non-auto action, never a default verdict.
65
+ _Avoid_: fallback, graceful degradation
66
+
67
+ **Truncated Context**:
68
+ A document the judgment is made over (a doc, diff, claim, or evidence item) that exceeded a cap and was cut before reaching Jev. A judgment over truncated context can never be `auto`. Cut item text (a jev_find or jev_rerank candidate, a jev_classify item or class description) is not Truncated Context: it is reported to telemetry only and does not change the action. jev_extract's capped candidate universe is a separate rule of its own field decision.
69
+ _Avoid_: partial input, clipped
70
+
71
+ **Reason Code**:
72
+ A stable machine-readable token explaining why a gate reached its action, such as `claims_contradicted`.
73
+ _Avoid_: error code, message
74
+
75
+ **Escape Hatch**:
76
+ An extra Choice option (ask_user, investigate, none) that lets Jev decline to pick among supplied candidates.
77
+ _Avoid_: abstain option, fallback option
78
+
79
+ **Composite**:
80
+ The weighted 0–1 summary of a patch review's four rubric scores.
81
+ _Avoid_: overall score, quality score
82
+
83
+ ### Inputs
84
+
85
+ **Claim**:
86
+ An assertion to be checked against evidence. A claim is never evidence for itself or for the patch it describes.
87
+ _Avoid_: statement, assertion (in field names)
88
+
89
+ **Evidence**:
90
+ The only material a claim may be judged against.
91
+ _Avoid_: sources, context, proof
92
+
93
+ **Candidate**:
94
+ One caller-supplied option to be found, ranked, picked, or extracted. In jev_extract a candidate is a verbatim regex match, and the returned value is always one of them or null.
95
+ _Avoid_: option (wire-level term), document, hit
96
+
97
+ **Cap**:
98
+ A hard size bound on an input; exceeding it either rejects the call or truncates, depending on the field.
99
+ _Avoid_: limit, quota
100
+
101
+ ### Providers and parity
102
+
103
+ **Provider**:
104
+ A transport that delivers questions to Jev and returns answers: TypeSafe direct, OpenRouter, Cloudflare, Vercel, or a Jev-compatible endpoint.
105
+ _Avoid_: backend, adapter, client
106
+
107
+ **Envelope**:
108
+ The provider response wrapper around the answers (answers object, usage, model). Providers validate only the envelope.
109
+ _Avoid_: payload, body
110
+
111
+ **Reference Implementation**:
112
+ The TypeScript reference server 0.5.0 whose observable behavior the Python server must match.
113
+ _Avoid_: the old server, the original, upstream
114
+
115
+ **Parity**:
116
+ Identical tool output from the Reference Implementation and the Python server given identical inputs and identical simulated answers.
117
+ _Avoid_: compatibility, equivalence
118
+
119
+ **Sanctioned Divergence**:
120
+ An intentional, ADR-recorded difference from the Reference Implementation that the parity suite expects rather than flags.
121
+ _Avoid_: known difference, deviation, bug-compat
122
+
123
+ **Reference Quirk**:
124
+ A behavior of the Reference Implementation that looks accidental and needs an explicit keep-or-diverge decision.
125
+ _Avoid_: bug, legacy behavior
@@ -0,0 +1,82 @@
1
+ # Contributing
2
+
3
+ jev-mcp-python is a Python MCP server exposing TypeSafe's Jev judgment tools,
4
+ frozen against a TypeScript reference server. The public repository is
5
+ https://github.com/PyModel/jev-mcp. Open a pull request against `main`.
6
+
7
+ ## Read first
8
+
9
+ - `README.md`: what the server is, how to run it, and the recorded eval numbers.
10
+ - `CONTEXT.md`: the project vocabulary.
11
+ - `ROADMAP.md`: phases and acceptance criteria.
12
+ - `docs/adr/`: the decisions. The spec is frozen: a change the ADRs do not cover
13
+ needs a new ADR, not a silent design choice.
14
+
15
+ ## Set up
16
+
17
+ Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/).
18
+
19
+ ```sh
20
+ uv sync --all-extras
21
+ ```
22
+
23
+ ## Prove a change
24
+
25
+ Run every CI stage locally, with `TYPESAFE_API_KEY` unset:
26
+
27
+ ```sh
28
+ env -u TYPESAFE_API_KEY make ci
29
+ ```
30
+
31
+ `make ci` must pass. The parity stage needs Node 24 and skips locally without it.
32
+ Report the command you ran and its result with the change.
33
+
34
+ - Fix a bug by first adding a test that fails, then making it pass.
35
+ - Never hand-edit `tests/parity/fixtures/`; change `tests/parity/cases/` and
36
+ re-record with `make parity-record`.
37
+ - Never delete or weaken a test to make the build pass.
38
+
39
+ ## Paid gates are not part of a contribution
40
+
41
+ `make security-live`, `make eval-live`, and `make ab` call the real TypeSafe API
42
+ and spend money. A normal contribution does not run them and must not require
43
+ them. They are run by the maintainer, within their budgets, when a change touches
44
+ live behavior.
45
+
46
+ ## Offer a contribution
47
+
48
+ 1. Branch from the current `main`.
49
+ 2. Keep the change focused; one concern per commit, imperative subject line.
50
+ 3. Rebase onto `main` so the branch fast-forwards.
51
+ 4. Hand the branch to the maintainer with the `make ci` result.
52
+
53
+ ## Releases
54
+
55
+ The Release workflow (`.github/workflows/release.yml`) cuts releases from
56
+ Conventional Commits on `main`; there is no release trailer or manual tag. It
57
+ keeps a release pull request open with the next version and changelog; merging
58
+ it creates a draft GitHub Release and its `v<version>` tag. The workflow builds
59
+ that tag, uploads the wheel, sdist, and `SHA256SUMS.txt`, installs the downloaded
60
+ wheel into a fresh venv, and publishes the release only if the installed version
61
+ matches the tag. A failed check leaves the release a draft. The verified wheel and
62
+ sdist are then uploaded to PyPI through trusted publishing: no token is stored in
63
+ the repository; the PyPI project (`jev-mcp-python`) must have a pending or active
64
+ publisher for `PyModel/jev-mcp`, workflow `release.yml`, environment `pypi`.
65
+
66
+ - The first release is `v0.1.0`: `pyproject.toml` already declares `0.1.0`,
67
+ `initial-version` in `release-please-config.json` records it, and
68
+ `.release-please-manifest.json` stays `0.0.0` (nothing released) until the
69
+ first release pull request is merged. That pull request needs a `feat` or
70
+ `fix` commit in the scanned history; the history starts at the initial commit.
71
+ - The release pull request is opened with the workflow token, so GitHub does not
72
+ run `ci` on it. Run `env -u TYPESAFE_API_KEY make ci` on its branch before
73
+ merging.
74
+ - The version gate is `scripts/check_release_version.py`, tested offline in
75
+ `tests/unit/test_release_version.py`.
76
+
77
+ ## License
78
+
79
+ The copyright holder is Mohamed Elkholy.
80
+
81
+ By contributing, you agree that your contributions are licensed under the MIT
82
+ License in `LICENSE`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohamed Elkholy⁠​‌​​‌‌​‌​‌‌​‌‌‌‌​‌‌​‌​​​​‌‌​​​​‌​‌‌​‌‌​‌​‌‌​​‌​‌​‌‌​​‌​​​​‌​​​​​​‌​​​‌​‌​‌‌​‌‌​​​‌‌​‌​‌‌​‌‌​‌​​​​‌‌​‌‌‌‌​‌‌​‌‌​​​‌‌‌‌​​‌
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,93 @@
1
+ # CI stages, in ROADMAP order. Every declared stage is real: pytest exits 5 (nothing collected)
2
+ # when its directory is missing or empty, so a stage cannot pass vacuously. A new stage joins `ci`
3
+ # in the same commit that adds its tests.
4
+ PYTEST := uv run pytest
5
+
6
+ .PHONY: ci lint typecheck unit property policy-coverage contract parity security build smoke eval eval-live security-live ab load
7
+
8
+ ci: lint typecheck unit property policy-coverage contract parity security build smoke
9
+
10
+ lint:
11
+ uv run ruff check
12
+ uv run ruff format --check
13
+
14
+ typecheck:
15
+ uv run pyright
16
+
17
+ unit:
18
+ $(PYTEST) tests/unit --cov=jev_mcp --cov-report=term-missing
19
+
20
+ property:
21
+ $(PYTEST) tests/property
22
+
23
+ # ROADMAP P3: the policy package keeps 100% branch coverage from its unit and property tests alone.
24
+ policy-coverage:
25
+ $(PYTEST) tests/unit tests/property -q --cov=jev_mcp.policy --cov-branch --cov-fail-under=100 --cov-report=term-missing
26
+
27
+ contract:
28
+ $(PYTEST) tests/contract
29
+
30
+ parity:
31
+ $(PYTEST) tests/parity
32
+
33
+ # ROADMAP P6: the scripted adversary, offline. Real now, so an empty stage fails (pytest exit 5).
34
+ security:
35
+ $(PYTEST) tests/security
36
+
37
+ # Live P6 gate against TypeSafe (paid, bounded; tests/security/test_live_typesafe.py). Fails without
38
+ # TYPESAFE_API_KEY. Not part of `make ci` or the CI security job.
39
+ security-live:
40
+ $(PYTEST) tests/security -m live
41
+
42
+ build:
43
+ uv build
44
+
45
+ # The integration tests, then the slow `uvx --from .` smoke test. A command-line `-m` replaces the addopts
46
+ # one, so the smoke line selects `smoke` alone and never re-admits `live` (ADR-0027).
47
+ smoke:
48
+ $(PYTEST) tests/integration
49
+ $(PYTEST) tests/integration -m smoke
50
+
51
+ # ROADMAP P9: local overhead at 1/4/16/32/64 concurrent calls, provider stubbed (tests/load/). Timing-based,
52
+ # so it stays out of `make ci`.
53
+ load:
54
+ $(PYTEST) tests/load -m load -s
55
+
56
+ # ROADMAP P7: offline eval scorer and calibration tests. No network, no API key.
57
+ eval:
58
+ $(PYTEST) tests/evals
59
+
60
+ # Live L3 smoke against TypeSafe (paid, bounded; evals/README.md). Fails without TYPESAFE_API_KEY.
61
+ eval-live:
62
+ $(PYTEST) tests/evals -m live
63
+
64
+ # ROADMAP P8 agent A/B pilot (paid, capped at 9 runs and 25 USD; evals/README.md § L4). Refuses unless
65
+ # the caller passes JEV_AB_LIVE=1 on the command line; this target never sets it. Refuses to overwrite a
66
+ # committed evals/reports/p8-pilot.md when neither its recorded runs nor a ledger are present.
67
+ ab:
68
+ uv run python -m evals.ab.pilot
69
+
70
+ # Parity fixtures (ROADMAP P0). The pinned TypeScript reference is fetched into
71
+ # tests/parity/reference/ (gitignored) and run under Node 24.19.0.
72
+
73
+ NODE ?= $(HOME)/.nvm/versions/node/v24.19.0/bin/node
74
+ NPM ?= $(dir $(NODE))npm
75
+ PARITY := tests/parity
76
+ REFERENCE := $(PARITY)/reference
77
+
78
+ .PHONY: parity-reference parity-record parity-verify
79
+
80
+ # Fetch and build the reference at the pinned commit. Needs the network once;
81
+ # later runs reuse the checkout and are offline.
82
+ parity-reference:
83
+ PATH="$(dir $(NODE)):$$PATH" NODE="$(NODE)" NPM="$(NPM)" $(PARITY)/harness/reference.sh $(REFERENCE)
84
+
85
+ # Regenerate tests/parity/fixtures/ from the pinned reference. Offline: the only
86
+ # provider is the local fake in harness/lib.mjs.
87
+ parity-record: parity-reference
88
+ PATH="$(dir $(NODE)):$$PATH" $(NODE) $(PARITY)/harness/record.mjs
89
+
90
+ # Replay every committed fixture against the reference through the fake and
91
+ # require byte-identical tool results.
92
+ parity-verify: parity-reference
93
+ PATH="$(dir $(NODE)):$$PATH" $(NODE) $(PARITY)/harness/replay.mjs
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.5
2
+ Name: jev-mcp-python
3
+ Version: 0.1.0
4
+ Summary: Behavior-compatible Python MCP server exposing TypeSafe's Jev judgment tools.
5
+ Author: Mohamed Elkholy
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Requires-Python: >=3.12
10
+ Requires-Dist: httpx
11
+ Requires-Dist: mcp<3,>=2.2
12
+ Requires-Dist: pydantic-settings
13
+ Requires-Dist: pydantic>=2
14
+ Provides-Extra: telemetry
15
+ Requires-Dist: opentelemetry-sdk; extra == 'telemetry'
16
+ Requires-Dist: prometheus-client; extra == 'telemetry'
17
+ Provides-Extra: typesafe
18
+ Requires-Dist: typesafe-sdk; extra == 'typesafe'