[render] round 4 NOTES

Verification numbers; the lock-rule divergence with UI (they were right, I was
wrong — the scrammed lesson misapplied); the showroom overflow postmortem; one
contract request (an inspected-entity channel for placed-and-selected auras).

Notes that round 3's MODELBEAST manifest is stale — ?showroom is the live one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-17 20:12:04 +10:00
parent 5e8e49ef0e
commit c97dd80a9b

View File

@ -422,3 +422,97 @@ Cheapest real fixes, in order:
- Real MODELBEAST assets through `?showroom`; splitter lamp driven by real round-robin
state instead of a timer; bloom-loop belt tell; HF dust piles; wildlife; save/load
camera state; LOD/culling if a megabase ever drags the frame.
### Round 4 — 2026-07-17 — Opus 4.8
**SHIPPED** — all 4 orders + housekeeping, verified against LANE-DATA's real v4 data
(which landed mid-round: 29 machines, 60 items, `archaeology-lab`, `asic-cooler
coolRadius:2`, `accent` on 8 machines) and UI's real migrated flow.
1. **Ghost keys off `mode`.** The `'__remove'` sentinel is ignored — mode is the truth,
and the `REMOVE_DEF` constant is deleted from this lane. Verified through UI's own
REMOVE tab: `selection()``{mode:'remove'}`, demolition decal + wash on the mosh
reactor's whole 3×3.
2. **Locked-machine ghost.** Padlock-amber `#ffb02e` — deliberately not the occupied-red,
because "not yet" and "not here" are different sentences. A padlock floats above,
tinted by the era gating it. Verified: `telecine-puller` → amber ghost + `#d8a24a`
reel brass; `asic-cooler` → amber + `#5fd08a` broadcast phosphor.
- **Era tell needed its own palette.** `ERA_SKIN.tint` can't do this job: it's a
multiplier tuned to leave DATA's chassis alone (stream is literally `#ffffff`), so
three of five eras would have told you nothing. Added `ERA_TELL` — five hues chosen
to be told apart, used as signal rather than surface.
3. **Cooler auras.** Verified on `asic-cooler` (fp 2×2, coolRadius 2) → **6×6 tiles**,
centred on the ghost, dashed + tick-marked, no fill.
- **It's a rectangle, not a ring.** `coolRadius` is CHEBYSHEV from the footprint, so
the cooled region is the footprint grown by r on each side. A circle would have been
prettier and would have lied — the corners it left out are cooled, and players would
plan around a boundary that doesn't exist. Drawn in the geometry the sim measures in.
4. **Lab visuals.** `archaeology-lab` (kind `lab`, 3×3) renders as a bench + the "bottled
artifact triptych" (§2) — three out-of-phase pulsing bottles. Verified geometry
`Box,Cylinder,Cylinder,Cylinder` and **`accent` consumed from data**: bottles emissive
`#ffc24a`, exactly DATA's authored value.
5. **Housekeeping.** Splitter lamp left timer-driven as approved. Showroom absorbed the
new catalog — see the bug below.
**VERIFIED**
- Perf standing rule holds: 500 entities + 2,000 items at **3.6ms/frame**, 5 instanced
draw calls. (R1 3.2 / R2 3.6 / R3 3.3 / R4 3.6 — auras, padlocks and the locked path
cost nothing measurable.)
- Showroom absorbs 29 machines + 60 items, all five eras present, hall inside the world.
**DECISIONS**
- **Matched LANE-UI's lock rule rather than my own, and it was a real divergence.** My
first cut treated absent `research` as "nothing is locked" — don't lie when the field
isn't wired. UI's `research.ts` reads the same rule the opposite way: nothing has
completed, so everything gated shows its padlock. **UI is right and I was wrong**: this
is the `scrammed` lesson misapplied. There, the field's absence meant the sim hadn't
wired a *behaviour*; here the rule is satisfiable from data alone and the contract says
"until that tech completes". Left unresolved, the build bar would have padlocked a
machine while the ghost waved it through — on the same screen. Also matched their
first-tech-wins tie-break for ids unlocked by two techs: a data bug either way, but we
must both blame the same tech.
- **Buffer fill now reads `bandwidth.capacity`** instead of re-summing `bufferCap`
locally. v4 publishes the total; a second copy of the sim's arithmetic in this lane is
exactly what the scram latch taught us not to keep. Falls back to the local sum only
while the field is absent.
- **`MachineDef.accent` wins outright, no legibility floor** — same reasoning as
`def.color`: explicit art-direction is a decision; the floor exists for *derived*
colours, which are incidental.
**BLOCKED/BROKEN** — nothing blocking.
- **The showroom bug I predicted last round arrived, and my fix was half a fix.** Round 3
noted the item hall would overflow when the catalog grew. It did (51 → 60 items), but
the failure wasn't the one I expected: the *machine* hall grew to 5 rows, ate the depth
budget, collapsed the item grid to **one row of 60 columns — a 206-tile row across a
64-tile world**. My round-3 "adaptive" fit budgeted depth only. Now fitted to both axes,
and it `console.warn`s if the catalog ever exceeds the hall rather than silently
stacking items off-world. Lesson: an auto-fit that constrains one axis just moves the
overflow to the other one.
- **"Placed-and-selected" auras aren't reachable** (order 3's third case). `SelectionState`
is `build | remove | null` — UI's click-to-inspect selection has no contract channel, so
a placed cooler rings on **hover**, not on inspect. Hover covers the same intent for
now; see CONTRACT REQUEST 1.
- Two tests fail repo-wide (`sim/reference.test.ts`, `ui/live.test.ts`) — both SIM/UI
in-flight research work, neither imports `src/render`. tsc is clean repo-wide.
**CONTRACT REQUEST**
1. **An inspected-entity channel**, if you want order 3's "placed-and-selected" case for
real. Cheapest shape: extend `SelectionState` with `{ mode: 'inspect'; entity: number }`,
or add `UIBus.inspected?(): number | null`. Renderer has no other way to know what the
player clicked. Low priority — hover already answers "what does this cool?".
2. Nothing else. v4 granted round 3's `setGhostMode` ask (as `setGhost(..., mode)`) and it
landed clean; the sentinel bridge can die in v5 whenever you like — this lane no longer
reads it.
**NOTE FOR THE MODELBEAST ORDER** — the manifest in round 3's NOTES is now stale: DATA
added 6 machines (`roto-bench`, `matte-bath`, `optical-printer`, `chroma-keyer`,
`neural-keyer`, `archaeology-lab`) and the tech tree now gates 13 across all five eras.
`?showroom` is the live manifest — it labels every machine with its exact `<asset>.glb`
filename and era, and re-reads data on load, so it can't go stale the way a table in a
doc does. Read it there rather than from round 3.
**NEXT (round 5 candidates, not self-assigned)**
- Real MODELBEAST assets through `?showroom`; heat-shimmer suppression reading as
*relief* inside a cooler's rectangle once SIM lands spatial cooling; bloom-loop belt
tell; HF dust piles; wildlife; save/load camera state; LOD/culling if a megabase ever
drags the frame.