mirror of
https://github.com/tiennm99/claude-code-usage-bubble.git
synced 2026-10-22 00:15:01 +00:00
docs: record the app runtime status and decisions
This commit is contained in:
1 parent
83f60d1c1c
commit
a395c66248
1 file changed
+52
-1
@@ -1,7 +1,7 @@
|
||||
---
|
||||
phase: 4
|
||||
title: "App runtime: state, scheduler, CLI, single instance"
|
||||
status: pending
|
||||
status: completed
|
||||
priority: P1
|
||||
effort: "5h"
|
||||
dependencies: [3]
|
||||
@@ -62,6 +62,57 @@ command and event bridge. All of it lives in the lib (D1); `run()` is the entry.
|
||||
2. Build `AppState`, the scheduler and propagate. Use a fake emitter trait so the scheduler's deadline logic is unit-testable without a window, including "Weekly to Daily with the last check 2 days ago checks at once".
|
||||
3. Wire the commands. Leave bubble creation to Phase 06; the test window from Phase 01 renders the payload as raw JSON for now.
|
||||
|
||||
## Todo
|
||||
|
||||
- [x] `src/cli.rs`: pure parser for `--diagnose`, `--wait-pid <pid>` and `--updated-to <v>` (alone and combined); unknown flags, `--apply-update`, pid 0 and non-version values are ignored; arguments read with `args_os`
|
||||
- [x] Pre-Builder order in `runtime::run()`: diag, `cfg(windows)` WebView2 guard with `message_box_error` and exit 0, `--wait-pid` wait capped at 15 s and logged, Linux `GDK_BACKEND=x11` rule, single-instance plugin first with a no-op callback, no other plugin
|
||||
- [x] `platform::wait_pid`: `kill(pid, 0)` every 100 ms on Unix, `OpenProcess`/`WaitForSingleObject` on Windows; `platform::windows::{webview2_available, message_box_error, is_dark}`
|
||||
- [x] `setup()`: settings load, `drop_offscreen_positions` against `available_monitors()`, theme read, `AppState` behind one mutex with `with_state`, `UiBridge` holding the `AppHandle`, startup cleanup, scheduler start, first poll
|
||||
- [x] `src/handoff.rs`: `relaunch(extra_args) -> io::Result<()>` (`$APPIMAGE` or `current_exe`, `--wait-pid <pid>`, Windows creation flags, own process group on Unix) and `cleanup_stale_files` with a temp-dir test
|
||||
- [x] `src/scheduler.rs`: `PollNow`, `SetPollInterval`, `RecomputeCountdown`, `SetUpdateInterval`, `UpdateCheckDone`, `Shutdown`; pure `Deadlines` tested with a fake host, including "Weekly to Daily with the last check 2 days ago checks at once"
|
||||
- [x] Poll worker: `AtomicBool` gate, registry poll, `apply_results`, CLI refresh (8 s each, session-expired alert for the first provider not `Refreshed`, no re-poll), then `propagate()`
|
||||
- [x] `propagate()`: snapshot under the lock, payloads built and emitted to `bubble-<slug>` from the main thread, countdown re-armed
|
||||
- [x] Commands `get_bubble_state`, `get_strings`, `log_js`, `bubble_ready`, with argument validation
|
||||
- [x] `RunEvent::ExitRequested { code: None }` prevents exit; `RunEvent::Exit` stops the scheduler; bubbles `prevent_close`
|
||||
- [x] Restart (save, `relaunch(&[])`, exit only on `Ok`) and Exit on `Runtime`
|
||||
- [x] `--updated-to` stored as a pending `UpdateApplied` alert
|
||||
- [x] Deleted `src/app.rs` and `src/update/handoff.rs`
|
||||
- [x] Host: `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test` (155 passed, 1 ignored), `npm run lint`, `npm test`, `npm run tauri build -- --no-bundle`
|
||||
- [x] CI Windows, Linux and macOS rows green
|
||||
- [ ] Linux desktop (X11) and Windows manual checks; they need a display and the Restart/Exit menu, which arrives with the menu work
|
||||
|
||||
## Implementation notes
|
||||
|
||||
- `GDK_BACKEND=x11` is set only when `DISPLAY` is also set. With
|
||||
`WAYLAND_DISPLAY` but no X server, forcing x11 would stop GTK from starting
|
||||
at all, so the native Wayland backend stays and positioning features become
|
||||
no-ops later (D12).
|
||||
- On Windows the parent wait is one `WaitForSingleObject` with the 15 s
|
||||
timeout instead of 100 ms polls: it returns as soon as the process exits and
|
||||
holds the handle, so a reused pid cannot be mistaken for the parent.
|
||||
- `--wait-pid 0` is rejected: on Unix `kill(0, 0)` addresses the process group.
|
||||
`--updated-to` accepts only version-like text (digits first, then
|
||||
`[0-9A-Za-z.+-]`, at most 64 chars), because it ends up in a notification.
|
||||
- The scheduler floors the poll interval at 10 s and the update interval at
|
||||
60 s, so a hand-edited `0` cannot become a busy loop. The update deadline is
|
||||
cleared when a check fires and only `UpdateCheckDone` re-arms it.
|
||||
- The scheduler channel is created before the thread starts, so the runtime
|
||||
holds its sender before the first action runs.
|
||||
- The update check action and the alert delivery are hooks: no updater or
|
||||
notification plugin is registered yet (D8, D9), so a due check only logs and
|
||||
alerts reach the diagnostic log. The pending update-applied alert waits in
|
||||
`AppState::pending_update_alert`. `tray::sync`, `menu::refresh` and
|
||||
`panel::refresh_if_visible` join `propagate()` with their modules.
|
||||
- `bubble_ready` shows the window with `show()` until the no-activation show
|
||||
path exists (D5).
|
||||
- The scaffold window is now labelled `bubble-<first enabled provider>`, is a
|
||||
decorated 460x420 window, renders the payload JSON from `get_bubble_state`
|
||||
and `bubble:update`, and forwards errors through `log_js`. Like every bubble
|
||||
it ignores close requests.
|
||||
- `LocaleStrings` derives `Serialize` (camelCase) for `get_strings`.
|
||||
- `src/update/mod.rs` and `install.rs` still name the deleted `handoff`
|
||||
module. They are outside the module tree; the updater rewrite replaces them.
|
||||
|
||||
## Validation
|
||||
|
||||
- Host: `cargo test cli:: scheduler:: handoff::` is green.
|
||||
|
||||
Reference in new issue
Block a user