Etwa eine Woche lang lief auf OpenRouter ein Modell namens Ox Alpha. Kein Labor dahinter, kostenlos solange es dauerte, und dann das Übliche: Screenshots, Streit darüber, ob die Benchmarks etwas bedeuten, und Warten auf die Auflösung. Es war GLM 5.3-flash.
Kostenlos und namenlos ist eine gute Kombination für einen Test, den ich vor mir hergeschoben hatte. Ich arbeite sonst nicht mit OpenCode. Ich wollte wissen, ob ich einen Plan schreiben kann, der so genau ist, dass ein einziger Ausführungs-Prompt ihn bis zur ausgelieferten Seite trägt.
Das ist eine andere Frage als die, ob das Modell gut ist. Meine Zeit bei Agentenarbeit geht in den Abstand zwischen dem, was ich meinte, und dem, was ich aufgeschrieben habe. Schließt der Plan diesen Abstand, verschwindet die Zeit, und was übrig bleibt, ist der Teil, den kein Plan tragen kann. Diesen Rest wollte ich sehen.
Der Plan ist die Arbeit
Er wurde 1.153 Zeilen lang, und ihn zu schreiben hat länger gedauert als der Bau.
Die Regel, an die ich mich gehalten habe: jede Zahl darin muss gemessen sein und nicht bevorzugt, und jede Entscheidung kommt mit ihrer Begründung. Eine Begründung überlebt bis in den Code, eine bloße Anweisung nicht. Ein paar Zeilen wirken ohne Zusammenhang absurd:
- Preise kommen je Instanz, je Knoten, in Cent oder je GPU. Traue nie dem Feld einer Quelle, das schon je GPU rechnet.
- Ein historischer Datensatz markiert 38.620 von 46.589 Zeilen als reine CPU-Angebote. Ohne diesen Filter ist der Median null.
- Überspringe unbekannte Hardwarenamen. Rate nie einen. Ein Mapper, der rät, verdirbt eine Zeitreihe. Einer, der überspringt, hinterlässt eine Lücke, die sichtbar eine Lücke ist.
Nichts davon ist Wissen über GPUs. Es ist Wissen darüber, auf welche Weise genau vier bestimmte Preisquellen falsch liegen, und es stammt aus einer Recherchephase, die lief, bevor eine Zeile des Plans geschrieben war. Der Plan beginnt mit genau dieser Anweisung an sich selbst: erst ansehen, dann planen, nichts annehmen.
Das Zweite, was der Plan nach vorn zieht, sind die Entscheidungen, die man nicht nachrüsten kann. Ob die App auf dem Server oder im Browser rendert, setzt die Obergrenze für den Lighthouse-Wert, und man verschiebt sie später nicht, ohne die Hülle neu zu bauen. Lint-Regeln greifen nur, wenn generierter Code ab dem ersten Commit ausgenommen ist und nicht ab dem vierzigsten. Beides steht oben, als Randbedingung, nicht als Abschlussaufgabe.
Der Prompt hat nicht allein gearbeitet
Ein Ausführungs-Prompt heißt nicht ein Arbeiter. Er hat delegiert, und die Delegation hat Spuren hinterlassen: fünfzehn Untersuchungen kamen als geschriebene Berichte zurück, über dreizehn Domänen. Ein TanStack-Review gegen die Best Practices des Frameworks, ein Performance-Bericht, ein Animationsdurchgang, ein End-to-End-Audit, ein Design-Engineering-Audit, ein Review für Such- und Antwortmaschinen, ein Deploy-Bericht, ein Befund zum Vorrendern, drei getrennte Berichte zur Datenqualität des Crawlers und zwei Produktionsreife-Audits.
Sieben benannte Skills setzten den Prüfmaßstab, fünf davon Regelwerke für Motion und Design Engineering: emil-design-engineering, animation-performance, animation-accessibility, web-animation-design und transitions-polish, dazu grill-me, um die Aufgabenstellung vor dem Schreiben auseinanderzunehmen, und improve-animations für den Prüfdurchgang über das Ergebnis.
Dass sie Namen haben, ist der Teil, der wirkt. „Mach die Animationen schöner" ist eine Meinung, und ein Agent kann ihr zustimmen und nichts ändern. „Jede Animation liefert zwei Varianten, und reduzierte Bewegung ist eine davon" hält im Diff oder hält nicht. Ein Audit gegen ein benanntes Regelwerk ist ein reiner Lesedurchgang mit bestanden oder nicht bestanden pro Regel, und deshalb ist das Design-Engineering-Audit ein Dokument und kein Gespräch.
Die zweite Regel war, dass kein Modell die eigene Änderung abgenommen hat.
Was dabei herauskam
Drei Tage und eine Seite, die läuft: cmpinf.com, ein täglicher Medianpreis-Index für GPU-Miete, LLM-Token und Strom im Großhandel. Rund 29.000 Zeilen Quellcode in 57 Commits, 110 Unit-Tests, 43 End-to-End-Tests in 8 Suiten, 12 Routen, drei Cloudflare Worker.
Ich habe nachgezählt, statt zu glauben, und bei den End-to-End-Tests brauchte das zwei Anläufe. Ausgeschrieben sind nur 31. Die anderen zwölf entstehen in einer Schleife über die Routenliste. Die Suite meldet 43, die Datei zeigt 31, und beides ist richtig.
Lighthouse auf der ausgelieferten Seite, drei Läufe, Median:
Performance 100 Barrierefreiheit 100 Best Practices 100 SEO 92
LCP 589ms TBT 0ms CLS 0,002
Die acht fehlenden SEO-Punkte sind eine Content-Signal-Zeile, die Cloudflare in die robots.txt schreibt und die Lighthouse nicht kennt, also als Fehler wertet. Diese Signale sind ein Rechtevorbehalt nach Artikel 4 der EU-Urheberrechtsrichtlinie. Der ist mehr wert als acht Punkte, also bleiben sie.
Eine Sache hat den Durchlauf unterbrochen, und es war nicht der Plan. Ein kostenloses Vorschaumodell mit so viel Andrang läuft in Timeouts, also kam ich ein paar Mal zurück und sagte, es solle weitermachen. Das ist ein Transportfehler und kein Fehler der Aufgabenstellung, und man sollte beides getrennt zählen, sonst weiß man nicht mehr, welches von beidem man vor sich hat.
Wohin ein Plan nicht reicht
Und jetzt der Teil, um den es mir ging. Alles, was der Plan nicht abgedeckt hat, hatte eines gemeinsam: es wird erst sichtbar, wenn die Sache ausgeliefert ist.
Der klarste Fall ist eine Preload-Optimierung. Das Dokument lädt die vier API-Aufrufe der Startseite vor, damit sie mit dem HTML rausgehen und nicht erst, wenn das Bundle geparst ist. Diese Hinweise trugen crossorigin nur dann, wenn die API auf einer anderen Origin lag, mit der Begründung, ein gleichursprünglicher Fetch schicke Anmeldedaten, zu denen ein anonymer Preload-Eintrag nicht passt.
Die Begründung ist falsch, und schlimmer: sie war dort, wo sie geschrieben wurde, nicht prüfbar. In der Entwicklung läuft die API auf einem eigenen Port, also nahm die Bedingung immer den Cross-Origin-Zweig und der End-to-End-Test lief grün durch. Auf der ausgelieferten Seite ist die API gleichursprünglich, alle vier Hinweise meldeten „preloaded but not used", und die ganze Optimierung war wirkungslos, während sie wie eine aussah. Die Reparatur brachte das LCP von 600 ms auf 464 ms.
Kein Plan hätte das vorgeben können. Es ist keine fehlende Anforderung. Es ist eine Tatsache über den Unterschied zwischen zwei Umgebungen, und es existiert erst, wenn es beide gibt.
Drei weitere derselben Art, alle gefunden, indem die ausgelieferte Seite bedient wurde und nicht, indem jemand den Code las:
- Das Linting prüfte eine Datei mit, die Playwright nach jedem Lauf schreibt. Also wurde es rot wegen einer Ausgabe, die kein Mensch erzeugt hatte.
- Playwrights voreingestellte Worker-Zahl brachte den Entwicklungs-Proxy um. Acht Worker auf einer Maschine mit sechzehn Kernen erledigten ihn in drei von drei Läufen, die Antwortzeiten stiegen von 60 ms auf 890 ms, danach wurde jede weitere Anfrage abgewiesen. Die Suite hatte eine Maschinengrenze als Produktfehler gemeldet.
- Die Browser-Suite erklärte keine Abhängigkeit auf die App, die sie prüft, also enthielt ihr Cache-Schlüssel das Frontend nie. Eine Komponente ändern und die Tests laufen lassen ergab ein Bestanden, ohne dass irgendetwas ausgeführt wurde. Sie wurde grün auf einem kaputten Diagramm und auf dessen Reparatur gleichermaßen.
Vor dem letzten Punkt sollte man Respekt haben. Er ist der Grund, warum ich ein Prüfgatter, das ich nie habe scheitern sehen, inzwischen als ungetestet behandle. Zu dieser Regel bin ich auf dem teuren Weg gekommen, und ich habe darüber in dem Text über den Wechsel vom Schreiben zum Prüfen geschrieben.
Was ich jemandem sagen würde, der das versucht
Die unumkehrbaren Entscheidungen gehören an den Anfang des Plans, nicht ans Ende. Rendering-Modell, Geltungsbereich der Lint-Regeln und alles, was Geld oder Konten berührt, setzen Randbedingungen, gegen die danach alles andere gebaut wird. Keine davon lässt sich später ergänzen, ohne etwas aufzureißen.
Und dann sollte man hinnehmen, dass ein Plan genau einen Abstand schließt: den zwischen dem, was man meinte, und dem, was man aufgeschrieben hat. Vom Abstand zwischen der eigenen Maschine und der Produktion schließt er nichts. Diesen zweiten sollte man einplanen, statt sich von ihm überraschen zu lassen.
Next
Derselbe Plan ist inzwischen überarbeitet, mit allem darin, was dieser Durchlauf zutage gefördert hat, und auf ein anderes Produkt gerichtet. Dort gibt es noch keinen Commit, also auch nichts ehrlich Berichtbares, bevor es gelaufen ist.
Wenn du das selbst probierst: die Zahl, um die ich dich bitten würde, ist nicht die Punktzahl des Modells in irgendetwas. Es ist deine eigene Zählung. Wie viele deiner Folgenachrichten waren der Plan, der versagt hat, und wie viele waren etwas, das du nur durch Ausliefern lernen konntest. Ist die zweite Zahl die größere, dann tut dein Plan seine Arbeit und deine Testumgebung nicht.
Commit-Zahlen, Testzahlen und Lighthouse-Werte sind aus dem Repository gelesen und auf der Live-Seite gemessen, je drei Läufe, nicht aus der Erinnerung.
Baust du an etwas Ähnlichem?
Ich schreibe hier über Setups, die ich selbst benutze. Wenn du an etwas Vergleichbarem arbeitest, würde mich interessieren, wie dein Workflow aussieht.