AI coding agents

Building Wheels apps with AI coding agents

We ran a set of coding agents at real feature work in a Wheels application and measured how often they finished the job. This page reports what we measured, every number, and what we changed in Wheels as a result.

700 / 790
scored trials passed — 88.6% 660 / 790 (83.5%) raw, before two hidden-check corrections

Our aim was a like-for-like comparison with the way Ruby on Rails' own ai-evals measures agents: the same harness, the same agent, a comparable sample app, and the same style of task with hidden acceptance checks. Where we couldn't match Rails exactly, we say so.

1. What we measured, and why

Ten tasks (plus a hello-world control) × three attempts per cell. A "cell" is one model in one arm. Twenty-four cells in all: nine models in both arms, four more in the shipped arm only, and two Claude Code cells.

Integrity first. The case we wanted to test honestly is simply whether Wheels deserves a seat at the table. So: no benchmark-specific caching, no pre-generated answers, and no app state an agent wouldn't have in normal use. Every improvement we made to help agents shipped to every Wheels user — in wheels new, the docs, and the MCP server — not just to the test. Every run was recorded, including failures and infrastructure errors, and those are reported below.

2. Latest results (October 2026)

Overall, across the ten tasks, the agents passed 700 of 790 scored trials (88.6%) — raw, before two hidden-check corrections (section 5), 660 of 790 (83.5%).

Steps are the agent's tool-use turns (a guard stopped a trial at 150). Spend is the settled provider cost for that cell. The "docs" arm is the shipped AI context; "bare" is a stock app.

ModelProviderAgentArm Pass (raw)SpendSteps (mean)
GPT-5.6 LunaOpenAIlemansbare19/33 (18)$0.7015
GPT-5.6 LunaOpenAIlemansdocs21/33 (20)$0.7116
DeepSeek V4.1 FlashDeepSeeklemansbare32/33 (31)$2.0281
DeepSeek V4.1 FlashDeepSeeklemansdocs33/33$1.8973
GPT-5.6 SolOpenAIlemansbare32/33 (28)$10.2618
GPT-5.6 SolOpenAIlemansdocs32/33 (28)$11.4418
Sonnet 5.5Anthropiclemansbare33/33 (29)$10.6118
Sonnet 5.5Anthropiclemansdocs33/33 (31)$10.7218
Haiku 4.5Anthropiclemansbare12/33 (10)$14.9982
Haiku 4.5Anthropiclemansdocs9/33$13.1574
Gemini 3.8 FlashGooglelemansbare31/33 (30)$33.6298
Gemini 3.8 FlashGooglelemansdocs32/33 (31)$34.3897
Qwen3.8-27BAlibabalemansbare31/32 (29)$27.4489
Qwen3.8-27BAlibabalemansdocs30/32$28.4188
Opus 5.5Anthropiclemansbare33/33 (31)$21.3924
Opus 5.5Anthropiclemansdocs32/33 (31)$23.5624
GPT-6 AstraOpenAIlemansbare33/33 (30)$33.5915
GPT-6 AstraOpenAIlemansdocs33/33 (31)$35.4716
Kimi K3Moonshotlemansdocs33/33 (30)$60.9164
GLM 5.3Zhipulemansdocs32/33 (29)$77.1195
Grok 4.7xAIlemansdocs33/33 (32)$83.6150
Fable 5.1Anthropiclemansdocs33/33 (31)$87.7442
Opus 5.5AnthropicClaude Codedocs29/33$30.39—
Fable 5.1AnthropicClaude Codedocs29/33$90.36—

Notes:

3. Did the shipped AI context help?

For the nine models that ran in both arms, with both check corrections applied:

Bare (raw)Shipped docs (raw)
Total, 9 models256/296 (236)255/296 (244)

Honestly: the effect is within noise. After correcting the two over-strict hidden checks (section 5), the shipped docs did not produce a measurable across-the-board lift — the pooled difference is a single trial, in the noise at three attempts per cell. Most of the apparent raw gain (+8 trials) came from one of the corrected checks, which the docs arm happened to pass more often by chance.

Where the docs did help was narrower and more plausible: a model occasionally used a 4.2 API it would otherwise have missed, and a couple of models took fewer steps with the docs present. Cost and step counts barely moved with docs either way (within about ±10% on spend, under one step for most models).

We read this as: the strong models already know how to build a Wheels app from the stock conventions, and the shipped context mostly helps at the margins and on newer APIs. We'd rather report that plainly than overstate it.

The bare/docs totals here were recomputed from the rescored data plus the erase-account per-trial flips, and confirmed by re-running the tally: bare 256/296, docs 255/296 (raw 236 vs 244).

4. The ten tasks

Seven tasks mirror a Rails ai-evals task; three are Wheels-native (no Rails counterpart). Pass rate is across all 24 cells, rescored.

TaskRails counterpartDifficultyPass
ar-bulk-access-grants — grant a roster of readers in one insert, notify each once, idempotentyesmedium71/72 (99%)
ar-release-recap — keep a cached "recap" matching exactly what a publish committedyesmedium71/72 (99%)
ar-compact-positions — compact hand-ordered items to a dense 1..n, trashed ones includedyesmedium66/72 (92%)
as-purge-embedded-images — free image files on delete, with reference counting and rollback safetyyeshard63/72 (88%)
sup-legacy-conversions — find and fix every removed/changed 4.x API in an admin reportyesmedium63/72 (88%)
wn-query-not-array — a "recently edited" list, and the same list as a JSON arrayno (Wheels-native)easy63/72 (88%)
ar-erase-account — erase an account and everything only it owns, atomicallyyeshard60/72 (83%)
wn-literal-route — add print + archive pages without breaking legacy redirect linksno (Wheels-native)medium60/72 (83%)
wn-reversible-trash — soft-delete books to a trash with restore and a 30-day purgeno (Wheels-native)medium57/72 (79%)
hw-scoped-broadcast — live updates that reach exactly the people who can currently read a bookyeshard54/70 (77%)

(hello-world control: 72/72.)

What failed, and why:

A recurring, framework-agnostic lesson showed up too: CFML strings have no backslash escapes, so a digit route constraint must be written "\d+", not "\\d+" — one agent got this wrong and broke the app's reading URLs. (We've since made that explicit in the routing guide.)

5. Corrections and deviations, in full

We'd rather show the rough edges than hide them.

6. What changed in Wheels because of this

Per our integrity rule, everything the rounds surfaced was fixed for all Wheels users, not just the test. Running real agents at real tasks turned out to be an excellent way to find rough edges. A selection of the user-facing changes the rounds drove, each a public PR:

Several of these — the application cache, query assertions, the clock seam — are new in 4.2 precisely because an agent needed them and we agreed every Wheels developer would too.

7. How we kept it honest

Credits

Models and providers tested: OpenAI (GPT-5.6 Luna, GPT-5.6 Sol, GPT-6 Astra), Anthropic (Opus 5.5, Sonnet 5.5, Haiku 4.5, Fable 5.1), Google (Gemini 3.8 Flash), DeepSeek (V4.1 Flash), Alibaba (Qwen3.8-27B), Moonshot (Kimi K3), Zhipu (GLM 5.3), xAI (Grok 4.7). Harness and agent: Rails' lemans / miniswen (ai-evals) and Anthropic's Claude Code.