11 KiB
God's Eye View — Testing Guide (voice map-annotation whiteboard + live tracking)
[!NOTE] This is a manual field-test scenario script for the June-2026 whiteboard + tracking work. The AUTOMATED gates live elsewhere:
npm test(unit),npm run test:track(tracking invariants), and the headless harnesses underscripts/qa-*.mjs— together these are the full automated test surface.
This guide covers the work hardened over 4 adversarial-review batches on
feat/annotate-hybrid. Record a voice note + screenshots as you go; each scenario
lists what ✅ pass looks like and (where it applies) the ❌ old bug it replaces.
Focus/horizon moving evidence
With the Vite development server already running on port 4173, capture all four focus/recession scenarios with a deterministic virtual frame clock:
node scripts/qa-focus-evidence.mjs --url http://localhost:4173 \
--screenshots-dir qa-shots/focus-evidence \
--json qa-shots/focus-evidence/report.json
For a quick operator loop, --smoke captures only S1 in six frames. For visual
sign-off, add --headful; this removes the SwiftShader launch flags and uses
the machine's real GPU. The harness brings its page to the foreground at the
start of every scenario so a headful Chromium run keeps streaming tiles.
Google 3D remains the default basemap. If its tile stream is the bottleneck rather than the behavior under test, select an existing map stack explicitly:
--basemap bing-aerial
--basemap osm
Accepted values are photoreal, bing-aerial, bing-labels, and osm; Bing
stacks still require the app's usual Cesium ion token.
Tune both systems without editing source by adding, for example:
--params '{"focus":{"dimFloor":0.35,"nearerBehavior":"partial"},"horizon":{"scaleFloor":0.5,"alphaFloor":0.4}}'
The script never starts the server. During scenarios it pauses Cesium's default
render loop, advances focus time explicitly, and renders each frame before the
screenshot, so computed alpha/scale sequences repeat for identical parameters.
Headless Chromium still forces SwiftShader, so its pixels are relative CI/A-B
evidence only; headful real-GPU output is the sign-off surface. Screenshots use
scenario/frame names and the JSON report records effective tuning plus
per-contact alpha, scale, and screen data. Before each scenario's first capture,
the harness gives the active Google photoreal tileset up to 45 seconds to reach
Cesium's tilesLoaded/allTilesLoaded condition. Every frame records
tilesSettled: true|false and whether that gate applied; a timeout is recorded
as false, never promoted to a pass. Non-photoreal stacks record the gate as
settled and not applicable because no Google 3D tileset is active.
[!IMPORTANT] Do not use a screenshot for visual judgment unless its report frame records
tilesSettled: true.
Setup
- URL: http://localhost:4173 — auto-flies to Austin on load. Give photoreal tiles ~10s.
- Voice (the real feature): click GEV MIC (bottom of screen) → wait for LISTENING →
just talk. It marks the map as it talks, without announcing that it's drawing. Click
STOP when done. (Needs
OPENAI_API_KEY;dev-fresh.shinjects it from Keychain.) - Console (deterministic, no mic/live-data needed): open DevTools (Cmd-Opt-J) and use:
window.__gevAnnotations.tour()— self-running narrated SF tour (camera + marks in sequence)window.__gevAnnotations.demo()— lays the SF set down at oncewindow.__gevAnnotations.clear()— erase all markswindow.__gevAnnotations.count()— how many marks are live
What changed (the list)
Live aircraft tracking & camera (Batch D) — civilian + military, mirrored:
- R14 warm-up: tracked plane glides immediately (no freeze-then-jump / backward snap), via a display-layer reconciliation that smooths any position discontinuity over ~0.9s.
- R15 framing: calibrated initial follow distance (altitude-scaled, 3–30 km).
- R16 trail: head stays glued to the moving icon per-frame; never trails ~1s behind or pokes out in front of the nose.
- R13 z-order: screen annotations fade where they'd cover the tracked plane + its label.
Voice annotation — scoping & honesty (Batch B):
- R1 resolver scope: a place name resolves to the right thing (building vs neighborhood vs natural feature vs city) instead of an oversized admin blob.
- R2 boundary stitching: complex outlines no longer close with bay-spanning chords.
- R6 route honesty: a routing outage draws a labeled straight "direct line", never a silently faked road.
- R12 partial honesty: if some targets fail, it says so — no masking partial as success.
- R10 cache: transient failures aren't negative-cached for the whole session.
Annotation rendering & motion (Batch C):
- R8 route flow: route dashes animate (flow along the path).
- R9 / R17 perf: idle annotations stop their animation loop; height cache is bounded.
- R11 no-freeze: large/complex boundaries simplify without locking the UI.
Abuse guards (Batch A) — mostly internal: input caps on annotate_map, clear/new-topic
cancellation, hardened Overpass + route proxies. Not much to see by hand (see §4).
1. Live aircraft tracking (Batch D) — the 3 issues you reported + z-order
Needs a live plane. Track by clicking a plane icon; Esc (or click empty space) untracks. If you see no planes, scroll out once — Texas airspace is busy.
1a · Warm-up smoothness (your issue #1 → R14)
- Click a moving plane. 📸 Snap the instant it locks, then watch ~2–3s.
- ✅ Starts gliding smoothly immediately. ❌ Was: froze ~1s, then jumped forward.
1b · Initial framing (your issue #2 → R15)
- On the same lock-on, look at how the camera frames the plane. 📸 Snap the initial view.
- ✅ Plane + label readable with context, no scrolling. ❌ Was: jammed in too tight.
1c · Trail glued to the plane (your issue #3 → R16)
- Keep tracking ~10s. 📸 Snap the cyan trail while it moves.
- ✅ Trail tail stays attached to the plane; nothing pokes out in front of the nose; no ~1s lag. ❌ Was: trail lagged a beat behind.
1d · Military layer (same fixes, mirrored)
- Enable the Military layer (left column). Track an amber plane. Repeat 1a–1c.
- ✅ Identical smooth behavior.
1e · Z-order: tracked plane stays on top (→ R13, trickiest to stage)
- While tracking a plane over Austin, GEV MIC: "annotate downtown Austin."
- Orbit/zoom so the plane crosses the annotation's outline or label. 📸 Snap the overlap.
- ✅ The annotation dims where it covers the plane/label — plane stays visible on top. ❌ Was: the annotation drew over and hid the plane.
2. Voice annotation — scoping & honesty (Batch B)
All from the Austin default view (no camera move needed). Click GEV MIC, then speak.
2a · Scope: building vs region (→ R1) — say each, watch what gets outlined:
- "annotate the Texas State Capitol" → ✅ the Capitol building, not the whole state.
- "annotate Barton Creek" → ✅ the creek / greenbelt, not Barton Creek Mall or the city.
- "annotate downtown Austin" → ✅ the downtown district, a sensible neighborhood-size area.
- "annotate the University of Texas at Austin" → ✅ the campus, not the city.
- 📸 Snap each outline. ❌ Was: incidental names ballooned into giant county/state blobs.
2b · Classic SF set (optional) — first say "take me to San Francisco," then:
- "annotate the Mission District" → neighborhood. "...the Presidio" → the full former-base outline (not a single point, not a bay-spanning blob → R2). "...Chinatown" → the district.
2c · Route honesty (→ R6)
- "draw a route from Austin-Bergstrom airport to the Texas Capitol."
- ✅ A real road route with a flowing dashed line + a labeled callout.
- If a route ever comes back as a straight line, it should be labeled as a direct/approx line (not pretending to be a road). ❌ Was: silent fake straight-line "routes."
2d · Partial-failure honesty (→ R12)
- "annotate the Texas Capitol and the Flibbergibbet Building."
- ✅ It annotates the Capitol and tells you it couldn't find the other one. ❌ Was: reported success and silently dropped the missing one.
2e · Clear / new-topic race (→ R4)
- "annotate downtown Austin" and, right as it starts, "actually, clear everything."
- ✅ Marks clear and stay cleared (the in-flight one doesn't pop back a second later).
- Sanity in console:
window.__gevAnnotations.count()→0after a clear.
3. Annotation rendering & motion (Batch C) — deterministic, no mic
3a · Full experience (smoke test)
- Console:
window.__gevAnnotations.tour(). 📸 A couple of frames as it runs.
- ✅ Camera flies to SF; Palace highlight → arrow → Presidio draped outline → ILM pin → Crissy Field route appear in sequence; marks stay glued as the camera moves.
3b · Route dashes animate (→ R8)
- During/after
tour()(ordemo()), watch the route line (Crissy Field shoreline).
- ✅ The dashes flow along the path (animated), not static. ❌ Was: dashes never moved.
3c · Draping & persistence
- After
demo(), orbit the camera around the Presidio outline.
- ✅ The footprint drapes onto the 3D ground/buildings and conforms; callouts/rings/arrows are the hand-drawn SVG style and stay anchored to their real spot.
3d · Large boundary, no freeze (→ R11)
- Console:
window.__gevAnnotations.annotate([{type:'area',target:'Travis County, Texas',label:'Travis County',color:'green',footprint:true}],{flyTo:true,persist:true})
- ✅ The complex county boundary simplifies and draws without freezing/janking the UI.
4. Robustness / guards (Batch A) — mostly internal
These are server-side / defensive and don't have a clean visual tell. Light checks only:
- Rapid-fire several annotate commands, then a clear — UI should stay responsive and end clean
(
count()→0). - Nothing here should change normal behavior; flag it only if something feels broken (stuck spinner, marks that won't clear, errors in the console).
5. General feel — open feedback
While recording, call out anything in these areas — this is the feedback I most want:
- Tracking feel: does follow motion feel smooth/natural, or floaty/laggy/overshooting?
- Framing: is the initial tracked view a good "hero" shot, or too close/far?
- Annotations: do outlines land on the right thing? Are labels readable / well-placed / not overlapping? Does the hand-drawn style read well over photoreal tiles?
- Voice: does it mark things as it talks (not after), and confirm only what actually happened? Any command it misunderstood?
- Anything that looks wrong, janky, or surprising — screenshot it; that's the gold.
If something looks off
- Grey globe / slow tiles: wait a few seconds after a camera flight; photoreal streams in.
- A voice mark didn't land: the place may not geocode — try a more specific name (e.g. "Palace of Fine Arts, San Francisco").
- No planes: OpenSky data may be momentarily sparse; scroll out or wait a poll cycle.
- No GEV MIC button / voice errors:
OPENAI_API_KEYdidn't load — use the console API for the annotation tests and skip the voice-only ones (§2).