Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/17-keyboard-stevia-dictation.md

7.4 KiB

TASK 17 — Keyboard (stevia) + dictation polish

Status: Squeekboard replacement source authored 2026-08-11; parser tests green, full package build and glass proof pending. Stevia remains the active fallback until the new Squeekboard package is installed and survives repeated dismiss/reopen cycles.

Current decision (2026-08-11)

One keyboard owns the phone: Squeekboard. The daily layout has a permanent number row plus Fn/numpad; the terminal hint selects the compact terminal layout. Both expose the same first-party dictation action. The old Stevia/Squeekboard switcher and drag-up keyboard swap retire only after the replacement is proven on glass.

Pixel3Arch/pkgs/squeekboard now carries:

  • a dictate layout action that spawns packaged /usr/bin/souveraine-stt;
  • daily and terminal layouts with the mic available from their base rows;
  • a Cairo-drawn, state-honest mic: restrained violet at idle, three breathing violet bubbles while recording, a rotating broken ring while transcribing, and a red-violet error mark;
  • animation driven by $XDG_RUNTIME_DIR/souveraine-stt/state, polled only while the keyboard widget is mapped.

No bitmap was imported and no Stevia completion code was reused. Native Squeekboard word completion remains the next layer after the single-keyboard path is stable.

Earlier Stevia path (historical, currently installed)

  • stevia is the OSK, patched to run under Hyprland. Upstream stevia hard-requires zphoc_device_state_v1 (phoc-private) before creating a keyboard surface, so under Hyprland it sat "Wayland not yet ready" forever and the phone had NO keyboard. Patched optional. Pixel3Arch/pkgs/stevia (0.56.0-3), builds native on-device. Squeekboard retired (SouveraineOS/blueline/squeekboard/ kept as layout reference only).
  • Mic/dictation key on every layout's bottom row (patch 0002): spawns souveraine-stt, a record→transcribe→type toggle CLI. Config (endpoint, enable) lives in Config.options.speech, surfaced in the new Settings → Speech page (souveraine 402e887), with a live /health probe. STT hits Casey's VPN faster-whisper box (see whisper-stt-server memory).
  • Terminal arrow keys (patch 0002): the terminal layout's bottom row gained ← ↓ ↑ → (the shortcuts bar always had them but sat under the pill).
  • Nav pill fix: the SystemGestureRail was lifting the pill 315px (a stale squeekboard height) which stacked it OVER the keys and stevia's upward-opening layout menu — "keyboard selection not working" was this. Now lifts to stevia's real 200px top edge; pill stays visible as the dismiss handle, clear of the keys (souveraine 5e5bf04).
  • souveraine-stt error honesty (67aeb25): distinguishes server 5xx / 4xx / unreachable from a genuine empty transcript. The old "didn't catch that" on any no-text result masked a whole server outage as a mic bug.

Historical follow-ons and retained evidence

  1. Dictation UX: the earlier Stevia implementation established the state contract. Squeekboard now renders that contract directly in the mic key; package and glass proof remain.

    2026-07-30 progress:

    • souveraine-stt now writes a 3-state file $XDG_RUNTIME_DIR/souveraine-stt/state (idle|recording|transcribing|error) and --status reads it (with reconciliation). notify toasts fire at every transition. Deployed on the phone.
    • Real "last word didn't type" cause found + fixed: whisper wraps output in embedded \n, and ydotool type typed \n as Enter — chopping/ submitting the dictation mid-stream. The CLI now collapses newlines→spaces (+ --key-delay) before typing.
    • stevia patch 0006 (pkgs/stevia/0006-dictate-key-status-animation.patch, Pixel3Arch e9320be, pkgrel 2): polls the state file from pos-osk-widget and swaps the dictation key's icon by state (recording = mic pulse, transcribing = content-loading, error = warning). Written, applies clean, NOT YET BUILT — archdev's aarch64 GTK3 sysroot + cross-file aren't set up where build-cross.sh expects; building 0.56.0-2 is the remaining step (then pacman -U + systemctl --user restart souveraine-stevia, verify with grim).
  2. Size: Casey settled on gsettings set mobi.phosh.osk scaling "[]" (200px, no auto-scale). The taller auto value is ['auto-portrait','auto-landscape'] (348px). Applies live, no restart. Not a bug — just record the chosen default so a reflash keeps it.

  3. Layouts: the vendored squeekboard us+apple (iOS-style) and us+hacker designs are the target feel; stevia uses its own JSON layout format (src/layouts/*.json in the stevia tree). Porting the iOS layout to stevia is open design work — start from the squeekboard header notes in SouveraineOS/blueline/squeekboard/. The target is now explicit: iOS-like letter geometry, a permanent number row, Hunspell completion retained, working language/layout switcher, mic retained, and compact arrows available outside the terminal-only layout. The parked surfaces/quickshell/assets/keyboard/us.json number-row draft is input, not acceptance.

  4. Hyprland key safety: Pixel3Arch a5fdbf6 ships stevia 0.56.0-5 with high virtual eventcodes plus zeroed fallback modifiers. Keep the compositor-collision hammer test (bound letters/digits must never dispatch Hyprland actions or shutdown) in every later layout patch.

  5. TTS: no server unblocked 2026-07-28. souveraine-speech serves POST /audio/speech at 10.10.20.123:7863 (chatterbox.cpp on ArchDev's RX 560), deliberately API-compatible with the retired VibeVoice route. Config.options.speech.tts and the Settings field are ready — this is now filling in a URL, not building a service.

Context

  • Patches: Pixel3Arch/pkgs/stevia/0001-make-zphoc-device-state-optional.patch (Hyprland compat, upstream candidate) and 0002-dictation-key-terminal-arrows.patch (mic key + arrows).
  • CLI: Pixel3Arch/rootfs-overlay/usr/local/bin/souveraine-stt.
  • Shell: souveraine/surfaces/quickshell/modules/settings/SpeechConfig.qml, modules/common/Config.qml (speech block), settings-phone.qml.
  • The OSK D-Bus plumbing (sm.puri.OSK0 SetVisible, GlobalStates.oskOpen, the "osk" IPC target) is unchanged from squeekboard — stevia's unit claims the same bus name, so shell chrome tracking needed no changes.

Acceptance

Squeekboard raises from ordinary and terminal inputs, types letters/numbers, and survives at least five dismiss/reopen cycles. Its mic key dictates real speech into the focused field and visibly traverses idle → recording → transcribing → idle; the error state is also forced once. The AI side panels must not dismiss or strand it. Only after that proof may Stevia, souveraine-osk-switch, and the shell's keyboard-swap gesture be removed. Native word completion is a following acceptance step, not a blocker for the single-keyboard cutover.

Connects to

whisper-stt-server (the STT backend), TASK-15 (dictation is a network fetcher the idle coordinator must wake for), the stevia patches are upstream candidates (Hyprland compat especially). Under viewtop the OSK's z-order is structurally enforced by the compositor (ad2b6cb, TASK-43) — a layer derived from the surface's furniture role, not a layerrule — so the layer-collision class this task fought in quickshell does not arise there.