Luke Czak

Writing · AI Engineering

What Two Months of AI-Assisted Building Actually Produces

Two months of shipping daily through Claude Code and Codex multi-agent pipelines: where the speed is real, where the security isn't, and why review rigour — not model choice — is the actual differentiator.

For the past two months I have built software almost entirely through AI agents — Claude Code and Codex running in parallel lanes, each task in its own git worktree, every change gated by an independent review before it merges. Not a pilot, not a demo week: daily production work across web, 3D and infrastructure. This post is the honest ledger of what that actually produces — the patterns I can evidence, rather than the ones that make good conference slides.

The speed is real

Let me concede the hype its due first. The throughput change is not marginal. Work that used to be a day is an hour; work that used to be "next sprint" happens while I review something else. Running several agents in parallel, each isolated in its own worktree, turns one person into a small delivery team. Nothing below argues against the speed. Everything below is about what the speed produces.

Nearly half of it is insecure by default

Veracode's 2025 GenAI Code Security Report tested more than 100 language models across 80 real-world coding tasks and found the models chose an insecure implementation in 45% of cases — rising to a 72% failure rate in Java. The finding that should worry you more: security performance showed no improvement in newer, larger models. The code got more plausible; it did not get safer.

That matches my ledger exactly. The gates in my pipeline catch the same classes of defect week after week: missing authorisation checks, injection paths, secrets committed then "removed" (still live in git history), multi-tenant reads that leak across customers. On security-relevant work, an unreviewed agent is roughly a coin flip. Fast and sound are different properties, and the model only sells you the first one.

Enabled is not correct

The clearest public example of the pattern is CVE-2025-48757: researchers confirmed 170+ live applications built on Lovable exposing emails, messages, payment records and API keys to anyone holding the public anon key, because Row Level Security was missing or wrong (Superblocks, TNW). The detail worth internalising: the scanner shipped in response checks whether RLS is enabled, not whether the policy is right. A policy of USING (true) passes the scanner, shows green in the dashboard — and returns every row in the table to a stranger.

That is not a Lovable story; it is the general failure mode of AI-assisted building. Agents are excellent at making indicators go green, because presence is what the indicator measures. Whether a policy actually separates the roles it is meant to separate is a question only a reviewer reads deeply enough to answer — and the agent that wrote the policy is the least qualified reviewer available.

The testing ceiling

Agents write tests generously. The suite grows, the checks pass, the coverage number climbs. Look closer and a familiar pattern emerges: assertions that cannot fail, mocks testing other mocks, and "done" reports backed by a confident paraphrase of what the code should do. The moment you insist on evidence instead of assurance — the verbatim command output, the rendered screenshot, the row that actually landed in the database — a surprising share of reported progress evaporates.

This is the ceiling: left alone, agent-written tests converge on verifying what the code does rather than what it was supposed to do. Intent and acceptance do not automate. Two months in, the human hours I spend have shifted almost entirely from writing code to specifying it precisely and refusing to accept unproven claims about it.

What a second engine sees

Here is a concrete example from this week. I had one engine diagnose the scroll performance of a 3D site I am building for my own studio — a scroll-driven Three.js journey with about 1,500 instanced meshes. It found three real problems: two easing filters stacked on top of each other (compounding input lag), too many instances, and an over-long pinned hero section.

I then handed the same codebase to a different vendor's engine for an independent diagnosis. It agreed with all three findings — and listed five cost multipliers the first engine had missed entirely: an unusually high-detail icosahedron putting roughly two million triangles on screen, a 4x-MSAA half-float post-processing target, three GPU buffer uploads on every rendered frame, a "lazily loaded" chunk that actually initialises immediately, and animation tweens created on every scroll event. Seed count alone — the first engine's headline fix — would have left most of the real cost in place.

That is why cross-engine review is the backbone of my pipeline. Models share blind spots with themselves but not with each other. The engine that wrote the analysis rationalises it; a rival engine, with no ego in the diff, reads it cold. One model builds, a different model attacks, and a change ships only when it survives.

The differentiator is the harness, not the model

After two months, my conclusion is unfashionable but well-evidenced: which frontier model you use matters far less than the verification harness you wrap around it. The builder engines are interchangeable and will be leapfrogged again by Christmas. What compounds is the machinery that doesn't ship trust: adversarial review by a different engine, proof-of-work gates that demand artefacts instead of claims, isolation so parallel work can't trample itself, and a human who owns intent and acceptance.

AI-assisted building produces enormous volumes of plausible software, roughly half of it insecure at the point of generation. What reaches production is decided by the review. That is where the engineering now lives.

← All writing