Commit Graph
413 Commits
Author SHA1 Message Date
Said TurkseverandClaude Fable 5.1 335b4b08a2 test(ui): cover rail exclusion and add the panel-resize QA harness
The right-rail test now proves a .panel-floating panel is neither
measured, allocated nor auto-collapsed while its docked sibling still is.
scripts/qa-panel-resize.mjs drives the CCTV panel in a real browser:
lift-out by header drag, all eight handles with the opposite edge pinned,
minimum size, reload restore and double-click snap-back. Its pure helpers
sit behind a main guard so src/tooling/panelResizeQa.test.mjs can check
them without a browser. Run it with `npm run qa:panel-resize`.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-23 15:21:21 +01:00
Said TurkseverandClaude Fable 5.1 317c0a7e0c feat(ui): add panelResize geometry for edge and corner resizing
Pure box arithmetic for resizing a floating panel from any of the eight
compass handles: the named edges follow the pointer, the opposite edge
stays pinned, and minimum size plus the viewport margin win. Owned by the
same boundary groups as PanelPositionControls, which wires it next.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-23 14:45:54 +01:00
ulihhhh 5b4931572a Merge upstream/main into feature/catalonia-cctv-cameras
Keeps PR #595's Catalonia CCTV pack in sync with upstream's DelDOT
CCTV pack (#699) and the wind/weather doc updates from #617. The
sources.js conflict was a false positive from git's line-based diff
interleaving two structurally similar but independent loader
functions (loadCataloniaSourcesFromOpenData / loadDelDOTSourcesFromOpenData);
resolved by keeping both as complete, separate functions.

Full unit suite passes (4743/4743, 1 pre-existing Node-version skip).
2026-09-23 12:12:58 +02:00
Bilawal Sidhuandmanjunath22466 082074a006 feat(layers): Recent Imagery — open satellite imagery for a selected box (#716)
Select a box on the world and browse the last 30 days of open satellite imagery over it, keyless: NASA GIBS Harmonized Landsat Sentinel-2 (30 m) and the VIIRS daily overview (250 m), with a day strip, IMAGE / VS BASEMAP / A / B modes with a swipe divider, PNG export and share links. The before/after swipe from the Nepal scene moves into shared modules so both use it.

Co-authored-by: manjunath22466 <[email protected]>
2026-09-22 20:34:11 -05:00
25491f7e33 feat(taps): shared address contract for receiver taps (#382)
* feat(taps): shared address contract for receiver taps

Receiver taps (#57 RTL-SDR, #56 Rayhunter, #7 TAK, #6 Meshtastic) differ from
every other provider in this tree in one way that matters: the upstream address
comes from the user at runtime rather than from a fixed constant, so each tap
route is an SSRF surface unless the address is constrained. Today each tap
would answer that question for itself, and they would disagree.

parseTapAddress() is the single place the rule lives:

  A tap may address loopback or an RFC1918 private network, plus the
  `localhost` and `*.local` (mDNS) names. Nothing else.

That is what a tap is for — reading your own device on your own network. A tap
pointed at a public address is either a mistake or the proxy being used as a
confused deputy, and both get the same answer. Link-local (169.254/16) is
excluded wholesale, which covers the cloud metadata address by construction
rather than by blocklist.

Deliberately NOT reusing isNonGlobalIpv4() from radio/stations.js: it reports
malformed input like 999.1.1.1 as non-global, which is the safe direction for
the radio proxy's "is this public enough to fetch?" test but inverts into
*allowing* garbage under a tap's "is this local enough to fetch?" test. A
positive allowlist cannot invert that way, and the tests pin that case.

Two documented non-goals so they don't read as oversights: no general hostname
resolution (a name other than localhost/*.local is rejected rather than
resolved-and-pinned, avoiding DNS-rebinding defence for no gain), and no IPv6
(zone-index handling is platform-specific and no tap has needed it).

Scoped to the address rule alone. The recorded-fixture harness lands with the
first tap, designed against a real recorded response rather than guessed at
with no consumer.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01KGKBNNjPh4iQe8sviGZNPb

* style: adopt the tap address contract into the format scope

Mechanical. Adds server/providers/common/tap-address.js and its test to
scripts/format-scope.json and applies prettier, matching the six sibling
modules in server/providers/common/ that are already adopted. No behaviour
change.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01KGKBNNjPh4iQe8sviGZNPb

* docs(taps): state accurately which taps this contract governs

The header claimed #57, #56, #7 and #6 as consumers. Only #56 (Rayhunter)
actually is today: it takes ?base=host:port from the browser, which is the
shape that makes a route an SSRF surface. #57 would qualify if built
server-side.

The other three are different shapes, and forcing them through a private-only
check would be wrong rather than merely unnecessary:

- Meshtastic (#6) reads a fixed public broker, mqtt.meshtastic.org.
- WiGLE (#11) reads a fixed public API behind a token.
- TAK (#7) takes its host from operator-set env config rather than from the
  browser, and a TAK server is frequently a legitimate remote host.

No behaviour change; comment only.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01KGKBNNjPh4iQe8sviGZNPb

* refactor(taps): move the tap address contract to src/data so both sides share it

The browser needs the same answer the server does — the server as a trust
boundary, the client to give immediate feedback on a typed address without a
round trip. Keeping the rule under server/providers/ would have meant the
client re-deriving it, which is how the Rayhunter branch already carried a
hand-synced copy of the regex with a comment admitting it.

#274 is open about eight independent copies of haversine, one of which had
silently swapped its arguments. Shipping a new duplicated validator across a
trust boundary in the same tree would be hard to defend.

server/providers/gbfs.js already imports src/data/gbfsSource.js, so shared
validation living in src/data with the server importing it is the established
direction here rather than a new one.

Pure move plus the path/docblock updates. No behaviour change; the 12 contract
tests are untouched and still pass.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01KGKBNNjPh4iQe8sviGZNPb

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
Co-authored-by: Bilawal Sidhu <[email protected]>
2026-09-22 19:22:55 -05:00
0251c74109 feat(weather): add globe wind, observed weather and cyclone context (#617)
Wind (NOAA GFS and ECMWF IFS: animated particles, colour field, a reading at map centre), observed weather (NOAA MRMS radar, GOES and NESDIS infrared clouds, lightning density) on one shared history timeline, NHC and CPHC cyclone advisories with tracks and cones, and a WEATHER panel in the right rail. On 3D Tiles the observed products render as raised shells with a sharper window around the view.

Co-authored-by: Gustavo Beneduzi <[email protected]>
Co-authored-by: Daniel Slay <[email protected]>
Co-authored-by: Rehaan Delmotra <[email protected]>
Co-authored-by: Cursor Agent <[email protected]>
2026-09-22 17:45:39 -05:00
ulihhhh 49a322519a Merge remote-tracking branch 'upstream/main' into feature/catalonia-cctv-cameras
# Conflicts:
#	CHANGELOG.md
2026-09-21 19:00:01 +02:00
Sameh Khamis 5d684c22b3 Merge origin/main into fix/ais-unavailable-sog-cog
# Conflicts:
#	CHANGELOG.md
#	docs/CURRENT-STATE.md
2026-09-20 16:33:53 -07:00
daikaginza ae35a2c939 docs(attribution): credit adsbdb and carry its route-data terms
adsbdb supplies the aircraft type, model name and registration behind every
enriched flight, and the airline and origin/destination pair behind the
tracked contact's FROM -> TO strip. It appeared in neither attribution
surface: DATA_SOURCES.md and src/data/dataCredits.js each held zero
occurrences of it, against the rule both files state for themselves and
CONTRIBUTING's fourth pull-request item. adsb.lol is a different operator and
its ODbL credit does not reach this data.

The reporter of #256 left the patch off deliberately, saying the terms were
what should not be guessed. They are published, so this takes them from the
source rather than inventing them: adsbdb credits PlaneBase for the aircraft
data and Guillaume Michel for the ICAO-to-N-number conversion, and states that
the flight route data "is the work of David Taylor, Edinburgh and Jim Mason,
Glasgow, and may not be copied, published, or incorporated into other
databases without the explicit permission of David J Taylor, Edinburgh". No
licence or rate limit is published for the service itself.

That restriction is the reason the note records what the proxy does with what
it fetches: responses are cached per key for 24 hours in .gev-cache/adsbdb.json,
which is gitignored, so the data stays on the operator's machine and is never
bundled with this repo or redistributed.

A test pins the credit. The attribution is a requirement rather than a
preference, so it should fail loudly if a later edit drops the names or the
restriction, instead of surviving on luck.
2026-09-19 20:12:36 +07:00
Theerayut BoonkirdandClaude Opus 5 75869d0c10 chore: adopt the new AIS test into the explicit formatting scope
scripts/format.mjs skips *.test.mjs during runtime discovery, so a test
added under a discovered root is never seen by format:check until it is
listed in scripts/format-scope.json — which is what CODE-BOUNDARIES.md
means by adding tests to the explicit list as they are adopted. The file
went in unformatted and the check stayed green, hiding it.

Listed and formatted; format:check now covers 917 files instead of 916.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-18 00:43:02 +01:00
ulihhhhandClaude Sonnet 5 25f90692cf Merge upstream main into feature/catalonia-cctv-cameras to resolve PR #595 conflicts
Upstream added Director, Transit/GTFS-Realtime and Bhote Koshi scene work
in the same window; the only real conflict was two adjacent CHANGELOG
entries, resolved by keeping both.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-16 10:34:16 +02:00
Sameh Khamis 078fc290ec Add Director authoring, import previews and scene bundles 2026-09-15 20:15:32 -07:00
Sameh Khamis 80027756ef feat: add declarative Director feature actions 2026-09-15 19:16:49 -07:00
Sameh Khamis 92526e9a92 feat(director): add bounded scene data packs and placement 2026-09-15 17:59:53 -07:00
Sameh Khamis 13c0b8d1bc feat(director): add authored camera directions and anchors 2026-09-15 16:53:26 -07:00
Sameh Khamis 18300e7e00 feat(director): validate scene documents and preserve saved edits 2026-09-15 16:20:36 -07:00
Sameh Khamis 8a3c4868b0 refactor(director): separate timing clocks and scene pack presentation 2026-09-15 15:41:42 -07:00
Reloded 976efed6dc feat(cctv): add Lithuania Eismoinfo road cameras 2026-09-16 00:14:46 +03:00
Bilawal Sidhu 50d3672a00 fix(transit): keep parked vehicles pointed along their course while the camera orbits (#603)
## Changes

Follow-up to #596 from the owner's look: a parked transit vehicle turned with the camera. Moving vehicles project their world course into screen space on every camera change, but a vehicle that had never moved on screen could have no display course and was skipped by that pass, leaving its billboard at a screen-anchored angle; rotation invalidation also relied on camera events that a pose change without a revision could miss. Now every visible vehicle with any usable course (derived, held, or the feed's reported bearing) is re-projected at the existing 5 Hz cadence on camera pose changes. Moving playback and the 120°/s course limiter are unchanged.

## How it was verified

- `npm run format:check` (861 files), `npm run check:boundaries` (109 groups), `npm test` (4,068 passing), `npm run build` clean; tracking regression 109/109 in a real browser on Google 3D tiles.
- Node tests: a stationary vehicle with a held course, and one with only a reported bearing, under a camera at heading 0° then 90° yield screen rotations 90° apart.
- Browser harness (`scripts/qa-transit.mjs`, keyed on Google 3D tiles): a parked scripted vehicle orbited by 90° rotates 90.000° on screen; a moving vehicle's rotation still matches its rendered travel; both checks fail on main and pass here. Full keyed run: 201 pass; the nine failures are the per-frame allocation gate already recorded as a follow-up and threshold-edge readability lines on the Boston matrix, both unchanged from #596.
2026-09-15 14:15:27 -05:00
Bilawal Sidhu 0bb61f53c6 fix(transit): keep the real silhouettes under sensor presets, make the selected trail visible, put Transit in Movement (#596)
## Changes

Follow-up to #587 after the owner's first look at the merged transit layer on Google 3D tiles.

- **Sensor presets keep the real silhouettes.** Under NVG, thermal (white-hot, black-hot, Ironbow) and noir, vehicles are the same silhouettes as in normal view, filled opaque white with a 2 px dark halo, at the CRT display sizes (26 px fleet, 39 px selected). The solid rounded "signature" bodies are gone.
- **The selected vehicle's trail is visible.** The retained history is now draped onto 3D tiles and terrain (`GroundPolylinePrimitive`, `ClassificationType.BOTH`, the way the traffic heat-lines are drawn), 3 px core over a 5 px dark backing, per-segment age colour, a short draped head clipped to the sprite. Two defects kept it off screen before: Cesium's per-instance attribute getters return copies, so the renderer's show/colour edits were discarded, and a marker did not recover after the camera jumped to it, which hid the trail with it. Trail geometry is now prepared on selection independent of floor resolution and marker visibility; sparse long intervals (rail) keep a bounded marker corridor instead of dropping the interval; classification survives map-source changes.
- **Transit sits in the Movement panel group** between Street Traffic and Bike Share (the panel orders by `PANEL_GROUPS`, not by catalog order; the catalog is moved too).

## How it was verified

- `npm run format:check` (854 files), `npm run check:boundaries`, `npm test` (4,062 passing), `npm run build` clean; tracking regression 109/109 in a real browser on Google 3D tiles.
- Browser harness (`scripts/qa-transit.mjs`), keyed on Google 3D tiles and keyless: keyed 194 pass, with the trail pixel check passing at 300, 600 and 900 m; the remaining keyed failures are the per-frame allocation gate already recorded as a follow-up from #587 (CPU and frame time within budget), four readability lines at threshold edges, and the card-anchor check now counting frames where the selected marker is legitimately off screen; keyless 193 pass with the remaining misses being threshold edges on the thin tram silhouette (centre 0.83–0.88 against 0.85) and one bus ring 0.28 against 0.25 on a pure-white roof.
- New harness checks: `Google 3D selected trail visible at 6 of 8 projected samples` (repeated off/on framebuffer captures at 300/600/900 m, samples outside the sprite footprint, a background-change negative control; fails on main, passes here), a camera-arrival check (select a moving vehicle, `setView` onto it, marker shown and trail body drawn within 2 s), `PANEL_ORDER` pinned, raster tests comparing every sensor raster's mask and aspect ratio to the normal silhouette.
- Direct look on a keyed build: a live CapMetro bus at 30 m/s selected through the layer API draws its draped trail along the highway lane (harness capture `keyed-600m-trail-visible.jpg`).
- Adversarial review by Codex Astra before the last two fix passes (stack-switch classification, marker corridor under the vertex cap, pixel-gate loophole), all three fixed with regressions.

Docs: `docs/CURRENT-STATE.md` and `CHANGELOG.md` updated in this PR. No data-source changes.
2026-09-15 13:26:41 -05:00
Pedro Lobato fa9af39e7b fix(terrain): bound the client terrain-height cache with LRU eviction
The in-memory cache in the terrain-height resolver had no eviction, so a
session retained every coordinate it ever resolved for the lifetime of the
page. The 5-decimal rounding documented in the file header makes repeated
visits to one place share a key, but it does not bound how many distinct
places a session visits.

Cap it at 20 000 entries, overridable per instance so the bound is testable
without minting twenty thousand coordinates. Eviction is least-recently-used
rather than insertion-ordered because revisits here are spatial: the cell the
camera is parked on must not be dropped for having been resolved early.

The bound sits far above a city-scale session at the ~111 m floor grid, so
normal use never evicts and issues no additional proxy requests. Batch results
are assembled from what the call resolved, so eviction during a large batch
cannot report a just-resolved point as unresolved.
2026-09-15 11:33:56 -05:00
ulihhhhandClaude Sonnet 5 ffbe98b4ac test(format-scope): register cctvCataloniaSource.test.mjs for format:check
Mechanical addition per CONTRIBUTING.md, following the existing per-pack
test-file entries (cctvCalgary.test.mjs, cctvNswSource.test.mjs, etc.).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-15 18:07:40 +02:00
Sameh Khamis bf1d50f29b refactor: separate map feature queries and source records 2026-09-15 08:10:32 -07:00
Sameh Khamis 3155e4e0bf refactor: separate transit sources and request service 2026-09-15 07:41:56 -07:00
Sameh Khamis ae99843c14 build: discover owned runtime modules in the formatter gate 2026-09-15 07:26:32 -07:00
Bilawal Sidhu 76c20be277 feat(transit): live public-transit vehicles from open GTFS-Realtime feeds (#587)
Supersedes #218 by @spcpza, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Contributor: @spcpza. His original commit is the base of this branch, and his own re-port onto main (2026-09-15, `5b69011`) was consulted while finishing the height work. That port reads every vehicle's surface from the app's shared ground-floor system (`cachedGroundFloor` / `warmGroundFloor` / `GROUND_FLOOR_LIFT_M`) rather than sampling the scene per layer, keeps a vehicle hidden until its cell answers, warms a bounded batch per poll on a timer instead of per frame, and renders at the ellipsoid above the altitude gate. That is the sounder primitive — one floor system for the app, with the rooftop-versus-street question already settled against a datum-correct DEM prior — and this branch's height work was rebuilt on it, replacing a bespoke cell cache, ground prior and rooftop rule written here. Credit for that direction is his.

Future work (not in this PR), both written up in docs/CURRENT-STATE.md:

- Readable route names. The realtime feeds carry only `route_id`; `route_short_name` / `route_long_name` live in each operator's static GTFS `routes.txt`, and headsigns in `trips.txt`. Doing it properly wants a server-side metadata loader beside the transit proxy with fixed registered static sources, bounded indexes built once and persisted, a slow conditional refresh, and a versioned route dictionary the browser caches. Shipped here: ids are never rewritten, and a cut one carries an ellipsis instead of reading as a typo.
- Below-ground rendering. Subway vehicles are drawn on the surface directly above themselves, because the feeds carry no depth and a train nobody can see is not worth drawing; the card says so plainly. Real treatment wants OSM tunnel geometry per city and a ghosted sprite tethered to the surface. The owner recorded it and left it.

Round four and after (2026-09-15). The owner tested round three under FLIR and NVG, and then asked for the design to be taken further: elegant in performance, beautiful on camera, trails with a cache for public transport, Cesium-native, and a core other moving layers can adopt. Codex Astra reviewed the plan (it confirmed the speed fault: a glide started from the drawn position at receipt time but spanned the gap between report times, so with MBTA reporting every ~10 s against a 15 s poll every second glide ran at 1.5x; it rejected a queued-segment patch), then wrote the design, then implemented it in commit-sized passes with adversarial review between them and real-browser harness runs by the integrator.

What this PR now contains beyond the contributor's original port:

- Delayed playback in a contact-agnostic core (`src/data/contactPlayback.js`): each vehicle keeps a typed, bounded fix history and a display clock that runs at one second per second through it, a feed-derived lag behind real time, holding at its newest fix rather than extrapolating and never sprinting to catch up. Marker, course, motion word, card and trail all read the same displayed sample. The clock has an explicit time-offset and seek API so a rewind is a later feature, not a rewrite; flights and vessels are untouched.
- A selected-vehicle trail (`src/data/contactTrailRenderer.js`, `src/layers/transit/trails.js`): the retained history drawn with batched Cesium primitives, clipped at display time so the head is exactly the sprite, faded by age, in the mode colour (white under sensor presets), on the same surface path as the marker.
- Bounded proxy-side history (`server/providers/transitHistory.js`): fifteen minutes and at most 128 fixes per vehicle with hard byte ceilings, MBTA only for now (opt-in per feed), served by a small endpoint that never fetches upstream, so a selected trail survives a browser reload while the server keeps running.
- Scene work bounded to what is visible and moving, an occluder, cached DETECT candidates, holds on the render loop only while something visible moves.
- Sensor presets: white-hot haloed sprites under NVG/FLIR/noir (black-hot inverts), saturated mode colours under CRT, per-mode bracket tiers in every theme, the selected card keeping its mode colour.
- A discriminating browser harness (`scripts/qa-transit.mjs`) that samples postRender frames, reads the real card anchor, and measures fleet budgets at 800 and 3,000 vehicles.

Not built, recorded as follow-ups: curated route display names (lowest priority per the owner), fleet-wide tails, route snapping, a rewind UI, adoption of the playback core by flights and vessels.

Verified at merge (2026-09-15 morning): unit suite 3,896 passing, build clean, format and boundary gates clean, tracking regression 109/109, browser harness keyless 200 pass / 0 fail (13 sensor checks unexercised because the live view offered fewer than six isolated sprites; every judged sprite passed), keyed on Google 3D tiles 198 pass with the per-frame allocation gate as the only failure. Follow-ups recorded: the keyed build's playback sampler still allocates per frame (CPU and frame time stay within budget; the 3,000-vehicle metro view sits at a 27.6 ms frame interval against a 25 ms budget), the shared detection overlay's per-paint allocation, friendlier route names, fleet-wide tails, a rewind UI, and adopting the playback core for vessels and flights.
Co-authored-by: spcpza <[email protected]>
2026-09-15 05:18:30 -05:00
Sameh Khamis a79208181f refactor: separate Nominatim transport from search composition 2026-09-14 22:14:51 -07:00
Sameh Khamis 66eb6d6a7c refactor: add configurable Nominatim adapter and portable source helpers 2026-09-14 22:08:16 -07:00
Sameh Khamis e46d50ce52 refactor: expose reference sources independently of standalone setup 2026-09-14 21:52:27 -07:00
Sameh Khamis cc960b0dbe refactor: enforce import directions and expose source factories 2026-09-14 21:12:01 -07:00
Sameh Khamis 4507f3a1d0 refactor: separate voice sessions from protocol adapters 2026-09-14 20:27:12 -07:00
Sameh Khamis 55b240e3ab refactor: separate voice action schemas from descriptions 2026-09-14 20:05:32 -07:00
Sameh Khamis ea6c8653b3 refactor: expose portable source record protocols 2026-09-14 19:36:32 -07:00
Bilawal SidhuandMatthew-Selvam 6fa25c349a fix(ui): name the missing provider key on a key-gated layer row (#575)
Supersedes #296 by @Matthew-Selvam, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Matthew-Selvam <[email protected]>
2026-09-14 21:26:09 -05:00
Bilawal Sidhuandsendmebits 7fa0cfbb26 feat(search): Nominatim as the last-resort geocoder (#573)
Supersedes #350 by @sendmebits, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: sendmebits <[email protected]>
2026-09-14 21:22:08 -05:00
Bilawal SidhuandKuraPiee cca6442997 feat(search): coordinates and bundled presets resolve keyless (#572)
Supersedes #388 by @KuraPiee, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: KuraPiee <[email protected]>
2026-09-14 21:18:07 -05:00
Bilawal SidhuandYashveer Singh d9fac6d88e feat(ui): tilt and north-up compass controls (#571)
Supersedes #442 by @yashveeeeeeer, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Yashveer Singh <[email protected]>
2026-09-14 21:15:29 -05:00
Bilawal SidhuandMiguelGFerreira 2b0fcd4595 fix(bikeshare): address the GBFS proxy by path, not query string (#569)
Supersedes #441 by @MiguelGFerreira, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: MiguelGFerreira <[email protected]>
2026-09-14 21:08:12 -05:00
Sameh Khamis 27dec4e949 Merge branch 'main' into feat/alpr-visual-treatment 2026-09-14 18:13:10 -07:00
Sameh Khamis fdf030cbc9 Merge remote-tracking branch 'origin/main' into feat/alpr-visual-treatment
# Conflicts:
#	scripts/package-boundaries.json
2026-09-14 18:10:05 -07:00
Bilawal Sidhuandspcpza d78696dc17 feat(directions): keyless A→B directions with turn-by-turn steps and FLY (#564)
Supersedes #219 by @spcpza, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: spcpza <[email protected]>
2026-09-14 20:09:41 -05:00
Bilawal Sidhu 9fc8d1966b feat(annotations): draw on the world by hand (#547)
Supersedes #235 by @cora-fresh-labs, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Future work (not in this PR): hand-drawn marks do not persist across a reload today, and neither do spoken annotations; there is no storage layer for marks. The natural home is Scenes: a drawing that belongs to a shot and persists per shot, so a scene animation can carry its own marks. Needs an owner.
Co-authored-by: Clint Borle <[email protected]>
2026-09-14 19:59:26 -05:00
Bilawal Sidhuandrileygramlich 409e27d7f9 feat(cctv): add the Open Calgary camera pack (#514)
Supersedes #438 by @rileygramlich, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: rileygramlich <[email protected]>
2026-09-14 19:45:52 -05:00
Bilawal Sidhuandvegettto a04502559e docs(cctv): correct the panel reset instructions to the current storage key (#509)
Supersedes #408 by @vegettto, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: vegettto <[email protected]>
2026-09-14 19:42:24 -05:00
Sameh Khamisandmanjunath22466 87629ac175 Port ALPR camera visuals into the shared layer
Add camera badges, gradient direction wedges and animated tactical selection cards while preserving bounded loading and layer lifecycle. Align the ALPR data-layer header and retain native pick ownership for overlay badges.

Co-authored-by: manjunath22466 <[email protected]>
2026-09-14 17:35:24 -07:00
Bilawal SidhuandPedro Lobato 70dca86bc1 fix(pinokio): disclose incoming changes before Update pulls and installs (#507)
Supersedes #356 by @Lob26, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Pedro Lobato <[email protected]>
2026-09-14 19:34:23 -05:00
Bilawal SidhuandMemel 8702458cf6 perf: subset the icon font and drop the unused second family (#513)
Supersedes #239 by @mml-studio, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Memel <[email protected]>
2026-09-14 19:21:38 -05:00
Bilawal SidhuandMaher Kurdi da700be77f fix(cctv): bound the Range header and release abandoned camera streams (#512)
Supersedes #253 by @Maher-Reven, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Maher Kurdi <[email protected]>
2026-09-14 19:17:52 -05:00
Bilawal Sidhuanddaikaginza 687edc4da7 test: check the destination preset table as data (#506)
Supersedes #168 by @daikaginza, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: daikaginza <[email protected]>
2026-09-14 19:08:00 -05:00
Bilawal SidhuandVassago DevTeam a1d0a42450 fix(test): resolve the macOS temp root through its symlink in the launcher and preview tests (#501)
Supersedes #301 by @VassagoDevteam, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Vassago DevTeam <[email protected]>
2026-09-14 18:55:24 -05:00