feat: boards load before you ask for them
The owner asked for one map, with detail arriving in the background rather than
behind a wait. The interface already said one place (4bd8481: one ladder, no tab
strip, no boot card). This is the world catching up: on a desktop both metros are
now resident within seconds of landing, and the switch that used to be a build
becomes a fog dip over a cache hit.
**Measured, three runs each, California -> The Bay after an 8 s dwell:**
the longest blocking task falls from **521 ms to 58 ms** (before 700/501/521,
after 58/58/61) and long tasks from 2 to 1.
**And the cost, stated rather than omitted.** Over ten seconds sitting on the
state board: 601 frames -> ~571, p95 frame interval 18.0 -> 18.7 ms, and **one
long task of ~500 ms that did not exist before**. The build is not chunked yet,
so this moves a freeze from the moment of interaction to a moment nobody asked
for. That is a real trade and the follow-on that removes it is chunking the
build. `PREFETCH_ENABLED` in main.ts turns the whole lane off in one line.
A parked board draws nothing: 371 draws per frame before the lane lands a board
and 371 after, patched at the GL entry points. The performance budget reproduces
every cell to the digit.
**Three defects found on the way, two of them latent for a while.**
1. `environmentRig` had no idea what off-stage meant. `createScene` calls
`apply()` unconditionally, two hundred lines above the `present` check, and
the rig holds one probe per kind: on a key miss it convolves a new one,
disposes the one the visible board is using, and repoints every applied scene
at the replacement. A board built ahead of the camera is observed at its own
centre — about forty minutes of apparent solar time across the state — so its
key differs by construction. The board on screen would have changed colour
because something invisible finished loading. Harmless until today only
because every build was followed within ~800 ms by the swap that presented it.
Fixed with `ApplyOptions.offstage`; the regression test was written first and
failed first.
2. `mounting` was assigned and never cleared. Harmless while the only reader was
the next `mountCity` wanting something to abort. It stopped being harmless the
moment a second lane asked "is a foreground build in flight?", because the
honest answer after the first mount of the session was permanently yes — the
background lane armed exactly never, and the only symptom was a feature that
silently did nothing. Found by measuring, not by reading.
3. `buildBoard`'s `onProgress` ends in `bootProgress`, which raises the switch
pill. A prefetch would have put "Building The Bay Area... terrain 42%" over a
visitor who did nothing — the exact chrome that removing the tab strip was
for. `quiet` closes it.
**The policy is pure and lives with the eviction policy it has to agree with.**
`prefetchTarget` and `canAdmit` in boards.ts take scalars, never a camera, so
boards.ts keeps CONTRACT section 1's no-DOM/no-WebGL/no-three promise and
prefetchPolicy.test.ts can assert against the real pack bounds. Two regimes,
because collapsing them was the first version's mistake: with free room the gate
is simply "is there a slot", since the common path is to land on the state at
1,551 km and click a metro, and on that path a proximity trigger fires never;
with the cache full — the handheld case, capacity two with California pinned —
proximity is the only thing that justifies an eviction. The discs are asserted
non-overlapping against the shipped bounds (92 + 146 km of reach across a 314 km
gap), which is the covering-set argument residentCapacity already rests on.
**Also fixed, and separately load-bearing: reconcile's flag parser lied.** It
prefix-matched, so `?reconcile=palette` selected nothing and produced an empty
set — indistinguishable from the flag being absent. Every photograph taken to
judge a rule could have been a photograph of the unreconciled board with no way
to tell. Exact names now, with a warning that says "the flag is NOT off".
And two consumers were reading the raw packs beside a reconciled World:
`buildLadder` derives every rung's stand-off from `focus`, and `createMinimap`
was handed `entry.city` next to `handle.world`. Both now read `world.city`.
Latent with the flag off — `reconciledCity` returns by identity — which is what
kept it alive: it corrupts the measurement rather than announcing itself.
**What I did NOT ship, having tried it.** `roads` on by default. The rule exists
to stop California drawing 1,919 m freeways, and `city.roads` is not what draws
them: California is the one board with `roadTraffic`, so `scene.ts:816` takes the
`createFreewayWorld` branch and `createRoads` — the only reader of `Road.width` —
is never called for it. The visible corridor is a deliberate atlas glyph sized so
DRIVE mode can drive down it. Photographed at three chapters the rule moved
Downtown LA not at all (empty diff bbox), FiDi by RMSE 0.0006, California by
0.001% of pixels; the only measurable effect anywhere was -112 triangles on
Southern California. See DEFAULT_RULES for the whole argument.
1,688 + 295 tests, every gate, chapter-identity OK against the unmodified
fixture, ui-smoke PASS, budget PASS with private-request checks clean on all ten
cells.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+44
-4
@@ -806,9 +806,31 @@ export async function createScene(
|
||||
// two disagree for the one frame before the app's first `setLighting`.
|
||||
const opening = options.lighting ?? cityDaylight(pal, boardSpan);
|
||||
kit.applyLighting(opening);
|
||||
// The environment before the first layer is added, so the very first frame
|
||||
// has a sky to reflect rather than acquiring one a `setLighting` later.
|
||||
options.environment?.apply(scene, opening, "city");
|
||||
/*
|
||||
* The environment before the first layer is added, so the very first frame has
|
||||
* a sky to reflect rather than acquiring one a `setLighting` later.
|
||||
*
|
||||
* `offstage` is the `present` flag, one line early. It has to be, because this
|
||||
* call is two hundred lines above the `if (options.present !== false)` that
|
||||
* decides whether anybody will ever look at this scene — and the rig holds one
|
||||
* probe per kind, disposes it on a key miss, and repoints every applied scene
|
||||
* at the replacement. A board built ahead of the camera is observed at its own
|
||||
* centre, so its key differs by construction, and without this a board loading
|
||||
* invisibly in the background would change the sky of the board on screen.
|
||||
* `onEnter` below applies it again, for real, when it is presented.
|
||||
*/
|
||||
/**
|
||||
* The lighting this scene was last told about, and whether anybody is looking.
|
||||
*
|
||||
* Both are held because the environment is applied from three places — here at
|
||||
* construction, from `setLighting` on every clock tick, and from `onEnter` on
|
||||
* arrival — and all three have to agree about the same two facts. A board that
|
||||
* is off screen must never rebuild the shared probe; a board that is on screen
|
||||
* must always be allowed to.
|
||||
*/
|
||||
let lighting = opening;
|
||||
let presented = options.present !== false;
|
||||
options.environment?.apply(scene, opening, "city", { offstage: !presented });
|
||||
|
||||
scene.add(createWater(world));
|
||||
scene.add(createShorePlates(world));
|
||||
@@ -1172,6 +1194,23 @@ export async function createScene(
|
||||
// stale detail card for something the pointer is nowhere near reads as a
|
||||
// bug.
|
||||
onExit: () => kit.resetPick(),
|
||||
/*
|
||||
* Claim the environment on arrival.
|
||||
*
|
||||
* A board built with `present: false` was applied `offstage`, which means it
|
||||
* borrowed whatever probe was cached rather than building its own — right
|
||||
* while it was invisible, wrong the moment it is not. This is the same call
|
||||
* every board already makes; on a cache hit it costs no convolution, which
|
||||
* is the case a prefetched board arriving at the same hour always hits.
|
||||
*
|
||||
* It runs on every entry, not only the first, and that is deliberate: a
|
||||
* board returned to after an office visit or another board has been off
|
||||
* screen while the clock moved, and re-asserting is how it catches up.
|
||||
*/
|
||||
onEnter: () => {
|
||||
presented = true;
|
||||
options.environment?.apply(scene, lighting, "city");
|
||||
},
|
||||
tick(dt) {
|
||||
// Exactly one subsystem owns the camera. In particular, OrbitControls
|
||||
// must stay disabled while the road layer writes its follow pose.
|
||||
@@ -1347,6 +1386,7 @@ export async function createScene(
|
||||
arrival = { from, to: rest, elapsed: 0 };
|
||||
},
|
||||
setLighting: (state) => {
|
||||
lighting = state;
|
||||
kit.applyLighting(state);
|
||||
clouds.setLighting(state);
|
||||
fireLayer?.setLighting(state);
|
||||
@@ -1364,7 +1404,7 @@ export async function createScene(
|
||||
* rig, the scene is applying it, and the environment is derived from the
|
||||
* decision rather than being a second opinion about the light.
|
||||
*/
|
||||
options.environment?.apply(scene, state, "city");
|
||||
options.environment?.apply(scene, state, "city", { offstage: !presented });
|
||||
},
|
||||
setAerialFog: ({ near, far }) => {
|
||||
// The three fog owners on a city board and no more. `ports`, `vessels`,
|
||||
|
||||
Reference in New Issue
Block a user