Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/SETTINGS-APP-PLAN.md

9.4 KiB

Souveraine shell — plan (2026-07-13)

What this is now

qs -c souveraine — our own quickshell config, composed by deploy.sh: our files (shell.qml, SouveraineFamily, services/, modules/settings/) are symlinked from this repo; untouched ii directories are borrowed as whole-dir symlinks; directories where we override any file are composed file-by-file. ii's tree stays pristine — no overlay symlinks, no .upstream backups. We step on end-4's toes nowhere; we borrow deliberately and vendor per-directory only when a reason forces it.

SouveraineFamily.qml is the convergence scoreboard: one family, both modes (desktop + phone). Panels that differ by form factor get an extraCondition: Config.options.souveraine.phone gate; a panel is "homogenized" when its gate is deleted. No panelFamily switching — the config loads SouveraineFamily, period.

Live on laptop + phone as of 2026-07-13. Hyprland flipped: laptop via the qsConfig var, phone via sed across its 4 hardcoded qs -c ii sites (backup: hyprland.lua.bak-souveraine-config).

The Settings app

souveraine/settings-phone.qml — purpose-built mobile shell (list → push → back, 68px finger rows, fullscreen, no titlebar), launched by settings-launch.sh (imports compositor env from the user manager) via souveraine-settings.desktop in the phone's app grid. Page registry shape [{name, icon, component}] is identical to desktop settings.qml, so pages are interchangeable. Pages edit Config.options (JsonAdapter → config.json, hot-apply + persist).

Current pages: Device (souveraine.phone flag + future per-device overrides), Lock screen, Dock, Pill, Keyboard, About (ii's stock page verbatim).

Doctrine — "tie back down"

Two tiers, nothing app-private:

  1. Shell settingsConfig.options.* → config.json. Idempotent, survives redeploy, diffable. Zero new persistence.
  2. System settings → the owning daemon, live: NetworkManager, ModemManager (mmcli -J), bluez, UPower, brightnessctl. The app is a view over system state — kill it and the system is still the truth. No shadow copies, no sync jobs. Privileged writes via polkit (pkexec — setuid fixed 2026-07-13, Pixel3Arch gap #7), zero sudo.

Upstream drift — the decision (2026-07-13)

Our overrides were forked against the phone's vintage of ii. The laptop runs a newer ii. Drift is large and one-directional. The question is not "rebase everything" — it's "which upstream additions do we actually want, and which are desktop features we're deliberately not running on a phone-first shell."

Laptop-upstream additions we do NOT have:

  • background.widgets.{visualizer,stats,systemResources} — desktop widgets (the pctrade-style widget system landed upstream). Phone doesn't use these. BUT: borrowed Background.qml reads Config.options.background.widgets.* unconditionally → TypeError spam on laptop. Fix: backport the keys into our Config.qml (small surgical add), don't pull the widget machinery.
  • claudeUsage — Claude Pro/Max subscription gauge in the bar. Want later.
  • fileSearch — indexed file search in the launcher. Want later.
  • sidebar.width/widthExtended, AiChat fontSize live-binding. Want.
  • dpmsTimeout, unlockHook, autoIdleInhibit, termBgTone — small knobs.
  • GlobalStates super-press timing (superPressTime, shouldSuppressSuperReleaseSearch) — press-and-hold-super suppresses search. Conflicts with our dockRevealPulse patch (both touch the super-release block). Rebase needed eventually; not breaking anything today.
  • Ai.qml: OpenAI Responses API strategy, thoughtSignature, FileView chat save. Our Ai.qml is heavily customized (no hardcoded models, Bifrost server, agent/resume) — rebase here is the dangerous one; do carefully or not at all.

What we have that upstream DROPPED:

  • Config.options.dock.stacks (fan-out stacks, "stackId|appId,appId") — upstream removed it. Our DockStack.qml arc feature is ours alone now, not just forked. Keep.

Drift action items (priority order)

  1. Backport background.widgets.* keys into our Config.qml — kills the laptop TypeError spam. Small, surgical, no widget machinery pulled in.
  2. GlobalStates.qml — rebase dockRevealPulse onto upstream's super-press rewrite. Both touch the same block.
  3. Ai.qml — decide: carry our customizations forward on the old base (safe, current path) or rebase onto upstream's Responses-API Ai.qml (risky, gets us thoughtSignature + FileView). Defer until we want one of those.
  4. SidebarLeft/Right/Overview — dedupe the OSK flee-fix (15 lines triplicated) into one place after any rebase.
  5. Don't rebase dock/osk/TaskbarApps unless a specific breakage forces it.

Pages still to build (deferred, "in time")

  • Display — brightness (Brightness service), screen toggle (blueline-screen-toggle), idle/suspend timeouts. hypridle.conf is user-owned: regenerate whole from template, don't sed.
  • Network — WiFi via existing Network service; Cellular needs a new services/Cellular.qml wrapping mmcli -J (data toggle, APN, signal, operator, SIM PIN). The real new work.
  • Bluetooth — BluetoothStatus exists, but org.bluez activation fails on the phone (journal, every boot). Fix the service before building UI on it.
  • App health check — surfaced as a wanted page; not built.
  • Dock pins/stacks editor — list editor with rename; consumes the staged renameStack/stackName plumbing in TaskbarApps/DockStack.

Other open items

  • Phone cold-boot verification (autostart line flipped, unproven until next boot).
  • souveraine.phone defaults false; Device page exposes the toggle but deploy.sh --phone doesn't flip it. Tying it down on phone deploy would satisfy idempotency doctrine.
  • Services rename to be more "souveraine-esq" — deferred.
  • Licensing sweep — see ~/Projects/MAKE_PROPER_LICENSES_FOR_ALL_PROJECTS.md.

Ecosystem — the framework basics (2026-07-13)

Reference studied: PostMarketOS-Blueline/references/phosh (full source checkout). Phosh's shell is built on three primitives we can learn from without copying its C: PhoshLayerSurface (every visible thing subclasses it), the zwlr_layer_shell_v1 layer it sits on (BACKGROUND/TOP/OVERLAY), and zphoc_stacked_layer_surface_v1 — phoc's extension for ordering layer-surfaces above/below each other within a layer (bare wlr can't). Plus a PhoshState bitmask (NONE / MODAL_SYSTEM_PROMPT / BLANKED / LOCKED / SETTINGS / OVERVIEW) that the shell reads to gate layer visibility — use_top_layer = !phosh_shell_get_locked() is the canonical line. State drives layer visibility, not the reverse.

Note: PhoshDockedManager is NOT "the dock" in our sense — it's hardware docking (phone → external display: disables OSK, stops auto-maximize, flips is-phone). It's the system-level analog of our souveraine.phone flag: the phone-becomes-desktop transition. They rhyme; they aren't the same feature.

What we're actually building (three pieces, compose incrementally)

  1. Layer registry + ShellState — declare each surface's layer and stack-order explicitly, driven by a state bitmask. GlobalStates is almost this already (it has the state bits) but doesn't own the layer/stack declarations. Quickshell gives us layer-shell via PanelWindow anchors + exclusive zones — same protocol as Phosh, QML binding not C. Steal the model, not the code.

  2. Live manifest per surface — the dock (then each major surface) projects its current state as a queryable structure: pinned apps, stacks, positions, visibility, mode. This is a service, not UI — dock.manifest{pinned, stacks, hidden, mode}. The dock already holds this state internally; the manifest is the projection for external consumers.

  3. Method abstraction for the agent — the agent does NOT get a new toolcall integration. Souveraine is already a fully-fleshed harness with its own integration state; we use THAT. What lives on the dock side is a small method surface (dock.pin(appId), dock.restack(...), dock.reveal()) with state checks baked in — validate inputs, refuse mutation when the dock is in a state that forbids it (locked, mid-drag), return real results. The agent calls a guarded method, not a footgun; it genuinely can't mess up the dock through the abstraction.

Where the lessons live — Souveraine School

The teaching of these methods — what they are, when to use them, the lessons — is NOT inline in the dock or the agent. It lives in the Souveraine School, taught to agent and human in proper time. The dock's job is to expose the abstraction; the School's job is to teach it. Two separate concerns; do not conflate.

First artifact

The dock manifest is the smallest concrete first step: the dock is built, working, and already has internal state (pinned apps, stacks, reveal/pulse). Projecting it into a queryable manifest + guarded method surface proves the pattern. The layer registry generalizes it after.

Reference material on disk

  • Phosh source: ~/Projects/PostMarketOS-Blueline/references/phosh (full C/meson checkout, read-only reference — do not edit).
  • end4-pC fork (pctrade): ~/Projects/end4-pC — studied for the panelFamilies + background-widget patterns; not copied.
  • Pure Maps (Kirigami/QML nav) — referenced in Pixel3Arch/docs/car-and-dock-references.md; not yet pulled as source.