|
| 1 | +# Hestia Mobile AI-Primary UI Plan |
| 2 | + |
| 3 | +> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task. |
| 4 | +
|
| 5 | +**Goal:** Define and prototype the Hestia Mobile UI as an AI-primary PureOS/Phosh phone experience where the normal app launcher is secondary. |
| 6 | + |
| 7 | +**Architecture:** Keep the working voice/backend/bridge services, but do not assume desktop/laptop `hestia-shell` is the production mobile shell. Build a mobile-native visual layer for PureOS/Phosh/Wayland that subscribes to the existing local assistant socket and renders a mostly blank AI canvas, transient cards/material, and a bottom-right affordance for the traditional app interface. |
| 8 | + |
| 9 | +**Tech Stack:** PureOS Byzantium, Phosh/phoc Wayland session, local Unix sockets from `hestia-ai-bridge`, `unmute-streaming-client`, GTK/libadwaita or another Phosh-compatible Wayland surface toolkit, optional future compositor/session integration. |
| 10 | + |
| 11 | +**Integration owner repo:** `hestia-mobile` |
| 12 | + |
| 13 | +**Component repos:** |
| 14 | +- `hestia-mobile` — integration, plans, probes, release gates, product direction. |
| 15 | +- `hestia-ai-bridge` — local HTTP/socket health and assistant event bus. |
| 16 | +- `unmute-streaming-client` — always-available voice client. |
| 17 | +- `hestia-shell` — desktop/laptop Quickshell reference UI, not currently the production mobile UI. |
| 18 | +- Proposed: `hestia-mobile-shell` or `hestia-mobile-ui` — PureOS/Phosh-native AI-primary visual layer. |
| 19 | + |
| 20 | +**Runtime topology:** |
| 21 | +- Phone local session: `Phosh:GNOME`, `phoc`, Wayland. |
| 22 | +- Voice service: `hestia-unmute-voice.service`. |
| 23 | +- Bridge service: `hestia-ai-bridge.service`. |
| 24 | +- Local sockets: `$XDG_RUNTIME_DIR/hestia-shell/ai.sock`, `$XDG_RUNTIME_DIR/hestia-shell/assistant.sock`. |
| 25 | +- Backend: `tiny-emerson` over Tailscale. |
| 26 | + |
| 27 | +**Acceptance gates:** |
| 28 | +- Blocking: phone remains reachable; voice service continues speaking; bridge health remains `status=ok`; local assistant socket is consumed by the new UI; normal app access remains available. |
| 29 | +- Non-blocking initially: replacing Phosh completely, lockscreen integration, notification-center integration, packaging/image builds. |
| 30 | + |
| 31 | +--- |
| 32 | + |
| 33 | +## Verified environment |
| 34 | + |
| 35 | +Checks run on the phone showed: |
| 36 | + |
| 37 | +```text |
| 38 | +XDG_CURRENT_DESKTOP=Phosh:GNOME |
| 39 | +XDG_SESSION_DESKTOP=phosh |
| 40 | +XDG_SESSION_TYPE=wayland |
| 41 | +OS=PureOS 10 (Byzantium) |
| 42 | +Kernel=6.6.0-1-librem5 aarch64 |
| 43 | +``` |
| 44 | + |
| 45 | +Active graphical shell processes include: |
| 46 | + |
| 47 | +```text |
| 48 | +/usr/bin/phoc |
| 49 | +/usr/libexec/gnome-session-binary --session=phosh |
| 50 | +/usr/libexec/phosh |
| 51 | +/usr/bin/squeekboard |
| 52 | +xdg-desktop-portal / xdg-desktop-portal-gtk |
| 53 | +``` |
| 54 | + |
| 55 | +No running `qs`, `quickshell`, Hyprland, or desktop `hestia-shell` process was found. The local `hestia-shell` repo is on the expected branch/commit, but it is not the active visible shell: |
| 56 | + |
| 57 | +```text |
| 58 | +hestia-shell branch: feat/hestia-voice-gateway |
| 59 | +hestia-shell head: 44e52aa0 fix(assistant): align orb input region with wrapper |
| 60 | +``` |
| 61 | + |
| 62 | +The AI runtime path is healthy: |
| 63 | + |
| 64 | +```text |
| 65 | +hestia-ai-bridge.service: active/running |
| 66 | +hestia-unmute-voice.service: active/running |
| 67 | +$XDG_RUNTIME_DIR/hestia-shell/ai.sock: present |
| 68 | +$XDG_RUNTIME_DIR/hestia-shell/assistant.sock: present |
| 69 | +bridge /health: status=ok, orchestrator_online=true |
| 70 | +``` |
| 71 | + |
| 72 | +## Conclusion from the checks |
| 73 | + |
| 74 | +`hestia-shell` is not currently the visible phone shell. It is a useful desktop/laptop and protocol/UI reference, but the phone is running Phosh/phoc on PureOS. Therefore the missing orb is expected: the Quickshell UI layer is not loaded. |
| 75 | + |
| 76 | +For Hestia Mobile, the production direction should not be “port the current desktop shell wholesale.” The current desktop/laptop shell assumes a different stack and interaction model. The mobile product direction is substantially different: |
| 77 | + |
| 78 | +- The normal app interface is secondary. |
| 79 | +- The default screen can be mostly blank/desktop-like. |
| 80 | +- The AI is the primary interface and brings up relevant freeform material only when needed. |
| 81 | +- A bottom-right affordance opens the normal app interface. |
| 82 | +- Voice remains the primary control surface. |
| 83 | + |
| 84 | +This warrants a dedicated mobile UI/shell repository or at least a distinct mobile UI package under the Hestia Mobile umbrella. |
| 85 | + |
| 86 | +## Product shape |
| 87 | + |
| 88 | +Default/resting state: |
| 89 | + |
| 90 | +```text |
| 91 | +┌─────────────────────┐ |
| 92 | +│ │ |
| 93 | +│ │ |
| 94 | +│ blank calm AI │ |
| 95 | +│ canvas │ |
| 96 | +│ │ |
| 97 | +│ ◉ │ bottom-right app/interface affordance |
| 98 | +└─────────────────────┘ |
| 99 | +``` |
| 100 | + |
| 101 | +When the AI has relevant material: |
| 102 | + |
| 103 | +```text |
| 104 | +┌─────────────────────┐ |
| 105 | +│ │ |
| 106 | +│ ┌───────────────┐ │ |
| 107 | +│ │ contextual │ │ |
| 108 | +│ │ card/material │ │ |
| 109 | +│ └───────────────┘ │ |
| 110 | +│ ◉ │ |
| 111 | +└─────────────────────┘ |
| 112 | +``` |
| 113 | + |
| 114 | +When the user explicitly wants normal apps: |
| 115 | + |
| 116 | +```text |
| 117 | +┌─────────────────────┐ |
| 118 | +│ app launcher / │ |
| 119 | +│ normal Phosh-like │ |
| 120 | +│ interface │ |
| 121 | +│ │ |
| 122 | +│ ◉ │ |
| 123 | +└─────────────────────┘ |
| 124 | +``` |
| 125 | + |
| 126 | +## Recommended repo decision |
| 127 | + |
| 128 | +Create a separate repo when implementation starts: |
| 129 | + |
| 130 | +```text |
| 131 | +Code4me2/hestia-mobile-shell |
| 132 | +``` |
| 133 | + |
| 134 | +Alternative names: |
| 135 | + |
| 136 | +```text |
| 137 | +Code4me2/hestia-mobile-ui |
| 138 | +Code4me2/hestia-phosh-shell |
| 139 | +``` |
| 140 | + |
| 141 | +Recommendation: use `hestia-mobile-shell` because the scope is broader than a single app, but still clearly separate from desktop `hestia-shell`. |
| 142 | + |
| 143 | +`hestia-mobile` remains the integration/meta repo and should reference this future repo in `mobile-stack.json` once created. |
| 144 | + |
| 145 | +## What to keep from current work |
| 146 | + |
| 147 | +Keep and reuse: |
| 148 | + |
| 149 | +- `hestia-ai-bridge` health and assistant socket. |
| 150 | +- `unmute-streaming-client` voice/reconnect service. |
| 151 | +- `hestia-mobile` probes, compatibility matrix, runbooks, release gates. |
| 152 | +- `hestia-shell` event model and assistant UI ideas as reference. |
| 153 | + |
| 154 | +Do not depend on: |
| 155 | + |
| 156 | +- Hyprland-specific shell assumptions. |
| 157 | +- Quickshell being present in PureOS/Phosh. |
| 158 | +- Arch-based package assumptions. |
| 159 | +- Desktop/laptop bar/dashboard patterns. |
| 160 | + |
| 161 | +## Task 1: Add mobile UI stack discovery probe |
| 162 | + |
| 163 | +**Objective:** Extend `hestia-mobile` with a read-only probe that reports the active phone session and whether a mobile UI layer is loaded. |
| 164 | + |
| 165 | +**Files:** |
| 166 | +- Create: `scripts/probe-mobile-ui-session.sh` |
| 167 | +- Modify: `docs/acceptance-gates.md` |
| 168 | + |
| 169 | +**Implementation notes:** |
| 170 | + |
| 171 | +The script should report: |
| 172 | + |
| 173 | +```bash |
| 174 | +#!/usr/bin/env bash |
| 175 | +set -euo pipefail |
| 176 | + |
| 177 | +printf 'desktop=%s\n' "${XDG_CURRENT_DESKTOP:-}" |
| 178 | +printf 'session_desktop=%s\n' "${XDG_SESSION_DESKTOP:-}" |
| 179 | +printf 'session_type=%s\n' "${XDG_SESSION_TYPE:-}" |
| 180 | +printf 'wayland_display=%s\n' "${WAYLAND_DISPLAY:-}" |
| 181 | +printf 'display=%s\n' "${DISPLAY:-}" |
| 182 | + |
| 183 | +printf '\nprocesses:\n' |
| 184 | +pgrep -af 'phosh|phoc|gnome-shell|mutter|hyprland|Hyprland|qs|quickshell|hestia-mobile|hestia-shell' || true |
| 185 | + |
| 186 | +printf '\nbinaries:\n' |
| 187 | +for c in phosh phoc qs quickshell gsettings busctl gdbus; do |
| 188 | + if command -v "$c" >/dev/null 2>&1; then |
| 189 | + printf '%s=%s\n' "$c" "$(command -v "$c")" |
| 190 | + else |
| 191 | + printf '%s=missing\n' "$c" |
| 192 | + fi |
| 193 | +done |
| 194 | +``` |
| 195 | + |
| 196 | +**Verification:** |
| 197 | + |
| 198 | +Run: |
| 199 | + |
| 200 | +```bash |
| 201 | +bash -n scripts/probe-mobile-ui-session.sh |
| 202 | +scripts/probe-mobile-ui-session.sh |
| 203 | +``` |
| 204 | + |
| 205 | +Expected on current phone: |
| 206 | + |
| 207 | +```text |
| 208 | +desktop=Phosh:GNOME |
| 209 | +session_desktop=phosh |
| 210 | +session_type=wayland |
| 211 | +processes include phosh/phoc |
| 212 | +qs=missing or no running qs process |
| 213 | +``` |
| 214 | + |
| 215 | +## Task 2: Create mobile visual contract document |
| 216 | + |
| 217 | +**Objective:** Define the shell-facing event contract for the AI-primary mobile canvas. |
| 218 | + |
| 219 | +**Files:** |
| 220 | +- Create: `docs/contracts/mobile-visual-surface.md` |
| 221 | + |
| 222 | +**Contract outline:** |
| 223 | + |
| 224 | +- Inputs: |
| 225 | + - assistant normalized events from `$XDG_RUNTIME_DIR/hestia-shell/assistant.sock` |
| 226 | + - bridge health from `http://127.0.0.1:8765/health` |
| 227 | + - optional call state source |
| 228 | +- UI states: |
| 229 | + - blank/resting |
| 230 | + - listening |
| 231 | + - thinking |
| 232 | + - speaking |
| 233 | + - showing contextual material |
| 234 | + - normal app interface visible |
| 235 | + - call paused |
| 236 | + - offline/error |
| 237 | +- Visual verbs: |
| 238 | + - `show_card` |
| 239 | + - `update_card` |
| 240 | + - `dismiss_card` |
| 241 | + - `show_transcript` |
| 242 | + - `show_tool_status` |
| 243 | + - `open_app_interface` |
| 244 | + - `close_app_interface` |
| 245 | + - `confirm_action` |
| 246 | + |
| 247 | +**Verification:** |
| 248 | + |
| 249 | +Document must explicitly say the visual layer consumes normalized `assistant.*` frames, not raw backend events. |
| 250 | + |
| 251 | +## Task 3: Spike mobile UI implementation approach |
| 252 | + |
| 253 | +**Objective:** Decide whether the first prototype should be a GTK/libadwaita fullscreen app, a Phosh plugin/extension path, or a compositor/session replacement experiment. |
| 254 | + |
| 255 | +**Files:** |
| 256 | +- Create: `docs/spikes/mobile-ui-approach.md` |
| 257 | + |
| 258 | +**Options to compare:** |
| 259 | + |
| 260 | +1. Fullscreen GTK/libadwaita app launched on login. |
| 261 | + - lowest risk |
| 262 | + - works with current Phosh |
| 263 | + - can subscribe to assistant socket |
| 264 | + - may not truly replace home shell |
| 265 | +2. Phosh/plugin/extension integration. |
| 266 | + - better OS integration |
| 267 | + - likely more complex and packaging-sensitive |
| 268 | +3. Dedicated compositor/session later. |
| 269 | + - closest product fit |
| 270 | + - highest risk |
| 271 | + - not first prototype |
| 272 | + |
| 273 | +**Recommended first spike:** fullscreen GTK/libadwaita AI canvas that can be launched/killed without destabilizing Phosh. |
| 274 | + |
| 275 | +**Verification:** |
| 276 | + |
| 277 | +Plan should identify exactly how the prototype exits and returns to normal Phosh, so it cannot strand the phone. |
| 278 | + |
| 279 | +## Task 4: Create `hestia-mobile-shell` repo skeleton |
| 280 | + |
| 281 | +**Objective:** Create a dedicated repo for the mobile-native visual layer once the approach is approved. |
| 282 | + |
| 283 | +**Files:** |
| 284 | +- New repo: `Code4me2/hestia-mobile-shell` |
| 285 | +- Initial files: |
| 286 | + - `README.md` |
| 287 | + - `docs/architecture.md` |
| 288 | + - `docs/contracts/mobile-visual-surface.md` |
| 289 | + - `docs/spikes/mobile-ui-approach.md` |
| 290 | + - `scripts/probe-runtime.sh` |
| 291 | + |
| 292 | +**README must state:** |
| 293 | + |
| 294 | +- This is not desktop/laptop `hestia-shell`. |
| 295 | +- Target is PureOS/Phosh/mobile Wayland first. |
| 296 | +- Voice is primary; app launcher is secondary. |
| 297 | +- The default screen can be blank until the AI has relevant material. |
| 298 | +- The UI consumes local assistant socket events. |
| 299 | + |
| 300 | +**Verification:** |
| 301 | + |
| 302 | +Repo exists, branch pushed, and `hestia-mobile/mobile-stack.json` references it as optional/experimental. |
| 303 | + |
| 304 | +## Task 5: Prototype blank AI canvas |
| 305 | + |
| 306 | +**Objective:** Build a minimal safe UI that proves the product shape without replacing Phosh. |
| 307 | + |
| 308 | +**Files:** |
| 309 | +- TBD after approach spike. |
| 310 | + |
| 311 | +**Behavior:** |
| 312 | + |
| 313 | +- Launches as a fullscreen or near-fullscreen mobile surface. |
| 314 | +- Shows mostly blank canvas. |
| 315 | +- Shows bottom-right app/interface button. |
| 316 | +- Subscribes to assistant socket. |
| 317 | +- Displays state text or minimal visual indicator for listening/thinking/speaking. |
| 318 | +- Can exit cleanly and return to normal Phosh. |
| 319 | + |
| 320 | +**Verification:** |
| 321 | + |
| 322 | +- Voice continues speaking. |
| 323 | +- UI receives assistant events. |
| 324 | +- User can return to normal app interface. |
| 325 | +- Phone is not stranded if the UI crashes. |
| 326 | + |
| 327 | +## Immediate recommendation |
| 328 | + |
| 329 | +Do not try to force desktop `hestia-shell` into the current PureOS/Phosh session as the production path. Use it as a reference, keep the current PRs as desktop/laptop/contract stabilization, and begin a mobile-native UI track under `hestia-mobile` with a separate `hestia-mobile-shell` repo when ready. |
0 commit comments