027b9b96b325153367ce16544f1808a6ddb39f21
- SurfaceAdjustmentInfo: high-side instruction sourced exclusively from SurfaceGuidance.from(displayed pitch, displayed roll).highLabel - the deadbanded axes supply the label hysteresis, so wording cannot flap at direction boundaries. - Shared SettlingDetector exposed through the pipeline as the sole motion gate; strong guidance defers behind a quiet Settling state. - RiseRun (core/sensors, pure): tan-based mm/m and in/ft, derived from the same deadbanded magnitude as the numeric readout; pinned at 45 degrees = 1000 mm/m = 12 in/ft. - Persisted MeasurementUnits preference in core/settings (metric default); Tools UI control remains deferred per plan. - Guidance renders only in face-up Surface mode, hidden at level (no direction below the 0.1-degree deadband). 56 tests passing. Audited-by: Claude (no findings) 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%