myjev · a personal Jevdeemwar · 2026-09

Build your own Jev from your agent logs

A small model on your own machine that judges an agent's work the way you would: would you accept this turn, did the agent stop short, how would you react. It is trained on nothing but your own Claude Code and Codex history, and it answers in about 60 ms on a laptop CPU.

1. What you get, and what you don't

A Jev-style model is a cross-encoder: it reads a state (here: your request plus what the agent said and did) and a hypothesis (a question with one answer filled in), and returns how strongly the state supports it. Asked the right way, that is a judge. Trained on your reactions, it is your judge.

Judge a turn

Would you accept it as is? Did it stop short or hand work back? Accept / redirect / reject / stop? How satisfied, 0–4?

Pick like you

Given options, which one you would choose, with probabilities and a confidence you can threshold.

Route like you

Which skill or tool an agent should reach for first, learned from what your agents actually did.

What it is not. It never writes text: it scores and chooses. And it is not a safety gate: your logs contain almost no denied actions, so it cannot yet tell a dangerous command from a safe one. Keep permission prompts for that.

2. The Jev contract in one minute

Every question becomes one entailment check per answer, with the state as the premise. The hypothesis is the instructions plus one criterion: trim(instructions) + " " + trim(criterion). Three answer types come out of the same forward pass:

TypeAsked withAnswered with
Noulinstructions + a true and a false criterionnoul: a probability in [0,1]
Choice2+ options, each a descriptionchoice, probabilities (P(entailment) normalised over options), confidence
Scoreordered levels, lowest firstscore (expected level), legend, probabilities, confidence

Confidence for n options is clip((n·p_max − 1)/(n − 1), 0, 1): 0 at a uniform guess, 1 when one option takes everything. The HTTP shape is the System One one (POST /v1/systemone with a state and a map of typed questions), so any client written for it works against your local server by changing a base URL.

3. The pipeline

Your agent logsExtract decisionsHindsight labelsRows + merge Smoke gate (CPU)GPU runKeep-or-drop gateServe + use Claude Code + Codex jsonlrequest · proposal · reactionsmall-model ensemblesoft targets, balance every stage, tiny samplerent · train · pull · destroyAUC on your future logsONNX · hook · CLI · skill dropped? change one thing, run again
Everything left of the GPU runs on a laptop and one CPU box; the GPU is rented per run and destroyed automatically.

4. Turn logs into decisions

Claude Code keeps every session as JSONL under ~/.claude/projects/; Codex keeps its own under ~/.codex/sessions/. One decision event is one agent turn:

The model's input (the state) is only request + proposal, rendered exactly the same way at training and at serving time, trimmed to a 440-token budget (actions first, then agent text, then request):

Request: fix the typo in the README heading
Agent: Fixed and verified. README.md line 1 now reads "Installation". grep returns nothing.
Actions:
- Edit README.md: # Installation
- Bash: grep -n Instalation README.md

Keep everything. Scheduled and templated prompts are your instructions too, and bot turns you let stand are decisions. Tag them origin = human | automated for weighting instead of filtering them out. Redact secrets (known vault values plus key/token/password shapes) and check every file with a secret scanner before it leaves the laptop.

5. Hindsight labels

The trick is to label with hindsight, not taste guessing. A labeller model reads the turn and your actual reaction, and reports what you decided. The model then learns to predict that decision from the turn alone.

Question (trained text, versioned)TypeLabel the labeller gives
Would the owner accept this proposal as it is?Noulyes / no
Did the answer stop short, miss a part, or hand work back?Noulyes / no
Did the agent do more than asked?Noulyes / no
Does the owner agree with the plan / allow the refactor / accept the code?Noulyes / no / n.a.
How does the owner react?Choiceaccept · accept with changes · redirect · reject · stop
How satisfied is the owner?Score0 frustrated … 4 delighted

6. Rows, soft targets, balance

Each labelled question becomes training pairs (state, hypothesis) → [P(entailment), 0, P(contradiction)]: the true criterion with p, the false criterion with 1 − p; a Choice or Score becomes one row per option with that option's vote share. Training minimises log loss against these soft targets, so the model learns your uncertainty too, not just the majority.

Two things we added after the first runs:

7. Open data that is safe to add

Public Jev-style datasets help the general heads (routing, reading documents, code review), not your taste. Add them with generic wording ("a reviewer accepts this code"), never with your personal question texts: only your logs may speak for you. Vet the provenance of every set; several popular ones are distilled from a commercial Jev and must not be used.

DatasetUseWhy it is safe
ZefanCai/Open-Jev (+ v1.1)typed decisions, routing, browser actionsCC0 synthetic, human-audited; v1.1 adds WANLI (CC BY)
Praveenrajus/jev-bench22 human-labelled sets recast as choice/noul/scorehuman labels and human vote distributions
tasksource typed decisionsbroad decisionslabels from established datasets; filter to commercial licences
tasksource proceduralrule-followinganswers computed from rules, Apache-2.0
JevForge-Mind2Webweb-agent actionsMind2Web human annotations, CC BY 4.0
jev-decisions-v1which tool the agent calls nextderived from public agent trajectories, CC BY 4.0
github-codereviewcode accepted as written vs changed after reviewhuman reviewers only

Excluded after reading the cards: a distillation corpus whose card states its teacher is a commercial Jev, two benchmarks that ship a commercial Jev's predictions, sets labelled by an unnamed teacher model or by a closed LLM, and the distilled rows of an otherwise human-labelled mixture. In the sets we used, mind duplicated option texts (identical hypotheses with opposite labels) and cap each source so none dominates.

8. Training on a rented GPU

The recipe is deliberately boring: microsoft/mdeberta-v3-base (multilingual, licence-clean), max length 512, 2 epochs, AdamW 2e-5, bf16, plus ~51k general NLI rows replayed so it does not forget how to read. About 330k training rows; one run is ~650k–840k examples.

  1. Smoke on CPU firstEvery training stage on a tiny sample (teacher, export, eval, benchmark), on any CPU box. The launcher refuses to rent a GPU without a passing smoke.
  2. Dry runCounts the rows, confirms your personal rows actually made it into the merge, prints the estimate and the cheapest suitable offer. Rents nothing.
  3. Rent, upload, preflightCheapest verified GPU under a price ceiling; attach your SSH key; upload scripts and data with sha256 checks; preflight checks CUDA, disk, RAM and GPU memory at the run's real shapes, then runs the smoke again on the GPU.
  4. Train, export, evaluateTeacher training, fp32 ONNX export with an ONNX-vs-PyTorch agreement check (0 flips on 300 pairs), evaluation on your held-out logs and a public benchmark.
  5. Pull, then destroyA finisher pulls the results (weights in 8 parallel byte ranges, sha256-checked) and destroys the box.
GPU (vast.ai, verified)$/hMeasured / estimated speedOne run
RTX 4090, random batches0.4069 ex/s (measured)~4–5 h, ~$1.7
RTX 4090, length-bucketed batches0.4091 ex/s (measured, +32%)~3 h, ~$1.25
RTX 50900.41~135 ex/s (estimate)~2.3 h, ~$0.95
H100 SXM1.5–1.7~250 ex/s (estimate)~1.3 h, ~$2.2

Length bucketing is the cheapest speed-up we found: shuffle, then sort each window of 100 batches by length so a batch pads to similar lengths, then shuffle the batch order again. Same recipe, a third faster. Moving the export's agreement check from CPU to the GPU saved another hour of paid idle time per run.

9. Don't lose money on idle GPUs

Every dollar we wasted came from a finished or broken box that nobody destroyed. Four layers, each covering the one above:

  1. An EXIT trap in the launcherIf anything fails before the job starts, the box is destroyed. Use EXIT, not ERR: bash skips ERR traps for failures inside functions, and that once left a box idle for 4.7 hours.
  2. A finisher, detached from your terminalWaits for == DONE (or a failure marker), pulls, destroys. Start it in its own session (setsid); a finisher started from an agent's shell dies when the session restarts, and the finished box bills on.
  3. A watchdogmin($ cap, 2 × estimate + 30 min), then destroy no matter what. A dollar cap alone is a 10-hour leash on a cheap GPU.
  4. A reaper serviceA launchd job every 5 minutes, independent of any session: restarts a dead finisher on a finished job, destroys a box whose GPU sat idle 45 minutes without one, and anything older than 10 hours. Plus caffeinate -w <finisher pid>: a sleeping laptop pauses finishers and sleep timers alike.

10. Evaluate on your own future

The only number that matters is how well the model predicts your later sessions. For each question, take the true-criterion rows from the held-out (latest) sessions and compute the AUC of P(entailment) against what actually happened. Then keep or drop each new version with one rule:

KEEP  if the mean AUC over your personal questions rises
      and no strong question (AUC ≥ 0.85) drops by more than 0.01
DROP  otherwise; change one thing and run again

Accuracy lies on lopsided questions; AUC doesn't. And look at the base rates: a head at 0.985 accuracy on a question that is 99% "yes" has learned nothing.

Calibrate after the gate (per-question temperature, fitted on half the held-out logs and kept only where the other half's calibration error falls). It is free and needs no retraining; the server applies p' = sigmoid(logit(p)/T) per question.

11. Serve it on CPU

Export fp32 ONNX (model, tokenizer.json, config.json, calibration.json) and serve it with any System One compatible server on ONNX Runtime. On a recent laptop CPU:

RequestLatency
one yes/no question (2 pairs)~60 ms p50
five owner questions (16 pairs)~410 ms
throughput, 8 concurrent~19 req/s

12. Put it to work: hook, CLI, skill

A Stop hook that judges every agent turn

A global Claude Code Stop hook rebuilds the last turn with the same parser and state format as training, asks P(accept) and P(wanted more), and, in block mode, sends the agent back with a specific reason:

myjev (the owner's decision model): the owner would likely NOT accept this as it is (P(accept) 0.07):
verify the result and show the evidence; the owner would likely want MORE (P 0.70): finish the missing
part yourself instead of handing steps back. If this is already right, say so briefly with the evidence and stop.

A CLI

myjev hook install --mode shadow     # add the Stop hook (backs up settings, touches only its own entry)
myjev hook uninstall                 # remove it, other hooks untouched
myjev hook mode block                # shadow | block | off
myjev hook review                    # verdicts next to what you said next
myjev judge --request "..." --proposal "..." --action "Bash: go test ./..."
myjev ask "Which should the agent do next?" --context "..." \
  --option "stop=Stop and report, wait for my call" --option "run=Start the paid run now"

An agent skill

A skill tells every agent when to consult the model: judge your own turn before handing back; before asking the human "A or B?", ask the model and act only on a confident answer (choice confidence ≥ 0.6, yes/no P ≤ 0.2 or ≥ 0.8), otherwise ask the human and mention the model's lean. Never as a safety gate.

13. Results so far

First version, held-out on the latest sessions (AUC of P(entailment) against what really happened):

QuestionAUCVerdict
Did the agent stop short / hand work back?0.96use it
How satisfied is the owner?0.96use it
How does the owner react?0.90use it
Which skill should the agent load first?0.88use it
Would the owner accept this as it is?0.87use it
Which tool first? / did the agent do too much?0.78 / 0.76weak
Would the owner allow this action?0.71weak: 99% of logged actions were allowed
Plan agreed / refactor allowed / code accepted0.63 / 0.54 / 0.49not learned yet (few "no" examples)

The clearest thing it learned is a taste for evidence. The same one-line fix scored P(accept) 0.007 as a bare "Fixed X" and 0.995 with the grep that proves it. Its clearest shortcut: a long list of actions reads as "did the work", so scope creep with many tool calls still scores high. Balancing alone (second version) helped five questions and hurt three, and failed the gate; the next versions add the vetted open data aimed at exactly the weak questions.

14. Rules we would not break

15. Lessons that cost money

What happenedCostThe rule now
The rented box got the provider account's SSH key, not the one in the agentbox unreachable, idleattach your agent's key to every box
Cleanup on an ERR trap that never fired inside a function4.7 h idle, ~$2cleanup is an EXIT trap
cd dir && job & over ssh held the connection openfinisher never startedcd dir; nohup job > log 2>&1 < /dev/null &
Finisher and watchdog started from an agent's shell~55 min idle after DONEdetach them; a reaper service as backstop
A hand-built staging dir missed a data source, and "missing" was grepped awaya run without 1,200 rowsone build script; the merge exits on any missing source
The tokenizer file truncates to 512 by defaultevery length cap silently wrongpin a tokenizer with truncation off
An int8 model looked 18% faster70% of answers flippedalways check agreement against fp32
A hook blocked on a CPU-starved server2–9 s added to every agent stopshadow scoring runs detached

Start this weekend

  1. Count your decision events (a few thousand turns is enough to start).
  2. Extract turns and redact secrets; check every file.
  3. Label with two or three small models and a dollar cap; add a bigger model only on their conflicts.
  4. Build rows with soft targets and a time split; smoke every stage on a CPU.
  5. One GPU run behind a watchdog and a detached finisher (about $1).
  6. Gate it on your latest sessions by AUC; serve it locally; put the hook in shadow mode and watch.

Then the loop that makes it better: every day of your normal work becomes new labelled data about you.