5.2 KiB
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
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.