Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/SHELL-SURFACES.md
Fimeg bde961c6f2 saf: one spine — device, state, and work under the index
PAF becomes saf/device (history kept), STATE.md dissolves
into saf/state.md with the dated era archived, the substrate
SAF moves up from souveraine, and every agreement points at
saf/INDEX.md and nowhere else. one map, nothing to remember
2026-08-18 09:47:30 -04:00

93 lines
5.2 KiB
Markdown

# Shell surfaces — migration checklist
Why this exists: migrations have been silently lossy. The subconscious three-tier
surface was stranded for over a week when the shell moved `ii``souveraine`
the files survived, but the running shell never loaded them, and nobody noticed
until asked. Five packages went stale the same way for the same reason: there was
no list of what exists, so there was nothing to tick off.
This is that list. **Every shell surface and first-party service, the contract
it is defined against, the substrate it lives in today, and whether it actually
reaches the glass.** Before any substrate cutover (`ii``souveraine`, later
`souveraine` → Membrane, currently viewtop), walk this table. If a row's
substrate is the thing being left, it must be re-homed first or it drops.
The rule that would have caught the subconscious: **a feature defined as "QML in
a shell tree" dies with that tree; a feature defined against a contract
survives.** The subconscious *model* (`services/Ai.qml`, substrate-neutral) made
the crossing unscathed; only the *views* (riveted to the `ii` overlay system)
were stranded. Define features at the contract layer — the model, the `wire`
facts/intents under Membrane (currently viewtop) — not welded to a shell.
## Souveraine-native surfaces (in `modules/souveraine/`)
| Surface | Contract / definition | Renders in `souveraine` shell? |
| --- | --- | --- |
| Boot bloom | `modules/souveraine/boot` — boot animation overlay | yes |
| Lock surface | `modules/souveraine/lock` + sessiond `ext-session-lock` | yes |
| Gesture rail (pill) | `modules/souveraine/navigation` — always-on gesture bar | yes |
| Radial dial | `modules/souveraine/dial` — quick-action ring | yes |
| Selection menu | `modules/souveraine/selection` + `services/Selection.qml`; chip tap broken (TASK-18), viewtop-bound | partial — paints, not tappable |
| **Subconscious surface** | `modules/souveraine/subconscious` + `services/Ai.qml`; relocated out of `ii` 2026-07-30 | yes — hosted 2026-07-31 (`AiChat.qml`) |
The subconscious row was the cautionary one, and it stayed inert for a further
day after being re-homed: Tier 1 (the ticker) was mounted in `AiChat.qml`, Tier 2
(the event panel) was mounted by nothing at all, and the difference was invisible
because a component nobody instantiates logs nothing. It was reported as
deployed twice.
**Closed 2026-07-31.** `AiChat.qml` hosts the panel and supplies the chrome the
panel deliberately does not own — scrim, dismissal, a close target. Two ways in:
the ticker's long-press (`requestOpenPanel`, which had no listener), and a
`psychology` indicator beside the input box. The second exists because the
ticker is only visible while a pass is running, so long-press alone made the log
reachable exactly when it was already on screen.
The lesson generalises, and it is the same one §10 of `DEVICE-STATE-MACHINE.md`
learned about dead sensors: **a surface that never instantiates and a surface
that renders nothing are byte-identical from outside.** Verify a row by looking
at the glass, not by confirming the files are in the tree.
## Still on the `ii` substrate (in `modules/ii/` or `ii-base/`) — UNVERIFIED
These render through the legacy `ii` tree. Whether the active `souveraine` shell
actually composes each one has **not been verified** — that is the first work
this checklist demands. Any that the `souveraine` shell does not load are
already silently stranded, the subconscious all over again.
| Surface | Source | Renders in `souveraine` shell? |
| --- | --- | --- |
| Bar / status panel | `modules/ii/bar` | unverified |
| Dock (app switcher) | `modules/ii/dock` | unverified |
| On-screen keyboard | `modules/ii/onScreenKeyboard` + stevia/squeekboard/osk-switch | unverified |
| Overview / app grid | `modules/ii/overview` | unverified |
| Sidebar left (AI chat) | `modules/ii/sidebarLeft` | unverified |
| Sidebar right | `modules/ii/sidebarRight` | unverified |
| Polkit agent | `modules/ii/polkit` | unverified |
| Notifications | `modules/ii/notificationPopup` | unverified |
| Screen corners / session screen / wallpaper selector | `modules/ii/*`, `ii-base/*` | unverified |
## First-party services (substrate-neutral, in `services/`)
These are the contract layer. They survived `ii``souveraine` untouched and
will survive `souveraine` → viewtop the same way — they are the pattern done
right. Views should depend on these, never on a shell tree directly.
`Ai` (subconscious model + stream + event log), `Selection` (primary-selection
watcher), `Speech` (`Speech.speak` TTS), `SessiondBridge`, `GlobalStates`,
`DeviceEvidence`, `Haptics`, `NotifyEvents`, `CrashReporter`.
## How to verify a row
`qs list --all` for the instance, then read
`/run/user/1000/quickshell/by-id/<id>/log.log`. A surface that exists in the
tree but never instantiates leaves no log line and no error — silence is the
failure mode. Confirm each `ii`-substrate row is actually composed before
counting the `ii` exit done.
## Connects to
`saf/state.md` (the resume anchor — keep this table current when a surface moves),
`INVENTORY.md` (component/repo ownership, tiered), TASK-43 (viewtop — the
substrate these all migrate to), the selection-menu and subconscious design
docs. The package-side twin of this problem is in TASK-25.