Modul XII — Qualität, Evals & Testing
Modul XII beantwortet eine einzige Frage — macht mein Agent immer noch das Richtige? —, indem es Kandidaten-Outputs gegen versionierte Golden-Suites bewertet (scoring) und das Ergebnis als kanonischen, modulübergreifenden Nachweis ausgibt. Es ist ein Modul der Intelligence-Schicht: es misst, es führt das untersuchte Subjekt nicht aus und es agiert nicht auf der Infrastruktur. Diese Seite ist die Referenz dafür, was das Evals-Modul heute leistet, und für seine ehrlichen Grenzen.
Was es misst (und was es niemals ausführt)
Abschnitt betitelt „Was es misst (und was es niemals ausführt)“XII ist eine Mess-, keine Ausführungsschicht. Ein Kandidaten-Output erreicht es bereits
fertig erzeugt — aus der Testing-Sandbox (Modul XVII), aus CI, inline in der Anfrage oder
als gesampletes Signal aus einer realen Session — und XII bewertet ihn gegen die Fälle einer
Suite. Das einzige Modell, das XII jemals aufruft, ist der Judge (für den llm_judge-Scorer);
es führt niemals den untersuchten Agenten oder das Modell selbst aus. Outputs zu erzeugen ist
Aufgabe der Sandbox, nicht von XII.
Das Scorer-Set ist austauschbar. Deterministische, reine Built-ins decken die gängigen
Verträge ab — exact, contains, not_contains, regex, json_valid, json_equal
und numeric_range. Daneben steht ein llm_judge-Scorer, der über den Judge-Port ein
Modell aufruft, um anhand einer Rubrik zu bewerten.
Suites, Runs und das kanonische Artefakt
Abschnitt betitelt „Suites, Runs und das kanonische Artefakt“Eine Suite ist ein versioniertes Golden-Dataset: sie enthält ihre Fälle, einen Default-Scorer,
einen Bestehensschwellenwert und einen Regressionsschwellenwert. Fälle sind append-only und
unveränderlich pro Version — die Korrektur eines Falls prägt eine neue suite_version, niemals
eine Bearbeitung an Ort und Stelle, sodass das Dataset, das ein vergangenes Urteil erzeugt hat,
stets rekonstruierbar ist.
Ein Run bewertet jeden Fall einer Suite, aggregiert einen score und eine pass_rate und
persistiert drei Dinge: append-only Nachweise pro Fall, ein veränderbares Run-Aggregat und ein
zentrales EvalResult — das kanonische Artefakt (Suite, SubjectKind, SubjectID,
Score, Passed, OccurredAt, Metrics), das Compliance (XIII) und die UI lesen, ohne die
eigenen Tabellen von XII zu kennen. Runs werden synchron ausgeführt; der SSE-Stream eines
Runs gibt den persistierten Run wieder (Frames pro Fall, dann eine Zusammenfassung), er löst
nichts aus. Eine Regression ist ein Vergleich mit einem Baseline-Run. Liegt der
Score-Abfall über der regression_threshold der Suite und schließt das 95%-Intervall der
Pass-Rate-Differenz (Newcombe, Differenz von Wilson-Intervallen) null aus, setzt der Run
regressed und schreibt ein zentrales Finding (Kind = eval_regression). Ein Abfall
über dem Schwellenwert, dessen Intervall null enthält, wird als inconclusive_noise
markiert und nicht als Regression; der Vergleich zeigt das Intervall und beide Nenner,
sodass kleine Suites weniger Findings auslösen. Die automatische Baseline ist der letzte abgeschlossene Run derselben
Suite und desselben Subjekts, bei gesetzter Variante auch derselben Variante, ohne als inconclusive_noise markierte Runs. Dieser
Run kann eine andere Suite-Version, ein anderes Modell oder einen anderen Scorer
nutzen, und der Vergleich meldet nicht, was sich geändert hat. Nach einem Wechsel der
Suite-Version übergeben Sie eine explizite Baseline oder pinnen eine (POST /baselines).
Das Finding wird nach bestem Bemühen auf dem Bus als
finding.reported ausgegeben, damit Delivery-Module (Health/Benachrichtigungen)
es routen. Auf der Leseseite aggregieren Scorecards Pass-Rate, mittleren Score und Trend pro
Subjekt und exportieren als CSV/JSON.
Minimal-data, konstruktionsbedingt
Abschnitt betitelt „Minimal-data, konstruktionsbedingt“Der Kandidaten-Output wird niemals persistiert — aus keiner Quelle. Ein Ergebnis pro Fall
speichert nur einen Einweg-Detail-Hash und ein geklammertes, bereinigtes Label für die UI; die
Maskierung erledigt der Handler vor der Speicherung, sie wird niemals vom Store vorausgesetzt. Der
Monitor bewertet Verhaltenssignale einer realen Session — ihren Zustand, die Finding-Anzahl,
die maximale Schwere und Token-/Kostenwerte (aus den zentralen Signalen Session, Finding und
CostRecord) — und niemals den rohen Output-Text, den die Plattform überhaupt nicht persistiert.
Golden-Fixtures sind die eine begrenzte Ausnahme: betreiberautorisiert, opt-in, nicht-produktive
Inhalte, vom Handler vor dem Schreiben geklammert, damit eine Suite tatsächlich ausgeführt werden kann.
Judge-Kalibrierung, Bias-Minderung und das CI-Regressions-Gate
Abschnitt betitelt „Judge-Kalibrierung, Bias-Minderung und das CI-Regressions-Gate“Den Urteilen des Judge wird erst vertraut, nachdem sie gemessen wurden. Ein menschlich
gelabeltes Kalibrierungs-Set (erstellt mit der geführten Session olivares evals label) speist
einen Kalibrierungs-Run, der den Judge gegen die menschliche Referenz misst: prozentuale
Übereinstimmung mit ihrem 95%-Wilson-Intervall, Cohens Kappa (Übereinstimmung allein ist
unter Klassenungleichgewicht nicht vertretbar), Sensitivität/Spezifität mit ihren Nennern und
eine Verbosity-Bias-Korrelation. Der Report ist append-only Nachweis; das Ziel —
Übereinstimmung ≥ 0,85 und ein definiertes Kappa ≥ 0,6 — kann pro Run angehoben, aber niemals
gesenkt werden. Ein Set, dessen menschliche Labels alle „pass” lauten, kann keine zufallskorrigierte
Übereinstimmung messen und zertifiziert nichts.
Bias-Minderung ist eingebaut und gemessen: der Judge-Prompt erzwingt die Begründung vor
dem Urteil (die Analyse wird im Flug verworfen — Minimal-data) und weist an, Länge nicht zu
belohnen; der opt-in paarweise Modus des A/B-Vergleichs bewertet jeden geteilten Fall zweimal mit
vertauschter Präsentationsreihenfolge, erklärt einen Sieger nur, wenn beide Reihenfolgen
übereinstimmen, und berichtet die gemessene position_consistency-Rate.
Das Regressions-Gate (POST /gate, CLI evals gate) verwandelt all dies in ein
blockierendes CI-Urteil: eine Regression gegenüber der Baseline, eine Pass-Rate unter dem
Suite-Schwellenwert oder ein unkalibrierter Judge lässt das Gate scheitern (Exit 1); ein
fehlender Judge-Credential degradiert zu einer deklarierten Warnung, niemals zu einem stillen
Pass. Der Seed des Gates wählt die Fälle der Stichprobe; er macht ein entferntes Modell nicht
deterministisch. Ein Treffer im Urteils-Cache (Schlüssel: Inhalt, Judge-Modell-Pin und
Prompt-Version) gibt das gespeicherte Urteil zurück. Ein Fehltreffer und jeder gewöhnliche
llm_judge-Run außerhalb dieses Gates rufen den entfernten Judge erneut auf und können
abweichen. Die FinOps-Vorprüfung läuft nur auf diesem Gate. Gilt für die Judge-Aufrufe
kein FinOps-Budget, das blockiert oder drosselt, erlaubt das Gate die Ausgabe. Ist der
Budgetspeicher nicht lesbar, verweigert das Gate die Ausgabe und scheitert mit
budget_blocked. Ein Budget, das blockiert oder drosselt, stoppt die Ausgabe. Der einzige
Ausweg aus einem gescheiterten Gate ist das gesteuerte Override — Admin-Stufe, schriftliche
Begründung, auditiert —, das das effektive Urteil ändert, das CI erneut prüft, niemals das
aufgezeichnete. Jede berichtete Rate kommt mit ihrem Nenner und 95%-Intervall, ebenso der Regressionsvergleich.
Siehe
docs/EVAL-METHODOLOGY.md im Repository für die vollständige Methodik und Quellen.
Verwandt
Abschnitt betitelt „Verwandt“- Modulkatalog — wo XII sitzt und die Trennung von Govern/Actuate.
- Event-Bus-Referenz — das
finding.reported-Event, das eine Regression ausgibt. - Architekturüberblick — die Intelligence-Schicht.
- Steuern und genehmigen — auf ein Regressions-Finding reagieren.
- Ehrlichkeit & Grenzen — die deny-closed Nähte über das Produkt hinweg.