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.
- jev_mcp_python-0.1.0/.github/workflows/ci.yml +98 -0
- jev_mcp_python-0.1.0/.github/workflows/release.yml +158 -0
- jev_mcp_python-0.1.0/.gitignore +23 -0
- jev_mcp_python-0.1.0/.python-version +1 -0
- jev_mcp_python-0.1.0/.release-please-manifest.json +3 -0
- jev_mcp_python-0.1.0/CHANGELOG.md +8 -0
- jev_mcp_python-0.1.0/CONTEXT.md +125 -0
- jev_mcp_python-0.1.0/CONTRIBUTING.md +82 -0
- jev_mcp_python-0.1.0/LICENSE +21 -0
- jev_mcp_python-0.1.0/Makefile +93 -0
- jev_mcp_python-0.1.0/PKG-INFO +18 -0
- jev_mcp_python-0.1.0/README.md +99 -0
- jev_mcp_python-0.1.0/ROADMAP.md +205 -0
- jev_mcp_python-0.1.0/docs/adr/0001-behavior-compatible-rewrite-against-frozen-ts-reference.md +11 -0
- jev_mcp_python-0.1.0/docs/adr/0002-model-judges-policy-decides.md +42 -0
- jev_mcp_python-0.1.0/docs/adr/0003-uniform-envelope-validation-across-providers.md +11 -0
- jev_mcp_python-0.1.0/docs/adr/0004-extract-regex-dialect-and-isolation.md +34 -0
- jev_mcp_python-0.1.0/docs/adr/0005-lengths-measured-in-utf16-code-units.md +12 -0
- jev_mcp_python-0.1.0/docs/adr/0006-js-compatible-result-serialization.md +14 -0
- jev_mcp_python-0.1.0/docs/adr/0007-vercel-provider-reserved-not-emulated.md +11 -0
- jev_mcp_python-0.1.0/docs/adr/0008-provider-endpoints-and-credentials-are-process-config-only.md +11 -0
- jev_mcp_python-0.1.0/docs/adr/0009-distribution-name-jev-mcp-python.md +11 -0
- jev_mcp_python-0.1.0/docs/adr/0010-python-312-and-mcp-sdk-v2.md +12 -0
- jev_mcp_python-0.1.0/docs/adr/0011-propagate-mcp-cancellation-to-providers.md +12 -0
- jev_mcp_python-0.1.0/docs/adr/0012-keep-reference-validation-quirks.md +22 -0
- jev_mcp_python-0.1.0/docs/adr/0013-one-registry-one-execution-kernel-ten-tool-definitions.md +63 -0
- jev_mcp_python-0.1.0/docs/adr/0014-cap-values-measurement-and-enforcement-are-separate.md +48 -0
- jev_mcp_python-0.1.0/docs/adr/0015-one-python-parity-fixture-loader.md +21 -0
- jev_mcp_python-0.1.0/docs/adr/0016-extract-dialect-translates-executors-execute.md +52 -0
- jev_mcp_python-0.1.0/docs/adr/0017-redaction-secret-set-derives-from-settings-schema.md +17 -0
- jev_mcp_python-0.1.0/docs/adr/0018-extract-runs-on-stdlib-re-with-a-narrower-subset.md +32 -0
- jev_mcp_python-0.1.0/docs/adr/0019-parsed-json-value-shape-primitives-live-in-domain.md +17 -0
- jev_mcp_python-0.1.0/docs/adr/0020-divergence-registry-single-source-of-truth.md +38 -0
- jev_mcp_python-0.1.0/docs/adr/0021-stdio-is-the-product-transport-http-is-tier-b.md +27 -0
- jev_mcp_python-0.1.0/docs/adr/0022-schemas-are-validated-faithful-at-construction.md +78 -0
- jev_mcp_python-0.1.0/docs/adr/0023-same-origin-redirects-only.md +35 -0
- jev_mcp_python-0.1.0/docs/adr/0024-record-non-fixture-divergences.md +46 -0
- jev_mcp_python-0.1.0/docs/adr/0025-extract-pool-saturation-has-its-own-reason.md +26 -0
- jev_mcp_python-0.1.0/docs/adr/0026-paid-eval-harness-shares-one-agent-run-one-relay-one-ledger.md +124 -0
- jev_mcp_python-0.1.0/docs/adr/0027-one-contract-test-guards-every-paid-path.md +53 -0
- jev_mcp_python-0.1.0/docs/adr/0028-scorers-expose-judgments-pinned-to-real-output.md +46 -0
- jev_mcp_python-0.1.0/docs/adr/0029-openrouter-referer-names-this-repo.md +16 -0
- jev_mcp_python-0.1.0/docs/architecture.html +15078 -0
- jev_mcp_python-0.1.0/docs/architecture.json +467 -0
- jev_mcp_python-0.1.0/docs/jev_docs/README.md +16 -0
- jev_mcp_python-0.1.0/docs/jev_docs/SOURCES.md +37 -0
- jev_mcp_python-0.1.0/docs/jev_docs/api.md +89 -0
- jev_mcp_python-0.1.0/docs/jev_docs/models.md +50 -0
- jev_mcp_python-0.1.0/docs/jev_docs/patterns.md +50 -0
- jev_mcp_python-0.1.0/docs/jev_docs/primitives.md +50 -0
- jev_mcp_python-0.1.0/docs/readme/badges.svg +14 -0
- jev_mcp_python-0.1.0/docs/readme/banner.svg +7 -0
- jev_mcp_python-0.1.0/docs/readme/bench-speed.svg +9 -0
- jev_mcp_python-0.1.0/docs/readme/bench-time.svg +9 -0
- jev_mcp_python-0.1.0/docs/reference/divergences.json +212 -0
- jev_mcp_python-0.1.0/docs/reference/parity-manifest.json +342 -0
- jev_mcp_python-0.1.0/docs/reference/ts-0.5.0-tools-list.json +699 -0
- jev_mcp_python-0.1.0/evals/README.md +162 -0
- jev_mcp_python-0.1.0/evals/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/ab/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/ab/arms.py +121 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/README.md +7 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/durations.py +11 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/pricing.py +20 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/__init__.py +0 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_durations.py +15 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_legacy.py +14 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_pricing.py +18 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/tests/test_textutils.py +14 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/snapshot/textutils.py +13 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t1-bulk-boundary/acceptance_test.py +17 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t1-bulk-boundary/prompt.md +1 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t1-bulk-boundary/reference/pricing.py +20 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t2-slugify/acceptance_test.py +34 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t2-slugify/prompt.md +7 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t2-slugify/reference/textutils.py +25 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/acceptance_test.py +19 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/overlay/ISSUE.md +14 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/prompt.md +1 -0
- jev_mcp_python-0.1.0/evals/ab/fixture/tasks/t3-durations/reference/durations.py +16 -0
- jev_mcp_python-0.1.0/evals/ab/grade.py +118 -0
- jev_mcp_python-0.1.0/evals/ab/ledger.py +21 -0
- jev_mcp_python-0.1.0/evals/ab/pilot.py +338 -0
- jev_mcp_python-0.1.0/evals/ab/proxy.py +58 -0
- jev_mcp_python-0.1.0/evals/ab/report.py +159 -0
- jev_mcp_python-0.1.0/evals/ab/review_server.py +22 -0
- jev_mcp_python-0.1.0/evals/ab/stream.py +80 -0
- jev_mcp_python-0.1.0/evals/ab/tasks.py +68 -0
- jev_mcp_python-0.1.0/evals/ab/unsafe.py +57 -0
- jev_mcp_python-0.1.0/evals/agent.py +139 -0
- jev_mcp_python-0.1.0/evals/baselines/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/baselines/ranking.py +64 -0
- jev_mcp_python-0.1.0/evals/bench/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/bench/analysis.py +101 -0
- jev_mcp_python-0.1.0/evals/bench/answer.py +98 -0
- jev_mcp_python-0.1.0/evals/bench/chart.py +254 -0
- jev_mcp_python-0.1.0/evals/bench/gate.py +83 -0
- jev_mcp_python-0.1.0/evals/bench/items.py +113 -0
- jev_mcp_python-0.1.0/evals/bench/ledger.py +19 -0
- jev_mcp_python-0.1.0/evals/bench/pi.py +183 -0
- jev_mcp_python-0.1.0/evals/bench/prompt.py +163 -0
- jev_mcp_python-0.1.0/evals/bench/proxy.py +136 -0
- jev_mcp_python-0.1.0/evals/bench/run.py +355 -0
- jev_mcp_python-0.1.0/evals/bench/spans.py +80 -0
- jev_mcp_python-0.1.0/evals/bench/stats.py +27 -0
- jev_mcp_python-0.1.0/evals/calibration/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/calibration/bounds.py +68 -0
- jev_mcp_python-0.1.0/evals/calibration/flips.py +24 -0
- jev_mcp_python-0.1.0/evals/calibration/rows.py +24 -0
- jev_mcp_python-0.1.0/evals/calibration/split.py +31 -0
- jev_mcp_python-0.1.0/evals/calibration/targets.py +22 -0
- jev_mcp_python-0.1.0/evals/calibration/threshold.py +46 -0
- jev_mcp_python-0.1.0/evals/datasets/bench150/items.jsonl +150 -0
- jev_mcp_python-0.1.0/evals/datasets/synthetic/classify.jsonl +10 -0
- jev_mcp_python-0.1.0/evals/datasets/synthetic/classify.outputs.jsonl +10 -0
- jev_mcp_python-0.1.0/evals/datasets/synthetic/live-classify.jsonl +3 -0
- jev_mcp_python-0.1.0/evals/datasets/synthetic/live-verify.jsonl +3 -0
- jev_mcp_python-0.1.0/evals/manifests/live-classify.json +7 -0
- jev_mcp_python-0.1.0/evals/manifests/live-verify.json +7 -0
- jev_mcp_python-0.1.0/evals/manifests/synthetic-classify.json +7 -0
- jev_mcp_python-0.1.0/evals/relay.py +167 -0
- jev_mcp_python-0.1.0/evals/reports/.gitkeep +0 -0
- jev_mcp_python-0.1.0/evals/reports/bench150-sample.html +15 -0
- jev_mcp_python-0.1.0/evals/reports/bench150.html +15 -0
- jev_mcp_python-0.1.0/evals/reports/bench150.md +16 -0
- jev_mcp_python-0.1.0/evals/reports/p8-pilot.md +78 -0
- jev_mcp_python-0.1.0/evals/runners/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/runners/live.py +102 -0
- jev_mcp_python-0.1.0/evals/runners/manifest.py +95 -0
- jev_mcp_python-0.1.0/evals/runners/score.py +93 -0
- jev_mcp_python-0.1.0/evals/scorers/__init__.py +1 -0
- jev_mcp_python-0.1.0/evals/scorers/fields.py +31 -0
- jev_mcp_python-0.1.0/evals/scorers/metrics.py +171 -0
- jev_mcp_python-0.1.0/evals/scorers/tools.py +601 -0
- jev_mcp_python-0.1.0/evals/spend.py +89 -0
- jev_mcp_python-0.1.0/pyproject.toml +79 -0
- jev_mcp_python-0.1.0/release-please-config.json +20 -0
- jev_mcp_python-0.1.0/scripts/check_release_version.py +106 -0
- jev_mcp_python-0.1.0/src/jev_mcp/__init__.py +1 -0
- jev_mcp_python-0.1.0/src/jev_mcp/__main__.py +3 -0
- jev_mcp_python-0.1.0/src/jev_mcp/domain/__init__.py +32 -0
- jev_mcp_python-0.1.0/src/jev_mcp/domain/answers.py +25 -0
- jev_mcp_python-0.1.0/src/jev_mcp/domain/json.py +49 -0
- jev_mcp_python-0.1.0/src/jev_mcp/domain/questions.py +75 -0
- jev_mcp_python-0.1.0/src/jev_mcp/domain/usage.py +16 -0
- jev_mcp_python-0.1.0/src/jev_mcp/errors.py +59 -0
- jev_mcp_python-0.1.0/src/jev_mcp/extract/__init__.py +1 -0
- jev_mcp_python-0.1.0/src/jev_mcp/extract/candidates.py +75 -0
- jev_mcp_python-0.1.0/src/jev_mcp/extract/dialect.py +400 -0
- jev_mcp_python-0.1.0/src/jev_mcp/extract/executor.py +118 -0
- jev_mcp_python-0.1.0/src/jev_mcp/extract/worker.py +198 -0
- jev_mcp_python-0.1.0/src/jev_mcp/ids.py +49 -0
- jev_mcp_python-0.1.0/src/jev_mcp/limits.py +218 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/__init__.py +98 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/actions.py +41 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/claims.py +103 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/extract.py +73 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/ranking.py +41 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/review.py +73 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/screen.py +48 -0
- jev_mcp_python-0.1.0/src/jev_mcp/policy/thresholds.py +74 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/__init__.py +26 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/base.py +236 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/cloudflare.py +59 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/compatible.py +43 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/openrouter.py +47 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/resolver.py +106 -0
- jev_mcp_python-0.1.0/src/jev_mcp/providers/typesafe.py +127 -0
- jev_mcp_python-0.1.0/src/jev_mcp/py.typed +0 -0
- jev_mcp_python-0.1.0/src/jev_mcp/serialize.py +199 -0
- jev_mcp_python-0.1.0/src/jev_mcp/server.py +176 -0
- jev_mcp_python-0.1.0/src/jev_mcp/settings.py +73 -0
- jev_mcp_python-0.1.0/src/jev_mcp/stdio.py +99 -0
- jev_mcp_python-0.1.0/src/jev_mcp/telemetry.py +223 -0
- jev_mcp_python-0.1.0/src/jev_mcp/text.py +42 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/__init__.py +20 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/arguments.py +447 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/base.py +153 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/classify.py +187 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/common.py +96 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/compare.py +143 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/decide.py +206 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/extract.py +262 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/find.py +113 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/gate.py +236 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/observed.py +69 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/rerank.py +139 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/review.py +236 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/screen.py +126 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/toolset.py +92 -0
- jev_mcp_python-0.1.0/src/jev_mcp/tools/verify.py +141 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/__init__.py +25 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/caps.py +93 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/choice.py +65 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/extract.py +48 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/noul.py +15 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/numbers.py +21 -0
- jev_mcp_python-0.1.0/src/jev_mcp/validation/score.py +20 -0
- jev_mcp_python-0.1.0/tasks/p1-foundation-notes.md +14 -0
- jev_mcp_python-0.1.0/tasks/p5-tools-notes.md +14 -0
- jev_mcp_python-0.1.0/tasks/p6-security-notes.md +67 -0
- jev_mcp_python-0.1.0/tasks/p9-observe-notes.md +93 -0
- jev_mcp_python-0.1.0/tests/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/contract/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/contract/test_divergence_registry.py +64 -0
- jev_mcp_python-0.1.0/tests/contract/test_extract.py +241 -0
- jev_mcp_python-0.1.0/tests/contract/test_fail_closed.py +329 -0
- jev_mcp_python-0.1.0/tests/contract/test_limits.py +163 -0
- jev_mcp_python-0.1.0/tests/contract/test_paid_gates.py +169 -0
- jev_mcp_python-0.1.0/tests/contract/test_providers.py +578 -0
- jev_mcp_python-0.1.0/tests/contract/test_regex_executor.py +85 -0
- jev_mcp_python-0.1.0/tests/contract/test_tools_list.py +136 -0
- jev_mcp_python-0.1.0/tests/evals/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/evals/data/bench-dryrun.jsonl +2 -0
- jev_mcp_python-0.1.0/tests/evals/data/claude-stream-json-sample.jsonl +12 -0
- jev_mcp_python-0.1.0/tests/evals/test_ab_harness.py +356 -0
- jev_mcp_python-0.1.0/tests/evals/test_agent.py +288 -0
- jev_mcp_python-0.1.0/tests/evals/test_bench.py +597 -0
- jev_mcp_python-0.1.0/tests/evals/test_bench_dryrun.py +270 -0
- jev_mcp_python-0.1.0/tests/evals/test_bench_pi.py +178 -0
- jev_mcp_python-0.1.0/tests/evals/test_calibration.py +145 -0
- jev_mcp_python-0.1.0/tests/evals/test_live_typesafe.py +50 -0
- jev_mcp_python-0.1.0/tests/evals/test_metrics.py +119 -0
- jev_mcp_python-0.1.0/tests/evals/test_real_output.py +181 -0
- jev_mcp_python-0.1.0/tests/evals/test_relay.py +221 -0
- jev_mcp_python-0.1.0/tests/evals/test_runners.py +145 -0
- jev_mcp_python-0.1.0/tests/evals/test_scorer_contract.py +192 -0
- jev_mcp_python-0.1.0/tests/evals/test_tool_scorers.py +221 -0
- jev_mcp_python-0.1.0/tests/integration/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/integration/test_http.py +71 -0
- jev_mcp_python-0.1.0/tests/integration/test_stdio.py +94 -0
- jev_mcp_python-0.1.0/tests/integration/test_tools_stdio.py +134 -0
- jev_mcp_python-0.1.0/tests/integration/test_uvx_smoke.py +20 -0
- jev_mcp_python-0.1.0/tests/load/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/load/test_overhead.py +128 -0
- jev_mcp_python-0.1.0/tests/parity/README.md +72 -0
- jev_mcp_python-0.1.0/tests/parity/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/parity/cases/_helpers.mjs +53 -0
- jev_mcp_python-0.1.0/tests/parity/cases/boundary.mjs +265 -0
- jev_mcp_python-0.1.0/tests/parity/cases/extract.mjs +112 -0
- jev_mcp_python-0.1.0/tests/parity/cases/judgments.mjs +304 -0
- jev_mcp_python-0.1.0/tests/parity/cases/malformed.mjs +175 -0
- jev_mcp_python-0.1.0/tests/parity/cases/normal.mjs +193 -0
- jev_mcp_python-0.1.0/tests/parity/cases/provider.mjs +98 -0
- jev_mcp_python-0.1.0/tests/parity/cases/text.mjs +268 -0
- jev_mcp_python-0.1.0/tests/parity/cases/truncated.mjs +70 -0
- jev_mcp_python-0.1.0/tests/parity/divergences.py +124 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/classify-at-thresholds-js-number-format.json +124 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/classify-items-x-classes-over-budget.json +797 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/compare-aspect-count-over-cap.json +48 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/compare-margin-single-key-choice.json +67 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/compare-out-of-range-confidence-is-null.json +67 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/decide-candidate-id-pattern-rejected.json +46 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-aggregate-preview-over-budget.json +46 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-candidate-at-2000-kept-2001-skipped.json +77 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-flags-normalized.json +79 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/extract-only-overlong-matches.json +40 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/find-exists-at-absent-floor.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/find-exists-at-found-tiny-probabilities.json +108 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/gate-threshold-default-review-at-follows-auto-accept.json +125 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/rerank-aggregate-over-budget.json +240 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/review-composite-at-floor.json +102 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/review-fractional-scores-clamped-composite.json +103 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/review-threshold-invariant-violated.json +38 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-injection-at-block-at.json +70 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-injection-at-custom-review-at.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-substance-at-skip-floor-relevance-below.json +80 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/screen-tofixed-half-rounds-up.json +71 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/boundary/verify-confidence-at-auto-accept.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/compare-contradicts-auto.json +66 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/decide-requirements-contradicted-plural.json +150 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/decide-single-requirement-contradicted.json +112 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/gate-contradicted-below-auto-accept.json +149 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/contradicted/verify-contradicted-auto.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/classify-duplicate-class-id.json +48 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/classify-duplicate-item-id.json +52 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/classify-omitted-ids-get-positional-fallbacks.json +109 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/decide-candidate-collides-with-escape-hatch.json +45 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/decide-duplicate-candidate-id.json +45 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/decide-hatch-name-allowed-without-hatches.json +87 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/extract-duplicate-field-id.json +45 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/find-ids-sanitized-and-suffixed.json +108 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/rerank-duplicate-id.json +43 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/rerank-fallback-avoids-supplied-ids.json +90 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/duplicate-id/verify-duplicate-evidence-ids-suffixed.json +107 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-multiline-flag.json +81 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-named-group.json +80 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-syntax-error.json +85 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-unicode-flag.json +81 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-unknown-flag.json +42 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/invalid-pattern/extract-variable-lookbehind.json +80 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/classify-low-margin.json +93 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/compare-below-auto-accept.json +68 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/extract-none-matched-ambiguous.json +77 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/extract-none-matched-confident.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/gate-claim-confidence-tiers.json +149 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/review-min-confidence-below-review-at.json +102 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/review-safe-to-apply-review-tier.json +102 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/screen-injection-review-tier.json +70 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/low-confidence/verify-low-and-null-confidence.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/classify-extra-probability-key.json +111 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/compare-invalid-overall-and-aspect.json +92 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/decide-invalid-check-kept-silent.json +133 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/decide-invalid-recommendation.json +133 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-body-array.json +71 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-body-not-json.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-usage-infinite.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/envelope-usage-null-model-absent.json +71 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/extract-choice-not-argmax.json +77 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/extract-sum-0-99-rejected.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/gate-rubric-confidence-out-of-range.json +125 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/rerank-missing-noul.json +88 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/rerank-out-of-range-noul.json +79 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/malformed/verify-claim-choice-inherited-key.json +77 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/classify-batch-with-context.json +164 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/compare-with-aspects.json +92 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/decide-with-requirements.json +159 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/extract-two-fields.json +97 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/find-ranked-top-k.json +99 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/gate-accepted.json +148 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/rerank-top-k.json +104 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/review-auto-env-model.json +104 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/screen-with-purpose-pass.json +79 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/normal/verify-multi-evidence-model-override.json +123 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-200-control.json +77 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-401-after-regex.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-429-echoes-key-redacted.json +95 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-500-text.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-502-empty-body.json +124 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/provider-failure/compatible-503-body-sliced-at-200.json +71 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/regex-timeout/extract-catastrophic-then-valid-field.json +83 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/regex-timeout/extract-only-field-times-out.json +39 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-cloudflare-token-without-account.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-compatible-key-without-url.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-no-credentials.json +32 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-openrouter-key-not-sk-or.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/auto-unknown-provider-name.json +35 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-cloudflare-account-without-token.json +35 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-cloudflare-unset.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-both-unset.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-key-unset.json +35 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-other-tool.json +32 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-compatible-url-unset.json +35 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-openrouter-not-sk-or.json +35 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-openrouter-unset.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-typesafe-unset.json +34 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-typesafe-uppercase-unset.json +35 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/explicit-vercel-unset.json +37 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/resolver-error/extract-zero-match-never-resolves.json +36 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/compare-margin-zero.json +66 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/decide-candidate-tied-with-escape-hatch.json +89 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/extract-tie-picks-second.json +77 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/find-tie-keeps-caller-order.json +99 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/tie/rerank-equal-scores-stable.json +103 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/classify-item-and-class-text-over-cap.json +93 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/find-candidate-text-over-cap.json +90 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/gate-claim-over-cap.json +125 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/gate-evidence-item-over-cap.json +137 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/review-request-exactly-at-cap.json +103 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/truncated/review-tests-over-cap.json +102 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/classify-astral-ids-preserved.json +93 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/compare-aspect-200-units-astral.json +81 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/compare-aspect-201-units-astral-rejected.json +38 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/extract-dot-matches-single-units.json +80 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/extract-quantifier-counts-units.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/extract-whitespace-class.json +78 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/find-truncation-splits-surrogate-pair.json +92 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/gate-claim-truncation-splits-surrogate.json +127 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/screen-purpose-quoted-in-instruction.json +79 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unicode-astral/verify-astral-rtl-combining-text.json +106 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/decide-escape-none.json +89 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/find-exists-absent.json +89 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/gate-unsupported-confident.json +148 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/unsupported/verify-says-nothing-source-none.json +99 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/zero-match/extract-no-matches-no-provider-call.json +40 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/zero-match/extract-one-field-matches.json +83 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/classes/zero-match/extract-zero-length-matches-dropped.json +40 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/index.json +3730 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/001-compatible-provider-sends-the-standard-request-to-the-configured-endpoint.json +80 -0
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/004-compatible-provider-rejects-a-malformed-response.json +80 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/005-compatible-provider-reports-non-2xx-status-with-the-body-redacted.json +80 -0
- 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
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/009-compatible-provider-rejects-malformed-or-incomplete-usage.json +278 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/010-compatible-provider-tolerates-an-absent-usage-block-and-reports-zeros.json +79 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/011-compatible-provider-reports-missing-configuration-before-making-a-request.json +38 -0
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/013-jev-classify-preserves-valid-argmax-outputs-and-auto-review-decisions.json +123 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/014-jev-classify-rejects-a-choice-that-is-not-the-argmax.json +104 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/015-jev-classify-accepts-either-tied-maximum.json +123 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/016-jev-classify-handles-invalid-and-valid-items-independently.json +123 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/017-jev-classify-applies-the-1e-9-argmax-tolerance.json +123 -0
- 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
- 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
- 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
- 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
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/024-jev-decide-accepts-a-candidate-id-named-constructor.json +114 -0
- 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
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/028-jev-review-respects-composite-floor-as-a-parameter.json +105 -0
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/030-jev-gate-escalates-on-a-confidently-contradicted-claim.json +131 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/045-jev-screen-still-passes-on-complete-benign-answers.json +83 -0
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/047-jev-find-still-ranks-candidates-on-complete-answers.json +93 -0
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/049-jev-verify-still-returns-verified-verdicts-on-a-complete-response.json +81 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/050-jev-screen-rejects-injection-undefined-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/051-jev-screen-rejects-injection-null-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/052-jev-screen-rejects-injection-0-1-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/053-jev-screen-rejects-injection-0-1-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/054-jev-screen-rejects-injection-1-1-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/055-jev-screen-rejects-injection-true-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/056-jev-screen-rejects-substance-undefined-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/057-jev-screen-rejects-substance-null-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/058-jev-screen-rejects-substance-0-1-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/059-jev-screen-rejects-substance-0-1-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/060-jev-screen-rejects-substance-1-1-with-purpose-undefined.json +72 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/061-jev-screen-rejects-substance-true-with-purpose-undefined.json +72 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/081-jev-find-rejects-malformed-best-case-0.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/082-jev-find-rejects-malformed-best-case-1.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/083-jev-find-rejects-malformed-best-case-2.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/084-jev-find-rejects-malformed-best-case-3.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/085-jev-find-rejects-malformed-best-case-4.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/086-jev-find-rejects-malformed-best-case-5.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/087-jev-find-rejects-malformed-best-case-6.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/088-jev-find-rejects-malformed-best-case-7.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/089-jev-find-rejects-malformed-best-case-8.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/090-jev-find-rejects-malformed-best-case-9.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/091-jev-find-rejects-malformed-best-case-10.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/092-jev-find-rejects-malformed-best-case-11.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/093-jev-find-rejects-malformed-best-case-12.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/094-jev-find-rejects-malformed-best-case-13.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/095-jev-find-rejects-malformed-best-case-14.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/096-jev-find-rejects-malformed-best-case-15.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/097-jev-find-rejects-malformed-best-case-16.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/098-jev-find-rejects-malformed-best-case-17.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/099-jev-find-rejects-malformed-best-case-18.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/100-jev-find-rejects-malformed-best-case-19.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/101-jev-find-rejects-malformed-best-case-20.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/102-jev-find-rejects-exists-undefined.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/103-jev-find-rejects-exists-null.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/104-jev-find-rejects-exists-0.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/105-jev-find-rejects-exists-1.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/106-jev-find-rejects-exists-2.json +91 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/107-jev-find-rejects-exists-false.json +91 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/141-jev-verify-preserves-valid-relation-with-confidence-undefined.json +146 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/142-jev-verify-preserves-valid-relation-with-confidence-null.json +146 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/143-jev-verify-preserves-valid-relation-with-confidence-0.json +146 -0
- 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
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/145-all-three-tools-fail-closed-for-answers-undefined.json +233 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/146-all-three-tools-fail-closed-for-answers-null.json +233 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/147-all-three-tools-fail-closed-for-answers.json +233 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/148-all-three-tools-fail-closed-for-answers-bad.json +233 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/149-all-three-tools-fail-closed-for-answers-0.json +233 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/150-all-three-tools-fail-closed-for-answers-true.json +233 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/151-jev-verify-validates-source-answers-against-supplied-evidence-ids.json +1058 -0
- jev_mcp_python-0.1.0/tests/parity/fixtures/mock/152-mathematically-exact-0-01-sum-deltas-survive-float-comparison.json +169 -0
- jev_mcp_python-0.1.0/tests/parity/harness/js_oracle.mjs +24 -0
- jev_mcp_python-0.1.0/tests/parity/harness/lib.mjs +131 -0
- jev_mcp_python-0.1.0/tests/parity/harness/mock-hooks.mjs +120 -0
- jev_mcp_python-0.1.0/tests/parity/harness/record.mjs +186 -0
- jev_mcp_python-0.1.0/tests/parity/harness/reference.sh +37 -0
- jev_mcp_python-0.1.0/tests/parity/harness/regex_oracle.mjs +32 -0
- jev_mcp_python-0.1.0/tests/parity/harness/replay.mjs +64 -0
- jev_mcp_python-0.1.0/tests/parity/test_extract_differential.py +227 -0
- jev_mcp_python-0.1.0/tests/parity/test_policy_fixtures.py +253 -0
- jev_mcp_python-0.1.0/tests/parity/test_provider_fixtures.py +117 -0
- jev_mcp_python-0.1.0/tests/parity/test_serialize_differential.py +193 -0
- jev_mcp_python-0.1.0/tests/parity/test_serialize_fixtures.py +27 -0
- jev_mcp_python-0.1.0/tests/parity/test_tool_fixtures.py +72 -0
- jev_mcp_python-0.1.0/tests/property/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/property/test_argument_schema_properties.py +259 -0
- jev_mcp_python-0.1.0/tests/property/test_policy_properties.py +194 -0
- jev_mcp_python-0.1.0/tests/property/test_text_ids_serialize_properties.py +104 -0
- jev_mcp_python-0.1.0/tests/property/test_validation_properties.py +116 -0
- jev_mcp_python-0.1.0/tests/security/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/security/test_gates.py +16 -0
- jev_mcp_python-0.1.0/tests/security/test_injection.py +132 -0
- jev_mcp_python-0.1.0/tests/security/test_inputs.py +331 -0
- jev_mcp_python-0.1.0/tests/security/test_live_typesafe.py +200 -0
- jev_mcp_python-0.1.0/tests/security/test_redos.py +127 -0
- jev_mcp_python-0.1.0/tests/security/test_wire.py +303 -0
- jev_mcp_python-0.1.0/tests/security/tools.py +262 -0
- jev_mcp_python-0.1.0/tests/support/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/support/bench_agent.py +123 -0
- jev_mcp_python-0.1.0/tests/support/bench_provider.py +81 -0
- jev_mcp_python-0.1.0/tests/support/fake_mcp_server.py +69 -0
- jev_mcp_python-0.1.0/tests/support/fixtures.py +98 -0
- jev_mcp_python-0.1.0/tests/support/jev.py +64 -0
- jev_mcp_python-0.1.0/tests/support/node.py +58 -0
- jev_mcp_python-0.1.0/tests/support/peer.py +132 -0
- jev_mcp_python-0.1.0/tests/support/replay.py +87 -0
- jev_mcp_python-0.1.0/tests/support/secrets.py +46 -0
- jev_mcp_python-0.1.0/tests/support/stdio.py +139 -0
- jev_mcp_python-0.1.0/tests/support/tools_list.py +60 -0
- jev_mcp_python-0.1.0/tests/unit/__init__.py +0 -0
- jev_mcp_python-0.1.0/tests/unit/test_arguments.py +120 -0
- jev_mcp_python-0.1.0/tests/unit/test_dependencies.py +37 -0
- jev_mcp_python-0.1.0/tests/unit/test_domain.py +82 -0
- jev_mcp_python-0.1.0/tests/unit/test_extract_candidates.py +72 -0
- jev_mcp_python-0.1.0/tests/unit/test_extract_dialect.py +111 -0
- jev_mcp_python-0.1.0/tests/unit/test_frame.py +49 -0
- jev_mcp_python-0.1.0/tests/unit/test_ids.py +68 -0
- jev_mcp_python-0.1.0/tests/unit/test_policy.py +444 -0
- jev_mcp_python-0.1.0/tests/unit/test_providers.py +417 -0
- jev_mcp_python-0.1.0/tests/unit/test_release_version.py +98 -0
- jev_mcp_python-0.1.0/tests/unit/test_resolver.py +152 -0
- jev_mcp_python-0.1.0/tests/unit/test_runtime.py +66 -0
- jev_mcp_python-0.1.0/tests/unit/test_schema_compile.py +119 -0
- jev_mcp_python-0.1.0/tests/unit/test_serialize.py +183 -0
- jev_mcp_python-0.1.0/tests/unit/test_settings.py +119 -0
- jev_mcp_python-0.1.0/tests/unit/test_stdio.py +42 -0
- jev_mcp_python-0.1.0/tests/unit/test_telemetry.py +377 -0
- jev_mcp_python-0.1.0/tests/unit/test_text.py +113 -0
- jev_mcp_python-0.1.0/tests/unit/test_tool_boundaries.py +74 -0
- jev_mcp_python-0.1.0/tests/unit/test_validation_choice.py +296 -0
- jev_mcp_python-0.1.0/tests/unit/test_validation_noul_score.py +85 -0
- 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,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'
|