# HeadScroll 0.1.0 — measured validation 11 October 2026. Windows 11 Home 10.0.26200 x64; Intel Core i9-13900HX, 32 logical CPUs; integrated camera 0, DirectShow. Developer machine, not a clean Windows VM. This is a working prototype with a real portable executable. A broad compatibility or accuracy certification has not been completed. Public source includes the camera-off packaged UI/model checks and reproducible test scripts. Raw human hardware-session logs remain local; filenames below identify that retained evidence and do not imply those raw logs are published. The suite was rerun on 15 October 2026: 96 passed. ## Observed evidence | Check | Result | Evidence / limits | |---|---|---| | Automated logic and regression checks | 96 passed | `tests/`: pitch signs, scaled/invalid matrices, mixed yaw, dwell, hysteresis, reversal, frame-rate independence, stale generations, no burst, profile/config validation, atomic Undo preserving global safety preferences, final dispatch guards, calibration Finish, safe quit during blocked assistant setup, diagnostics copy/scroll/export, private-path omission, persisted setup/view, abrupt process exit, concurrent save rollback, camera switching and queued Enable cancellation | | Independent pose/control and Windows review | Material findings corrected | Reviewers reproduced and rechecked matrix axes, invalid timestamps, unstable neutral, wizard gates, stale final snapshots, hover changes, clutch and pause races. These are code/replay reviews. | | Integrated camera, real face | 386 / 386 processed frames contained one detected face | 15.06-second local numeric probe after opening privacy shutter. No frames saved. Does not establish pose accuracy or a completed guided calibration. | | Camera resolution / throughput | 640 × 480; 25.63 processed fps including startup | 30 fps requested; median inference 10.01 ms, median host-dequeue-to-inference 12.25 ms. `camera-face-probe.json` | | External visible Windows scrolling | Down and up observed | Disposable Qt QTextBrowser in another process: scroll position 0 → 120 with negative wheel input, then 120 → 60 with positive input; 36 events of 10 wheel units. Pointer inside target. `scroll-probe.json` | | Real local model, source integration | Proposal / validation / Apply / readback / Undo passed | Installed `qwen3:1.7b`, real LangChain ChatOllama; speed 600 → 300; forbidden safety field rejected. Temporary profile only. `assistant-probe.json` | | Source GUI | Four tabs, light/dark, 1180 × 900 and 880 × 700 rendered | Camera off and paused; Test button arms a real five-second countdown. `ui-smoke.json`, `ui-*.png` | | Real assistant through source GUI | Preview / Apply / Undo passed | Real QThread request, visible table 600 → 300, button-driven Apply/readback and Undo; forbidden safety proposal rejected; 9.49 seconds. `source-assistant-ui.json` | | Portable EXE model and GUI | Passed on developer Windows machine | Bundled actual vision model loaded, blank frame correctly returned no face; x64 INPUT=40 bytes, MOUSEINPUT=32; four packaged GUI tabs rendered. `packaged-self.json`, `packaged-ui.json` | | Packaged assistant GUI cycle | Verified with real installed model | Latest rebuilt EXE: QThread request, visible preview 600 → 300, button-driven Apply/readback and Undo; forbidden proposal rejected; 17.54 seconds. `packaged-assistant.json` | | Guided human calibration and practice | User confirmed both directions and neutral stop | Live packaged wizard produced both directions and displayed Neutral.Stopped. User reported Finish completed. Latest refinement saves calibration across sessions and makes that wizard optional. `guided-calibration.json` | | Saved calibration and view | Automated/replay verified | Numeric proper-rotation/direction roundtrip, each camera slot, old-config migration retaining ranges, cancellation, failed atomic replace, simultaneous preference write, view before close and a subprocess exiting abruptly after Recenter. No camera images; quick-setup direction still needs human confirmation. Packaged `--ui-test` verifies restored setup/view, paused and camera off. | An initial external-reader probe sent events but did not scroll visibly with the pointer outside the reader. It was treated as a failed compatibility observation, then repeated with the pointer inside. “Events sent” is never counted as visible success. Chrome launching through PowerShell was rejected by automatic approval review with “blocked by policy”; no successful browser-scroll claim follows from that attempt. ## Compatibility matrix | Application / scenario | Status | Exact remaining check | |---|---|---| | Disposable external Qt reader | Native down/up measured; human head test failed | User reported head-driven scrolling failed. Old EXE diagnostics showed PAUSED, events 0, camera active with 4971 frames and no error; separate movement is not attributed to head input. Updated diagnostics expose enable/calibration/practice/blocking state for the retest. | | HeadScroll sandbox | Live packaged practice and human direction confirmation | User confirmed chin up moved down, chin down moved up, neutral stopped, and calibration finished. This establishes one user's practice result; it does not measure sensor latency or accuracy. `guided-calibration.json` | | Chrome long page and nested container | Pending | Establish intended foreground/container and observe scroll position; a local HTML fixture is supplied | | Edge | Pending | Same visible-scroll test; no claim from shared Chromium engine | | Firefox | Pending | Visible partial-wheel accumulation and neutral stop | | PDF viewer / browser PDF | Pending | Observe scrolling in a disposable PDF; choose manual browser-PDF profile | | Microsoft Word | Installed, pending | Disposable long document, visible up/down and modifier checks | | File Explorer | Pending | Disposable file list, correct target, app switching | | Focus / hover races, modifiers, additional faces | Replay verified | Real multi-app switching, typing, held modifiers/buttons and second-person camera test | | Windows sleep / lock | Native handlers and long-gap replay verified | Physical sleep/lock, resume held-tilt test on this machine | | Multiple monitors / different DPI settings | Pending | Current-machine GUI captures only; no multi-monitor certification | | Elevated apps / UAC / secure desktop | Deliberately blocked by guards | Read-only desktop/integrity probes and replays; real protected-surface check pending | | Games / protected surfaces / remote sessions | Untested | Explicit app-specific testing required; no privilege bypass | | Offline clean Windows without Python/Ollama | Pending clean-machine test | EXE bundles interpreter/model and starts without a developer shell here; this is not proof on a clean installation | | Ten-minute neutral reading/typing pilot | Pending | Human reading/typing with numeric event log and any unintended events recorded | ## Performance and timestamp limits The face-camera probe used about 49.33% CPU on the psutil **one logical CPU = 100%** convention, and reached 164.82 MiB process RSS. On a 32-thread machine this CPU figure is roughly 1.54% of total logical capacity; it is not a Windows Task Manager reading. A separate short, non-isolated 12-second observation (`benchmark.json`) measured the HeadScroll Python process at 66.38% one-core CPU / 159.78 MiB mean RSS with vision, and 135.31% / 205.29 MiB while a real local help request was running. The request took 9.60 seconds. **Ollama server/runner resource use is excluded.** These observations include startup and concurrent developer activity, not steady-state packaged UI performance or a ten-minute pilot. The camera backend rejected CAP_PROP_BUFFERSIZE. Timestamps are host frame-read/dequeue completion times from `perf_counter`, not verified sensor-exposure times. A one-frame application mailbox prevents an application queue, but cannot prove the absence of driver buffering. A read stall ends the session and requires reopening/resume; calibration remains saved. Recenter if seat or camera angle changes. Full sensor-to-output latency, human neutral/pause stop within 150 ms, loss stop within 250 ms, and human tilt start within 400 ms remain unmeasured. The controller replays verify immediate observed-neutral clearing, 180 ms default cached-frame expiry, a fixed 250 ms worker-heartbeat expiry, no output after expiry, and no catch-up burst. Manual frame expiry is bounded to 150–200 ms and cannot be changed by the assistant. The user reported a camera-off transition without clicking Disable; a later live snapshot showed normal DirectShow processing, no camera error and 4971 processed frames. Its cause was not established. The external reader attempt remains failed until a successful head-driven observation. The user also reproduced diagnostics scroll/copy resetting: replacing all text every 80 ms was the cause. The updated UI throttles live snapshots, preserves scroll/selection, provides explicit Copy/Refresh/Export, and keeps export confirmation visible. Export regressions cover calibration/output flags and omission of private filesystem paths. The shipped archive is checked against its SHA256 manifest, including the executable, vision model, Qt Windows platform plugin, documentation and LGPL text. The matching `.zip.sha256` file records the current archive hash. The EXE has version metadata 0.1.0 and is NotSigned. ## Reproduce and finish validation Run `scripts/bootstrap.ps1`, then `.venv/Scripts/python.exe -m pytest -q` and `scripts/build.ps1`. Camera probe: `scripts/probe_camera.py` (numeric only; no frames). Real assistant: `scripts/probe_assistant.py`. GUI render: `scripts/smoke_ui.py`. Disposable external reader: `scripts/probe_scroll.py`; establish the target and pointer using normal interaction, then confirm the saved scroll positions. The packaged diagnostic flags `--self-test`, `--ui-test`, and `--assistant-test` each take an output JSON path. They do not open the camera or emit wheel input. The assistant diagnostic uses an already installed qwen3:1.7b and a temporary profile, with visible Preview, Apply and Undo controls. All hardware/manual rows above must retain their pending status until genuinely observed.