conrads.website


DIZZY LAB: 13 Models, One Prompt

I gave the same prompt — build a standalone HTML/JS visualization of a mock robot arm driven by a DIZZY-style event-sourced system — to 13 different model/agent combinations, with zero other context or coaching. Three ran in Claude Code (Fable 5, Opus 4.8, Sonnet 5), and ten ran through pi, a lighter-weight agent CLI (Sakana Fugu Ultra twice — once bare, once with a design-system "viz skill" loaded — OpenAI's GPT-5.6 across six variants: the luna/sol/terra effort tiers, and their -pro counterparts — plus single bare runs of Zhipu's GLM 5.2 and Moonshot's Kimi K3). Below is what came out, what it cost, and how the approaches differ.

Update: added the -pro variants of GPT-5.6-luna, -sol, and -terra after the original 8-way comparison — same single-shot prompt, same pi harness, run from three fresh empty directories. GPT-5.6-sol-pro failed with a provider-side Internal Server Error on the first attempt (no output, no cost billed) and succeeded on retry; that's reflected in its session but not in the metrics below.
Update: added a twelfth run — Zhipu's GLM 5.2 (z-ai/glm-5.2 via OpenRouter) through the same pi harness and identical single-shot prompt, from a fresh empty directory. Like the GPT-5.6 entries it ran genuinely single-shot (one prompt in, done); its metrics below are measured at the point its visualization was committed and pushed, before the blog entry you're reading was authored in the same session.
Update: added a thirteenth run — Moonshot's Kimi K3 (moonshotai/kimi-k3 via OpenRouter) through the same pi harness and identical single-shot prompt. Unlike every other pi/CLI entry, this one was not hands-off: it repeatedly hit its output token limit mid-response and had to be manually nudged to "try to continue" before it finished, and it spent several tool calls scripting its own headless-Chromium test harness — writing and then deleting throwaway shot_test.html/ shot_modal.html/test_drive.html driver files to screenshot and console-check its own output before declaring done. Turn count and cost below reflect that extra back-and-forth.

Metrics

"Turns" below counts agent (LLM) responses within the session — how many times the model spoke or acted before finishing. All 13 got the identical single-shot prompt from PROMPT.md; most of the pi/CLI runs stayed genuinely single-shot (one prompt in, done), while all three Claude Code runs got a courtesy /model//export/ "commit and push" nudge afterward — and Fable 5 specifically ran out of room mid-task and needed a manual "Continue from where you left off" to finish, which is reflected in its outsized turn count and cost below. Kimi K3 is the one pi/CLI exception: it hit its own output token limit mid-response more than once and needed a manual "try to continue" nudge to finish, on top of spending several turns writing and screenshotting throwaway HTML test files.

Agent turns

Fable 5
60
Opus 4.8
57
Sonnet 5
113
Fugu Ultra
31
Fugu + skill
44
GPT-5.6-luna
7
GPT-5.6-sol
10
GPT-5.6-terra
4
GPT-5.6-luna-pro
6
GPT-5.6-sol-pro
5
GPT-5.6-terra-pro
8
GLM 5.2
54
Kimi K3
47

Tool calls (bash / read / edit / write)

Fable 5
28
Opus 4.8
26
Sonnet 5
56
Fugu Ultra
36
Fugu + skill
57
GPT-5.6-luna
6
GPT-5.6-sol
12
GPT-5.6-terra
3
GPT-5.6-luna-pro
7
GPT-5.6-sol-pro
4
GPT-5.6-terra-pro
6
GLM 5.2
53
Kimi K3
45

Total tokens (input + output + cache read/write)

Fable 5
4.76M
Opus 4.8
3.23M
Sonnet 5
11.14M
Fugu Ultra
1.38M
Fugu + skill
2.78M
GPT-5.6-luna
0.07M
GPT-5.6-sol
0.16M
GPT-5.6-terra
0.03M
GPT-5.6-luna-pro
0.30M
GPT-5.6-sol-pro
0.22M
GPT-5.6-terra-pro
0.26M
GLM 5.2
2.13M
Kimi K3
2.80M

Cost (USD, list price)

Fable 5
$19.11
Opus 4.8
$4.94
Sonnet 5
$4.62
Fugu Ultra
$3.01
Fugu + skill
$4.56
GPT-5.6-luna
$0.08
GPT-5.6-sol
$0.79
GPT-5.6-terra
$0.15
GPT-5.6-luna-pro
$0.41
GPT-5.6-sol-pro
$1.85
GPT-5.6-terra-pro
$0.80
GLM 5.2
$0.65
Kimi K3
$2.75

Lines of output HTML/JS/CSS

Fable 5
933
Opus 4.8
780
Sonnet 5
740
Fugu Ultra
958
Fugu + skill
1335
GPT-5.6-luna
303
GPT-5.6-sol
637
GPT-5.6-terra
76
GPT-5.6-luna-pro
478
GPT-5.6-sol-pro
359
GPT-5.6-terra-pro
306
GLM 5.2
934
Kimi K3
823

Costs are computed from raw token usage at published list pricing per model (Claude models: Anthropic API rates as of 2026-07; pi/OpenRouter models: per-session usage.cost reported by the provider). Cache-read/write tokens are priced at their usual discount/premium multipliers, not 1:1 with fresh input tokens — "total tokens" above is a raw sum across all four buckets and is a proxy for context volume, not a linear cost driver.

Who did what

Model Harness Real IK? Queue engine Visual Unique touch
Fable 5Claude Code✓ 2-link, law of cosinesFull — capacity, backpressure, retry-on-failureSVG, darkOnly one with a modeled failure/retry policy
Opus 4.8Claude Code✓ 2-link, law of cosinesMessage-bus, single-cycleSVG, darkExplicit query/querier read-loop wired separately from reactivity
Sonnet 5Claude Code✓ angle-lerped 2-linkFull — concurrent samples, serialized arm accessSVG, darkOnly one with continuous multi-sample throughput (play/pause/speed)
Fugu Ultrapi✓ 2-link, law of cosinesSingle dispatch/demoHTML+CSS+SVG, dark, glassmorphismGuided-tour "run 3 recipes" demo mode
Fugu + viz skillpi✓ 2-link, law of cosinesSingle dispatch, multi-step "protocol" builderSVG, dark, most elaboratePalette-validator provenance comment + live JSON model readout
GPT-5.6-lunapi✗ hardcoded CSS rotationsNone — linear scripted run()Pure CSS/HTML, no SVG/canvasSmallest real logic footprint (~40 lines JS)
GPT-5.6-solpi✓ 2-link, law of cosinesSingle dispatch, modular helper functionsSVG, light/paper — the one non-dark themeQueue-card "aging" progress bars, live trace-ID readout
GPT-5.6-terrapi✗ hardcoded CSS rotationsNone — linear scripted run()Pure CSS/HTML, isometric floor grid76 lines total — most information-dense per line of any entry
GPT-5.6-luna-propi✓ 2-link, atan2/acosSingle dispatch, linear async scriptSVG, dark control-room, dual physical+logical graphClickable/keyboard-accessible SVG hotspots for sample+processor selection
GPT-5.6-sol-propi✓ 2-link, two-circle intersectionConfigurable multi-stop route, parallel policy/projection dispatchSVG, dark lime/cyan "terminal" themeUser-orderable multi-processor route + Promise.all fan-out — most architected of the six pi/CLI runs
GPT-5.6-terra-propi✓ 2-link, atan2/acosSingle dispatch, linear async scriptSVG, dark navy/cyan/limeToast notifications on selection change; seeded initial event feed
GLM 5.2pi✓ 2-link, atan2/acos, elbow-config selectionFull — continuous scheduler, gated policy fan-out, autoloop re-enqueueSVG, dark three-panel control-roomSemantically-guarded policy fan-out + full 8-component vocab with animated query→policy read-loop
Kimi K3pi✓ 2-link, atan2/acosFull — pump() queue loop, concurrent policy+projection dispatch, conditional policy firingSVG, dark three-panel control-roomRead side genuinely consulted mid-dispatch (proc.queries query→data-loop hop) before the command executes

11 of 13 implemented genuine inverse kinematics (atan2/acos or two-circle-intersection law-of-cosines solves for a 2-link arm) despite the prompt never mentioning IK, physics, or joint math — it just asked for an arm that "can pick up a sample ... and move it." Only the base (non--pro) GPT-5.6-luna and GPT-5.6-terra skipped IK entirely, in favor of keyframing pose-to-pose in CSS. Notably, their -pro counterparts both picked up real IK and the same effort tier's queue sophistication didn't automatically follow — luna-pro and terra-pro stayed single-shot linear scripts even with correct arm geometry, while sol-pro alone crossed into a genuinely reconfigurable multi-stop route with parallel policy/projection dispatch — the most architected of the GPT-5.6 pi/CLI runs. GLM 5.2 went further still: a continuous scheduler with semantically-guarded policy fan-out and the full eight-component read-loop wired, not just narrated. Kimi K3, the thirteenth entry, landed in similar territory — a real pump() queue loop with concurrent policy/projection dispatch and conditional policy firing — but got there the hard way, needing a manual nudge past its own output limit and burning several turns on a self-authored headless-browser test harness before it converged.

Notes per run

Claude Fable 5 Claude Code

933 lines · 60 turns · 28 tool calls · $19.11 · needed a manual "continue"
Kinematics
Real 2-link IK (toPolar/fromPolar, law of cosines), with a sweepTo() outward "bulge" so the arm never clips through the floor mid-swing.
Queue/events
The most systems-accurate of the eight: a real QUEUE array with a pump() scheduler that only runs commands whose preconditions hold — arm busy, processor busy, tray full — plus a genuine ~20% random failure rate feeding a retry_processing policy.
Notable
Read models are explicitly rebuilt from events only, never touched directly from the physical scene — the only entry that enforces that separation in code, not just naming.

Most architecturally faithful simulation of an actual event-sourced system — but it's also the most expensive run by a wide margin, largely because it ran out of room and had to be told to keep going.

Claude Opus 4.8 Claude Code

780 lines · 57 turns · 26 tool calls · $4.94
Kinematics
Real 2-link IK via solveIK(tx,ty), decoupled per-frame easing (lerp) toward IK targets in a separate tick() loop from rendering.
Queue/events
A message-bus (emit/project/queryRead) drives the queue panel and graph together; quadratic-bezier particles are colored differently for reactivity, projection, and query-read edges.
Notable
Explicitly wires in a full query/querier read pair (get_recipe) — DIZZY's full 8-part vocabulary, not just the 6 core types most others used.

The cleanest, most legibly-sectioned code of the eight, correct IK, strong graph choreography — least "systemically complex" of the three Claude runs (no concurrent job queue) but very readable.

Claude Sonnet 5 Claude Code

740 lines · 113 turns · 56 tool calls · $4.62
Kinematics
Real 2-link IK (ik(tx,ty)), animated by interpolating joint angles rather than raw positions — avoids the pop/gimbal artifacts a naive Cartesian lerp would produce.
Queue/events
The only implementation with true continuous multi-sample throughput: spawnSample() auto-creates work, a single-consumer commandLoop() serializes handlers, and armSerial() queues physical arm moves so up to 4 concurrent samples don't fight over the one arm.
Notable
Play/pause, speed slider, live "completed"/"in-flight" counters — feels like watching a running production system rather than a scripted trace.

Highest turn count of all eight by far (113) but the second-cheapest of the three Claude runs — it did a lot of small, cheap iterations rather than a few expensive ones. Technically the most "systems" feeling.

Sakana Fugu Ultra pi

958 lines · 31 turns · 36 tool calls · $3.01
Kinematics
Real 2-link IK (updateArmGeometry), recomputed fresh each frame from the target rather than carrying separate joint-angle state.
Queue/events
Percentage-space SVG network graph with a floaty sinusoidal-wobble particle animation; five distinct processors (mixer/heater/scanner/cooler/archive) vs. the more common three.
Notable
A surviving code comment documents a mid-session bug fix ("old fixed px*4.3 mapping ... drifted") — visible evidence of iterative self-correction. Leans into a guided-tour UX with recipe shortcut buttons and an auto-chaining demo button.

Competent and correct, with a more consumer/product-demo feel — emoji icons, guided tour — than the "engineering mock" tone of the Claude runs.

Sakana Fugu Ultra + viz skill pi

1335 lines (largest) · 44 turns · 57 tool calls · $4.56
Kinematics
Same real 2-link IK formula as the bare Fugu run, plus a dashed "travel line" that previews the gripper's straight-line path before it moves.
Queue/events
Full query/querier round-trip edges in the graph and a live raw-JSON model readout (<pre>JSON.stringify(model)</pre>) alongside a scrolling system log — the only entry with a live model dump.
Notable
Opens with an explicit palette-validation provenance comment citing a design-system skill run (node scripts/validate_palette.js ... ALL CHECKS PASS) and data-palette/data-mode attributes — direct evidence the loaded skill changed behavior. Also the only one with a multi-step "protocol" builder chaining several processors in one route.

The skill's fingerprints are visible mainly in color-system rigor and accessibility bookkeeping, not kinematics — most visually/documentation-polished of the pi runs, at nearly 1.5x the bare Fugu's line count.

GPT-5.6-luna pi

303 lines · 7 turns · 6 tool calls · $0.08 — cheapest run
Kinematics
None. The arm is a .arm div with hardcoded per-station CSS transform: rotate(...) values and fixed-angle pseudo-element segments — no geometry computed at runtime.
Queue/events
No real queue — a single linear async function run() walks a fixed script with hardcoded await pause(ms) delays. One JS-driven particle animates along a straight line from graph-center to target node.
Notable
Despite skipping IK and a queue engine entirely, still auto-runs a full command→event→policy→projection narration once on load, with explanatory footer prose.

The simplest and least "real" of the eight, but by far the cheapest — 7 turns and 8 cents for a functional, well-styled illustration.

GPT-5.6-sol pi

637 lines · 10 turns · 12 tool calls · $0.79
Kinematics
Real 2-link IK (renderArm(x,y), Math.hypot/atan2/acos), wrapped in an eased cubic tween.
Queue/events
Genuine SVG-path particle flow plus a distinctive touch: queue cards show an animated CSS progress underline representing message "aging" through queued→routed→handled states, and an embedded "current trace" narration panel.
Notable
The only implementation with a light/paper theme (cream/orange/teal) instead of the dark "control room" look every other entry converged on — a genuinely different visual take on the identical brief.

Technically solid — real IK, real path-based flow — with the strongest visual-design differentiation of the eight, for well under a dollar.

GPT-5.6-terra pi

76 lines (smallest by far) · 4 turns · 3 tool calls · $0.15
Kinematics
None. Fixed rotate() angles baked directly into CSS for each joint; the one JS animation applies a single whole-arm-group transform at a few scripted keyframes.
Queue/events
No queue engine — activate(node, link, color) toggles CSS classes and moves a single particle div from a fixed center point to the target node, 9 hardcoded steps total.
Notable
An isometric floor grid via perspective()/rotateX() CSS gives real depth for zero extra JS — the whole interactive document is under 30 lines of actual script.

The least technically ambitious entry — no IK, no queue, no concurrency — but remarkably polished-looking for 76 lines. Reads as staged rather than simulated, and it's honest about that trade.

GPT-5.6-luna-pro pi

478 lines · 6 turns · 7 tool calls · $0.41
Kinematics
Real 2-link IK — poseFor(target) uses Math.atan2/Math.acos law-of-cosines, with a code comment explicitly calling out "a small inverse-kinematics solver." A clean upgrade from the base luna's hardcoded CSS rotations.
Queue/events
animatePacket() genuinely moves tokens along SVG paths via getPointAtLength + requestAnimationFrame, replacing base luna's CSS-transition approach — but the orchestration underneath (runTransfer) is still one linear scripted async sequence with hardcoded delays, not a real scheduler.
Notable
Two separate SVG panels — physical scene and logical wiring graph — with keyboard-accessible (tabindex/role=button) clickable hotspots for choosing sample and processor, plus a "SIMULATION / NO HARDWARE CONNECTED" watermark.

A real jump from the base model: proper IK and JS-driven animation replace CSS keyframes entirely, though it's still a single scripted run rather than an engine.

GPT-5.6-sol-pro pi

359 lines · 5 turns · 4 tool calls · $1.85 · needed one retry (provider error, $0 billed)
Kinematics
Real 2-link IK via drawArm(x,y), solved with the two-circle-intersection formula rather than atan2/acos — same underlying law-of-cosines geometry, different derivation.
Queue/events
The most architected run of the entire set: a user-configurable, click-to-order multi-stop processor route (1-3 stations), Promise.all parallel fan-out for policy + projection dispatch, DOM-position-resolved wire animation via ResizeObserver, per-run cancellation guards, and genuine auto-expiring "draining" queue cards with countdown progress bars.
Notable
Switches from the base sol's light/paper theme to a dark lime-green/cyan "terminal" aesthetic — the visual differentiation moved, but the IK and code quality both held or improved.

The standout of the three -pro runs and arguably of the whole pi/CLI cohort — a genuinely reconfigurable route engine, not just a nicer single-shot demo.

GPT-5.6-terra-pro pi

306 lines · 8 turns · 6 tool calls · $0.80
Kinematics
Real 2-link IK — setArm(target) uses atan2/acos law-of-cosines for both the elbow and end-effector angle, plus perpendicular-vector math to orient the gripper jaws. A comment notes "every station is physically reachable in this mock cell."
Queue/events
Animated packet dots (pulse()) travel real SVG paths, colored by command/event/projection type, but there's no persistent queue-list UI — just a live record feed and node/edge highlighting. execute() remains one hardcoded linear sequence, no route configuration or concurrency.
Notable
Toast notifications on selection change ("Command subject updated — no fact has been written."), a live ticking clock, and seeded initial feed records so the log has context before the first run.

Gains real IK and path-based animation over the base terra, but stays the least ambitious of the three -pro runs — same single fixed-dropdown, single-sequence shape as before, just with correct geometry underneath.

GLM 5.2 (Zhipu) pi

934 lines · 54 turns · 53 tool calls · $0.65
Kinematics
Real 2-link IK — ik(tx,ty) solves shoulder→elbow via atan2/acos law-of-cosines, then selects between the two valid elbow configurations by keeping the one that sits higher (smaller y), so the arm never swings through the floor. Gripper jaws are oriented perpendicular to the forearm each frame.
Queue/events
The most complete scheduling engine in the pi cohort — a real QUEUE/ACTIVE scheduler with tryLoadNext() continuous dispatch, autoloop re-enqueue, and gated policy fan-out: on_arrival fires only when to=proc, on_rack only when to=rack, so one sample_transferred can't spuriously trigger both. Both loops are wired with animated packets — including back-arc policy→command edges arching over the graph and the query→policy read-return round trip.
Notable
Full eight-component DIZZY vocabulary (c/d/e/y/j/m/q + querier) all present and animated; interactive — click rack slots to spawn or enqueue vials, plus pause/play/speed/autoloop controls. Processors animate per type (heater pulses, centrifuge spins, spectrometer beams); vials blend color toward each processor they pass through. Verified headless: no console/page errors, the arm reaches every station without NaNs, and the feed fills with the full c/d/e/y vocabulary.

The most architected pi run in the set — a genuine continuous scheduler with semantically-guarded policy dispatch and the full eight-component read-loop wired end-to-end, not just narrated.

Kimi K3 (Moonshot) pi

823 lines · 47 turns · 45 tool calls · $2.75 · needed a manual "try to continue"
Kinematics
Real 2-link IK — ik(gx,tx,ty) via atan2/acos, with a fixed elbow-side branch chosen explicitly (per a code comment) for "smooth, machine-like motion" rather than picking whichever solution is closer each frame.
Queue/events
The whole feature is declared as data upfront (FEATURE = {commands, procedures, policies, projections, models, queries}, a literal in-code .feat.yaml) and driven by a real async pump() loop over a shared queue: dispatchCommand makes procedures consult the read side (proc.queries) before executing, and dispatchEvent fans out to policies and projections concurrently via Promise.all, with policies conditionally firing (policyFires) rather than always dispatching.
Notable
The one run in the whole set that visibly struggled: it hit its own output token limit mid-response more than once and needed a manual "try to continue" to finish, then spent several tool calls writing, running, and deleting throwaway headless-Chromium test rigs (shot_test.html, shot_modal.html, test_drive.html) to screenshot and console-check its own work before cleaning them up and declaring done.

Technically on par with the best of the pi cohort — real IK, a genuine queue engine with conditional policy firing and a query round-trip — but the only run that needed hand-holding to actually finish, and the most expensive pi/CLI entry as a result.

See it yourself

Live visualizations:

Full agent session transcripts:

Shared prompt: PROMPT.md — identical text handed to every model, no other context, no follow-up coaching beyond housekeeping commands.