thejayman77 422854de07 Slice 3: tactile bullseye instrument (Codex)
- SurfaceGuidance (core/sensors, pure, tested): the sole source of
  bubble position, high-side direction, and ring scale. Bubble and
  1/2/5-degree etched rings share one 5-degree visual range; the
  clamped target puts a saturated bubble exactly at the rim ring.
- SurfaceBullseye: Compose Canvas glass vial with crosshairs and
  amber bubble. Critically damped (no-overshoot) spring toward the
  pre-clamped target; velocity carries across retargets. Reduced
  motion (in-app pref or ANIMATOR_DURATION_SCALE == 0) snaps directly.
- Lock treatment: brief lime ring pulse on acquisition, persistent
  lime tolerance label while locked, neutral numeric readout. Never
  color-only; no full-screen lime state.
- Pipeline passes stable calibrated pitch/roll to the instrument;
  deadbanded readout remains authoritative. Bullseye renders only in
  the FACE_UP presentation.

53 tests passing.

Audited-by: Claude (1 finding raised and resolved)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 15:30:45 -04:00
2026-07-11 18:34:57 -04:00

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 by SensorContractTest). 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.
S
Description
No description provided
Readme 1.7 MiB
Languages
Kotlin 83.9%
HTML 16.1%