> ## Documentation Index
> Fetch the complete documentation index at: https://panopticon-cli.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Jev (TypeSafe) judgment client

> Optional, off-by-default typed judgment calls through TypeSafe's Jev model

# Jev (TypeSafe) judgment client

Overdeck can ask TypeSafe AI's Jev model small, typed questions: yes/no, pick-one, or a score
on a rubric. Jev is a judgment model, not a coding model. It answers questions about a piece of
text and never generates text, so it cannot run an agent. It is optional and **off by default**.

## What Jev is

Jev ("System One") takes a `state` (text or JSON) and a set of named questions, and returns a
calibrated answer for each one:

* a **Noul** question returns a probability from 0 to 1 that the statement is true;
* a **Choice** question returns a probability for each option;
* a **Score** question returns an expected score on a rubric.

Answers typically come back in under half a second. Overdeck uses them for fuzzy judgments that
are hard to do with keyword lists, such as "does this agent message end by asking a question?".

## Two routes

You can reach Jev through OpenCode Zen or directly through TypeSafe.

| Route | `jev.base_url` | `jev.model` | Key |
| - | - | - | - |
| Zen route | `https://opencode.ai/zen` | `jev-1.13-free` (limited time) or `jev-1.13` | An OpenCode Zen API key |
| Direct route | unset (the SDK uses `https://api.typesafe.ai`) | a pinned version, for example `jev-1.13.0` | A key from [console.typesafe.ai](https://console.typesafe.ai/keys) |

The Zen route needs no new account if you already have an OpenCode Zen key. Both routes use the
same key slot.

## Configuration

Add a `jev:` block to `~/.overdeck/config.yaml`:

```yaml theme={null}
jev:
  base_url: https://opencode.ai/zen   # omit for the direct route
  model: jev-1.13-free                # required; there is no default
  api_key_ref: TYPESAFE_API_KEY       # env var used when api_keys.typesafe is empty
  timeout_ms: 2000                    # per request, 1–30000

api_keys:
  typesafe: <your TypeSafe or OpenCode Zen key>

background_ai:
  cheap_mode: false
  features:
    jevTurnEndAssessment: true
```

You can also set the key in **Settings → Background AI → TypeSafe API key (Jev)**. Overdeck looks
for the key in this order:

1. `api_keys.typesafe`;
2. the environment variable named by `jev.api_key_ref` (default `TYPESAFE_API_KEY`).

**There is no default model.** With `jev.model` unset, every Jev feature reports
`model-not-configured` and makes no request. Overdeck never falls back to the SDK's own default
model.

Each Jev feature has its own toggle under `background_ai.features`, and all three are off by
default:

* `jevTurnEndAssessment`
* `jevAcceptanceCriteriaReview`
* `jevMemoryRelevance`

Low-cost mode (`background_ai.cheap_mode`, on by default) turns all of them off regardless of their
toggles. With no `jev:` block, low-cost mode on, or a toggle off, Overdeck behaves exactly as it
does without Jev: no request, no startup check, and no warning.

### Set it in Settings

**Settings → Background AI** also exposes the route, model and timeout directly, below the
TypeSafe API key row — no manual YAML editing required (PAN-4508):

* **Route** — a select with three options. **OpenCode Zen** sets `jev.base_url` to
  `https://opencode.ai/zen`. **TypeSafe direct** removes `base_url`. A third option, **Custom**,
  appears only when `jev.base_url` is already some other URL; choosing it again keeps that URL
  as-is — there is no field here to type a new custom URL.
* **Model** — a text field with suggestions `jev-1.13-free`, `jev-1.13`, `jev-1.13.0`. It is
  required while any Jev toggle above is on; clearing it in that case shows an error and the
  change is not saved.
* **Timeout** — a number field, 1–30000 ms.

Every field saves automatically as you edit it (debounced while typing) and applies to the next
Jev request — no restart needed. `jev.api_key_ref` has no Settings control and stays
config.yaml-only. Turning a Jev toggle on while `jev.model` is blank shows an error and the
toggle change is not saved.

## What is sent to TypeSafe

`jevTurnEndAssessment` and `jevAcceptanceCriteriaReview` are both live. `jevTurnEndAssessment`
sends the agent's role and the tail (trimmed to 6,000 characters) of its last assistant message
to TypeSafe, and nothing else from the transcript. It runs only for idle interactive agents —
plan agents and conversations — whose transcript is a claude-code JSONL or a codex rollout; every
other harness kind is `unsupported-harness` and never reaches Jev. `jevMemoryRelevance` is not
yet called by anything; turning it on today sends no request.

Turning a toggle on sends the following data:

| Toggle | What it sends |
| - | - |
| `jevTurnEndAssessment` | Sends an agent's last message (trimmed to 6,000 characters) and its role to TypeSafe to classify why the agent stopped. |
| `jevAcceptanceCriteriaReview` | Sends the id and title text of each acceptance criterion of the plan's non-cancelled items to TypeSafe at plan finalize, for advisory warnings. |
| `jevMemoryRelevance` | Sends your prompt and up to 20 memory snippets (about 600 characters each) to TypeSafe to drop irrelevant memories before injection. |

The same text appears under each toggle in Settings.

Acceptance-criteria text can quote issue text that anyone wrote in a public tracker, so Overdeck
treats the Jev result as advice only: it prints warnings and never blocks plan finalize.

## Turn-end classification

`jevTurnEndAssessment` (PAN-4371) reads why an idle interactive agent (a plan agent, or a
conversation) stopped talking without opening a modal or asking through a tool call. Jev classifies
the message into one of five kinds — `asks_operator`, `reports_complete`, `reports_blocked`,
`progress_update`, `other` — and separately answers whether the message needs an operator answer.
Three of the five kinds replace the generic "Answer the agent" label with a specific one on the
Needs-you row and on a parked `idle-running` row: **Asked you a question** (`asks_operator`),
**Reported done** (`reports_complete`), and **Blocked** (`reports_blocked`); `progress_update` and
`other` keep the generic label.

A classification is shown only when Jev's confidence in the chosen kind is at least `0.7`
(`TURN_END_MIN_CONFIDENCE`) — below that, nothing is attached and the row reads exactly as it did
before this feature existed. Nothing is persisted: the result lives only in an in-process, mtime-keyed
store that a restart clears, and it is read back on the next poll tick or parked-population read.

**Readiness:** advisory; accuracy under measurement. The 2026-09-29 measurement against a 40-row
labeled fixture (`evals/jev-turn-end.eval.ts`, model `jev-1.13-free`) put `asks_operator` precision
at 0.7778, recall 0.875 — below the 0.9 bar this feature would need to be called ready. See
`evals/README.md` for the full per-class table.

## Privacy

On the direct route, requests go straight to TypeSafe AI. On the Zen route, they go to OpenCode
Zen, which forwards them to TypeSafe. TypeSafe states that it does not train on customer data.
Zero data retention is available only on TypeSafe's enterprise plan.

Overdeck never logs the API key or the request body. The client pins the SDK log level to `warn`,
which also overrides a `TYPESAFE_LOG_LEVEL=debug` environment variable.

## Cost

Jev costs \$0.042 per million input tokens, and output is free. `jev-1.13-free` records \$0.

Every real request (not a repeat served from Overdeck's in-process memo) appends one event to the
cost ledger with the source `background:<feature>`, for example
`background:jevTurnEndAssessment`. The 24-hour spend appears next to each toggle in
Settings → Background AI.

## Usage readout

The Jev settings panel also shows, per feature: **calls in the last 24 hours**, the **last call
time**, and the **last error** (failure reason and HTTP status, if any) — so you can see whether
Jev is actually doing anything without reading logs (PAN-4508).

That readout is built from a plain-text usage log: every real (non-memo) Jev request appends one
JSON line to `~/.overdeck/jev/usage/<UTC date>.jsonl`, with the time, feature, outcome
(`answered` or `failed`), failure reason and HTTP status (on a failure), model, and request
duration. The log never records the API key, the text sent to Jev, the answer, or an error
message. A repeat served from the in-process memo is not counted — it made no request.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.