1
0
This repository has been archived on 2026-08-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
karti 285b5b19e7 fix: the merged board's live feeds, and two instruments it could not be judged without
An ultracode investigation mapped the single-board work across five parallel
readers and three adversarial reviewers. It found things this session would have
walked into, and two of them are fixed here.

**THE MERGED BOARD WAS SHIPPING WITH THREE FEEDS SILENTLY OFF.** Live ADS-B and
live weather were gated on `id !== "california"` — "not the coarse statewide
board", correct the day it was written, since live aircraft over a board at
1,919 m to the unit are a glyph problem and one station cannot speak for a
thousand kilometres of coast. `cities/unify.ts` then built a board that is the
whole state AND metro-detailed, keeping the `california` id deliberately so the
fire gate, the ladder's region table and every `?city=` deep link keep working.
It inherited a gate meant for something else. Measured before the fix: the
`#source` badge read `""` on the merged board and `live weather · live traffic`
on the Bay Area's. A defect that reads as "it feels less alive" and never as an
error.

`carriesMetroDetail(city)` asks the pack instead: `focusRegions` is the honest
predicate and needs no new field, because the coarse state pack declares none
and every pack with ground worth drawing at metro resolution declares one.

**AND ASKING WAS NOT ENOUGH, BECAUSE THE FEEDS ARE PER-METRO.** With the gate
fixed the board asked — and was refused: `GET /flights?lat=37.30&lng=-119.25&
radiusNm=402 → 400 bad_request, "Nothing this deployment serves is near
37.3,-119.25"`. Correctly: `regionOf` derives its circle from the board's bounds,
which on a statewide board is 402 nautical miles centred on the middle of the
state, and what the deployment serves is San Francisco and the Southland, five
hundred and sixty kilometres apart.

`mergedTraffic` asks for both. In `adapters/http.ts` and not `engine/flights.ts`
for the reason `TrafficSource` itself lives there: the engine draws darts at
coordinates and has no business with provenance, and every interesting part of
this merge is provenance. De-duplicated by id, because overlapping circles both
see the aircraft between them and `flights.ts` measures a track's span from
repeated observations — a duplicate is not merely a double image. `live()` is
`some` and not `every`, so one dark metro does not make the other's observed
traffic claim to be simulated. Verified: `?lat=37.77` → 200 live, 24 aircraft;
`?lat=33.82` → 200 live, 15 aircraft; `#source` now reads `live traffic` on the
merged board and stays `""` on the coarse one.

**TWO INSTRUMENTS, BOTH BECAUSE THIS SESSION KEPT FAILING WITHOUT THEM.**

`scripts/performance-budget.mjs` gains a `california-one` cell. Until now the
only way to measure the merged board was to hand-edit the `california` cell's
query, run, and edit it back — done six times in one session, which is exactly
the procedure that gets half-done. Its `ready` asserts `#sea-section`, not just
the signature chapter: `california-overview` is on the coarse board too, so a
cell whose `?one=1` quietly stopped working would measure the coarse board and
pass. No ports, no section, no readiness. Caps are RECORDED from its first run
with headroom, in the same spirit as bay-area and socal — they were briefly
copied from `california` and that is wrong for the same reason that cell's
numbers are wrong for this board. **No existing cap was raised.**

`scripts/look.mjs` gains `--lat/--lng/--standoff/--height`. Every aim in this
harness goes through a control a reader also uses, which is right and stays the
default — but it means a board can only be photographed where a chapter already
points, and the merged board carries the state pack's six: the whole state, the
north, two corridors, two doors. None is near a city. The board exists to put
cities on the state and there was no way to photograph one; three attempts by
clicking the minimap and guessing wheel notches landed in open ocean twice and
on empty coast once. The seek moves the camera and nothing else.

**A regression the new cell caught within one run.** The first version of the
marker fix gated on bounds alone, like the office doors. The coarse state
board's rectangle contains San Francisco, so it picked up forty-four company
markers it has no business drawing at 1,919 m to the unit: 373 draw calls → 417.
Now gated on `carriesMetroDetail` as well, and `california` measures 372,415
triangles / 373 draws — identical to before this commit.

All twelve budget cells pass. 1,705 tests pass.

Recorded for the next round, from the review: **SoCal's two focus rectangles
overlap by 1.7 x 4.6 km** (verified: lat 34.075–34.090, lng −118.300–−118.250),
so any per-rectangle terrain tier must clip them to a disjoint cover first or it
draws that ground twice. Today's per-axis lattice is what hides it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 04:16:33 -07:00
2026-08-19 03:06:01 -07:00

Tera

The map view of Lumbridge Simulate — California from above, in three.js. Its other half, Spaces, is the offices you walk into: one engine and one asset library, seen from outside and from inside.

Apache 2.0. Runs at tera.lumbridgecorp.com.

San Francisco


What it is

An engine plus data packs. The default board joins Los Angeles and San Francisco with live deterministic traffic on US-101 and on the honest I-5 → I-580 → I-80 approach. Choose either route chapter to follow the procedural black Model X.

The engine renders terrain, coastline, built cities on authored street grids, bridges, roads, markers, road traffic and air traffic. A city pack is pure data — coastlines, hills, districts, landmarks, camera chapters — so adding a city is a data contribution anyone can review, not a fork.

California, the detailed Bay Area, and Los Angeles / Orange County / Riverside ship today. The corridor is intentionally sparse; detailed cities remain their own boards rather than forcing a 600 km world into one full-resolution mesh.

A plan view sits top right: the board drawn flat, with the footprint of the camera's own frustum on it, so you can see where you are looking from outside the shot. Click or drag it to move the camera; scroll it to dolly. It is a 2D canvas rather than a second WebGL context, drawn from the same city pack, and it follows the sun into the night along with everything else.

Who sees what

Three tiers, resolved once at boot by src/access.ts:

anonymous signed in admin
the map, the plan view, the named chapters
observed weather and live aircraft
the office public depth — shell, furniture, viewpoints, nobody home full depth, with presence full depth
the marker feed per TERA_MARKERS_ACCESS
the godmode panel (G) — date, season, weather override, counters, pose editor

The sky is public on purpose. Cloud cover over San Francisco is a government sensor reading, and the aircraft are broadcasting their positions unencrypted to anyone with a receiver; neither is something an account can grant you access to. Gating them cost the only moment that makes this project land — real fog rolling off the Pacific onto a city you recognise, at the real time of day, on a first visit.

The markers are the one feed that can carry something private, so the server decides. TERA_MARKERS_ACCESS is members by default and an operator has to say public out loud, which /api/v1/health then announces in degraded[]. The default is the safe answer rather than the common one, because the failure mode is silent: nothing errors, nothing looks broken, the data is just readable by the internet.

These are drawing decisions, not a security boundary, and src/access.ts says so at length. Live data and office presence are withheld by the API, from a caller it does not recognise; the client tier stops the app asking for something it will not get. Admin is granted only by TERA_ADMIN_SUBJECTS on the server — never inferred in the browser, and never from an API that failed to answer. A deployment with no API at all is open, because "clone it and it works" is the promise; it is not "clone it and you are an administrator".

Quick start

npm install
npm run dev

Play controls

The bottom mode dock is the local-player source of truth: View, Drive, Explore, Fly, or office Walk. A transition clears stale held input and atomically hands the follow camera to one subsystem. WASD is movement; Q/E is vertical or yaw, I/K pitches the crow, Space is the primary action, G glides, P resumes assistance, R resets, and C switches the driving camera. A standard gamepad maps both sticks, triggers, shoulders, and rising-edge action buttons.

Touch play uses a pointer-ID analogue stick at lower left and only the actions that apply to the current mode at lower right. The Map button remains available during possession. Touch, keyboard, and gamepad state are independent, so a released or cancelled finger cannot clear another source that is still held. The UI and follow camera are presentation adapters only; they never enter Arena observations, rewards, snapshots, traces, or simulator hashes.

Headless RL environments

Tera also exports a versioned, renderer-independent Arena contract with five deterministic environments: US-101/I-5 driving, Frontier Valley office navigation, seeded SF/LA office robot jobs, crow waypoint flight, and California electric-aircraft flight. They share the client controllers and office plan, but require no canvas, DOM, Three.js scene, network service, or new runtime dependency.

Import them from @lumbridge/tera/arena. Seeded train/dev scenarios, component rewards, safety terminals, maximum steps, snapshots, checksummed traces, exact replay and executable inaction/scripted baseline proofs are documented in ARENA.md.

The visible SF and LA office robots use that same fixed-step job state. Their patrol, parcel, inspection, and charging loops are authored demonstration scenarios—not presence, telemetry, or evidence of real company work—and the UI labels them as a seeded simulation.

Using the engine

import { createScene } from "@lumbridge/tera/engine/scene.ts";
import { createStage } from "@lumbridge/tera/engine/stage.ts";
import SAN_FRANCISCO from "@lumbridge/tera/cities/sf.ts";

// One stage per canvas, for the life of the page. Cities are put on it and
// taken off again; a renderer per city leaks its shadow map on every switch.
const stage = createStage(canvas);

const scene = await createScene(stage, {
  city: SAN_FRANCISCO,
  markerPalette: { hiring: 0x4ade80, closed: 0xef4444 },
});

scene?.setMarkers([
  { id: "1", lat: 37.7765, lng: -122.4241, label: "Somewhere", colorKey: "hiring" },
]);

createScene is async because the heightfield is built in a Worker — half a million samples, about 730 ms on the Bay Area, and not on the main thread. It resolves to null if the build was abandoned through options.signal, which is what makes switching city mid-build cheap.

The engine renders Marker[] and looks colours up by colorKey in a palette you supply. It does not know what your markers mean — that mapping lives in your adapter. This is what lets one renderer serve a private map coloured by one scheme and a public map coloured by another, without either being a fork.

Adding a city

Write src/cities/<id>.ts exporting a City. Trace the coastline and parks by hand, place hills as radial peaks, and give each district its street bearing.

Two rules, and they are not stylistic:

  • Do not import geometry from OpenStreetMap. OSM and Nominatim output is ODbL — share-alike, and incompatible with this repo's licence.
  • Do not commit logos or brand assets. They are trademarks, not code.

See ARCHITECTURE.md §3 for the full reasoning, and NOTICE for the attribution and data-provenance statement, and PROVENANCE.json for the machine-checked shipped-artifact and original procedural-lineage ledger. Run npm run provenance, npm run licenses, and npm run sbom before accepting assets or dependencies.

Aircraft

The engine takes a FlightSource. Two ship here: SimulatedFlights (original, flies real approach and departure corridors) and AdsbFlights (open community ADS-B feeds such as adsb.lol).

FlightRadar24 is deliberately absent — their terms forbid scraping and forbid redistributing their data, so a client for it cannot live in an Apache-2.0 repository. Commercial sources belong in private deployments. The best long-term answer is an RTL-SDR receiver: first-party data with nothing to comply with.

Layout

src/engine/    renderer — terrain, blocks, structures, markers, flights, scene, minimap
src/cities/    data packs — pure geography, no code
src/transport/ serializable route packs and renderer-independent simulation
src/arena/     versioned headless RL contract, scenarios, traces and environments
src/assets/    original procedural asset library
src/adapters/  where outside data plugs in
src/tools/     instruments — god-only, dynamically imported, never statically

engine never imports cities; neither imports adapters.

Nothing under src/tools/ may be reached by a static import from the app. It is loaded by one await import() behind access.can.debug, so a visitor who is not an admin does not download the code at all — which is the strongest available reading of "nothing here runs for a non-god visitor": not a hidden panel, not a disabled panel, no panel. src/tools/index.ts states the rule and what silently undoes it.

Licence

Apache License 2.0 — see LICENSE and NOTICE.

The ordered build plan and parallel work lanes live in BUILD_PLAN.md.

S
Description
Immutable Apache-2.0 Tera baseline through 2026-08-24; current development is proprietary.
Readme Apache-2.0 9 MiB
Languages
TypeScript 93.3%
JavaScript 5.3%
HTML 1.3%