Skip to main content

jevassert

CI License

Regression tests for Jev question packs: assert accuracy, calibration and cost in CI, with recordings so runs are deterministic, free and rate-limit free.

Independent community tool. Not affiliated with TypeSafe AI.

Jev returns typed decisions with probabilities, which means two things your normal test suite cannot check: does the decision match the labels, and does the stated probability mean what it says. jevassert checks both — and never calls the model during check, because CI should run on a recording.

record  →  predictions.jsonl  →  check  (offline, deterministic)  →  exit 0/1/2

Quickstart

uvx jevassert record examples/demo-triage -o triage.jsonl   # needs TYPESAFE_API_KEY
uvx jevassert check  examples/demo-triage -p triage.jsonl --failures

record calls Jev once per case (concurrently, with retries) and writes one JSONL line per case — model version, usage, latency, answers. check replays that file: no API key, no network, same result every time.

Re-record when the pack questions, the gates or the model version change, then compare:

uvx jevassert record examples/demo-triage -o triage-next.jsonl
uvx jevassert compare examples/demo-triage --a triage.jsonl --b triage-next.jsonl

Packs

A pack follows spec v0 (canonical: jev-packs/SPEC.md):

examples/demo-triage/
  pack.yaml     # state contract, questions, optional threshold floors
  cases.jsonl   # {"id", "state", "expect"} per line
  gates.yaml    # optional — jevassert quality gates

Questions are the SPEC shapes — noul, choice (options), score (levels) — and every closed set must include the label unknown (Jev cannot abstain). Score levels may carry level_descriptions so the API gets situational text instead of bare keys:

questions:
  queue:
    type: choice
    instructions: Which team should handle this message?
    options: {billing: ..., technical: ..., unknown: Cannot tell.}
  urgency:
    type: score
    instructions: How soon does this need a human response?
    levels: [low, normal, high, unknown]
    level_descriptions:
      low: No stated impact or time pressure; can wait.
      high: Stated impact or time pressure; needs a response today.

thresholds in the pack are the author's recommended operating point (per-label probability floors; labels without a floor always go to review).

Gates live in gates.yaml, so the quality contract is explicit:

min_accuracy: 0.85
max_ece: 0.15
max_cost_per_case_usd: 0.001
max_p95_latency_ms: 800
min_coverage_at_precision: {precision: 0.9, min_coverage: 0.6}
min_accuracy_ci_lower: 0.8          # bootstrap CI lower bound (n small-safe gate)
per_question:
  queue: {min_accuracy: 0.9, max_ece: 0.1}

What check reports

  • accuracy per question and overall, with a bootstrap 95% CI (--bootstrap N, default 1000; 0 disables)
  • ECE — expected calibration error of the decision probability, equal-mass bins (meaningful with a few hundred items; small packs get a warning)
  • Brier — for Noul questions
  • coverage — accept when p >= threshold: how much you automate, at what precision
  • author thresholds — auto-accept coverage under the pack's own floors
  • threshold suggestion--target-precision 0.95 finds the highest-coverage cut that still reaches that precision
  • cost and latency — dollars per case and p50/p95, from the recording
  • --failures — every mismatch with expected/got/probability and the state

check warns when the recording's model version differs from pack.tested, when cases are missing or extra, and when tested is still null.

Exit codes: 0 all gates pass, 1 a gate failed, 2 usage/IO error. --junit FILE writes JUnit XML; --report FILE writes a markdown report (the spec's evidence.md); --json prints machine-readable metrics.

GitHub Action

- uses: dtduc-git/jevassert@v0
  with:
    pack: examples/demo-triage
    predictions: triage.jsonl
    report: jevassert-report.md

Record outside CI (or as a scheduled job), commit the predictions file, and the Action enforces the gates on every pull request.

Commands

command what it does
jevassert record PACK -o FILE [--model M] [--resume] [--rpm N] [--dry-run] [--shuffle-options SEED] [--repeat N] call Jev for every case, write predictions JSONL
jevassert check PACK -p FILE [--failures] [--bootstrap N] [--target-precision P] [--partition dev|test] compute metrics, evaluate gates, exit 0/1/2
jevassert compare PACK --a A --b B paired accuracy deltas + exact McNemar p-value

record extras: --dry-run estimates tokens/cost from the pack without sending anything; --resume retries only cases that errored; --rpm paces requests; --shuffle-options records a robustness pass with permuted Choice option order (Score levels stay ordinal) — compare it against the base recording; --repeat N records N independent rounds (FILE-r2.jsonl, ...) and prints the discordant decision count across rounds.

check --partition dev|test evaluates only one deterministic hash-split half (--partition-seed, --partition-ratio) — tune thresholds on dev, then verify on test without fooling yourself.

Environment: TYPESAFE_API_KEY (record only), TYPESAFE_BASE_URL (override the endpoint, e.g. a local Jev-compatible replica).

Reading the numbers

  • Accuracy on <30 items per question is noisy (±19pp at n=10). Prefer packs with 100+ items per question before gating on tight thresholds, and let --bootstrap show the CI — gate on min_accuracy_ci_lower when n is small.
  • ECE needs a few hundred items to be meaningful; with small n the bins collapse to per-item gaps. Treat it as a smoke signal, not a measurement.
  • Stability: record twice and compare — the flip rate is your run-to-run noise floor. Question wording, option order and model version all move it; --shuffle-options isolates the option-order effect and --repeat N prints the flip rate automatically.
  • Threshold tuning: suggest on one half, verify on the other — check --target-precision 0.95 --partition dev, then --partition test. (CIs are percentile bootstrap; with heavily tied probabilities the ECE CI can be slightly skewed.)

Scope

  • Backend-neutral: anything that speaks the System One request/response shape.
  • File-based and offline-first: no server, no database, no telemetry.
  • Not a labeling tool, not a dashboard, not an observability product.

jevassert.packs is the reference loader/validator for SPEC v0 and is meant to be imported by other tools (jev-table, packs CI).

Release files for jevassert 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jevassert 0.1.0
File Size Uploaded
jevassert-0.1.0.tar.gz 57.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jevassert 0.1.0
File Interpreter ABI Platform
jevassert-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 90.3 kB

Release files / jevassert-0.1.0.tar.gz

Download URL jevassert-0.1.0.tar.gz
Size 57.9 kB
Tags Source
SHA-256 checksum
How to use checksums
949b2f2d450949549ccab6089743352f1fb9dfae588e1a6806994d3b096f744a
BLAKE2b-256 checksum
How to use checksums
e6cd8604e3a837badd8ee503e3aa72cd71519376c4190d1f792e1a3ac238a52e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / jevassert-0.1.0-py3-none-any.whl

Download URL jevassert-0.1.0-py3-none-any.whl
Size 32.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bb2c6eec31d2b60b0be7c3ad09571cb666adebfaa57345db8b0b41d7df0e7614
BLAKE2b-256 checksum
How to use checksums
7540387621a2b4712cc17d9f1dfca8f29cf7e95b593b72a35063b227028792dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page