Revise Surface plan per audit: near-vertical spec, calibration guards, shared settling, pure guidance mapping (Codex)

This commit is contained in:
Jay
2026-07-13 11:52:52 -04:00
parent abff397364
commit 0c197894ff
+60 -26
View File
@@ -1,6 +1,6 @@
# Surface Level — Implementation Attack Plan # Surface Level — Implementation Attack Plan
**Status:** Proposed; send to Claude for audit before implementation. **Status:** Audited; ready for implementation after this revision.
**Scope:** Surface Level only. Do not change Angle, Edge, ruler, or billing in this stage. **Scope:** Surface Level only. Do not change Angle, Edge, ruler, or billing in this stage.
## Outcome ## Outcome
@@ -28,8 +28,13 @@ The user should be able to answer three questions at a glance or by sound:
- Surface means the phone is intended to lie flat, screen-up, on the plane being - Surface means the phone is intended to lie flat, screen-up, on the plane being
measured. Its level-lock behavior is valid only in that geometry. measured. Its level-lock behavior is valid only in that geometry.
- Numeric measurements are never hidden because the phone is steeply oriented. - Numeric measurements are never hidden because the phone is steeply oriented.
Outside the ideal Surface geometry, show the actual angle and a quiet placement Surface tilt magnitude remains authoritative from 0 to 180 degrees. Outside
the ideal face-up geometry, show the actual magnitude and a quiet placement
hint; suppress level-lock feedback rather than replacing the reading with `—`. hint; suppress level-lock feedback rather than replacing the reading with `—`.
- Above 80 degrees of tilt, de-emphasize/suppress Pitch and Roll because their
off-axis parameterization becomes noisy near vertical. Above 90 degrees,
identify the screen-down-side state rather than pretending the bullseye is a
useful placement tool. The magnitude remains visible in both cases.
- The central visualization is a bullseye vial. It has a finite visual range: - The central visualization is a bullseye vial. It has a finite visual range:
beyond that range the bubble rests at the rim, while numeric information remains beyond that range the bubble rests at the rim, while numeric information remains
full-range and authoritative. full-range and authoritative.
@@ -42,20 +47,30 @@ The user should be able to answer three questions at a glance or by sound:
- Refactor Surface placement gating so it only controls the level-lock state, - Refactor Surface placement gating so it only controls the level-lock state,
lock haptic, and geometry-specific guidance. lock haptic, and geometry-specific guidance.
- Keep primary angle, pitch, and roll visible at 0-90 degrees. - Keep the primary tilt magnitude visible from 0-180 degrees. Keep Pitch and
- Add tests at flat, near level, 30 degrees, and near vertical proving numeric Roll visible only where their meaning is stable (below 80 degrees tilt).
readings remain present and correct; verify invalid placement never locks. - Add tests at flat, near level, 30 degrees, 80 degrees, near vertical, and
screen-down. Verify magnitude stays correct, off-axis values are suppressed
in their ambiguous range, and invalid placement never locks.
- Keep the existing lock tolerance semantics: a lock label states the tolerance - Keep the existing lock tolerance semantics: a lock label states the tolerance
rather than pretending any non-zero value is exactly flat. rather than pretending any non-zero value is exactly flat.
### 2. Add the guided Surface calibration flow ### 2. Add the guided Surface calibration flow
- Add a Surface Calibration route from the Level header. - Add a Surface Calibration route from the Level header.
- Explain that the phone may be calibrated on any firm, stable surface; the - Explain that the phone may be calibrated on any firm, stable, *roughly level*
surface itself does not need to be level. surface; it need not be perfectly level. Warn and ask for a flatter surface
- Step 1: settle, sample for a short stable window, capture. when the measured tilt exceeds 5 degrees.
- Step 2: rotate the phone exactly 180 degrees in the same plane, settle, capture. - Capture the two samples from the uncalibrated sensor path. Never derive a new
- Reject/retry if readings indicate motion or inconsistent placement. calibration from readings that an existing calibration has already corrected.
- Step 1: settle, collect a 1.5-second stable window, capture.
- Step 2: rotate the phone exactly 180 degrees in the same plane, settle, then
collect and capture another 1.5-second stable window.
- Use the shared settling detector: enter Settling above 1.0 degrees/second of
two-axis plane movement; leave it only after movement is at or below 0.3
degrees/second for 500 ms. Reject/retry windows that are not settled.
- Reject/retry a derived calibration bias above 3 degrees as evidence that the
device, setup, or turn was inconsistent. Suppress lock feedback during the flow.
- Persist only the resulting Surface calibration; never alter Edge calibration. - Persist only the resulting Surface calibration; never alter Edge calibration.
- State that the calibration applies to the current phone/case/contact setup. - State that the calibration applies to the current phone/case/contact setup.
- On completion, show a concise success result and a way to clear/re-run it. - On completion, show a concise success result and a way to clear/re-run it.
@@ -67,10 +82,19 @@ The user should be able to answer three questions at a glance or by sound:
- Glass, fluid, and meniscus effects must improve depth/readability; avoid a - Glass, fluid, and meniscus effects must improve depth/readability; avoid a
decorative or excessively glossy treatment. decorative or excessively glossy treatment.
- Bubble target position derives directly from stable calibrated pitch/roll. - Bubble target position derives directly from stable calibrated pitch/roll.
- Bubble movement uses a critically damped animation toward that real target: - Derive bubble target, high/low instruction, and rise/run direction from one
no random drift, autonomous wobble, or animation that contradicts the number. pure SurfaceGuidance function. Its hysteretic next-state input must prevent
quadrant labels from flapping at an axis boundary. Use an edge label when the
minor axis is under 25% of the dominant axis; otherwise use a corner label.
- Bubble movement uses a critically damped spring (damping ratio >= 1) toward
that real target: no overshoot, random drift, autonomous wobble, or animation
that contradicts the number. Clamp the target to the vial's visual range before
applying the spring so the bubble settles at the rim.
- Etched rings are real visual calibration marks, not decoration: map them to
explicit degree values (initially 1, 2, and 5 degrees) using the same pure
measurement-to-position mapping as the bubble.
- Respect disabled system animations and the app's reduced-motion preference by - Respect disabled system animations and the app's reduced-motion preference by
minimizing or removing the display spring. direct-positioning the deadbanded bubble value instead of running the spring.
- Show a large total tilt beside/below the vial, then Pitch and Roll below it. - Show a large total tilt beside/below the vial, then Pitch and Roll below it.
- At level lock, use the restrained lime state and an explicit text label. - At level lock, use the restrained lime state and an explicit text label.
@@ -82,32 +106,42 @@ The user should be able to answer three questions at a glance or by sound:
millimetres per metre and/or inches per foot based on the selected unit system. millimetres per metre and/or inches per foot based on the selected unit system.
- Treat exact board/counter dimensions and calculated shim/foot height as a later - Treat exact board/counter dimensions and calculated shim/foot height as a later
Adjustment Assist feature, not a requirement of this stage. Adjustment Assist feature, not a requirement of this stage.
- When the reading is moving, show a subtle `Settling` state and defer strong - Use the shared settling detector from calibration. When it is settling, show a
correction guidance until the stable measurement is trustworthy. subtle `Settling` state and defer strong correction guidance until the stable
measurement is trustworthy.
- Add a persisted units preference in core/settings for rise/run formatting;
the Tools settings UI remains deferred.
### 5. Add optional hands-free Audio Level Assist ### 5. Add optional hands-free Audio Level Assist
- Surface-only, off by default, explicitly user-enabled. - Surface-only, off by default, explicitly user-enabled.
- Use a soft sonar-like pulse with a gentle attack and naturally fading tail; - Use a soft sonar-like pulse with a gentle attack and naturally fading tail;
never a harsh alarm or rapid smoke-detector cadence. never a harsh alarm or rapid smoke-detector cadence.
- Silent while settling or materially outside the usable placement geometry. - Silent while the shared settling detector is active or materially outside the
- Near level: occasional low-key proximity pulses. usable placement geometry.
- Near level: occasional low-key proximity pulses with hysteresis between audio
proximity bands, so band changes cannot chatter.
- Locked: one distinct soft lock ping; optionally provide a sparse repeat-while- - Locked: one distinct soft lock ping; optionally provide a sparse repeat-while-
locked preference so a user adjusting a large plank can hear that it remains level. locked preference so a user adjusting a large plank can hear that it remains level.
- Reuse the existing lock dwell/hysteresis/debounce so sound cannot chatter. - Reuse the existing lock dwell/hysteresis/debounce so sound cannot chatter.
- Respect media volume, audio focus, system sound settings, app lifecycle, and - Use SoundPool with `USAGE_ASSISTANCE_SONIFICATION`; mix with media rather than
the user's Audio Assist preference. taking audio focus for intermittent pulses. Respect media volume, system sound
settings, app lifecycle, and the user's Audio Assist preference. Release audio
resources with the tool composable/flow collection.
## Surface acceptance criteria ## Surface acceptance criteria
- A stable phone on a known level plane achieves lock without repeated feedback. - A stable phone on a known level plane achieves lock without repeated feedback.
- A 180-degree calibration on a stable but non-level plane improves repeatability - A 180-degree calibration from uncalibrated stable samples on a stable,
without zeroing that plane's real slope. roughly-level plane improves repeatability without zeroing that plane's real
- A screen-up phone at 30 and near 90 degrees still shows meaningful numbers; slope; inconsistent/moving captures are rejected.
it does not falsely claim Surface lock. - A screen-up phone at 30, 80, near 90, and screen-down angles always shows a
- Bubble direction agrees with Pitch/Roll and with the high/low instruction. correct magnitude. Pitch/Roll are suppressed at their documented ambiguous
- Bubble visual remains physically believable but never leads or disagrees with range, and the Surface tool never falsely claims a lock.
the stable numeric reading. - Bubble direction, high/low instruction, and rise/run direction agree in all
four quadrants through one pure, unit-tested guidance function.
- Bubble position is a pure mapping of stable measurement plus a no-overshoot
spring. Its etched rings match that mapping's documented degree marks.
- Audio can guide a user to lock without viewing the screen and stays quiet when - Audio can guide a user to lock without viewing the screen and stays quiet when
disabled, settling, backgrounded, or outside the Surface geometry. disabled, settling, backgrounded, or outside the Surface geometry.
- Manual checks cover phone-with-case, phone-without-case, a firm tabletop, and - Manual checks cover phone-with-case, phone-without-case, a firm tabletop, and