ai newsSa., 24. Okt.
EilmeldungKI-Agenten lesen bei indischen Firmen Live-Daten, ohne dass jemand es bemerkt

Zwei KI-Agenten, zwei Worktrees: Codex schreibt Tests blind, Claude Code laesst sie bestehen

Book: AI That Ships The series: AI in TypeScript — 5 books, from your first LLM call to agents in production — all five here My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub Ask one agent for parseDuration an

dev.toSamstag 10:01 · 24.10.DE10 Min. Lesezeit
Bild: dev.to

Fragt man einen Agenten in einem einzigen Prompt nach parseDuration und seinen Tests, erhält man eine Funktion und eine Testdatei, die zueinander passen. Ob eine der beiden mit eurer Spezifikation übereinstimmt, ist eine andere Frage, und die Tests können das nicht beantworten. Sie wurden von etwas geschrieben, das bereits wusste, was der Code tun würde.

Leute, die TDD-Workflows für Agenten aufbauen, laufen immer wieder in dieses Problem. Ein Claude-Code-TDD-Artikel auf alexop.dev beschreibt, wie in einem Kontextfenster die detaillierte Analyse des Test-Schreibers in das Denken des Implementierers hineinblutet, und teilt die Arbeit daher in separate Subagenten für Test-Schreiber und Implementierer auf. Der Skill tdd-context-split, der 2026 aktiv entwickelt wird, baut auf 2 Agenten mit minimalem Austausch: Der Test-Autor und der Implementierer teilen sich keinen Kontext, nur die Spezifikation. Auch Anthropics eigene Claude-Code-Best-Practices bringen es auf einen Satz: Ein Claude schreibt die Tests, ein anderes schreibt den Code, der sie erfüllt.

Diese Barrieren leben in Prompts und Subagent-Setups. Ein Prompt bittet den Implementierer, die Tests nicht anzufassen. Dieses Tutorial verlegt die Mauer in git. Codex schreibt die Tests allein aus der Spezifikation, auf seinem eigenen Branch in seinem eigenen Worktree, bevor es überhaupt eine Implementierung gibt. Ihr commitet sie und cherry-pickt diesen Commit in einen zweiten Worktree. Claude Code arbeitet dort unter einer Deny-Regel für die Test-Pfade. Ein einziger git diff zeigt euch dann, ob die Tests so zurückkamen, wie Codex sie hinterlassen hat.

Ausgangspunkt ist ein kleines TypeScript-Repo in ~/code/duration. Vier Dateien landen auf main, bevor einer der Agenten startet. Zuerst die Spezifikation, die alles ist, was Codex erhält:

# SPEC.md: parseDuration `src/duration.ts` exports `parseDuration(input: string): number`. - Returns whole seconds. - Units are h, m and s. At least one part is required. - Parts appear in the order h, m, s, each at most once: "1h30m" -> 5400, "45s" -> 45, "2h" -> 7200. - Leading and trailing whitespace is ignored: " 10m " -> 600. - Anything else throws a RangeError: "", "90", "1x", "30m1h", "1h1h", "-5m". Enter fullscreen mode Exit fullscreen mode Dann ein Stub, damit der Import auflöst und jeder Test zunächst rot ist:

// src/duration.ts export function parseDuration ( input: string ): number { throw new Error ( `not implemented: ${ input } ` ); } Enter fullscreen mode Exit fullscreen mode Die Tests laufen auf Nodes eingebautem Runner, daher gibt es nichts zu installieren. node:test ist seit Node 20 stabil, und Node führt.ts-Dateien direkt aus, seit Type Stripping mit Node 22.18.0 und 23.6.0 zum Standard wurde. Type Stripping entfernt nur die Typen, daher brauchen Imports die.ts-Erweiterung, und Enums sind tabu.

{ "name": "duration", "private": true, "type": "module", "scripts": { "test": "node --test \" test/**/*.test.ts \" " } } Enter fullscreen mode Exit fullscreen mode Die letzte Datei ist die Deny-Regel in.claude/settings.json:

{ "permissions": { "deny": [ "Edit(/test/**)", "Edit(/package.json)", "Edit(/.claude/**)" ] } } Enter fullscreen mode Exit fullscreen mode Laut der Permissions-Dokumentation gelten Edit-Regeln für alle eingebauten Tools, die Dateien bearbeiten, und ein führendes / in den Projekteinstellungen verankert das Muster am primären Arbeitsverzeichnis der Session. In einer Worktree-Session ist das der eigene Ordner des Worktrees. Die package.json-Zeile verhindert eine stille Umleitung des Test-Skripts, und die.claude/**-Zeile hält die Regeldatei selbst außer Reichweite. Deny rules block in every mode, so die Seite zu den Permission-Modes, einschließlich bypassPermissions. Deny-Regeln in den Projekteinstellungen greifen außerdem ohne den Workspace-Trust-Schritt, weil sie nur einschränken.

Committet alle vier Dateien. Die Regel ist für dieses Experiment da. Nehmt sie später heraus, wenn Claude in diesem Repo wieder Tests schreiben soll.

Gebt jedem Agenten seinen eigenen Worktree, beide von main abgeschnitten:

cd ~/code/duration git worktree add -b tests/duration../duration-tests main git worktree add -b impl/duration../duration-impl main cd../duration-tests codex --sandbox workspace-write --ask-for-approval on-request Enter fullscreen mode Exit fullscreen mode Beide Flags stammen aus der Codex-CLI-Referenz. Dann gebt ihr Codex die Aufgabe:

Read SPEC.md. Write tests for parseDuration in test/duration.test.ts using node:test and node:assert/strict. Import from "../src/duration.ts". Every expected value must come from SPEC.md. Cover each example and each RangeError case. Do not create or change anything outside test/. Run npm test: it should fail, because src/duration.ts is a stub. Enter fullscreen mode Exit fullscreen mode Es gibt noch nichts zum Hineinspähen. Der einzige Code im Repo ist ein Stub, der eine Exception wirft. Der /tdd-Skill auf AI Hero enthält die Regel, an die man Codex halten sollte: Erwartete Werte müssen von woanders stammen: ein bekannt guter Literalwert, ein durchgerechnetes Beispiel, die Spezifikation. Die Art von Test, die man zurückbekommen will, sieht so aus:

import { test } from " node:test "; import assert from " node:assert/strict "; import { parseDuration } from "../src/duration.ts "; test ( " combines hours and minutes ", () => { assert. equal ( parseDuration ( " 1h30m " ), 5400 ); }); test ( " rejects parts out of order ", () => { assert. throws (() => parseDuration ( " 30m1h " ), RangeError ); }); Enter fullscreen mode Exit fullscreen mode Dieses Tutorial verlässt sich für Codex nicht auf eine Pfadregel. Ihr prüft seine Arbeit mit git, bevor irgendetwas committet wird:

git status --short npm test git add test git commit -m "Tests for parseDuration, from SPEC.md" Enter fullscreen mode Exit fullscreen mode git status --short sollte nur Pfade unter test/ und sonst nichts auflisten. npm test sollte fehlschlagen. Wenn ein Test gegen einen Stub, der eine Exception wirft, besteht, testet er nichts, also geht er zurück. Lest die Tests auch selbst. Das ist der eine Punkt im Ablauf, an dem ein Mensch prüft, ob sie zur Spezifikation passen.

Wechselt in den Implementierungs-Worktree und holt den Test-Commit herein:

cd../duration-impl git cherry-pick tests/duration npm test claude --permission-mode acceptEdits Enter fullscreen mode Exit fullscreen mode git cherry-pick wendet die Änderung an, die ein Commit einführt, und zeichnet dafür einen neuen Commit auf. Es benötigt einen sauberen Working Tree, was ein frischer Worktree hat. npm test ist wieder rot, aus demselben Grund. Nun die Aufgabe für Claude Code:

npm test fails. Make it pass by changing src/ only. The tests in test/ come from SPEC.md and are fixed: you can't edit them. If a test looks wrong to you, stop and tell me which one and why. Enter fullscreen mode Exit fullscreen mode Ein Agent, der einen Test, dem er widerspricht, nicht bearbeiten kann, braucht einen Ausweg, der nicht darin besteht, ihn zu umgehen. Die letzte Zeile des Prompts ist dieser Ausweg.

Im acceptEdits-Modus bearbeitet Claude Code Dateien ohne Nachfragen und genehmigt außerdem automatisch mkdir, touch, rm, rmdir, mv, cp und sed innerhalb des Arbeitsverzeichnisses. Andere Bash-Befehle fragen weiterhin nach, abgesehen von einem eingebauten Read-only-Set. Die Deny-Regel steht über all dem.

Wenn die Suite grün ist, vergleicht die geschützten Pfade mit dem Commit, aus dem Codex' Tests stammen:

git diff --exit-code tests/duration -- \ test / package.json.claude/ git status --short -- test / git diff --stat tests/duration Enter fullscreen mode Exit fullscreen mode Der erste Befehl vergleicht euren Working Tree mit der Spitze von tests/duration, aber nur auf diesen Pfaden, und beendet sich mit non-zero, falls etwas abweicht. Der zweite fängt neue, ungetrackte Dateien unter test/ ab, die git diff nicht zeigt. Der dritte zeigt, was Claude insgesamt geändert hat, und das sollte allein src/ sein.

Diese Prüfung braucht ihr, weil die Deny-Regel eine Grenze hat, und die Dokumentation sagt genau, wo sie liegt. Read- und Edit-Deny-Regeln decken Claudes eingebaute Datei-Tools ab, Datei-Befehle, die Claude Code in Bash erkennt, etwa cat, head, tail, sed und tee, sowie Redirect-Ziele wie > file. Sie decken keine beliebigen Subprozesse ab, die Dateien indirekt lesen oder schreiben, etwa ein Python- oder Node-Skript, das Dateien selbst öffnet. Für eine Blockade auf OS-Ebene verweist die Dokumentation auf Sandboxing. Die Regel macht es Claude schwer, einen Test zu bearbeiten. Der Diff sagt euch, ob es trotzdem passiert ist.

Wenn alle drei Befehle sauber durchlaufen, committet und mergt:

git add src git commit -m "Implement parseDuration" cd ~/code/duration git merge impl/duration git worktree remove../duration-tests git worktree remove../duration-impl git branch -d impl/duration git branch -D tests/duration Enter fullscreen mode Exit fullscreen mode git branch -d verweigert tests/duration, und das ist richtig so. main enthält eine gecherry-pickte Kopie des Test-Commits, nicht den Commit selbst, daher kann git diesen Branch nicht als gemerged erkennen. Verwendet -D, sobald die Diff-Prüfung bestanden ist.

Ich baue Hermes IDE, also bewertet diesen Abschnitt vor diesem Hintergrund. Alles oben Genannte funktioniert in einfachen Terminals. Hermes erspart euch die Buchhaltung und ersetzt die git-diff-Prüfung nicht.

Drückt ⌘N (Ctrl+Shift+N auf Windows und Linux), wählt Codex im Agent-Picker aus und fügt den Prompt aus Schritt 2 als Aufgabe ein. Hermes startet Codex in einem echten Terminal auf seinem eigenen hermes/-Branch in seinem eigenen Worktree, mit der Aufgabe als erstem Prompt. Wie im Screenshot unten listet die Sidebar den Branch jeder Session auf, sodass ihr den Namen des Tests-Branches dort ablesen könnt. Committet Codex' Testdateien über das Review Desk, das Stage, Unstage und Commit für jedes Projekt übernimmt.

Codex und Claude Code nebeneinander in Hermes 2.3.4, jeweils in einem eigenen hermes/ Worktree, mit Status, Kontextnutzung, Kosten und Branch in der Seitenleiste.

Drücke erneut ⌘N und wähle Claude Code. Beginne die erste Zeile der Aufgabe mit git cherry-pick <tests branch>, gefolgt vom Step-3-Prompt. Sobald der Agent startet, drücke Shift+Tab in seinem Terminal, um in den Accept-Edits-Modus zu wechseln, genau wie in jedem anderen Terminal (Permission-Modi). Claude Code hält an und fragt nach, bevor es den Git-Befehl ausführt. Der Attention-Inbox zählt die Agenten, die auf dich warten, und ⌘I springt zu dem, der am längsten wartet. Du antwortest direkt im Terminal des Agenten und siehst den exakten Befehl, bevor er ausgeführt wird. Hermes beantwortet niemals eine Berechtigungsanfrage für dich.

Wenn die Testsuite grün ist, öffne das Review Desk (⌘G) für Claudes Aufgabe. Es zeigt Änderungen entweder nach Turn oder nach Datei. Der Cherry-Pick selbst erscheint im ersten Turn. Alles unter test/ in einem späteren Turn bedeutet, dass Claude einen Weg um die Regel gefunden hat, und du kannst einen Zeilenkommentar hinterlassen, der direkt an Claude zurückgeht. Führe die Step-4-Befehle ebenfalls im Worktree-Ordner dieser Aufgabe aus, mit dem hermes/ Branch-Namen von Codex anstelle von tests/duration.

Das Review Desk (⌘G) in der By-Turn-Ansicht: jeder Turn mit seinen Dateien und Zeilenzahlen, das Diff des ausgewählten Turns und eine aus den Turns entworfene Commit-Nachricht.

Dann Land. Es committet, öffnet einen Pull Request oder merged lokal in einem Schritt, in den Branch, aus dem die Aufgabe gestartet wurde, und der Vorgang lässt sich rückgängig machen. Das Landen von Claudes Aufgabe bringt die gecherry-pickten Tests und die Implementierung gemeinsam in main. Hermes ist kostenlos, als Quelloffen unter BSL 1.1 verfügbar und läuft auf macOS, Windows und Linux. Es steht in keiner Verbindung zu Anthropic, OpenAI, Nous Research oder einem anderen Agent-Anbieter.

Git hält die Kontexte der beiden Agenten getrennt und verhindert, dass die Tests abdriften. Es kann die Tests aber nicht besser machen. Wenn Codex die Spezifikation falsch liest, wird Claude Code dieses Missverständnis implementieren. Deshalb endet Step 2 damit, dass du die Tests liest.

Es verhindert auch nicht, dass Claude überanpasst. Eine Funktion, die "1h30m" speziell behandelt, besteht einen Test, der nur "1h30m" prüft. Mehr Beispiele in der Spezifikation helfen, ebenso das Lesen von git diff --stat, um alles zu finden, was wie eine Nachschlagetabelle aussieht. Ich habe keine Belege dafür, dass ein geteilter Workflow weniger Bugs ausliefert. Was er dir bringt, ist enger gefasst: Die Tests, an denen du misst, wurden vor dem Code geschrieben und sind während der Codeerstellung unverändert geblieben.

Wenn du es ausprobierst, würde ich gerne wissen, was zuerst kaputtgeht: Codex' Tests, Claudes Geduld mit ihnen oder die Deny-Regel. Sag es mir in den Kommentaren.

Eine Testsuite, die der implementierende Agent nicht bearbeiten kann, ist ein Guardrail, und Guardrails sind die Hälfte dessen, worum es bei AI That Ships geht. Das Buch behandelt Evals, Guardrails, Kostenkontrolle und das Deployen auf Node.js, in TypeScript, für LLM-Features, die du nach der Demo weiter am Laufen halten musst. Wenn sich die git diff --exit-code-Prüfung oben wie der richtige Instinkt angefühlt hat, wendet das Buch diesen Instinkt auf alles rund um das Modell an.

Es ist Band 5 der Reihe AI in TypeScript, eine fünfbändige Serie, die von deinem ersten LLM-Aufruf bis zu Agenten im Produktionsbetrieb reicht. Wenn du dieses Zwei-Agenten-Setup ohne den Umgang mit mehreren Terminals nutzen möchtest, lade die Hermes IDE herunter oder verankere sie mit einem Stern auf GitHub.

Automatisch übersetzt. Das Original auf Englisch ist unten aufklappbar.

Original (Englisch) anzeigen

Ask one agent for parseDuration and its tests in a single prompt, and you get a function and a test file that agree with each other. Whether either of them agrees with your spec is a different question, and the tests can't answer it. They were written by something that already knew what the code would do.

People building TDD workflows for agents keep running into this. A Claude Code TDD write-up on alexop.dev describes how, in one context window, "the test writer's detailed analysis bleeds into the implementer's thinking," and splits the work into separate test-writer and implementer subagents. The tdd-context-split skill, under active development in 2026, is built on "2 agents with minimal sharing": the test author and the implementer "do not share a context, only the spec." Anthropic's own Claude Code best practices put it in one line: "have one Claude write tests, then another write code to pass them."

Those barriers live in prompts and subagent setups. A prompt asks the implementer not to touch the tests. This tutorial moves the wall into git. Codex writes the tests from the spec alone, on its own branch in its own worktree, before any implementation exists. You commit them and cherry-pick that commit into a second worktree. Claude Code works there under a deny rule on the test paths. Then a single git diff tells you whether the tests came back the way Codex left them.

Start from a small TypeScript repo in ~/code/duration. Four files go on main before either agent starts. First the spec, which is all Codex gets:

# SPEC.md: parseDuration `src/duration.ts` exports `parseDuration(input: string): number`. - Returns whole seconds. - Units are h, m and s. At least one part is required. - Parts appear in the order h, m, s, each at most once: "1h30m" -> 5400, "45s" -> 45, "2h" -> 7200. - Leading and trailing whitespace is ignored: " 10m " -> 600. - Anything else throws a RangeError: "", "90", "1x", "30m1h", "1h1h", "-5m". Enter fullscreen mode Exit fullscreen mode Then a stub, so the import resolves and every test starts red:

// src/duration.ts export function parseDuration ( input: string ): number { throw new Error ( `not implemented: ${ input } ` ); } Enter fullscreen mode Exit fullscreen mode The tests run on Node's built-in runner, so there is nothing to install. node:test has been stable since Node 20, and Node runs.ts files directly since type stripping became the default in Node 22.18.0 and 23.6.0. Type stripping only erases types, so imports need the.ts extension, and enums are out.

{ "name": "duration", "private": true, "type": "module", "scripts": { "test": "node --test \" test/**/*.test.ts \" " } } Enter fullscreen mode Exit fullscreen mode The last file is the deny rule, in.claude/settings.json:

{ "permissions": { "deny": [ "Edit(/test/**)", "Edit(/package.json)", "Edit(/.claude/**)" ] } } Enter fullscreen mode Exit fullscreen mode According to the permissions docs, Edit rules "apply to all built-in tools that edit files," and a leading / in project settings anchors the pattern at the session's primary working directory. In a worktree session, that is the worktree's own folder. The package.json line stops a quiet rewrite of the test script, and the.claude/** line keeps the rule file itself out of reach. "Deny rules block in every mode," says the permission modes page, including bypassPermissions. Deny rules in project settings also take effect without the workspace trust step, because they only restrict.

Commit all four files. The rule is there for this experiment. Take it out later if you want Claude writing tests in this repo again.

Give each agent its own worktree, both cut from main:

cd ~/code/duration git worktree add -b tests/duration../duration-tests main git worktree add -b impl/duration../duration-impl main cd../duration-tests codex --sandbox workspace-write --ask-for-approval on-request Enter fullscreen mode Exit fullscreen mode Both flags are from the Codex CLI reference. Then give Codex the task:

Read SPEC.md. Write tests for parseDuration in test/duration.test.ts using node:test and node:assert/strict. Import from "../src/duration.ts". Every expected value must come from SPEC.md. Cover each example and each RangeError case. Do not create or change anything outside test/. Run npm test: it should fail, because src/duration.ts is a stub. Enter fullscreen mode Exit fullscreen mode Nothing to peek at exists yet. The only code in the repo is a stub that throws. The /tdd skill on AI Hero has the rule worth holding Codex to: "Expected values have to come from somewhere else: a known-good literal, a worked example, the spec." The kind of test you want back looks like this:

import { test } from " node:test "; import assert from " node:assert/strict "; import { parseDuration } from "../src/duration.ts "; test ( " combines hours and minutes ", () => { assert. equal ( parseDuration ( " 1h30m " ), 5400 ); }); test ( " rejects parts out of order ", () => { assert. throws (() => parseDuration ( " 30m1h " ), RangeError ); }); Enter fullscreen mode Exit fullscreen mode This tutorial doesn't rely on a path rule for Codex. You check its work with git before anything is committed:

git status --short npm test git add test git commit -m "Tests for parseDuration, from SPEC.md" Enter fullscreen mode Exit fullscreen mode git status --short should list paths under test/ and nothing else. npm test should fail. If a test passes against a stub that throws, it isn't testing anything, so send it back. Read the tests here, too. This is the one point in the run where a human checks that they match the spec.

Move to the implementation worktree and bring the test commit in:

cd../duration-impl git cherry-pick tests/duration npm test claude --permission-mode acceptEdits Enter fullscreen mode Exit fullscreen mode git cherry-pick applies the change a commit introduces and records a new commit for it. It needs a clean working tree, which a fresh worktree has. npm test is red again, for the same reason. Now the task for Claude Code:

npm test fails. Make it pass by changing src/ only. The tests in test/ come from SPEC.md and are fixed: you can't edit them. If a test looks wrong to you, stop and tell me which one and why. Enter fullscreen mode Exit fullscreen mode An agent that can't edit a test it disagrees with needs a way out other than working around it. The last line of the prompt is that way out.

In acceptEdits mode, Claude Code edits files without asking and also auto-approves mkdir, touch, rm, rmdir, mv, cp and sed inside the working directory ( permission modes ). Other Bash commands still prompt, apart from a built-in read-only set. The deny rule sits above all of that.

When the suite is green, compare the guarded paths with the commit Codex's tests came from:

git diff --exit-code tests/duration -- \ test / package.json.claude/ git status --short -- test / git diff --stat tests/duration Enter fullscreen mode Exit fullscreen mode The first command compares your working tree with the tip of tests/duration on just those paths, and exits non-zero if anything differs. The second catches new, untracked files under test/, which git diff doesn't show. The third shows what Claude changed overall, which should be src/ alone.

You need this check because the deny rule has an edge, and the docs say exactly where it is. Read and Edit deny rules cover Claude's built-in file tools, file commands Claude Code recognizes in Bash "such as cat, head, tail, sed, and tee," and redirect targets like > file. They don't cover "arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself." For a block at the OS level, the docs point to sandboxing. The rule makes it hard for Claude to edit a test. The diff tells you whether it did anyway.

If all three commands come back clean, commit and merge:

git add src git commit -m "Implement parseDuration" cd ~/code/duration git merge impl/duration git worktree remove../duration-tests git worktree remove../duration-impl git branch -d impl/duration git branch -D tests/duration Enter fullscreen mode Exit fullscreen mode git branch -d refuses tests/duration, and it's right to. main holds a cherry-picked copy of the test commit, not the commit itself, so git can't see that branch as merged. Use -D once the diff check has passed.

I build Hermes IDE, so weigh this section with that in mind. Everything above works in plain terminals. Hermes saves you the bookkeeping, and it doesn't replace the git diff check.

Press ⌘N (Ctrl+Shift+N on Windows and Linux), pick Codex in the agent picker, and paste the Step 2 prompt as the task. Hermes starts Codex in a real terminal on its own hermes/ branch in its own worktree, with the task as its first prompt. As in the screenshot below, the sidebar lists each session's branch, so you can read the tests branch name off it. Commit Codex's test files from the Review Desk, which handles stage, unstage and commit for each project.

Codex and Claude Code side by side in Hermes 2.3.4, each in its own hermes/ worktree, with status, context use, cost and branch in the sidebar.

Press ⌘N again and pick Claude Code. Make the first line of the task git cherry-pick <tests branch>, followed by the Step 3 prompt. Once it starts, press Shift+Tab in its terminal to switch to accept-edits mode, the same as in any terminal ( permission modes ). Claude Code stops to ask before running the git command. The attention inbox counts the agents blocked on you, and ⌘I jumps to the one that has waited longest. You answer in the agent's own terminal, and you see the exact command before it runs. Hermes never answers a permission prompt for you.

When the suite is green, open the Review Desk (⌘G) on Claude's task. It shows changes by turn or by file. The cherry-pick itself shows up in the first turn. Anything under test/ in a later turn means Claude found a way around the rule, and you can leave a line comment that goes straight back to Claude. Run the Step 4 commands in that task's worktree folder too, with Codex's hermes/ branch name in place of tests/duration.

The Review Desk (⌘G) in By turn view: each turn with its files and line counts, the selected turn's diff, and a commit message drafted from the turns.

Then Land. It commits, opens a pull request or merges locally in one step, into the branch the task started from, and it can be undone. Landing Claude's task brings the cherry-picked tests and the implementation into main together. Hermes is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux. It isn't affiliated with Anthropic, OpenAI, Nous Research or any agent vendor.

Git keeps the two agents' contexts apart and keeps the tests from drifting. It can't make the tests good. If Codex misreads the spec, Claude Code will implement the misreading. That's why Step 2 ends with you reading the tests.

It also doesn't stop Claude from overfitting. A function that special-cases "1h30m" passes a test that only checks "1h30m". More spec examples help, and so does reading git diff --stat for anything that looks like a lookup table. I don't have evidence that a split workflow ships fewer bugs. What it does give you is narrower: the tests you grade against were written before the code and stayed put while the code was written.

If you try it, I'd like to know what broke first: Codex's tests, Claude's patience with them, or the deny rule. Tell me in the comments.

A test suite the implementing agent can't edit is a guardrail, and guardrails are half of what AI That Ships is about. The book covers evals, guardrails, cost control and deploying on Node.js, in TypeScript, for LLM features you have to keep running after the demo. If the git diff --exit-code check above felt like the right instinct, the book applies that instinct to everything around the model.

It is book 5 of AI in TypeScript, a five-book series that runs from your first LLM call to agents in production. If you want to run this two-agent setup without juggling terminals, download Hermes IDE or star it on GitHub.

Originaltitel: Two Agents, Two Worktrees: Codex Writes the Tests Blind, Claude Code Makes Them PassQuelle: dev.to (dev.to). Original öffnen