Bericht

Die Auswertung der v3-Kampagne — was die Agenten taugen und welche Konfiguration das lokale Modell trägt. Gerendert aus benchmarks/antifa_survivors_v3/BERICHT.md.

Antifa Survivors v3 — Bericht

Stand: 2026-09-11 · Spiele und Auswertung: <./> · Spezifikation: docs/superpowers/specs/2026-09-09-antifa-survivors-v3-design.md · Rohdaten: benchmarks/antifa_survivors_v3/runs/


1. Kurzfassung

v3 sollte zwei Fragen trennen, die v2 vermischt hat: Was taugen die Agenten? und Welche Harness-Konfiguration trägt ein lokales Modell? Beide sind beantwortet.

Was die Agenten taugen. Über sieben Runden hat keine der acht Claude-Zeilen die Spezifikation vollständig umgesetzt. Der beste Wert der Kampagne sind 20 von 24 Fähigkeitspunkten, erreicht von Claude Sonnet 5 in Hermes in Runde 6 — und, aus dem Stand gleichauf, von Qwen3.8-27B in der Konfiguration rec3 in Runde 3. Die Harness entscheidet dabei mehr als das Modell: Sonnet 5 und Opus 5 holen in Hermes sechs bis acht Punkte mehr als in Claude Code, bei identischem Modell und identischer Aufgabe.

Welche Konfiguration Qwen trägt. Keine der vier getesteten Konfigurationen bringt Qwen über sieben Runden. Der Grund ist nicht das Modell, sondern eine Größenrelation: das Artefakt wächst schneller als das Fenster. Ab etwa 100 kB Build passt Lesen und Zurückschreiben nicht mehr in ein 65.536er Fenster, und die Runde stirbt an der Kompaktierung, nicht an der Aufgabe. Die beste Konfiguration (rec3) verschiebt diese Grenze deutlich und erreicht dabei den besten Qwen-Wert der Kampagne; sie hebt sie nicht auf.

Was wir dabei über uns selbst gelernt haben. Zwei Dinge. Erstens: Die von mir vorab empfohlene Konfiguration war die mit Abstand schlechteste (§4.2). Zweitens: Die schwächste Zeile der Kampagne ist zu einem großen Teil ein Messfehler — das Spiel läuft, nur der Startknopf des Graders greift nicht (§3.2b).


2. Was gemessen wurde

Sieben Runden, jede ein Folgeauftrag an dieselbe Agentensitzung — kein Phasenplan, sondern so, wie man wirklich promptet. Der Agent bekommt die Spezifikation und den Hinweis, wo die Dateien liegen; die Datei bleibt auf der Platte und wird nicht in den Prompt geklebt. Das war der zentrale Defekt von v2 und ist in v3 behoben.

Bewertet wird zweifach:

Maß Bereich Bedeutung
Spielbarkeits-Gate 0–5 Lädt, zeigt Titelbild, startet per Taste und per Berührung, reagiert auf Eingabe, läuft flüssig
Fähigkeits-Checkliste 0–24 Die Inhalte der Spezifikation: Gegner, Waffen, Passive, Evolutionen, Bosse, Musik, Sieg

Jeder Build wird dreimal bewertet, gewertet wird der Median je Check; die Spannweite [min, max] steht bei jedem Ergebnis. Die Checkliste bekommt der Agent nie zu sehen — er bekommt die Spezifikation, aus der sie abgeleitet ist.

Zwischen Agent und Modellendpunkt hängt in jeder Zeile ein eigener Trace-Proxy. Er zählt mit, was sonst niemand sieht: Prompt- und Cache-Token je Aufruf, Zeit bis zum ersten Token, Token pro Sekunde, Anteil der Werkzeugergebnisse am Prompt.


3. Ergebnis A — was die Agenten taugen

3.1 Endstand

Acht Zeilen: vier Claude-Modelle × zwei Harnesses. Alle sieben Runden vollständig, alle bewertet. best ist der beste Rundenwert, r7 der Stand am Ende.

Zeile Gate best r7 Verlauf der Fähigkeitspunkte Build r7 aktive Zeit
Hermes · Sonnet 5 5 20 18 7 → 12 → 11 → 14 → 15 → 20 → 18 130 kB 1,7 h
Claude Code · Fable 5.1 5 18 18 9 → 10 → 10 → 13 → 14 → 14 → 18 165 kB 2,7 h
Hermes · Opus 5 5 18 16 9 → 10 → 10 → 13 → 14 → 18 → 16 373 kB 7,0 h
Hermes · Fable 5.1 5 17 17 8 → 9 → 9 → 9 → 13 → 17 → 17 176 kB 2,9 h
Claude Code · Opus 5 5 12 12 9 → 10 → 10 → 11 → 12 → 12 → 12 316 kB 6,7 h
Claude Code · Sonnet 5 5 12 12 7 → 10 → 10 → 10 → 12 → 11 → 12 134 kB 3,8 h
Claude Code · Haiku 4.5 4 11 11 6 → 8 → 8 → 10 → 9 → 9 → 11 118 kB 0,3 h
Hermes · Haiku 4.5¹ 0 4 0 4 → 4 → 4 → 4 → 4 → 0 → 0 59 kB 0,4 h

Aktive Zeit ist die Summe der Modellaufrufe je Zeile, um Pausen bereinigt (Lücken über 15 Minuten herausgerechnet). Sie enthält keine Bewertungszeit.

¹ Diese Zeile misst überwiegend einen Ausfall des Messhakens, nicht die Bauqualität — siehe §3.2b.

3.2 Die Harness entscheidet mehr als das Modell

Derselbe Modellname, zwei Harnesses — und der Abstand hat kein Vorzeichen:

Modell Hermes best Claude Code best Differenz
Sonnet 5 20 12 +8 für Hermes
Opus 5 18 12 +6 für Hermes
Fable 5.1 17 18 −1
Haiku 4.5 4 11 −7 für Hermes¹

Das ist das wichtigste Einzelergebnis von v3: wer zwei Modelle vergleichen will, muss die Harness festhalten, sonst misst er die Harness. Bei Sonnet und Opus holt Hermes sechs bis acht Punkte heraus, und dieser Abstand ist über alle sieben Runden stabil.

¹ Der Haiku-Wert ist als Modellaussage nicht belastbar. Die 4 Punkte entstehen überwiegend daraus, dass der Startbefehl des Graders in diesem Build nicht greift, nicht daraus, dass das Spiel nicht liefe. §3.2b stellt es nach.

3.2b Der Haiku-Einbruch: zwei getrennte Ursachen, beide nachgestellt

Die Zeile Hermes · Haiku 4.5 bleibt fünf Runden auf Gate 1 und 4 Punkten und fällt dann auf 0. Das sieht nach einem Modell aus, das nichts zustande bringt. Es ist etwas anderes. Ich habe beide Builds im selben Browser nachgestellt, den auch der Grader benutzt.

Runden 1–5: Das Spiel läuft. Der Messhaken fehlt. Lädt man r5 und drückt die Leertaste, startet das Spiel, der Bildschirm ändert sich in jedem Einzelbild, nach acht Sekunden stehen drei Abschüsse auf der Uhr. Was fehlt, ist ?autoplay=1 — und zwar durch eine Ringabhängigkeit im Build:

// in start_run(), also erst NACH dem Start:
state.autoplay = get_param("autoplay") === "1";

// in der Spielschleife, Bedingung für den Start:
if (state.autoplay && state.title_elapsed > TITLE_SCREEN_DT) start_run();

Das Merkmal autoplay wird erst gesetzt, wenn der Lauf beginnt — und der Lauf beginnt nur, wenn das Merkmal gesetzt ist. Gemessen mit ?autoplay=1: state.autoplay bleibt false, mode bleibt "title", die verstrichene Spielzeit bleibt bei 0, und sechs Bildschirmfotos über neun Sekunden sind byteidentisch. Der Grader protokolliert wahrheitsgemäß „does not animate".

Fünf Runden, 20 von 24 Punkten, an einer einzigen fehlenden Zuweisung. Die Spezifikation verlangt den Haken, der Agent hat ihn nicht umgesetzt — das ist sein Fehler. Aber die gemessene Zahl beschreibt nicht die Bauqualität, sondern den Ausfall eines einzigen Messhakens. Das ist ein Defekt des Messaufbaus, nicht nur des Builds (§8, Punkt 1).

Die Gegenprobe gehört dazu: Genau eine weitere Zeile hat über die ganze Kampagne „animiert nicht" bekommen — Qwen · rec in Runde 1 —, und dort liegt es nicht am Haken. Unter ?autoplay=1 schaltet dieser Build ordentlich auf running und die Spielzeit läuft; er zeichnet nur nichts. Der Ausfall trifft also eine Zeile, nicht die Messung insgesamt. Alle übrigen Runden erreichen Gate 5, was ohne funktionierenden Haken gar nicht möglich wäre.

Runden 6–7: ein echter Absturz beim Laden. In Runde 6 schreibt der Agent die Datei vollständig neu und sie schrumpft dabei von 63 auf 55 kB. Im Browser:

TypeError: can't access property "length", state.enemies is undefined
@ game.js:375

Das Skript stirbt beim Laden, window.__state entsteht nie, die Leinwand bleibt auf ihrer Vorgabegröße von 300×150. Gate 0, 0 Punkte, und Runde 7 erbt den Schaden.

Die eigene Schlussmeldung des Agenten zu ebendieser Runde 6 lautet:

Verified: ✓ Syntax | ✓ All features | ✓ Boss mechanics | ✓ Stage progression | ✓ Victory/death endings | ✓ HTTP serving | ✓ No regressions | ✓ Ready for grading

Die Syntaxprüfung stimmt sogar — node --check geht durch. Der Build stirbt zur Laufzeit, und der Agent hat ihn nie geladen. Selbstberichtete Verifikation ist in diesem Datensatz wertlos; das gilt nicht nur für Haiku, sondern ist hier nur am deutlichsten zu sehen.

Was von der ursprünglichen Lesart übrig bleibt: Dieselbe Modellversion kommt in Claude Code auf 11 Punkte und stürzt dort nicht ab. Der Unterschied ist plausibel die Bearbeitungsart — Claude Code ersetzt Zeichenketten, Hermes ließ hier eine Ganzdatei-Neuschrift zu, und genau diese Neuschrift hat die Zustandsinitialisierung verloren.

3.3 Wo alle scheitern

Die Checkliste über die jeweils beste Runde jeder Zeile. X bestanden, . nicht.

Check ccFab ccHai ccOpu ccSon hFab hHai hOpu hSon qRec3 qStk
state_contract X X X X X . X X X X
title_screen X X X . X X X X X .
manual_control X X X X X X X X X X
keyboard_input X X X X X X X X X X
touch_input X X X X X X X X X X
kills X X X X X . X X X X
survives_window X . X X X . . X X .
music_playing . X . X . . X X X .
enemies X X X X X . X X X X
level_up X X X X X . X X X X
weapons_4 X . X X X . X X X X
weapons_8 . . . . . . . . X .
weapons_12 . . . . . . . . . .
passive_1 X . X X X . X X X X
passives_6 X . . . . . . . . X
evolution_1 . . . . . . X X . .
evolutions_5 . . . . . . . . . .
bystanders X X X X X . X X X .
nipster_hidden X X . . X . X X X .
nipster_revealed X . . . X . X X X .
boss_spawned X . . . X . X X X .
boss_defeated X . . . X . X X X .
stage_2 X . . . X . X X X .
victory . . . . . . . X X .

Drei Beobachtungen:

3.4 Große Builds sind kein Vorteil

Opus 5 schreibt in beiden Harnesses mit Abstand die größten Builds (316 kB und 373 kB) und braucht dafür die meiste Zeit (6,7 h und 7,0 h). Sonnet 5 in Hermes kommt mit 130 kB in 1,7 Stunden auf zwei Punkte mehr.

Zeile Build r7 aktive Zeit best
Hermes · Opus 5 373 kB 7,0 h 18
Claude Code · Opus 5 316 kB 6,7 h 12
Hermes · Sonnet 5 130 kB 1,7 h 20

Die Kennzahl „Zeilen Code" misst hier nichts Gutes.


4. Ergebnis B — welche Konfiguration Qwen trägt

4.1 Die vier Konfigurationen

Alle auf demselben lokalen Qwen3.8-27B, Fenster 65.536 Token.

Konfiguration Knöpfe Runden Gate Fähigkeitspunkte beste Runde
rec3 Schwelle 49.000, protect_last_n 6, target_ratio 0,1, Hauptmodell reasoning_effort low, Kompaktierung reasoning_effort none 4 5 12 · 12 · 20 · 20 (No-op) 20
stock unverändert, Hermes-Standard 5 5 8 · 8 · 9 · 9 (No-op) · 10 10
rec2 Schwelle 49.000, protect_last_n 6, target_ratio 0,1 1 5 8 8
rec (meine Empfehlung) Schwelle 40.000, max_tokens 16.384, effort medium 1 1 3 3

4.2 Meine Empfehlung war falsch

Die Konfiguration, die ich vor der Kampagne als „empfohlen" gesetzt habe, ist die schlechteste gemessene. Die Zahlen:

rec (empfohlen) stock (unverändert)
Kompaktierungen in Runde 1 57 8
Dauer Runde 1 179 min (Timeout) 66 min (sauber)
Ergebnis Runde 1 Gate 1, 3/24 Gate 5, 8/24

Die zu niedrig gesetzte Schwelle (40.000 bei 65.536 Fenster) löst eine Kompaktierungsschleife aus: Der Prompt pendelt zwischen 38–39k und 11–12k, jede zweite Anfrage ist die Kompaktierung, deren Zusammenfassung allein rund 11k Ausgabetoken kostet, und der geschützte Schwanz füllt den Prompt sofort wieder auf. In drei Stunden 299 Modellaufrufe und rund 800.000 erzeugte Token — für ein Ergebnis, das unter dem unveränderten Standard liegt.

Lehre: Eine Kompaktierungsschwelle unter etwa 70 % des Fensters ist kein Sicherheitspuffer, sondern ein Rückkopplungsmechanismus.

4.3 Warum die Runden sterben

Nicht am Modell. An einer Größenrelation, die man ausrechnen kann:

Posten Token
Build auf der Platte (101 kB) ~28.000
Spezifikation + Rundenauftrag + Systemprompt ~15.000
Summe für einmal Lesen ~43.000
Kompaktierungsschwelle bei 65.536er Fenster 49.152

Einmal Lesen belegt 88 % der Schwelle. Danach das Ergebnis zurückschreiben überschreitet sie zwangsläufig, Hermes kompaktiert, und weil der geschützte Schwanz die eben gelesene Datei enthält, bringt die Kompaktierung nichts. Nach drei Versuchen bricht die Harness ab: „Context length exceeded: max compression attempts (3) reached."

Das ist in allen vier Konfigurationen in Runde 2 passiert. Der gemessene Prompt-Höchststand bestätigt es: rec 55.000, rec2 62.114, rec3 60.931, stock 64.333 — alle drücken gegen die Wand des 65.536er Fensters.

Werkzeugergebnisse machen 16–35 % des Prompts aus; die Argumente der Werkzeugaufrufe (Ganzdatei-Schreibvorgänge) kommen oben drauf. Claude Code umgeht das strukturell: es ersetzt Zeichenketten statt ganzer Dateien und hält von großen Dateien nur eine 2-kB- Vorschau im Kontext. Das ist kein Modellvorteil, das ist ein Harness-Entwurf.

4.4 Was rec3 besser macht

rec3 dreht an einem Knopf, den sonst niemand anfasst: Die Kompaktierung selbst läuft mit reasoning_effort: none, geliefert über custom_providers[].extra_body. chat_template_kwargs — der einzige Weg, auf dem Hermes solche Felder überhaupt durchreicht. Gemessene Wirkung:

stock rec3
Größe einer Kompaktierungs-Zusammenfassung 18.000–25.000 Token ~9.800 Token
Reasoning-Anteil der Zusammenfassung ~0,80 0,20
Beste Fähigkeitspunkte 10 20
Build in der besten Runde 121 kB 109 kB

Eine Zusammenfassung, die halb so groß ist, lässt doppelt so viel Arbeitsfläche übrig. Runde 3 lief damit 168 Minuten sauber durch und landete bei 20/24 — gleichauf mit der besten Claude-Zeile der Kampagne.

Eine Einschränkung, die dazugehört: Dieser Durchbruch kam in Runde 3, also nach dem Abbruch in Runde 2. Unter der Regel „wenn eine Runde abbricht, ist gelaufen", die jetzt gilt, wäre er nie gemessen worden. Die Regel macht die Kampagne planbar und kostet Erkenntnis; beides ist wahr und beides gehört in den Bericht.


5. Messgrenzen — was dieser Bericht nicht sagt

Dieser Abschnitt ist nicht Pflichtprogramm. Er enthält die Punkte, an denen jemand die Zahlen sonst überdehnen würde.

5.1 Reasoning-Anteil ist zwischen Hermes und Claude Code nicht vergleichbar

Die Claude-Code-Zeilen stehen in den Rohdaten bei 0 % Reasoning. Das ist ein Anzeigeeffekt, kein Verhaltensunterschied, und der Proxy beweist es: Claude Code fordert

thinking: {"type": "adaptive", "display": "omitted"}

Hermes dagegen

thinking: {"type": "adaptive", "display": "summarized"}

Bei omitted liefert die Programmierschnittstelle überhaupt keine Denkblöcke aus — der Proxy kann nichts zählen, was nie über die Leitung geht. Die Token werden trotzdem erzeugt und berechnet. Aus diesem Datensatz lässt sich nicht ableiten, dass Claude Code weniger nachdenkt. Die Reasoning-Spalte ist nur innerhalb derselben Anzeigeart vergleichbar.

5.2 Werkzeugargumente werden nicht als Zeichen gezählt

Der Proxy zählt bei Antworten Text- und Denkzeichen, aber die Argumente von Werkzeugaufrufen nur als Anzahl, nicht als Umfang. Bei den Claude-Zeilen stehen deshalb 0,08–0,55 Zeichen je Ausgabetoken zu Buche, bei den Qwen-Zeilen rund 3,0. Der Unterschied ist überwiegend Buchhaltung, nicht Verhalten: Bei Claude steckt der Dateiinhalt in Werkzeugargumenten, bei Qwen im sichtbaren Text. Die Token-Summen stimmen in beiden Fällen, die Zeichen-Kennzahlen nicht.

5.3 Jede Zeile ist ein einzelner Lauf

Ein Lauf je Zeile. Jede Aussage über einen Abstand von ein oder zwei Punkten zwischen zwei Zeilen ist eine Anekdote. Die Abstände, die dieser Bericht als Befund führt (Harness-Effekt von 6–8 Punkten, der Haiku-Einbruch über sieben Runden, rec gegen stock), liegen deutlich darüber und sind im Verlauf stabil.

5.4 Die Streuung der Bewertung sitzt genau dort, wo es weh tut

Die drei Bewertungen je Build stimmen in 59 % der Runden exakt überein, im Median ist die Spannweite 0, im Mittel 0,76 Punkte. Das ist deutlich besser als die ±3 aus v2.

Aber die Ausreißer verteilen sich nicht zufällig — sie sitzen bei den besten Runden:

Zeile Runde Median Spannweite Breite
Hermes · Sonnet 5 7 18 [13, 19] 6
Hermes · Fable 5.1 7 17 [12, 18] 6
Hermes · Fable 5.1 6 17 [13, 17] 4
Qwen · stock 4 9 [3, 10] 7

Der Grund ist strukturell: Die Spätspiel-Checks (boss_spawned, boss_defeated, stage_2, victory) sind nur erreichbar, wenn die buildeigene Autoplay-Figur lange genug überlebt, und das Bewertungsfenster wird je Durchgang aus [180, 300] Sekunden gezogen. Bei Hermes · Sonnet 5 Runde 7 liefen alle drei Bewertungen technisch sauber (Gate 5, 59,6–59,8 fps, keine Ablehnung) und kamen auf 19, 19 und 13 Punkte. Der Unterschied sind sechs Spätspiel-Checks, die in einem Durchgang nicht erreicht wurden.

Bei Qwen · stock Runde 4 ist es etwas anderes: Eine der drei Bewertungen meldet Gate 1 und 0,0 fps — der Build ist in diesem Durchgang gar nicht angelaufen. Der Median fängt es ab, aber die Ursache ist ungeklärt.

Folge für v4: Der in der Spezifikation vorgesehene Zeitraffer __testHooks.speed ist im Grader nicht implementiert. Er ist der naheliegende Hebel: Spätspiel-Checks sollten über einen vom Grader gesetzten Zeitraffer geprüft werden, nicht über Echtzeit plus Glück.

5.5 Nicht gewertete Runden

Diese Runden sind nicht als 0 gewertet, sondern ausgeschlossen und hier benannt:

Zeile Runde Grund
Qwen · rec2 2 Kompaktierungsabbruch — auf Aarons Anweisung vom 2026-09-10 aus der Bewertung genommen
Qwen · rec2 3–7 Kampagne abgebrochen
Qwen · stock 6–7 auf Aarons Anweisung abgebrochen
Qwen · rec3 5–7 Regel „wenn eine Runde abbricht, ist gelaufen"
Qwen · rec 2–7 Zeile nach Runde 1 beendet

Zusätzlich sind zwei Runden No-ops: Qwen · stock r4 und Qwen · rec3 r4 sind byteidentisch zur Vorrunde — die Runde brach ab, bevor eine Datei angefasst wurde. Sie stehen mit dem Wert der Vorrunde in der Tabelle, tragen aber keine eigene Leistung.


6. Durchsatz

Median über alle Modellaufrufe der Zeile.

Zeile Aufrufe Prompt-Token gesamt Prompt max tok/s TTFT s Cache-Treffer Werkzeug-Anteil
Claude Code · Haiku 4.5 180 20,1 M 196.255 189,3 1,55 98 % 17 %
Hermes · Sonnet 5 417 109,5 M 499.929 139,6 1,21 99 % 48 %
Hermes · Haiku 4.5 172 10,9 M 140.897 132,6 0,84 94 % 18 %
Hermes · Fable 5.1 209 43,3 M 349.270 125,3 2,07 95 % 35 %
Claude Code · Sonnet 5 636 72,6 M 168.860 121,2 0,98 98 % 32 %
Qwen · stock 984 42,7 M 64.333 118,5 2,93 0 % 35 %
Qwen · rec3 738 28,3 M 60.931 116,7 2,59 0 % 27 %
Claude Code · Opus 5 1331 152,0 M 169.089 111,8 1,11 99 % 50 %
Hermes · Opus 5 676 171,6 M 500.491 104,7 1,30 96 % 42 %
Claude Code · Fable 5.1 88 20,1 M 391.639 85,8 2,11 96 % 72 %

Drei Dinge sind daran bemerkenswert:


7. Offene Zeile: die Serving-Achse

Die Diagnose aus Abschnitt 4.3 lautet „das Fenster ist zu klein". Die Gegenprobe dazu läuft noch: dieselbe rec3-Konfiguration auf einem größeren Fenster, erkauft über eine billigere Darstellung des Schlüssel-Wert-Zwischenspeichers (kvarn_k4v2_g128, 4 Bit für die Schlüssel, 2 Bit für die Werte).

Die Korrektheit dieser Stufe ist gemessen, nicht aus der Dokumentation übernommen. Gemessen auf local RTX 3090 host (RTX 3090), vLLM 0.27.1 mit syv-ai-Patches, bench/residue_sweep.py über 64 von 128 Restklassen: 0 defekt von 64, Deckung 1,00 in allen 64 Fällen, und der Antwort-Hash ist byteidentisch mit dem der bf16-Läufe (1c9a7c9afa9e). Auf dieser Aufgabe kostet der 4/2-Bit-Cache keine einzige abweichende Ausgabe.

7.1 Wie groß darf das Fenster sein

Der Zwischenspeicher-Pool ist nicht konstant — er wächst mit dem Fenster. Drei Messpunkte der Karte:

Fenster Pool (Token) Sequenzen je Fenster
131.072 209.132 1,60
98.304 180.980 1,84
81.920 164.297 2,006

Die Gerade Pool ≈ 96.524 + 0,859 · Fenster passt auf 0,5 %. Daraus folgt: Über zwei Sequenzen je Fenster kommt man erst unterhalb von etwa 84.600 Token — großes Fenster und Platz für zwei gleichzeitige Anfragen schließen sich auf dieser Karte aus.

7.2 Warum das für diese Zeile egal ist

Unser Preflight verlangte bisher zwei Sequenzen je Fenster. Diese Schwelle stammt aus der Zeit, als acht Zeilen gleichzeitig gegen denselben Endpunkt liefen, und wurde auf ein Einzelexperiment mechanisch weitergeschleppt. Die eigenen Traces widerlegen sie:

Zeile Aufrufe davon inflight = 1 inflight = 2
rec 299 299 0
rec2 223 223 0
rec3 740 740 0
stock 986 985 1
Summe 2.248 2.247 1

Hermes ist strikt sequenziell. Die Kompaktierung läuft nicht neben der Hauptanfrage, sie ist ein eigener Aufruf, der abgeschlossen ist, bevor der nächste beginnt. Die Zeile fordert Nebenläufigkeit 1 an.

Der Preflight prüft deshalb künftig, dass der Pool mindestens 1,25 volle Fenster fasst, statt zwei — und die Pool-Tabelle bekommt je Fenster einen gemessenen Eintrag, weil sich der Pool eben nicht hochrechnen lässt.

Eine Einschränkung, auf die uns der Betreiber der Karte gestoßen hat und die wir nicht selbst gesehen hätten: In v2 gab es bei 131.072 auf int8 und Nebenläufigkeit 1,04 ganze 125 Verdrängungen — und auch dort war Hermes sequenziell. Sequenzialität allein verhindert Verdrängung also nicht. Bei 1,04 bleiben von 136.429 Token nur 5.357 frei, während der Prefix-Cache seine Blöcke hält; eine Anfrage, die neue Blöcke braucht, verdrängt dann die eigene laufende Sequenz. Bei 1,60 sind es 78.060 freie Token, das Vierzehnfache. Sollte num_preemptions_total sich trotzdem bewegen, ist die Ursache vermutlich Druck auf den Prefix-Cache und nicht Nebenläufigkeit — der Hebel wäre dann PREFIX_CACHE=0, nicht ein größerer Pool.

7.3 Was die Zeile beantworten soll

Entscheidend ist nicht das Fenster, sondern Hermes' Kompaktierungsschwelle, die darunter passen muss:

Fenster Auslöser Lesen (43k) Lesen + Zurückschreiben (~71k)
65.536 49.000 knapp nein — hieran ist die Vergleichszeile gestorben
98.304 65.000 ja nein — misst „mehr Fenster"
131.072 86.016 ja ja — misst die eigentliche These

Gewählt ist deshalb 131.072. Nur dort lässt sich die Frage beantworten, wegen der die Zeile existiert: Überlebt Qwen sieben Runden, wenn das Artefakt vollständig ins Fenster passt? Bei 98.304 hätten wir vermutlich denselben Tod eine Runde später gemessen.

Die Auslöserwerte sind nicht die konfigurierten Zahlen, sondern die von Hermes daraus berechneten — nachgerechnet an ContextCompressor und anschließend im Lauf bestätigt. Der konfigurierte Anteil von 0,50 wird bei Fenstern unter 512k auf 0,75 angehoben (nur nach oben); der Auslöser entsteht aus (Fenster − max_tokens) × Anteil, und threshold_tokens greift erst, wenn es kleiner ist als dieses Ergebnis.

Die Bestätigung kam in Runde 2: Die erste Kompaktierung fiel bei einem Prompt von 88.875 Token. Damit ist der Auslöser 86.016 und nicht 90.000 — und daraus folgt etwas, das man dem Datenverkehr nicht ansieht: Die Angabe model.max_tokens: 16384 ist zwar tot, was den Anfragen zugeht (der Proxy sieht max_tokens: null in jeder einzelnen), sie erreicht aber den Kompressor und verkleinert dort den Auslöser um 12.288 Token. Eine Einstellung, die in einer Messung als wirkungslos gilt, steuert in einer anderen das Ergebnis.

Die Vergleichszeile bei 65.536 löst bei exakt 49.000 aus. Der Abstand zwischen beiden Zeilen ist also Faktor 1,76.

7.3b Was das große Fenster kostet — und warum man es nicht sauber trennen kann

Das größere Fenster ist auf dieser Karte nur mit dem 4/2-Bit-Cache zu haben, und der kostet Durchsatz. Bei gleicher mittlerer Sequenztiefe (Prompt plus halbe Antwort, also die Tiefe, die das Modell während des Erzeugens im Mittel gesehen hat):

mittlere Tiefe 65.536, bf16 131.072, KVarN Verhältnis
unter 20k 178,6 (n=34) 97,0 (n=1) 0,54
20k–40k 123,8 (n=250) 75,5 (n=10) 0,61
über 40k 110,7 (n=452) 66,3 (n=13) 0,60

Die beiden tiefen Klassen liegen bei 0,60 und 0,61, und die Tiefenkurven verlaufen parallel: Der Abstand sieht nach Cache-Typ aus, nicht nach Tiefe. Der 4/2-Bit-Cache kostet auf dieser Karte bei gleicher Tiefe rund 40 % Durchsatz. (Zahlen aus der noch laufenden Runde 1; sie werden nachgeführt, wenn die Zeile durch ist.)

Zwei dokumentierte Mechanismen erklären ihn, und sie greifen an verschiedenen Enden:

Die saubere Trennung ist auf 24 GB nicht herstellbar. Ein Gegenversuch „gleiches Fenster, anderer Cache" scheitert an der Karte: Der bf16-Pool fasst 68.605 Token, bei einem 131.072er Fenster wären das 0,52 Sequenzen. vLLM verweigert den Start mit „KV cache is needed, which is larger than the available KV cache". Das ist keine Bequemlichkeit, sondern die Grenze der Karte, und sie gehört als solche in die Auswertung: Auf dieser Hardware ist „großes Fenster" untrennbar mit „langsamer Cache" verbunden.

Wie ein Scheitern dieser Zeile zu lesen wäre. Wenn die Runden am Drei-Stunden-Limit sterben, ist das kein unauswertbarer Lauf. Es ist ein Ergebnis mit Etikett: Bei 131.072 passt das Artefakt ins Fenster, aber der einzige Cache-Typ, der dieses Fenster auf 24 GB trägt, ist so viel langsamer, dass die Runde am Zeitlimit stirbt. Das beantwortet die Ausgangsfrage — es sagt, dass die Karte zu klein ist, nicht dass die These falsch war.

Eine Zahl geht in die andere Richtung. Die Dokumentation erwartet, dass der quantisierte Cache die Logits so verschiebt, dass der Entwurfskopf seltener zustimmt, und veranschlagt rund 7 % Akzeptanzverlust. Gemessen wird das Gegenteil: 3,41 Token je Schritt (17.609 Entwürfe, 42.397 angenommene Token) gegen 3,05 auf bf16 und 2,97 auf int8 — 12 % besser statt 7 % schlechter. Die naheliegende Erklärung ist der Arbeitslast-Mix: Ein Agent, der eine bestehende Datei umschreibt, sagt zu großen Teilen voraus, was schon dasteht. Falls das stimmt, fällt der Akzeptanzverlust von KVarN bei genau dieser Art Arbeit nicht an.

7.3c Erstes Ergebnis: Runde 1 im direkten Vergleich

Dieselbe Konfiguration, dieselbe Aufgabe, dieselbe Runde — einmal im alten Fenster, einmal im neuen:

rec3 @ 65.536, bf16 rec3 @ 131.072, KVarN
Modellaufrufe 155 49
Kompaktierungen 13 0
höchster Prompt 49.928 70.692
Dauer 58 min 32 min

Der Prompt überschreitet mit 70.692 Token das gesamte alte Fenster. Diese Runde ist bei 65.536 nicht darstellbar, nicht einmal mit perfekter Kompaktierung. Der Auslöser dieser Zeile (86.016) wurde dabei nie erreicht — es gab schlicht nichts zu kompaktieren.

Bemerkenswert ist das Verhältnis von Kosten und Nutzen: Die neue Zeile erzeugt mit rund 60 % des Durchsatzes (§7.3b) und ist trotzdem fast doppelt so schnell fertig. Der Kompaktierungszyklus hat mehr gekostet als der langsamere Cache. Die 13 Kompaktierungen der alten Zeile sind nicht nur 13 zusätzliche Aufrufe, sondern der Grund für die übrigen 106 Aufrufe Unterschied: Nach jeder Kompaktierung muss sich der Agent neu orientieren und liest wieder, was er schon gelesen hatte.

Die Checkliste sagt etwas anderes als die Betriebszahlen. Derselbe Rundenauftrag, bewertet:

rec3 @ 65.536 rec3 @ 131.072
Gate 5 5
Fähigkeitspunkte 12 / 24 7 / 24
Spannweite [12, 12] [7, 7]

Die kleine Zeile hat in Runde 1 den Titelbildschirm und alle zwölf Waffen gebaut; die große hat keinen Titelbildschirm und keine Waffe über die Startwaffe hinaus. Sie war schneller fertig, mit weniger Aufrufen und ohne Kompaktierung — und hat dabei weniger gebaut. Der 50.588-Token-Planungsdurchgang zu Beginn (§7.3) hat einen Plan erzeugt, den der Agent dann nicht eingelöst hat.

Beides ist n=1, und der Rundeninhalt schwankt. Es ist trotzdem ein Warnschild gegen die naheliegende Erzählung: Mehr Fenster heißt nicht besserer Build. Die These dieser Zeile ist auch eine andere — sie lautet überlebt Qwen sieben Runden, nicht baut Qwen besser. Die Antwort darauf steht noch aus; der Build wächst, und mit ihm der Prompt.

7.4 Die zweite Gegenprobe: eine frische Sitzung je Runde

Wenn auch das größere Fenster die Zeile nicht durchbringt, läuft dieselbe Zeile ein zweites Mal — mit einer frischen Agentensitzung je Runde statt einer fortgesetzten.

Der Gedanke dahinter ist einfach: Was die Runden tötet, ist nicht die Aufgabe, sondern der Gesprächsverlauf, der kompaktiert werden muss. Eine frische Sitzung hat keinen. Sie bekommt je Runde die volle Spezifikation, den Rundenauftrag und den Hinweis, dass ihre Dateien im Arbeitsverzeichnis liegen. Sie verliert also Kontext, nicht Arbeit — genau die Unterscheidung, um die es in v3 ohnehin geht, weil die Datei seit v3 auf der Platte bleibt und nicht im Prompt klebt.

Beide Läufe unterscheiden sich in genau einem Punkt, der Sitzungsart; alles andere — Modell, Fenster, Schwelle, Aufgabe, leeres Arbeitsverzeichnis zu Beginn — ist gleich. Der Nachfolgelauf startet automatisch, sobald der erste seine erste abgebrochene Runde hat, und er beendet sich bei seiner eigenen ersten abgebrochenen Runde selbst.

8. Was v4 anders machen sollte

  1. Der Grader muss selbst starten können. ?autoplay=1 ist derzeit ein einzelner Ausfallpunkt: Greift der Haken nicht, misst der Grader einen Standbild-Titelschirm und schreibt „animiert nicht" — auch wenn das Spiel auf Tastendruck einwandfrei läuft (§3.2b). Der Grader kann Tasten drücken, er tut es im Gate ohnehin. Fällt autoplay aus, soll er starten und das im Protokoll vermerken, statt die Zeile auf 4 von 24 festzunageln.
  2. Zeitraffer im Grader. __testHooks.speed steht in der Spezifikation und fehlt im Code. Ohne ihn entscheiden Zufall und Fensterlänge über die Spätspiel-Checks — genau dort, wo die Rangfolge fällt (§5.4).
  3. Werkzeugargumente zeichenweise zählen. Ein Feld im Proxy, und die Zeichen- Kennzahlen werden zwischen Harnesses vergleichbar (§5.2).
  4. Anzeigeart des Denkens protokollieren und angleichen. Solange eine Harness omitted und die andere summarized schickt, ist der Reasoning-Vergleich wertlos (§5.1). Der Proxy zeichnet das Feld inzwischen auf; die Auswertung muss danach gruppieren.
  5. Prompt-Caching für den lokalen Aufbau. 0 % gegen 94–99 % ist der größte ungenutzte Hebel der ganzen Kampagne (§6).
  6. Mindestens zwei Läufe je Zeile, sonst bleibt jeder Abstand unter drei Punkten eine Anekdote (§5.3).
  7. Inhaltstiefe getrennt bewerten. Alle Zeilen bauen ein laufendes Spiel und füllen es nicht. Wenn v4 Fleißarbeit messen will, muss die Rundenaufgabe sie einfordern, statt sie als einen von 24 Checks zu führen.

9. Wo alles liegt

Was Wo
Spielbare Builds, alle Runden aller Zeilen <./>
Auswertung v3 mit Durchsatz, Ereignisleiste, Gantt, Titelbildwand <analytics.html>
Ältere Läufe (v1, v2) <archiv.html>
Rohdaten je Lauf, Traces, Screenshots benchmarks/antifa_survivors_v3/runs/
Spezifikation docs/superpowers/specs/2026-09-09-antifa-survivors-v3-design.md
Entscheidungen und Befunde der Umsetzung .superpowers/sdd/2026-09-09-antifa-survivors-v3/progress.md

Die Builds sind nicht veröffentlicht. Sie liegen ausschließlich im Tailnet. Der Spielinhalt ist eine politische Aussage; eine Veröffentlichung braucht Aarons ausdrückliche Freigabe.