36c0cfa5abaad671ad9e7bc54b06d4302ca35210
Replaces the hands-free audio assist after extensive on-device iteration (full journey + rejected approaches in AUDIO_DESIGN_LOG.md; current design in SOUND_DESIGN_HANDOFF.md, from Jay's sound-design sessions). Surface (TONES) = continuous proximity ticking: tick.wav repeats faster as you near level (axis-agnostic warmer/colder, the rate is the message). - Exponential rate in stable tilt error, clamped 1.5/s (>=~5 deg) to 8/s (<=~0.4 deg), hard-capped; constant loudness (acceleration is the signal). - Deadline scheduler off a monotonic clock (SystemClock.elapsedRealtime): advances a next-tick deadline, so no drift and no catch-up bursts; <=1 tick per sensor update; immediate tick on re-entry (enable/return FACE_UP/unlock). - Lock reuses LockDetector.isLocked (dwell + hysteresis, no second audio threshold): stop ticking, play level.wav once, silence while held. The 1.39s level stream is retained and stopped on unlock/disable so a fresh tick can't overlap its tail. - Pure SurfaceTickPolicy (unit-tested: anchors/clamps, monotonic rates, gating, immediate re-entry, no catch-up burst, level-once, resume on unlock). Voice (VOICE) = settled-change announcer: one correction on the dominant axis, silent while moving, speaks again on settle only if direction changed, crossed coarse->fine, or reached lock. No periodic repeat. (VoiceGuidancePolicy, unit-tested.) Assets: tick.wav + level.wav downsampled to mono 44.1kHz in res/raw (from Jay's SoundQ-derived 96k masters). AudioAssistMode adds OFF/TONES/VOICE. Retired the settle-gated two-ding packet scheduler (AudioAssistStateMachine + its ding assets) - superseded by ticking for Surface; logged as tested/rejected. Edge staircase (1-D, future): 5 pitch-contour masters staged in sonar-staircase-v3/ for when Edge mode is built. 76 tests passing; assembleDebug clean; blessed on-device. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On the Level
Offline-first Android pocket toolset: a trustworthy level, angle meter, and calibrated screen ruler (Pro). Kotlin + Jetpack Compose, single module, no backend.
- BRIEF.md — the authoritative v1 product & technical brief
- AUDIT.md — audit of the brief; the amendments it lists are incorporated
- resources/ — concept board (visual direction)
Building
Open in Android Studio, or:
./gradlew assembleDebug # build
./gradlew testDebugUnitTest # measurement-math unit tests
Scaffold status
The project skeleton follows BRIEF.md §Sensor and measurement architecture. Implemented and tested:
core/sensors— sensor selection (game rotation vector → gravity → low-passed accelerometer), device-frame gravity stream, and the pure measurement math: orientation mapping, two-sample per-mode calibration (derived in angle space, applied in vector space so it stays correct away from zero), EMA smoothing, lock hysteresis/dwell/debounce, display deadband, placement validity, and the sensor-vector contract (all sources emit device-frame world-up; flat = +9.81 on Z, pinned bySensorContractTest). All unit-tested.core/settings— DataStore preferences and per-mode calibration persistence.core/billing— entitlement interface with a stub (free-tier) implementation.feature/level,feature/angle— live numeric scaffolds wired to the real sensor pipeline, with manual Surface|Edge selection, placement-validity hints, lock state (locked label states the tolerance so it can never contradict the rounded readout), and directional hold-to-zero (vector reference, not magnitude subtraction).feature/ruler,feature/tools— static placeholders.
Not yet implemented (deliberately — see TODO markers):
- The tactile vial visuals and the spring-animated display value (value 3 of 3 in the brief); scaffold screens render the deadbanded stable value directly.
- Guided calibration flow UI (math and persistence are done).
- Edge-mode readout counter-rotation on the portrait-locked activity.
- Play Billing implementation of
ProEntitlementRepository. - Screen ruler measurement UI and per-display scale persistence.
- Audio cue, reduced-motion behaviors, preferences UI.
Description
Languages
Kotlin
83.9%
HTML
16.1%