The pre-push gate linted only the dirty tree, so the commits about to be pushed went
unchecked; and every failed overlay projection was sticky, which cost a finger result its
overlay over one bad frame while box results were retried nowhere. gate.ps1 now takes
-LintBase (default origin/main, exit 2 on an unknown ref), the projector declares whether
its own failures are permanent, and serve_stored_view decides before it sets the view.
Verified with gate.ps1 (PASS: 569 studio + 485 shared tests, 632 ui_check checks) and the
two round-2 red samples kept in scratch.
Drop orisys.util.draw_arrows; box live and replay both use
_paint_shared_flow_arrows with sdk_box_policy when no policy is passed.
Recovered box flow uses the same inverse as finger. Verified with
shared/tests/test_image_backend.py arrow/idle/recovered cases.
Replay left the 3D pane on the rest mesh or a sparse overlay, and Analyze skipped the setup dialog unless the file was re-picked. Live Run no longer starts a chain on a video path. Verified with Studio tests for flush, overlay mask, Analyze open, live-video refusal, and locales.
Box analysis used the finger sample grid, so replay packed arrows into the contact zone. The pass now stores draw_arrows cells; stale box caches miss and re-run. Verified with shared and Studio tests, including a live-vs-replay canvas check.
Opening a recording while the session that recorded it was still live never reached
``stored_result()``, so the panel reported no result over a recording whose result was on
disk. The guard now follows the cache read, results move to the app's derived-data root
(swept at startup, the old in-recording root ignored), and the panel states which of the
four no-result states it is in, with the pass's own reason.
Verified: apps/studio 462/0/18, shared 431/0/1, autocal 358, ui_check 628/0, both gates
clean, real-GL snapshots per state.
A replay could draw arrows but not depth, and the recording view said there was
nothing to draw even when a result existed. Depth is now quantised per frame
(14 B empty, 486 B at the worst frame seen), read from the cache by the same
draw path live uses, and the raw-recording note appears only when no result
exists. Format version 2; see apps/studio/docs/replay-analysis.md.
Replay re-ran the SDK chain on every seek: 0.48-0.51 wall-seconds per video
second, about 4.8 minutes for a ten-minute recording. The new
orisys_app_shared.analysis package runs that pass once and stores the flow
samples a replay draws - 4,034 B per frame at the shipped finger grid instead of
the chain's 1,176,000 B; the result contract is in
apps/studio/docs/replay-analysis.md.
Verified: shared/tests 416 passed / 1 skipped (15 new) and apps/studio/tests
unchanged at 425 items / 0 failed / 18 skipped; tools/lint_gate.py clean; a
264-frame pass costs 0.5036 wall-s per video-s against 0.5052 for the bare chain
measured the same day.