Delete TASK-26; record what DEVICE-STATE-MACHINE actually built
TASK-26 duplicated this doc and should not have been written. The doc already covers the seven-actor scatter, the evidence model, the proximity-lock/screen-toggle mapping, and names sessiond as the owner. Corrects the status: b4b30b1 built the enum, the transition guard, the confidence arithmetic and the forensic log, but nothing drives them - the daemon never leaves Active, so six of eight states are unreachable outside tests, and no sensor feeder exists. Notes the two places the code already diverges from section 4.
This commit is contained in:
parent
49332838d3
commit
ab600c2c16
2 changed files with 28 additions and 147 deletions
|
|
@ -1,7 +1,34 @@
|
|||
# Device state machine — unified design
|
||||
|
||||
**Status:** design doc, not yet implemented.
|
||||
**Status:** partly built and entirely inert (verified in code 2026-07-25).
|
||||
**Created:** 2026-07-24.
|
||||
|
||||
`b4b30b1` landed most of this in `souveraine/src/sessiond/device_state.rs`:
|
||||
the §2 enum (all 8 variants), a 20-pair `LEGAL_TRANSITIONS` guard, §4's
|
||||
confidence arithmetic with exactly the weights below, and the forensic log.
|
||||
**None of it runs.** `transition()` has no caller outside `update_sensors`,
|
||||
which only fires when already `Locked` — and nothing ever puts it there, so
|
||||
the daemon never leaves `Active` and `Locked`/`Observed`/`DozeLight`/
|
||||
`DozeDeep`/`Suspending`/`Asleep` are unreachable outside tests. There is no
|
||||
sensor feeder anywhere (`sensor_input` has no sender), no logind/D-Bus code,
|
||||
no `PrepareForSleep`, and no DPMS/freeze/inhibitor call. Both confidence
|
||||
gates are computed, logged, and never branched on. Live IPC:
|
||||
`observed_confidence: 0.0`, `forensic_log count: 0`.
|
||||
|
||||
Two divergences to settle when wiring, code-first per doc precedence:
|
||||
- The `Locked → Observed` transition keys on **raw `proximity_near`**, not on
|
||||
the §4 threshold table.
|
||||
- §4 says proximity-near + accel-moving is hand-held so DPMS wake is NOT
|
||||
suppressed; the code computes 0.4+0.3−0.2 = 0.5 ≥ 0.3 and suppresses it
|
||||
anyway (its own test asserts the suppression).
|
||||
|
||||
Not in this doc, and needed before any of it can be trusted: **evidence-source
|
||||
health is device state.** On 2026-07-25 SLPI took a CHRE fatal, remoteproc
|
||||
recovered it, `blueline-hexagonrpcd-sdsp` exited "successfully" and was never
|
||||
restarted — every sensor was dead for hours and nothing noticed, because a
|
||||
consumer of a dead sensor looks identical to one whose sensor is quiet. See
|
||||
`Pixel3Arch/PAF/slpi.md`. "No evidence" and "evidence says nothing is
|
||||
happening" must not be the same state.
|
||||
**Supersedes:** the scattered state machines in IdleCoordinator.qml (7 states),
|
||||
sessiond server.rs Phase (4 states), blueline-screen-toggle (2 states), and
|
||||
blueline-proximity-lock (2 states). Those are projections of this model, not
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
# TASK 26 — Sensor evidence and reactions belong to the state machine
|
||||
|
||||
**Status:** open — carved 2026-07-25 after finding the device state machine
|
||||
is not "observational", it is **blind**, while a scatter of standalone
|
||||
`/usr/bin` shell scripts each hold their own sensor claim and act on their
|
||||
own authority.
|
||||
|
||||
**Blocks:** TASK-08(a) idle tiers, TASK-15 idle coordinator. Both are
|
||||
efferent — they give the machine actuators. Neither supplies it afferents,
|
||||
and both read as though something already does.
|
||||
|
||||
## The finding
|
||||
|
||||
`souveraine-sessiond` is running, package-owned, and answering IPC:
|
||||
|
||||
{"device_state":"active","display_active":true,"locked":false,
|
||||
"observed":false,"observed_confidence":0.0,"phase":"released",
|
||||
"shell_alive":true,"suppress_dpms_wake":false}
|
||||
forensic_log -> {"count":0,"entries":[]}
|
||||
|
||||
`observed_confidence` is **0.0 and structurally cannot move**, and the
|
||||
forensic buffer **cannot fill**. `src/sessiond/protocol.rs` defines
|
||||
`Request::SensorInput(SensorInput)` for proximity / accelerometer / light /
|
||||
touch, and **nothing in any repo ever sends one.** The only match outside
|
||||
sessiond is `surfaces/quickshell/services/SessionAudit.qml:logSensorInput()`
|
||||
— a logging helper with no callers. `SessiondBridge.qml` implements only the
|
||||
lock handoff (`shell_ready` / `locked_ack`), not evidence.
|
||||
|
||||
The DUMP's "still observational — it logs, it drives nothing" undersells
|
||||
this. It logs nothing either. It has no inputs.
|
||||
|
||||
## The sensors are not the problem — they were brought up long ago
|
||||
|
||||
**SLPI bring-up is SOLVED (2026-07-10) and the sensor set is wide.** The
|
||||
bounded SUID sweep of 2026-07-13 (`Pixel3Arch/PAF/slpi.md`) found working
|
||||
SUIDs for:
|
||||
|
||||
| sensor | part |
|
||||
|---|---|
|
||||
| `accel` / `gyro` | BMI160 |
|
||||
| `mag` | LIS2MDL |
|
||||
| `pressure` | BMP380 |
|
||||
| `ambient_light` / `proximity` | TMD2725 |
|
||||
| `sensor_temperature` | LIS2MDL |
|
||||
|
||||
Only `amd` (activity-motion-detect) lacks a SUID. `iio-sensor-proxy` has run
|
||||
always-on from boot since 2026-07-20 via `blueline-sensors-enable.service`
|
||||
(`After=blueline-hexagonrpcd-sdsp.service`), replacing the old on-demand
|
||||
start/stop. PAF README: *"Proximity (TMD2725) and accelerometer both live."*
|
||||
|
||||
So the protocol's four evidence sources are all backed by real hardware that
|
||||
already works. **There is nothing to bring up here.** The work is entirely
|
||||
about who owns the evidence and who acts on it.
|
||||
|
||||
## The real shape of the problem: it is scattered into scripts
|
||||
|
||||
Each consumer is an independent standalone shell script in `/usr/bin`, owned
|
||||
by no package, holding its own `monitor-sensor` claim and reaching its own
|
||||
conclusion:
|
||||
|
||||
| script | sensor | acts on |
|
||||
|---|---|---|
|
||||
| `blueline-proximity-lock` | proximity | blanks panel when locked |
|
||||
| `blueline-screen-toggle` | proximity | DT2W wake gate |
|
||||
| `blueline-autorotate` | accelerometer | screen rotation |
|
||||
|
||||
These are not merely "unpackaged" (TASK-25) — they are **parallel
|
||||
authorities over device state**, which is the thing
|
||||
`SESSION-AUTHORITY-DOCTRINE.md` exists to forbid, and the same collision
|
||||
called out for `org.freedesktop.secrets` vs gnome-keyring on 2026-07-24.
|
||||
|
||||
**They must not become "clients" of the state machine. The state machine
|
||||
absorbs them.** Proximity-while-locked, the DT2W gate, and rotation are all
|
||||
*device state reactions* — they are the machine's job by definition. A shell
|
||||
script that independently decides to blank the panel is a second state
|
||||
machine with no forensic log, no confidence model, and no coordination with
|
||||
the first.
|
||||
|
||||
This is also why they must land together rather than one at a time: two of
|
||||
them read the *same* proximity signal and can reach opposite conclusions, and
|
||||
splitting the work leaves that contradiction in place for longer.
|
||||
|
||||
## Why this must precede TASK-08(a) / TASK-15
|
||||
|
||||
TASK-19's rule is that every control is a view over the owning service — no
|
||||
success-shaped switches. A control over `observed_confidence` today would be
|
||||
a view over a constant. Wiring actuators to a machine with no afferents
|
||||
manufactures exactly the lie TASK-19 forbids: settings that *look* correct in
|
||||
the UI and are inert.
|
||||
|
||||
**Sensors before actuators.** This is the precondition, not a parallel track.
|
||||
|
||||
## The evidence path silently dies — and nothing notices
|
||||
|
||||
Live incident, 2026-07-25 06:04:33 (this is not hypothetical):
|
||||
|
||||
kernel: qcom_q6v5_pas 5c00000.remoteproc: fatal error received:
|
||||
err_qdi.c:456:EF:sensor_process:1:fatal_error.cc:22:CHRE
|
||||
fatal@platform_sensor_manager.cc:158
|
||||
remoteproc remoteproc2: crash detected in slpi / recovering slpi
|
||||
remoteproc remoteproc2: remote processor slpi is now up
|
||||
|
||||
SLPI recovered. But `blueline-hexagonrpcd-sdsp.service` took
|
||||
`Could not fetch next FastRPC message: Broken pipe` and
|
||||
**"Deactivated successfully"** — systemd read a clean exit and never
|
||||
restarted it. SLPI came back up; its HexagonFS daemon did not. Result:
|
||||
|
||||
iio-sensor-proxy: 'registry' sensor unavailable, is hexagonrpcd running?
|
||||
HasAccelerometer: false HasAmbientLight: false HasProximity: false
|
||||
|
||||
**Every sensor on the device was dead for hours** and nothing reported it.
|
||||
The scripts kept running against a proxy with nothing behind it — a standalone
|
||||
script consuming a dead sensor looks identical to one whose sensor is simply
|
||||
quiet.
|
||||
|
||||
Two consequences for this task:
|
||||
|
||||
1. **`blueline-hexagonrpcd-sdsp.service` needs a restart policy that survives
|
||||
SLPI crash-recovery** (SLPI recovers itself; its filesystem daemon must
|
||||
follow). That fix belongs in `Pixel3Arch/rootfs-overlay/`, **never only on
|
||||
the device** — a fix that lives only on the phone is erased by the next
|
||||
reprovision, which is the whole reason the pacman pipeline exists.
|
||||
2. **Evidence-source health is itself device state.** The machine must know
|
||||
its afferents are gone rather than quietly reporting steady state on
|
||||
absent input. "No evidence" and "evidence says nothing is happening" are
|
||||
different, and only one of them is safe to act on.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- `observed_confidence` moves off 0.0 in response to a real physical event.
|
||||
- `forensic_log` returns entries with `count > 0` after that event.
|
||||
- Proximity-while-locked, the DT2W gate, and autorotate are all decided by
|
||||
the state machine; no standalone script holds a `monitor-sensor` claim.
|
||||
- `pacman -Qo` names a package for every surviving component.
|
||||
- Sensor-stack death is visible in device state, not silent.
|
||||
- No regression: locked-screen proximity blank, DT2W, and rotation all still
|
||||
work.
|
||||
|
||||
## Connects to
|
||||
|
||||
TASK-08 (device state manager — this feeds its tiers), TASK-15 (idle
|
||||
coordinator — same owner question), TASK-19 (why the ordering is not
|
||||
negotiable), TASK-25 (the scripts are unowned, and the restart fix must live
|
||||
in the overlay), `Pixel3Arch/PAF/slpi.md` (sensor island, SUID sweep, the
|
||||
CHRE fatal history), and
|
||||
`SouveraineOS/docs/SESSION-AUTHORITY-DOCTRINE.md`.
|
||||
Loading…
Reference in a new issue