mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge upstream main into feat/tools-area-breakdowns
Keep this branch's CHANGELOG entry above upstream's; upstream main no longer lists the GBFS station-name entry an earlier merge carried here. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
commit
e312a007ab
97 files changed
+10951
-1371
No files matched your search
+1
-1
@@ -158,7 +158,7 @@ routing and regional caches. Request parameters cannot override these endpoints.
|
||||
Voice controls accept an action runner and a controller factory through
|
||||
`createVoiceCommands` (`./voice/commands`). The default Realtime controller owns
|
||||
microphone tracks, playback, push-to-talk, tool cancellation and radio handoff.
|
||||
Its backend supplies `requestToken({ tier, signal })` and
|
||||
Its backend supplies `requestToken({ tier, authMode, signal })` and
|
||||
`negotiate({ offerSdp, credential, signal })`. The Realtime-compatible adapter
|
||||
(`./voice/realtime-backend`) accepts separate token and connection transports
|
||||
and endpoints. Only the short-lived client secret reaches the SDP endpoint.
|
||||
|
||||
+138
-8
@@ -405,6 +405,9 @@ camera moves with easing, duration and holds. Playback and seek share one
|
||||
coordinate sampler; navigation/manual input revokes authored motion and pending
|
||||
holds. Anchor heights and explicit endpoints require the WGS84 ellipsoid
|
||||
reference. Legacy projects retain their ordinary flights, content and edits.
|
||||
Seeking between ordinary camera poses uses the shortest longitude arc across the
|
||||
dateline while preserving both authored endpoint longitudes, and turns heading
|
||||
and roll the short way for any authored angles.
|
||||
See [camera directions](DIRECTOR-CAMERA.md).
|
||||
|
||||
Realtime voice composes separate connection, response/tool, Radio handoff, input
|
||||
@@ -920,6 +923,24 @@ owners. Tuner calculations have a pure entry, with existing layer exports
|
||||
preserved. Destruction removes listeners and state subscriptions before ending
|
||||
tuning; a delayed Enable result cannot reveal or refocus removed controls.
|
||||
|
||||
## NYC DOT TMC CCTV source pack
|
||||
|
||||
The CCTV catalog can add New York City traffic cameras from the NYC DOT
|
||||
Traffic Management Center. NYC DOT requires developers to sign a data-sharing
|
||||
agreement for the camera feed, so this is the one opt-in pack: it loads only
|
||||
when `CCTV_NYC_ENABLED=1`, and with the flag unset the server makes no NYC
|
||||
request. NYC DOT's requested disclaimer is in the Data attribution popover.
|
||||
When enabled, the server reads the keyless
|
||||
camera list at `https://webcams.nyctmc.org/api/cameras` and keeps cameras the
|
||||
feed marks online. Frame URLs are built from each camera UUID under
|
||||
`https://webcams.nyctmc.org/api/cameras/<uuid>/image`; they are never taken
|
||||
from the payload. There is no heading in the feed, so gizmos use the shared
|
||||
id-hash fallback at low confidence.
|
||||
|
||||
Once enabled, the 250 cameras nearest the five borough cores load.
|
||||
`CCTV_NYC_MAX_SOURCES` sets the pack cap (8–400). The catalog-wide ceiling stays at 4,000 and is shared
|
||||
round-robin, so adding this pack does not silently drop another region.
|
||||
|
||||
## DriveBC CCTV source pack
|
||||
|
||||
The CCTV catalog adds DriveBC highway cameras for British Columbia alongside the
|
||||
@@ -1001,6 +1022,8 @@ and sharpen. Display supplies actions and renders settings; effect execution has
|
||||
no DOM dependency. Existing presets and the 500 ms transition remain unchanged.
|
||||
Stopping the controller revokes animation before asynchronous UI teardown; final
|
||||
destruction removes its stages and restores the borrowed bloom configuration.
|
||||
Snow's sideways sway stays within a fixed range at any session age; Wind scales
|
||||
its amplitude.
|
||||
|
||||
## Display control ownership
|
||||
|
||||
@@ -1035,6 +1058,9 @@ Automatic collapse remains presentation only, prioritizes the latest explicit
|
||||
panel, and honors keyboard focus on the right. Mobile layout still releases
|
||||
desktop allocation styles. Stable Display allocation avoids unnecessary style
|
||||
writes. This extraction does not change panel positions or layout defaults.
|
||||
The right rail skips panels hidden by other CSS (computed `display: none`), but
|
||||
keeps the collapsed panels its own exclusive presentation hides, so automatic
|
||||
collapse can still be undone.
|
||||
|
||||
## Surface keyboard lifecycle
|
||||
|
||||
@@ -3077,7 +3103,7 @@ its criteria cannot be silently ignored.
|
||||
| Satellites | CelesTrak | `src/data/satellites.js` | `/api/celestrak` | 120s |
|
||||
| Space Missions (30d) | Launch Library 2 + CelesTrak | `src/data/rocketLaunches.js` | `/api/launches` + `/api/celestrak/active` | 5 min |
|
||||
| Traffic | Selectable TomTom / OpenStreetMap / Hybrid roads; optional TomTom flow (BYOK) | `src/data/traffic.js` | browser-direct OpenFreeMap tiles; `/api/tomtom` for flow | viewport-driven; capped tile cache |
|
||||
| CCTV | Austin + Caltrans (CA) + TfL London + Ontario 511 + Fintraffic (FI) + DriveBC (BC) + TxDOT (TX) + Estonia (Tallinn, Tarktee) + Live Traffic NSW + Open Calgary Open Data + Statens vegvesen (NO, stills + live HLS) + Street View fallback | `src/data/cctv.js` | `/api/cctv` | 10s (active) |
|
||||
| CCTV | Austin + Caltrans (CA) + TfL London + Ontario 511 + Fintraffic (FI) + DriveBC (BC) + TxDOT (TX) + Estonia (Tallinn, Tarktee) + Live Traffic NSW + Open Calgary Open Data + Statens vegvesen (NO, stills + live HLS) + NYC DOT TMC (opt-in) + Street View fallback | `src/data/cctv.js` | `/api/cctv` | 10s (active) |
|
||||
| Radio | Radio Browser (public-domain station directory) | `src/data/radio.js` | `/api/radio/stations`, `/api/radio/click/:uuid` | 45 min directory refresh |
|
||||
| Transit 🚌 | Operator GTFS-Realtime VehiclePositions (7 keyless regions, `src/data/transitFeeds.js`) | `src/layers/transit/` via `src/app/layers/transit.js` | `/api/transit` | 15s (poll + delayed playback) |
|
||||
| Bikeshare 🚲 | GBFS (Lyft + BCycle) | `src/data/bikeshare.js` | `/api/gbfs` | 60s |
|
||||
@@ -3102,8 +3128,8 @@ meaning), one viewer host and one on-globe credit per active provider. Each
|
||||
provider draws in one colour (`PROVIDER_COLORS` in
|
||||
`src/layers/streetLevel/policy.js`); 360° cones are rings and the selected
|
||||
sequence is GEV cyan. Share options: `m` (Mapillary), `r` (the other providers' switches by id,
|
||||
e.g. `google-1` for Street View), `p` (`a`/`p`/`f` panoramas), `s` (since, days). Mapillary and Google
|
||||
Street View are registered. Without
|
||||
e.g. `google-1` for Street View), `p` (`a`/`p`/`f` panoramas), `s` (since, days). Mapillary, Google
|
||||
Street View and KartaView are registered. Without
|
||||
`MAPILLARY_CLIENT_TOKEN` the panel reads KEY REQUIRED and the controls are
|
||||
disabled. With it, coverage draws as z0–5 overview points from orbit and z11–14
|
||||
sequence lines below 60 km; the proxy strips the unused `image` layer from z14
|
||||
@@ -3154,9 +3180,12 @@ Providers implement the contract in `src/layers/streetLevel/registry.js`. The
|
||||
core routes clicks by pick prefix, swaps viewer adapters in the one host,
|
||||
manages each provider's credit and fans the filter out to every provider. To
|
||||
add a provider: implement the definition, register it in
|
||||
`src/app/layers/streetLevel.js`, add its boolean option to the `street-level`
|
||||
group in `src/data/layerState.js` and its modules to
|
||||
`scripts/package-boundaries.json`. With providers on different keys the
|
||||
`src/app/layers/streetLevel.js` and add its modules to
|
||||
`scripts/package-boundaries.json`; its share switch travels in `r` by id.
|
||||
A provider with line coverage builds it on `lineCoverage.js` (camera-driven
|
||||
XYZ tiles, draped or cast to bare earth, selection recolouring) and its cones
|
||||
on `sequenceCones.js`, passing its tile fetch, zoom ladder, colours and pick
|
||||
prefixes; Mapillary's `coverage.js` and `sequences.js` are such wrappers. With providers on different keys the
|
||||
layer's `requiresKeyId` is null and each chip reports its own key.
|
||||
|
||||
Google Street View (`providers/google/`) runs on the Maps JavaScript API with
|
||||
@@ -3203,6 +3232,97 @@ once; a lookup or open Google never answers fails after 10 or 20 s. In CI
|
||||
shows off Google 3D, even switched on by a share link; the click and button
|
||||
step skips as `no Google key`.
|
||||
|
||||
KartaView (`providers/kartaview/`) is keyless and browser-side: CORS is open
|
||||
on `api.kartaview.org` (the documented `api.openstreetcam.org` answers but
|
||||
serves empty tiles), `cdn.kartaview.org` and `storage*.openstreetcam.org`.
|
||||
Its chip starts off. Coverage comes from z14 JSON tiles below 2.5 km above
|
||||
ground and z13 up to 6 km (lower zooms take seconds per tile; z10 does not
|
||||
answer), so higher up the hint says to zoom in, and an empty view says there
|
||||
are no KartaView photos in it. A tile's lines are OSM way segments with
|
||||
photos and carry no sequence, date or projection, so `decode.js` chains
|
||||
segments that meet end to start (about four times fewer lines; linear time,
|
||||
at most 20,000 segments a tile and 5,000 points a line), they are
|
||||
drawn as `kv:line:<z/x/y/n>`, up to 1,600 per tile, and never highlighted
|
||||
(`highlightsSequence: false`, so the legend has no "Selected"), and the
|
||||
provider declares `filters: ['pano', 'since']` and `coverageLabel` ("N
|
||||
streets in view · click a line for its nearest photo"). KartaView filters
|
||||
coverage only in its PNG tiles (`/sequence/tiles/{x}/{y}/{z}.png?fieldOfView=360|plane&startDate=YYYY-MM-DD`;
|
||||
its JSON, GeoJSON and jsoncanvas tiles come back empty once a filter is
|
||||
asked for), so a filtered tile is drawn from the cached JSON segments that
|
||||
lie on the filtered PNG's drawn pixels (`maskedSegments`: at least half the
|
||||
points sampled every 2 px have a drawn pixel within one; on Jakarta's 360°
|
||||
filter, 332 of 1,041 segments lie on it, 676 miss it, 33 fall between).
|
||||
A filter change reloads the lines (`lineCoverage.reload`: the drawn ones show
|
||||
until the new ones are in), keeps the JSON segments, and caches masks per
|
||||
filter and tile. A dense filtered PNG can take KartaView over a minute the
|
||||
first time (it answers 504 at 60 s and keeps drawing), so a timeout or 5xx is
|
||||
asked again 4 s later, four tries in all; then the panel says it did not
|
||||
filter the area in time. KartaView's `startDate` is the upload date (its
|
||||
server filters by nothing else), so SINCE goes by upload date throughout,
|
||||
the cut-off taken as its UTC day (`passesKartaViewFilter`): the nearest
|
||||
lookup asks the photo API for the projection (`SPHERE`/`PLANE`; it ignores
|
||||
`fieldOfView`) and upload date and checks each answer the same way (when
|
||||
photos are near but none passes, the panel says so), and the cones pass on
|
||||
each photo's projection and upload date. The provider declares
|
||||
`sinceBasis: 'upload'`, so while it is lit the panel shows "KartaView: by
|
||||
upload date" under the SINCE slider (`sinceNote` in the UI state). Tiles come uncompressed and
|
||||
uncacheable, so the last 24 decoded tiles are kept for 10 minutes while
|
||||
KartaView is lit (`createTileCache`, dropped when it is switched off); one
|
||||
that does not answer in 20 s is asked once more, and one that is not a line
|
||||
list is not cached. A click on a line reaches
|
||||
`handlePick(id, {groundPoint})`, and the provider asks the core
|
||||
(`actions.openNearest`) for its nearest showable photo within 50 m, without
|
||||
framing: many photos are archived (their file answers 409, while a HEAD says
|
||||
200) or have no file, so the six nearest are probed at once with a GET cut
|
||||
off at the headers, and where all are gone the panel says KartaView's photos
|
||||
there are archived. Only a definite answer (403/404/409/410, or 200) is
|
||||
remembered; a storage timeout or 5xx is asked again. The open photo's
|
||||
sequence draws as cones from the 250-photo page holding it
|
||||
(`/2.0/sequence/{id}/photos`); the panel counts the drive's own photos
|
||||
(`countActivePhotos`, asked once per sequence). The camera direction (the
|
||||
marker, cones, FOLLOW, and a panorama's centre) is the direction of travel
|
||||
to the next photo a few metres on (`assignCourses`): KartaView is dashcam
|
||||
imagery, while its `heading` is the device compass, which reads 0 for whole
|
||||
drives without one and can sit a steady 110° off inside a car. Until the
|
||||
drive's page arrives the compass stands in (0 counts as unknown), and the
|
||||
pose is sent again once the course is known. The open photo's marker is a
|
||||
purple view cone (`marker: {kind: 'view-cone'}`), as Street View's is blue. Pages follow photo ids, which only roughly
|
||||
follow the index, so the page is found by search (both ways, halving past the
|
||||
end when many photos were deleted), a neighbour page joins within 12 photos
|
||||
of an edge, and the cones re-centre whenever a photo of the selected sequence
|
||||
opens on another page. ‹ › (and ← →) open through the core without framing,
|
||||
step on from the photo already on its way, skip archived photos, and disable
|
||||
up front at the ends. `api.kartaview.org` speaks HTTP/1.1, so of the
|
||||
browser's six connections to it tiles take three, lookups two and pages one
|
||||
(newest first), and a lookup never waits behind tiles; the photo API answers
|
||||
429 to more than about three requests at once, so a 429 is retried with
|
||||
backoff (at most 10 s), and a lookup gets 8 s, then 15 s once more (KartaView
|
||||
sometimes sits on a lookup for 11 s and answers the same one in 3 s); a
|
||||
request that could not be made at all (no network, CORS) says so and is not
|
||||
repeated. Answers
|
||||
are read with a running byte count and cut off past 16 MB (KartaView sends
|
||||
them chunked, without a length). Photo URLs are built from
|
||||
`storage` and `filepath*`: the API's `fileurl*` always name storage1, where
|
||||
photos stored elsewhere 404, and a `fileurl*` fallback must itself be an
|
||||
https storage host. The viewer (`viewer.js`) shows a flat photo at 1,280 px,
|
||||
then 2,560 px, from the image proxy (`pr:sharp/rs:fit:W:H/<base64url>`),
|
||||
with KartaView's own 1,280 px file as the fallback, and a 360° photo's
|
||||
equirectangular `wrapped_proc` image (13,000 px wide upstream) resized to
|
||||
1,024 px, then 2,048 (docked) or 4,096 px (expanded, or once the viewer
|
||||
grows), decoded off the main thread into an ImageBitmap and uploaded as RGBA
|
||||
(about 90 ms → 15 ms for 4,096 px on a phone-class CPU), on `panorama.js`, a
|
||||
single-triangle WebGL renderer (image centre = the camera heading; drag,
|
||||
pinch, wheel, Shift+← →, ↑ ↓, + −; the canvas re-measures every frame; a
|
||||
closed viewer keeps a 1×1 texture). Without WebGL, or if the proxy fails
|
||||
within 15 s, a 360° photo shows its front view. A lost context draws the
|
||||
photo again on a new canvas (a lost canvas only gives back its lost
|
||||
context), through the core and facing where the user was looking; a newer
|
||||
photo that was opening is drawn on the new canvas instead. FIT / FILL hide
|
||||
for panoramas (`supportsRenderModes`). The
|
||||
caption has no place name (KartaView's is where the drive began) and links to
|
||||
the full-size photo through the image proxy, since kartaview.org's photo
|
||||
pages fail for signed-out visitors.
|
||||
|
||||
Street Level has two browser gates. `npm run qa:street-level -- --url <server>`
|
||||
runs against real Mapillary and needs `MAPILLARY_CLIENT_TOKEN`. `npm run
|
||||
qa:street-level:fixtures -- --url <server>` answers every Mapillary request
|
||||
@@ -4214,6 +4334,8 @@ and unreachable upstream (502/504) separately from road geometry.
|
||||
|
||||
### Place-search providers
|
||||
|
||||
Coordinate input requires exactly two nonempty components; extra comma or semicolon separators decline to geocoding rather than silently choosing a location.
|
||||
|
||||
Location search/fly-to, annotations and Radio location lookup receive one
|
||||
`placeSearch.geocode(query, { bias, signal })` service. `src/standalone` composes
|
||||
two offline providers first — a strict decimal-degree coordinate reader and an
|
||||
@@ -4338,7 +4460,7 @@ are omitted rather than framing the wrong part of the globe.
|
||||
- **Esri surface and the swipe.** While any image is on the map (a preview included) the layer holds the map lease (`acquireImageryComparison`, owner `recent-imagery`, `esri-if-photoreal`): on Google 3D the map switches to Esri, because 30 m pixels over 3D buildings do not read, and Cesium's split only works on the globe. The lease is handed back, and Google 3D restored unless the operator changed maps meanwhile, when the last image leaves the map or the layer is disabled; the notice line says so while it holds. While a day is shown the imagery keeps Esri: a manual switch that lands on Google 3D is answered at once with a new lease under the same policy (`keepEsri`), the notice reads `Imagery stays on Esri · CLEAR to use Google 3D`, and the divider never suspends because of a map switch. It re-leases once per switch generation and only for a manual one (`MapSourceController#getSwitchOrigin()` is `manual` for an outside `setStack`, `automatic` for the controller's own fallback or recovery), never for the lease's own switch and never while releasing, so CLEAR and disable still return to Google 3D; a lease another owner holds stays refused. When Esri fails and the controller falls back to Google 3D on its own, the layer lets the lease go without restoring anything, both days drape on the tileset without a swipe and the guidance reads `Esri map unavailable · no swipe`; only the next manual switch to Google 3D takes Esri again, so a failing Esri map is never retried in a loop. Switching between globe stacks (Esri, OSM, Bing) only rebinds. On a tileset host both images drape without a swipe. The split control (`createImagerySplit`, labels A / B, or IMAGE / BASEMAP) exists only while a swipe is live, recentres on every new comparison (not while scrubbing the second day), except once for a split restored from a link. There is no keyboard shortcut (Space is the app's push-to-talk): SWAP (`#ri-swap`, in the controls row, its slot reserved and the button disabled while no swipe is live) trades the two sides, A to the right and B to the left, or the image to the right of the basemap, and a second click restores; the hint reads `Drag the divider · SWAP trades sides`. The swap is not in the share link, and every new comparison starts unswapped. One opacity applies to both drapes. Another owner holding the lease is reported and the images still drape.
|
||||
- **Panel.** `#recent-imagery-panel` is static rail markup in `src/ui/templates/context.html` beside `#weather-panel`, registered in `PanelLayoutController`, `PanelChrome` and the share panel state (`ui` token `i`), hidden while the layer is off and opened on first appearance unless a stored or shared collapse choice exists (`dataset.collapsedPreference`). `LayerPanel.attachRecentImagery(factory)` mounts the readout (`createRecentImageryPanel` in `src/ui/recentImagery.js`) into its `data-rail-scroller` body, as the weather readout is mounted. The body is a fixed stack in which no block changes height and no control moves in any state: `#ri-actions` (SELECT BOX · USE VIEW · CLEAR, rail-card actions), `#ri-notice` (one line: `#ri-notice-text` with the refusal, error, CLEAR notice or the Esri note, and `#ri-zoom-in` in a fixed slot at its right end, reserved unless an oversized box or view can be fitted), `#ri-strip` (day cards newest first: thumbnail, date, sensor, cloud, START HERE, PREVIEW, and a SHOW chip or A and B chips; ← → Home End move, S / A / B pin, Enter previews), `#ri-hint` (one line: the next step), `#ri-selection` (`#ri-mode` IMAGE · VS BASEMAP · A / B, then `#ri-slot-a` and `#ri-slot-b` with `#ri-unpin-a` / `#ri-unpin-b` kept in place when empty), `#ri-controls` (`#ri-opacity`, EXPORT / EXPORT A and EXPORT B) and `#ri-details`, a collapsed rail card holding the focused day's acquisition, coverage and granules, catalog notes, the empty-days toggle and the imagery credit. Absent controls are reserved (invisible), never removed. Every render preserves the body's `scrollTop`.
|
||||
- **Share links.** Layer options (token `1`): box edges as integers at degrees × 100000, pins `a` and `b` as compact days (`S20260918`), `m` mode (0 image, 1 basemap, 2 A / B), `p` split percent (share-link only: never stored locally) and `v` for the daily overview. Row chips: `MORE DETAIL · 30 m` (on) and `DAILY OVERVIEW · 250 m` (off).
|
||||
- Regression surface: the colocated `*.test.mjs` beside each module (shared doubles in `src/layers/recentImagery/testDoubles.mjs`; `src/ui/recentImagery.test.mjs` includes a DOM-structure guard: every control keeps its place in the tree, nothing is hidden, and every fixed-height block keeps the class the stylesheet fixes its height by; it has no layout, so it cannot see movement), `src/ui/layerPanel.test.mjs` (mount), `src/maps/controller.test.mjs` (`subscribe`), `src/data/layerState.test.mjs` (codec), `src/sharelink.celestial.test.mjs` (panel token), and the live gate `scripts/qa-recent-imagery.mjs`, which also measures every control's rect across the transitions within 1 px; that measurement is the real layout-shift check.
|
||||
- Regression surface: the colocated `*.test.mjs` beside each module (shared doubles in `src/layers/recentImagery/testDoubles.mjs`; `src/ui/recentImagery.test.mjs` includes a DOM-structure guard: every control keeps its place in the tree, nothing is hidden, and every fixed-height block keeps the class the stylesheet fixes its height by; it has no layout, so it cannot see movement), `src/ui/layerPanel.test.mjs` (mount), `src/maps/controller.test.mjs` (`subscribe`), `src/data/layerState.test.mjs` (codec), `src/sharelink.celestial.test.mjs` (panel token), and the live gate `scripts/qa-recent-imagery.mjs`, which also measures every control's rect, relative to the panel, across the transitions within 1 px; that measurement is the real layout-shift check. `QA_RECENT_IMAGERY_SLOW_RENDER=1` gives loaded software renderers a 4 s zoom deadline and an 8-sample stability tail; the default stays 2 s and 12 samples.
|
||||
|
||||
### 3D Aircraft + Tracking (June 2026)
|
||||
|
||||
@@ -5089,6 +5211,12 @@ photoreal globe is hidden.
|
||||
|
||||
Map credentials are passed to each source constructor rather than changing SDK-wide Google or ion defaults.
|
||||
|
||||
Bing Aerial and Bing Labels resolve their ion imagery endpoint with the supplied
|
||||
token, then construct the Bing provider with `tileProtocol: 'https'`. Both styles
|
||||
request HTTPS tiles even on HTTP localhost, with the existing Content Security
|
||||
Policy unchanged. Ion attribution and Bing's per-tile credits are preserved;
|
||||
other ion imagery assets continue through the SDK's standard ion factory.
|
||||
|
||||
The controller accepts other source registries without adding provider branches.
|
||||
Each instance caches source construction, ignores superseded scene changes and
|
||||
releases imagery layers/listeners on replacement. Destroy invalidates pending
|
||||
@@ -5108,7 +5236,9 @@ its paint loop. Camera deactivation destroys the decoder, and fatal playback
|
||||
errors revert to the labeled frame fallback. Camera changes clear the old panel
|
||||
frame. hls.js is imported only when an HLS camera starts. Two live sessions may
|
||||
coexist with at most eight independent consumer leases each; no-access lease
|
||||
expiry is 15 seconds. Closing one consumer leaves other consumers running. Encrypted/fMP4/byte-range playlists fail
|
||||
expiry is 15 seconds. Closing one consumer leaves other consumers running. Lease
|
||||
ids use `crypto.randomUUID` where the page is a secure context and an equivalent
|
||||
v4 id from `crypto.getRandomValues` on plain-HTTP LAN pages. Encrypted/fMP4/byte-range playlists fail
|
||||
closed. Performance and live agency reliability require recorded validation.
|
||||
|
||||
## Wind forecast models
|
||||
|
||||
@@ -128,6 +128,12 @@ Use the same controls before attributing a difference to the application:
|
||||
6. Record live object counts before attributing a difference to the client.
|
||||
7. Treat a live-source outage as missing coverage, not as evidence of low client
|
||||
rendering cost.
|
||||
8. Record whether the app is running in Pinokio's embedded view or in an
|
||||
external browser. One Pinokio 8.2.0 user reported severe stutter in the
|
||||
embedded view that went away when the same local URL was opened in a normal
|
||||
browser ([#365](https://github.com/bilawalsidhu/gods-eye-view/issues/365)).
|
||||
Do not compare embedded-view and external-browser measurements directly;
|
||||
compare the reported GPU renderer and matched scene settings first.
|
||||
|
||||
## What is not established yet
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ The session adapter, action runner and backend interfaces remain unchanged.
|
||||
| Owner | State and responsibility |
|
||||
| --- | --- |
|
||||
| `realtimeConnection.js` | Start generation, request cancellation, peer/data channel, acquired microphone stream and playback element |
|
||||
| `realtimeBackend.js` | Token and SDP requests, their separate transports, the abort/timeout scope around both, and client-secret expiry |
|
||||
| `realtimeTurns.js` | Active and superseded responses, pending confirmations, deduplicated calls and action cancellation |
|
||||
| `realtimeRadio.js` | Speaker ducking, prepared playback, stronger-action reservations and playback observers |
|
||||
| `realtimeInput.js` | Physical Space gesture, microphone mute, input/output meters and their frame/listener lifetime |
|
||||
@@ -21,6 +22,15 @@ The session adapter, action runner and backend interfaces remain unchanged.
|
||||
| `resultDisplay.js` | What the voice card shows for a result and which items it numbers (read by the card and `referents.js`) |
|
||||
| `gevActions.js` runner | Analyst follow-up memory (session: `resetConversation()` on stop, `dispose()` on removal) |
|
||||
|
||||
The backend is replaceable per deployment: `realtimeController.js` accepts it as a
|
||||
`backend` option and falls back to `createRealtimeBackend()`. Its two method
|
||||
signatures live with [application construction](APPLICATION.md); what belongs here
|
||||
is the ownership. The connection is the backend's only consumer in the application.
|
||||
The connection reads credential metadata for diagnostics and cost accounting,
|
||||
then passes the complete credential unchanged to `negotiate`. Client-secret expiry is refused inside the backend, not by the connection.
|
||||
`realtimeOwners.test.mjs` drives whole sessions through a substitute that
|
||||
implements only those two methods.
|
||||
|
||||
Pure input policy, preferences and protocol-response policy have separate modules.
|
||||
Owners receive named readers, operations or focused collaborators. Cross-owner
|
||||
cancellation uses operations; response handling does not own Radio's reservations
|
||||
|
||||
Reference in new issue
Block a user