Spawn
playmakespawnjam
⌘K
visitorclaim namesign in
sign up
playmake
spawn / aboutwhat we're building

pinned

start herewhat spawn isfaqfrequently asked questionsthe betthe spawn bet

updates

engine v5.2LumeJul 10, 2026engine v5.1ConnectionJun 18, 2026engine v5.0For RealJun 4, 2026engine v4.6AtelierJun 1, 2026engine v4.5Surface TensionMay 22, 2026engine v4.4SolidMay 15, 2026engine v4.3GroovyMay 13, 2026engine v4.2ContinuumMay 9, 2026engine v4.1FoundationsMay 4, 2026engine v0.1GenesisApr 29, 2026

pinned

what spawn isstart herefrequently asked questionsfaqthe spawn betthe bet

updates

Lumeengine v5.23w agoConnectionengine v5.11mo agoFor Realengine v5.01mo agoAtelierengine v4.62mo agoSurface Tensionengine v4.52mo agoSolidengine v4.42mo agoGroovyengine v4.32mo agoContinuumengine v4.22mo agoFoundationsengine v4.13mo agoGenesisengine v0.13mo ago
← All posts
← All posts

engine v5.2.13

Engine v5.2.13

August 1, 2026

A patch in the Lume line.

what's new

  • Cameras are yours now, all the way down. Savi writes your camera as a script she can read and edit — every zoom, follow, and framing choice is a line she can change — instead of flipping switches on fixed camera presets. Existing games keep playing exactly as they are; when a world upgrades to this version, Savi rewrites its camera as a script with the same feel.
  • Crouch and prone finally have a real hitbox. Savi can now resize a character's collision capsule live — physics.capsule = { height, radius } — with the feet staying planted and the visible body untouched (animations own the pose). Standing up under a low ceiling politely waits until there's room instead of launching you through the roof, and shrinking always works. No more scaling the whole player down to a miniature to fake a prone hitbox.
  • Game UI now boots on slow phones. Before, a phone that needed more than 4 seconds to fetch the UI shell was cut off at exactly 4 seconds, every retry started over from nothing, and the game's menus and HUD never appeared — no matter how many times you reloaded. Now the engine tells "slow" apart from "broken": as long as the UI shell is still arriving it keeps loading, retries wait longer instead of giving up on the same schedule, and only a truly dead connection gets a failure report (a clearer one, saying whether nothing ever arrived or it started and stalled).
  • Reconnecting no longer looks like teleporting to your game's scripts. Rejoining, reloading, or coming back from a suspended tab used to make portal effects and travel triggers fire — the world-state snap read as a huge jump. Now scripts sleep through the join and wake to the settled world, and for mid-game re-syncs Savi can ask the engine "is this a real move or a sync?" (api.isSettling()).
  • Ground-hugging objects that MOVE stopped eating your frame rate. Anything scripted to sit on the terrain used to rebuild its whole shape every beat it moved — even across perfectly flat ground — and with lots of movers that destroyed performance. Now the engine first checks whether the ground actually changed under it, and skips the rebuild when it didn't. Slopes, cliff edges, and terrain edits still re-drape instantly.
  • Objects that couldn't fit on the GPU now appear as soon as room frees up. In long busy sessions, a newly spawned object could hit a full geometry table and just never render for the rest of the session — despawning things didn't bring it back. Now the engine retries the moment space opens. And when a rendering bug does get reported, the report finally carries the renderer's side of the story.
  • Uploaded skies are finally sharp. A high-res panorama used as a skybox used to get squeezed through the same 1568-pixel pipe as every other image and come out smeared. Skyboxes now load a 4K version cooked from your original upload — horizon seams, planets, and cloud edges stay crisp.
  • Savi can now ask the engine "can a player actually WALK from here to there?" and get a straight answer with the reason — "this step is 0.37m tall; characters can step 0.3m." Before, she could only check that floors and walls exist, so an unwalkable staircase looked identical to a walkable one until somebody played it and got stuck.
  • Savi can now weld a pile of building blocks into one clean solid. Walls, walkways, and towers built from many boxes used to shimmer where pieces overlapped — now she merges them into a single seamless piece (one object, one collider), and the flicker class disappears instead of being nudged one seam at a time.
  • Big worlds can fade things by distance now, without tricks. Savi sets a visible range on any object — "draw this within 700m", "draw the cheap far version beyond 700m" — and the engine handles the swap with no flash, no gap, and no flicker when you hover right at the boundary. City-scale builds stop strobing as you fly across them.
  • 2D cameras can now be fenced at the TOP of the world, not just the sides and bottom — no more camera drifting up past the painted level into grey void during fast action. And if a camera-fence field the engine doesn't understand ever gets written, the engine says so by name instead of silently ignoring it.
  • Traveling between zones can no longer bury you in the ground or a wall. Arrivals land on the destination's real, current ground — even when the spawn point went stale because terrain was dug, sculpted, or regenerated under it — and the crossing itself can no longer carry your old zone's coordinates into the new one. When the engine does have to lift an arrival out of the ground, Savi gets a log naming exactly which stored spawn was stale.
  • Held items stop fighting the game over their size. In busy multiplayer rooms, a weapon or tool attached to a player could visibly snap between two sizes forever — the server and the player's machine each kept "correcting" the other. Now exactly one side owns that number, the snapping class is gone, and if anything ever does fight over a value again, the bug report names the exact system doing it instead of blaming your scripts.
  • Objects that sit on the ground now stay pinned to the ground when you edit them in god mode. Before, grabbing and sliding a terrain-pinned object (or just touching it with an editing gesture at the wrong moment) could quietly replace its "sit on the terrain" rule with a frozen height — and if the object happened to be mid-settle when you touched it, that wrong height stuck: things looked fine while you played, then reloaded half-buried. Now the pin itself is what saves: slide a tree and it's still a tree-on-the-ground at the new spot, lift it deliberately and it becomes a tree-floating-that-much-above-the-ground, and a touch that didn't move it changes nothing at all.
  • Terrain stops going flat when texture generation is busy. New terrain materials get generated PBR detail (height and normal maps) from their texture, and while that generation was pending — or refused, e.g. for a too-small source image — the ground rendered as flat colored tint with no texture at all, sometimes for a whole day. Now the ground renders your actual texture immediately and the PBR detail upgrades in place when generation finishes. If generation refuses your texture, Savi now gets a report naming which texture and both ways out (upscale it, or turn pbr off) instead of a misleading "fix the texture reference".
›technical notes
  • Builtin camera kinds deleted — scripts are the only camera authority. The five spec camera archetypes (third-person/first-person/top-down/isometric/side-scroller), their rig implementations, the kind-swap prune vocabulary, the numeric transition interpolator, and the kind-keyed engine plumbing (pointer-lock/hide defaults, archetype state seeding, per-kind ortho zoom derivation, the renderer's first/third-person regime) are gone. One camera shape remains: kind: "custom" + behavior scripts, with the existing primitives (hideLocalPlayer, orientation authored-axes contract + getViewAngles(), pointerLock, cameraApi.raycast + collisionDist, state.orthoSize ortho zoom) carrying everything the kinds used to. The god camera and the 2D no-camera fallback rigs survive engine-internal and spec-invisible. A spec arriving at this version with a removed kind runs as custom (scripts-only semantics) and raises a structured spec-shape warning naming the migration — loud, never silent; it is unreachable except through an upgrade-path bug, since pinned worlds keep the engine that carries their kinds. The 2d-side starter now ships the canonical side-scroller camera script (dead zone / look-ahead / peek / world-bounds clamping) instead of a kind block, and the camera skills teach script recipes for every perspective.
  • Character capsule dims are authorable and runtime-writable — physics.capsule = { height?, radius? } (the crouch/prone primitive; the fixed 0.35/0.6 humanoid capsule becomes the default instead of the only option). Height is end-to-end (halfHeight = height/2 − radius, clamped at 0 — the same number traverseCheck reports as capsuleHeight); dims are entity-local and scale folds on top like every collider. Applied at the one spec seam (applyPhysicsSpec), echoed by readPhysicsSpec as realized collision truth (round-trip idempotent), and it rides the existing PhysicsBodyConfig wire codec (capsule halfHeight/radius were already on the wire), so remote followers realize the same hitbox. Non-character bodies get a one-time teaching warn (their capsule size belongs to the primitive/model + scale); the old normalizeColliderSpec warn that taught the uniform-scale workaround now names this property instead.
  • Grow admission, both backends: shrinking is always legal; a grow that would embed the capsule in STATIC geometry is HELD — old collider live, per-tick re-probe, applies the tick there is room (the held-handle "never trade a collider for a hole" idiom pointed at a new hazard). The probe is the stuck-escape's own predicate (same shrink tolerance, fixed-only + sensor-free, self excluded — one shared constant, CHARACTER_PENETRATION_TEST_SHRINK), so an admitted grow can never trip the penetration escape: no teleport-through-the-ceiling, by construction. 3D runtimes; rapier gates in getOrCreateHandle, mantle in ensureMantleEntity via overlapShape.
  • Mantle feet-anchor parity on rebuilds: a mantle body rebuild whose feetOffset changed now re-anchors center = feet + up·newFeetOffset before teardown (rapier already did this in its rebuild path) — previously a capsule shrink left mantle characters hovering at the old eye level, since the recreate seeded from the stale BodyPosition and the motor owns gravity.
  • Authored-UI shell boot: the fixed 4s load deadline became an escalating, progress-aware stall ladder (4s → 8s → 16s). The old choreography converted SLOW into NEVER on weak devices (ledger 1913, third specimen of the patience-topology class): a phone that needed 6s to land the shell document was killed at 4000ms, and the single cache-busted retry — killing the iframe aborts the in-flight fetch — restarted from byte zero under the same 4000ms, so no amount of retrying could accumulate progress; the session latched failed with "shell document never loaded within 4000ms, twice", re-armed on the next render, and died the same way forever. Now: three attempts with doubling windows (total 28s of patience for silence, still bounded for a genuinely dead shell), every retry still cache-busted (the poisoned-cached-response class keeps its medicine). Each window is a stall detector, not a duration cap — the shell HTML gained two inline one-liner progress beacons (tome-realm-progress, stage parsing at head-top / parsed at body-end; the only host-visible signal below the iframe load event, since the sandbox's opaque origin hides contentDocument/readyState), source-gated exactly like hello, and a stage ADVANCE re-arms the live window in place — same iframe, same in-flight fetch, no restart — so an observably arriving document is never killed; duplicates and spam are inert (advance-only, two stages max). The exhaustion fault stays ONE bounded ui.realm verdict and now names what the final attempt saw: "no byte of the document ever arrived" (dead route/serving class) vs "html parsed; the shell module never finished loading" (connection too slow or died mid-transfer) — the discriminator Savi can act on. Hello/ready phases unchanged.
  • Reconnect rebaselines are invisible or labeled to behavior scripts (dig 76609a1f — the "was that you moving my camera?" ghost). A join/reload/tab-reopen rebaseline surfaced as an unlabeled >8m position step, indistinguishable from portal travel — authored displacement detectors misfired on every reconnect (the specimen: an arrival-facing auto-turn snapped a player's camera toward the world origin 46s after a tab reopen). The hold: on netcode-client worlds, behavior update() and camera script hooks park until the first replicated baseline has ingested AND the reset cadence has been quiet for the settle window (1s, REPLICATION_SETTLE_WINDOW_SECONDS) — the whole boot choreography (including the observed double reset 54ms apart) happens inside the hold, so a script's FIRST observation of the world is the settled truth, even for deployed legacy scripts that will never check a flag. Boot-only latch: once released it never re-arms, so a mid-session reset storm can never freeze live gameplay. Camera rig maintenance (projection sync, first-person visibility, pointer lock) keeps running through the hold — boot frames still have a camera.
  • Felt cost, deliberate (the release's one deliberately-felt boot change): on fast kernel multiplayer joins, scripts and camera hooks start ~1s after the last boot reset — a breath before the world starts moving. Pre-baseline motion was placeholder-world motion the snap threw away; physics pause usually overlaps the window.
  • The name — api.isSettling() (ObjectAPI + CameraAPI): true while pre-baseline or within 1s of the last reset-projection ingest. Mid-session rebaselines (wake reset on tab resume — the ledger-1896 adopt-everything envelope; self-heal resets) cannot be held without freezing gameplay, so they are labeled instead. Named residue, pinned as such: unguarded legacy scripts still misfire on a mid-session takeover iff the position actually moved — the label exists for exactly that guard.
  • Relay-bootstrap worlds synthesize their baseline locally — the hold releases at that edge with no settle window. Real portal teleports after settle stay fully visible (pinned). Reset ingests funnel through applyProjectionResetAdoption, which stamps noteReplicationRebaseline on the client clock the behavior gate reads; unarmed worlds (unit tests, sim-check, server worlds) are inert.
  • Redrape pre-check — a moved usesGround anchor replays the mint's recorded ground samples before paying a generator re-run (tucker's P1, thread 1785563036; dump 9e8d30a3: tome/scripted-primitive-ground-redrape at p95 21.3ms/tick, max 294ms, 370 watched recipes in one place). scriptedGroundStateKey folds the quantized anchor transform (1/64 m feet), so an object MOVING across ground moved its change token every cadence window — and the redrape system answered every moved token with a full generator re-run (sandbox execution, mesh build, hashing, physics refresh) even when the ground under the new footprint answers byte-identically; N movers × 5Hz windows = the destruction. The key stays the cheap, never-under-triggering dirty bit; the consumer now pre-checks: the mint records its ground-call ARGUMENTS (process-local GroundSampleTrace, never on the wire) beside the recipe's existing #11170 results tape, and a moved key replays those arguments through a live sampler comparing quantized answers against the tape — all equal ⇒ a re-run would emit identical bytes (deterministic generator, identical ground answers at every branch point) ⇒ skip, costing a few terrain height lookups. Any differing answer (real terrain change, slope arriving under a mover, pose change) re-mints exactly as before.
  • Vintage honesty: recipes without a provable trace — pre-#11170 mints, over-cap groundDigest recipes, boot/restore, ownership handoff — fall back to the re-mint, whose mint re-stamps trace + tape: one paid run, then covered. An adopted row whose tape ≠ the local trace is never vouched for (element-wise identity guard). Same-system bonus: the key's O(vertices) footprint scan (per window per watched entity) is now cached per content-addressed geometry value.
  • Pins are mutation-checked (disabling the pre-check turns exactly the three skip-pins red): zero generator re-runs across 10 movement+yaw windows on flat terrain (counted by trace identity — equals-gated component writes made object identity a vacuous counter); movement onto genuinely different terrain still re-drapes; a sculpt on a recorded contact point still re-mints while a near-miss chunk bump skips; the traceless fallback pays once and self-heals.
  • Renderer census in engine-bug client dumps (dig 80a1746b; ledgers 1854/1833/1831 — third render-family investigation in a week blocked by the same instrument gap). EngineBugClientDump.render gains primitives (live primitive + bespoke record counts; count + first-12 entityIds of live entities at representation=null — the museum-blackout signature; the null classifiers waits/parkedWaits/deriveFailed/starved; per-lane arena used/ceiling rows with overflowed and gpuAllocFailed verdict bits), flags (the session's enabled render feature flags — [] is a positive all-off receipt), and drawCalls, riding the existing 1 Hz perf-sample mirror (≤1s stale by construction; zero per-frame state). Bounded (12 ids / 16 lane rows / 8 flags) and re-clamped server-side regardless of what a hostile or future client ships; old 5.2.x dumps parse to null fields, never reject.
  • Arena-refusal rollbacks became retryable — the structural half. The three silent representation=null paths (the batched-lane allocateSlot ceiling refusal + the two bespoke rollback branches) now register in store.starvedRepresentations; a bounded (≤4/prepare), epoch-gated sweep re-derives them whenever arena capacity MAY have freed (lane slot release, idle-lane disposal, device-limit grant — freed-range best-fit reuse genuinely heals). Epoch-stamping at registration is the ping-pong guard: a failed retry's own partial rollback cannot re-arm itself; stable scenes pay O(1) per prepare. An object refused at tick N renders the moment room frees, instead of staying invisible for the session.
  • Lane GPU buffer creation/grow OOM is now loud (the long-session whole-lane-blank hypothesis): error scope on recreateGpuState, once-per-lane console line + primitives-lane-gpu-alloc-failed diagnostic + the gpuAllocFailed census bit. Rollback is not representable (the buffer stays invalid until memory frees and the next grow) — but it is visible now.
  • Checked, no fix needed: a 202'd GLB already re-fetches in-session (Retry-After-scheduled re-probe + a render-on-change wake at the retry deadline, plus the slow-cook diagnostic when the loop outlives its threshold) — never-arriving assets point at the cook side, and the dump now carries that receipt.
  • Equirect skies serve from the max-res-4k variant — the 1568 canonical cap protects Savi's eyes, not the players' (r-afa42722; ravi's dig 67b78fd3 on enfeul's partner-tier report). His 8688×4344 skybox rendered from a 1568×784 KTX2 because every canonical persists at DEFAULT_MAX_DIMENSION=1568 (deliberate: Anthropic-vision-optimal + the >2000px session-wedge guard) — Savi diagnosed the cap herself in-session and was right. One pure helper (tome/skybox-texture.ts, upgradeSkyboxTextureRef) applied at the two places that must agree — atmosphere-sky-utils.ts (the DrawSkybox textureId the sky renderer leases) and spec-assets.ts (asset-manifest registration + preload hints): cdn/foo.webp → cdn/foo.max-res-4k.webp, and the KTX2 transport derives ….max-res-4k.webp.ktx2, so the GPU texture cooks from the 3840-cap variant. Non-cdn/ refs, query-bearing refs, and non-image extensions pass through unchanged. First production use of the max-res lane; staging receipts end-to-end with the specimen's actual source pixels (canonical 1568×784 unchanged; max-res-4k 3840×1920 PNG + KTX2 minted on demand).
  • api.traverseCheck — the walkability probe (r-be446670; tucker's bridge dig). Savi ran SIX collision probes on an unwalkable bridge and every one answered TRUE, because colliders existed everywhere — the bridge stepped +0.368m between slab tops against the character controller's autostep maxHeight 0.3, and walkability = f(riser, autostep) was computed nowhere she could read (~20h of blind authoring). The verb marches the segment at controller-scaled steps over the same resolved collider volumes the overlap probes use (rapier-pinned) plus the terrain samplers, reading the LIVE PhysicsCharacterControllerConfig (+ the body's resolved capsule) through the same voxel-place effective rule the stepping controller applies — the CC's own numbers, never duplicated constants. Body resolution: opts.body → caller-if-character → a player in the place → engine defaults. First blocker + WHY: blockedAt pins the failing location, blockedBy names the entity, detail carries measured-vs-limit.
  • What the controller ignores, the probe ignores: sensors never block; other characters pass through by the CC's own packed-group law; dynamic (pushable) bodies only with includeDynamicBodies: true. Pure geometry, no simulation mutation — answers identically in run_script's snapshot (where the bridge session went blind — exec-lane test included), on the multiplayer server, and on live clients.
  • Prompt budget (the #11746 convention): traverseCheck joins the Raycasting long tail as a bare name (16,097 < 16,100 cap); the full contract rides api-reference §Raycasting + TomeAPI.md; the worked example rides the pointer-raycasting skill. The pinned test suite includes the bridge specimen exactly (13 slabs, +0.368 risers → riser_exceeds_autostep, detail.riser ≈ 0.368, blockedAt at slab-0's top).
  • api.unionSolid(objectIds, options?) — the union-solid primitive (r-9b856490). Takes N axis-aligned box/cube objects (any 90°-multiple rotation; validated as a signed-permutation rotation matrix) and produces one object wearing primitive: { kind: "custom" } whose geometry is the exact boundary of the box union, computed by the 3d-rooms apex extractor (rooms/boundary.ts — one face per boundary location, owner resolved by input order, interior/coplanar-duplicate faces impossible by construction; same-paint solids pre-merge via mergeSolidsForExtraction). Per-piece paint rides the bespoke vertex lanes (linearized color multiplies instance albedo; metalness/roughness/emissive carry the negative keep-instance-scalar sentinel when unpainted). The result spawns through the normal spawn pipeline (persistence, ownership, undo, replication all inherited), inputs are destroyed after the spawn commits, and physics (when any piece had a body) is static with a bespokeMesh collider — N box colliders → 1. A shared non-default material family (water, explicit keys) survives the merge — the union spawns wearing the family key; keyed pieces merge BARE (per-piece overrides on a keyed family refuse: paint is a standard-family lane those shaders never sample). Refusals are structured ({ merged: false, reason, message, blockers[] }) and name EVERY blocking piece: not_found / not_a_box / rotated / degenerate (floor = the extractor's 10 µm lattice, so no accepted piece can quantize to zero cells) / has_children / has_parent (a union spawns as a root object and would stop following the parent) / has_behavior / unsupported_physics (dynamic/kinematic bodies, sensors, collision filters, friction/restitution — the one plain static collider cannot represent them) / unsupported_material / mixed_material_keys / mixed_places / mixed_realms, plus call-level too_few_pieces, too_big (the 16,384-vertex bespoke cap refuses instead of truncating), and id_taken (a live options.id refuses — the union never mutates or shadows an existing object). Determinism pinned by test (identical input → identical buffers).
  • Runtime-spawn lane: inline-custom geometry now collides as its mesh (ledger-906 parity). applyObjectPhysics in object-api.ts gains the interpreter's bespoke branch: an entity whose appearance is inline bespoke geometry (kind "custom", no DrawPrimitive) and whose collider resolves auto/mesh gets { kind: "bespokeMesh", geometry: <signature> } instead of falling through to the 1m default box — the "collision only at the center of the objects" class (triage 70410cc7) arriving through the spawn lane. Explicit collider shapes (box/sphere/capsule) behave as before.
  • Prompt/docs: unionSolid joins the always-on Lifecycle tail as a bare name (+12 chars, 16,020 → 16,032, cap 16,100 unchanged); the full contract (@tomeapi on the verb + result types) rides api-reference §Lifecycle; the custom-geometry skill's one-solid-not-stacked-plates law now points at the verb for already-spawned assemblies.
  • properties.visibleRange — per-object camera-distance visibility, renderer-evaluated with hysteresis (r-005e6f9a; ravi's NY-1:1 LOD dig ef4136e0). Savi structurally could not express 10-lines-of-three.js distance visibility (if (dist < 700) mesh.visible = …) without destroy/respawn entity churn or tick-lagged property writes — the observed tier swap was destroy-now-respawn-on-a-later-pass (≥4–8 blank display frames per swap, a strobing ring traveling with the camera at fly speed; three overlapping hand-rolled LOD systems in one world). Now: a DrawVisibleRange component (replicate: "aoi", forwardToRenderer: "always") carries only the authored band; the renderer registry (lume/entities/visible-range.ts) precomputes squared thresholds at write time and sweeps per frame against THAT frame's camera; verdict flips rewrite lane visible bits through the same paths a visibility-mask op uses, composing as one more AND with the camera visibility mask across every primitives-store representation (batched lanes, oversized pools, scripted, water, bespoke parts). Objects without the property pay ZERO per-frame work (registry-only iteration, size===0 short-circuits).
  • Hysteresis is engine-owned — a hovering camera can never flicker: the authored boundary is the CENTER of a ±5% band (shown hides only past max × 1.05; hidden shows only inside max × 0.95; min mirrored; between them the previous verdict sticks). Pinned: 500 camera sweeps at ±98% of the half-band produce ZERO toggles from both armed states; decisive crossings flip exactly once; a REPLACED range inherits the standing verdict (no one-frame blink); complementary bands admit at least one tier at every distance.
  • ObjectAPI getProperty/setProperty("visibleRange", …) round-trip in the spec shape; invalid writes warn and HOLD the standing range (a bad write must not silently un-range a streamed building). In-passing fixes at the same seam: refreshPrimitiveVisibility now honors OVERSIZED representations (a visible: false op on an oversized-represented primitive silently did nothing), and fresh oversized slot acquisition re-asserts current visibility (a hidden entity re-deriving into a pool slot no longer pops visible).
  • worldBounds.top completes the 2D camera fence (ledger 1870, gutterbt's grey-void report; dig 3faa4158). The set was {left?, right?, bottom?} at every layer — an authored top silently dropped (the zod schema stripped it on parse; isWorldBounds/clampToBounds never read it), so shot-follow drove the eye high and opened grey void above the painted world, unfixable by any authored rect. Now top rides the type, the schema, isWorldBounds, and clampToBounds, honored exactly like bottom, mirrored: frame top never passes top; shorter-than-viewport levels center vertically. The gutterbt repro is pinned (bounds {left:-70, right:70, bottom:-24, top:24}, camera driven to y=60 → eye pins at 19, frame top exactly 24 — no void above the paint), plus top-alone, level-entity-published top, short-level centering, and schema-parity pins.
  • The silence dies — spec-shape warning for unrecognized worldBounds fields (tolerance stays: unknown fields still no-op; once per room per field-set, a newly authored unknown field re-warns): the warn names the field, states the four understood edges, and says what an ignored field means (that edge is NOT fenced). The next authored field that doesn't exist warns by name instead of dropping traceless.
  • Named residue (row 1870's remaining shape): BOUNDS_ASPECT still assumes 16:9 (a 2.03:1 screen under-clamps horizontally ~2.75wu/side); the fence stays opt-in (derive-default-from-painted-extent is the bigger cut); unknown fields in level-entity-published state.worldBounds (runtime state, not spec) still drop silently.
  • The zone-arrival contract — transitions land on a validated destination spawn, never carried source coords (r-23615562, dig ec420521; three specimens in five days on one prod world: wall-regen embedding 07-29, "it put me in the wall" 07-31, arrive-in-the-ground 08-01). Two halves. Client: the reset client-sim guard (ledger 1848) rewrote guarded reset rows to server-stamped components only, so a traveler's OWNED transform kept source-place coordinates while PlaceMembership flipped underneath — the client rebased into the destination standing at source coords and uploaded them back as canonical (the specimen telemetry exactly: Place=gnollwarren, position=wildlands, minimap lagging). A guarded reset row carrying a PLACE CHANGE now adopts wholesale (proof of server origin — a client can never rewrite PlaceMembership on a live entity); same-place resets keep preserving owned locals (the guard's send-failure-storm purpose, pinned by test). Server: enterPlace spawn resolution checked nothing against destination ground — explicit spawnPoints, "last" memories, and authored fixed-y defaults all go stale under digs/sculpts/regens, and the KCC cannot depenetrate out of a heightfield from underneath. New tome/place-arrival.ts validates player arrivals against the destination's current terrain. Players only — authored under-terrain props stay legal.
  • Structured verdict when validation moves a player: runtime log code: "arrival-embedded-lift" naming the stale source (explicit / last-memory / authored default), from-y, resolved ground, and place — Savi sees WHY someone arrived where they did instead of investigating a mystery.
  • Named residue: cold first-residency arrivals fail open (the destination's terrain definition installs a tick after ensurePlaceResident, so there is no ground to judge at verb time — pinned by test); mesh/prop overlap at the arrival stays the character controller's depenetration job.
  • GeometryScale single-writer treaty — the server-side fit solver never writes a client-simulated entity (dig ad327a50 cuts 1+3; badgerblunts' warfare room: ~2/s geometry/scale stomps on one held weapon, 66/30s, 7,043/session, weapons visibly snapping). geometry-fit-solve ran mode:"both" with zero simulator guard: a server-side solve on a client-simulated entity was a LOCAL-origin write → forwarded, fencing the owner's uploads and replacing the owner's local values — with realm-skewed bounds inputs the two solvers disagree indefinitely. The engine fighting itself; no script to stop. Now it adopts terrain-reanchor's exact treaty: server half skips client-simulated entities WITHOUT consuming the dirty mark (write duty returning re-solves immediately); observer half consumes the mark as bookkeeping (the simulator's replicated rows carry the answer); fresh-boot/headless/exec/singleplayer worlds solve exactly as before; unowned place content under client-auth pauses until a host claims it (the same pause terrain-reanchor and behaviors obey). The fight class is structurally unrepresentable: the simulator is the only realm that writes.
  • Sustained-fight verdict that names the writer. Same-(entity, component) fence drops crossing 50 in 60s escalate the per-client teach to ONE structured verdict per pair per window (data.verdict = "sustained-write-fight"), and a new local-write observer seam (setLocalWriteObserver, fires only on LOCAL-origin marks) + the executor's ambient withSystemContext bracket let the verdict name the actual writer: server-side writer "tome/geometry-fit-solve" is fighting the owner of <entity> over "geometry/scale". Hook/cron/run_script writes (outside any system bracket) stay unattributed and keep the script-lane diagnosis — correct for that family. The old blanket "a server-side script keeps writing it" was wrong for engine-writer fights and unactionable.
  • Dump surfacing (the fence lane is DD-invisible by construction): EngineBugRealmContext.uploads now carries uploadDrops per gate + serverWrites (including sustainedFightVerdicts) in every engine-bug/incident dump. Enforcement is byte-identical — the verdict is a receipt, never a behavior change (pinned).
  • God-mode gesture commits preserve terrain anchors — the spec's y: { terrain: offset } form is the truth; the live resolved y is only its projection (cal's Final Abyss dig, dump 4456c18d). commitGestureEdit diffed and persisted feetPosition through getProperty — resolved world coords — so ANY gesture touching a terrain-anchored root baked its current live height into the spec as a concrete number and deleted the anchor. When the live projection was wrong (not-yet-streamed terrain resolution, a script re-seat mid-flight, cross-realm height divergence), the wrongness became durable: cal's boundary trees sank 6–10m at the touch and reloads kept them buried, while his ground-warden script re-lifted them live every 2s — "looks fine until it suddenly doesn't", and "not persisting" on every boot. Now readEnvelopeValue reads feetPosition in the frame the spec stores it (the live TomeTerrainAnchor component, root-only — armed by every terrain-form write, removed by every concrete write, so it always mirrors the last form a writer chose): before/after compare form-to-form, a gesture that never rewrote the pin contributes no feetPosition diff at all (zero-move touches and menu picks bake NOTHING, even while the live y wobbles underneath), a slide persists the pin at the new x/z, and undo restores the authored form. Bonus determinism: the commit diff no longer depends on per-realm terrain samples, so client and server record identical undo entries by construction.
  • Horizontal slides carry the authored offset verbatim. The translate pad and the spline move pad derived their terrain offset from liveY − terrainHeight at press — a wrong live y turned a purely horizontal slide into a durable vertical edit. Both now read the offset (and the f64 x/z base) from the object's authored spec form when it is terrain-anchored: { terrain: 0 } slides as { terrain: 0 } exactly, with no terrain-sample round trip to smudge it, and the y-less { x, z } shorthand keeps its shape. Unanchored (concrete-y) roots keep the live derivation — the pad converts them to terrain-relative at the float the creator sees, which is the pad's long-documented intent ("persists a terrain-RELATIVE y … rides later terrain edits instead of being buried") finally reaching the spec instead of being re-baked concrete by the commit. Deliberate vertical lifts keep their as-found rule: they re-author the pin's offset ({ terrain: newOffset }), still terrain-form. Snap TOP-STACK mates still re-derive (a deliberate vertical correction). Pinned red-first in terrain-anchor-commit.test.ts, including the exact cal shape: spec { terrain: 0 } + live y corrupted meters downward + horizontal touch → the pin survives and the wrong y never bakes.
  • Coverage boundary against the LIVE-PARKED-ENTITY class (dig 6f5f9bb5 — cal's XZ teleports to glade center: live entities sitting at the park transform (origin x/z, y=3.8, identity scale) because spec position was never applied while scale was; receipts: ha-tarn-mourn-5 durably baked to (0, 3.8, 0) at v16197, plus four kernel identity-scale resets v16193/v16196/v16201/v16203). Pinned by test, honestly: (1) a zero-move touch on a parked object now bakes NOTHING — the grab-verbatim park write (v16197's shape) is dead at commit; the one residue is an undo entry whose before is the resolved park (no anchor was ever armed, so the press-time envelope falls back to the live read) — undo after such a touch re-bakes the park. (2) A real drag on a parked TERRAIN-ANCHORED object lands at authored+delta — the pads base x/z on the authored spec row, never the live park — so the teleport-toward-origin is cured for the terrain-form specs cal's trees actually carry. (3) NOT cured, the follow-up's cases: a real drag on a parked CONCRETE-y object still persists park+delta (no authored terrain form to read); deliberate-vertical grips on a parked object still derive from the parked live; and script-lane editors (getProperty/setProperty in game scripts, e.g. the session's editor.js move arrows) never pass through this commit at all. The root — the silent partial transform-apply that parks the entity — is the named follow-up; fixing it re-arms the anchor and closes every residual above at once.
  • Zero-effective-delta touches of concrete-writing handles bake nothing (found in adversarial review — the form-based diff would otherwise have OPENED a bake path master didn't have). Several drag handlers write concrete feetPosition from the press-time live snapshot on every drag tick, including a tick with zero effective delta: the cylinder cap extrudes (hover + declared grip), the plane edge extrude, and the 2d-top/2d-side pad branches. On an anchored root, that idle write strips the live TomeTerrainAnchor (concrete write = de-pin), so the commit diffed form-before vs resolved-after and baked the live — possibly corrupted — height on a plain press+release; master's resolved-vs-resolved compare baked nothing on that same touch. All five sites now skip the feet write at zero effective delta (no movement, no write — which also stops an idle touch from silently de-arming the live anchor, a live-only master bug). Pinned red-first: cylinder bottom-cap hover extrude, zero-move touch, corrupted live y → spec byte-identical, no undo entry. Real (nonzero) resize drags keep their as-found rule: cap/edge extrudes persist concrete feet — the "never de-pins" rule is the MOVE grips' (pads, lifts); resize extrudes that genuinely move feet still convert, as they always did, and undo now restores the authored form.
  • THE COMMIT SEAM — one boundary rule closes the whole zero-move-bake class, for every handler present and future. The per-writer guards above fix the sites they name, but the class was wider (review round 3): cube extrudes write concrete feet unconditionally — and for axis=y sign=1 the shift is hardcoded 0, so even a REAL grow-taller drag wrote value-identical concrete feet and de-pinned the root; the vertical grips (terrain-offset, verticalMoveGrip) write { terrain: liveDerived + total } at total=0, baking a corrupted live y as a wrong offset; writeAnchoredScale does the same on the fallback/model handle set — the handles cal's actual trees carry. Instead of a third round of per-site guards, the commit now owns the rule: captureUndoEnvelope records the LIVE feet as the gesture found them (GESTURE_LIVE_FEET_KEY), and commitGestureEdit drops feetPosition from the diff when the release-time live feet are byte-identical — "a gesture that left the live feet where it found them persists no feet change". That is master's own zero-move semantics (its resolved-vs-resolved compare could never persist feet without live movement) restored structurally, composed with the form-based diff for genuine moves — so the seam can never bake where master didn't, and it also stops the zero-move pad touch of a concrete-y root from phantom-converting the spec to terrain form. Pinned red-first per family: cube face touch, cube top-grip REAL grow (scale persists, pin survives), vertical-grip touch on a parked object, model size-star touch, concrete-y pad touch. The per-writer zero-delta guards stay as live-write hygiene — an idle touch must not de-arm the live TomeTerrainAnchor even transiently; the seam protects the spec, not the live component, and the unguarded families still de-arm/re-derive the live anchor on an idle touch exactly as master did.
  • Out of scope, named for the follow-up: the gesture-seam reconciliation (client-predicted vs server-applied divergence inside a drag — what produced cal's 6–10m mid-gesture drops). This change removes that divergence's path into the SPEC; reconciling the live projection across realms during a gesture is the #11775 zone-arrival doctrine transposed to god-mode object writes, and it is not built here.
  • Terrain raw-albedo fallback — a pending or refused Patina cook no longer degrades new terrain to flat tint (dig 554e8cd9, jacob's "blurry with lines" 08-01). Since pbr-by-default (#10552, prod ~07-26) every new textured terrain material's textureId is the Magic-CDN Patina albedo+height variant (<albedo>.pbr.json.png.ktx2?transform=albedo-height), and until that derived source lands the atlas rendered the layer as its tint color over a 1×1 placeholder — so a fresh mint (cook minutes), a starved cook queue (the 07-31 storm), or the 24h Patina 4xx reject park (c9c080f68f) all read as textureless watercolor ground. Now buildMaterialPack threads the raw albedo the variant was cooked from as fallbackTextureId, and the terrain layer atlas requests it whenever the variant isn't already resident: the raw texture joins the array and renders (the pre-07-23 look — alpha-as-height off while it serves, so height-aware blending never reads opacity as height), and the cooked variant supersedes it the moment it lands (join priority: a fallback never displaces a resident or batched primary; the warm path — variant already resident — never fetches the raw albedo at all).
  • Reject-seam honesty: terrain-atlas-tint-fallback now fires only when NO source can serve the slot (variant rejected AND raw albedo absent/rejected). A variant that can't pack while the raw texture serves fires the new milder terrain-atlas-raw-albedo-fallback teaching ("ground stays textured, PBR surface detail is what's missing"), and a variant that rejects while its raw albedo was warm-path-deferred kicks the fallback load right then.
  • Cook-refused verdict (texture-pbr-variant-refused): a Patina-derived map URL that dead-parks or tombstones at the texture service (the kiln 24h reject verdict serves a descriptive 400) no longer teaches the generic "fix the texture reference in the spec" — the engine minted that URL itself, so the teaching misdirected Savi at a ref she never wrote. The new verdict names the SOURCE texture, says the raw texture keeps rendering, and puts the fix where it lives: upscale/regenerate the source, or pbr: false. Teaching leads, server detail trails (the diagnostic rail truncates from the end).
  • Named residue (follow-up, dig shape 3): blendWidth = max(fwidth, 0.18) on the pbr shader variant is untouched this PR — height-aware blend width without landed heights is a separate softness contributor and deserves its own change.