# TOASTSIM — Build Brief **For: Claude Opus 4.8, executing in Claude Code on this Mac (M3 Ultra, cwd `/Users/m3ultra/Documents/toastsim`).** **Approved by the owner. Build the whole thing; commit and push per milestone. Asset generation is free and pre-authorized — see §3.** --- ## 1. What we're building **TOASTSIM** — a browser game about making toast, where the *inputs are analog* and the *output is judged*. Two connected activities: 1. **The Toast Round** — toast bread (timing + power), spread it (pressure/angle physics per spread type), scrape burnt bits (risk/reward), get scored by a deadpan judge. 2. **The Cutlery Drawer** — a 3D physics minigame: a tangled drawer of *similar-but-not-identical* metal cutlery; fish out the specific requested item against a timer, **while your toast cools** (cold toast = hard butter = harder spread round). Tone: dry, characterful, slightly absurd. PowerWash-Simulator-style satisfaction with a scoring screen that makes you go "one more toast." **Arcade loop:** a customer order appears ("dark toast, thin vegemite, NO burnt bits") → drawer → toast → spread/scrape → judgment → next order, escalating. ## 2. Stack & repo - **Vite + TypeScript + Three.js** for everything (both scenes 3D — the toast slice is a real GLB you paint on). **@dimforge/rapier3d-compat** for drawer physics. No React needed; DOM overlay for UI is fine. Target 60fps in Chrome. - Repo: the folder is empty. `git init`, build in it, remote is `https://gitea.partly.party/monster/toastsim.git` (exists, empty). Push `main` after each milestone with a clear message. - Create `.claude/launch.json` with the Vite dev server so the app is previewable via the Browser pane. Verify visually with screenshots as you go — don't trust "it compiles." - Generated assets go in `public/assets/` (committed — they're small GLBs/PNGs and reproducibility matters less than a working repo). ## 3. Asset factory — MODELBEAST (free, local, pre-authorized) This Mac runs MODELBEAST, a job server wrapping local ML tools. **You are explicitly allowed to use it. Everything below is $0 (on-device).** Full reference: `~/Documents/MODELBEAST/AGENTS.md` — read it before your first job. ### Auth & basics ```bash cd ~/Documents/MODELBEAST source data/agent.env # sets MB_HOST + MB_TOKEN (guest: local ops only, free by design) ./mb ops -v # live operator catalog — trust this over docs ``` If the server is down (`curl http://localhost:8777/api/health` fails): `~/Documents/MODELBEAST/scripts/serve.sh`. Guest tokens **cannot** run paid cloud ops (server-enforced 403) — never try to work around that; the local chain below is the intended path. ### The two pipelines you'll use **Prompt → 2D image** (UI art, judge portraits, backdrops, labels, title screen): ```bash ./mb run flux_local -p prompt="..." -p model=flux2-klein-4b -p steps=4 -p seed=7 --wait --download out/ ``` Fixed seeds = reproducible. 1024×1024 default; set `width`/`height` for backdrops. **Prompt → 3D GLB** (bread, toaster, cutlery, jars, plate): ```bash # 1. generate a clean "product shot" image of the object ./mb run flux_local -p prompt=", single object centered on plain light grey background, soft studio lighting, 3/4 view, stylized chunky game asset" -p seed= --wait # 2. cut it out (biggest quality lever for image→3D) ./mb run bg_remove_local --asset --wait # 3. mesh it (GLB + PBR texture, ~4-5 min, no login needed) ./mb run hunyuan3d_mlx --asset -p octree_resolution=256 -p texture_size=1024 --wait --download public/assets/models/ ``` `blender_convert` exists if you need format conversion. `mflux_image_edit` for prompt-based image fixes. ### Job etiquette (hard rules) - **GPU jobs run one at a time** (serial lane). Queue asset jobs early, then *keep writing code while they run* — check with `./mb jobs` / `./mb log -f`. Never spam retries on `queued`. - First run of an operator may download weights (10–30 min). Be patient; don't cancel. - Don't delete assets you didn't create. `./mb rm-asset` your own intermediates when done. ### Art direction & asset manifest Pick ONE style token and use it in every prompt for coherence. Recommended: **"chunky stylized claymation kitchen, soft matte plastic look, warm colors"** — chunky geometry hides image→3D artifacts, reads well at game scale, and gives cutlery thicker (physics-friendlier) forms. Generate (3D via the pipeline above, one flux seed noted per asset so it's re-runnable): | Asset | Notes | |---|---| | Bread slices ×4: white, thick-cut sourdough, multigrain, raisin | These are the paint canvases — need a clear flat top face. If Hunyuan's top-face UVs are unusable for painting, **fallback: procedural slice** (rounded-box extrusion in Three.js) with a flux-generated bread-crust texture — the paint tech matters more than the mesh source. | | Toaster (2-slot, retro) | Hero prop of the toast scene | | Cutlery: butter knife, dinner knife, steak knife, spreader; dinner fork, dessert fork; teaspoon, dessert spoon, soup spoon | The "similar but not identical" cast. If thin tines/blades come out mangled from image→3D, **model cutlery procedurally** (extruded 2D profiles) — silhouettes must be hand-controlled anyway for fair gameplay. Decide after one test generation. | | Butter dish, peanut-butter jar, vegemite jar (fictional brand: "MITEY") | Bench props / selection UI | | Plate, kitchen bench surface | Bench = one big flux texture on a plane is fine | | Judge portraits ×5 expressions (neutral, intrigued, impressed, disappointed, horrified) | 2D, flux + bg_remove. Same character every time: describe them exactly, fix the seed, vary only the expression phrase. A stern older health-inspector type with a clipboard works. | | Title art, order-ticket paper texture, UI icons | 2D | **Normalize every GLB on load in code** (bounding-box → unit scale, recenter pivot) — don't hand-fix meshes. ## 4. Game design spec ### 4.1 Toasting - Browning is a **2D scalar field** (~64×64) per slice face, advanced each tick by heat input; render it by compositing into the slice's diffuse texture (white → golden → brown → black, with char speckle past 0.85). - Heat input = toaster power dial (1–10) × coil proximity map (hotspots near coil lines, cooler edges, slight random per-run bias so no two runs identical). - Per-bread params: `thickness` (thermal lag), `moisture` (delays browning then accelerates — sourdough), `sugar` (raisin browns fast and burns faster). - Player controls: power dial + lever down; **no timer readout** — you judge by smell cues (text wisps: "smells warm… toasty… SMOKY") and can pop early anytime. Popping early and re-toasting is allowed but re-toasting browns unevenly (field already has gradient). ### 4.2 Spreading & scraping — the star mechanic - Knife follows the mouse over the slice's top face (raycast → UV → paint into spread field, a second 2D field with `amount` per texel). - **Scroll wheel = knife angle.** Flat (low angle) = wide contact, gentle pressure, spreads. Steep = narrow contact, high pressure: scrapes spread *off* — or drags burnt char off (reduces browning field where >0.85, spawns crumb particles). Too steep + too fast on clean bread = **gouge** (permanent damage decal, integrity penalty). One unified control, three behaviors. - Dip into the butter/jar to load the knife (visible blob on blade, depletes as you spread). - **Spread rheology** per type: `{ yieldPressure, viscosity, pickupAmount, tempSoftening }` - **Butter**: high yieldPressure when cold — below it the butter doesn't spread, it *tears the bread* (drags the surface, integrity damage). `effectiveHardness = f(butterTemp, toastWarmth)`; toast warmth decays in real time (drawer dawdling matters). Soft butter = dream mode. - **Peanut butter**: high viscosity, big pickup — goes on thick, hard to get even, drags. - **Vegemite**: low viscosity, tiny correct dose — the skill is spreading then **scraping most of it back off**. Judge wants a translucent film; opaque = massive penalty ("This is a hate crime"). - Wrong tool from the drawer applies modifiers: spoon = blotchy coverage, fork = tears, steak knife = gouge-prone. ### 4.3 The drawer - Rapier scene: drawer box, 10–14 cutlery pieces spawned tangled (drop-settle at load, cached). Order card shows a **silhouette** of the required item. - Mouse grabs via spring joint (raycast to nearest piece, joint to grab point); pieces clatter and snag realistically. Lift the right item fully clear of the drawer rim to win. - Timer = your toast cooling. Grabbing the *wrong* item and committing (button) lets you proceed with the wrong-tool modifier — sometimes the smart play. - **Colliders: hand-authored compound primitives** (capsules/boxes) per archetype, NOT trimesh — stability and speed. Visual mesh can be the generated GLB. - Start with 8 pieces; only raise the count once tangling feels good. - Metal-on-metal clatter sounds are non-negotiable for feel (see §4.5). ### 4.4 Judging Score 0–10, itemized so the player sees exactly why: | Criterion | Measures | |---|---| | Browning match | mean browning vs. order target | | Evenness | browning field variance | | Coverage | % of face with spread in the target thickness band | | Uniformity | spread field variance | | Char | texels >0.85 remaining (scraping fixed it? no penalty) | | Integrity | gouges, tears, over-scrape | | Order compliance | right spread, right amount class (thin/normal/thick) | | Time bonus | small — never dominant | Judge delivers 1–2 dry lines keyed to the worst and best criterion (write a bank of ~40; e.g. "The coverage is admirable. The crater is not."). Show the toast rotating on a pedestal with a heatmap toggle. Grade stamp (S/A/B/C/F). **This screen is the game — make it excellent.** ### 4.5 Sound & feel - Web Audio, synthesized where possible: toaster tick, lever clunk, pop (with slice launch physics!), knife scrape (pitch ∝ pressure), butter-tear rip, cutlery clatter (Rapier collision events → filtered noise bursts, velocity-scaled), judge stamp thunk. - Screen-shake on pop, crumb particles on scrape, steam wisps off warm toast. ## 5. Milestones (commit + push each; verify in browser before moving on) - **M0 — Scaffold**: Vite+TS+Three+Rapier boots, launch.json, placeholder cube scene, pushed. *Also: fire off the first MODELBEAST asset jobs now so weights download while you build M1.* - **M1 — Toasting**: procedural slice + browning field + toaster controls + pop. Playable: make toast of any darkness. - **M2 — Spreading**: knife, angle control, butter + vegemite + PB rheology, scraping, gouges. This milestone is where the fun lives — iterate until dragging cold butter genuinely feels bad in a funny way. - **M3 — Judging**: full rubric, judge lines, grade screen, "next order" loop with 5 handwritten orders. - **M4 — Drawer**: physics drawer with 8 pieces, silhouette orders, spring grab, toast-cooling link, wrong-tool modifiers. - **M5 — Content & escalation**: 4 breads, order generator with difficulty curve (day 1: butter on white → day 7: thin vegemite on warm crumpet-thick sourdough with a steak knife because the drawer's a mess), persistent day/score. - **M6 — Art & polish pass**: swap placeholders for generated assets, judge portraits, title screen, sound polish, perf check (60fps with drawer active). At each milestone: run it, screenshot it, check the console is clean, then commit. If a milestone's feel is wrong, fixing feel beats advancing. ## 6. Judgment calls you're pre-authorized to make - Procedural vs. generated meshes per asset (test generation first, choose per §3 fallbacks). - Any tuning of the rheology/browning constants — the spec's numbers are starting points. - Cutting scope inside a milestone to protect feel (e.g., 2 spreads that feel great > 3 that don't). - Do **not** add paid/cloud dependencies, accounts, or external services. Do not touch anything in `~/Documents/MODELBEAST` except via the `mb` CLI as documented.