--- name: porting-zeus-to-the-browser description: "I had Claude Code port a 155k-line C++ city builder to TypeScript. The first attempt compiled and was unplayable. The second one worked. Here's what changed, the bugs, and the $5,747 receipt." allowed-tools: - Bash - Read - Edit - Write - Grep - Glob - Agent --- ## Harness-First Code Port with Agent Waves Port a large codebase to another language or runtime by building a behavioural test harness first, then running waves of parallel subagents with disjoint file ownership and a single integrator. ## Signals to apply - User asks to port, convert, or rewrite a codebase of more than ~10k lines into another language or platform - The source code is the only spec (no test suite, no written requirements) - A previous port attempt compiles but "doesn't work" or cannot be verified - The work is large enough that multiple subagents will edit one tree concurrently ## Implementation steps 1. Inventory the current state before porting: count source units with no counterpart in the target, and count stub bodies (for example methods that throw "STUB not implemented"). 2. Build the harness before any further porting: - A headless driver (Playwright or equivalent) against a dev server with hot reload OFF - An in-app probe object exposing: start a known scenario, perform domain actions by NAME through the real pipeline (not by setting internal state), advance time deterministically, read state, round-trip a save and compare bytes - Error capture: any page error, console error, or harness error fails the test - First spec: attempt every top-level feature by name and record what throws. This gap list becomes the wave briefs. 3. Write the rules where subagents can read them: a short root CLAUDE.md, an AGENT_BRIEF.md, and role files (porter, playtester, integrator, reviewer). Do not rely on session memory. 4. Run a wave: 4-5 agents in parallel, each brief containing CLUSTER, current state from the harness, source files to read, YOU OWN (paths), DO NOT EDIT (paths and who owns them), DELIVERABLE phrased as a harness-verifiable outcome, and a spec file to write. 5. Assign each shared hot file to exactly one agent per wave. Every other agent writes the exact patch it needs under an INTEGRATOR TODO heading in status/.md, written in final form BEFORE its last long-running command. 6. Agents verify only their own slice: their spec, a boot smoke test, and the type checker. They never run the full suite. 7. After the wave, run ONE integrator agent alone: apply all INTEGRATOR TODO patches, run the full suite (backgrounded to a log), fix, commit. 8. Every wave, include at least one playtester agent: "reach the way a user would, and fix every defect at its root", with a defect log (symptom, root cause, fix, covering test). 9. Add mechanical fidelity audits as they become possible: source declarations vs target (missing methods, stub bodies, ownership semantics such as weak pointers ported as strong references). 10. Convert data-shaped source (generated tables, registries) with a script, and verify by counts against the source. 11. Do not simplify or optimise while porting. Once behaviour is locked in by tests, verify every optimisation against a whole-state fingerprint (hash of the full simulation state after a fixed deterministic run); an unchanged hash is the pass condition. 12. For questions of feel (scrolling, animation, input latency), build a lab page with 4-5 switchable variants plus live measurements, and have the human rank them. Fold the winner into defaults. ## Quick start AGENT BRIEF TEMPLATE Read AGENT_BRIEF.md first and follow it. CLUSTER: CURRENT STATE: SOURCE OF TRUTH: YOU OWN: , test/.spec.ts, status/.md DO NOT EDIT: (owned by this wave). Needed changes go under INTEGRATOR TODO in your status file as exact patches. DELIVERABLE: , no errors during a long deterministic fast-forward, save round-trips byte-exact. VERIFY: your spec + boot smoke + type check only. Foreground commands with timeouts. No background waiters or monitors. REPORT: write status/.md in final form before your last long command. ## Key constraints - Input tests must use real pointer and keyboard events at CSS coordinates, at device pixel ratio 1 AND 2. Probes that set hover or selection state directly hide coordinate bugs. - A screenshot described in prose is not verification. Add a pixel or bounding-box assertion. - Assert on state after deterministic time advance, never on wall-clock time. Any wall-clock budget inside the simulation (for example a per-tick millisecond limit) makes results load-dependent; budget by work units instead. - Enforce test worker counts and suite locks in config, not in prompts. - Every spec must finish inside the shell command time cap, or agents will spawn orphaned background runs. - Cap concurrent agents at 4-5 on one machine, and lower when a human is using the same machine. - Never verify a game loop in a hidden or embedded preview tab: requestAnimationFrame is throttled there. - When the source has upstream bugs, port them verbatim and flag them; change behaviour only with an explicit, commented deviation. - Custom agent types load at session start. In the session that creates them, spawn a general-purpose agent and instruct it to read the role file.