Hopper · Loyalytics · 2026-05-14

Hopper picks the ticket.
The model writes the code.
The human reviews the PR.

Hopper is Loyalytics' autonomous engineering agent. It pulls a Linear ticket the moment it's ready, opens an isolated sandbox, drives a coding model end-to-end through the work, and lands a real PR — without checking in mid-stream. Humans live at the boundaries: writing the ticket, and reviewing the result.

Operating principle

Human at the boundaries, not in the middle.

Every "please confirm before continuing" check-in is a context switch that pulls an engineer out of deep work. Hopper's job is to absorb the entire middle of the ticket — the searching, the editing, the iterating, the testing, the pushing — so the human only has to think at the two moments where their judgment is irreplaceable: defining what good looks like, and verifying that the PR meets it. When something is genuinely blocked, Hopper opens a draft PR with what it has and explains the blocker — it never pauses asking for input mid-task.

Boundary 1
Human
Writes the Linear ticket: what to build, why it matters, what "done" looks like.
The middle
Hopper
Picks it up, sandboxes, clones, drives the model through editing/committing/pushing, opens the PR.
Boundary 2
Human
Reviews the PR, requests changes if needed, or merges it.

01The runs so far

This page collects every Hopper Run we've completed. Each run is also a head-to-head: we ran every ticket through five frontier coding models in parallel — same prompt, same tools — to see which model Hopper should default to.

2 runs completed — one simple, one complex
5 models per run · OpenAI, DeepSeek, Z.ai, MiniMax, Google
10/10 PRs landed on GitHub
~$66 total spend (one outlier — see SWA-6400)
Run 1 · Simple · 2 points
SWA-6435

Remove the /next basePath and assetPrefix — mechanical config change rippling through ~5 files.

Winner: GLM-5.1 · 5/5 PRs landed · <$5 spent
Run 2 · Complex · Urgent
SWA-6400

Consolidate competing PostHog + Sentry implementations into one central monitoring module — 9 acceptance criteria, 18.9KB spec.

Winner: gpt-5.5 (retry) · 5/5 PRs · $62 spent

02The setup

Identical conditions for every model. The only variable is the brain inside the box.

Execution
One isolated cloud sandbox per model — fresh clone, no shared state
Agent harness
Pi — unified coding agent CLI from earendil-works
Tools the model gets
read · write · edit · bash · grep · find · ls
Spec delivery
Full Linear ticket as a single file the model can reference
Thinking budget
high across the board (one xhigh experiment in SWA-6400 attempt 1)
Output
Real branch, real commits, gh pr create on the swan-apps repo

The pipeline

Linear ticketspawn 5 parallel sandboxesgit clone + branchPi(spec + instructions)model edits filescommit + pushPR opens

03What we actually learned

costThe xhigh trap

$56.41 → $0

gpt-5.5 at default thinking=xhigh burned $56 over 169 turns and produced nothing on the complex ticket — OpenAI quota exhausted. The same model at high + a budget instruction shipped the best PR for $4.56.

valueThe DeepSeek surprise

$0.07 total

DeepSeek finished 2nd in both runs. Total cost across both: 7 cents. The cost-per-PR is so low it changes the economics of automated implementation entirely.

freeThe GLM streak

$0.00 cost

GLM-5.1 won the simple ticket outright and placed 3rd on the complex one — never charging a cent. The most consistent all-rounder we have.

policyProduction rule

high + budget

Never default to xhigh on complex tickets. Always pair OpenAI models with a budget instruction. Cost-per-thinking-level is non-linear and unsafe at the top.

Switch to a run tab above for the full per-model breakdown on each ticket.

Run 1 · Simple · 2-point ticket

SWA-6435 // remove the /next basePath

A clean, mechanical config-file change. Five models, five PRs, ranked by how cleanly each one threaded the needle.

01The ticket

SWA-6435 High Remove the /next basePath and assetPrefix

next.config.mjs prepends /next/ to every URL because the app used to live inside an Angular iframe. The Angular shell is gone — the prefix is now pure friction. One-line removal that ripples through ~5 files (config, middleware, image loaders, a couple of hardcoded paths).

Acceptance: next.config.mjs stops referencing basePath / assetPrefix, no /next/ string survives a recursive grep, and the app still builds.

02The leaderboard

#ModelPRCostTimeTurnsDiff
1GLM-5.1#23$0.005.5m22+16/−27
2DeepSeek-V4-Pro#22$0.013.4m15+14/−20
3gpt-5.5#25$3.8317.9m88+53/−47
4Gemini-3.1-Pro#24$0.6011.5m44+13/−17
5MiniMax-M2.7#21$0.021.2m25+14/−20
Winner

GLM-5.1 — PR #23

Did exactly what was asked, in fewer turns and at zero cost. Cleanest diff: removed both config keys, fixed the few downstream string references, didn't touch anything else.

Cost
$0.00
Turns
22
Diff
+16/−27
Files
5

03How each model played it

In rank order. The full read on what each model did, where it shined, and where it didn't.

GLM-5.1

Z.ai
1st of 5
PR
Cost
$0.00
Time
5.5m
Turns
22
Diff
+16/−27 · 5f

Mechanical and surgical. Touched only the 5 files that actually had /next references, removed both basePath and assetPrefix, fixed the few hardcoded path strings that needed updating, didn't expand scope. The kind of PR a senior engineer would write on a Monday morning before the first coffee.

What stood out
  • Cleanest diff scope in the field — exactly the 5 files that needed touching, no more.
  • Zero cost. Mechanical work on GLM is operationally free.
  • 22 turns, 5.5 min — efficient without over-verifying.

DeepSeek-V4-Pro

DeepSeek
2nd of 5
PR
Cost
$0.01
Time
3.4m
Turns
15
Diff
+14/−20 · 5f

Essentially tied with GLM on the work itself — same surgical diff scope — but completed it 40% faster (3.4m vs 5.5m) and in fewer turns (15 vs 22). One cent for a clean, mergeable PR.

What stood out
  • Fastest of the five. 15 turns is the lowest in the leaderboard.
  • Tied with GLM on diff quality — they're indistinguishable on this task.
  • $0.01 is functionally free — best raw value per turn.

gpt-5.5

OpenAI
3rd of 5
PR
Cost
$3.83
Time
17.9m
Turns
88
Diff
+53/−47 · 13f

Most thorough analysis of the field — checked harder than required. 13 files changed where the others touched 5, 88 turns where the others used 15–25. The work is defensible (and arguably more robust) but the PR is bigger than the ticket asked for and the cost is 400× DeepSeek's.

Watch-outs
  • Scope creep. 13 files changed for a 5-file task. Every extra file is a merge-conflict surface.
  • 88 turns is a smoke signal. The model wanted to verify every consequence — when it's allowed to do that on a $0.05/turn model, it adds up.
  • Cost-to-complexity mismatch. $3.83 for what should be a $0.01 task.

Gemini-3.1-Pro-Preview

Google
4th of 5
PR
Cost
$0.60
Time
11.5m
Turns
44
Diff
+13/−17 · 6f

Got the basics right — small diff, right files — but was slower than GLM/DeepSeek by 2–3× and pricier by 60× without an obvious quality advantage. The PR is fine; the path to get there wasn't.

Watch-outs
  • Slower than GLM at 60× the cost — no compensating quality bump.
  • For mechanical tickets like this one, there are 3 strictly cheaper-and-faster options.

MiniMax-M2.7

MiniMax
5th of 5
PR
Cost
$0.02
Time
1.2m
Turns
25
Diff
+14/−20 · 5f

Fastest wall-clock in the war by a wide margin — 1.2 min where the next-fastest took 3.4 min. The diff looks right at a glance. But the review caught a subtle regression in the changes that the other models avoided.

Watch-outs
  • Subtle regression. The diff looks right but introduces a behavior change that doesn't match the ticket — the exact failure mode that makes fast models risky to merge unattended.
  • Speed is real and so is the cost (almost free). Use only where a human will carefully diff-review before merge.
Run 2 · Complex · Urgent

SWA-6400 // PostHog + Sentry consolidation

Eight sub-issues, nine acceptance criteria, 18.9KB of spec. The kind of ticket where bad architecture choices snowball.

01The ticket

SWA-6400 Urgent Fix broken PostHog + Sentry — consolidate to central monitoring module

One-line summary: The codebase has a "central monitoring module" (lib/monitoring/) that looks like the official entrypoint, but a simpler PostHogProvider is what's actually mounted — so half of tracking calls hit dead code.

Eight concrete problems the model has to fix:

  • Two competing posthog.init() calls — delete one, mount the central MonitoringProvider
  • App Router pageviews broken — every user looks stuck on the landing URL forever
  • Sentry config drifttracesSampleRate: 1.0 in three places, unmasked replays, sendDefaultPii: true — SOC2 risk
  • No tenant attribution — needs a posthog.group() on every session
  • Server-side errors anonymous — API exceptions hit Sentry without setUser
  • Error boundaries bypass the central wrapper — direct Sentry.captureException calls
  • No /ingest reverse proxy — adblockers eat PostHog
  • Nine feature areas with zero tracking events — fraud-detection, sftp-sync, webhooks, +6 more

Plus an ESLint rule that fails the build on direct posthog-js / @sentry/nextjs imports outside the central module, so this can't silently regress again.

02The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1gpt-5.5 (retry, high)#30$4.567.6m6824/25
2DeepSeek-V4-Pro#29$0.0614.2m4822/25
3GLM-5.1#27$0.0015.0m9620/25
4MiniMax-M2.7#26$0.204.0m5718/25
5Gemini-3.1-Pro#28$1.207.9m6617/25
gpt-5.5 (attempt 1, xhigh)FAILED$56.4142.1m169quota out
Winner

gpt-5.5 (retry, thinking=high) — PR #30

All 9 acceptance criteria addressed in code. Wrote a createCrudFeatureTracker factory that saved ~300 lines of boilerplate every other model produced by hand. ESLint rule lives in the real config. Leanest "complete" diff in the field.

But: only because we forced it down from xhigh after attempt 1 burned $56 with no output. Caveat baked in.

Score
24/25
Cost (retry)
$4.56
Diff
+327/−298
Turns
68

03How each model played it

In rank order. Score bars, signature moves, and red flags per model.

gpt-5.5 (retry, thinking=high)

OpenAI
1st of 5 · 24/25
PR
Cost
$4.56
Time
7.6m
Turns
68
Diff
+327/−298 · 21f
Correct
5/5
Scope
5/5
Quality
5/5
Risk
4/5
Surgical
5/5

The only model that wrote a real abstraction. createCrudFeatureTracker generates all 9 zero-coverage feature trackers from a config object — ~40 lines replacing ~300 lines of copy-paste. ESLint rule via eslint.config.mjs (the real build gate, not an enforce-standards.mjs workaround). Three Sentry config files delegate to initSentry() from the central module — single source of truth.

What stood out
  • Factory pattern instead of copy-paste. 40 lines vs ~300 for the same 9 trackers.
  • ESLint rule in the real config. Other models used enforce-standards.mjs, which is a script not a build gate.
  • Single source of truth for Sentry. Three config files delegate to one initSentry().
  • Smallest "complete" diff in the field at +327/−298, 21 files.
Watch-outs
  • AC7 server-side setUser reads x-user-id headers — silently no-ops if upstream middleware doesn't set them.
  • Deleted PostHogProvider.test.tsx without adding a replacement test.
  • Conditional success. Without the thinking=high downgrade and the budget instruction, this model fails catastrophically on this class of ticket (see failed run below).

DeepSeek-V4-Pro

DeepSeek
2nd of 5 · 22/25
PR
Cost
$0.06
Time
14.2m
Turns
48
Diff
+885/−252 · 19f
Correct
4/5
Scope
5/5
Quality
4/5
Risk
4/5
Surgical
5/5

Safest path choices in the field. Used relative imports (./src/lib/monitoring/config) in root-level Sentry configs instead of the @ alias — avoiding a latent runtime risk that bit GLM. Reached for the existing SwanConfigPayload type for JWT decoding instead of casting payloads. Added a real server.ts wrapper for AC7. 88% of the winner's quality at ~1% of the cost.

What stood out
  • Cleanest diff hygiene — no lockfile noise, no comment stripping, no speculative refactors.
  • Used existing types correctly instead of Record<string,unknown> casts.
  • $0.06 for a 22/25 PR. Best raw value in the war by an order of magnitude.
Watch-outs
  • Missing Dockerfile NEXT_PUBLIC_GIT_SHA — Sentry release tagging won't work in Docker CI.
  • replayMask* fields referenced in init but not added to the sentryConfig object — TypeScript build risk.
  • No unit test for MonitoringProvider mount.

GLM-5.1

Z.ai
3rd of 5 · 20/25
PR
Cost
$0.00
Time
15.0m
Turns
96
Diff
+1057/−265 · 22f
Correct
4/5
Scope
5/5
Quality
4/5
Risk
3/5
Surgical
4/5

Impressive output at $0 cost. Comprehensive TypeScript event types, dedicated Sentry mock file for tests, proper unit test for layout mount, Dockerfile update with NEXT_PUBLIC_GIT_SHA. Threaded sendDefaultPii through the config cleanly. The one knock is a latent alias-resolution risk in the Sentry root configs.

What stood out
  • Free. Comprehensive output at zero marginal cost.
  • Only model that added a Sentry mock file for test isolation.
  • Properly updated the Dockerfile with the Sentry release SHA arg.
Watch-outs
  • Used @/lib/monitoring/config alias in root-level Sentry configs. These files live at apps/next-swan/ root and the @ alias may not resolve at server boot — could fail silently.
  • Has a raw import posthog from 'posthog-js' in MonitoringProvider that would self-violate the new ESLint rule it just added.

MiniMax-M2.7

MiniMax
4th of 5 · 18/25
PR
Cost
$0.20
Time
4.0m
Turns
57
Diff
+969/−176 · 18f
Correct
4/5
Scope
4/5
Quality
4/5
Risk
3/5
Surgical
3/5

Fastest in this run (4 min) and the most thorough TypeScript event-type surface — full discriminated unions in types.ts, comprehensive fs-based test assertions. But silently broke onRequestError in instrumentation.ts with a custom async wrapper that doesn't match Sentry's API signature.

What stood out
  • Most thorough TypeScript types — discriminated unions for all 9 trackers.
  • Most thorough test suite — fs-based assertions in monitoring.test.ts.
  • Fastest of the field at 4 min.
Watch-outs
  • Broke onRequestError. Custom async signature drops the hints argument — runtime regression for server-side error context.
  • Edited CLAUDE.md at repo root instead of apps/next-swan/CLAUDE.md.
  • Untyped JWT decode: used Record<string,unknown> casts instead of the existing SwanConfigPayload.

Gemini-3.1-Pro-Preview

Google
5th of 5 · 17/25
PR
Cost
$1.20
Time
7.9m
Turns
66
Diff
+531/−387 · 22f
Correct
4/5
Scope
3/5
Quality
4/5
Risk
3/5
Surgical
3/5

Made the most novel contribution: the only model that added posthog-node and built a server-side server.ts capture module — closest to the ticket's "broadcast.send_failed" spirit. But scope discipline collapsed: committed a noisy package-lock.json diff, added a CI script that calls npx next build inside itself, stripped existing JSDoc.

What stood out
  • Only model to add posthog-node. Built a real server-side capture surface — the ticket's "broadcast.send_failed" spirit.
  • Tried to add a Sentry source-map verification CI gate — right instinct.
Watch-outs
  • Lockfile churn. Hundreds of cosmetic "peer": true flag changes in package-lock.json — monorepo merge-conflict risk.
  • Recursive CI script. verify-sentry.js calls npx next build inside itself.
  • Stripped JSDoc from MonitoringProvider.tsx without explanation.
  • AC3 incomplete. Missing useSearchParams in the pageview hook.

gpt-5.5 (attempt 1, thinking=xhigh)

OpenAI
Failed · no PR
PR
none
Cost
$56.41
Time
42.1m
Turns
169

Ran for 42 minutes at default thinking=xhigh, burned 169 turns, then exhausted the OpenAI spending quota with no PR created. The xhigh thinking budget made every turn enormous; the model couldn't converge fast enough to land before the credit cap. This is the same model that won the retry — so the model isn't the problem. The default thinking level on this class of ticket is.

Lesson
  • Never default to xhigh on complex tickets. Cost-per-thinking-level is non-linear and unsafe at the top.
  • Always pair OpenAI models with a budget instruction: "land partial work rather than time out".
  • The same model at high + budget shipped a 24/25 PR for $4.56 — 12× cheaper, 5× faster, complete output.
Simple · 2pts · FOUND-1 blocker

SWA-6427 // Add ts-node + typescript workspace deps

Unblock the entire foundation queue. Make npx jest and npx tsc work locally from apps/next-swan/.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1k2p6#63$0.009.8m2818/25
2DeepSeek-V4-Pro#50$0.028.2m2017/25
3GLM-5.1#38$0.005.2m2317/25
4gpt-5.5#48$0.837.4m4117/25
5MiniMax-M2.7#36$0.014.8m1315/25
Winner

k2p6 — PR #63

Correctly installs at workspace root + removes from apps/next-swan. Type stub for @loyalytics/observability present (GLM missed this). Same conservative pins. BUT 80+ lockfile peer-flag mutations create noise; no decision doc.

Score
18/25
Cost
$0.00
Turns
28
Time
9.8m

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

k2p6

1st of 5 · 18/25
PR
Cost
$0.00
Time
9.8m
Turns
28
Correct
5/5
Scope
3/5
Quality
4/5
Risk
3/5
Surgical
3/5

Correctly installs at workspace root + removes from apps/next-swan. Type stub for @loyalytics/observability present (GLM missed this). Same conservative pins. BUT 80+ lockfile peer-flag mutations create noise; no decision doc.

What stood out
Only model to do BOTH workspace-root add AND app-level remove (architecturally cleanest). Type stub addresses tsc --noEmit gap that GLM left. Free.
Watch-outs
1245 lines of unrelated peer-flag lockfile churn (different npm version artifact). No decision doc.

DeepSeek-V4-Pro

DeepSeek
2nd of 5 · 17/25
PR
Cost
$0.02
Time
8.2m
Turns
20
Diff
+131/−77 · 3f
Correct
4/5
Scope
3/5
Quality
4/5
Risk
3/5
Surgical
3/5

Correct npm-generated lockfile, type declarations with proper JSDoc & named interfaces, conservative version pins. Loses only the decision doc.

What stood out
Real lockfile (passes npm ci); type stub with JSDoc + named interfaces; conservative version pins. 88% of winner quality at 1% of cost across the field.
Watch-outs
No decision doc — only AC item missed.

GLM-5.1

Z.ai
3rd of 5 · 17/25
PR
Cost
$0.00
Time
5.2m
Turns
23
Diff
+103/−77 · 2f
Correct
4/5
Scope
4/5
Quality
3/5
Risk
3/5
Surgical
3/5

Identical correct lockfile to DeepSeek, same conservative pinning, but omits the type stub and decision doc.

What stood out
Genuinely npm-generated lockfile, free, minimal diff.
Watch-outs
No type declaration stub (tsc --noEmit may still fail). No decision doc.

gpt-5.5

OpenAI
4th of 5 · 17/25
PR
Cost
$0.83
Time
7.4m
Turns
41
Diff
+23/−2 · 4f
Correct
2/5
Scope
4/5
Quality
4/5
Risk
2/5
Surgical
5/5

Most surgical diff and ONLY PR with the AC-required decision doc. But lockfile is hand-edited without npm install — npm ci will fail with integrity mismatch.

What stood out
Only PR with the decision doc (only one to satisfy that AC). Tightest diff at 58 lines.
Watch-outs
Lockfile is hand-edited not npm-generated — npm ci will fail. A decision doc cannot compensate for a broken install.

MiniMax-M2.7

MiniMax
5th of 5 · 15/25
PR
Cost
$0.01
Time
4.8m
Turns
13
Diff
+150/−80 · 2f
Correct
3/5
Scope
3/5
Quality
4/5
Risk
3/5
Surgical
2/5

Well-typed declarations and genuine npm-generated lockfile, but dual ts-node versions (root@10.9.2, app@10.9.1) suggest install-order quirks. Wider caret ranges add risk.

What stood out
Best type declaration quality of the group (named interfaces + clear JSDoc).
Watch-outs
Dual-version ts-node from install conflict. Caret ranges on a foundation ticket. No decision doc.
Security · 3pts · FOUND-6

SWA-6431 // Add CSRF Origin validation for state-mutating APIs

Close standard CSRF: Origin allowlist on POST/PUT/PATCH/DELETE. Same-origin allow, allowlisted external allow, foreign deny, missing-Origin deny.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1gpt-5.5#43$1.316.5m4825/25
2GLM-5.1#39$0.005.3m2419/25
3k2p6#64$0.0010.8m3417/25
4DeepSeek-V4-Pro#46$0.027.3m2614/25
5MiniMax-M2.7#35$0.033.7m2110/25
Winner

gpt-5.5 — PR #43

The only PR that normalizes both sides of the Origin comparison (incoming header + env var entries), robust to LEGACY_APP_URL values with path components. Clean decomposition, dedicated integration test file, all 4 required cases plus GET/HEAD/OPTIONS bypass. 149 additions, zero lockfile noise.

Score
25/25
Cost
$1.31
Turns
48
Time
6.5m
Diff
+149/−0 · 4f

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

gpt-5.5

OpenAI
1st of 5 · 25/25
PR
Cost
$1.31
Time
6.5m
Turns
48
Diff
+149/−0 · 4f
Correct
5/5
Scope
5/5
Quality
5/5
Risk
5/5
Surgical
5/5

Only PR normalizing Origin on BOTH sides. New dedicated test file. All 4 required cases + GET/HEAD/OPTIONS. 149 additions, zero lockfile noise.

What stood out
Belt-and-suspenders defense: normalizes the incoming Origin AND the allowlist entries via new URL(...).origin. Robust to path-suffixed LEGACY_APP_URL values that bit the others.
Watch-outs
None material.

GLM-5.1

Z.ai
2nd of 5 · 19/25
PR
Cost
$0.00
Time
5.3m
Turns
24
Diff
+233/−3 · 3f
Correct
3/5
Scope
5/5
Quality
4/5
Risk
3/5
Surgical
4/5

Right file, richest test suite (10 cases). Single bug: env var stored raw without new URL().origin normalization.

What stood out
Richest test suite (10 cases). Best docs (auth-trust-model.md table). Extends existing test file cleanly.
Watch-outs
Stores raw NEXT_PUBLIC_LEGACY_APP_URL without normalization — silently breaks if env var includes a path.

k2p6

3rd of 5 · 17/25
PR
Cost
$0.00
Time
10.8m
Turns
34
Correct
3/5
Scope
4/5
Quality
3/5
Risk
3/5
Surgical
4/5

Whitespace-trim on env var (better than GLM raw store). 403 shape exact. All 4 required test cases + PUT/PATCH/DELETE coverage. BUT no URL normalization on either side — same structural gap as GLM. Production config with path in LEGACY_APP_URL silently breaks.

What stood out
Whitespace env-var trim. Doc placed in correct app-scoped path. Backward-compatible test helper.
Watch-outs
Missing new URL().origin normalization on both sides — silent production failure mode if LEGACY_APP_URL includes a path. Same severity as GLM's bug.

DeepSeek-V4-Pro

DeepSeek
4th of 5 · 14/25
PR
Cost
$0.02
Time
7.3m
Turns
26
Diff
+314/−78 · 4f
Correct
3/5
Scope
2/5
Quality
4/5
Risk
3/5
Surgical
2/5

Same env-var normalization gap as GLM, plus lockfile contamination — 1200 lines of unexplained lockfile mutations with no package.json change.

What stood out
describe.each pattern generates 16 sub-tests across all 4 mutating methods.
Watch-outs
Lockfile churn (1200+ lines, no package.json change). Same normalization gap as GLM.

MiniMax-M2.7

MiniMax
5th of 5 · 10/25
PR
Cost
$0.03
Time
3.7m
Turns
21
Diff
+322/−0 · 3f
Correct
1/5
Scope
3/5
Quality
3/5
Risk
1/5
Surgical
2/5

Security control doesn't execute. Created _middleware.ts in src/app/api/ — not a Next.js-recognized middleware path. proxy.ts untouched. CSRF guard is dead code in production.

What stood out
getAllowedOrigins() with URL normalization and error handling is technically solid code. Documentation is good.
Watch-outs
CRITICAL: middleware never invoked. _middleware.ts at src/app/api/ is not a Next.js path. proxy.ts not touched. The CSRF vulnerability remains unfixed.
Docs · 2pts · FOUND-8

SWA-6437 // Update CLAUDE.md to reflect current truth

Auth0→Kinde rename. Strip Angular-iframe language. Reduce 8-step workflow to one line for non-trivial features.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1k2p6#66$0.0012.0m4524/25
2gpt-5.5#31$0.351.5m1324/25
3DeepSeek-V4-Pro#37$0.013.1m1118/25
4GLM-5.1#33$0.003.3m2514/25
5MiniMax-M2.7#32$0.011.7m712/25
Winner

k2p6 — PR #66

Ties gpt-5.5 at 24/25 with BROADER scope: only model that also updated coding-standards.md (caught the stale 'Auth0 bug' comment example) AND product-documentation.md (Angular localhost → Next.js). Clean Kinde rename, no FOUND-9 hallucination, correct workflow one-liner.

Score
24/25
Cost
$0.00
Turns
45
Time
12.0m

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

k2p6

1st of 5 · 24/25
PR
Cost
$0.00
Time
12.0m
Turns
45
Correct
5/5
Scope
5/5
Quality
5/5
Risk
5/5
Surgical
4/5

Ties gpt-5.5 at 24/25 with BROADER scope: only model that also updated coding-standards.md (caught the stale 'Auth0 bug' comment example) AND product-documentation.md (Angular localhost → Next.js). Clean Kinde rename, no FOUND-9 hallucination, correct workflow one-liner.

What stood out
Only model to find and fix stale Angular references in product-documentation.md and the coding-standards.md comment-table example. Zero FOUND-9 hallucination — defers to canonical doc.
Watch-outs
108 lines vs gpt-5.5's 52 — broader scope is correct but slightly larger blast radius. Root CLAUDE.md not touched (shared gap).

gpt-5.5

OpenAI
2nd of 5 · 24/25
PR
Cost
$0.35
Time
1.5m
Turns
13
Diff
+5/−15 · 1f
Correct
4/5
Scope
5/5
Quality
5/5
Risk
5/5
Surgical
5/5

Avoided hallucinating FOUND-9 numbers. Clean Kinde rename. Tight 52-line diff.

What stood out
Best FOUND-9 handling: expresses rule intent in general terms without inventing numbers. Auth removal of '(via proxy JWT)' is correct.
Watch-outs
Root CLAUDE.md not documented as reviewed (shared gap across all 4 PRs).

DeepSeek-V4-Pro

DeepSeek
3rd of 5 · 18/25
PR
Cost
$0.01
Time
3.1m
Turns
11
Diff
+5/−17 · 1f
Correct
3/5
Scope
5/5
Quality
4/5
Risk
3/5
Surgical
3/5

Heading cleanup (drops '(Optional)'). BUT keeps stale '(via proxy JWT)' on the Kinde line — actively misleads agents. Over-removes still-valid 50-line function rule.

What stood out
Only PR to drop '(Optional)' from the workflow heading. Defers FOUND-9 detail to canonical doc — hallucinates nothing.
Watch-outs
Keeps '(via proxy JWT)' on the Kinde line — factually wrong, misleads agents on auth mechanism. Silently removes the still-valid 50-line function rule.

GLM-5.1

Z.ai
4th of 5 · 14/25
PR
Cost
$0.00
Time
3.3m
Turns
25
Diff
+4/−15 · 1f
Correct
2/5
Scope
5/5
Quality
2/5
Risk
2/5
Surgical
3/5

Hallucinated 'Files: max 300 lines (enforced via npm run enforce, not ESLint)' — neither in spec.

What stood out
Auth and Angular removals clean. Smallest diff (51 lines).
Watch-outs
Fabricated rule: 'max 300 lines' and 'not ESLint' invented from thin air. Agents will enforce a made-up number. Workflow heading retains '(Optional)'.

MiniMax-M2.7

MiniMax
5th of 5 · 12/25
PR
Cost
$0.01
Time
1.7m
Turns
7
Diff
+6/−18 · 2f
Correct
2/5
Scope
3/5
Quality
3/5
Risk
2/5
Surgical
2/5

Touched extra file (coding-standards.md fix is correct, scope creep debatable). BUT silently REPLACES 'Page components: max 50 lines' with hallucinated 'Files: max 300 lines'.

What stood out
Only PR to fix a stale Auth0 reference in coding-standards.md. Drops '(Optional)' from workflow heading.
Watch-outs
Worst-of-both: hallucinated '300 lines' rule + silently destroyed the existing valid 'Page components: max 50 lines' rule. Scope creep onto coding-standards.md unannounced.
Tech debt · 3pts · FOUND-3

SWA-6429 // Delete Angular iframe scaffolding

~1,500 LOC of iframe-supporting code. IframeDetector, FeatureLayoutClient, EmbeddedViewportProvider, 5 hooks. Delete all of it.

⚠ Only 3 of 5 models produced PRs. gpt-5.5 and Gemini didn't land.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1DeepSeek-V4-Pro#62$0.0825.1m6125/25
2GLM-5.1#61$0.0020.1m9721/25
3k2p6#69$0.0021.9m9117/25
4MiniMax-M2.7#53$0.139.8m3912/25
Winner

DeepSeek-V4-Pro — PR #62

The only PR that would pass npm run build:next-swan without further edits. All 8 named targets deleted plus their __tests__. isInIframe correctly migrated from the deleted hook to @/lib/api-utils. forceBodyContainer prop fully excised from type signatures.

Score
25/25
Cost
$0.08
Turns
61
Time
25.1m
Diff
+205/−3875 · 48f

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

DeepSeek-V4-Pro

DeepSeek
1st of 5 · 25/25
PR
Cost
$0.08
Time
25.1m
Turns
61
Diff
+205/−3875 · 48f
Correct
5/5
Scope
5/5
Quality
5/5
Risk
5/5
Surgical
5/5

Complete deletion + correct migrations. All 8 named targets and tests gone. isInIframe migrated to @/lib/api-utils. forceBodyContainer prop fully excised from type signatures.

What stood out
Only PR with complete migration. New BroadcastBuilderLayoutClient.test.tsx is appropriate. ESLint suppression comments cleaned alongside hook removals.
Watch-outs
None material.

GLM-5.1

Z.ai
2nd of 5 · 21/25
PR
Cost
$0.00
Time
20.1m
Turns
97
Diff
+168/−3852 · 47f
Correct
4/5
Scope
5/5
Quality
4/5
Risk
4/5
Surgical
4/5

Near-identical functional output to DeepSeek. isInIframe migrated correctly. BUT leaves orphaned forceBodyContainer parameter on portal type signatures + widespread missing-trailing-newline violations.

What stood out
useEffect in sonner.tsx preserved properly. Test simplifications appropriate.
Watch-outs
forceBodyContainer parameter still on DialogPortal/AlertDialogPortal type definitions. Multiple files missing trailing newlines — may fail npm run enforce.

k2p6

3rd of 5 · 17/25
PR
Cost
$0.00
Time
21.9m
Turns
91
Correct
3/5
Scope
4/5
Quality
3/5
Risk
3/5
Surgical
4/5

All 8 deletion targets confirmed gone. (main)/layout.tsx cleaned. SettingsPageClient + SettingsLayoutClient correctly migrated. sonner useEffect preserved. But Portal forceBodyContainer left in alert-dialog + dialog — iframe code still wired and reachable.

What stood out
Most thorough deletion of barrel exports + api-utils cleanup. Tests properly simplified. sonner useEffect preserved.
Watch-outs
forceBodyContainer={ignoreEmbeddedPosition} still live in AlertDialogContent + DialogContent. Portal bodies untouched. ignoreEmbeddedPosition remains as unused destructured param — likely fails npm run enforce.

MiniMax-M2.7

MiniMax
4th of 5 · 12/25
PR
Cost
$0.13
Time
9.8m
Turns
39
Diff
+69/−3842 · 37f
Correct
2/5
Scope
3/5
Quality
2/5
Risk
2/5
Surgical
3/5

Two build-breaking defects: SettingsPageClient.tsx never updated (still imports from deleted hook), sonner.tsx converts useEffect to bare top-level if-block.

What stood out
Correctly identifies and removes ignoreEmbeddedPosition from downstream call sites. JSDoc updated to remove Angular references.
Watch-outs
CRITICAL: SettingsPageClient.tsx imports from deleted @/hooks/use-parent-route-sync — hard compile failure. sonner.tsx converts useEffect to bare if-block — violates React rules, leaks style tags.
Design system · Urgent

SWA-6403 // Eliminate hardcoded styles + bare HTML — enforce design system

97 bare buttons + 92 hardcoded color classes. ESLint rules, enforce-standards checks, refactored design system tokens, then backfill.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1gpt-5.5#56$2.6010.3m7023/25
2GLM-5.1#41$0.005.8m3021/25
3k2p6#70$0.0024.2m9621/25
4DeepSeek-V4-Pro#59$0.0411.6m3818/25
5MiniMax-M2.7#49$0.117.6m3417/25
Winner

gpt-5.5 — PR #56

ESLint rules land in eslint.config.mjs (correct gate). Error-page allowlist is a second config block — drops bare-element restrictions only while keeping the color rule active. Full sonner refactor (icons, shadow, title, description, action/cancel/close buttons, status borders — all tokenized).

Score
23/25
Cost
$2.60
Turns
70
Time
10.3m
Diff
+324/−45 · 10f

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

gpt-5.5

OpenAI
1st of 5 · 23/25
PR
Cost
$2.60
Time
10.3m
Turns
70
Diff
+324/−45 · 10f
Correct
5/5
Scope
5/5
Quality
4/5
Risk
5/5
Surgical
4/5

Correct allowlist logic, full sonner refactor, --avatar-foreground token, clean abstractions.

What stood out
Best sonner refactor by far. Only PR to replace hardcoded text-white with text-avatar-foreground. isInsideDir() helper is more robust than file.startsWith().
Watch-outs
Avatar null fallback returns avatarColorClasses[0] (a color token) rather than a neutral like bg-muted. LESSONS_LEARNED footer bumps Wisdom Principles incorrectly.

GLM-5.1

Z.ai
2nd of 5 · 21/25
PR
Cost
$0.00
Time
5.8m
Turns
30
Diff
+406/−25 · 10f
Correct
4/5
Scope
5/5
Quality
4/5
Risk
4/5
Surgical
4/5

Best docs (richest 'What's Enforced' section). BUT Tailwind color ESLint rule is 'warn' not 'error' — spec violation. Sonner barely touched.

What stood out
Best CLAUDE.md update (dedicated 'Design System Enforcement' subsection). Governance table is clearest. Only PR with belt-and-suspenders Check 26 for bare HTML.
Watch-outs
Tailwind color ESLint rule severity is 'warn' instead of 'error' — violations would ship silently to main. Sonner unrefactored (7 of 8 violations remain).

k2p6

3rd of 5 · 21/25
PR
Cost
$0.00
Time
24.2m
Turns
96
Correct
5/5
Scope
4/5
Quality
4/5
Risk
4/5
Surgical
4/5

Wrote a real inline ESLint plugin (proper AST visitors, not just no-restricted-syntax). Best Tailwind color rule of any model — handles Literal, TemplateLiteral, BinaryExpression. Most complete sonner refactor. New --info/--success/--warning + 10 avatar tokens. Mass eslint-disable for backfill is greppable. But 2 spec deviations.

What stood out
Best ESLint architecture (real inline plugin with AST visitors). Most complete sonner refactor in field. Tailwind @theme aliases properly registered. Backfill TODOs greppable.
Watch-outs
Color rule disabled on error pages (spec says color rule should stay active there). Missing --avatar-foreground token — dark mode text may be invisible on the new avatar palette.

DeepSeek-V4-Pro

DeepSeek
4th of 5 · 18/25
PR
Cost
$0.04
Time
11.6m
Turns
38
Diff
+337/−20 · 11f
Correct
3/5
Scope
4/5
Quality
4/5
Risk
3/5
Surgical
4/5

Only PR with enforce:ci npm scripts. Correct ESLint 9 ignores idiom. BUT avatar null guard still returns 'bg-slate-400' — fires the new ESLint rule on itself.

What stood out
Only PR to add enforce:ci npm scripts to package.json. ESLint 'ignores' field is correct ESLint 9 idiom. Check 25 CSS-variable-skip logic is thoughtful.
Watch-outs
Avatar getAvatarColor null guard returns 'bg-slate-400' — hardcoded color triggering the rule the PR adds. No --avatar-foreground token. LESSONS_LEARNED YAML is malformed.

MiniMax-M2.7

MiniMax
5th of 5 · 17/25
PR
Cost
$0.11
Time
7.6m
Turns
34
Diff
+317/−19 · 10f
Correct
3/5
Scope
4/5
Quality
3/5
Risk
3/5
Surgical
4/5

'no-restricted-syntax':'off' for error pages disables existing <img> rule. Check 24 regex bug (unescaped \s).

What stood out
Smallest diff. Badge and alert refactors correct. Dark-mode avatar variants differentiated.
Watch-outs
'off' allowlist removes existing <img> enforcement on error pages — net regression. Template-literal regex bug means Check 24 silently misses all violations. No ESLint rule for hardcoded colors.
Storybook · High

SWA-6401 // Upgrade Storybook to enforcement tool — A+ implementation

Argos visual regression + a11y addon + story coverage enforcement + interaction tests + status tags + composite component stories.

⚠ Only 3 of 5 models produced PRs. gpt-5.5 and Gemini didn't land.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1GLM-5.1#42$0.006.3m4023/25
2k2p6#65$0.0011.8m6120/25
3MiniMax-M2.7#58$0.1511.3m5918/25
4DeepSeek-V4-Pro#52$0.0310.2m3913/25
Winner

GLM-5.1 — PR #42

Only PR to implement the deprecated banner (item 5 of spec). Best story-coverage scan scope (covers src/stories/ in addition to src/components/ui/). Clean 646-line diff with no lockfile noise. STATUS_TAGS exported as a typed const = single source of truth.

Score
23/25
Cost
$0.00
Turns
40
Time
6.3m
Diff
+230/−27 · 34f

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

GLM-5.1

Z.ai
1st of 5 · 23/25
PR
Cost
$0.00
Time
6.3m
Turns
40
Diff
+230/−27 · 34f
Correct
4/5
Scope
5/5
Quality
4/5
Risk
5/5
Surgical
5/5

Only PR with deprecated banner. Widest scan scope. Clean diff. Has a one-line bug: context.parameters.tags should be context.tags.

What stood out
Only PR to implement the deprecated banner. STATUS_TAGS exported as typed const. Widest story-coverage scan (includes src/stories/). CLAUDE.md references check numbers explicitly.
Watch-outs
context.parameters.tags is the wrong accessor — Storybook 7+ attaches tags to context.tags. Banner never renders until one-line fix applied.

k2p6

2nd of 5 · 20/25
PR
Cost
$0.00
Time
11.8m
Turns
61
Correct
3/5
Scope
4/5
Quality
4/5
Risk
4/5
Surgical
5/5

Widest scan scope of any PR (Check 23 covers BOTH directory + flat-file UI components). Correct context.tags accessor (fixes GLM's bug). 10 new story files for previously-uncovered components. preview.ts→preview.tsx rename (only PR to do this). BUT test:'todo' instead of test:'error' — a11y not actually CI-enforcing.

What stood out
Most thorough story-coverage scan + 10 new story files + preview.tsx rename + correct context.tags. Most additive contribution to the ecosystem.
Watch-outs
test: 'todo' should be test: 'error' — a11y won't gate PRs as-is. options.checks shape not valid axe-core API. Deprecated banner doesn't handle 'do-not-use' tag.

MiniMax-M2.7

MiniMax
3rd of 5 · 18/25
PR
Cost
$0.15
Time
11.3m
Turns
59
Diff
+188/−28 · 34f
Correct
3/5
Scope
4/5
Quality
3/5
Risk
4/5
Surgical
4/5

Clean diff but a11y config uses invalid axe-core property names — silently produces no enforcement.

What stood out
Story-tag migration thorough across all 28 files (incl. Foundations/ stories outside ui/). Clean diff, no lockfile churn.
Watch-outs
a11y config is invalid: 'evaluate: true' instead of 'enabled', 'minContrast' in wrong location. Silently produces no WCAG enforcement. No deprecated banner.

DeepSeek-V4-Pro

DeepSeek
4th of 5 · 13/25
PR
Cost
$0.03
Time
10.2m
Turns
39
Diff
+1134/−107 · 33f
Correct
4/5
Scope
1/5
Quality
4/5
Risk
2/5
Surgical
2/5

Best a11y config (correct runOnly with WCAG 2.x tags). Best docs. BUT 2100 lines of unrelated package-lock.json churn — peer-flag toggles + new @oxc-parser deps.

What stood out
Best a11y configuration of the three: correctly uses runOnly with explicit WCAG tags. Best docs with concrete CI gate table.
Watch-outs
2100 lines of unrelated package-lock.json churn (peer-flag mutations + new @oxc-parser deps). Major merge-conflict risk in NX monorepo.
Codebase intel · Urgent

SWA-6406 // Adopt Fallow for cross-module codebase intelligence

Rust-native static analysis as deterministic ground truth for AI-generated changes. Replaces knip/jscpd/madge/dependency-cruiser with one install.

⚠ Only 3 of 5 models produced PRs. gpt-5.5 and Gemini didn't land.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1k2p6#67$0.0012.4m5120/25
2DeepSeek-V4-Pro#40$0.025.3m1919/25
3GLM-5.1#34$0.003.6m2016/25
4MiniMax-M2.7#54$0.0813.1m3915/25
Winner

k2p6 — PR #67

Best architecture model: zone-based boundaries with autoDiscover for features — exactly maps the feature-isolation requirement. Only PR to update review-branch skill (PR 4 scope). Only PR with 'Alternatives Explicitly Not Used' section in docs. JSONC config with inline comments.

Score
20/25
Cost
$0.00
Turns
51
Time
12.4m

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

k2p6

1st of 5 · 20/25
PR
Cost
$0.00
Time
12.4m
Turns
51
Correct
4/5
Scope
4/5
Quality
5/5
Risk
3/5
Surgical
4/5

Best architecture model: zone-based boundaries with autoDiscover for features — exactly maps the feature-isolation requirement. Only PR to update review-branch skill (PR 4 scope). Only PR with 'Alternatives Explicitly Not Used' section in docs. JSONC config with inline comments.

What stood out
Zone-based boundary model with autoDiscover is the most architecturally coherent. Only PR to update review-branch skill. 'Alternatives Explicitly Not Used' section matches spec. JSONC config with comments.
Watch-outs
Unverified config fields (.fallowrc.jsonc filename, health.maxCrap, duplicates.mode/threshold). Fallow version ^2.74.0 implausible. No CI workflow file.

DeepSeek-V4-Pro

DeepSeek
2nd of 5 · 19/25
PR
Cost
$0.02
Time
5.3m
Turns
19
Diff
+298/−0 · 5f
Correct
4/5
Scope
3/5
Quality
5/5
Risk
3/5
Surgical
4/5

Best docs. Only PR with Next.js framework conventions in .fallowignore. severityPolicy block. Invented config fields (allowBarrelImports, maxDepth) are minor risks.

What stood out
Best .fallowignore (Next.js framework conventions handled). severityPolicy block implements blocking policy in one readable location. ci block in config is forward-thinking partial credit for missing workflow.
Watch-outs
allowBarrelImports / allowSharedDomain / maxDepth fields likely don't exist in Fallow schema. fallow: ^1.0.0 assumes a stable major release.

GLM-5.1

Z.ai
3rd of 5 · 16/25
PR
Cost
$0.00
Time
3.6m
Turns
20
Diff
+232/−1 · 5f
Correct
3/5
Scope
2/5
Quality
3/5
Risk
4/5
Surgical
4/5

Best governance comparison table in docs + entryPoints config detail. BUT {{featureA}}/{{featureB}} placeholder syntax in feature-isolation rule likely not valid Fallow config.

What stood out
entryPoints array in config is the right operational detail. Governance stack comparison table is clearest. Lean .fallowignore.
Watch-outs
{{featureA}}/{{featureB}} placeholder syntax probably model-invented. If Fallow doesn't interpret these as wildcards, the feature-isolation rule silently does nothing.

MiniMax-M2.7

MiniMax
4th of 5 · 15/25
PR
Cost
$0.08
Time
13.1m
Turns
39
Diff
+248/−0 · 5f
Correct
3/5
Scope
3/5
Quality
3/5
Risk
3/5
Surgical
3/5

Solid architecture rules + clean triage workflow in docs. BUT embeds ESLint config inside fallow.config.json — likely runtime error.

What stood out
Clean layers + rules schema. Triage section mirrors ticket spec language. CLAUDE.md entry clean.
Watch-outs
ESLint config embedded inside fallow.config.json is structurally wrong, likely to error on first run. Path-relative .fallowignore may not resolve from apps/next-swan/.
Docs platform · Urgent

SWA-6404 // Migrate fumadocs to native source layer + docs CI gates

Replace custom fs walker with fumadocs-mdx + Zod-validated frontmatter. Add CI gates for feature-doc parity, stale-reference detection.

⚠ Only 3 of 5 models produced PRs. gpt-5.5 and Gemini didn't land.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1DeepSeek-V4-Pro#60$0.0413.1m4524/25
2GLM-5.1#44$0.007.0m4221/25
3k2p6#71$0.0038.3m15720/25
4MiniMax-M2.7#51$0.078.8m306/25
Winner

DeepSeek-V4-Pro — PR #60

Correct frontmatterSchema.extend() from fumadocs-mdx/config. Extends existing enforce-standards.mjs rather than replacing. check-doc-impact.mjs handles GITHUB_EVENT_PATH correctly. Real broadcast/README.mdx demo file proves components render end-to-end.

Score
24/25
Cost
$0.04
Turns
45
Time
13.1m
Diff
+974/−9 · 13f

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

DeepSeek-V4-Pro

DeepSeek
1st of 5 · 24/25
PR
Cost
$0.04
Time
13.1m
Turns
45
Diff
+974/−9 · 13f
Correct
4/5
Scope
5/5
Quality
5/5
Risk
5/5
Surgical
5/5

Correct API. Additive enforce-standards. Demo MDX proves render. Only fix needed: align fumadocs-mdx ^15.0.4 to fumadocs-core ^16.5.0.

What stood out
Only PR that reads GITHUB_EVENT_PATH for actual PR body. Broadcast demo MDX file actually uses APITable, Callout, EnvVar — proof of end-to-end render.
Watch-outs
fumadocs-mdx ^15.0.4 vs fumadocs-core ^16.5.0 version mismatch (one-line fix).

GLM-5.1

Z.ai
2nd of 5 · 21/25
PR
Cost
$0.00
Time
7.0m
Turns
42
Diff
+659/−2 · 16f
Correct
4/5
Scope
4/5
Quality
4/5
Risk
5/5
Surgical
4/5

Correct API + correct version alignment (^16.5.0). Clean component code with types. BUT no proof-of-render MDX file, thinner docs.

What stood out
Correct fumadocs-mdx version alignment with fumadocs-core. Clean MDX components in kebab-case naming.
Watch-outs
No demo MDX file proving components render. documentation.md is shorter (80 lines vs 284). Coarser opt-out semantics in Gate 2.

k2p6

3rd of 5 · 20/25
PR
Cost
$0.00
Time
38.3m
Turns
157
Correct
4/5
Scope
5/5
Quality
4/5
Risk
3/5
Surgical
4/5

Most ambitious diff in the war: full 128-file .md→.mdx rename in one pass + all 5 MDX components + all 3 CI gates. Callout wraps fumadocs-ui/components/callout natively (best architectural choice). enforce-standards extended additively with 4 new checks (23-26). BUT 2 structural omissions: tsconfig.json not updated to include source.config.ts/.source/**, and no root mdx-components.tsx.

What stood out
Most complete fumadocs migration in the war — full 128-file corpus renamed. Callout wraps fumadocs-ui natively. enforce-standards extension is cleanest additive impl in field.
Watch-outs
tsc will fail — tsconfig.json missing source.config.ts + .source/** includes (GLM got this right). No root mdx-components.tsx. fumadocs-mdx ^15.0.4 vs fumadocs-core ^16.5.0 (same version mismatch as DeepSeek).

MiniMax-M2.7

MiniMax
4th of 5 · 6/25
PR
Cost
$0.07
Time
8.8m
Turns
30
Diff
+958/−670 · 12f
Correct
1/5
Scope
1/5
Quality
2/5
Risk
1/5
Surgical
1/5

DELETES all 22 existing enforce-standards checks. Wrong fumadocs API. Top-level return in script is a runtime SyntaxError.

What stood out
MDX components themselves are reasonable (cva variants in Callout).
Watch-outs
CRITICAL: rewrites enforce-standards.mjs from scratch, deleting all 22 existing checks. Wrong fumadocs API (defineCollection from wrong package). check-doc-impact.mjs has top-level return — SyntaxError.
Security CI · Urgent

SWA-6405 // Add deterministic security CI gates

SAST tool that actually gates PRs. Semgrep + gitleaks + blocking npm audit + ESLint security plugins + supply-chain hygiene.

⚠ Only 3 of 5 models produced PRs landed before fleet wrapper finalized.

01The leaderboard

Scored on five dimensions, 1–5 each: Correctness · Scope discipline · Code quality · Risk · Surgical-ness.

#ModelPRCostTimeTurnsScore
1gpt-5.5#57$2.4610.2m8022/25
2DeepSeek-V4-Pro#47$0.027.6m2915/25
3GLM-5.1#55$0.009.9m4412/25
4MiniMax-M2.7#45$0.057.2m338/25
5k2p6$0.0012.6m35
Winner

gpt-5.5 — PR #57

Only PR with a real audit-delta computation. ESLint rule calibration is thoughtful (high-confidence as errors, noisy rules as warnings with explanations). Semgrep rule has pattern-not for both await/non-await variants.

Score
22/25
Cost
$2.46
Turns
80
Time
10.2m
Diff
+327/−2 · 9f

02How each model played it

In rank order. Score bars (Correctness · Scope · Quality · Risk · Surgical) + signature behaviors + red flags per model.

gpt-5.5

OpenAI
1st of 5 · 22/25
PR
Cost
$2.46
Time
10.2m
Turns
80
Diff
+327/−2 · 9f
Correct
4/5
Scope
4/5
Quality
5/5
Risk
4/5
Surgical
5/5

Only PR with real audit-delta script. Best ESLint calibration. Needs workflow file follow-up.

What stood out
Only PR with actual audit-delta computation (correctly implements 'new findings block, existing findings do not'). ESLint warn/error split is well-documented. Two Semgrep pattern-not blocks for await/non-await variants.
Watch-outs
No .github/workflows/ci-pr-checks.yml changes — shared gap. Gitleaks 'regexes' field is wrong TOML section.

DeepSeek-V4-Pro

DeepSeek
2nd of 5 · 15/25
PR
Cost
$0.02
Time
7.6m
Turns
29
Diff
+299/−0 · 6f
Correct
3/5
Scope
3/5
Quality
3/5
Risk
3/5
Surgical
3/5

Valid parseable configs. Two Semgrep rules. BUT no useDefault=true in gitleaks (only 6 hand-written rules vs ~150 defaults). Test/spec files globally excluded.

What stood out
Valid parseable configs. Second Semgrep rule (console.log JWT detection) is genuine addition. CLAUDE.md gate summary table is useful for agents.
Watch-outs
No useDefault=true in gitleaks — loses ~150 default secret patterns. .test./.spec. globally excluded — would hide secrets in test fixtures. ESLint security flat-config spread without files filter applies to all files.

GLM-5.1

Z.ai
3rd of 5 · 12/25
PR
Cost
$0.00
Time
9.9m
Turns
44
Diff
+616/−863 · 10f
Correct
3/5
Scope
2/5
Quality
3/5
Risk
2/5
Surgical
2/5

Most rules + best docs. BUT 2285 lines of spurious lockfile churn from different npm version. Workflow shipped as a .yml reference file in docs/ (manual apply required).

What stood out
Two Semgrep rules (getSession + hardcoded secrets). Updates root CLAUDE.md correctly. security.md is the most thorough of the four.
Watch-outs
2285 lines of spurious lockfile churn unrelated to deps. Gitleaks uses [[rules.allowlist]] without [[rules]] block — TOML structural error. Workflow as reference doc, not actual .github/workflows/ entry.

MiniMax-M2.7

MiniMax
4th of 5 · 8/25
PR
Cost
$0.05
Time
7.2m
Turns
33
Diff
+148/−18 · 6f
Correct
1/5
Scope
3/5
Quality
1/5
Risk
1/5
Surgical
2/5

.gitleaks.toml and swan-rules.yml are single-line files with literal \n escape sequences — invalid TOML/YAML, won't parse.

What stood out
Intent of Semgrep rule (getSession check) is correct.
Watch-outs
CRITICAL: gitleaks/semgrep config files are single-line with literal \n — invalid syntax, won't parse. Deletes existing Rule 12 (audit-log enforcement). References non-existent ESLint rules (detect-eval-with-env, no-unsanitized/react, detect-inner-html, detect-document-write).

k2p6

5th
PR
none
Cost
$0.00
Time
12.6m
Turns
35

Kimi k2p6 (Moonshot coding plan). PR # at $0.000, 35 turns, 12.6m. Review pending — will be compared head-to-head against the top-2 models for this ticket.

What we should pull up next

Next Hopper Run

Looking at Jerub's open queue of Hopper-delegated tickets, here's the highest-leverage pick — plus the model we'd use.

Recommended next run
SWA-6427 Add ts-node and typescript as workspace dev dependencies

Why this one first:

  • FOUND-1 blocker. Every other Hopper foundation ticket Jerub owns (SWA-6403, 6404, 6405, 6431, 6437) sits behind this. Right now npx jest can't parse jest.config.ts and npx tsc --noEmit picks up the wrong TypeScript. Standards pipeline can't validate locally; the per-changed-file coverage gate is aspirational.
  • SLA-breached on 2026-05-12 (3 days overdue). Same urgency tier as 6400 but a fraction of the work.
  • Small (2 points) and mechanical — perfect for a fair model comparison without noise from interpretation differences.
  • Unblocks the rest of Jerub's queue once it lands. Highest impact-per-PR in the backlog.

Recommended model: GLM-5.1 at thinking=high. Same shape as SWA-6435 (mechanical, well-specified config change) where GLM won at $0 cost. DeepSeek-V4-Pro is the fallback. Skip gpt-5.5 — cost-to-complexity ratio doesn't justify it for a 2-point ticket.

02Runners-up in Jerub's queue

SWA-6431 · Urgent · 3 pts
CSRF Origin validation for state-mutating APIs. Security work — fits gpt-5.5 (retry-mode) where correctness ceiling matters.
SWA-6403 · Urgent
Eliminate hardcoded styles and bare HTML — enforce design system at PR-time. Larger scope, great Hopper-Run demo once foundation lands.
SWA-6405 · Urgent
Deterministic security CI gates — Semgrep, gitleaks, npm audit. Save for once 6427 unblocks the validation pipeline.
SWA-6401 · High
Upgrade Storybook from documentation tool to enforcement tool. Visual regression — needs a model with good design intuition.