Skip to content

feat(agent-dashboard): persist hook status across Orca restart#1480

Open
brennanb2025 wants to merge 2 commits intomainfrom
brennanb2025/agent-status-preserve-restart
Open

feat(agent-dashboard): persist hook status across Orca restart#1480
brennanb2025 wants to merge 2 commits intomainfrom
brennanb2025/agent-status-preserve-restart

Conversation

@brennanb2025
Copy link
Copy Markdown
Contributor

@brennanb2025 brennanb2025 commented May 6, 2026

Summary

  • Persists the hook server's per-pane lastStatusByPaneKey to userData/agent-hooks/last-status.json (atomic write, 250ms trailing debounce, sync flush on stop()), gated on experimentalAgentDashboard. Fixes done, blocked, and quiet working rows winking out after restart.
  • Adds an agentStatus:drop IPC so renderer dismissals (dropAgentStatus, dismissRetainedAgentsByWorktree) propagate to the main-process cache and the on-disk file, preventing dismissed rows from resurrecting on relaunch.
  • Adds a bounded bootstrap queue in useIpcEvents so setListener() replay during window creation isn't dropped while App.tsx is still hydrating tabsByWorktree; drains on the workspaceSessionReady false→true transition.

Design doc: docs/agent-dashboard-retention-restart.md.

Test plan

  • pnpm typecheck
  • pnpm test src/main/agent-hooks/server.test.ts (13 new persistence/hydration tests)
  • pnpm test src/main/ipc/agent-hooks.test.ts (new IPC handler tests)
  • pnpm test src/renderer/src/store/slices/agent-status-drop-ipc.test.ts (slice IPC fan-out)
  • pnpm test src/renderer/src/hooks/agent-status-bootstrap-queue.test.ts (queue/drain/cap)
  • Existing useIpcEvents.test.ts mocks updated for useAppStore.subscribe
  • Manual: with the experimental dashboard on, run an agent to done, quit, relaunch — row reappears within first dashboard frame
  • Manual: quit while a Claude is blocked on a permission prompt — row reappears with prompt + tool name
  • Manual: dismiss a retained row, quit, relaunch — row stays dismissed
  • Manual: archive a worktree with retained agents, quit, relaunch — none reappear; last-status.json no longer contains them
  • Manual: flag off — last-status.json is never created
  • Manual: hand-edit last-status.json to invalid JSON, relaunch — single warn, dashboard renders normally

Made with Orca 🐋

brennanb2025 and others added 2 commits May 5, 2026 17:45
Hydrates the hook server's per-pane lastStatusByPaneKey from
userData/agent-hooks/last-status.json before binding the HTTP listener,
mirrors mutations to disk via a 250ms trailing debounce, and flushes
synchronously on stop(). Renderer dismissals fan out a new
agentStatus:drop IPC so the on-disk file evicts the entry and a
relaunch cannot resurrect it. Adds a bounded bootstrap queue in
useIpcEvents so events replayed by setListener() during window creation
are not dropped while App.tsx is still hydrating tabsByWorktree.

Gated on settings.experimentalAgentDashboard. Done, blocked, and quiet
working rows now all survive across restart.

Co-authored-by: Orca <help@stably.ai>
Address review findings on the retention-restart branch:

- Wrap agentStatus:getSnapshot and agentStatus:drop IPC handlers in
  try/catch so a throw cannot surface as an unhandled invoke rejection
  (silent startup-hydration failure) or crash main from a fire-and-
  forget listener.
- runStatusPersist no longer permanently suppresses gate-off deletion
  retries on transient unlink errors (e.g. EPERM); deletedOnDisable
  now flips only on success or ENOENT.
- Tighten tests: stale-version-hydrate now asserts the warn message
  content; getSnapshot test uses toEqual; drop-handler test rejects
  null/{}/[] in addition to the prior bad inputs.

Co-authored-by: Orca <help@stably.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant