scene.environment was null for seven rounds. diffuse = albedo * (1 - metalness),
so a metal is nothing but reflected surroundings — and 13 of the 27 shipped GLB
materials are metallicFactor >= 0.8 (16 at >= 0.5, 21 with no MR texture). Round
6's GLB_EMISSIVE_FLOOR = 0.42 was cosmetics over a lighting hole.
- env.ts (new): procedural 128x64 half-float equirect through PMREMGenerator.
Zero bytes shipped, no asset fetch. Dark industrial room per codex 8; key/fill
blob directions passed in from index.ts's real lights, never duplicated.
- GLB materials take envMap explicitly (three overrides material.envMapIntensity
with scene.environmentIntensity on the scene-fallback path), so the assets can
be dosed at 2.6 while six rounds of hand-tuned world art keep 0.5.
- emissive floor 0.42 -> 0.18: re-tuned, not retired. Still the "never a hole"
guarantee and still what carries a machine through a brownout.
- registry.init no longer awaits probeAll: renderer.init 284ms -> 28ms, ready at
339ms -> 88ms. Placement juice suppressed on asset-version bumps so the factory
doesn't re-place itself a second into every boot; a def change still pops.
- era.ts: eraIndex now breaks a contested unlock FIRST-tech-wins, matching
LANE-UI's indexTech. It was LAST-tech-wins despite round 4's NOTES claiming
otherwise; the tests found it.
- registry.test.ts (new): 31 tests, this lane's first. 481 -> 512 repo tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The new farm stack changes the economics of every asset in the game. Measured,
same machine, same concept:
current (flux -> sf3d, albedo only) 1135 KB 27k tris no PBR
hunyuan3d_mlx raw 7408 KB 60k tris PBR
hunyuan3d_mlx + gltf-transform 418 KB 18k tris PBR <-- ships
trellis2_mlx raw 36087 KB 487k tris PBR
trellis2_mlx + gltf-transform 4147 KB 273k tris PBR (too heavy)
So the optimized Hunyuan path is 2.7x SMALLER than what ships today and adds real
metallic-roughness maps. 30 machines would be ~13 MB against today's 31 MB.
Enabling change: GLTFLoader.setMeshoptDecoder (three bundles the decoder).
EXT_texture_webp + KHR_mesh_quantization are native. Uncompressed GLBs unaffected.
Verified in the live showroom: served 428068 bytes, webp textures, 1 PBR-mapped
material, zero console errors.
mosh-reactor.glb replaced with the pilot output (LoRA-directed concept: rainbow
melt in the porthole, recovered anchor slab glowing in the airlock).
Also fixed on the farm, not in this repo: the FLUX LoRA library lived in ComfyUI's
models/loras, which flux_local does not search, on a queue that load-balances to a
second node that had none of them - every LoRA call failed with 'LoRA not found'
depending on which machine caught the job. Both nodes now carry the same set.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- registry: texel-following emissive floor + one-impossible-element accent beacon on every
hot-swapped GLB (generic, no hardcoded list) — restores the two-material rule on baked assets
- wildlife: parity-mite beetles with green checkmark eye, size-driven state tell (hunt/repair/
sated), derived 'repaired' tidy sparkle + firewall-can 'filed paperwork' cue
- relics/juice: golden excavation geyser on unfound->found transition
- devscene: parity-mite fixtures across all three states for verification
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round 4 orders 1-5:
- ghost keys demolition off setGhost's `mode` arg; the '__remove' sentinel is
ignored and REMOVE_DEF is gone from this lane.
- locked-build ghost: padlock-amber (not occupied-red — "not yet" and "not
here" are different sentences) + a padlock tinted by the gating era. Needed
a new ERA_TELL palette: ERA_SKIN.tint is a multiplier tuned to leave DATA's
chassis alone, so it can't carry a signal (stream is #ffffff).
- aura.ts: cooling coverage as a dashed RECTANGLE. coolRadius is chebyshev, so
the cooled region is the footprint grown by r per side; a circle would look
better and lie about the corners.
- lab placeholder: bench + the "bottled artifact triptych" (§2); consumes
MachineDef.accent when present, derivation stays the fallback.
Also:
- buffer fill reads bandwidth.capacity (v4) instead of re-summing bufferCap —
a second copy of the sim's arithmetic is what the scram latch warned about.
- lock rule matched to LANE-UI's reading: absent research means nothing has
completed, so gated machines padlock. Mine said the opposite; theirs is the
literal contract text, and the build bar and ghost disagreeing on the same
screen is worse than either answer.
- showroom fitted to BOTH axes. Round 3's depth-only fit collapsed the item
grid to one 206-tile row once the machine hall grew and ate the depth.
Verified against DATA's real v4 data and UI's migrated flow: 6x6 aura on
asic-cooler, reel/broadcast era tells, lab accent #ffc24a from data, 29
machines + 60 items in the showroom, 500 entities + 2,000 items at 3.6ms.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Confirms the units conversion (bufferCap 240 = 8.0s of cover at a 30/s
deficit) and reports scram survival: first scram t434, restart t934,
~718-tick duty cycle, ZERO brownout ticks across 20k, melt rate unchanged.
For the orchestrator:
- heat semantics need a one-line ruling. heatPerTick is GROSS in my model
(net = heatPerTick - coolPerTick). DATA's committed 0.0025 against the
0.004 default nets negative -- the decoder could never scram. Their
in-flight 0.0033/0.001 works, so we agree by luck of timing.
- the codex's literal bloom loop is not expressible with per-grade recipes
- asic-cooler does nothing without a spatial heat mechanic
- my sim code landed inside 45003db [ui] REMOVE mode: the shared tree has
one git index and an add-everything commit in another session swept it.
Not a UI ownership violation. Suggest a no-`git add -A` rule.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round 2 orders 1-6:
- topology.ts: belt neighbour analysis -> straight/cornerA/cornerB/merge,
one InstancedMesh per (def x shape), flow field baked per shape. Corners
sweep a quarter-arc; merges get inlet arrows.
- cargo follows the corner arc: `t` is progress along the tile, so walking
items straight through the centre made them cut corners and pop in at the
wrong edge. They now enter at the feeding edge (verified 0.089-0.248 off
the centreline where straight pins to 0.000).
- heat.ts + entities.ts: dull-red body ramp, rising shimmer column, throttle
(idle AND GLB clips slow together), scram (dead-dark + amber, frozen) and
a restart path that restores what scram zeroed.
- buffer tanks show fill from their share of bandwidth.stored / bufferCap.
- AnimationMixer plays clip 0 looped; rigged GLBs clone via SkeletonUtils so
instances don't share a skeleton.
- exact cargo interpolation via BeltItem.id, order-matching kept as fallback.
- multi-mesh belt GLBs merge with groups (2 materials, 1 draw call) instead
of rendering only the first mesh.
MachineDef.color is wired to the BODY, not the accent, against the letter of
the orders: all 21 values DATA authored are industrial chassis neutrals per
codex/§8, and wiring them to the emissive makes every machine glow muddy and
kills the two-material rule. Flagged in NOTES for the orchestrator to settle.
500 entities + 2,000 items still at 3.6ms/frame (4.6x headroom), 5 draw calls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the render stub with the full M1 surface:
- camera: ortho iso rig, wheel zoom, middle/right-drag + WASD pan, resize
- ground: shader tile grid w/ world-edge dissolve + screen-space vignette
- registry: procedural placeholders (two-material rule) + MODELBEAST GLB
hot-swap, probed on init and every 10s in dev. GLBs auto-normalise to
the machine footprint, so any export scale lands correctly.
- belts: InstancedMesh per belt def, chevron scroll injected into a
MeshStandardMaterial so belts keep lighting/fog/brownout
- cargo: InstancedMesh per item type, interpolated across ticks via alpha
- ghost + pickTile with footprint occupancy (cyan valid / red blocked)
- feedback: jam klaxon blink, brownout dims the scene via tone-mapping
exposure so emissives dim too
Machine accents are derived from data (recipes -> outputs -> ItemDef.color),
with a legibility floor: near-black products like MDAT ORE would otherwise
render the extractor's CRT head as a black panel and its ore as invisible.
Verified in the dev build: 500 entities + 2,000 belt items at 3.2ms/frame
(5 instanced draw calls); a GLB dropped in mid-session swaps without reload.
Dev scaffold is DEV-gated and tree-shaken from the prod bundle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>