# 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="<object>, single object centered on plain light grey background, soft studio lighting, 3/4 view, stylized chunky game asset" -p seed=<n> --wait
# 2. cut it out (biggest quality lever for image→3D)
./mb run bg_remove_local --asset <IMG_ID> --wait
# 3. mesh it (GLB + PBR texture, ~4-5 min, no login needed)
./mb run hunyuan3d_mlx --asset <CUT_ID> -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 <ID> -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.
