Watch
1
0
Fork
You've already forked SouveraineOS
0

audio: WirePlumber persistence measured working; settings owes a state-machine readout

TASK-39 step 1 is done and clean — default-routes stores 0.49 cubed and
rewrites within 6s of a change. 'Pinned on boot' is a faithful restore
of a value lower than wanted, so this is defaults and roles. No second
writer.

TASK-19 gains Casey's ask: source health, evidence and confidence have
no surface anywhere. Readout now, controls after 08(g) decides.
This commit is contained in:
Fimeg 2026-07-28 14:28:50 -04:00
commit b7ea433467
3 changed files with 68 additions and 2 deletions

View file

@ -67,6 +67,41 @@ Ground rules: each tweak is its own small diff with its own device check, no
batching. Anything touching the ii-base layer gets promoted to the laptop repo
the same session (divergence doctrine).
## The state machine needs a surface here (Casey, 2026-07-28)
> "the souveraine-settings section needs to have all these state machine
> mechanics health checks built"
Everything the device state machine knows is currently legible only through
`forensic.jsonl` and `qs ipc call sessiond device_state`. No screen shows any of
it. Three separate gaps, already named elsewhere and converging here:
- **TASK-08(f) — `sensors_degraded` reaches no surface.** §10 source health
landed: a source that reported and then went silent for 90 s is `Down`, not
quiet, and every forensic snapshot carries the flag. The trail knows; nothing
else does. The crash reporter structurally cannot help — the SLPI outage
exited status 0. Needs an ambient indicator saying *which* source and *since
when*, and `device_state` already ships `sensor_health` over IPC, so the data
is there.
- **TASK-08(g) — the confidence gates are computed, logged, and never branched
on.** A settings page over them would be honest only as a *readout*, not as
controls, until (g)'s decision is made. Showing a slider for a threshold
nothing consults is TASK-19's own "no success-shaped switches" rule broken.
- **Grip is now a fourth evidence source with no readout** (2026-07-28,
`PAF/edge-sense.md`). A refused squeeze — the pocket veto — is recorded via
`record_decision` and visible nowhere. "Why didn't my squeeze work" has no
answer on the device today.
**Ordering follows TASK-19's existing rule:** expose what actually actuates.
Health and evidence are *observations* and can be shown honestly right now —
state, panel, evidence, confidence, per-source health and last-seen, the
`sensors_degraded` flag, and the recent decision entries. Controls over the
confidence bands wait on (g).
That split matters: a health readout that is merely accurate is useful the day
it ships, whereas a controls page over a machine that ignores its own thresholds
would be lying.
## Acceptance
1. Hammer Settings icon ten times: exactly one standalone PID/window, zero new

View file

@ -12,6 +12,37 @@ model is right. **Repo:** `souveraine` (sessiond + surfaces), `Pixel3Arch`.
> others. Frankly most times I think the phone should be expected to have audio
> up to around 70%; but I may be errant."
## Measured 2026-07-28 — WirePlumber persistence is NOT the bug
Step 1 below is done, and it came back clean. Do not build a second persistence
layer.
`~/.local/state/wireplumber/default-routes` carries the speaker route's volume:
alsa_card.platform-sound:output:...Speaker={"mute":false, ...
"channelVolumes":[0.118778, 0.118778]}
`0.118778 = 0.49³`, and `wpctl get-volume @DEFAULT_AUDIO_SINK@` reports exactly
`0.49` — wpctl shows the cubic-mapped value, the state file stores linear. They
agree.
Persistence was tested directly rather than inferred: set the sink to `0.55`,
and within 6 s `default-routes` was rewritten with `channelVolumes":[0.166378`
(`= 0.55³`). Restored to `0.49` cleanly. WirePlumber 0.5.15, `restore-device`
working through `default-routes` (there is no separate `restore-device` file in
this version — that naming is older).
**So "sound seems pinned on boot" is not a failure to save.** It is WirePlumber
faithfully restoring `0.49` every boot, which is simply lower than the ~70% Casey
expects. That makes this entirely a *defaults and roles* question — which is what
the rest of this file already says the real question is — and removes the one
scenario that would have justified sessiond owning the value.
Note `alsa-restore` is `static` and active on this device, and PAF/audio.md
records it re-enabling TX7 every boot. It is a second writer to the codec, but
it was not implicated here: the route volume it would fight over is being
written and read back correctly.
## Check this before building anything
**WirePlumber already restores stream and device volumes across boots** (its

View file

@ -24,7 +24,7 @@ plus open threads from the 2026-07-17 session.
| 16 | [culver: usable messenger + contacts as Personal-class store](16-culver-messenger-contacts.md) | in progress | A/B/D landed; C contact card next; F is the folded-in TASK-01 |
| 17 | [Keyboard (stevia) + dictation polish](17-keyboard-stevia-dictation.md) | shipped-partial | OSK + mic key + STT live; **no word completion** — stevia asks hunspell for `en-us`, the dict is `en_US` (07-25) |
| 18 | [Selection/highlight action menu](18-selection-menu.md) | open | design captured 07-21; component-first, Read Aloud gated on TTS server |
| 19 | [First-party Settings control center](19-settings-control-center.md) | in progress | guarded standalone launch + owned pages; absorbed TASK-22's polish sweep |
| 19 | [First-party Settings control center](19-settings-control-center.md) | in progress | guarded standalone launch + owned pages; absorbed TASK-22's polish sweep; **owes the state-machine + source-health readout** (07-28) — 08(f)/(g) surface here |
| 20 | [Souveraine Player video + agent control](20-player-video-agent.md) | open | video/snapshot/manifest; preserve music |
| 21 | [Reboot-to-Android confirmation](21-reboot-android-confirmation.md) | open | scoped 07-22; one-tap irreversible slot flip still bare in app search |
| 23 | [culver locked-notification nudge](23-culver-locked-notification-nudge.md) | open | designed 07-22; needs `SyncBurst()` + IdleCoordinator schedule |
@ -42,7 +42,7 @@ plus open threads from the 2026-07-17 session.
| 36 | [CHRE nanoapp host for the SLPI](36-chre-nanoapp-host.md) | open | chrecd already runs CHRE with zero nanoapps; method table recovered 07-27, three methods to add |
| 37 | ["Back" as a first-class verb](37-navigation-back-verb.md) | open | our Gestures.qml is already the compositor half; `can_go_back` is the dial's enabled/reason |
| 38 | [Pill swipe-to-max swaps the keyboard](38-pill-swipe-osk-swap.md) | open | micro; the ONLY route to a terminal keyboard since stevia dropped its layout |
| 39 | [Audio levels as tracked state, and sound roles](39-audio-levels-as-state.md) | open | check WirePlumber restores first; roles before a number |
| 39 | [Audio levels as tracked state, and sound roles](39-audio-levels-as-state.md) | open | **measured 07-28: WirePlumber persistence works** — it restores 0.49 faithfully, so this is defaults+roles, not a save bug; do not add a second writer |
| 40 | [Inference tiering for the sensor surfaces](40-inference-tiering-sensors.md) | **open, gating** | P1 applied to sensord/grip/dial; blocks TASK-13's raw stream and gates TASK-31's IPC |
| 41 | [Producers must be attested; one authority per input](41-attested-producers.md) | open | doctrine §10 pointed at a real surface; demonstrated live 07-28 — a squeeze and a dial-open both accepted from an SSH shell |
| — | [Unify the shell trees](unify-shell-trees-laptop-phone.md) | open | ~900-file `ii` drift; blocks durable shell fixes reaching the phone |