tasks: rewrite 03 (boot timing, source-verified faults), add 17 (keyboard/dictation)
03: today's deep boot investigation — the splash-to-splash flicker is a DRM-master handoff race on a panel with supportsAsyncCommit:false (56 EBUSY commits); the Hyprland splash text is killed (disable_splash_rendering); the corner box is an unidentified top-right toast (NOT the error overlay, which stays); the recovery-mode wedge is documented. The EBUSY handoff fix is the one real remaining timing bug. 17: stevia OSK + mic key + dictation shipped this session; layout/UX polish and TTS wiring remain.
This commit is contained in:
parent
e37551014b
commit
8578e654d2
3 changed files with 175 additions and 50 deletions
|
|
@ -1,72 +1,117 @@
|
|||
# TASK 03 — Boot timing: fade splash → lock, no extra fixes
|
||||
|
||||
**Status:** open. This is Casey's framing of the real goal: "the dang
|
||||
boot video is more than long enough if things were being timed right
|
||||
such that we didn't need all these extra fixes."
|
||||
**Status:** open, deeply diagnosed 2026-07-21. Casey's framing: "the dang
|
||||
boot video is more than long enough if things were being timed right such
|
||||
that we didn't need all these extra fixes." The boot is visually ugly even
|
||||
on a *successful* boot — splash-to-splash flicker, a stray corner box, and
|
||||
the desktop assembling in the open before the lock covers it. Three of the
|
||||
faults are now root-caused to source; two fixes landed today.
|
||||
|
||||
## Goal
|
||||
|
||||
One clean boot timeline: boot video (splash) plays, fades directly onto
|
||||
the lockscreen. No second PIN flash, no polkit interruption, no gap that
|
||||
needs a fallback surface to paper over. The fixes from 2026-07-17
|
||||
(splash deadlock removed, fallback made quiet, dismissnotify) are
|
||||
patches; this task is making the timing actually right so the patches
|
||||
stop being load-bearing.
|
||||
the lockscreen. No flicker, no error box, no gap that shows the desktop.
|
||||
|
||||
## The desired timeline
|
||||
|
||||
```
|
||||
kernel quiet ─ splash starts ─ DRM probes ─ splash animating
|
||||
─ greetd initial session (souveraine-session)
|
||||
─ souveraine-splash --wayland holder maps (act two)
|
||||
─ sessiond acquires ext-session-lock, renders glance (TASK-02)
|
||||
─ quickshell starts, registers, sessiond hands off the lock
|
||||
─ shell lockscreen glance visible
|
||||
splash fades onto the shell lockscreen ─ done
|
||||
─ quickshell starts, BootBloom maps, holder crossfades to it
|
||||
─ sessiond hands off the lock, shell lockscreen visible
|
||||
splash → holder → bloom → lock, one continuous bloom ─ done
|
||||
```
|
||||
|
||||
The splash must hold DRM master until the shell lockscreen has real
|
||||
content, then release. Today `souveraine-splash.service` (oneshot) +
|
||||
`souveraine-session` (greetd initial session, pokes `/run/souveraine-splash.sock`
|
||||
and waits for it to vanish) own this handoff. The 30s deadlock that
|
||||
gated every boot is fixed (`Pixel3Arch 93c1371`, `0ec54da`); verify the
|
||||
handoff is now prompt, not riding the backstop watchdog.
|
||||
## Root-caused faults (2026-07-21, source-verified)
|
||||
|
||||
The visible mess is THREE distinct problems, not one. Read the live boot
|
||||
log: `journalctl -b -o short-monotonic` and the Hyprland instance log at
|
||||
`/run/user/1000/hypr/<sig>/hyprland.log` (grep -v the GL_ extension dumps).
|
||||
|
||||
1. **The splash-to-splash flicker = a DRM-master handoff race on a panel
|
||||
that can't async-commit.** aquamarine logs `drm: drmProps.supportsAsyncCommit:
|
||||
false` for DSI-1, then `Clearing stale page-flip state for DSI-1 (pending
|
||||
for 598ms)`, then **56 consecutive** `atomic drm request: failed to
|
||||
commit: Device or resource busy`. The C splash leaves a page-flip pending
|
||||
when it drops DRM master; Hyprland grabs the CRTC and, unable to queue
|
||||
behind the stale flip (no async commit on this panel), spins EBUSY until
|
||||
it retires. Source: hyprwm/aquamarine `src/backend/drm/DRM.cpp`
|
||||
(`CDRMOutput::commitState` retries as blocking modeset, sets
|
||||
`commitTainted` on fail — no per-frame backoff before that).
|
||||
- Escape hatch (blunt): `env = AQ_NO_ATOMIC,1` forces legacy KMS
|
||||
("heavily not recommended" upstream, but real). NOT applied.
|
||||
- Proper fix (UNDONE): tighten souveraine-session's handoff so the C
|
||||
splash fully drains its last page-flip and drops master BEFORE
|
||||
Hyprland modesets — no overlapping pending flip. This is the real
|
||||
TASK-03 work item.
|
||||
|
||||
2. **The "Hyprland :)" splash TEXT — FIXED 2026-07-21.** `disable_hyprland_logo`
|
||||
(already set) only kills the mascot background; the handwritten splash
|
||||
text is a SEPARATE option, `misc.disable_splash_rendering`, which
|
||||
defaulted on. Now `= true` in overlays/hypr/hyprland.lua (Pixel3Arch
|
||||
488139b), live-confirmed `set:true`.
|
||||
|
||||
3. **The small upper-right corner box during the flashes — NOT yet pinned
|
||||
to a specific trigger.** It is one of Hyprland's top-right toasts
|
||||
(`src/notification/NotificationOverlay.cpp`) — startup callers in
|
||||
`Compositor.cpp` fire for: non-"Hyprland" XDG_CURRENT_DESKTOP, missing
|
||||
`hyprland-dialog`, failed render assets (`m_failedAssetsNo > 0`, red),
|
||||
no watchdog fd — and `PluginSystem.cpp` toasts a **failed plugin load**
|
||||
(hyprgrass is loaded via `hyprpm reload` at boot step 2). Most likely
|
||||
suspects here: failed-assets or a hyprgrass API-version toast. NEXT:
|
||||
catch it live (it is transient; a boot screen-record or reading
|
||||
`hyprctl notifications`/asset-fail count right after boot names it).
|
||||
This is NOT the CHyprError overlay (`src/errorOverlay/`) — Casey
|
||||
explicitly does NOT want that touched; leave error reporting intact.
|
||||
|
||||
Separately: **the desktop-visible ~12s gap.** Splash releases ~20.8s but
|
||||
sessiond doesn't confirm the shell's lock until ~33s. The bloom holder
|
||||
(souveraine-splash --wayland, added 2026-07-21, Pixel3Arch 20e72c5) is
|
||||
meant to cover this whole window; on Casey's eyes it still leaks Hyprland
|
||||
through. Verify the holder actually maps first and stays up until BootBloom
|
||||
pokes it — a gap here is a holder-timing bug, not a new surface.
|
||||
|
||||
## Worse, separate: recovery-mode wedge
|
||||
|
||||
If `hyprland.lua` fails to load, Hyprland falls to `recoverycfg.lua`
|
||||
(autogenerated), whose boot exec chain never runs the real step 0-4 wiring
|
||||
AND which grabs the ext-session-lock itself, showing the built-in "Oopsie
|
||||
daisy… lockscreen app died" screen. Then sessiond/shell can never take the
|
||||
lock (`lock denied/revoked — another locker owns the session`) because
|
||||
Hyprland owns it and Wayland only lets the locking client unlock. Observed
|
||||
2026-07-21 after a shell restart landed on a prior recovery instance.
|
||||
Recovery is: at the device, drop Hyprland's lock (the fallback screen
|
||||
prints the commands) or cold boot. Watch for it: `hyprctl binds | grep -c
|
||||
dispatcher` returns ~3 in recovery vs ~48 on the real config; `ls
|
||||
/run/user/1000/hypr/<sig>/recoverycfg.lua` present is a tell but not proof
|
||||
(Hyprland writes it as a fallback artifact even on good boots).
|
||||
|
||||
## Context
|
||||
|
||||
- `~/Projects/Pixel3Arch/rootfs-overlay/etc/systemd/system/souveraine-splash.service`
|
||||
— oneshot, deliberately NOT `Before=greetd` (that was the deadlock leg 1).
|
||||
- `~/Projects/Pixel3Arch/overlays/greetd/souveraine-session` — the
|
||||
initial-session wrapper that fades the splash and waits for DRM release
|
||||
before exec'ing start-hyprland.
|
||||
- `~/Projects/Pixel3Arch/overlays/greetd/config.toml` —
|
||||
`[initial_session] command = "/usr/local/bin/souveraine-session"`.
|
||||
- `~/Projects/Pixel3Arch/overlays/hypr/hyprland.lua` — boot step 3
|
||||
restarts `souveraine-shell.service` (supervised, `Pixel3Arch d230764`).
|
||||
- `~/Projects/SouveraineOS/docs/LOCK-DPMS-LESSONS.md` §5 — lock
|
||||
architecture: sessiond takes the lock before the shell; ~1.05s handoff
|
||||
gap; `lockdead_screen_delay = 4000` in hyprland.lua.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Instrument before touching.** Boot once with timestamps:
|
||||
`journalctl -b -o short-monotonic | grep -E 'souveraine-splash|souveraine-session|souveraine-sessiond|souveraine-shell|greetd'`.
|
||||
Find where the wall-clock actually goes. Don't tune blind.
|
||||
2. Confirm the splash fades onto the shell lockscreen with no visible
|
||||
second surface (validates TASK-02's quiet fallback end-to-end).
|
||||
3. Confirm no polkit/NM password prompt interrupts boot (see handoff
|
||||
doc "Boot password prompt" note — was NetworkManager 802.11 auth
|
||||
timeout, patched live on the named SSIDs; verify it stays fixed).
|
||||
4. Only if there's a real gap, tighten ordering. Target: splash visible
|
||||
for its full intended duration, then a single fade to the lock.
|
||||
- `Pixel3Arch/bootsplash/` — the C DRM splash (`main.c`) + the new
|
||||
`--wayland` holder (`wayland.c`) + `splash-signal.c` (pokes both the
|
||||
/run and $XDG_RUNTIME_DIR sockets). Builds native on the phone.
|
||||
- `Pixel3Arch/overlays/greetd/souveraine-session` — greetd initial
|
||||
session; pokes the DRM splash and waits for socket vanish before
|
||||
exec start-hyprland. **This is where fault #1's handoff fix goes.**
|
||||
- `Pixel3Arch/overlays/hypr/hyprland.lua` — boot step 0 launches the
|
||||
holder, step 3 restarts souveraine-shell.service.
|
||||
- `SouveraineOS/docs/LOCK-DPMS-LESSONS.md` §5 — lock arch, ~1.05s handoff
|
||||
gap, `lockdead_screen_delay = 4000`.
|
||||
- Panel fact: DSI-1, 1080x2160@60, `supportsAsyncCommit:false`,
|
||||
freedreno/FD630 — the async-commit limit is hardware, not config.
|
||||
|
||||
## Acceptance
|
||||
|
||||
A cold boot shows: boot video → fade → lockscreen. One lock surface,
|
||||
ever. No password prompt mid-fade. `systemd-analyze blame` shows the
|
||||
splash isn't gating on the watchdog.
|
||||
A cold boot shows: boot video → one continuous bloom → lockscreen. No
|
||||
splash-to-splash flicker (no EBUSY storm, or it's hidden). No Hyprland
|
||||
splash text (done). No stray corner toast. No desktop visible before the
|
||||
lock. One lock surface, ever.
|
||||
|
||||
## Connects to
|
||||
|
||||
TASK-02 (the glance the splash fades onto), TASK-10 (mkinitcpio removes
|
||||
the white initramfs text before the splash — separate but adjacent),
|
||||
TASK-11 (souveraine-secrets, which must not prompt at boot).
|
||||
TASK-02 (the glance the bloom fades onto), TASK-10 (mkinitcpio initramfs
|
||||
text before the splash), TASK-11 (souveraine-secrets must not prompt at
|
||||
boot). The EBUSY handoff fix (#1) is the last load-bearing timing bug.
|
||||
|
|
|
|||
78
docs/tasks/17-keyboard-stevia-dictation.md
Normal file
78
docs/tasks/17-keyboard-stevia-dictation.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# TASK 17 — Keyboard (stevia) + dictation polish
|
||||
|
||||
**Status:** shipped-partial 2026-07-21. The phone went from NO on-screen
|
||||
keyboard to a working patched stevia with a mic key and live dictation in
|
||||
one session. What shipped works; the follow-ons are UX/layout polish.
|
||||
|
||||
## What shipped (2026-07-21)
|
||||
|
||||
- **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.
|
||||
|
||||
## Follow-ons (the polish that remains)
|
||||
|
||||
1. **Dictation UX**: the mic key spawns the CLI fire-and-forget — no
|
||||
in-keyboard recording indicator (the CLI sends a notify-send "Listening…"
|
||||
toast, which is coarse). A pressed/recording state on the key itself
|
||||
(stevia has `--status` wired: `souveraine-stt --status` → idle|recording)
|
||||
would be the honest tell. Needs a stevia patch to poll status and
|
||||
restyle the key, OR drive it off the notify path.
|
||||
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/`.
|
||||
4. **TTS**: Config.options.speech.tts + the Settings field exist but the
|
||||
endpoint is empty — no TTS server on the VPN yet (VibeVoice runs on
|
||||
10.10.20.19 but isn't wired to a REST route the shell can call). When
|
||||
one exists, the settings field is ready.
|
||||
|
||||
## 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
|
||||
|
||||
Keyboard usable in every app; mic key dictates real speech into the
|
||||
focused field (verified 2026-07-21: "Hello, can you hear me?" end-to-end);
|
||||
pill dismisses without eating key taps; a recording indicator makes the
|
||||
mic key's state obvious.
|
||||
|
||||
## 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).
|
||||
|
|
@ -12,9 +12,9 @@ plus open threads from the 2026-07-17 session.
|
|||
|
||||
| # | Task | Status | Blocks / blocked-by |
|
||||
|---|------|--------|---------------------|
|
||||
| 1 | [Favorites — wife's name on her number](01-favorites-contacts.md) | blocked | needs a contacts-store decision (qtpim retired — see archive/06) |
|
||||
| 1 | [Favorites — wife's name on her number](01-favorites-contacts.md) | blocked | blocked-by TASK-16 (culver-contacts is the store) |
|
||||
| 2 | [Lockscreen-as-Rust-system: glance + swipe](02-lockscreen-rust-system.md) | in progress | stopgap shipped 2026-07-17 |
|
||||
| 3 | [Boot timing: fade splash → lock, no extra fixes](03-boot-timing-splash-to-lock.md) | open | paired with TASK-11 (now archived) |
|
||||
| 3 | [Boot timing: fade splash → lock, no extra fixes](03-boot-timing-splash-to-lock.md) | diagnosed | EBUSY handoff race is the last timing bug; splash text killed, holder added |
|
||||
| 7 | [WCD9340 mic: functional-pinned; unpin + fidelity](07-mic-wcd9340-slim-tx.md) | functional 07-20 | defect: power pin; kernel `mic-race-fix` |
|
||||
| 8 | [Device state manager / power profiles](08-device-state-manager.md) | open | blocked-by TASK-09 suspend item |
|
||||
| 9 | [Suspend-resume FTS calibration race](09-suspend-resume-fts.md) | interim-fix | kernel-side; cold-boot only |
|
||||
|
|
@ -22,6 +22,8 @@ plus open threads from the 2026-07-17 session.
|
|||
| 13 | [Active Edge (squeeze) as a sensor input](13-active-edge-squeeze.md) | open | substrate up; bring-up unit not drafted |
|
||||
| 14 | [Overview pane → phone app grid](14-overview-appgrid.md) | open | shell-side; appgrid prior art linked in-file |
|
||||
| 15 | [Idle coordinator: freeze, doze, scheduled wakeups](15-idle-coordinator.md) | open | design; blocked-by 09 for suspend tier; eats half of 08 |
|
||||
| 16 | [culver: usable messenger + contacts as Personal-class store](16-culver-messenger-contacts.md) | open | unblocks TASK-01; uses TASK-11 (keying) + archive/04 (NotifyEvents) |
|
||||
| 17 | [Keyboard (stevia) + dictation polish](17-keyboard-stevia-dictation.md) | shipped-partial | OSK + mic key + STT live 07-21; layout/UX follow-ons |
|
||||
|
||||
Archived (see `archive/`): 05 crash reporter — done 2026-07-21,
|
||||
CrashReporter.qml in-shell watcher, kill-test verified on device;
|
||||
|
|
|
|||
Loading…
Reference in a new issue