- 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]>
Resolve conflicts with #1234: keep redirect: 'manual' on both DATEX
fetches and keep main's 30 s TARKTEE_FETCH_TIMEOUT_MS. Drop this
branch's 15 s constant and its import, which auto-merged into a
duplicate export. Keep both sets of Estonia tests and drop the 15 s
claim from the changelog fragment.
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]>
in push-to-talk, answer a Gemini tool call that arrives with no input, reply
or tool result outstanding with a failure instead of running it, and refuse
every other call in the reply it starts, including one after unprompted
speech; the reply stays tracked so the next input retires it and its late
boundary cannot close the user's turn
in push-to-talk, a caption that arrives after its turn ended no longer opens
a reply, so the next request is not retired with its tool calls discarded
open mic cannot tell either case from a new reply and stays unchanged
check packet ownership after the narration callback before queuing tools,
and raise the per-connection call history to 4096 IDs
move the pointer turn event, context item and announcement into
pointerContext so the OpenAI and Gemini controllers share them, and drop the
Gemini token route's copy of the shared exact-Origin comparison
- The selected sequence is drawn past the per-tile caps again, and its
highlight takes every loaded part, drawn or not: in a dense tile a
clicked Mapillary or Panoramax line kept its cones but lost its line.
- photoViewer tries :fullscreen and :popover-open one at a time, each in
its own try: Safari before 16.4 parses neither, and the fallback threw
on every flat KartaView or Panoramax photo.
- A lit Street View off Google 3D says it needs the Google 3D map again,
instead of "every provider is switched off".
- Chips carry their provider colour again (--chip-color, as on main).
Each comes with the test that reproduced it.
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]>
- Default backoff is 30 min, longer than the 15-minute catalog refresh,
so a failing Kartverket costs one attempt per backoff, not per refresh.
- A point a 200 answer leaves out is cached as no height (6 h TTL)
instead of being asked again, and waited on, every refresh.
- Only 408, 429 and 5xx stop the lookup; any other 4xx marks that
request's points as no height and the lookup carries on.
- Each request has its own 10 s timeout inside the shared 30 s deadline;
a lookup cut short only by the deadline resumes without a backoff.
- The lane waits only on a cold cache (>10% of cameras missing); a few
new cameras or expired misses are looked up in the background.
- applyVegvesenGroundHeights skips cameras without finite coordinates,
so it really never throws.
- clearKartverketHeightCache bumps a generation, so a lookup started
before a clear cannot write to the cache, backoff or pending slot.
- Credit and DATA_SOURCES note the modification (water set to 0 m,
rounded to 0.1 m) as CC BY 4.0 asks; docs match the stop rules.
- Tests for the deadline being shared, per-request timeouts, 503,
oversized and non-JSON bodies, 4xx, left-out points, Retry-After end
to end, overlapping refreshes, the warm-cache wait, bad coordinates,
the cache-clear generation and the loader's wait budget.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- A background catalog refresh that rejects now keeps the old catalog for
another TTL, as an empty refresh already did, so a refresh that keeps
failing is retried once per TTL instead of on every request.
- Trim notes are keyed by the source list they describe, and /sources asks
for the list it served, so a request answered during a refresh never pairs
the old cameras with the new list's notes.
- Tests: a failed background refresh (one warning, no unhandled rejection,
no retry before the TTL, trim notes stay with their list) and an empty
background refresh (old catalog kept, no upstream fetch before the TTL).
The race assertion's message now names the failure; its timer is cleared.
- The Tarktee test no longer imports the new constant, so on main it fails
on its own assertion instead of taking the whole file down.
- precompute-cctv-heights waits 60 s for a cold catalog, past Tarktee's 30 s.
- CURRENT-STATE notes the 30 s bound and the retry spacing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Assert the key never reaches the camera records sent to the browser or
the "Loaded" log line.
- Count fetches in the keyless test instead of relying on assert.fail
inside the mock, which the loader's catch would swallow; a
whitespace-only key is treated as missing.
- Cover the key hint for 400/401/403 and its absence for 429/500/503,
and log the failure as one string without a trailing empty argument.
- Add _resetOntarioKeyWarningForTest so the logged-once check no longer
depends on test order.
- Read CCTV_ONTARIO_MAX_SOURCES from the same env as the key, and keep
console output out of the suite.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
refreshCctvFocusStyles passes cameraColorFor as baseColorFor, but only
refreshCoverageStyles was tested. The new rendering.test.mjs runs the
focus pass through createRendering with stubbed focus services and
checks that an idle video camera fades from violet, a still from cyan
and the active camera from amber. It fails if the focus callback goes
back to the old active/idle check. Also adds the missing semicolon on
the policy.js import in cctv.test.mjs.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Drive drawProjectionFrame with a fake runtime and a recording canvas:
a 640x480 still draws at its fitted rectangle over the matte, the same
pixels at the same size skip the redraw, and the same pixels at a new
aspect redraw at the new fit. The last case fails on the pixel-only
signature; the first fails if drawImage stretches to the canvas again.
Expected rectangles now read the canvas size from policy.js.
Co-Authored-By: Claude Opus 5.5 <[email protected]>