6f74d31469
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6f74d31469 |
Kitchen panel no longer leaks over station scenes
It was born visible — a day starting at a station (prep/juice/grate) never passes through kitchen.enter()/exit(), so the BROWNING panel sat over every station HUD. Hidden at construction like every other scene; verified hidden at bench, shown after handoff, hidden at juice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
31f2eff28e |
M10 WIP + Build Brief 2: the bakery is code-complete, the prep bench is specced
M10 (code-complete, verification pending — see OPUS-BUILD-BRIEF-2.md §2):
- Brands with mechanical quality (WONDERSLICE 0.25 vs Crustworthy 0.8 etc.):
quality scales heat-map patchiness and crumb fragility. Bakery sourdough is
loaf-only.
- Slicing minigame: aim thickness, saw with vertical strokes; progress/wobble/
squash; wedge slices brown unevenly in the toaster (the bad cut follows you);
squash arrives as pre-existing damage.
- Bread Knife + THE BEST THING (heavy, soft-scalloped, saw eff 1.65) join the
drawer; on loaf days the drawer trip happens BEFORE toasting ("they are
waiting") and whatever you fish out is what you slice with.
- Day 9 handwritten (the inspector wants a doorstop with parallel faces),
procedural brands/loaf days from day 10, The Cut criterion (band + wedge +
squash, TBT signature bonus), cut line bank.
- Verified so far: day-9 ticket chips, knife-trip drawer with bread_knife AND
the_best_thing present, timer label, typecheck + build. Slicer end-to-end
play, tuning, and couplings assertions are itemised in the brief.
OPUS-BUILD-BRIEF-2.md — the prep bench: generalized ingredients + cutting
(slip, juice, piece-evenness CV), the judged mess field, oranges + ribbed
pyramid juicer (halve evenness caps yield, seeds by juicer tier, the
Juicernaut), the grater (zest/pith line, cheese needs cold, knuckles), onions
(sting that blurs REAL vision, the stop-short-of-the-stem criss-cross dice),
and bruschetta as the capstone (temperature planning, roast tomatoes on the
browning field, topping Clark-Evans, the sog clock vs doorstop slices).
Bakery asset batch partially failed (flux errors + one lost GLB) — regen
instructions with retries are in the brief §8.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
16860cf5d6 |
M9: the fresh-eyes pass — played it cold, fixed what a stranger hits
Sat down with it like someone who'd never seen it. Five findings, all reproduced before fixing, all verified after: 1. The kitchen panel was a cheat console. BREAD/SPREAD/TOOL/BUTTER are the order's facts, but the widgets stayed live — you could fetch a soup spoon and then quietly re-select the butter knife. Locked during play; the browning dial stays yours because it's a real control. 2. The drawer card printed the ANSWER under the silhouette. The entire "similar but not identical" puzzle, solved by a caption. The name is gone; after ten seconds of fumbling it fades in as a pity: "fine. it's the butter knife." 3. Lifting anything above the rim committed it instantly — but fishing means lifting blockers, so you could accidentally "choose" whatever you were moving aside. Commit now needs 0.45s of continuous hold above the rim, which doubles as a beat to compare what you're holding against the silhouette. Verified: a wobbly lift takes ~0.95s because dipping below the rim resets the clock, and that's correct. 4. Coverage scored 20% on a slice a player had visibly covered corner to corner. Root cause: the "covered" floor scaled with the ASKED amount, so Coverage and Amount both punished thinness — double jeopardy. Coverage now asks its own question (are there bare patches? floor = 0.06 absolute) and the same conscientious play scores 84%. 5. Nothing told you how much was on the toast until the verdict. New live readout, computed by the judge's own functions: "on the toast: thin — normal asked · 84% covered". Watching it, a played-well day 1 went 8.8 -> 9.0, and the missing 0.2 is named on the card (stripes), not hidden. Also: the drawer holds 11 pieces dropped down a tighter column (a heap you rummage in, not an exploded diagram — padded with extra teaspoons, like every real drawer), it sits on a bench instead of floating in a void, Service is sim-time rather than wall-clock, and the title mentions the drawer exists. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ff006e65db |
M8: crunchy vs smooth, and the jar that separates
Natural peanut butter stratifies while it sits. The jar carries the state:
strat 0..1, set per order (smooth 0.75, crunchy 0.9 — chunks sink). The first
unstirred dip takes the oil slick off the top; the ones after it dig into what
the oil left behind. Verified dip trace, no stirring: 0.875, 0.669, 0.462,
0.256. Swirl the knife in the jar (~2.5 circles of angular sweep; holding still
stirs nothing) and every dip is 0.5. Stirring costs time, and time costs toast
warmth — the mechanic pays the same tax as everything else.
Consistency pushes back through the physics that already exist: an oily load
multiplies the yield down (glides at any angle, goes on thin), a dry one
multiplies it up (fights like cold butter, tears). The shader shows it — slick
is dark and shiny, grout is pale and matte.
The judge reads what LANDED, not what the jar was: every deposit remembers the
oil it landed at, and the criterion scores the mass-weighted mean AND stdev.
The stdev is the design catch, found by verification: a slick strip and a grout
strip average to 0.54 — "just right" — and the first cut scored the lazy play
as if the jar had been stirred. Nobody eats the average:
never stirred, strips oil 0.54 ±0.23 "slick here, grout there" C
one slick dip, whole oil 0.87 ±0.00 "a slick"
stirred first oil 0.50 ±0.00 "just right"
Crunchy reuses the particle system wholesale — chunks ride the knife, shed per
stroke-distance, get judged with the same Clark–Evans index ("Peanut chunks —
21 bits, evenly strewn (R 1.20)"), and the rind line bank is genericised via a
{bits} placeholder so he complains correctly about either.
Day 6 is crunchy now ("the PROPER kind"), the ticket warns when a jar has been
sitting, and the JAR bar shows how mixed it is. Five new judge lines, including
"You did not stir the jar. The jar knows. I know."
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
1ba66f0cdf |
M4: the cutlery drawer — and the link that makes it matter
toast -> drawer -> spread. Eight pieces settle into a real tangle; find the one
on the card, drag it up and over the rim, and whatever you're holding is what
you're spreading with.
The link, verified end to end (day 4, butter softness 0.3):
4s in the drawer warmth 0.78 yield 0.343 needs angle 0.36 comfortable
50s in the drawer warmth 0.17 yield 0.565 needs angle 0.60 cliff is 0.62
Dawdling walks you to within two hundredths of the scrape cliff. On day 7
(fridge-hard butter) it tips over into genuinely unspreadable. The drawer isn't
a timer bolted on the side — it's the thing that makes the butter hard.
Physics choices that earn their keep:
- Compound boxes, never trimeshes. A trimesh fork tangled in a trimesh fork is
a solver nightmare and slow with it; the tine envelope is what matters anyway.
- Grab is a capped PD spring, not a fixed joint, so a snagged piece fights the
ones lying on it and loses instead of tunnelling through them.
- The solver is fixed-stepped so a frame hitch can't detonate the pile, and the
drawer settles offline so you open it on an existing mess.
- Clatter is synthesised from real contact-force events, velocity-scaled — a
drawer of cutlery is a noise, and the noise has to come from the collisions.
Three fixes:
- Quaternion.toArray() returns [x,y,z,w]; Rapier wants {x,y,z,w}. Every axis
read back undefined -> NaN in the solver -> wasm panic on the first step.
- The drag plane faced the camera, but the camera looks down into the drawer, so
dragging to the top of the screen couldn't physically lift anything over the
rim. It's a vertical plane now: up-screen means up.
- Cooling lived in kitchen.update(), which stops running the moment the drawer
opens — so the toast stayed hot no matter how long you rummaged, quietly
cancelling the entire mechanic. It's an app-level tick now.
The drawer was 4.6x3.4 and the pieces politely spread out flat. Tangling needs
crowding: 3.1x2.2, dropped down a narrow column so they land on each other.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
b07d57e9e9 |
M3: judging — the scorecard, the judge, and a colour-space bug
The loop closes: ticket -> toast -> spread -> ENTER -> verdict -> next day.
- judging.ts: 9 weighted criteria, each reading the same fields the knife was
pushing around, so every line of the scorecard points at something real
("0.78 against 0.68 asked", "thick — thin asked", "28% burnt").
- lines.ts: ~45 lines keyed to whichever criterion actually decided the score,
so the verdict and the scorecard always agree — the verdict just has feelings
about it. MITEY has its own vocabulary.
- judge.ts: the toast turns on a pedestal under a spotlight, grade stamps in,
heatmap toggle for browning/spread. The generated inspector reacts by grade.
- orders.ts: seven handwritten days, then procedural. Day 1 is soft butter on
white; day 7 is a translucent film of MITEY on wet sourdough with fridge-hard
butter and a steak knife.
The find: every art colour was authored as sRGB and fed straight into a linear
lighting pipeline. Linear 0.14 encodes back out to sRGB ~0.4, so "near-black"
MITEY rendered as TAN and saturated butter washed to pale cream. This was the
root cause of the legibility fights in M0 and M2 — I'd been treating the symptom
by pushing the specular around. One line (albedo = pow(albedo, 2.2), mixing
stays in sRGB because that's the space the palette was picked in) and the whole
art direction landed: MITEY is genuinely black, butter is butter, the crust went
from cream to a rich golden brown.
Also: the specular lobe was far too broad. The slice is flat with the light and
camera both above it, so dot(N,H) ~0.98 everywhere and a wide lobe blankets the
whole slice in white. Tightened, so only ridges tilted into the light catch —
which is what a spread actually looks like.
The slice rolls its own lighting and ignores scene lights, so the judge's
spotlight did nothing to it; it now swaps its own rig for presentation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
eb74170011 |
M2: spreading — one control, three behaviours
Knife angle (wheel) is the only input, and spread/scrape/gouge all fall out of it.
Verified by driving real input through the real code paths:
cold toast + fridge butter -> damage 0.015, spread 0.029 (tears, as designed)
fresh warm toast -> damage 0, spread 0.117 (flows cleanly)
burnt toast, knife on edge -> char 99.9% -> 82.7% -> 54.5%
evenness 0.029 -> 0.123 -> 0.226
pale toast, knife on edge -> gouges; steak knife gouges 3.2x harder
That evenness column is the mechanic: scraping rescues you from char and wrecks
uniformity doing it. The judge will have opinions.
The trap is calibrated, not hoped for. Pressure comes from steepness, but past
SCRAPE_ANGLE the knife stops spreading:
fridge butter / cold toast yield 0.72 needs angle 0.75 IMPOSSIBLE
bench butter / cold toast yield 0.54 needs angle 0.57 (cliff at 0.62)
fridge butter / fresh toast yield 0.36 needs angle 0.38 fine
soft butter / fresh toast yield 0.16 needs angle 0.12 dream mode
So cold toast + hard butter cannot be spread at any angle, and the way out isn't
technique — it's not dawdling. The pressure gauge draws both marks so you can
see the gold sitting past the red and understand why you're losing.
Emergent and kept: a steak knife's narrow blade concentrates pressure enough to
beat cold butter's yield. It's the right tool for cold butter and a menace
everywhere else.
- cutlery.ts: 9 hand-authored archetypes (silhouettes are gameplay — the drawer
has to be fair) + compound box colliders for M4.
- dev.ts: harness that drives real gestures deterministically. Earns its keep.
Two bugs: cutlery meshes used mesh.rotation.x = -PI/2, which sends a profile
drawn toward +y to -z and one drawn toward -y to +z — the handle and blade were
laid out in opposite directions, overlapping, nowhere near the cursor. Now
rotated at the geometry level. And resize() computed aspect = 0/0 = NaN when the
container reports zero, which poisons the projection matrix so every raycast
silently misses — i.e. the entire mechanic stops with no error.
Metals need something to reflect: added a RoomEnvironment IBL and rebalanced the
direct rig, which was tuned before it existed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
67cfe56bb9 |
M1: toasting — browning sim, toaster, lever, and the pop
Playable: pick a bread, set the dial, drop the lever, watch it brown, pop it onto the plate. No timer readout — you go by smell. - toasting.ts: heat map from real toaster behaviour (element stripes, cool top edge where the slice stands proud of the slot, edge falloff, per-run noise bias). Moisture must boil off before the crust browns at full rate, so sourdough stalls then catches up; sugar browns and burns early. Rate is measured against the heat map's actual ~0.77 mean, not guessed: power 6 -> golden 0.511 at 10s, verified in-browser. - Props on a real scale (1 unit ~ 11cm, one slice wide) — the toaster is meant to dwarf the bread. - The pop solves a genuine ballistic arc from slot to plate. Three bugs found by driving it rather than trusting the compile: - valueNoise2D read one past its grid at x=w-1, so heatBias was NaN along an edge, which poisoned mean browning to NaN — i.e. every judge score would have been NaN. Clamped. - erode() clamped at the field border, so border texels could never erode out of the mask and kept those NaNs in scope. Off-grid now counts as outside. - Timer.connect(document) zeroes dt whenever document.hidden is true, which froze the sim solid in an embedded browser. Dropped; rAF already pauses for hidden tabs. App.step(dt) is now exposed so the game can be driven deterministically for verification. Also: screen shake was mutating the camera permanently instead of offsetting it per-render, and the plate's lathe profile touched the axis (degenerate triangles -> starburst normals) — rebuilt from primitives. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |