feat: live activity push watcher, new session command, resume rename - #359
Merged
Conversation
jongio
force-pushed
the
go/live-activity
branch
2 times, most recently
from
July 22, 2026 16:52
e117dbd to
7518464
Compare
jongio
force-pushed
the
go/live-activity
branch
from
August 1, 2026 17:16
faf35ec to
08be397
Compare
- Add fsnotify-based EventWatcher for push session updates (replaces polling) - Add SessionTracker for PID tracking of launched sessions - Add focus window support (Win32 SetForegroundWindow) - Add new session launcher with + keybinding - Add W keybinding to focus selected session terminal window - Rename custom_command to resume_session_command with v1->v2 migration - Add new_session_command config field and settings panel entry - Add blinking dot and highlighted row for waiting sessions - Show last event type and timestamp in session detail pane - Update all docs (README, SECURITY, config.astro, features.astro) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 37403417-09bc-4600-8056-fbb5a2fb18bb
… --resume' - Change defaultNewSessionCommand from 'gh copilot' to 'copilot' - Flip FindCLIBinary() to prefer 'copilot' over 'ghcs' - Update README, spec doc, web config page with new defaults - Add new_session_command to web config.astro options table Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 37403417-09bc-4600-8056-fbb5a2fb18bb
Two cross-platform bugs surfaced by the new SessionTracker tests on Linux. IsProcessAlive treated PID 0 as alive on Unix: syscall.Kill(0, 0) targets the caller's own process group, so it returns nil. Both implementations now reject non-positive PIDs up front. The existing coverage lived in a windows-only test file, which is why CI never caught it; the tests move to process_test.go so they run on every platform. EventWatcher used one time.AfterFunc per session for debouncing, and Stop only called Timer.Stop() without waiting. A timer that had already fired could invoke onChange after the TUI closed eventWatchCh, panicking with "send on closed channel" (reproduced in 3 of 4 internal/tui runs). Debouncing now uses a dirty set drained by a single goroutine, and Stop waits on a WaitGroup, so no callback can be in flight once Stop returns. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: dac50159-d2c8-4ade-920a-333a51fc9ce3
LastSessionEvent built SessionEvent field-by-field from an identical struct (staticcheck S1016); use a direct conversion instead. Also explicitly discard the return values of the Win32 syscall wrappers in focus_windows.go, which errcheck flags when linting on Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: dac50159-d2c8-4ade-920a-333a51fc9ce3
SessionTracker was never populated outside its own tests. LaunchNewSession always returns PID 0 because wt.exe spawns a detached child whose PID it cannot recover, and the TUI discarded that value anyway, so HasLive was always false and the focus path always fell through to the lock-file lookup. Remove the type and its tests, and collapse handleFocusWindowKey onto FindSessionPID, which is the mechanism that was actually doing the work. The test plan is updated to map the focus cases onto the platform PID tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: dac50159-d2c8-4ade-920a-333a51fc9ce3
jongio
force-pushed
the
go/live-activity
branch
from
August 1, 2026 18:39
48a43d1 to
deebcef
Compare
The rewritten debounce fired a fixed 50ms after the first change rather than after changes stopped arriving, turning it into a throttle. A sustained burst of appends therefore produced one callback per 50ms window instead of one per quiet period, which is what TestEventWatcher_DebounceCollapses caught under the race detector. Reset the window on every new change, as the original per-session timers did, and cap the total deferral at 500ms so a continuously active session still refreshes instead of having its window extended forever. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: dac50159-d2c8-4ade-920a-333a51fc9ce3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds push-based live activity monitoring, session launch/focus capabilities, and renames the config field from
custom_commandtoresume_session_commandwith automatic migration.Changes
Live Activity (push-based)
Stop()blocks until that goroutine exits, so no callback can fire after the TUI tears down its channel.SetForegroundWindowAPI to bring a session's terminal window to front (Wkeybinding). The PID is resolved from the session's lock file, then the parent process chain is walked to find a visible top-level window.+keybinding)Visual Enhancements
Config Rename
custom_commandrenamed toresume_session_command(config v1 to v2 migration)new_session_commandconfig fieldBug fixes found while getting CI green
IsProcessAlivetreated PID 0 as alive on Unix, becausesyscall.Kill(0, 0)targets the caller's own process group. Both implementations now reject non-positive PIDs. Its test coverage lived in a//go:build windowsfile, which is why CI never caught it; the tests moved toprocess_test.goso they run on every platform.EventWatcher.Stop()only calledTimer.Stop()on its per-session debounce timers without waiting, so an already-fired timer could invokeonChangeafter the TUI closedeventWatchChand panic with "send on closed channel". Reproduced in 3 of 4internal/tuiruns before the fix.Testing
IsProcessAlive: 3 tests, now running on all platformsgo vetand golangci-lint clean