Providers write cache files and logs into .gev-cache and .gev-logs while the app runs. A serve-only standalone plugin adds both to server.watch.ignored, so the dev watcher no longer stats them; source changes still reload.
Route tleCatalogNumber() and noradIdFromSatnum() through one decoder that
accepts only plain digits or a valid Alpha-5 field. parseInt and Number()
read '2554A', '255 4', '-1234', '0x1F0', '1.5' and blank as numbers; they
now return null/NaN. Digit satnums of any length still decode, so OMM
satrecs numbered past 99999 keep working.
Add a layer test that several Alpha-5 satellites survive ingestion dedupe,
the changelog fragment for #767, and note in CURRENT-STATE that this is
Alpha-5 TLE compatibility and malformed fields are rejected.
World Packet #880 removes the duplicate tracking table from gevActions; the Cockpit refusal source-scan test should inspect the actual exported source of truth instead of assuming the previous file position. Fix failing Node 24 exact-head CI without duplicating runtime definitions.
Reuse one context/contacts/tracking owner in voice and World Packet. Compare voice outputs after stripping presentation fields; remove the unconsumed fingerprint API pending an actual caller. Document the exported packet boundary and reject null options safely.
Review guidance: asturksever on origin #880; Windows parity diagnosis by quanticsoul4772. Existing source ownership retained.
CONTRIBUTING.md said "Only a couple (`qa:map-source-tray`, `qa:transit`) have
an `npm run` alias". package.json defines five: `qa:map-source-tray`,
`qa:panel-resize`, `qa:street-level`, `qa:street-level:fixtures` and
`qa:transit`.
The two missing names are not incidental -- .github/workflows/ci.yml already
invokes `npm run qa:street-level:fixtures` and `npm run qa:panel-resize`, so a
contributor reading the guide is told to reach for `node scripts/<gate>.mjs`
for gates the project itself runs through npm.
Verified against package.json scripts and .github/workflows/ci.yml on main
(1df2a27).
render/navara.js: one always-on-top engine.movers chevron bank (atlas of
every chevron icon at 32 px), MMSI pick ids, trail on engine.lines,
camera reads through the shared Navara layer view (extracted from the
aircraft renderer to src/layers/shared/render/navaraView.js, + camera
pickEllipsoid and canvas clientWidth). Registered in navaraMode.
QA: vessel qaDrawn; probe selected() falls back to getSelectedInfo;
qa-w1-layers vessel section; qa-vessels-engines side by side; --engine
for qa-vessel-cards/datum; qa-flights-engines military near pose 100 km.
Unit tests on the fake engine pass; browser runs NOT done (see progress).
Reconcile #880 with current main. Delegate the view-state builder while keeping enabled-only layers, disabledLayerCount, provenance, context semantics, and existing voice behavior. Add parity and roster-read regressions; retain package export, boundaries and changelog fragment.
Preserve original GEV voice, layer and packet contributor credit.
Carry reviewed #816 onto current main without conflicts; preserve i18n updates, replace obsolete changelog edit with a fragment, and add a constructor-wiring regression alongside the owner and rail tests.
Credit: raysung-2026 (report), asturksever (review), quanticsoul4772 (Windows diagnosis).
T11 review follow-up to ed9ea7e6. CPU hits rank as the engine draws them:
sets without a depth test over depth-tested ones, then by set order
(the tracked bank over the fleet, flights over local ADS-B), then depth —
so the CPU's top hit that checks a GPU answer is the instance drawn on
top. A model hit is no longer taken as answered: the model mover keeps
each instance's drawn diameter (after minimumPixelSize/maximumScale) and
the CPU checks the hit against its projected position within that radius
(+3 px); the CPU pick sees models at that radius too.
Review follow-up on #975. The shared same-site gate refuses any forwarding header, which is right for routes that spend a key, but terrain is keyless and needed for rendering: behind the reverse proxy the README documents, every /api/terrain/heights chunk got 403 and fell back to the geoid. Terrain now uses admitSameSiteKeyless, which keeps the Sec-Fetch-Site and exact-Origin checks (comparing Origin against a single X-Forwarded-Proto scheme) but does not refuse forwarding headers. The shared admitSameSite gate is unchanged for every other route. The changelog entry moves to changelog.d/975-terrain-cross-site-gate.md.
Co-authored-by: daikaginza <[email protected]>
src/layers/vessels/render/cesium.js holds the Cesium objects the layer
built itself, one for one: the translucent BillboardCollection of
chevrons (centred, screen-aligned, never depth-tested), the horizon
occluder, window projection, canvas size, viewer.trackedEntityChanged,
and the trail (data/trailRenderer's entity polyline, kept on Cesium: the
engine.lines Primitive path did not draw below the photoreal mesh in
round 6 — the plan's T13/T15 blocker; flights does the same).
The logic imports no Cesium: geo math, Rgba WHITE, the chevron artwork in
icons.js, clicks through the engine's selection dispatcher (own-rule
owner, same rule). Registered as CESIUM_LAYER_RENDERERS['ais-live-vessels'];
src/layers/vessels joins the boundary rule.
W1 replay vs 7c7422e2: vessels/flights/military/localAdsb counts, known
objects, screen points, requests and shot sha256 identical.
qa-vessel-cards --data synthetic 2/2 and qa-vessel-datum (?qaFeed=
vessels:fixture) 4/4, the same as 6eec8f6c.
Tests moved with the code (same meaning): cameraHandoff (the click body
is handleClick), inputOwnership (the guard precedes the click rule's
read of the pick), renderers.test (vessels in the extracted list),
importDirections (an unmoved example layer is satellites), the
ownership services fixture (renderer service).
Vessels' click rule (sibling ownership, cyclone background, card hit
test, unkeyed records) does not map onto the plain or look-under rules:
an owner with onClick(ctx) gets every click with the top pick, no gesture
rule (its old LEFT_CLICK handler), and is another layer to the rest.
getNearby returns the contact's label as `id` (the callsign when it has
one) and its key as `icao24`; the drawn rows are keyed by icao24, so the
model lookup missed and every contact was measured at its sprite. Under a
3D model that sprite is hidden and keeps the pre-floor height by design
(T7): the "buried at -27 m" contacts on Cesium (the geoid at AUS) were
those hidden sprites, at HEAD and on 7c7422e2, whose script measured every
sprite. The Cesium report also gives each contact's model state and the
floor cell the layer reads.
AUS, 100 s after enabling flights, both engines: 3 low contacts, 0 buried;
N3752 / DAL848 drawn by their models at 130.2 / 135.4 m over a 123.5 /
128.6 m mesh, the DEM-prior cell warm (123.5 / 128.6 m).
The instance colour (sRGB, as Cesium takes colours: the military amber
#FFB800) was mixed into the linear material colour as is, so a tinted
model drew paler and brighter than Cesium's: the military footprint gate
read 124 % (more pixels cleared the contrast threshold over water) and
the median luminance +9 %. White (flights) is the same either way, which
is why the flights gate passed. The tint is now sRGBTransferEOTF-decoded,
as the sprite sets already decode theirs.
qa-flights-engines' model gate adds the highlights: the p90 luminance of
the model pixels within ±10 % of Cesium, with the near-white pixel count
reported (10b review low 2).
Models on, near pose (computed scale ratio ~1.0000 on both):
- military (from 100 km): footprint 9,902 vs 8,610 px (115 %), median
luminance 158.9 vs 155.3, p90 190.9 vs 184.5 — 18/18;
- flights: footprint 104 %, median 189.8 vs 196.7, p90 223.1 vs 247.8
(near-white px 83 vs 510: Cesium's white models saturate where Navara's
tone mapping rolls them off) — 20/20.
Models off: flights 16/16, military 15/15. Side-by-sides regenerated.
- The DEM prior column read a fresh import of src/data/groundFloor.js, a
module the app does not use for its layers (they read the scene's
surface services), so it was null for every contact. It now reads
window.__godsEyeView.surfaceServices.groundFloor. The terrain proxy
answers 200 and the AUS cells resolve within one or two polls (123-128 m);
the "proxy 503" reading in the task-11 report was this misread.
- A contact a 3D model draws is measured at the model's translation (the
probe's drawn() reports it now): its sprite is hidden and keeps the
pre-floor height by design (T7), so measuring the sprite reported a
buried aircraft that is not drawn.
Navara 0.2.1 can answer a click with the previous gesture's pick. The
check let that answer through when its instance was drawn within twice its
pick radius of the click — the followed aircraft at the centre beside the
clicked one (the 20/24 flights checklist run: a click selected the
previously followed aircraft). A GPU answer for a sprite or point set now
has to be drawn under the click (no slack) and be the instance the CPU
pick finds on top there (lines left out: they are not in the GPU pick);
otherwise the CPU pick answers. Models, which the CPU pick does not see,
are still taken as answered. The CPU drill takes `includeLines`.
Test: 20 gestures alternating a click on A and a click on its neighbour B
answered with A's stale pick — B every time. In the app, 40 scripted
click/follow/release gestures on Navara selected the clicked aircraft
every time with and without the fix (the stale answer is rare).