You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refitting an earbud on a multi-display setup no longer requires recalibrating every screen. The AirPods yaw datum is arbitrary per connection, but the angles between displays are not, so one aim restores the whole layout: an "Aim here" target appears at the center of the covered screen, and facing it and tapping resumes protection immediately, reusing the saved per-display calibration. The menu bar panel offers "Recenter" as well, with a 3-second countdown.
Recentering is available by hand whenever a screen is covered, so boundaries that feel off can be re-aimed without a full recalibration.
Fixes and reliability
Fixed saved settings appearing to vanish after removing and refitting an earbud. A multi-display setup was marked as needing recalibration on every tracking loss (and every launch); the per-display profiles stayed on disk but went unused, and recalibrating then overwrote them. A one-tap recenter now covers this.
Fixed drift correction becoming permanently unusable in a long session. Learning ran only while uncovered, and samples were only collected inside the work area, so once drift pushed the head past a boundary the two conditions deadlocked and the correction froze until a recalibration. Stationary poses are now collected while covered, and if the work area stays unreachable for 3 minutes while the head is parked steadily just outside it, the work area re-aligns and the screen is revealed.
Fixed the work area jumping off-target after a brief AirPods dropout. A sensor time gap now clears only the sample buffer and keeps the learned correction. Physical drift does not reset because the stream broke, so discarding the correction snapped the work area back by exactly the drift it had removed — usually straight into the deadlock above.
Removed the fixed ceiling on accumulated correction (previously min(15°, smallest boundary × 0.5)). Drift grows without bound, so any fixed ceiling is eventually exceeded and leaves the work area permanently offset; narrow work areas were capped hardest. A wrong correction is now contained by the per-check slew limit, a symmetric acceptance window, and the spread gate, with a 90° runaway guard.
Added drift-rate feed-forward. A pure proportional controller trails steady drift by a fixed residual, which was consuming boundary margin for the whole session.
Fixed censoring bias in sampling. Samples were clipped at the work-area boundary, which pulled the median back toward the center and under-estimated the drift — worsening as the drift grew. Samples now come from a symmetric window around the current center.
Single-display setups now get drift correction too. Only per-display calibration ran through the estimator; the single-profile path relied on recentering after a dropout, which did not match the README.
Tightened the steady-state step to 0.5° (the first 90 s after calibration still uses 1° to clear a pre-existing offset), keeping it near the real drift rate so sitting off-center is less able to drag the work area.
Sample throttling is now per display instead of shared.
Verification
11 new tests: recovery past a boundary, no recovery on a deliberate large turn, no recovery on a short stall, no recovery on an unsteady pose, no recovery when the display is ambiguous, corrections kept across a stream gap, large drift tracked in a narrow work area, steady-drift residual, seam-crossing sample throttling, and single-display drift correction.
Each calibrated screen now exposes editable left, right, upper, and lower angles under “Calibrated Screens”; changes apply and persist immediately without recalibration.
Fixes and reliability
Improved drift correction: the first samples are no longer locked as the zero baseline, so sensor offset already present at calibration time is removed gradually.
Raised the per-step correction cap from 0.5° to 1° (up to about 6° per minute) and now corrects pitch drift alongside yaw drift.
Added drift diagnostics: per-screen correction totals, valid-sample counts, and the current status (including skip reasons such as insufficient samples, short windows, wide spread, and suspended learning). Every correction and reset is written to the Privacy log category for inspection in Console.app.
Added a preview build switch: HEADUP_PREVIEW=1 ./script/build_and_run.sh build (debug) or HEADUP_PREVIEW=1 HEADUP_SIGNING_IDENTITY=- ./script/package_release.sh (release) compiles with -DHEADUP_DEBUG and records per-second debug traces (sample attribution, speed gating, corrected centers and offsets per screen); these hot-path traces are compiled out of release builds.
Removed the tick marks under every settings slider in favor of continuous tracks that still snap to the previous increments.
Verification
Added tests for pre-existing offset removal, pitch drift, suspended-learning diagnostics, insufficient-sample diagnostics, per-screen angle persistence, the debug-trace switch, and source-to-table localization coverage; both normal and preview builds compile cleanly.
Added optional AirPods-based screen protection that covers every connected display when the wearer turns outside a calibrated work area.
Added five-step calibration for the center, left, right, upper, and lower work-area boundaries, with independent angle and response-delay controls.
Added blur-and-dim and solid-color overlays with system date and time, optional Open-Meteo weather, and custom text.
Reorganized settings into General, Posture Reminder, Screen Protection, and Overlay Content tabs, with quick protection status and controls in the menu bar dashboard.
Reliability and privacy
Added hysteresis and separate cover/reveal delays to avoid flickering near a boundary.
Kept protection active when AirPods tracking is lost, with an Esc escape path, and filtered duplicate Core Motion frames from liveness checks.
Saved the four-direction calibration locally, kept it when one AirPod is removed or tracking briefly reconnects, and automatically recentered protection when fresh motion data resumed.
Kept head-orientation processing local; optional weather requests send only the configured city to Open-Meteo.
Verification
Added tests for four-direction boundary detection, wrapped yaw calibration, persistence, weather-code mapping, and duplicate motion samples.
Verified the settings tabs, full-screen blur preview, Esc recovery, application build, and launch flow.