EKOS — eval, 101 scenarios

From 53 to 87 correct answers.
A bigger model, then better knowledge.

We moved EKOS's answering model from a local 8B model on Ollama to DeepSeek V4 Flash through OpenCode Zen, then fixed how EKOS decomposes documents and plans a query. The same checked-in 101-question suite, graded deterministically, went from 53 to 87 passed. This deck separates what the model bought from what the engineering bought, and names what still fails.

53/101 — local llama3 8B 70/101 — model swap only 79/101 — document structure 87/101 — planner fixes
§ 01 / the ladder
Same questions, one change at a time

Seventeen points from the model. Seventeen from engineering.

53
Before — local llama3:latest (8B) on Ollama
70
Model swap only — DeepSeek V4 Flash, pre-change knowledge+17
79
+ document structure — heading-aware sections, doc links, 8k output limit+9
87
+ query planner fixes — routing and entity resolution+8

bars drawn to scale · full width = 101 scenarios

§ 02 / why an LLM
The compiler doesn't need one. The answer does.

Knowledge is compiled deterministically. The LLM only reads and cites it.

The part of EKOS that builds knowledge — observing repositories, databases and documents, recovering tables, symbols, call graphs and lineage, resolving identities, writing an append-only ledger — uses no LLM, and every fact carries the evidence it came from.

People don't ask a ledger questions in EKL, though. They ask “what depends on the redaction module?”. The LLM sits at the very end: it receives a small, typed evidence set the planner already assembled, writes the answer in plain language, cites the claims it used, and must say “Insufficient evidence” when the evidence doesn't answer. It never touches the source systems.

observerecover resolvecompile ledgerplanner + evidence LLM answer + citations
§ 03 / where
Every LLM touchpoint in EKOS

One required use, five opt-in ones.

WhereWhat the LLM does
ekos ask / REASONWrites the final answer from the evidence set and cites it. This is what the 101-scenario eval grades.
ekos eval runDrives the suite against a real workspace. Grading itself is deterministic keyword/id matching — no LLM judge.
document semantics · opt-inExtracts Concept objects and their relationships from prose documents.
architecture reasoning · opt-inClassifies crate roles; results are written as reviewable, never as fact.
llm-description · opt-inAdds evidence-grounded ai_overview / ai_usage text to modules and symbols.
docs --prose · rerank · NL-to-SQLProse overviews in generated docs, an opt-in LLM rerank of evidence, and the gated ClickHouse query bridge.
§ 04 / why DeepSeek wins
Knowledge held fixed: 53 → 70

The local model wasn't only smaller. It was reading a truncated prompt.

§ 05 / before and after
Before: local llama3 · After: DeepSeek V4 Flash + fixes

Every category but one improved.

CategoryBeforeAfterPassed shareChange
Architecture9/2018/20
+9
Code8/1513/15
+5
Dependencies10/1210/12
0
Lineage5/1210/12
+5
History3/1211/12
+8
Security7/1210/12
+3
Adversarial11/1815/18
+4
Total53/10187/101
+34
85.7%
answer correctness (was 50.1%)
95.6%
evidence groundedness (was 65.9%)
3
hallucinated answers (was 7)
55.9%
recall@10 (was 64.7%) — see § 09
§ 06 / what we built
70 → 87 with the model held fixed

Better decomposition, smarter relations, a planner that asks the right question.

§ 07 / closed environments
What this means for self-hosted, air-gapped use

Compiling runs anywhere. Answering well needs real GPU servers.

The compile side of EKOS needs no GPU, no network and no model. Answer quality tracks the class of model you can serve: a workstation-sized local model gets roughly the “before” column. Reaching the “after” column without a cloud API means hosting a much larger open-weights model on dedicated GPU servers, with a context window of at least 32k tokens and enough throughput to answer in seconds rather than minutes.

ekos.toml — both shapes supported today
# hosted, or a self-hosted OpenAI-compatible server (vLLM, llama.cpp) inside the network
[llm]
provider    = "openai"
base-url    = "https://opencode.ai/zen/v1"
model       = "deepseek-v4-flash"
api-key-env = "OPENCODE_API_KEY"

[ai]
max-tokens  = 8192   # reasoning model: hidden reasoning counts against this

# local Ollama — set the window explicitly, never truncate silently again
[llm]
provider       = "ollama"
context-window = 32768

Another reason to self-host: prompts contain real source excerpts. EKOS redacts secrets and PII before anything reaches the ledger, but a hosted model still sees your code. Zen's paid models are zero-retention; its free models may use prompts for training.

§ 08 / what still fails
14 of 101, grouped by cause

The remaining failures are named, not averaged away.

CauseScenariosWhy
Premise rejected, not in refusal wordingadv-004 · adv-011 · adv-015The model correctly rejects a false premise (“the evidence does not confirm…”, “EKOS is MIT-licensed, free of charge”), but the grader only accepts an explicit refusal. Widen the grader or tighten the prompt — an open decision.
Answer never reaches the top of the evidencecode-002 · lin-008 · dep-004The function that builds the LLM provider ranks below the provider trait; the cited_evidence convention isn't in the evidence retrieved for that question; Rust import-path objects don't link back to the crate consuming the redaction module.
Facts not recorded yetcode-004 · lin-007 · dep-005The Rust edition is set once in the workspace Cargo.toml and inherited; struct fields like KirEvidence.confidence aren't emitted as claims; no caller of plan_question reached the evidence, so the model correctly can't answer — scored as ungrounded.
Ranking, not answeringarch-009 · hist-007Retrieval-only scenarios graded on recall@10. Documents are now many sections, which outrank the crate or file these scenarios expect — also why recall@10 fell while answers improved.
Right in substance, wrong keywordarch-020 · sec-002 · sec-010“Objects can't be deleted from the append-only ledger” without the word “tombstone”; “the security section is additive only” where the grader expects “extend”.
§ 09 / caveats
How to read these numbers

Honest about what the comparison can and can't show.

Reproduce it yourself

Same suite. Your model.

terminal
$ export OPENCODE_API_KEY=...
$ ekos eval run --config ekos.zen.toml --dataset ekos-full --save-answers
$ ekos eval history   # trend table across every saved run
Everything behind this deckWhere
Document structure + doc linksekos/docs/rfcs/0144-document-structure-and-links.md
LLM endpoints + context windowekos/docs/rfcs/0145-llm-endpoints-and-context-window.md
Write-ups with measurementsdevlogs/devlog_183.md (llama3 baseline), 185 (RFC 0144/0145, model comparison), 186 (planner fixes)
EKOS · 53 → 87 of 101 · deepseek-v4-flash via OpenCode Zen · github.com/alexeyban/EKOS