The panel's window label becomes a choice of the server's window and each
shorter one. The feed and map filter to it locally; the hotspot counts are
read again for it (/api/news/hotspots?hours=N, now on the allowlist). A
server names the longest window it serves as maxWindowHours.
Outlines move to geometry version 4: the news server now follows Natural
Earth's own border vertices instead of a coarse grid, and the new version is a
new cache entry. A severity a reviewer set (severityBy 'label') is kept as such
instead of reading as the rules'.
A host may serve fewer hours than the day. The hotspots answer may name its window
(`windowHours`, a whole number from 1 to 24); the layer keeps reports, the
feed, In view and the chosen event inside it, and the panel says
"Last 12 h" or "Last 24 h" accordingly. Without a window named, or with one
out of range, the layer keeps the full day as before.
The news layer brought its own ColorBrewer yellow, orange and red, solid
coloured marker discs, a coloured edge on every card, an amber developing
ring and pink disputed areas, which read as foreign next to GEV's cyan glass.
Severity now uses colours GEV already has (dim and primary text, the military
layers' amber, the Cockpit's emergency red), drawn as GEV's dark disc with a
severity rim and icon; attestation is still the rim's form. Cards lose the
coloured edge and name significant and major events in a mono badge;
attestation chips follow the status badge; outlines stay in the accent family
with disputed areas dotted in the primary text colour.
From review of the news layer:
- An event's other sides older than 24 hours (or undated) are no longer
listed, and a report dated more than 15 minutes ahead is outside the
window, as in the regional brief.
- Picture cards are one canvas per event in a bounded cache (24), repainted
in place when the age changes, with each card's picture dropped with it;
the age in the key had made a new canvas every minute.
- The feed list drops reports that leave the window and is capped at 600.
- "In view" is filtered from the reports the layer already holds; it reads
the feed only with minor news on, once per refresh, never per pan.
- Infinite scroll restarts after a filter change or a failed read.
- The two filter selects stack, so "Significant and above" is not cut off.
- The timeout tests hold the event loop until aborted, so they pass on
Node 22 as well.
`./server/providers/news` (node) with its own package boundary, so a host composing its own local providers can serve /api/news from GEV_NEWS_ORIGIN as Core's standalone server does.
Events ▸ News draws the last 24 hours of reports from curated hotspots
(Ukraine–Russia, Israel–Gaza–Lebanon, Iran–Hormuz, Yemen–Red Sea, Sudan,
Sahel) and developing situations elsewhere, from any server that answers the
`/api/news` read routes.
- Globe: one marker per merged event, clamped to the ground and culled at the
horizon; one beacon per hotspot when zoomed out and a pulsing beacon for a
developing situation; hotspot outlines with disputed areas dotted and
labelled by who administers and who claims them; picture cards for at most
ten major or fast-growing events with two or more sources, never
overlapping, switchable off.
- Panel: hotspot chips, a severity filter (significant and above by default),
categories, minor news off by default, and a scrolling list of event cards
with picture, headline, place, sources, age and the sides that reported it.
"In view" lists what is near the map below 3,000 km once the camera
settles. A card flies the globe to its event and opens it with a link to
the publisher. Reduced motion stops the pulse and the flights.
- Core serves no news itself: the local server proxies GEV_NEWS_ORIGIN when it
is set, and answers 503 unavailable otherwise, so the layer reads "not
configured" once instead of retrying.
- Share token 9 (enabled-only); voice stays off for this layer.
The pure half of a news layer: validated records for a news server's
`/api/news/hotspots|feed|outline` contract, a presentation model and canvas
markers and picture cards, and a fetch client.
- Colour carries severity only (0 no physical event, 1 minor, 2 significant,
3 major), never a side; the category is the icon, the rim is attestation
(confirmed, a claim, one side's own press), size grows with sources and
markers fade with age.
- Cards say "Reported by {side} sources" and mark official channels; a
machine-read English headline is labelled as such.
- `createNewsSource` reads same-origin routes with a 15 s timeout, a 4 MiB cap
and record-by-record validation; `NEWS_API_PATHS` and `newsQueryAllowed`
let a host proxy exactly what the client sends. A 503 marked unavailable
means "not configured": no retries.
- Exported as `./layers/news/source`, with its own package boundary.
Regional News showed "REGIONAL NEWS UNAVAILABLE" above populated rows and a
static "RECENT" footer over months-old articles. The status banner kept
`display: grid` when hidden, every non-empty answer carried the unavailable
text, and nothing limited or sorted articles by age.
- One window (regionalNewsWindow.js, 24 h): the local proxy asks Google News
with `when:1d` and GDELT for 24 h, drops undated, older or future-dated
articles, sorts newest first, and reports newsWindowHours/newsFetchedAt.
- The Cockpit labels four states: fresh (banner hidden, "LAST 24 H"),
kept after a failed refresh ("CACHED · REFRESH FAILED"), no news in the
window, and unavailable. The footer lives in the news state, so it
survives page and tab changes, and the client drops out-of-window rows.
- `.cockpit-brief-status[hidden]` now hides the banner.
Riding an aircraft now adopts its layer the way a direct selection does, and
Contacts gives up a dependency the user adopts, so ending Contacts mid-session
(one of its layers off, or Contacts itself) no longer turns off the ridden
layer and ends the Cockpit. When Contacts goes off, Live Signals drops the
rows built from its snapshot instead of leaving stale distances marked
CURRENT, and the feed-off warning is no longer duplicated.
Name each Rio feed in its credit instead of repeating the licence, drop the
deprecation history from the bus note, list Rio among the feeds with a
route-name table, and shorten the route-table header and test comments.
Both SMTR feeds now publish Position.speed in m/s. Compared with how far
vehicles moved between reports on 2026-11-05, the published values ran
3.1x (buses) and 3.6x (BRT) below the observed speed, so the km/h
conversion divided real speeds by 3.6. Drop speedUnit and the conversion.
SMTR's realtime feeds carry internal route keys, so a Rio card read
"Route O0731AAN0A" where riders know line SN731. Join both feeds to the
route_short_name in SMTR's static GTFS routes.txt (CC BY 4.0, same
publisher and terms). The keys cannot be parsed: O0014AAA0A is LECD135.
A 2026-11-04 snapshot found all 282 bus and 21 BRT routes in service in
the table; an unknown key still falls through raw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cockpit entry no longer needs Contacts or both flight feeds: a civilian
aircraft needs Live Flights, a military one Military Flights. Contacts and
every other layer can be turned on or off before or during a session, and
turning off the ridden layer ends it. A Context mode change in flight still
blocks entry.
When the other air feed is off, Live Signals and the Contact card say
FLIGHTS FEED OFF or MILITARY FEED OFF · PARTIAL PICTURE instead of
presenting a partial picture as complete. Voice refuses entry with
subject-layer-off rather than contacts-inactive, and its tool description
says Contacts is not required.
Double-clicking the followed aircraft enters Cockpit through the same gate.
The Cockpit takes the scene's double-click before Cesium's stock handler,
which would otherwise untrack a followed aircraft whose model is a
primitive. The entry also shows under the Intel HUD readout, sharing the
Contacts button's face. A test keeps the classes the Cockpit adds to the
body from matching another element's rule.
Arabic catalog strings carry optional marks ("تتبّع"), but people type
without them, so "تتبع" found no suggestion. Fold the marks out of both
the draft and the candidates before comparing.
- Host test switches AI Provider from chat Settings through the real
provider commands and checks the new mount keeps chat's context, frame,
Back to chat and focus on the provider choice.
- Drop the open and minimized branches of the carried presentation: the
provider choice lives only in Settings, so chat is never open then.
- One showChatSettings helper for the gear and the restore, and one
isStoppable helper for the live-or-error check in chat and the panel close.
Split the Cockpit camera update into the aircraft's own front half and a
shared placeCamera that reads the eye's forward and up offsets, pitch and
ground clearance from a profile. The aircraft profile carries the existing
constants, so the aircraft view is unchanged; other subjects can now supply
their own eye.
Resolves the DATA_SOURCES.md conflict by keeping main's rewritten Transit
and Radio bullets and restating the count for this branch: eighteen feeds
covering seventeen regions (the two Rio feeds share one region).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Switching AI Provider in Settings opened from chat rebuilt the voice
control, so Settings fell back to voice and the dock went idle, widening
the wings. The switch now carries chat's Settings, or chat itself, to the
new provider as it already carries the input mode; the conversation still
starts fresh and focus stays on the provider choice.
After a voice error, opening chat or closing the voice panel left the dock
red on ERROR, because both stopped only an active session. They now also
end a session left in error, which returns the dock to idle.
The quick commands "Reset to globe view" and "Show earthquakes" reached t()
through a .map(), so the catalog check never saw them and every language
showed them in English. They are now marked with msg() and translated.
Review of the 71 strings from #1507 in all eleven languages:
- zh-Hant is regenerated from zh-CN with OpenCC s2tw, as its guide says;
40 entries had Taiwan vocabulary instead.
- ar "Dock to the right" names the left side, where RTL puts that rail.
- ja "What am I looking at?" no longer asks what the assistant sees.
- Provider Settings, dock, provider, live and map use each glossary's terms.
- de drops the du-form; ja drops spaces between Japanese and Latin text.
- Calques, register and the example commands read naturally.
A poll that returned the same stale snapshot dropped STALE from the
Contacts cohort until the next answer, because the in-flight loading flag
outranked stale and the source revision ignored the provider name. A
source that has answered now reads its status without the loading flag;
one that has never answered (AIS first connect) still reads as loading,
so it shows no STALE before any snapshot exists.