[render] round 5 NOTES

The colorspace finding written up with measurements; the relic's two-zoom
contrast numbers; the 63.7s frame-delta bug.

Includes the B8 picking investigation: 27.6% of the viewport cannot be clicked,
and #screen — a purely decorative overlay in index.html — accounts for 6.9% of
it because it takes pointer events while #ui correctly does not. That is the
review's "unclickable machines". One-line fix, but index.html is not my file.

Two contract requests (a renderer inspect channel, the #screen fix) and a
renewed proposal for a worktree per lane: other lanes saving files triggered a
Vite reload every 5-15s and wiped probes mid-measurement, so this round had to
be verified against an isolated snapshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-18 14:09:20 +10:00
parent a89525ecbf
commit c441ec3a53

View File

@ -524,3 +524,144 @@ doc does. Read it there rather than from round 3.
*relief* inside a cooler's rectangle once SIM lands spatial cooling; bloom-loop belt *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 tell; HF dust piles; wildlife; save/load camera state; LOD/culling if a megabase ever
drags the frame. drags the frame.
### Round 5 (MEGA) — 2026-07-18 — Opus 4.8
**THE HEADLINE: "the game about place has no place" was a COLOR-MANAGEMENT BUG, not a
missing feature.** I wrote the whole floor — fbm terrain, era hinting, seam glints — ran
it, and the screen was still black. The shader was fine. `THREE.Color.setHex()` converts
sRGB → the linear working space, but a raw `ShaderMaterial` gets none of the renderer's
output includes, so the linear value went to the framebuffer untouched. Measured, not
guessed: crust authored `#0c0a15` (RGB 12,10,21) was rendering as **RGB (1,1,2)**; even a
mid-grey `#2a2440` came out (6,5,13). Everything this lane has drawn with a raw shader has
been ~6× too dark **since round 1** — the grid, the crust, all of it. One
`#include <colorspace_fragment>` in `ground.ts` and the floor measures (10,8,18) against
an authored (12,10,21). The void was never a design problem; it was a missing include.
That's why the "before/after" is so stark, and it's the single most valuable thing I found
this round.
**SHIPPED** — all 8 orders.
*Part A*
1. **Inspect highlight** — selection ring + cooler aura on `{mode:'inspect'}`. Verified:
inspecting a 2×2 extractor rings it at its centre with scale 2.5; inspecting the
asic-cooler shows ring **and** its 6×6 coverage rect. This closes the
"placed-and-selected" case round 4 couldn't reach.
2. **Wildlife** (`wildlife.ts`) — dust piles as HF-dust glitter heaps scaling with `size`;
mosquito swarms as pixel-gnat clouds orbiting `target`, with the harassed machine
stuttering (§8: wrongness of motion is a faction uniform). Two draw calls for the whole
ecosystem.
3. **Fixture hygiene** — devscene now fabricates `commissionQueue`, `research`,
`wildlife` and `relics`, plus an asic-cooler and archaeology-lab so the v4/v5 kinds are
reachable in the scaffold.
*Part B*
4. **THE FLOOR** (`ground.ts`, `seams.ts`) — fbm tone mottle + neutral rim + 8 data-driven
seam regions that skin the crust with their era and glint with their ore.
5. **THE RELIC** (`relics.ts`) — unfound = a breathing static patch; found = a fossil on a
plinth. Numbers below.
6. **JUICE** (`juice.ts`) — placement scale-pop + dust puff, demolition burst, shipment
flash. All derived from snapshot deltas, since `render()` never sees events.
7. **THE BREAK ROOM** (`breakroom.ts`) — GLYTCH arcade cabinet, own raycast, `cursor:
pointer` on hover, click → `window.open('./match.html')` **verified firing**.
8. **CAMERA + CLICKS** — default framing lifts world origin to screen y=264, clear of the
build bar at y=679. Picking investigation below — it found more than expected.
**VERIFIED (numbers)**
- **Relic is subtle-but-findable, measured at two zooms.** Brightest pixel on the relic vs
plain floor 7 tiles away: at wandering zoom (12) **+39** — findable. At overview zoom
(30) **18** — i.e. indistinguishable from floor mottle. You cannot spot it from above;
you have to be down there looking. That's the Mario-hidden-pipe budget, in numbers.
- **Perf holds with everything on**: 500 entities + 2,000 belt items + 50 piles + 198
gnats + 8 seam regions + the new floor = **4.4ms/frame**, 3.8× headroom, 8 instanced
draw calls. (R1 3.2 / R2 3.6 / R3 3.3 / R4 3.6 / R5 4.4.)
- **Juice**: puff → 14 particles decaying over ~0.67s; burst → 22; shipment flash fired 22
times tinted `#ff7a3f`, exactly MELT's authored colour — so the flash reads which item
shipped, not just that something did.
- Prod bundle: `devscene`/`showroom`/`plinth`/`window.__render` all 0 hits; the round-5
shipping code (seams, aura, relics, breakroom) present. 446 tests pass, tsc clean.
**DECISIONS**
- **Dropped my own era-rim guess when DATA contradicted it.** The orders asked for strata
whispers toward the world edges and I built exactly that — sepia north, phosphor east.
Then `data/seams.json` landed mid-round, its doc saying "RENDER: `era` skins the ground",
with reel in BOTH the north-west and north-east and disc both north-centre and
south-west. My directional guess would have contradicted the data on screen, so era is
now skinned per seam region with a wide soft falloff. It still reads as strata whispers
toward the rim — the richest seams live out there anyway.
- **Seam glint is flecks, not veins.** First pass drew continuous sinusoidal veins; on
screen they were bright green worms crawling over the floor, competing with the belts.
Mineral glitter is sparse and twinkles, so it's now a fleck grid with per-fleck sparkle
clocks. The body fade is deliberately SHORT (0.8 tiles): SIM extracts on any
footprint/rect overlap, and a glint dying two tiles inside the boundary would
under-report where mining actually works.
- **The cooler aura stays a rectangle** (round 4's reasoning) and the relic monument, the
cabinet and the seams all now carry `colorspace_fragment` for the same reason the ground
does.
- **Cabinet is rotated 45°** to face the iso camera and sized to its own marquee — at the
rig's closest zoom a 0.03-unit marquee pixel was sub-pixel and GLYTCH was a smudge.
**BLOCKED/BROKEN**
- **A frame-delta of 63.7 SECONDS was silently eating all juice.** `clock.getDelta()`
returns the real gap, and a backgrounded tab / alt-tab / GC pause / first frame after
load hands back seconds. Particles have a 0.5s TTL, so every effect was born and killed
inside one update — and a 63s integration step flings them to infinity. `render()` now
clamps dt to 0.05 (main.ts clamps the sim accumulator for the same reason; this is the
renderer's half). This also protects the scale-pop, camera pan and heat animation.
- **`match.html` only exists in `dist/`** (deploy.sh copies it there). In a dev server the
cabinet's click opens a 404. Not fixable from this lane — `public/` is mine but the file
is the deploy's. Flagged so nobody reports it as a cabinet bug.
- The devscene relic sits at (9,-7), which is NOT inside DATA's `relicReserve`
(12,12,20,20). That's fine for a fixture, but SIM's real relic should land in the
reserve — worth a check when SIM lands `relics`.
- The cabinet is decorative and reserves no tiles, so a player can place a machine
"inside" it. Cosmetic only.
**B8 PICKING INVESTIGATION — 27.6% of the viewport cannot be clicked**
I probed a 20px grid over the whole viewport (2,205 points) asking "does a click here
reach the game canvas?". 609 points — **27.6%** — do not. Breakdown:
| blocker | points | note |
|---|---|---|
| `#screen` | 153 (6.9%) | **decorative overlay, `pointer-events: auto`** |
| `#fk-build` + hint | 155 (7.0%) | build bar — legitimately interactive |
| `#fk-fax` + flavor | 90 (4.1%) | fax panel — legitimately interactive |
| `#fk-top` | 36 (1.6%) | bandwidth panel — legitimately interactive |
The one that is a **bug**: `#screen` is THE SCREEN's canvas in `index.html`, purely
decorative, 322×182 at top-centre, `z-index: 5`, and it takes pointer events. `#ui` next to
it correctly sets `pointer-events: none`. So a 6.9% rectangle of prime play area silently
swallows clicks — I hit it myself: the cabinet at (-5,-5) rendered *underneath* it and was
both invisible and unclickable, which is exactly the review's "machines spawned
unclickable". **Fix is one line in `index.html` (orchestrator-owned): add
`pointer-events: none` to `#screen`.** I moved the cabinet to (6,12) as a workaround, but
the dead zone is still there for machines.
Also seen: `#fk-screenview` (LANE-UI's theatre mode) is a full-viewport `pointer-events:
auto` host. Correctly `display:none` when closed — not a bug, noting it so the next person
who probes picking isn't confused by it the way I was.
**CONTRACT REQUEST**
1. **A renderer inspect channel.** `Renderer.setGhost`'s mode is only `build|remove` and
main.ts passes `'build'` during inspect, so nothing about the inspected entity reaches
this lane. `SelectionState` carries it, so I read `window.__fktryBus.selection()` each
frame as a bridge — same shape as the old `'__remove'` sentinel, documented on both
sides, and it wants a real hook: either widen `setGhost`'s mode to include `'inspect'`
with the entity id, or add `Renderer.setInspect(id | null)` that main.ts calls.
2. **`pointer-events: none` on `#screen`** in `index.html` (see above). Not my file.
3. Advisory: SIM doesn't gate extraction to seam rects yet, so the glint is currently a
cosmetic tell rather than a rule. The moment SIM lands the overlap check the floor
already teaches it — no renderer work needed.
**PROPOSAL — the shared tree cost me real time again.** Verification kept failing because
LANE-UI and LANE-SIM save `src/ui/*.ts` / `src/sim/*.ts` every few seconds and Vite
full-reloads my page, wiping every probe mid-measurement (the vite log shows a reload every
515s for minutes). I finished the round by snapshotting the repo to a scratch dir and
running an isolated dev server against it. That works, but it's a workaround for the same
root cause as round 3's commit collision: **one working tree, five writers.** A worktree
per lane fixes both.
**NEXT (round 6 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; relic excavation VFX on the
`relicFound` event; bloom-loop belt tell; save/load camera state; LOD/culling if a
megabase ever drags the frame.