1
0

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:
2026-08-23 13:15:37 -07:00
parent 2ff11a385e
commit 85be0b13f8
9 changed files with 1239 additions and 31 deletions
+142
View File
@@ -353,3 +353,145 @@ test("the rig constructs no light of any kind", () => {
// hence matching the import statement rather than the word.)
assert.doesNotMatch(source, /^\s*import[^\n]*RoomEnvironment/m);
});
// ---- The prefetch hazard ---------------------------------------------------
/**
* A board being built off-stage must not relight the board on screen.
*
* ## The mechanism
*
* `createScene` calls `options.environment?.apply(scene, opening, "city")` at
* `scene.ts:811` — unconditionally, and two hundred lines above the
* `if (options.present !== false) stage.setScene(stageScene)` at `:1331` that
* decides whether anybody is going to look at this scene at all. `main.ts`
* builds one rig on one renderer for the life of the page, so an off-stage
* board and the visible one are the same rig.
*
* The rig caches exactly one PMREM target per kind, keyed on a fingerprint of
* the lighting. On a key **miss** it does three things, in this order: renders
* and convolves a new probe on the shared renderer, `dispose()`s the target the
* visible board is currently using, and then walks `applied` reassigning every
* scene of that kind to the new texture.
*
* That is correct and necessary when the miss comes from time passing. It is a
* defect when the miss comes from a board **nobody is looking at**: a board
* prefetched for another part of the state is observed at its own centre, which
* across California is about forty minutes of apparent solar time, so its sun
* direction — and therefore its key — *will* differ. The visible board's sky
* would change because something invisible was loaded behind it.
*
* It is harmless today only because every build is followed within about
* 800 ms by the swap that makes it the visible board. It stops being harmless
* the moment anything builds a board it does not intend to show.
*
* ## What this asserts
*
* The property, at the rig's own boundary: applying to a scene while telling the
* rig it is off-stage must not disturb any scene already applied. Written before
* the fix, and it failed before the fix, which is the only way to know a
* regression test is testing anything.
*/
test("an off-stage apply does not relight the scene already on screen", () => {
const fake = fakeRenderer();
const rig = createEnvironmentRig(fake.as());
const visible = new THREE.Scene();
rig.apply(visible, lightingState(), "city");
const wasShowing = visible.environment;
const wasTarget = targetOf(fake, visible);
assert.ok(wasShowing, "the visible board never got an environment");
// A board prefetched for elsewhere in the state: same kind, different sun.
// This is the key miss that does the damage.
const offstage = new THREE.Scene();
rig.apply(offstage, lightingState({ sun: { direction: [0.62, 0.51, -0.6], color: 0xffd9a8, intensity: 1.7 } }), "city", {
offstage: true,
});
assert.equal(
visible.environment,
wasShowing,
"building a board off-stage reassigned the visible board's environment",
);
assert.equal(
wasTarget.texture,
wasShowing,
"building a board off-stage disposed the texture the visible board is using",
);
rig.dispose();
});
/**
* The other half, and the reason the fix is a deferral rather than a refusal:
* the off-stage board must still end up correctly lit when it is presented. A
* fix that simply skipped the apply forever would give the incoming board no
* environment at all, which is the "plastic" look this rig exists to cure.
*
* Two cases, and they are different on purpose. With nothing cached there is
* nothing to borrow, so the build happens at presentation — which is correct,
* and is the same one build the board would have paid anyway. With a probe
* already cached on the same key, the off-stage board borrows it and
* presentation costs no convolution at all, which is the case that actually
* matters: it is what a prefetched board hits when the visitor arrives.
*/
test("an off-stage board is lit when it is finally presented", () => {
const fake = fakeRenderer();
const rig = createEnvironmentRig(fake.as());
const offstage = new THREE.Scene();
rig.apply(offstage, lightingState(), "city", { offstage: true });
rig.apply(offstage, lightingState(), "city");
assert.ok(offstage.environment, "a presented board has no environment");
rig.dispose();
});
test("a prefetched board borrows the cached probe and presents for free", () => {
const fake = fakeRenderer();
const rig = createEnvironmentRig(fake.as());
const visible = new THREE.Scene();
rig.apply(visible, lightingState(), "city");
const built = fake.renders;
assert.ok(built > 0, "the first apply did not build anything");
// The board built behind it, at the same hour, is the common case.
const prefetched = new THREE.Scene();
rig.apply(prefetched, lightingState(), "city", { offstage: true });
assert.equal(prefetched.environment, visible.environment, "the probe was not borrowed");
assert.equal(fake.renders, built, "an off-stage apply convolved a new probe");
// And arriving costs nothing.
rig.apply(prefetched, lightingState(), "city");
assert.equal(fake.renders, built, "presenting a cache hit convolved a new probe");
assert.ok(prefetched.environment, "the presented board lost its environment");
rig.dispose();
});
/**
* The failure mode the fix must not introduce: an off-stage board whose sun
* differs must not go dark. It borrows the cached probe — slightly wrong for its
* own hour, and invisible, and corrected the instant it is shown.
*/
test("an off-stage board at a different hour borrows rather than going unlit", () => {
const fake = fakeRenderer();
const rig = createEnvironmentRig(fake.as());
const visible = new THREE.Scene();
rig.apply(visible, lightingState(), "city");
const elsewhere = new THREE.Scene();
rig.apply(
elsewhere,
lightingState({ sun: { direction: [0.62, 0.51, -0.6], color: 0xffd9a8, intensity: 1.7 } }),
"city",
{ offstage: true },
);
assert.ok(elsewhere.environment, "an off-stage board at another hour was left with no environment");
assert.equal(elsewhere.environment, visible.environment, "it did not borrow the cached probe");
rig.dispose();
});