Watch
1
0
Fork
You've already forked SouveraineOS
0

TASK-42: viewtop compositor

Foundation landed: lock handoff, admission gate, layer stack, back verb,
intent table. 123 tests, CI green for the first time (repo was never
fmt-clean). No Wayland/DRM yet.

Records the two traps: the lock handoff is the normal path, and sessiond
is already the availability layer so the compositor gets no fallback
presenter.
This commit is contained in:
Fimeg 2026-07-28 17:22:28 -04:00
commit 32ed4fcf6c
2 changed files with 86 additions and 0 deletions

View file

@ -0,0 +1,85 @@
# TASK 42 — viewtop: the Souveraine compositor
**Status:** foundation landed 2026-07-28; no Wayland/DRM yet. **Size:** several
sessions, one lane each. **Repo:** `~/Projects/souveraine-viewtop`
(`10.10.20.120:4455/Fimeg/souveraine-viewtop`), head `a308f39`.
## Goal
Replace Hyprland + quickshell with our own compositor, so the surfaces whose
guarantees are currently documented-but-unenforced become structural, and so the
agent composes over the scene instead of asking a window manager for permission
(doctrine §13).
## What exists after 2026-07-28
4574 lines, 123 tests, CI green on all four gates. **The repo had never been
fmt-clean, so CI had never been able to pass; it can now.**
- `sessiond-client` — the twelve-verb table, `describe`-driven. Plus
`register_shell()`, which holds the heartbeat whose EOF is shell death, and
reads `{"directive":"lock"}` back down it. `Heartbeat` is `#[must_use]`:
dropping it locks the phone.
- `compositor/lock.rs``ext-session-lock-v1` served, sessiond still deciding.
Models the real two-client handoff (below).
- `compositor/gate.rs` — one predicate for input routing, disclosure, and
composition. Replaces denial's `secure_session_locked()`.
- `compositor/layers.rs` — furniture stacking as a derived total order.
`pill_outranks_dock` is a test, not a comment in another repo's Lua.
- `compositor/navigation.rs` — TASK-37's back verb, both tiers, predictive drag.
- `compositor/registry.rs` — surfaces, and what the shell is shown of them.
- `wire/verbs.rs` — the intent table, with examples enforced to parse.
- `docs/SHELL-BOUNDARY.md`, `docs/LOCK-AUTHORITY.md` — the two settled forks.
## The three things that will bite a fresh session
1. **The lock handoff is the normal path.** sessiond's glance and the shell's
lockscreen pass the lock without it ever unlocking
(`SessionOutcome::Released`; Hyprland needs `misc:allow_session_lock_restore`).
The compositor cannot tell a release from a crash and must not try.
TASK-03: *one lock surface, ever*.
2. **Do not build a fallback presenter.** sessiond already is the availability
layer — heartbeat EOF, retake, its own `draw.rs` surface (TASK-02). A second
one breaks the criterion above. This was designed wrong once already.
3. **The engine runs in-process** and that is settled on the embedder contract
(`fbo_with_frame_info_callback` + buffer age + vsync), not on preference.
`wire` is a vocabulary over a platform channel, not IPC.
## What to build, in order
1. **Smithay frontend.** `wl_compositor`, xdg-shell, layer-shell, seat/input.
Wire `gate.rs` at the input, clipboard, capture and Xwayland boundaries —
denial's placements (`input.rs:599,768,1045,1704`, `clipboard.rs:526`,
`handlers.rs:933,978,1010`) are the map; the predicate is ours.
2. **`ext-session-lock-v1` server**, bound to `lock.rs`. Verify against smithay's
`wayland::session_lock` at denial's pinned rev `812bd33` — assumed, not yet
checked. Acceptance is sessiond taking the lock through viewtop exactly as it
does against Hyprland today, including the release-without-unlock handoff.
3. **DRM/KMS + the arm64 engine.** Lift `kms_state.rs` and the eleven-patch
series; retarget the x86_64 manifest. This is the long pole.
4. **External texture → GBM atlas**, then the Dart shell.
## Owed, named rather than hidden
- `StepUp::from_authority` has no caller: sessiond has **no step-up verb**, so
`Reveal(Credential)` is refused outright. Wire it when the verb lands.
- `may_take_lock` is a uid check. TASK-41's attestation lands there and nowhere
else; it is named partial in the code as that task asks.
- `LockEffect::Report` produces trail entries nothing writes yet — §11's
`forensic.jsonl` is where they go.
- `shell-host` classifies (`Chrome`) but hosts no engine.
## Do not
- Port `authentication.rs`. PAM is sessiond's.
- Let `locked` become a bool the compositor owns.
- Add furniture without placing it in `layers::ALL` — the test will catch it,
which is the point.
- Build on the phone or the laptop. archdev, `-i ~/.ssh/ani`, absolute paths.
## Connects to
`VIEWTOP-AND-DENIAL.md` (what is liftable), TASK-02/03 (the lock surfaces and
the boot timeline it must not regress), TASK-30 (the intent table is one of the
surfaces that owed one), TASK-31/37 (the dial and back share the table),
TASK-41 (attestation), TASK-25/27 (viewtop is not packaged), doctrine §4/§13.

View file

@ -45,6 +45,7 @@ plus open threads from the 2026-07-17 session.
| 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 |
| 42 | [viewtop: the Souveraine compositor](42-viewtop-compositor.md) | **foundation 07-28** | lock/gate/layers/back + intent table, 123 tests, CI green for the first time; no Wayland/DRM yet. Engine in-process is settled; the two-client lock handoff is the thing not to get wrong |
| — | [Unify the shell trees](unify-shell-trees-laptop-phone.md) | open | ~900-file `ii` drift; blocks durable shell fixes reaching the phone |
Archived (see `archive/`): 05 crash reporter — done 2026-07-21,