Watch
1
0
Fork
You've already forked SouveraineOS
0

TASK-26: sensor evidence and a single authority over it

The device state machine is not observational, it is blind: nothing in any
repo ever sends SensorInput, so observed_confidence cannot leave 0.0 and the
forensic log cannot fill. Meanwhile blueline-proximity-lock is live and
acting on proximity on its own authority, unowned by any package. Carved as
its own task because 08(a) and 15 are both efferent and assume afferents
that do not exist - wiring actuators first would manufacture exactly the
success-shaped switches 19 forbids.

Also: 08(b) corrected (ChargeType and PercentageTrusted existed on the bus
but reported defaults for days; three fixes needed, only the third moved it),
25 gains the real kernel blockers and the unowned-file inventory, and STATE
no longer claims the kernel ships by pacman.
This commit is contained in:
Fimeg 2026-07-25 08:14:15 -04:00
commit 7cb55401e6
4 changed files with 208 additions and 4 deletions

View file

@ -28,9 +28,18 @@ regression, not a fallback.
kernel + initramfs onto those generic names. **`boot_a` is stale** — it still
carries `pmos_root_uuid` and no `root=`, so it is NOT what boots the system.
Flashing it changes nothing.
- Everything is packaged: `souveraine`, `-secrets`, `-machined`, `-sessiond`
(aarch64 only — the laptop hits lock-screen errors with sessiond),
`upower-souveraine`, kernel. Nothing belongs in `/usr/local/bin` any more.
- Packaged and delivered by `pacman -Syu`: `souveraine`, `-secrets`,
`-machined`, `-sessiond` (aarch64 only — the laptop hits lock-screen errors
with sessiond), `upower-souveraine`. Nothing belongs in `/usr/local/bin`
any more.
- **The kernel is NOT yet in that list** (corrected 2026-07-25). It was
`pacman -U`'d by hand; `kernel.yml` has never once passed and
`kernel-latest` has never been published. Three blockers precede
`repo-add --sign` — see TASK-25. Parked by Casey 2026-07-25.
- **5,624 files under `/usr /etc /opt /boot` are still owned by nothing**
the same disease, not yet colliding. One of them,
`blueline-proximity-lock`, is a running second authority over proximity
(TASK-26). Inventory + the conflict-computation recipe: TASK-25.
**Real reasons to flash, and only these:** the boot chain itself is broken
(pocketboot/extlinux/initramfs unbootable), partitioning changes, or a
@ -184,5 +193,8 @@ to Gitea (`Fimeg/Chatty`, `Fimeg/libcmatrix`, `Fimeg/qtpim`).
- `session-trust-map.html` — moved from ~/ on 2026-07-16.
- `DUMP-pacman-pipeline-2026-07-24.md` — the session that retired flashing:
pacman pipeline, the eleven unowned binaries, and the traps found.
**Corrected 2026-07-25** — its charge-type conclusion was wrong (the `N/A`
was read from the charger, not the battery); see the inline correction and
TASK-08(b).
- DEPRECATED: `qtpim-contacts-handoff.md`, `contacts-design.md`,
`chatty-matrix-features.md` — historical, superseded by Matrix sensorium.

View file

@ -31,7 +31,30 @@ Wants (from handoff doc item 12):
constant_charge_current_max 1950000 (capped at 1C = 2.97A)
upower exposes `ChargeType` + `PercentageTrusted` over D-Bus (the
Souveraine fork, `souveraine/charge-type`). pop-os/system76-power
Souveraine fork, `souveraine/charge-type`). **Both properties existed but
reported defaults until 2026-07-25 — do not trust a D-Bus property merely
because it is present.** `ChargeType` read `unknown` and
`PercentageTrusted` read `no` on hardware for days. Three fixes were
needed, and neither of the first two moved the symptom on its own:
`628283f` (kernel spells NONE as `N/A`), `718e921` (SDM845 splits fuel
gauge from charger — `qcom-battery` has **no** `charge_type`; walk the
kernel's device links to `pmi8998-charger`), and `f974714` — the one that
actually did it: `up-enumerator-udev.c` tries
`UP_TYPE_DEVICE_SUPPLY_BATTERY` first for every power_supply and only falls
back to `UP_TYPE_DEVICE_SUPPLY`, so a real battery never ran the refresh
where the fork set these. `beb94dc` fixes `PercentageTrusted`, whose
heuristic tested `charge_full` — absent here, and not what upower reads the
percentage from anyway (it uses `capacity`).
**Verified on device 2026-07-25: `charge-type: fast` against the charger's
`Fast`.** Note `charge_type` (active regime) is a different attribute from
`charge_types` (the settable profile list `up-device-supply-battery.c`
already uses for thresholds) — easy to conflate when wiring (b).
Hardware gaps that are not bugs: `charge_full`, `charge_now`, `energy_*`,
`cycle_count` and model/serial are all absent, so `energy-full` falls back
to design (13.068 Wh), health reads a meaningless 100%, and charge-cycles
is N/A. Also seen: `temp` = 570 → **57 °C while charging** — verify whether
that is real before building thermal policy on it.
pop-os/system76-power
`charge_thresholds.rs` is still the capability-probing pattern to copy —
probe, do not assume, since the attrs exist only on this kernel.
Cosmetic: 4.4V encodes to 4.395V so the threshold getter reads 99, not

View file

@ -35,6 +35,40 @@ and have every producer publish into it.
publish into the shared `edge` release — `souveraine/.gitea/workflows/ci.yml`
lines ~248-256 are the reference implementation. Kernel updates then arrive
by `pacman -Syu`; flashing becomes a recovery tool, not a release channel.
**`repo-add --sign` is NOT the first blocker** (verified 2026-07-25;
parked by Casey the same day). Three things sit in front of it:
- **The job has never once passed.** 11 runs, 11 failures, none since
Jul 14; `kernel-latest` is a 404 and has never been published. The Jul 14
chain (`b1d3226``9c51f3f`) was successive gitea-credential fixes to
`build.sh` and **the last fix was never re-run** — it may already work.
- **`pkgver` is static.** `kernel/PKGBUILD:12-13` is `pkgver=7.1.1` /
`pkgrel=1`; the commit lives only in the kernelrelease, so every build is
`7.1.1-1` and `-Syu` can never see an upgrade. `build.sh:27-28` hardcodes
both artifact filenames — they must become dynamic in the same change.
- **The obvious fix is non-monotonic.** `vercmp 7.1.1.g588929024
7.1.1.gaaa111222` → `-1`: a bare `.g<sha>` sorts as hex, so a newer
kernel can sort *below* an older one. Use `7.1.1.r<count>.g<sha>`
(verified monotonic), matching souveraine's own scheme. Never `+`.
**Archive shape — Casey chose "additive" 2026-07-25.** Publishing into the
shared `edge` release as written above does not work today: `ci.yml`
**deletes the release and tag and recreates it**, uploading only its own
`pacman-repo` (which it `rm -rf`s first), so anything another producer
published there is erased on the next souveraine push. ci.yml must stop
delete-and-recreate; each producer then does read-modify-write on
`souveraine-<arch>.db` under a shared archdev flock (`repo-add` replaces
the same-pkgname entry, so old versions drop out), uploading its own
packages plus the refreshed db and deleting only its own superseded
assets. Both jobs are `runs-on: archdev`, so one flock serialises them.
Two things that make it easier than expected: the archive key
`3CD9E99E…C8E911` is **already a secret key in casey's gpg keyring on
archdev** and souveraine's CI signs with it there, so kernel.yml needs no
new signing secret; and `~/.git-credentials` on archdev holds both
`oauth2:` and `casey:` gitea entries. Pixel3Arch CI does still need a
token that can write to `Fimeg/souveraine`.
2. **squeekboard + stevia** are Pixel3Arch packages — once the kernel job is
generalised into a "build these packages, sign, publish" job, they are extra
entries in it, not new pipelines.
@ -116,6 +150,40 @@ live sysfs + D-Bus backend, so a battery/charge page can be honest today.
So: package the surfaces → expose what already actuates (charge, existing
pages) → add state-machine controls as TASK-15/08 wire them up.
## The actual inventory (measured 2026-07-25)
379,153 files under `/usr /etc /opt /boot`; **5,624 owned by nothing**. The
same disease as the eleven binaries, just not yet colliding: 16
`/usr/bin/blueline-*` scripts, the `gadget-*` set, `clatd`, `mmsdtng`,
`qmic`, `qrtr-*`, `rmtfs`, a hand-installed `Qt6Contacts` cmake tree,
`libcmatrix.so.0u` (the `ldconfig` warning on every transaction), and stale
`chatty.orig-pacman` / `chatty.pacman-orig` leftovers.
One of them, `blueline-proximity-lock`, is not merely unpackaged — it is a
**running second authority** over proximity. See TASK-26.
**`pacman -Syu` had been blocked for days by exactly one of these files.**
Intersecting the unowned set against the 112,051 files shipped by the 199
pending packages gave a conflict set of ONE:
`/usr/include/aquamarine/backend/FrameScheduler.hpp`, hand-dropped Jul 9 into
a directory whose every other header belongs to `aquamarine 0.12.1-1`, and
shipped by `extra/aquamarine 0.13.0-2`. It was also a version-mismatched
header sitting in the include path the whole time. Backed up to
`/var/backups/unowned-preupgrade/` and removed.
**Compute conflicts, do not guess at them:**
pacman -Fy
pacman -Ql | awk '{print $2}' | sed 's#/$##' | sort -u > owned
find /usr /etc /opt /boot -xdev \( -type f -o -type l \) | sort -u > ondisk
comm -13 owned ondisk > unowned
pacman -Qu | awk '{print $1}' > pending
xargs -a pending pacman -Fl | awk '{print "/" $2}' | sed 's#/$##' | sort -u > newfiles
comm -12 unowned newfiles # <- exactly what will abort -Syu
The phone's login shell is **zsh** — no `mapfile`; run this under `bash -s`
over ssh.
## Acceptance
- Pushing to any SouveraineOS repo produces a signed package in

View file

@ -0,0 +1,101 @@
# TASK 26 — Sensor evidence, and a single authority over it
**Status:** open — carved 2026-07-25 after finding the device state machine
is not "observational", it is **blind**, and that a second authority is
already acting on the signal it was built to arbitrate.
**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. Its
state machine is live:
{"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 for
`SensorInput` outside sessiond itself 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 second authority
Proximity evidence **does** exist on the device and is **already being acted
on** — by a shell script:
pid 981 /bin/sh /usr/bin/blueline-proximity-lock
pid 1227 monitor-sensor --proximity
`blueline-proximity-lock` blanks the panel when proximity is blocked while
the lockscreen is up. It is unowned by any package (`pacman -Qo` → "No
package owns"), one of the 5,624 unowned files in package territory
(TASK-25). It reaches its own conclusion from proximity and acts on the
display, with no reference to sessiond's state machine.
That is two authorities over one signal — the shape
`SESSION-AUTHORITY-DOCTRINE.md` exists to forbid, and the same collision
called out for `org.freedesktop.secrets` vs gnome-keyring on 2026-07-24.
## 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 whose backing state
is always the default, which will *look* correct in the UI and be inert.
**Sensors before actuators.** This task is the precondition, not a parallel
track.
## Shape
1. **An evidence producer.** Something must call `SensorInput`. Proximity is
available today via iio-sensor-proxy (`monitor-sensor --proximity`), which
is what `blueline-proximity-lock` already consumes. Decide the owner:
sessiond subscribing to iio-sensor-proxy over D-Bus directly is the
straight line (it already owns lock state, and TASK-15 notes the
coordinator likely *is* sessiond), versus the shell relaying — but the
shell is the wrong owner for evidence that must survive shell death, which
is the whole reason sessiond exists.
2. **Retire the competing authority.** `blueline-proximity-lock` either
becomes a client of the state machine or its behaviour moves into it. It
must not keep deciding on its own. Its actual behaviour is worth
preserving — the locked-screen proximity blank is a real feature, and
`blueline-screen-toggle`'s DT2W proximity gate is a related second
consumer; check that one too.
3. **Audit the other sensors.** `accelerometer` is claimed but
`monitor-sensor` reports *"Failed to claim accelerometer: NoReply"*
determine whether that is contention with the running script or genuinely
absent. iio devices present are only `pmic@0:adc@3100` and
`pmi8998-rradc` (PMIC analog), so accel/light provenance needs
establishing before the protocol's four sources are assumed available.
Do not design for evidence that does not exist.
4. **Package whatever survives** — see TASK-25. An authority that lives in an
unowned `/usr/bin` script cannot be reasoned about or updated.
## Acceptance
- `observed_confidence` moves off 0.0 in response to a real physical event.
- `forensic_log` returns entries with `count > 0` after that event.
- Exactly one component acts on proximity; `pacman -Qo` names a package for
it.
- The locked-screen proximity blank still works (no regression).
## 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 script is unowned), and
`SouveraineOS/docs/SESSION-AUTHORITY-DOCTRINE.md`.