Records what the 2026-07-21/22 sessions actually found and shipped, so the ledger matches reality: - TASK-16: A, B, D landed; C (contact card) implemented, phone acceptance pending; new unit E (history-fill boot amnesia) done. - TASK-08: shell-side state projection exists; add the maintenance- lease requirement so a deploy can never race the idle lock again (root cause of the 19:29 auto-lock-during-deploy crash). - TASK-09: stale-lock incident — panel/IRQ alive, session-lock routing stale; capture both in the resume test. - TASK-14: expand to the Auxo-style running-app surface and an unconditional Home tap; folds in the GLES OpacityMask and workspace-ratchet findings. - TASK-17: pin the iOS-like keyboard target and the Hyprland key-safety hammer test. - Mic trace path corrected to its new home. New: TASK-19 (settings control center), TASK-20 (player video + agent control), TASK-21 (reboot-to-Android confirmation), TASK-22 (settings/fullscreen tweaks), TASK-23 (culver locked-notification nudge).
2.9 KiB
TASK-23 — Culver locked-notification nudge (the push analogue)
Status: designed 2026-07-22, not started. Depends on culver's activity orchestrator (landed 2026-07-22) and the shell's LockedHint write-back (landed same day, souveraine Session.qml).
Problem
Culver now stops its Matrix sliding sync while the session is locked
(battery: locked = zero network/CPU — verified on device). The trade: no
Matrix messages arrive while locked, so no lock-screen banners. SMS is
unaffected (the modem is the platform's real push channel and telephony is
exempt from set_active).
Android solves this with FCM push waking a brief sync
(isSyncingNotificationEvent in Element X's SyncOrchestrator). SouveraineOS
has no Google push — but it has something better positioned: the shell is
always awake, owns the lock surface, and already talks to culver's
notification pipe.
Design
A periodic, shell-driven sync nudge while locked:
- Culver exposes a D-Bus method on the session bus:
net.wiuf.Culver1.SyncBurst()— runs ONE sliding-sync round-trip (SyncService start → first room-list response → stop, bounded ~10s hard timeout) even while inactive, emitting notifications for anything inbound. Idempotent; a burst during active sync is a no-op. - The shell's IdleCoordinator schedules the nudge while locked, riding the
idle stages it already manages:
- stage 0–1 (recently locked): every 2 min
- deeper stages: every 10–15 min, aligned with any existing wake (the point is coalescing with wakeups that happen anyway, not adding timers)
- suspend pending/inhibited: no nudges (system asleep = truly quiet)
- Notification path is unchanged: culver's inbound fold already posts org.freedesktop.Notifications, which the shell renders as the lock card.
Security notes (same doctrine as timeline-architecture.md §activity)
- SyncBurst grants nothing: it can only cause culver to do work it is already authorized to do. Any same-user process could equally start the app; the method is a battery lever, not an authority boundary.
- The nudge cadence is shell policy, not culver policy — the component that owns idle/battery state owns the schedule. Culver stays policy-free.
- No content crosses the nudge interface — notifications flow through the existing pipe with its existing redaction behavior on the lock card.
Non-goals
- Real push (ntfy/UnifiedPush relay) — a later, separate task; this design is forward-compatible (a push arrival would call the same SyncBurst).
- Per-room priority — the sliding-sync round already orders by recency.
Acceptance
Lock the phone, have someone send a Matrix message, wait ≤2 min: the lock
card shows the banner while journalctl --user -u culver-app shows exactly
one burst (start → response → stop), then silence resumes. Battery
regression check: overnight locked drain within noise of the pre-nudge
build.