Camera catalog image URLs were pinned by string prefix, so a URL that only
began with the agency's directory before dot segments or an encoded separator
were resolved still counted as inside it. The pin now parses the URL and
requires the same scheme, the exact host, no credentials, the default port and
a normalized path inside the pinned directory. Redirects on a pinned host must
stay inside the same directory.
Document the response format checks and API response headers alongside the
existing server hardening notes.
CCTV frames and the Street View fallback accept only JPEG, PNG, GIF, WebP and
AVIF, parsed from the media type essence and sent under the canonical type;
any other type is cancelled and falls through to the next fallback as a
failed upstream does. Live media must match its feed kind (video/mp4,
video/webm, or multipart/x-mixed-replace with a boundary) before the camera
is reported healthy or any byte is relayed, and its redirects now stay on the
registered origin like frames. Every /api/cctv route uses the same-site gate.
The GBFS proxy relays only bodies that parse as JSON, re-serialized under a
fixed application/json type.
Merge origin/main and retain both format-scope additions.
Give StarrySky a separate black environment cube map and release it on destroy.
Guard anime updates when StarrySky is absent, require a visible Normal sky
before anime QA, and compare a lit airplane against black and white controls.
Document the sky background contract and its verification.
Co-Authored-By: GPT-6 (Codex) <[email protected]>
- taiwan.js: a failed download serves the last good table (up to 24 h)
and is not retried for an hour. The table host does not answer from
some networks outside Taiwan, and each attempt held the shared catalog
refresh for the ~10 s connect timeout.
- Own server/providers/cctv/taiwan.js in package-boundaries.json
(check:boundaries failed).
- Decode numeric character references; name falls back to the CCTVID
when a row has no road details.
- Credit names the dataset and links the OGDL Taiwan licence.
- Document CCTV_TAIWAN_URL; list Taiwan in the CURRENT-STATE source table.
- Tests: isolate catalog env, reset loader state, cover the byte cap,
failed fetch, backoff, last-good fallback, cap clamping, redirect with
a valid body, name fallback, numeric entities and UUID camera ids.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fetch keyless DATA.GOV.HK camera locations at runtime and pin stills to
tdcctv.data.one.gov.hk with required attribution. Default cap 1,100 covers
the ~1,013-camera TD catalog, prioritized across Hong Kong Island, Kowloon
and the New Territories.
Co-authored-by: Cursor <[email protected]>
- Google 3D: the OPEN button re-measures a ground whose tiles are still
loading (a few times, a second apart) and on a map change, not only
after the next camera move.
- Mapillary: two mounts on one host during the first download share one
build instead of leaking a second WebGL viewer.
- Retired floating-panel keys (v8 panelPos, panelFloatHintShown) are
dropped from localStorage; dead inline-position resets, the drag JSDoc
and the dead qa-ui-disposal observer branch are gone.
- Docs: z ladder, panel chrome, position storage and the fixture gate's
actual coverage; changelog fragment for #974 (old .gev-cache/mapillary
can be deleted).
- ru/es: the layer is named as everywhere else in the UI.
- Fixtures and test fakes: unused exports removed; a fake credit removal
of an absent credit no longer drops another one; the tile test reset
frees upstream slots.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The far-plane comment said z = w (the code puts z just under w), the Milky
Way constant is a brightness, not an opacity, and the CDS acknowledgement
lives in the Data attribution popover, not DATA_SOURCES.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- qa-anime-sky keeps only the Milky Way case; the satellites and keyless
cases checked an anime shader this branch no longer changes.
- Drop qa-sky-sun-moon.mjs: the viewer-options unit test covers it.
- VisualEffects sets the sky's visibility directly: the viewer always
carries a StarrySky and never outlives the effects.
- Drop the unused star intensity knob, the malformed-row tolerance for
our own pack, the test-only Transforms parameter and a private-name test.
- DATA_SOURCES points to sky/README.md instead of repeating it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Scene reads skyBox._cubeMap as the environment map that lights models, in
the TEME, flipY layout of Cesium's own sky box; the ICRF Milky Way would
light them rotated. Rename the field so models keep Cesium's default.
Test the anime fade on a real StarrySky and that the viewer gets the sky
as an option (skyBox: false would drop the Sun and Moon). Correct three
comments on the star limit and the Milky Way levels.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The fine 0.4 degree blur kept the residual glow of unresolved stars as
mottled patches at the band's edges. Blend towards a 2 degree blur where
the coarse copy is faint (smoothstep over 0.5-8 % of the range), so the
core keeps its dust lanes and the faint sky goes smooth. Faces 85 -> 62 kB.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
page.waitForFunction polls on requestAnimationFrame by default. In a
minimised or hidden headful window rAF stops while timers keep running, so
each 120 s slice only checked the predicate when it started: a drain that
finished in the last slice was recorded as a FAIL on the sign-off path.
- waitForPredicate replaces waitForFunctionSliced and the other three
waitForFunction calls: one short page.evaluate per tick (1 s for the
drain, 250 ms elsewhere), a monotonic performance.now() deadline, retry
across a context swap, and a throwing predicate fails the run instead of
silently spending the budget.
- One in-page window.__qaRenderFrames(count, capMs) helper serves both the
gizmo-drag and the sibling-owner frame waits.
- The sibling pick counts as a stalled renderer only at 0 of 3 frames, so a
slow SwiftShader frame still reports a real miss; the record flattens and
prints the frame count once.
- Review screenshots log and continue when a capture fails.
- Launch with pipe: true (no localhost CDP port) and protocolTimeout
300_000 like the other harnesses; drop the occlusion flag that puppeteer
already passes by default.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
When the sibling-owner pick misses after fewer than 3 rendered frames, the
cause is a stalled renderer, not a pick regression. Record it as a failure
on the headful sign-off path and as inconclusive under headless GL, with
"renderer stalled: N/3 frames" in the detail. A missed pick after 3 frames
still fails in both modes. Also corrects the catalog-size comment (~3,700).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The headful drain budget is uncapped (camCount * 800 + 30000 ms, ~50 min
at N≈3,700), but each page.waitForFunction is one CDP call that puppeteer
aborts after its 180 s default protocolTimeout. The .catch then recorded
"timed out waiting for drain on the real-GPU sign-off path" after ~3 min.
- Poll the drain in <=120 s slices (waitForFunctionSliced) so no single
CDP call outlives protocolTimeout, whatever the catalog size.
- Launch with protocolTimeout 240 s, headroom above the largest slice and
the 60 s fixed waits.
- Bound the sibling-owner 3-frame postRender wait at 10 s and report the
frame count, so a renderer that stops producing frames fails with
evidence instead of hanging the evaluate.
- List --disable-backgrounding-occluded-windows explicitly. Puppeteer
25.10 already passes it by default, so this documents the headful
contract rather than changing behaviour.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Conflicts: the Street Level and Gemini voice strings both appended to the
es/ru catalogs, and both sides' modules to package-boundaries.json — kept
both. scripts/qa-panel-resize.mjs stays deleted (floating panels removed).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Away from the galactic plane the ESO panorama keeps a mottled glow of
unresolved stars and dust. With the black level at the darkest quarter of
the sky and a hard cut, it showed as grey clouds with black holes around
the globe. The black level now sits at the median sky and eases in with a
soft knee on luminance, keeping each pixel's hue: high galactic latitudes
are black, the band keeps its glow. Faces shrink from 247 to 85 KB.
The changelog fragment also notes the anime fade and the new asset weight.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- VisualEffects.destroy() puts skyBox.milkyWayVisibility back to 1, as it
already restores the borrowed bloom stage, so a surviving viewer does not
keep a faded sky.
- Rename scripts/qa-anime-space-mask.mjs to qa-anime-sky.mjs: rewrite the
header for the current approach, drop --space-expr and --repo, import
puppeteer as a package, reject unknown cases and count the milkyway case
as reached only while the anime stage is on.
- Put both sky QA scripts under format:check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The far-plane mask in the anime shader read the post-process depth, which
cannot tell the sky from far geometry: with a layer that clamps the near
plane to 0.1 m (satellites) the whole Earth lost its cel bands, keyless
terrain above the ellipsoid horizon did too, and the atmosphere, Sun and
Moon stopped banding.
Restore the anime shader from main and fade the Milky Way glow with the
style instead: VisualEffects sets skyBox.milkyWayVisibility to
1 - anime intensity. scripts/qa-anime-space-mask.mjs checks all three
cases headless and that the anime sky shows no bands.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On CI's SwiftShader the ground-clamped cones take a few frames after a
sequence is selected; a single pick search found none.
Co-Authored-By: Claude Opus 5.5 <[email protected]>