Skip to content

[Engine] Jev System One decision endpoint (/v1/systemone): typed decisions with calibrated probabilities - #2639

Closed
justindressler wants to merge 42 commits into
Niko1221:mainfrom
justindressler:jev-port
Closed

justindressler wants to merge 42 commits into
Niko1221:mainfrom
justindressler:jev-port

Conversation

@justindressler

@justindressler justindressler commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Problem and result

Problem. Strata can dump logprobs for verification, but there is no per-request way to
read the logits of arbitrary label tokens at the final position. Without that, the engine
cannot serve a System One decision contract — a caller that wants a typed answer with a
calibrated probability (noul yes/no, choice pick-one, score ordinal) has to make the
model generate prose and then parse it, which is slow, unparsable in the failure case, and
gives a confidence the model chose to write rather than a number the caller can threshold.

Result. An opt-in engine wire (--jev-brow) that returns the final-row logits for
exactly the label tokens asked, plus a serve-layer POST /v1/systemone endpoint that applies
the Jev readout math and per-tuple post-hoc calibration (Platt for noul, temperature for
choice/score). One decode step produces a typed answer with a probability and a margin;
the same model keeps serving chat, can answer decisions inside a chat call, and can decide
then narrate. Everything is gated by STRATA_JEV_MODES; with it unset, the process behaves
exactly like stock Strata (a decision surface that is not enabled returns 404, so probing
learns nothing).

Related discussion

  • No issue or scope agreement exists for this one: it is a direct port of the jevcpp
    reference implementation's wire and math onto the Strata engine. Opening it as a PR rather
    than asking first is deliberate, and a maintainer can redirect it to an issue if that is
    the preferred shape.
  • @TwoAnts commented in this thread that reading jev to check the stop token was something he
    had considered — that is the same readout, used for a different purpose.
  • Prior close: 2026-10-19 tracker reset for 0.2.0-beta, not a content rejection. Reopening
    through /reopen.

Approach

  • Engine (additive, 5 files, +149 lines): Verifier::brow_row in verify.hpp/.cpp plus
    the --jev-brow flag; final-row logits for a supplied token list, fail-closed on any
    mismatch. No change to existing decode paths.
  • Serve: /v1/systemone with the donor's error contract (422 +
    {"error": {"field": ...}}), the frozen D3 prompt block, and readout math ported from
    jevcpp. Calibration is post-hoc and argmax-preserving, per tuple (mode|qtype|set), hot-
    swappable through POST /admin/calib, with donor-schema log rows for the offline fit.py.
  • Mode gating: STRATA_JEV_MODES=chat,decision (default for the jevport presets),
    decision alone, or unset for stock behaviour; unknown tokens refuse to boot.
  • Compatibility: no wire change to /v1/chat/completions unless "jev" is present; no
    new default; model format unchanged. Divergences from the donor plan are listed in §4d of
    the detail below, each with the reason.

Validation

Revision: branch jev-port head fbffc99a, base 296b59d2 (v0.1.43 lineage).
Environment: RTX 3090 24 GB, QFN = Qwen3.8-Flash-Next IQ3_XXS MoE, 32k ctx, calibration
tuple p-jevcpp-qwen38-27b|q4_k_xl|timber|v1|V|all.

Passed:

  • Jev unit suite (mock engine) 73/73; full serve/discovery run 858 executed, 0 failed,
    11 skipped
    .
  • Concurrency: 7 clients × 3 questions FIFO-serialized, zero cross-talk observed.
  • Calibration A/B on held-out items, offline replay of identical prompts: per-tuple accuracy,
    NLL and ECE15 pre→post — table in §4a below.
  • Head-to-head against the donor's own benchmark (same three tasks, different model and
    quant): §4b below.
  • Warm single-client performance, n=10 per cell (p50 / p95 / rps): §4c below.
  • Live responses captured for text, image-direct, decide-then-narrate, multi-question and
    inline-chat shapes: §2 below.

Failed:

  • none observed on this revision.

Not run:

  • Re-validation on current main (v0.2.1.4, 9de04cd4). This branch is 42 commits behind
    and mergeable_state is dirty, so a rebase is required before the numbers above can be
    re-claimed on the current tree. Queued next.
  • HIP and SYCL builds — only CUDA was built and executed.
  • Any GPU other than the RTX 3090, and any model other than QFN.

Limits

  • Calibration is per model and per quantization; the shipped tuples are for
    QFN/IQ3_XXS/32k. Another model or quant needs its own refit before the probabilities mean
    anything — the PR ships the fitting path, not universal numbers.
  • Multiple questions against one state cost roughly one readout each until prefix reuse
    lands (that is the separate suffix-reuse PR, [Engine] suffix-reuse: conversation KV prefix mount, quant-safe splices, state checkpoint ladder #2351).
  • image_mode: direct reads raw image embeddings; it was validated on the QFN vision path
    only.
  • Deliberate gaps against the donor plan are enumerated in §4d, not silently dropped.

Background and design detail

What a System One decision model is. Most uses of a language model are
"System Two": the model writes text and the caller reads, parses and trusts it. A
System One decision model does the opposite. It receives a state (text, JSON, or an
image) and a set of typed questions, and returns typed answers with calibrated
probabilities
: a yes/no (noul), a pick-one (choice), or an ordinal rating (score).
It never generates prose to decide. Nothing has to be parsed, and the confidence is a number
the caller can threshold, route on, or log, rather than a sentence the model chose to write.
That makes it suited to fast, repeatable, auditable decisions inside a loop: routing,
guardrails, triage, scoring, and game or agent control.

Jev. "Jev" is TypeSafe's commercial System One decision API: POST /v1/systemone with
{state, questions}, answers read from token probabilities rather than generated text. Its
request/response shape is the wire this work follows. Open implementations of the same idea
already exist (see References); the goals here are correctness, speed and honest
probabilities, not novelty.

Laya. Laya (convaiinnovations/laya, Apache-2.0) approaches the same contract with a
different mechanism: a small purpose-trained encoder (ModernBERT-large, 421M parameters;
non-autoregressive) that answers all questions in one forward pass (~33 ms reported),
trained with reinforcement learning against strictly proper scoring rules (RLCD) so that
honest probabilities are what maximises reward. Two things in its documentation shaped this PR: its probabilities ship
over-confident until a temperature is refit per question type and option count
(reported mean ECE 0.466 → 0.081, with the instruction to do this on your own data before
trusting them), and its comparison against Jev uses third-party published Jev figures
that it did not measure itself. We kept the first idea (per-tuple calibration, refit on
local data) and measured our own numbers on our own harness. The mechanism differs: a
general LLM read at its label logits, with no task-specific training.

jevcpp. The reference implementation this port follows: a llama.cpp-based server that
serves the Jev wire from a generative model by reading the label logits at the final
prompt position (Qwen3.8-27B, with a shipped calibration file and a metamorphic/golden test
set). Its plan and amendments define the request contract, the frozen prompt template, the
readout math and the test strategy that this PR ports.

What this PR does. It brings that System One surface to Strata. Strata's engine could
already dump logprobs for verification, but had no per-request way to read the logits of
arbitrary label tokens. This PR adds an opt-in --jev-brow engine wire (BROW) that returns
the final-row logits for exactly the label tokens asked, and a serve-layer
/v1/systemone endpoint that applies the Jev readout math and per-tuple post-hoc
calibration
(Platt scaling for yes/no, temperature scaling for choice/score) on top. The
same model keeps chat, and can answer decisions inside a chat call, from an image directly,
or decide-then-narrate. It is opt-in per process (STRATA_JEV_MODES).

Donor reference: jevcpp on Qwen3.8-27B (q4_k_xl), shipped calibration tuple
p-jevcpp-qwen38-27b|q4_k_xl|timber|v1|V|all (T_choice 1.5861). This port runs on
QFN = Qwen3.8-Flash-Next IQ3_XXS MoE (RTX 3090, Strata engine v0.1.43-lineage, 32k ctx).

1. Features (the full jevcpp surface)

Feature Request Status
Core decision endpoint POST /v1/systemone {state, questions} — noul (yes/no), choice (letters), score (0-10 levels) ✅ live
Frozen D3 prompt byte-frozen question block (donor render, enable_thinking=false, verbatim string states) ✅ golden-tested
BROW readout --jev-brow engine flag; final-row logits, fail-closed ✅ engine commit
Calibration (M3.2) post-hoc, argmax-preserving: Platt (a,c) for noul, temperature for choice/score; per-tuple (L/V/D/S) files calib-<mode>.json; POST /admin/calib hot-swap; donor-schema log rows for fit.py ✅ live
V-mode (M3.1) header X-Jev-Mode: V — per-option yes/no branches, p = softmax(s_yes − s_no), name-keyed ✅ live
Image → decision (M3.8) image_b64 + image_mode: summary (vision → 160-tok summary → decide) or direct (raw image embeddings + question, ONE readout) ✅ live
Decide-then-generate (M3.9) "then": {"generate": {...}} — answers folded into the last user turn, one wire request ✅ live
Chat surface (M3.3) POST /v1/chat/completions with `"jev": {state messages, questions}`
Concurrency FIFO-serialized engine turns; 7 clients × 3 questions, zero cross-talk (tested) ✅ tested

Error contract: donor's 422 + {"error": {"field": ...}}. Streaming refused with the
jev extension, state XOR messages, image_mode validated, D+V refused with 422.

2. Usage

# text decision (one decode step)
curl -s $URL/v1/systemone -d '{
  "state": {"engine": "hot", "load": 0.9},
  "questions": {"q1": {"type": "noul", "instructions": "Throttle?"}}}'

# image → decision, direct mode (raw image tokens decide)
curl -s $URL/v1/systemone -d '{
  "image_b64": "'"$(<screen.b64)"'", "image_mode": "direct",
  "questions": {"threat": {"type": "noul", "instructions": "Enemy visible?"}}}'

# decide, then narrate
curl -s $URL/v1/systemone -d '{
  "state": {"hp": 12}, "questions": {...},
  "then": {"generate": {"messages": [{"role": "user", "content": "Narrate."}],
                        "max_tokens": 128}}}'

# MULTIPLE questions, mixed types, ONE state (each question = its own readout;
# cost scales ~linearly until prefix reuse lands)
curl -s $URL/v1/systemone -d '{
  "state": "Reactor at 84%. Coolant loop A nominal, loop B pressure rising slowly.",
  "questions": {
    "threat":  {"type": "noul",   "instructions": "Is loop B a current threat?"},
    "action":  {"type": "choice", "instructions": "Which action first?",
                "criteria": {"inspect": null, "throttle": null, "shutdown": null}},
    "urgency": {"type": "score",  "instructions": "How urgent is intervention?",
                "criteria": ["none", "low", "medium", "high", "critical"]}}}'
# -> {"answers": {"threat":  {"type": "noul", "noul": 0.5429, "calib": "platt_v1"},
#                 {"action":  {"type": "choice", "choice": 0,
#                              "probabilities": [0.830, 0.160, 0.010],
#                              "confidence": 0.7453, "calib": "T_choice_v1"},
#                 {"urgency": {"type": "score", "score": 1.5928,
#                              "probabilities": [0.103, 0.374, 0.376, 0.121, 0.026],
#                              "confidence": 0.2201, "calib": "T_score_v1"}},
#      "margin": top1−top2 present on every answer (cascade-routing number)}
#     "usage": {"prompt_tokens": 303, "readout_tokens": 3}}
# (live response, QFN; note each answer carries its OWN calibrator id)

# INLINE jev on the chat surface — decisions inside an OpenAI chat call; the
# conversation itself is the state (v1-chat template), no "state" field needed
curl -s $URL/v1/chat/completions -d '{
  "model": "jev",
  "messages": [{"role": "system", "content": "You are the plant supervisor."},
               {"role": "user", "content": "Loop B pressure is rising. Inspect now?"}],
  "jev": {"questions": {"inspect":
      {"type": "noul", "instructions": "Should loop B be inspected now?"}}}}'
# -> {"id": "jev-1792055290765", "object": "jev.response",
#     "model": "qwen3.8-flash-next-iq3_xxs-jevport",
#     "jev": {"answers": {"inspect": {"type": "noul", "noul": 0.9230,
#                                      "calib": "platt_v1"}},
#             "usage": {"prompt_tokens": 82, "readout_tokens": 1}}}
# (live response; jev answers ride alongside the normal chat fields, so any
#  OpenAI client gets decisions without a second endpoint)

# MODE GATING — decisions are OPT-IN (donor --modes; the default differs, see section 4d)
# STRATA_JEV_MODES unset            -> "chat" ONLY: a process that never mentions
#                                      jev behaves exactly like stock Strata
# STRATA_JEV_MODES="chat,decision"  -> both (what the jevport presets run)
# STRATA_JEV_MODES="decision"       -> decision-only: no generation path at all
# Unknown tokens fail closed at load (serve refuses to start).
# "decision" gates /v1/systemone + the chat jev extension;
# "chat"     gates plain generation + then.generate narration.
# Gated surfaces return 404 not_found_error (probing learns nothing).

Full surface + examples: docs/JEV-SYSTEMONE.md. Refit calibration:
calib/README.md (the suite IS the procedure). Mode gating:
STRATA_JEV_MODES env ("decision" = decision-only — no generation path
exists on the instance at all; outputs are probabilities over the caller's own
labels. Unset = "chat" only: decisions are opt-in, and the jevport presets set
"chat,decision" explicitly. Fail-closed on unknown tokens and on gated
routes).

Why logit readout instead of asking the model for confidence: models asked to state their
own confidence are mostly overconfident with high calibration error (Groot &
Valdenegro-Toro, TrustNLP 2024, see References). Reading label probabilities from the
logits and calibrating them post-hoc on held-out data (Platt / temperature scaling) is the
standard alternative, and it is what this PR does; its measured effect is in section 4a.
Laya reaches the same conclusion from the training side: its probabilities also need a
temperature refit on local data before they can be trusted.

3. Test strategy

Unit (mock engine) — 73/73 green (jev modules; full serve/ discovery 858 run, 0 fail, 11 skipped): readout math invariants, prompt rendering
(byte-pinned noul/choice blocks — the Yes/No-swap regression is now a golden test),
per-tuple calibration isolation, V-mode softmax, image two-call/direct shapes,
decide-then-generate, chat-surface validation arms, 7×3 concurrency + FIFO
serialization.

Live suites (calib/bench_suite.py): dev-split fit → held-out test eval,
standard top-label ECE15 + mean NLL, per-item JSONL logs. Guards: Platt slope
a≤0 refused (label/prompt inversion detector — it caught a real bug), temperature
at search boundaries flagged.

Adversarial audit protocol (Justin's rule, 2026-10-15): 1-in-10 of all test
items re-verified by hand — text golds re-read from source passages, image items
regenerated from committed seeds with sha256 match against the logged hash, sampled
error images independently re-counted with vision. Result across text+image+real
suites: 0 scoring hallucinations, 0 gold errors, 1 documented CV-Bench ambiguity.
Artifacts: audit-*.json, audit-imgs/, *-item-log.jsonl (920 rows).

Real-benchmark converters (calib/convert_benchmarks.py): POPE adversarial,
CV-Bench, CountBenchQA via HF datasets-server; banned-field self-test (answer-bearing
fields never enter requests), sha256 image manifest, dev/test image-disjoint, POPE
sampled by image at exactly 50/50.

Vision strategy (externally reviewed before implementation):
6-arm design (D/S/S-QC/S-V/blind/shuffled — the last two are contamination
detectors), circular rotation for choice position bias, phased screen→full→frozen
PR gate.

4. Benchmarking results (all live, QFN IQ3_XXS, RTX 3090)

4a. Pre/post calibration (held-out test, offline replay of identical items)

tuple (mode|qtype|set) n acc pre→post NLL pre→post ECE15 pre→post
L|noul|BoolQ 100 .890 → .910 .298 → .262 .084 → .033
L|choice|ARC 100 1.000 → 1.000 .005 → .007 .005 → .006
L|score|SST-5 100 .520 → .520 1.471 → 1.049 .301 → .154
D|noul|POPE-adv 60 .867 → .883 .204 → .195 .122 → .081
D|choice|CV-Bench 20 .650 → .650 .944 → .863 .145 → .260*
D|score|CountBench 20 1.000 → 1.000 .102 → .036 .091 → .033

*CVB n=20, bin-noise territory; NLL improves, acc flat. Fitted: L a=.6127 c=.6539
Tc=1.0557 Ts=2.263 · D a=1.0571 c=−.172 Tc=1.5456 Ts=.6555.
Also shown in calib-prepost-ab.json: the OLD single global calibrator made image
tuples WORSE than raw (CountBench ECE .091→.451!) — the per-tuple fix is the story.

4b. Benchmark vs jevcpp's own benchmark (donor m2_baseline, same 3 tasks)

Donor: Qwen3.8-27B q4_k_xl, dense, its own server. Port: QFN IQ3_XXS MoE, Strata.
Same task sets (BoolQ / ARC / SST-5 slices from jevcpp's eval data), same metrics
code, post-calibration numbers:

task jevcpp 27B (donor) jev-port QFN (this PR) port, donor-ECE defn*
BoolQ noul acc 0.905 raw / 0.890 cal 0.910 cal —
BoolQ ECE15 0.036 raw / 0.049 cal 0.033 cal 0.035 cal
ARC choice acc 0.990 1.000 —
SST-5 score acc 0.569 0.520 (−4.9pp ≈ 1 SE at n=100) —
SST-5 ECE15 0.110 raw / 0.030 cal 0.154 cal 0.156 cal
SST-5 NLL 1.103 raw / 1.031 cal 1.049 cal —

*Both ECE variants are top-label, 15 bins; the donor scores each bin at its CENTER
((b+0.5)/15), this PR's harness scores the bin MEAN confidence. The donor-definition
column recomputes our logged raw_p under the donor's exact b13_eval formula so the
comparison is apples-to-apples. Under either definition the direction is the same.

The 26B-smaller IQ3 MoE matches the donor within ~1 standard error on noul and choice
(at n=100, SE≈3-5pp); score is −4.9pp (≈1 SE; the confounds are model size, MoE vs
dense, and quant — not separable at this n). Donor noul calibration HURT it
(0.905→0.890 acc); ours helps (0.890→0.910). SST-5 calibrated ECE remains ~5× the
donor's under both definitions — T_score=2.263 is doing damage control on a weak
5-way readout, not achieving donor-grade confidence. Stated plainly.

4c. Performance (warm, single client, n=10 per cell)

workload p50 p95 rps
text 1 question 272 ms 368 ms 3.7
text 3 questions 1002 ms 1016 ms 1.0
image direct, 1 question 275 ms 362 ms 3.6
image summary, 1 question 1625 ms 2731 ms 0.6

These cells are the warm-repeat regime (identical or near-identical prompts;
the engine's prefix mount fires). Instrumented per-turn measurements
(temporary build, since reverted) showed the two regimes explicitly, at a
67-token prompt: fresh question ≈ 1.0 s end-to-end (~0.97–1.14 s prefill +
decode + readout); identical repeat ≈ 0.35–0.45 s (mount skips prefill).
Multi-question requests and benchmark items are mostly fresh-prompt, so
expect the fresh column when prompts vary; the p50s above reflect settled
repeat traffic. Prefill dominates in both — that is the case for the
state-KV-reuse follow-up.

vs donor (27B dense, its m1_perf matrix, 1q-1c-warm): 71 ms p50 / 14.0 rps.
Measured budget of the port's ~350 ms (proxy, fresh connection), decomposed live:

component cost note
serve HTTP + JSON + calibration ~1 ms GET /health and /v1/models both p50 1 ms
engine turn (prefill + 1 decode + BROW readout) ~260 ms prefill-dominated on fresh prompts
fresh TCP + auth handshake ~47 ms keep-alive removes it (255 ms direct p50)
llama-swap proxy hop ~44 ms direct-to-serve-port removes it (302 ms)

Streaming is not a factor: systemone responses are single JSON bodies with
Content-Length (donor contract refuses stream: true). The gap vs the donor is
the un-prefixed engine turn, not protocol overhead — the donor amortized prefill
across forks (prefix-once + seq_cp); this port re-prefills per request. State-KV
reuse / prefix-LRU (the separate suffix-reuse work, out of scope here) collapses
the prefill share and projects decisions to ~60–80 ms. Repeat-identical requests
already hit the engine's prefix mount: 278–300 ms via proxy, and long states
(~470 tok) repeat at the same cost, confirming the mount fires when the prompt is
a full prefix. Image direct ≈ text latency (encoder cached); summary costs ~6×
direct (full 160-token generation).

Determinism / noise floor (measured, mechanism identified): repeat-decision
probability drift on this engine is p99 |Δp| ≈ 0.04–0.07 with zero argmax
flips in 720 repeated decisions
across idle, 8-decision and mixed 4-chat+4-
decision load (blockers-run/noise-floor.json). The donor's 5e-3 gate was a
DENSE-model gate and never applied here. Mechanism (verified in engine
source): MoE expert placement uses atomicAdd slot assignment
(src/prefill/moe_fused.cu place_kernel), so row order inside each expert is
warp-dispatch order — nondeterministic per run; float addition is non-
associative, so the expert GEMM sums differ in the last ulp and the divergence
compounds across layers; IQ3_XXS keeps the wobble above dequant noise and the
readout softmax amplifies it near p≈0.5–0.9 (Δp ≈ p(1−p)·Δd). It is a property
of the model+engine pair, not of load — the three load scenarios measured the
same floor. Decision margins (>0.9 typical) exceed the floor by an order of
magnitude; fitted calibrators average it out over the dev split. A
deterministic-placement option (sort rows by source index after the atomic
fill) would lower it, as an upstream engine follow-up — out of scope here.
Single-item probability deltas smaller than this floor (e.g. POPE +1.6pp at
n=60) must not be read as signal.

4d. Not ported / diverged (deliberate, vs the donor plan)

Donor item Why not
--modes chat,decision gating Ported as STRATA_JEV_MODES env (A0.1) with a deliberate divergence: unset = chat only (donor defaulted both-on). Opt-in keeps an unconfigured Strata process behaviorally identical to stock, per the repo rule that a new feature is opt-in and the default path stays unchanged. Values: "chat" / "decision" / "chat,decision"; fail-closed 404 on gated routes, refuse-to-start on unknown tokens. /admin/modes runtime flip not ported — restart is the policy boundary here
Prefix-fork + batched decode + naive differential (A2.7/A2.10) Strata's engine exposes BROW final-row logits, not seq forks; correctness is anchored by the golden battery + the ported jevref math, not a naive twin
V2 image-in-branch (crashed ggml) Superseded by image_mode: direct — same single-readout goal, no fork, D-tuple-calibrated, benched on POPE/CVB/CountBench
Chat-KV reuse for decisions (A3.5, PARTIAL in donor) Strata's conversation cache provides prefix reuse engine-side (272 ms warm L-mode)
B2 LoRA decision adapter Donor's own gate: only if B1 left gaps; the score tuple is the candidate, deferred
Batched/naive/fallback golden HTTP variants One serve path exists; the golden battery + 7×3 concurrency arm cover it

All 10 pre-PR blockers from the Opus review
(pre-PR external review) are closed: strict per-tuple
fallback, per-tuple log files, B1.4 tuple refusal, fail-closed /admin/calib,
token audit (PASS), a211 metamorphic battery, noise floor (see 4c), soak
(2,200 req, 0 jev errors, VRAM drift 0.026%), S-tuple fit (live), bootstrap
CIs + Brier (blockers-run/cis-brier.json).

5. Artifacts

  • calib-prepost-ab.json — 4a's numbers + method (offline replay, identical items)
  • perf-matrix.json — 4c (live measured)
  • text-suite.md, image-suite.md, real-suite.md + *-item-log.jsonl — suite reports
  • convert-manifest.json — real-benchmark provenance (sha256 per image)
  • audit-text-sample.json, audit-image-sample.json, audit-real-sample.json — 1-in-10 audits
  • Donor reference files: jevcpp/reports/m2_baseline.json, jevcpp/reports/m1_perf.json, jevcpp/calib/calib.json (all in the donor tree, not this repo)

6. Scope of change, compatibility, and testing status

Engine diff (5 files, +149 lines, additive): Verifier::brow_row (verify.hpp/.cpp),
the --jev-brow flag and BROW serve-loop handler (generate.cpp), a CMake test target
(verify_brow_test, CUDA builds only), and its test. Everything is opt-in: the handler
runs only when --jev-brow is passed and the server sends BROW; no existing request
path changes. One line runs on every verify window regardless of the flag
(last_row_T_ = T; in Verifier::run), an int store with no behavior change.

Default behavior: STRATA_JEV_MODES unset = chat only. Verified end to end with the
env var absent: /v1/systemone and the chat jev extension return 404, plain chat
returns 200. A stock Strata process is behaviorally unchanged.

Tested: CUDA build and GPU runs on an RTX 3090 (QFN IQ3_XXS, Qwen3.8-Flash-Next); the
full serve/ test discovery (858 tests) passes with the jev modules opted in.

Not tested in this PR: HIP, SYCL and Metal builds. brow_row is written for those
backends (the HIP compat headers map cudaMemcpy* to hipMemcpy*; a Metal branch is
included), but none of them was built or run as part of this PR.

7. References and prior work

Decision-model products and implementations

  • TypeSafe Jev: the commercial System One decision API whose /v1/systemone wire this
    follows.
  • Laya: Nandha Kishor M., convaiinnovations/laya (Apache-2.0).
    https://github.com/NandhaKishorM/laya, model card convaiinnovations/laya. Source of the
    RLCD training description, the one-forward-pass encoder design, and the per-(question
    type, option count) temperature-refit finding. Its README cites third-party Jev
    measurements of 236–276 ms p50 (AbdelStark/jev-benchmarks, nibzard/decision-model-benchmark).
  • jevcpp: the llama.cpp-based reference implementation and its PLAN.md,
    PLAN.amendments.md, DECISIONS.md, m2_baseline.json, m1_perf.json, calib.json
    (donor tree, not part of this repo). Its plan also lists open Jev-compatible projects as
    prior art: DIY-Jev (Rust), llm2jev, verdict, jevper, jev-compatible-server.

Calibration

  • J. Platt, Probabilistic Outputs for Support Vector Machines and Comparisons to
    Regularized Likelihood Methods
    , 1999: the Platt scaling used for yes/no.
  • C. Guo, G. Pleiss, Y. Sun, K. Q. Weinberger, On Calibration of Modern Neural Networks,
    ICML 2017: temperature scaling (choice/score) and the Expected Calibration Error metric.
  • T. Groot, M. Valdenegro-Toro, Overconfidence is Key: Verbalized Uncertainty Evaluation
    in Large Language and Vision-Language Models
    , TrustNLP 2024 (arXiv:2405.02917): LLMs and
    VLMs asked to state their own confidence show high calibration error and are mostly
    overconfident, the reason decisions are read from logits and calibrated externally.

Readout design (surveyed in docs/ research notes, 2026-10-15)

  • EleutherAI lm-evaluation-harness and HELM: loglikelihood multiple-choice scoring,
    single-token letter labels, acc / acc_norm, and the smoke-test invariants adopted in
    the golden battery.
  • OpenAI Cookbook, Using logprobs, and single-token classifier write-ups: first-token
    top_logprobs classification and top-1 − top-2 margin as the routing signal
    (returned on every answer here).
  • Constrained-decoding systems (Outlines, SGLang, XGrammar): the generate-then-parse
    approach this design avoids, and its documented whitespace/prefix pitfalls.
  • Real-time agent context: A Survey on LLM-Based Game Agents (arXiv:2404.02039) and
    The Latent Bridge (arXiv:2606.24470): why a single-pass fast path matters for
    frame-rate decision loops.

Benchmarks used for calibration and evaluation: BoolQ, ARC, SST-5 (text); POPE
(adversarial), CV-Bench, CountBenchQA (image).

Suzie (Hermes) added 30 commits October 14, 2026 09:07
serve/jev.py: frozen D3 prompt, donor 422 contract, jmath readout (M1 identity),
engine-turn discipline (svc.fifo), final_row_logits readout boundary (BROW on the
engine side). server.py: route + import. 10/10 tests; full-suite parity vs
baseline verified (0 new failures; 14 pre-existing regex-module errors, flaky
sampler tests vary run to run on both trees).
…fail-closed) + jev.handle wired to real contract
…, CUDA+Metal), --jev-brow flag, serve-loop BROW handler; golden battery fixture
…ly order, /admin/calib hot-swap, B1.1 log rows

- serve/jev_calib.py: donor src/server.cpp:518-633 surface - load (calib.json/v1.json,
  corrupt=identity), swap, apply (platt_v1 noul / T_choice_v1 / T_score_v1, argmax-safe,
  renormalized), tuple_of, async 4096-row log queue with 200ms flusher
- serve/jev.py: donor order (server.cpp:1134-1142) - softmax -> round 4dp -> renorm ->
  calibrate -> answers_from_calibrated; calib id surfaced per answer; B1.1 rows
  (ts/tuple/qid/type/raw_p unrounded; label_mass omitted - BROW is sparse, fit.py
  never reads it)
- serve/server.py: POST /admin/calib (Bearer STRATA_JEV_ADMIN_KEY, empty=open like
  llama-swap's control plane); startup swap() + daemon flusher + atexit drain
- tests: test_jev_calib (14) math+wire+hot-reload; test_systemone re-pinned to the
  donor 4dp contract. 29/29 green (mock, no GPU); full-suite regression running
…he live M3.2 bench

1. question_block now the donor render_qblock verbatim (server.cpp:305-334):
   full Options:/Levels: list with criteria descriptions, 'Question:'/'Answer:'
   anchors, noul Yes/No-means lines. The M3.0 render listed NO options -> the
   model picked labels blind (ARC 23% = chance).
2. enable_thinking=False on the decision render (D3, frozen): the readout
   position must predict the label, not open <think>.
3. render_state: string states pass through VERBATIM (server.cpp:266-268);
   objects stay pretty JSON. The port JSON-quoted every string state.

Live QFN before -> after: choice 23%->100%, noul 49%->88%, score 24%->55%
(donor 27B baseline: 99/90.5/56.9). 29/29 unit tests green.
…on yes/no branches, softmax(d)

- question_head + v_branch: donor render_qhead/render_vbranch verbatim
  (server.cpp:337-353): shared 'Question:/Options:' head, then one
  'Proposed answer: <name> ... Answer:' branch per option
- d_i = s_yes - s_no per branch (BROW readout), p = softmax(d), 4dp +
  renormalize, choice temperature applies (donor :1150-1163, calib_apply)
- response: probabilities keyed by option NAME, 'choice' = name string
  (donor A2.6 shape); usage.readout_tokens counts one BROW per branch
- X-Jev-Mode header passthrough in server.py; V scopes to choice only,
  noul/score fall through to the L path (donor :767)
- log rows: tuple ...|V|choice with v_d (donor B1.1 V schema)
- K sequential branch decodes share the state+head prefix - Strata's
  engine-side KV prefix mounting reuses it (M3.0 alignment, no EngineSeq)
- tests: test_jev_vmode (6) - name-keyed probs, branch prompt shape,
  shared-head prefix, per-option readouts, v_d log rows, L unchanged.
  35/35 green with calib/systemone/golden.
…n, one wire request)

- POST /v1/systemone with image_b64 (+ optional vision_prompt, default
  'Describe this game screen:') -> jev.handle_image
- stage 1: Strata's existing per-preset vision path (svc.prepare encodes the
  image and expands the image pads), one bounded summary generation (<=160 tok,
  thinking off)
- stage 2: the summary becomes the decision state; the standard L/V readout
  answers. Response: answers + image_summary + stages_used ['vision','decision']
  (donor PLAN B V1 contract, server.cpp:2419-2603; the donor's V2 single-seq
  fork crashed ggml and stays NOT ported)
- fail-closed: empty summary -> 502 and the decision stage never runs;
  no vision encoder -> 400; short b64 -> 422
- tests: test_jev_image (6) - two stages one request, summary rides into the
  decision state, vision_prompt accepted, fail-closed paths, validation first.
  41/41 green with vmode/calib/systemone/golden.
…e jev extension

M3.9 (donor amendment 7 mode 1): "then": {"generate": {...}} on /v1/systemone -
decide first, then generate with the answers folded into the LAST USER turn as
'Jev decisions (JSON): ...' (a trailing system message throws in the chat
template; donor folds too). Sampling mirrors the chat endpoint (temp 0.6,
top_p 0.95, top_k 20, max_tokens 512 defaults; stop strings honored).
Response = decision body + then{text, finish_reason, usage}.

M3.3 (donor A3.4): "jev": {state|messages, questions} on /v1/chat/completions -
jev.questions required; state XOR messages (400 on both/neither, donor
messages-must-be-empty rule); stream refused with the jev extension; the
conversation becomes the decision state (v1-chat, donor 3.5). Response wraps
the decision body under "jev" with an OpenAI-style envelope.

Tests: test_jev_then (9) - two stages one request, answers in the gen prompt,
sampling defaults, error propagation, chat-surface validation arms, plain chat
unaffected. 50/50 green with image/vmode/calib/systemone/golden.
…ns, no cross-talk, FIFO serializes engine turns

The donor's DoD arm on the serve port: 7 threads, 3 noul questions each -
every client gets exactly its own 3 answers (qid-keyed, no foreign qids), 21
readout turns, and an in-flight counter on engine.generate proves the FIFO
never lets two engine turns overlap (the serve-side stand-in for the donor's
per-decode-step ENG.mu, which M3.4 maps to svc.fifo - already held across
each request's whole readout loop).  52/52 green.
…ns, calibration, examples

Wire surface (request/response/422 contract), the four extensions (V mode,
image two-call, decide-then-generate, chat-surface jev), calibration math +
hot-swap + the measured QFN tables (raw vs calibrated, ms/item, donor-parity
numbers), concurrency arm, and curl examples for every path.
…enizer

Live QFN run caught two: the engine streams negative sentinel ids
(verification artifacts) which the byte tokenizer's token_bytes rejects, and
per-token decode re-decodes for stops. Now uses the server's own incremental
Detokenizer (split-multibyte safe), skips None/negative ids, and checks stops
against the last few decoded pieces.

Live-verified on QFN through llama-swap after the fix:
- then.generate: decision + 'Jev selects the second option ... 75.93%' (the
  answers folded into the prompt, 33-token completion, finish stop)
- chat-surface jev: {object: jev.response, jev: {answers... noul 0.9995}}
…cide

Justin's ask: can the image embeddings themselves drive the readout, without
the summary in between? Yes on Strata - the donor's V2 needed a seq fork off
image embeds (crashed ggml on hybrid attention); our readout is BROW on the
final decoded row, so one prompt [image + question_block], one decode step,
label logits off that row. No new engine primitive.

- image_mode: 'summary' (default, two-call) | 'direct' (single readout);
  invalid values 422 on image_mode
- the question text sits AFTER the image pad so the readout position attends
  the full image; svc.prepare encodes + expands pads (Strata's normal path)
- no outer fifo hold: prepare takes its own engine turn (deadlock found by
  the new test - same lock, held twice)
- response: answers + usage + stages_used ['image-direct']; calib log rows
  under a ...|D|<qtype> tuple (D = direct image readout) for a separate fit

Tests: direct-mode shape (one turn, question after image), bad mode 422.
54/54 green.
…mage was black without them

The live vision A/B caught it: chat-path control answered 'Red' (reasoning
described the white box and the RED text), while both image arms saw a
'completely black' image. prepare() stages the combined embeddings file on
svc.embeddings.path, but it is the CALLER that must pass embeddings=... to
engine.generate - that is what turns GEN into GENI and makes the engine load
the image. The decision handlers called generate() bare, so the pads attended
nothing. Both handlers now take svc.embeddings.path (run()'s exact pattern),
clear it, and delete the file when done, as run() does.

Also the summary loop's second run-in with negative sentinel ids (fixed the
same way as handle_then: Detokenizer + skip None/<0).

Also why the first bench arm died at 400: same crash, earlier code. 52/52
green after; live A/B rerun in flight.
…review

P0-1 (blocker): calibration was one GLOBAL Calib - fitting an image tuple
would have silently changed text decisions. Calibs are now keyed by readout
letter ('' text legacy, L, V, D, S) with per-mode files calib-<mode>.json and
fallback to the text fit when a mode has none. state_json reports every mode.

P0-2 (blocker): summary-mode image decisions logged under the text 'L' tuple,
indistinguishable from text rows. handle() now detects an image_summary state
and logs/applies under 'S'.

P0-3 (major): direct mode silently ignored X-Jev-Mode: V. It now 422s with a
clear message (D-V does not exist; the plan's assumed behaviour), pinned by a
test.

Tests: PerTupleCalib (image fit leaves text identity; fallback; swap loads
per-mode files) + DirectVMode 422. 54/54 green.
…wapped

Found by the small image calibration suite + Opus validation (2026-10-15):
image noul raw acc 0.0% with a perfect-inversion Platt fit (a=-2.80) while
choice/score on the same images were correct. Root cause, two compounding bugs
in the noul criteria path:

1. question_block unpacked descriptions as (true_d, false_d) but they are
   stored in [No, Yes] label order - so 'Yes means:' printed the FALSE
   description. The model read the reversed definitions and answered
   consistently - every noul with criteria was inverted.
2. The ': ' separator was baked into the stored descriptions AND re-added by
   question_block -> doubled colon ('Yes means: : ...').

Text noul (BoolQ) never sends criteria, so M3.2's 88-90% never exercised the
path; the image suite was its first caller. Fixed: descriptions stored bare in
[No, Yes] order, question_block renders Yes/no lines in donor order.

Also: fit_platt in the suite now REJECTS a <= 0 (a negative slope means the
labels/prompt are wrong, never a legitimate calibrator). New golden tests pin
the exact noul question-block text (Yes means true, No means false, no doubled
colon) and the choice description shape. 54/54 green.
- calib/bench_suite.py: live fit+eval suite (text/image/real); standard
  top-label ECE15 + mean NLL (the first suite's gold-class-pinned ECE variant
  was wrong - Justin caught the tables); per-item jsonl logs for adversarial
  audit; refuses Platt a<=0 and flags T at search boundaries
- calib/convert_benchmarks.py: POPE-adv/CV-Bench/CountBenchQA converters with
  the banned-field selftest (never sends prompt/text/rationales), sha256 image
  manifest, image-disjoint dev/test, POPE 50/50 by-image sampling
- calib/calib-L.json + calib-D.json: the ACTIVE per-tuple fits (2026-10-15,
  corrected harness): L a/c/T from BoolQ/ARC/SST-5 dev; D from POPE/CVB/CB dev.
  S stays identity until its own dev run
- calib/README.md: refit procedure + donor reference (jevcpp 27B calib.json,
  tuple p-jevcpp-qwen38-27b|q4_k_xl|timber|v1|V|all, T_choice 1.5861)

Live-verified after hot-swap: TEXT-L noul platt_v1, TEXT-L score T_score_v1,
IMAGE-D noul platt_v1, IMAGE-D score T_score_v1, IMAGE-S identity (own tuple
pending) - every mode answers under its OWN calibrator now.
…ev-vs-jev

The PR document package:
- pre/post calibration tables (held-out, offline replay of identical items;
  includes the old-global-calib comparison showing why per-tuple matters)
- benchmark vs the donor's OWN m2_baseline.json (same tasks/metrics code):
  QFN IQ3_XXS MoE matches the 27B within noise on noul/choice, -4.9pp on score
- performance matrix measured live (p50/p95/rps: text 272ms, image-direct 275ms,
  image-summary 1625ms) vs donor m1_perf 71ms/14rps - honest 3.8x gap + what
  buys it
- test strategy: 54/54 unit, live suites with guards, the 1-in-10 adversarial
  audit protocol + results, banned-field converter selftest, Opus vision plan
- artifacts bundled in docs/bench-artifacts/ (reports, item logs, audits,
  convert manifest)
…er-tuple logs, B1.4 tuple refusal

R1 (blocker): the per-tuple fallback contradicted itself — code fell back to
the TEXT fit for V/D/S while the comment and README promised identity. Strict
now: only ''/L share the legacy calib.json fit; V/D/S use their own
calib-<mode>.json or identity. (The S handoff was already threaded: handle()
detects image_summary states and applies/logs under 'S'.)

G3 (blocker): the donor's fit.py pools a single log by type — running it on a
mixed L/V/D/S log file would fit text+image rows into ONE calibrator, the
exact global-fit failure the per-tuple split fixed. log_flush now writes one
file per readout tuple: data/log-<mode>.jsonl.

G13: B1.4 tuple refusal — a calib-<X>.json whose tuple names a different
readout letter is refused at load (logged, identity), so copying calib-D.json
to calib-S.json cannot apply silently. Legacy calib.json/v1.json keep no mode
binding.

R7 (verified, no change): the [x / t ...] before apply() in the direct path is
the donor's 4dp-round renormalization (softmax -> round -> renormalize ->
calibrate), NOT a second temperature.

Tests: OpusPrereviewFixes (4 new) — S/D never inherit the text fit, L does;
mismatched tuple refused; matching tuple accepted; log split by tuple. Prior
tests updated to the new contracts (state_json modes shape, log-<mode> files).
61/61 green.
… Not-ported section

R3: the donor's b13_eval ECE scores each bin at its CENTER, our harness at the
bin MEAN — both top-label/15-bin but not directly comparable. Added a column
recomputing our logged raw_p under the donor's exact formula (BoolQ .035,
SST-5 .156 — same direction under either definition), stated the n=100 SE on
the -4.9pp score gap, and said plainly that calibrated SST-5 ECE stays ~5x
the donor's.

Rank 8: 'Not ported / diverged' section — mode gating, fork/batch/naive
differential, V2 (superseded by direct mode), chat-KV reuse, B2 LoRA, golden
HTTP variants — each with its one-line rationale, plus the open pre-PR list.
…(Opus G10)

G2 (security): with no ADMIN_KEY configured, /admin/calib was OPEN — anyone
could hot-swap calibrators and read state. Now 404s like the donor's
unconfigured --admin-key routes (404, not 401: probing must not learn the
surface could exist). Keyed operation unchanged. Test added.

G10: calib/token_audit.py — donor A1.3 parity for the QFN tokenizer. Loads the
real pack tokenizer (same path as serve/server.py main), checks all 38 labels
(A-Z, Yes/No, 0-9) for single-token, collision-free, prefix-free. Result:
PASS (reports/token_audit_qfn.json, donor schema). First run failed against
the byte stand-in — the audit must point at the pack, which the script now
takes as its second arg. 62/62 green.
…l negation, ambiguity (Opus G8)

Donor parity for reports/a211_metamorphic.json: (1) REORDER — permute the
questions in one request; per-question probabilities must be invariant
(Jensen-Shannon < 1e-9, argmax never flips). The port renders each question
as its own prompt so this is by construction — but the Yes/No-swap bug proved
construction is not evidence, so the test PROVES it. (2) NOUL NEGATION —
pos/neg question pairs must flip yes-probability; the >=4/5 gate binds on the
GPU arm (mock answers by token, documented). (3) AMBIGUITY — unanswerable
questions must not gain confident mass; |p-0.5| proxy for the donor's label
mass (BROW is sparse). 3/3 green on the mock; GPU arm reuses the same file
with RUN_BASE/RUN_KEY.
… (Opus ranks 3/5/6 + R1)

calib/blockers_gpu.py + artifacts in docs/bench-artifacts/blockers/:

NOISE FLOOR (30 items x 5 runs x {idle, 8-decision, 4chat+4decision}):
- argmax flips: ZERO in every scenario (stability gate passes)
- p99 |dp|: idle noul .070 / choice .039; dec8 .043/.044; chat4dec4 .039/.022
- The MoE drift floor is ~0.04-0.07 abs-prob — 14x the donor's dense 5e-3
  gate. Every suite delta must be read against THIS floor: POPE +1.6pp (1
  item at n=60) is within it, exactly as Opus R6 suspected.

SOAK: text 2000 req (1200 dec1q / 400 dec3q / 400 chat) = 1 error; image
direct 200 req = 0 errors. VRAM drift 23228->23222 MB (0.026%, donor: 0.07%).
The 1 error is a 503 at the moment the engine self-stopped mid-soak
(strata 'stopping' in logs — TTL/idle unload raced the soak, NOT a jev
crash); restarted cleanly, soak continued green. Documented as infra race.

S-FIT (summary-mode dev): a=.4892 c=.8313 (Tc .05 boundary — choice n=20
degenerate, same as CVB; Ts 1.8702). calib-S.json committed + live: S answers
now platt_v1, D unchanged. Honest finding: summary raw noul acc .75 vs direct
.867 on the same POPE dev — DIRECT BEATS SUMMARY for perception.

CIs/Brier (bootstrap 1000): POPE .067->.065, CVB .200->.179 (CIs overlap
raw), CountBench .018->.005 calibrated (3.7x better, CI clean). Supports
shipping D|choice as-is with CIs stated, not identity.
…donor's dense gate

Replaces the one-line 'determinism caveat' with the measured floor (p99
|dp| .04-.07, zero argmax flips in 720 repeats) AND the mechanism, verified
in engine source: atomicAdd expert slot assignment (moe_fused.cu
place_kernel) -> row order = warp-dispatch order -> non-associative float
sums differ per run -> compounds across layers -> IQ3_XXS keeps it above
dequant noise -> softmax amplifies near p .5-.9. Same floor across idle/
dec8/chat4dec4 (per-request kernel scheduling, not load). Donor's 5e-3 was a
dense-model gate. Mitigation note: deterministic placement = upstream engine
follow-up. Reviewer guidance: single-item deltas under the floor are not
signal.
…is the 260ms

3-arm + floor decomposition (live): /health p50 1ms, /v1/models 1ms,
systemone 262ms -> the serve layer is innocent; the cost is the engine turn
(prefill-dominated). Fresh TCP 47ms, proxy hop 44ms (keep-alive direct p50
255ms). Streaming was never in the decision path (Content-Length bodies,
donor refuses stream:true). Donor gap = no prefix amortization (it forked a
cached prefix; we re-prefill) — state-KV reuse projects 60-80ms, queued as
the suffix-reuse follow-up. Repeat-identical requests already hit the
engine's prefix mount (278-300ms even at 470-token states).
Suzie added 12 commits October 15, 2026 09:08
…ev (Justin's catch)

Two missing examples, both with REAL captured responses (not illustrative):
- multi-question: mixed noul/choice/score on one state; shows each answer
  carrying its own calibrator id (platt_v1 / T_choice_v1 / T_score_v1) and the
  per-readout usage block; notes cost scales ~linearly until prefix reuse
- inline jev: the chat-surface extension with the conversation AS state
  (v1-chat template, no state field); shows object: jev.response shape and
  that any OpenAI client gets decisions without a second endpoint
…variants + calibration-literature citation

Ecosystem survey (/opt/data/research/decision-readout-survey.md) adoptions:

1. margin (top1−top2 probability) on every noul/choice/score answer — the
   cascade-routing number from the classifier literature (separates 'confident'
   from 'no-alternatives'; route low-margin to escalation). noul margin =
   |p_yes − p_no|.

2. LmEvalSmokeInvariants in the golden battery: per-answer probabilities must
   be distinct, in (0,1), sum to 1, and carry margin — identical values are
   lm-eval's documented signature of a broken readout split (the BOS class of
   bug). Also asserts the new margin field.

3. JEV-PR.md: one-paragraph citation of the calibration literature
   (verbalized-confidence failure, ECE>0.37 Groot ACL-24; Platt 30-60% ECE
   cuts matching our measured −53%) justifying the logit+Platt architecture.

68/68 green (62 + metamorphic 3 + invariants 1 + margin asserts folded).
…er question

Justin's ask: confirm the decode-cost assumption instead of estimating it.
usage.timing_ms.readout = wall time of the per-question engine turn
(generate(ids,1) + final_row_logits), rounded 0.1ms. L-mode main loop and
both image paths instrumented (prepare/generate splits in the direct and
summary stages).

MEASURED (live QFN, post-cold-reload, 67-token prompts):
- fresh question: readout ~975-1135 ms (prefill of 67 tokens + 1 decode + BROW)
- identical repeat: readout ~348-451 ms (engine prefix mount skips prefill)
- => the DECODE-ONLY share is roughly (repeat total) minus fixed overhead:
   348-451 ms includes mount-check + decode + BROW + wire; the pure decode
   step is a fraction of that. Fresh-vs-repeat delta ~600-700 ms = the 67-token
   prefill — prefill dominates, as the latency budget stated.
- first-request-after-reload shows ~1s cold JIT/lazy-init tail (q0 1083 vs
  settled ~1000).

Also corrects the earlier 260ms engine-turn estimate: that was the settled
identical-repeat number INCLUDING the mount path; fresh-question turns are
~1s at short states. The PR's budget table stays directionally right
(prefill-dominated) but its 'engine turn ~260ms' line is the mounted
steady-state, now labeled as such in notes; doc table update queued.
… (fresh ~1s vs repeat ~0.4s at 67 tok)

The instrumented-build measurements (53307a1, since reverted) showed the
table's p50s are the mounted/repeat steady state; fresh-question turns are
~1s even at 67 tokens. Stated plainly so nobody reads 272ms as the
fresh-prompt cost. Prefill dominates both regimes -> the follow-up.
… parity; Justin's call)

- jev_calib.MODES: env STRATA_JEV_MODES='chat,decision' (default) |
  'decision' | 'chat'; unknown tokens raise at import -> serve refuses to
  start (fail-closed)
- Router gates: /v1/systemone + chat jev extension under 'decision';
  then.generate under 'chat'. Gated surfaces 404 not_found_error (probe
  learns nothing). Donor /admin/modes runtime-flip deliberately NOT ported:
  restart is the policy boundary
- 4 new tests (ModeGating) incl the env-leak regression this work itself
  hit (a leaking test env var gated later modules — cleanup now deletes)
- 72/72 green; JEV-PR.md usage section + 4d row updated (ported, not deferred)
…ustin's ruling)

undefined STRATA_JEV_MODES now means chat only: a serve process that never
mentions jev behaves exactly like stock Strata; the decision surface must be
explicitly opted into (chat,decision / decision). Deliberate divergence from
the donor (whose defaults were both-on) recorded in JEV-PR 4d. Live presets
carry STRATA_JEV_MODES=chat,decision explicitly so current behavior is
unchanged for existing callers. 72/72 green.
…o actually send direct

The chat-only default broke 53 tests - correctly: they now carry the
JEV_TEST_MODES_BOOTSTRAP env (setdefault chat,decision) before serve import,
which IS the new contract: decisions must be opted into. Also fixed
test_direct_rejects_v_header: it was posting REQ without image_mode=direct,
so it exercised the summary path where V is legal (200). Now sends direct+V
and gets the intended 422. 73/73 green.
…-on after the flip to chat-only

Found in the pre-PR audit: usage block, prose, and the 4d row all still
claimed STRATA_JEV_MODES defaults to chat,decision. Now: unset = chat only,
decisions opt-in, jevport presets set chat,decision explicitly; divergence
from donor recorded with the repo's own opt-in rule as rationale. Also moved
the mode-gating comment block inside the code fence (it was rendering as
markdown headings).
…r-file paths

- new section 6: engine diff scope (5 files +149, additive/opt-in, one
  unconditional int store), default-mode behavior verified env-unset,
  and an explicit NOT-VERIFIED list (HIP/SYCL/Metal builds, layer-split
  brow_row, pre-existing NoLeakedSampler isolation failure that reproduces
  on an unmodified Strata-043 tree)
- 54/54 -> 73/73 jev modules (858 full discovery)
- donor reference paths no longer imply files that live in this repo
…, testing-status wording

- new Introduction: what a System One decision model is and does, then Jev
  (TypeSafe's commercial API, the wire followed), Laya (RLCD-trained encoder,
  per-type/option-count temperature refit; claims checked against its README),
  jevcpp (the reference implementation), and what this PR adds to Strata
- new section 7 References: Jev/Laya/jevcpp + open Jev-compatible projects from
  the jevcpp plan; Platt 1999; Guo et al. ICML 2017; Groot & Valdenegro-Toro
  TrustNLP 2024 (arXiv:2405.02917, citation verified, the unsourced ECE>0.37
  figure removed); lm-evaluation-harness/HELM, OpenAI logprobs cookbook,
  constrained-decoding systems, game-agent surveys; benchmark datasets
- section 6: HIP/SYCL/Metal stated as not tested in this PR (nothing more)
- removed internal /opt/data review paths; corrected the engine-capability
  sentence (window_logprobs already existed)
@TwoAnts

TwoAnts commented Oct 15, 2026

Copy link
Copy Markdown

Wow, the other day I was actually thinking about using jev to detect whether the stop token in the answer is as expected, so as to prevent the task from ending illegally. Turns out it's already there now, haha.

@Niko1221

Copy link
Copy Markdown
Owner

Thanks for the pull request.

We're resetting the tracker for 0.2.0-beta. There are more than 1,300 open issues and pull requests, too many for us to review properly, so we're closing everything that isn't being worked on right now. Closed here does not mean rejected.

To reopen it takes about two minutes:

  1. Rebase on main if it no longer applies, and re-run your checks on 0.2.0-beta.
  2. Start the title with its area: [Engine], [GUI], [TUI], [Benchmark], [Docs] or [Other].
  3. Fill in the pull request template: the problem and result, and the validation (what you ran, on which revision, what you saw).
  4. Comment /reopen. A check runs and either reopens the pull request or lists what is still missing.

The rules are in CONTRIBUTING.md.

@Niko1221 Niko1221 closed this Oct 19, 2026
@justindressler justindressler changed the title Jev System One decision endpoint (/v1/systemone): calibrated typed decisions via an opt-in BROW logits wire [Engine] Jev System One decision endpoint (/v1/systemone): typed decisions with calibrated probabilities Oct 21, 2026
@justindressler

Copy link
Copy Markdown
Contributor Author

Rebased onto main at 011c9e60 and re-validated on 0.2.0-beta: #3643 supersedes this one.

What changed in the move: 42 commits replayed with no conflicts, and the feature code is unchanged
(the 38 added files are byte-identical to this branch, and the 5 modified files carry the same added
lines). What was run on the new base: CUDA build (nvcc 13.0.88, arch 86) exits 0 with no new warnings;
ctest has 156 tests and the 71 GPU-class ones were re-run on an RTX 3090, where 70 pass and the one
exception needs libstrata_kq.so, which this CMake configuration does not build; the full serve/
discovery is green on CI (1002 tests, 14 skipped); and a live POST /v1/systemone on the 3090 answers
a noul/choice/score state with platt_v1 / T_choice_v1 / T_score_v1 and three readout tokens.

Not run: HIP, SYCL, Metal, Windows, macOS, and the app's UI tests. Those are listed in #3643 as not run
rather than claimed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants