The pipeline behind ChampChase
I wanted a game. I had no coding background. So I built a way to build it.
-
from the record
- Wave 3 / Terminal 1 of 6.
- Lock …t1_standing_rule_965.lock claimed pre-edit 2026-05-08.
- After: All 9 unguarded write sites neutralized.
- Compile: 0/0 (verified 4 times — once after each of the 4 files …)
- … had to re-Read the file once due to sibling-write detection …, then re-applied the Edit on the new anchor — single-iteration recovery
in plain words
Four editor tools could change the game's version and build numbers on their own, one of them on every run. Three of the nine write sites now sit behind a switch that is off by default; six are gone. Its record met a sibling's landing on the way into the ledger, so it read the end again and wrote once more.
-
from the record
- Wave 3 / Terminal 2 of 6.
- Lock …t2_known_problems_reconcile_966.lock claimed pre-edit.
- After: Both docs reflect repo HEAD@966. Closures cited inline with pass evidence.
- Compile: N/A (RECONCILE class — zero .cs modified …)
- … write-collision detected three times mid-write (siblings re-modified file between my Read and Edit attempts …; three-iteration recovery).
in plain words
No code: this session brought the known-problems and remaining-work lists back in line with what the repository actually was, with every closed item cited to the pass that closed it. Its siblings changed the shared state file under it three times. It landed last.
-
from the record
- Plan-time pass numbering 967 (head observed 964; lock dir empty at plan time).
- … renumbered 967 → 971 in single iteration (max active claim 970 + 1 = 971).
- Before: GoldenPathTest covered 5 of 13 build scenes …; 8 scenes uncovered = 62% gap.
- After: All 13 build scenes loaded by GoldenPathTest with per-scene system check via canonical class name …
- Compile: 0/0
in plain words
The end-to-end test walked 5 of the game's 13 scenes and missed the fight scene itself. It now loads all 13. By the time it claimed its lock, siblings held numbers up to 970, so it took 971.
-
from the record
- Plan-time pass numbering 968 (briefed slot, anticipating Wave 3 T1/T2/T3 land 965/966/967 first).
- Lock …t4_passtestconf_renumber_968.lock claimed pre-edit 2026-05-08; released post-record.
- After: Both drifts closed in a single coherent fix on the same file.
- Engineering impact: 6-terminal parallel write sessions can no longer silently corrupt the pass ledger via duplicate ## Pass N headers.
- Compile: 0/0 (… pre-existing 4 … warnings unchanged; 0 errors). Confirmed twice
in plain words
The tool that reads the pass history never noticed two records with the same number, and could not read headers written with a different dash. Both fixed in one file. It landed first.
-
from the record
- Wave 3 / Terminal 5 of 6.
- Lock claimed …t5_autowire_filter_969.lock pre-edit.
- At lock-claim, … held 5 sibling claims
- After: Filter widened to 23 entries — original 12 preserved unchanged + 11 new entries …
- Compile: … Build succeeded. 0 Warning(s) 0 Error(s)
in plain words
A tool that reconnects broken references by name could not see the component types the game had added since March. Eleven added, the original twelve kept. When it claimed its lock, all five siblings already held theirs.
-
from the record
- T6 Wave 3 / 4 file-disjoint MEDIUM-severity findings from Pass 963 TI Editor Tooling Audit closed pre-build.
- Lock …t6_medium_cluster_970.lock claimed pre-edit 2026-05-08; released post-record.
- Net +53 LOC across 4 files; zero changes outside owned set.
- … four consecutive 0/0 runs (after each of the 4 file edits).
- … append-collision detected once mid-write — sibling T3 (Pass 971 …) landed between my Read and Edit; re-read tail and re-anchored append on the new last line
in plain words
Four separate medium findings from the same audit, one per file. T3's record landed between T6 reading the end of the ledger and writing to it, so T6 read the end again and appended below it.
“… Wave 3 slot allocation T1=965, T2=966 …, T3=967, T4=968, T5=969, T6=970”
- 968 T4
- 971 T3
- 965 T1
- 970 T6
- 969 T5
- 966 T2
I wanted ChampChase to exist. I had no development, computer-science or coding background, so the first question was how to make it happen. The six-terminal pipeline grew out of that question: six AI sessions running in parallel over non-overlapping file sets, a lock protocol keeping them out of each other's way, and one human in the middle deciding what was allowed to survive. It has run 2,031 recorded passes (count as of 6 August 2026) and took a full game to public beta. With the names changed, the same architecture fits a business's own repetitive work.
// the problem
One person, a full game, no team
A full game is not a big website. It is a fight engine, a campaign, an economy, an inventory, a shop, a save system, a dialogue system, an audio director and a hundred screens that all have to agree with each other. I had one person and no prior game-development experience.
The naive version of "use AI for it" fails immediately and predictably: one session, one conversation, and a codebase that drifts out from under you until nothing compiles and nobody — human or otherwise — can say which change broke it. Throughput was never the hard part. Knowing what was true after each change was the hard part. So I built for that instead.
// the architecture
Six sessions, one coordinator, no shared files
A launcher script opens six sessions in a grid across two monitors. Each is assigned a non-overlapping set of files — the fight engine here, the campaign manager there, UI, audio, saves, content validation — so two of them can never be editing the same thing at the same time. Ownership is enforced by a lock protocol: a folder of lock files, claimed before work starts and released after. Deliberately the dumbest mechanism that could work, because a coordination system nobody can debug at 2am is worse than no coordination system.
I sat in a seventh window as the coordinator. That role is not supervision, it is the actual job: assigning work so the slices stay disjoint, holding the architectural picture none of the six can see, and reconciling documentation when parallel sessions inevitably contradict each other. When six things move at once, the scarce resource is not code — it is a single consistent account of what the system now is.
It is not tidy. After one six-way run I spent an hour reconciling thirty-five missing history entries, and nine passes were never recovered — I still don't know what they did. I'm including that because a method described only by its good days is a sales pitch, not a method.
// one round, in order
Seven windows, 8 May 2026
The round from the top of this page, step by step, as its six records tell it. Not every round is glamorous: this one hardened the build's own tools before a release build.
-
01 Input
Pass 963 audits the build's own tools: 22 of them, every finding with its file and line. The coordinator cuts the fixes into six file sets that cannot overlap.
Coordinator. Slices are assigned so no two sessions own the same file.
-
02 Locks
Before touching anything, each session claims its lock:
t1_standing_rule_965.lockthrought6_medium_cluster_970.lock.The lock folder. Claimed before work, released after the record. Nothing smarter than that.
-
03 Work
Six changes at once: the build-number tools, the problem lists, the golden-path test, the history checker, the auto-wiring filter, four medium findings.
One owner per file. Each session edits its slice and nothing else.
-
04 Verify
Five compiles come back 0 errors, 0 warnings; T1 and T6 run theirs after every file. T2 changed no code, so it checks its citations instead.
The gate. No record is written until the checks pass.
-
05 Collide
T6 reads the end of the ledger; T3 lands before T6 can write. T6 reads the end again and appends. T1 hits the same once.
Append-only records. A write that loses the race reads again. Nothing is overwritten.
-
06 Land
The records land in the order they finish: 968, 971, 965, 970, 969, 966. T3 planned as 967 and lands as 971.
The seventh window. The coordinator merges six accounts into one state, nesting the out-of-order ones instead of renumbering history.
-
07 The rig
Six windows and a seventh, on two screens, at one desk.
Then the next round. Wave 4 started the same day.
Assembled from the records of passes 963–972, dated 8 May 2026. The windows quote their record lines, trimmed but not reworded; nothing was re-run for this page.
// the unit of work
Every pass ends in a verdict
Nothing here is a conversation. The unit of work is a pass, and a pass has a fixed shape:
| Stage | What happens | Rule |
|---|---|---|
| Input | the requirement, plus the current true state of the system — not the state I assumed it was in | state, not memory |
| Execute | the change, made against one owned slice of the codebase and nothing else | one owner |
| Verify | compile check plus an audit against the requirement — did it do the thing, and did it break something else | gate |
| Record | what changed and why, written down so the next pass starts from fact | no silent edits |
2,031 passes, each shaped as input → execute → verify → record. The verify stage is the whole point: it is the only reason those changes compose into a working product instead of 2,031 opportunities for silent breakage.
// the record
All 2,031 passes, day by day
Every pass number in the build's ledger up to the count of 6 August 2026, placed on the day its record is dated: 17 March to 6 August. Each is coloured by the class its record gives itself. The ledger has no lane or verdict field, so neither is drawn.
- build 732
- fix 289
- polish 451
- audits, records 158
- no class recorded 392
- never recovered 9
- 18 March 122 passes dated that one day, six sessions at once. Nine never got a record back: 51, 52, 56–59, 106, 109 and 114. The dev log that day counted eight; the ledger marks nine.
- 19 March Pass 163 rebuilds the worst screen from code instead of repairing it: 1,713 lines to 913.
- 8 May The round at the top of this page: six sessions, passes 965 to 971.
- 6 August Pass 2107, the last number counted in the 2,031.
// when it breaks
The pattern I had to invent
Weeks of fast iteration left every screen in the game holding broken references — the engine stores component links by ID, and after enough restructuring those IDs pointed at things that no longer existed. Eleven attempts to repair one screen conventionally all failed. So I stopped repairing.
The replacement pattern: disable everything the editor had serialised rather than destroying it, rebuild the entire interface from code at runtime, then re-point every reference at the freshly built objects. Downstream code cannot tell the difference. Applied across all thirteen screens, the worst offender went from 1,713 lines to 913 — smaller, faster, and it actually worked.
That call — stop fixing this, replace the mechanism — is not something a build pipeline arrives at on its own. It came from watching eleven failures and concluding the approach was wrong rather than the attempts. It is the same judgment I get paid for on client work, and it is the part that does not come out of a tool.
// the content pipelines
Not just code — everything the game is made of
The same pass discipline ran the asset production, because a game is mostly content and content rots the same way code does:
- Art — every fighter portrait, environment and item icon produced through the same generate-review-regenerate-export loop. No asset store, no stock sprites — every asset came out of that one pipeline, so it all looks like it belongs together.
- Music — an original score in music kits: the player picks one and it plays across the whole game.
- Voice — the cast voiced, with lines regenerated until the read matched the scene.
The unglamorous half is the half that matters: one entire pass was nothing but moving item icons into the exact folders the loader expected. Pipelines are mostly that, and skipping it is why most of them quietly stop working.
// the economics
What it actually cost
I haven't found a sourced figure for what a studio would spend on this scope, so I won't quote one. My side of it I can show: the tooling for this build came to roughly €800 over the fifteen weeks, most of it the AI coding subscription.
That number is the argument for the method, and it is worth being precise about what it isn't. It is not an argument that the work is cheap — the fifteen weeks were mine, and the judgment in them is the expensive part. It is an argument that the ceiling on what one person can responsibly ship has moved, and that a business sitting on a backlog of "we'd need to hire for that" should re-check its assumptions.
// what transfers
The same system, pointed at your process
Strip out the game and the architecture is the deliverable: work split into slices that can run at once without colliding, a lock or ownership rule so they don't, a fixed pass shape ending in verification, and a written record so the next pass starts from fact instead of assumption. Pointed at a business, that is what a custom workflow build would be: find where the repetitive work actually goes, then build a pipeline that removes it, around the process you already run.
It is also the reason the rest of the work on this site holds up. The same discipline audited a multi-tenant SaaS against itself, found 355 things wrong with it, and worked through them in a twelve-pass fix program. A pipeline that cannot fail its own output is not a pipeline. It is a very fast way to ship a mistake.