From bcda2856f7b9745ff2549c99eb4373887bff2017 Mon Sep 17 00:00:00 2001 From: Jay Date: Sat, 11 Jul 2026 18:25:38 -0400 Subject: [PATCH] Add authoritative v1 product & technical brief (Codex) --- BRIEF.md | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 BRIEF.md diff --git a/BRIEF.md b/BRIEF.md new file mode 100644 index 0000000..6c1c587 --- /dev/null +++ b/BRIEF.md @@ -0,0 +1,185 @@ +# On the Level — v1 Product & Technical Brief + +**Status:** Ready for final Claude review before implementation +**Date:** 2026-07-11 +**Companion audit:** [`AUDIT.md`](AUDIT.md) + +## Product decision + +On the Level is an offline-first Android pocket-tool app for quick, trustworthy +level and angle work. It should feel like a responsive physical instrument—not +a novelty simulation—while keeping displayed measurements stable and honest. + +v1 is deliberately small: a level, an angle meter, a calibrated screen ruler, +and the settings necessary to make them dependable. There is no account, +backend, advertising, camera/AR measurement, cloud sync, analytics dependency, +or subscription in v1. + +## Audience and promise + +For everyday DIY, hanging pictures, shelving, small home jobs, and quick rough +measurements. The app is not a substitute for a certified or safety-critical +instrument. Screen-ruler copy must state that it is for short, rough +measurements only. + +## Navigation and layout + +Use a simple three-destination bottom navigation: **Level**, **Angle**, and +**Tools**. The app is portrait-locked in v1. The UI is edge-to-edge and must +correctly handle system insets and back gestures. + +### 1. Level — default destination + +- Header: `LEVEL`, live/calibrated status, calibration/settings action. +- Explicit mode selector: **Surface** | **Edge**. Do not auto-switch modes in + v1; unexpected switching undermines confidence while positioning the phone. +- **Surface:** phone lying screen-up on a surface; use a two-axis cross-vial + visualization with meaningful pitch and roll readings. +- **Edge:** phone held upright on its long edge against a wall, shelf, or + picture frame; use a single, prominent vial/readout for that plane. +- The central visual is tactile: its bubble has restrained spring/damping, + settles naturally, and responds immediately to device movement. +- A locked state is a brief, accessible success reaction with a debounced + system-respecting haptic/audio cue. It is not the persistent normal UI. +- Keep the screen on while this destination is visible. + +### 2. Angle + +- Large primary angle readout. +- Secondary pitch, roll, and percent-grade readings. +- **Hold to zero** sets a relative reference and is always free. +- Percent grade is `tan(pitch) × 100`; define a sensible cap or infinity + presentation near a vertical surface. +- Target-angle alerts and saved named references are Pro features. + +### 3. Tools + +- **Screen Ruler**: a Pro tool with a clear preview and calm, intentional + paywall—not an interruption in the free level/angle flow. +- Calibration entry point. +- Units, haptic/audio, and motion/accessibility preferences. + +## Visual and interaction direction + +Use the concept board's deep graphite base, warm amber bubble, and lime level +lock as direction rather than a literal spec. Numeric measurements remain +near-white and must be readable in bright conditions. Never convey accuracy, +state, or purchase status by color alone. + +The visual vial may be expressive, but it must never contradict the numeric +reading. Provide an in-app reduced-motion option and respect disabled system +animations. Respect device haptic settings; do not force vibration. + +## Measurement modes and calibration + +Only promise calibration for the two physical orientations explicitly supported +in v1: + +1. **Surface** — screen-up, flat contact plane. +2. **Long Edge** — upright, long-edge contact plane. + +Store a reference orientation for each supported mode—not a scalar angle offset. +The calibration flow uses two samples: place the device, record; rotate it 180° +on the same plane, record; derive the reference/bias from both samples. This +reduces fixed device bias without requiring the user to start on a known-level +surface. Calibration UI must give exact, mode-specific placement instructions. + +Screen-ruler calibration is separate from sensor calibration. Offer calibration +against a standard credit-card width (85.60 mm) and a conventional ruler option. +Store scale with the active display/configuration characteristics and request +recalibration whenever a material display change makes the prior scale suspect. + +## Sensor and measurement architecture + +Use a small native Android/Kotlin Compose application. Keep one app module for +v1, with a manual application container rather than premature modularization or +Hilt. + +```text +app/ + core/design/ theme, typography, tactile animation primitives + core/sensors/ sensor source, device-axis mapping, measurement math + core/settings/ DataStore preferences and calibration persistence + core/billing/ entitlement abstraction and Play Billing implementation + feature/level/ state and UI for Surface / Edge level modes + feature/angle/ relative-zero logic and UI + feature/ruler/ ruler calibration and UI + feature/tools/ tools and settings UI +``` + +Require an accelerometer in the manifest. Select sensors in this order: + +1. `TYPE_GAME_ROTATION_VECTOR` +2. `TYPE_GRAVITY` +3. A low-pass-filtered `TYPE_ACCELEROMETER` + +The app does not need north/heading. Map device-frame sensor values explicitly +for the portrait-locked UI and for each measurement mode. Handle unavailable +sensors with a clear unsupported-device state. + +Maintain three distinct values: + +1. **Raw sensor value** — received from the selected sensor source. +2. **Stable calibrated measurement** — reference-orientation calibration plus + a defined EMA/low-pass filter. This is the sole input to numeric readouts + and level-lock detection. +3. **Animated display value** — a critically damped spring derived from the + stable value and used only to move the vial/bubble. + +Readouts use 0.1° resolution and a display deadband to prevent flickering. Lock +behavior starts at no more than 0.2°, exits at at least 0.35°, has a short dwell +time, and has a multi-second haptic debounce. Exact constants remain tunable, +but lock and readout must always use the same stable calibrated measurement. + +Register sensors only while a relevant screen is foregrounded; unregister them +when backgrounded. + +## Monetization + +Use one permanent, non-consumable **On the Level Pro** Google Play product. Do +not use a subscription. The free product is complete: + +- Surface and Edge level modes +- Angle measurement, pitch/roll, degree/grade display +- Hold-to-zero +- Calibration and basic feedback/unit preferences + +Pro adds deliberate, additive measurement tools: + +- Calibrated Screen Ruler +- Target-angle haptic/audio alerts +- Saved and named angle references + +Expose entitlement as `StateFlow` from `core/billing`. Billing +initialization must be asynchronous/lazy: free tools render immediately and +never block on Play services. Cache a previously Play-confirmed entitlement for +offline job-site use, refresh owned purchases when possible (including resume), +and never grant from an arbitrary preference value or a pending purchase. + +## Testability and release gates + +Keep all math—device-axis mapping, calibration, smoothing, hysteresis, grade, +and lock transitions—in pure Kotlin. Place sensor I/O behind an injected +`SensorSource` so tests can use synthetic and recorded real-device traces. + +Before release, verify: + +- Surface and Edge readings across supported orientations and screen rotation + conditions. +- Two-sample calibration improves repeatability and remains isolated per mode. +- Numeric readings, vial animation, and lock feedback stay consistent. +- Haptic debounce, system haptic settings, reduced motion, and bright-light + readability. +- Sensor absence, app backgrounding, and screen wake behavior. +- Pro purchase, restore, pending purchase, offline cached entitlement, and + billing-unavailable behavior without degrading free tools. +- Ruler calibration, display/configuration changes, and honest rough-measure + wording. + +## Explicitly out of scope for v1 + +- Camera-assisted or AR distance measurement +- Accounts, server verification, cloud storage, sharing, or collaboration +- Ads, subscription plans, consumable credits, or trial metering +- Automatic flat/edge mode switching +- Support claims for every device edge, case, or external/foldable display