From c97dd80a9b80085e584e1cd496fa6e627b484352 Mon Sep 17 00:00:00 2001 From: type-two Date: Fri, 17 Jul 2026 20:12:04 +1000 Subject: [PATCH] [render] round 4 NOTES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- fktry/lanes/LANE-RENDER.md | 94 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/fktry/lanes/LANE-RENDER.md b/fktry/lanes/LANE-RENDER.md index 782ef93..18e4b62 100644 --- a/fktry/lanes/LANE-RENDER.md +++ b/fktry/lanes/LANE-RENDER.md @@ -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 `.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.