system-one · working notes · ~/code/system-one · September 2026

system-one: rebuilding Jev in the open

Kahneman called System 1 "a machine for jumping to conclusions." Typesafe built one — Jev answers typed questions about text with calibrated probabilities instead of generated prose — and published no paper on how it works. system-one (the name is Kahneman's own term for the faculty it tries to be) reconstructs that behavior from public evidence on small open models, on a Mac, one measured experiment at a time: a machine for jumping to conclusions, carefully. The end state is a two-tier lineup — a 2.5B quality model quantized to 8-bit and a 0.6B volume model, both frozen, calibrated, and drop-in compatible with the official SDK. This page is the result, the mechanism, and the story — including what broke.

state "I've been charged twice for my flight to Berlin… I want my money back immediately." questions 3 output tokens 0
refund_requested · noul
yes0.68
no0.32
request_type · choice
refund0.99
rebooking0.01
information0.00
frustration · score (0–2)
calm0.07
annoyed0.15
angry0.78
Actual output of the 0.6B volume tier for this request (values rounded) — reproducible with the README quickstart's curl. Every valid question gets an answer; there is no generation step that can fail or drift off-format.

Why it matters

Software runs on decisions, not prose

The name is the thesis. Jev is named for the Jevons paradox — the economist W. S. Jevons's 1865 observation that when steam engines got more efficient, Britain burned more coal, not less: make a resource cheap enough and you don't save it, you find a thousand new uses for it. Machine judgment is that resource now. Cut a decision's cost from an LLM call — seconds, cents, a prompt to parse — to one forward pass at ~10 ms, and you don't automate the same decisions cheaper; you discover the millions of micro-decisions that were never worth automating at all.

Because most of what automation actually does is decide: route this ticket, flag this transaction, escalate this case, block this content, approve this claim. The output that matters is a branch condition, not text for a human to read. Speed is the visible benefit of a System One model — but four other properties are what make it fit for decision-taking systems where an LLM is the wrong tool:

uncertainty you can budget on
Thresholds set by cost of error
A calibrated probability lets the business choose its error tolerance and get the corresponding automation rate — automate above a threshold, confirm in the middle, escalate below. An LLM saying "I'm fairly confident" is a phrase; 0.94 with known calibration is a budget line. That's the risk–coverage curve below.
auditable by construction
Every decision is a logged, typed record
Same question, same state, same distribution — decisions can be replayed, regression-tested, monitored for drift, and explained to a regulator. Fraud, claims, moderation, and compliance workflows need this before they need eloquence.
cheap enough to embed everywhere
Judgment inside the loop, not around it
At ~10 ms and fractions of a cent, a judgment can sit inside every guardrail check, every agent tool-route, every queue item — millions of micro-decisions a day where an LLM's latency and cost per call make it structurally impossible.
logic stays in code
Atomic questions, composed by software
The model answers narrow, well-scoped questions; the workflow — weights, priorities, side effects, who gets escalated — stays in reviewable code and changes without retraining. Delegate the judgment, never the policy.

Where this shape of model earns its keep: ticket triage and intent routing, fraud and claims operations, content moderation queues, compliance screening, escalation gates, and — increasingly — as the fast decision layer inside agentic systems, where a large model plans and a System One model adjudicates every small step. Eight of these patterns ship as runnable examples in the repo — each with the real output of five systems, from the bare backbone to pinned Jev itself, including the honest misses.

Eight examples, five systems

correct answers per example against authored intended answers — 24 questions, an illustration, not a benchmark

Example2B base
(no FT)
0.6B FT2B FT2B FT q8
(served)
Jev 1.13.0
citation-check0/20/22/22/21/2
claims-intake3/43/44/44/44/4
lead-scoring3/31/33/33/33/3
llm-guardrail2/32/32/32/33/3
model-routing2/33/32/32/33/3
moderation2/33/33/33/33/3
rag-rerank2/22/22/22/22/2
support-triage3/43/44/44/44/4
Total17/2417/2422/2422/2423/24

The ladder reads left to right: fine-tuning is worth +5 questions on the same 2B backbone, 8-bit quantization costs nothing, and pinned Jev leads by one. The single questions each side misses are telling: Jev is the only system that catches the prompt injection; the fine-tuned tiers are the only ones that catch a citation that overreaches its source — which Jev waves through. Raw outputs, requests, and the scoring script are all committed in the repo.

…and why an open, self-hosted one matters to an enterprise

the data never leaves
Decisions run on your most sensitive records
Tickets, claims, transactions, HR cases — the states being judged are exactly the data that residency rules, client contracts, and internal policy keep inside the perimeter. A self-hosted decision layer removes the third-party API from the path entirely.
the function can't change under you
Frozen weights, not a moving alias
Hosted model aliases get upgraded and deprecated; thresholds calibrated last quarter silently mean something else. Owned weights with pinned temperatures make the decision function immutable until you change it — with an audit trail (this project binds calibration artifacts to weight hashes for exactly that reason).
auditable to the bottom
From decision back to training row
Risk and compliance can inspect the whole stack: training data provenance, corpus hashes, the decision log of every recipe change, reproducible evaluations with confidence intervals. An API is a black box with an SLA; this is a system of record.
customizable by fine-tuning
Teach it your rubrics, your policies, your edge cases
A hosted decision API answers with someone else's judgment. An open model learns yours: recast historical decisions into training questions, generate synthetic scenarios for the edge cases your queues actually see, distill from any teacher you trust, and refit calibration on your own outcomes. The entire loop in this project — data build, LoRA fine-tune, temperature fit, frozen evaluation — runs in about an hour per iteration at 0.6B scale, on one machine.
owned economics
Pay hardware, not tokens
At millions of decisions a day, owned capacity at ~10 ms per decision beats per-token metering, rate limits, and someone else's outage window. The unit cost of a decision approaches electricity.

The result

What the finished models do

Two tiers came out of this project, each judged on a reserved test it had never influenced. First, the volume tier: after freezing the recipe, the original reserved partition — 1,048 questions never touched by any training, tuning, or selection decision — was spent exactly once on the 0.6B model:

77.6%
accuracy · untouched test
0.049
calibration error (ECE)
1,048
questions, one look, spent
~10 ms
per decision · volume tier, local Mac

Accuracy by primitive

final test, temperature-scaled

noul84.7% · n=424
choice80.6% · n=464
score50.0% · n=160

Calibration error by primitive

lower is better · scale 0–0.15

noul0.045
choice0.051
score0.130

What calibration buys: automate the confident share, escalate the rest

each point is a confidence threshold; hover for detail — the marked point is the natural operating range

0%5%10% 15%20% 0%25%50% 75%100% coverage — share of decisions automated error rate among automated t=0.90 → 51% automated, 4.8% errors t=0.95 → 40% at 2.8% t=0.99 → 12% at 0.8%

Measured on the spent test's predictions. Thresholds are in-distribution numbers; they do not transfer to shifted workloads (a measured finding — see the ledger). Confidence is top-1 probability, not a probability of correctness.

Context: the development-set numbers are 82.0% / ECE 0.020, so the untouched test costs ~4 points and doubles the calibration error — a realistic in-family transfer gap. Earlier 3B experiments reached 91% argmax agreement with the real Jev on held-out sentiment, within 2–3 accuracy points of Jev itself. Served locally, a 12-question request answers in ~121 ms end-to-end.

The scale-up: same frozen recipe, 4× the parameters

MiniCPM5-2B-Base — development numbers, deliberately not comparable to the spent-test headline above

86.8%
dev accuracy (+4.8, CI [+2.7,+7.0])
0.018
dev ECE — no calibration tax
0.673
score accuracy (was 0.562)
2.2%
confident errors @≥0.9 (was 4.8%)

The one number that resisted every 0.6B intervention — score — moved decisively (MAE 0.564 → 0.435). Serving is measured too: a light 3-question request answers in 358 ms at BF16, 195 ms quantized. The dev win was later confirmed on a fresh reserved test the model had never influenced: +6.8 accuracy points over the 0.6B, CI [+4.5, +9.2] — see the timeline for the full story of that test, including the calibration criterion it narrowly missed.

Quantized for serving: q8 keeps everything, at half the size

the fused 2.5B winner converted with MLX — full dev battery, drift gates at three precisions, 16-case HTTP serving sweep

2.5 GB
weights (BF16: 4.7 GB)
1.61×
median serving speedup
0.018
dev ECE — unchanged
0
flipped answers, drift gate

Dev accuracy 86.6% vs 86.8% BF16, confident-error rates unchanged. 4-bit was measured too: 1.3 GB, but −1.4 accuracy points and no speed advantage over 8-bit on this hardware — it earns no tier of its own. The adoption gate is now closed (decisions 27–28): temperatures were fitted fresh under the q8 weight identity (choice 0.96, noul 1.07, score 1.39 — the score correction was real), the calibrated battery held with confident errors improving to 1.2% at t≥0.95, and the official TypeScript SDK smoke test passed against the q8 server, which reports the temperature hash in its identity endpoint. q8 is the quality-tier serving configuration (decisions 28 and 30). SemIf independently flags the same class of issue on its quantized 27B bridge; our drift gate and identity-bound calibration measure it instead of footnoting it.

The adopted lineup

decision 30 — each tier judged once on a reserved test it never influenced

TierModelWeightsUnbiased resultLight request p50
QualityMiniCPM5-2B, fine-tuned, fused, 8-bit2.5 GB+6.8 pts over volume tier on the fresh out-of-family test, CI [+4.5, +9.2]195 ms
VolumeQwen3-0.6B + LoRA, frozen recipe1.4 GB + 33 MB77.6% / ECE 0.049 on the in-family reserved test77 ms

Recorded honestly: the quality tier's confirmation gate asked for calibration error ≤ 0.08 on the fresh test and measured 0.0803 — a miss by 0.0003, inside the estimator's own noise, applied as written. The adoption therefore rests on an explicit judgment entry citing that near-miss, not on the pre-registered gate. The two tests use different data (in-family vs out-of-family), so the tiers' absolute numbers are not comparable to each other. Confidence thresholds for both tiers are valid in-family only until shift-robust calibration lands — the measured reason is in the ledger.

The key idea

How this differs from calling an LLM

An LLM and a System One model can be the same network — what changes is what you take from it. An LLM generates text token by token and you parse what comes out. Here, nothing is ever generated: one forward pass, then read the probability the model assigns to each allowed answer, directly from its output layer.

LLM call
  • Prompt with instructions + format demands"Respond ONLY with valid JSON…"
  • Autoregressive generation, token by tokenlatency scales with output length
  • Parse the text back into datacan fail: wrong format, invented labels, refusals
  • Ask for a confidence, get more text"I'm 90% sure" is a phrase, not a measurement
System One call
  • State + typed questions with the allowed answerschoice options, score levels, or yes/no
  • One forward pass, zero tokens generatedread logits at the answer position
  • Softmax restricted to the allowed answersevery output is answer-shaped by construction
  • The distribution is the confidencetrained toward calibration: 0.8 should be right ~80% of the time
choice
Which of these options?
Up to 255 named options → distribution + top choice + confidence. Routing, classification, intent.
score
Which level on a described scale?
2–10 ordered levels → distribution + probability-weighted score (fractional, e.g. 1.3). Severity, satisfaction.
noul
Is this statement true?
One number: P(yes) ∈ [0, 1]. A 0.5 means genuine uncertainty, not "medium".

The frozen recipe

What's actually inside

Backbones
One frozen recipe, two tiers: Qwen3-0.6B base + LoRA (volume) and MiniCPM5-2B base + LoRA, fused and quantized to 8-bit (quality) — attention-projection LoRA on Apple MLX. Wire-compatible server: the official Typesafe TypeScript SDK runs against both unchanged (smoke-tested, not certified).
Readout
Versioned prompt templates; the answer is a softmax over the allowed answer tokens at the final position. Multi-question requests can share one pass over the state (opt-in, FP32-gated).
Loss
Cross-entropy against a target distribution — a proper scoring rule — plus a Ranked-Probability-Score term on ordinal questions, adopted from Laya's published RLCD recipe after it measurably fixed score error on two backbones.
Data
8.7k questions recast from public datasets + 1.8k synthetic scenarios (cheap generator writes diverse states and rubrics; a pinned Jev version supplies the probability targets), filtered for teacher overconfidence, hash-verified, split by content groups so near-duplicates can't leak.
Calibration
Per-primitive temperatures fitted only on a dedicated calibration split, pinned to the exact weight hashes and fail-closed on any provenance mismatch. Both tiers fit near 1 (0.6B: 1.02–1.16; q8: 0.96–1.39) — calibration is trained in, and the fit is a trim, not a rescue.

The story

Five days, measured

Every step below is a frozen-protocol experiment with grouped-bootstrap confidence intervals; amber dots are the setbacks, kept on the record because they changed the plan.

The honesty ledger

What broke, and where it stands

Score is the weak primitiveOPEN
50% accuracy on the 0.6B final test. Scale moved it — 0.673 accuracy / 0.435 MAE at 2.5B (dev) — but the targeted patch pass came back a clean null: at 2.2% confident errors there was nothing left for kev's technique to fix. Still the weakest primitive everywhere — 53.8% on the fresh out-of-family test (vs 48.1% for the 0.6B); further movement likely needs better data, not more passes.
Calibration doesn't survive distribution shiftPARTIAL FIX
Quantified on fresh gold data: out-of-family confident errors hit 14–19% at t≥0.9 versus ~2% in-family. First fix measured: fitting a temperature on just 100 labeled decisions from a workload's own traffic cut aggregate confident errors to 3–4% — and on one workload the model was underconfident, so the fit nearly tripled safe coverage instead of shrinking it. Where miscalibration isn't a scalar (two of four workloads), a temperature is a no-op; those need abstention. Still open, now with a measured path.
The rubric benchmark was seed noiseRETIRED
42 hand-written cases swing ±6 correct answers on initialization alone. All accuracy claims made on it were withdrawn; it survives as a regression canary only.
Half the synthetic score rubrics weren't scalesFIXED FWD
A judge audit found 54% presented categories as "levels". The generator now requires a declared monotonic dimension — verified on the fresh patch batch, where ordinal rubrics rose from 46% to 80%. Retroactive exclusion was tested and measurably unnecessary.
The teacher is overconfident on missing evidenceFILTERED
A third of missing-evidence scenarios got near-certain answers from Jev itself. Those rows are filtered from training — except where the confident answer was an explicit "cannot determine", which is correct behavior.
Fast batching drifts at low precisionGATED
Shared-state execution showed batch-shape-dependent BF16 drift (one flipped answer). It's opt-in and FP32-only; measured drift at the API is now < 7×10⁻⁶.
255-option readout passes tests, fails realityOPEN
The experimental per-candidate readout scored 0/30 on a real 77-way task with near-uniform predictions — capacity is not competence. Needs a matched-compute rerun before scaling.
Agreement with a teacher ≠ correctnessOPEN
Synthetic evals measure fidelity to jev-1.13.0's judgments. An independently adjudicated workflow benchmark with error costs remains the gate for any "safe automation" claim.

The ecosystem

Where this sits among the Jev clones

ProjectBackboneTrained?Calibration measured?Distinguishing trait
jeff400M encoderno (zero-shot)global temperatureAPI server packaging
kev0.8B–9B family + pointer headyes, incl. targeted second passesyes, temp-scaled9B trails Jev by 3.5 pts on their suite
Nimble9B logit readoutyes, contrastive datanominimal-pair curation
Laya421M bidirectional encoderyes, RLCD (published)partially13ms latency; 512-token ceiling
openjevDiffusionGemma 26B-A4Bno (strong base, zero-shot)unknowndiffusion readout; free hosted tier; images
SemIfQwen3.5-4B frozen (also 0.6B, MiniCPM)no (frozen checkpoints)post-hoc, per workload4 runtimes incl. browser WebGPU; per-row provenance
system-one (this project)0.6B + 2.5B logit readoutyes, frozen protocolprimary metric, with CIsteacher distillation + audited retractions

Jev itself (~83% MMLU-Pro per black-box probes, 64k context) implies a far larger backbone — the competition here is on calibration, cost, and self-hosting, not frontier reasoning. SemIf is the closest cousin — same readout, same reproducibility instincts, even the same backbones — with one decisive difference: it never trains. Its frozen 4B needs temperature 2.5 to drag calibration error from 0.21 to 0.07 post-hoc; our fine-tuned models fit temperatures of 1.02–1.16 because calibration is trained in. That gap is this project's whole thesis.

Roadmap · as of September 2026

What's next

Snapshot at v0.1.0 — the living roadmap is docs/ROADMAP.md in the repo.