ADR 0037 — Host-side Jev Noul-only judge under judge:¶
Status: Proposed
Context¶
Prose gates are the language's reliability mechanism (ADR 0004). The host
turns a gates: relation into one transition by SPEC §5 first-true: scan
eligible gates in author order and fire the first that evaluates true.
Consecutive prose-only gates are fused into one LLM.judge call (ADR 0006);
the judge must not pick a "best" option out of order.
TypeSafe Jev (System One) can answer a batch of Noul questions cheaply. A prior measurement compared two host mappings of that API onto mklang's judge:
- Choice as
judge:mapping failed first-true. On thepriority_shadowboundary machine (near-overlapping conditions; gold is the earlier, narrower gate —docs/experiments/gate-divergence.md) it scored 0/4; overall Choice accuracy was 0.818. Jev Choice is a multi-option pick, not an ordered first-true walk. - Noul-batch, with the host applying first-probability-≥-threshold in gate order, preserved first-true (accuracy 1.0, n=11).
The existing host surface for "who judges" is the opt-in runtime judge:
key (ADR 0001, SPEC §2.1): a global override that forces one judge for
all prose gates. .mkl documents stay provider-neutral (ADR 0003). Exact
checks (amounts, dates, allowlists) already belong on hook: (ADR 0006),
not on an LLM.
Without a locked host mapping, a later adapter can silently choose Choice
as judge: mapping, wrap Jev as hook:, or treat Jev as a produce tier —
any of which would break first-true, mix probabilistic judgement into the
deterministic hook layer, or pin a vendor into generation.
Jev has no mklang-style untrusted fencing of its own. The same measurement
saw Choice injection accuracy of 0.833. ADR 0025 already requires judge
prompts to present produce output, reasoning, and context as delimited data
(<data-NONCE> fences plus an instruction that fenced spans are evidence,
not directives) while authored when conditions stay bare. A Jev judge
must keep that spirit on the System One content channel.
This ADR is Phase 1 only: it records the host mapping. It does not
implement an adapter, change the language, cut over production, or reopen
Choice as judge: mapping.
Decision¶
Adopt a Noul-only host judge behind the existing judge: config
key. Reject Choice as judge: mapping. Reject wrapping Jev as hook:.
Jev is not a produce tier.
A later implementation may land only after a dedicated EXPLORE / Path B measurement clears the quantitative bar named below. Until then the decision is Proposed.
Host mapping¶
| Rule | Spec |
|---|---|
| Unit of work | One gate decision → one POST …/v1/systemone call, model jev-latest (or a pinned successor). |
| Questions | One Noul per prose gate condition, in mklang gate order. Optional final Noul “none holds”, or a host default when no Noul fires. |
| Selection | The host walks results in order and fires the first condition whose probability is ≥ threshold. That preserves first-true. Jev never picks a “best” option. |
| None path | If no Noul is ≥ threshold: take the explicit none Noul if present, else the host “none / continue” default (document per machine). |
| Config surface | Provider behind the existing judge: key. Per-tier judge is out of this ADR (a later host change). |
| Forbidden | Choice as judge: mapping; calling Jev from hook:; treating Jev as a produce tier. |
| Exact rules | Amounts, dates, allowlists stay on hook: (code), never Jev. |
Normative intent of the walk:
fence(state_text) → payload
noul_i = gate_condition_i for i in order
response = systemone(content=payload, questions=nouls)
for i in order:
if response.noul[i].p >= threshold: return fire(gate_i)
return none_path()
Host fence (ADR 0025 spirit)¶
| Rule | Spec |
|---|---|
| Why | Jev does not fence untrusted text the way the reference judge does. Path B requires injection accuracy ≥ 0.95 under Noul after the fence. |
| What is untrusted | Produce text, user / state fields, and any append not authored as gate prose. |
| Host duty | Before building the System One content, wrap untrusted spans with a host fence: clear delimiters plus an instruction that fenced text is data, not instructions — the same spirit as ADR 0025 sentinel fences and the judge-role paragraph. |
| Gate prose | Trusted; sent as Noul question text, not inside the untrusted fence. |
| Residual | If the fence cannot reach 0.95 injection accuracy: do not accept a production cutover; document the residual and stop. |
| Keys | API keys live only in the host env / secret store (ADR 0023) — never in a .mkl or in git. |
Threshold¶
| Rule | Spec |
|---|---|
| Default | threshold = 0.5 (the Noul-batch “first ≥ 0.5” rule from the prior measurement). |
| Tunable | Config on the Jev judge adapter only. Changing it requires evidence on a pinned gate-divergence corpus. |
| Hard gate | On a reopen spike, priority_shadow accuracy must be 1.0 at the chosen threshold. |
| Confidence | Separate from threshold. Low confidence → prefer escalate / a divergence flag; never override first-true order. |
| Anti-pattern | Lowering the threshold to “fix” misses from Choice as judge: mapping, or using max(Noul) instead of first-≥. |
Observability¶
Log every judge call as structured fields comparable to
scripts/gate_divergence.py:
| Field | Notes |
|---|---|
judge_provider |
e.g. jev / jev-latest |
mapping |
always noul_first_ge |
threshold |
value used |
noul_probs[] |
ordered |
chosen_index / none |
result |
confidence[] or aggregate |
if the API returns it |
latency_ms |
wall |
tokens_in / estimated cost |
claim-check, not marketing |
fence_applied |
bool |
corpus_id / produce hash |
when in harness |
Harness: reuse the scripts/gate_divergence.py entry-state corpus. A
live DeepSeek / OpenAI comparison (Path C) is recommended before calling
any later adapter production-ready, and only after keys plus an explicit
go-ahead.
Out of scope (this ADR)¶
- Implementing the Jev judge adapter, wiring
POST …/v1/systemone, or changing runtime config schema beyond recording the intended surface. - Any SPEC / language / schema / conformance change.
.mklstays provider-neutral;judge:remains a host key. - Production cutover of the reference judge onto Jev.
- Reopening Choice as
judge:mapping (Path A is stopped). - Per-tier judge (still a later host change).
- Wrapping Jev as
hook:.
Consequences¶
- Positive. First-true stays a host walk, not a model pick. Noul
probabilities stay calibrated and ordered.
.mkldocuments remain provider-neutral viajudge:. Cost and latency are a potential win if a later measurement shows one. - Negative. The host owns fencing and the first-≥ walk. Global
judge:still cannot scope tofastalone. The adapter is a vendor dependency. Path B (and ideally Path C) must pass before any production cutover. - Neutral / deferred. Language change, platform deploy, Choice reopen, and a per-tier judge ADR.
- Acceptance before code. (1) Explicit EXPLORE go-ahead. (2) Path B
quantitative bar green, including
priority_shadowaccuracy 1.0 and injection accuracy ≥ 0.95 after the fence. (3) This ADR accepted as the host mapping. (4) Path C recommended before production-ready. Phase 1 records the decision only.
Implementation (Phase 2 spike)¶
The opt-in adapter is mklang.llm.jev.JevNoulJudge, selected only when
judge: is a reserved jev-* id (see docs/guides/jev-noul-judge.md).
Status stays Proposed: shipping the adapter is not a production cutover
and does not reopen Choice as judge: mapping. Live Path B numbers are
Lab measurements, not TypeSafe claims.