Repository navigation
Close Mac/Linux gaps: daemon-failure alert, K2 on Sway and X11, host tests - #153
algorithmx wants to merge 7 commits into
Conversation
tools/test-linux-host.sh runs the real vibebuddyd against the firmware core's simulator, joined through a PTY, with no box, desktop, user config or network. The simulator gains a test-only control socket (button levels, clock advance, reboot) and a --build override; desktop command helpers are stubbed and logged. A headless probe (host_status_probe) feeds live snapshots through the Linux app's status and tray model. The 28 scenarios cover boot identity and pairing, activity states, K2 routing, local K0/K1, unplug and replug, Wi-Fi signals, voice and Character pack writes and their failure paths, the status stream, malformed device output, screenshots and foreign firmware. CI runs the suite on Ubuntu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Mac app notifies when its supervisor gives up on the daemon; the Linux app, whose daemon systemd supervises, said nothing. It now notifies through notify-send once after 30 s without the daemon, and again only after a recovery. A unit stopped on purpose (inactive or deactivating) stays silent and is rechecked after another 30 s, so a failed restart after a stop still notifies. An unreadable unit state, or a systemctl that doesn't answer, still notifies. The policy lives in desktop/src/outage.rs; daemon_outage_probe drives it headless from the real status stream. - Restart daemon on Advanced works while the daemon is down: Advanced and the tray both restart through systemd and report a failure, as the Mac's button calls its supervisor. - The Linux status stream bounds response headers to 10 s and inactivity to 45 s, so a daemon that stalls with the socket open counts as down; SSE keepalives keep a quiet healthy stream alive. - Mac: the stream uses the same 45 s inactivity timeout, and the failure notification follows the last reported "Notify me" setting instead of defaulting to on once the status is cleared. Eleven host scenarios cover the grace period, recovery, the toggle, an intentional stop, a failed restart after it, crash loops and slow or failing systemctl. Not run on a real desktop; the Swift changes are not compiled here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the Mac, K2 brings the agent's terminal or app forward on any desktop. On Linux it focused a window only on Hyprland. daemon/src/window_focus.rs adds two backends that list windows with their pids and focus the one owned by the nearest of the agent's ancestors: Sway (`swaymsg -t get_tree`, then focus by container id) and X11 (`wmctrl -l -p`, then raise by window id). Hyprland stays the default; Sway is chosen only for a SWAYSOCK that exists, X11 only for an X11 session, so XWayland under a Wayland compositor is not X11. The window-system variables come from `systemctl --user show-environment` at each press, then from the daemon's own environment: systemd can start the daemon before the desktop imports them, and the user manager has what was imported since. The helper runs with those variables. The AUR package lists wmctrl as optional. GNOME and KDE under Wayland still get no window focus; a tmux pane switch still happens. Sixteen host scenarios run each backend against recorded listings: nearest ancestor, needs-input priority, a source surviving a restart, missing windows, malformed output, refused, failing and slow helpers, a stale Sway socket and XWayland. Not run on a real Sway or X11 login. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Show daemon log ran only xdg-terminal-exec, which Ubuntu 22.04, for one, doesn't have, so the button did nothing there. It now falls back to GNOME Terminal, Konsole, Xfce Terminal and xterm. Only a terminal that isn't installed moves on to the next; one that fails to start is reported. With none installed, Advanced says which command shows the log (zh-Hans included). The Mac has no such button: its daemon logs to a file in the logs folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/platform-parity.md compares the two apps row by row (settings, notifications, tray, K2, paths and packaging), names the code each row rests on, ranks the gaps that remain and says what has and hasn't been run. The README (both languages), docs/app.md and docs/architecture.md describe the daemon-failure notification, K2 on Sway and X11, and the tray on GNOME. docs/linux-host-testing.md explains the host suite. Two lessons from writing its scenarios go in LESSONS.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review notes on 1. "Restart daemon" now needs systemd —
|
Review of second-state#153 found two Linux features deciding from claims about the environment instead of from the thing they act on. K2 took the window system from systemd's user manager, which belongs to the user rather than a session and keeps what an ended session imported, and fell back to Hyprland when it knew nothing. A Hyprland signature left there made every press run hyprctl on a Sway or X11 login. Now: - the window system comes from the environment of the processes being focused (/proc/<pid>/environ), taken whole from the nearest graphical one; the user manager, then the daemon's own environment, are only a fallback for processes that can't be read; - Hyprland and Sway count only while their socket accepts a connection (Hyprland's in $XDG_RUNTIME_DIR/hypr, or /tmp/hypr before 0.40); - with no evidence, nothing is focused and no helper runs: the session "runs no supported window system". The Linux app assumed systemd ran the daemon. For one started by hand, Restart failed, Show daemon log showed an empty journal, and the failure alert read the unit's `inactive` as a deliberate stop and never fired. Now the daemon reports `daemon.supervisor` (systemd or other) from its own cgroup, not from INVOCATION_ID, which a terminal run as a service passes down. The app keeps the last answer while the daemon is down: - Restart and Show daemon log say why they can't act on that daemon; - the alert goes out without asking systemd and says to start the daemon again by hand; - POST /v1/daemon/restart refuses with 409 instead of exiting, since nothing would start the daemon again. The Mac app is unchanged: it already knows whether it or a LaunchAgent supervises the daemon (managesDaemon), and the daemon reports nothing there. Also drops a comment's reference to private review notes. The host harness now starts a real process for each placeholder pid with the scenario's session environment, and real listening sockets for Hyprland and Sway. New scenarios cover stale Hyprland and X11 variables in the user manager, the user-manager fallback, a socket nobody listens on, and a daemon outside the service. 61 host scenarios and 532 workspace tests pass. Breaking each new rule on purpose fails the scenarios meant to catch it. Not run on a real Sway, X11 or GNOME session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/parity-scenarios/ holds 70 notes, one per thing the Mac app does, read from its code: lifecycle and daemon supervision, the menu bar, notifications, each Settings tab, the first-run guide and errors. Each note gives the initial state, the trigger, the app's steps with the exact UI strings and daemon calls, and the final state. It ends with a checklist of questions for the Linux app and a blank result to fill in (same, differs by design, gap or not applicable). The README indexes them and says how to use them. The notes describe the Mac app only. Where platform-parity.md already records a difference as by design, the note says so; everything else is a question, not a claim about Linux. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@longzhi Thanks for the review. All three points were real, and each turned out to be one case of a wider problem, so 887ec20 fixes the cause rather than the symptom. 1. Restart without systemdI didn't add the
2. Stale Hyprland signatureFixed as you suggested, and more broadly:
This also covers stale X11 variables in the user manager and a Sway socket left behind by a crashed compositor. 3. "(G4 review 3.4)"Removed. TestsThe host suite now starts a real process for each placeholder pid, with the session environment each scenario sets up, plus real listening sockets for Hyprland and Sway. New scenarios cover stale Hyprland and X11 variables, the user-manager fallback, a socket nobody listens on, and a daemon outside the service.
Nothing has been run on a real Sway, X11 or GNOME session yet. Parity scenario notes7acc6a9 adds
The next commit will be based on these notes: I'll go through them against the Linux app, fill in the results, and fix the gaps they turn up. |
Closes part of the gap between the Mac app (
app/) and the Linux app (desktop/).docs/platform-parity.md(new) compares the two row by row, names the code each row rests on, and ranks what's still missing. Five commits, each reviewable on its own:tools/test-linux-host.shruns the realvibebuddydagainst the firmware core's simulator through a PTY: no box, desktop, user config or network. The simulator gains a test-only control socket (buttons, clock, reboot). Desktop helpers (hyprctl,swaymsg,wmctrl,notify-send,systemctl, …) are stubbed and recorded. CI runs it on Ubuntu.notify-sendafter 30 s without the daemon, again only after a recovery. A unit stopped on purpose stays silent but is rechecked, so a failed restart after it still notifies.daemon/src/window_focus.rs:swaymsgby container id,wmctrlby window id). The window-system variables are read fromsystemctl --user show-environmentat each press, so a daemon systemd started before the desktop imported them still finds the session. The AUR package listswmctrlas optional. GNOME/KDE under Wayland still get only the tmux pane switch.xdg-terminal-exec(missing on Ubuntu 22.04) to GNOME Terminal, Konsole, Xfce Terminal and xterm. With none installed, Advanced says which command to run. The Mac has no such button; its daemon logs to a file.platform-parity.md,linux-host-testing.md, README (both languages),app.md,architecture.md, two LESSONS entries.UI strings have zh-Hans translations (286 keys).
Validation
On Linux (Ubuntu), from
574b700:cargo test --workspace --locked: 525 passed, 1 ignored (the native-USB ROM test).cargo clippy --workspace --all-targets --locked: only the four warningsmainalready has.tools/check-localization.pyand the Python tool tests pass.tools/test-linux-host.sh: 55 scenarios pass (28 device/host, 11 daemon outage, 9 Sway, 7 X11).Not run: the Swift changes are not compiled here (the
mac-appjob will be their first build); no real Sway or X11 login; no real notification server or systemd unit; no tray on Fedora/upstream GNOME/KDE; no box attached. Those stay listed as pending inplatform-parity.md.🤖 Generated with Claude Code