Watch
1
0
Fork
You've already forked SouveraineOS
0

state: charge is a sensor source, and the laptop is moving to viewtop

The r506 build had ChargeEvidence reading sysfs from sessiond's clock with
conclusion() inside the driver type — the rule violated four times in one
object. Recorded here: the ruling (§4), the task reconciliation, and the
bearer audit under the same rule. Also the corrected cutover answer: the
laptop is the test bed, the chooser is phone-shaped, mechanism undecided.
This commit is contained in:
Fimeg 2026-08-15 11:45:28 -04:00
commit 3cdd36ff2f
3 changed files with 91 additions and 12 deletions

View file

@ -372,6 +372,43 @@ authority.
- Serve as a factor in authentication
- Override a manual lock (user pressed power button to lock)
### Charge is evidence, and the reporter never interprets (settled 2026-08-15)
Charging entered the machine as `ChargeEvidence` — a struct that read sysfs
*and* computed `conclusion()`, probed by sessiond itself on the clock
(TASK-33 §2's first build, r506). The review found it against the rule this
machine lives by, four times in one type:
1. **It never became a `SensorSource`.** It entered through `note_charge`, a
side door, so it got none of the gate: no `EvidenceSeen`, no
`SourceHealth`, no last-seen, no `Absent`-vs-`Down`. §10's gate only gates
what routes through it.
2. **The authority probed.** sessiond reached out and read
`/sys/class/power_supply` on a 5-second clock. The decider became a
driver; the afferent nerve has one job, and it is not deciding.
3. **The driver interpreted.** `conclusion()` lived on the type that read
sysfs. Belief's one load-bearing rule — interpretation may consume
evidence but never a driver — was broken inside a single object.
4. **Nothing left `tick()`.** No `Action`, no executor table, just a trail
line and JSON on the wire. §12's shape, absent.
And the comment justified it by citing `bearer` — another instance of the
same divergence, not doctrine. The disease had already propagated once and
was on its way to becoming precedent.
**The ruling:** charge is a sensor source like any other. `SensorSource::Charge`
+ `SensorValue::Charge` on the wire; the reporter reads the supplies and the
machine interprets; source health, freshness, last-seen and `Absent`/`Down`
are free because they are the gate. `conclusion()` lives on the machine, as
the machine's one decision, and the driver type is gone.
**Audit of bearer under the same rule:** bearer is the same shape — a probe
run by the authority on the clock, with `preferred()`/`tunnel_underlay()`
interpretation inside the driver type. Its actions *do* leave `tick()`
(§12's shape is present), which is the one difference from charge. The same
correction applies: the probe moves to the reporter, the interpretation to
the machine. That is a follow-up, not a debate.
---
## 5. Error and audit contract

View file

@ -1,7 +1,9 @@
# TASK 33 — Battery and charging belong to the device state machine
**Status:** open, raised 2026-07-26. **Size:** one session for (1), one for
(2); (3) is a policy decision before it is code.
**Status:** (2) shape landed 2026-08-15 — charge is `SensorSource::Charge`,
reported by `souveraine-sensord`, interpreted by the machine
(`conclude_charge`, one decision). (1) and (3) remain open. **Size:** one
session for (1), one for (2); (3) is a policy decision before it is code.
**Repos:** `~/Projects/souveraine` (`packaging/upower-souveraine`,
`surfaces/quickshell`, `src/sessiond`).
@ -67,14 +69,18 @@ still going straight to the glass.
upstream already defines, finally reporting the truth on this device.
Write path needs a polkit action; the shell is the agent for it.
2. **Charging as evidence, not as a display feed.** `device_state` already
carries sensor evidence and health (`§10`). Charging state belongs
there: plugged/unplugged, charge type, whether the charger is resting or
working, and — the part no surface can currently derive — *what the
machine concludes*, so "Charged", "Charging slowly", and "the cable is in
but nothing is happening and that is now unusual" are one decision made
once rather than three surfaces guessing. `sensors_degraded` (TASK-08 f)
is the precedent for the shape.
2. **Charging as evidence, not as a display feed.** Landed 2026-08-15. The
first build (`ChargeEvidence` reading sysfs from sessiond's clock, with
`conclusion()` inside the driver type) was reviewed out: the decider must
not probe, and a driver must not interpret. Charge is a sensor source like
any other — `SensorSource::Charge` enters through `sensor_input`, gets
`EvidenceSeen`/`SourceHealth`/last-seen from the gate for free, and the
machine's `conclude_charge()` makes the one decision ("Charged",
"Charging slowly", "the cable is in but nothing is happening and that is
now unusual") once. `souveraine-sensord` reports it on a 30-second poll,
change-driven; the 5-second sysfs probe on sessiond's clock is gone.
`DEVICE-STATE-MACHINE.md` §4 carries the full ruling, including the bearer
audit (same shape, same correction owed).
3. **A charge policy, and who is allowed to set it.** Casey's framing: the
agent might one day decide to let the pack run to 30% first, or hold it