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:
- Die Basis sitzt überall. Manuelle Steuerung, Tastatur und Berührung bestehen in jeder Zeile, auch in der abgestürzten. Das war in v2 nicht so — dort hat der Grader Pointer-Event-Builds fälschlich für tot erklärt. Der Defekt ist behoben, und das Ergebnis zeigt es.
- Der Inhalt bleibt liegen.
weapons_12schafft niemand,evolutions_5niemand,evolution_1nur zwei Zeilen. Die Agenten bauen ein funktionierendes Spiel und füllen es nicht. Zwölf Waffen sind Fleißarbeit, und Fleißarbeit über sieben Runden ist das, was hier fehlt — nicht Können. weapons_8schafft genau eine Zeile, und es ist Qwen. Das lokale Modell in derrec3-Konfiguration hat in Runde 3 mehr Inhalt eingebaut als jede Claude-Zeile.
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:
- Das lokale Modell ist nicht langsam. Qwen liefert 117–119 tok/s und liegt damit mitten im Feld, vor beiden Opus-Zeilen. Was ihm fehlt, ist Fenster, nicht Tempo.
- Cache-Treffer 94–99 % bei allen Remote-Zeilen, 0 % bei Qwen. Der lokale Aufbau hat kein Prompt-Caching. Bei einem Prompt, der dauerhaft bei 45–48k Token liegt, ist das der zweite große Hebel neben dem Fenster — und er ist bisher unangetastet.
- Die Prompt-Höchststände der Hermes-Claude-Zeilen liegen bei 500.000 Token. Hermes lässt den Kontext laufen, solange der Anbieter mitmacht. Genau das kann Qwen nicht, und genau daran stirbt er.
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:
- Je erzeugtem Token wird über den belegten Cache dequantisiert. Hadamard-Rotation plus 4-Bit-Schlüssel und 2-Bit-Werte je 128-Token-Kachel, entpackt beim Lesen. Das wächst mit der Sequenzlänge; die Dokumentation beziffert bei 112k einen Faktor 2,13, davon etwa 1,98 reine Schrittzeit.
- Ein fester Aufschlag je Anfrage. Der Aufmerksamkeitsblock muss auf dieser Stufe 2.048 Token groß sein, damit er zur Seitengröße des Gated-DeltaNet passt. Kurze Anfragen zahlen denselben Blockpreis wie lange und amortisieren ihn nicht — deshalb trifft es die flache Klasse am härtesten, genau wie gemessen.
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
- Der Grader muss selbst starten können.
?autoplay=1ist 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älltautoplayaus, soll er starten und das im Protokoll vermerken, statt die Zeile auf 4 von 24 festzunageln. - Zeitraffer im Grader.
__testHooks.speedsteht 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). - Werkzeugargumente zeichenweise zählen. Ein Feld im Proxy, und die Zeichen- Kennzahlen werden zwischen Harnesses vergleichbar (§5.2).
- Anzeigeart des Denkens protokollieren und angleichen. Solange eine Harness
omittedund die anderesummarizedschickt, ist der Reasoning-Vergleich wertlos (§5.1). Der Proxy zeichnet das Feld inzwischen auf; die Auswertung muss danach gruppieren. - Prompt-Caching für den lokalen Aufbau. 0 % gegen 94–99 % ist der größte ungenutzte Hebel der ganzen Kampagne (§6).
- Mindestens zwei Läufe je Zeile, sonst bleibt jeder Abstand unter drei Punkten eine Anekdote (§5.3).
- 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.