Watch
1
0
Fork
You've already forked souveraine
0

placement grades a covered sensor instead of gating on it; squeeze test follows the fix

This commit is contained in:
Fimeg 2026-08-05 20:23:29 -04:00
commit 620c7d313d
2 changed files with 36 additions and 19 deletions

View file

@ -1395,13 +1395,12 @@ pub struct Placement {
/// How sure the machine must be it is in a pocket before it refuses a wake.
///
/// Above the 0.35 a full pocket signature earns, on purpose: nothing available
/// today separates a pocket from a face-down phone on a desk, so the veto is
/// effectively disarmed until an input exists that can. That is the honest
/// state of the evidence, and it is a threshold rather than deleted code so
/// that adding the call-state input (§4) or a stillness signal re-arms it
/// without anyone having to rediscover why it was off.
const POCKET_VETO_CONFIDENCE: f32 = 0.6;
/// Below what a locked, covered phone earns, so the veto still does the job §4
/// keeps for it — and above what anything else here reaches, so only a pocket
/// reading can fire it. A threshold rather than a hardcoded rule because the
/// call-state input §4 calls owed, or a stillness signal, changes the numbers
/// and not the shape.
const POCKET_VETO_CONFIDENCE: f32 = 0.45;
pub fn is_locked(state: DeviceState) -> bool {
matches!(
@ -2652,17 +2651,31 @@ impl DeviceStateMachine {
// this recently" without needing a clock passed in.
let active = self.idle_since.is_none();
let (belief, confidence) = if !locked && lit && active {
// Covered is tested first: it is the only pocket-specific evidence
// here, and every other branch describes a phone in the open. Ordering
// it after "unlocked and lit" meant a covered sensor never reached this
// at all, because an unlocked lit phone matched Hand first.
let (belief, confidence) = if covered {
// Lock and darkness *grade* the reading rather than gate it.
// Gating on either disarmed the one thing §4 keeps the veto for —
// the pocket case worth stopping is a double tap about to light the
// screen up, which happens before the panel is dark and can happen
// before the lock hint catches up. Capped below Hand and Table
// throughout, because a face-down phone on a desk produces this
// exact signature and nothing here separates them.
let c = match (locked, lit) {
(true, false) => 0.7,
(true, true) => 0.6,
_ => 0.5,
};
(PlacementBelief::Pocket, c)
} else if !locked && lit && active {
(PlacementBelief::Hand, 0.8)
} else if !locked && lit {
// Unlocked and bright with nobody touching it. Casey's case, and
// the one the old boolean got most wrong.
(PlacementBelief::Table, 0.7)
} else if locked && !lit && covered {
// Everything a pocket would show, and still low: a face-down phone
// on a desk shows exactly the same three.
(PlacementBelief::Pocket, 0.35)
} else if locked && !lit {
} else if locked {
(PlacementBelief::Table, 0.5)
} else {
(PlacementBelief::Unknown, 0.0)
@ -3774,15 +3787,19 @@ mod tests {
}
#[test]
fn squeeze_is_vetoed_by_proximity_but_a_power_button_is_not() {
fn a_squeeze_is_never_vetoed_by_proximity_and_neither_is_a_button() {
let (mut sm, _t0) = locked_and_lit();
sm.sensor_evidence.proximity_near = true;
sm.mark_evidence_seen(SensorSource::Proximity);
// A squeezed chassis in a pocket reads exactly like a deliberate
// squeeze. A covered sensor is the veto, same as tap-to-wake.
assert!(sm.suppress_wake(InputTrigger::Squeeze));
assert!(sm.note_input_gated(InputTrigger::Squeeze).is_none());
// A squeeze is NOT vetoed by a covered sensor, and this test used to
// assert the opposite. Measured 2026-08-05: seven deliberate squeezes
// at deflection 2509-3320 were all refused while the phone was in a
// hand — holding it to squeeze it is what covers the sensor. Six strain
// gauges past a calibrated baseline is the stronger signal of the two,
// and §4 scopes the veto to tap-to-wake alone.
assert!(!sm.suppress_wake(InputTrigger::Squeeze));
assert!(sm.note_input_gated(InputTrigger::Squeeze).is_some());
// Intent from a hardware button is never refused (§4).
assert!(!sm.suppress_wake(InputTrigger::PowerButton));

View file

@ -1283,7 +1283,7 @@ fn handle_request(
let p = { shared.lock().device_state.placement() };
return refuse(
RefusalCode::RefusedByState,
format!(
&format!(
"believed {:?} at {:.2} (covered={}, locked={}, lit={})",
p.belief, p.confidence, p.covered, p.locked, p.lit
),