mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* feat(agent-dashboard): persist hook status across Orca restart 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> * fix(agent-dashboard): harden hook persistence IPC and gate-off deletion 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> * fix(agent-dashboard): bound on-disk hydrate growth and reject tabId/paneKey drift - Drop hydrate entries older than 7 days (HYDRATE_MAX_AGE_MS) so stale rows from worktrees archived weeks ago do not pile up forever. PTY- teardown eviction handles closed panes; the TTL covers daemon-restored PTYs that never re-attach and crash-recovery paths. - Reject hydrate entries whose `tabId` field diverges from the paneKey's tab segment. Cheap defensive add against future renamer/shape drift. Doc updated to move TTL out of the follow-ups list (now in scope). Tests: new "drops hydrate entries older than the TTL cutoff" and "drops a hydrate entry whose tabId disagrees with the paneKey prefix"; existing hydrate fixtures now use a `recentTs()` helper instead of fixed 2023 timestamps. Co-authored-by: Orca <help@stably.ai> * fix(agent-dashboard): post-review polish on hook status persistence Apply review-fix corrections on the agent-dashboard restart-persistence work: - Split dropStatusEntry from clearPaneState so renderer-driven dismiss IPC no longer wipes lastPromptByPaneKey/lastToolByPaneKey for a still-alive pane. - Validate paneKey shape at the IPC boundary (isValidPaneKey). - Let getSnapshot errors propagate instead of silently returning [] — matches the renderer's existing .catch and avoids masking a broken persistence path. - Trust main's authoritative timing.stateStartedAt unconditionally on same-state pings; fall back to existing only when timing is absent. - Use strict < on the snapshot/live updatedAt guard so two events in the same millisecond don't drop the second one (a <= guard regressed two existing slice tests). - Don't reset snapshotRequestedForReadyWindow in the catch handler; combined with the per-store-update subscriber it would retry-storm on persistent IPC failure. - scheduleStatusPersist now resets the timer on each call (true trailing-edge debounce) instead of leading-edge throttle. - Fix doc references that named clearPaneState in dismiss/IPC context where the implementation uses dropStatusEntry; add type-level JSDoc on AgentStatusIpcPayload. 109/109 in-scope tests pass. Co-authored-by: Orca <help@stably.ai> * fix(agent-dashboard): clean stale on-disk entries during hydrate - Defensive `lastStatusByPaneKey.clear()` at top of `hydrateLastStatusFromDisk` keeps repeat-start() calls from silently merging prior-session state. - When sanitize drops entries (drift, TTL, schema), log a single `[agent-hooks] last-status hydrate dropped N entries (kept M)` warn and synchronously rewrite the file. Pre-fix, stale entries stayed on disk until a fresh hook event triggered a debounced write — users who hadn't run an agent in 8+ days would re-drop the same entries every cold boot. - Prime `lastWrittenJson` from the raw on-disk bytes (instead of re-serializing) when hydration is lossless — robust against future shape drift in `serializeStatusFile`. - `LAST_STATUS_FILE_VERSION = 2` comment now records why v1 was skipped (in-flight branch shape). - IPC test mock uses `vi.importActual` for `isValidPaneKey` so it stays in sync with the real validator. Co-authored-by: Orca <help@stably.ai> * fix(agent-dashboard): persist acknowledgedAgentsByPaneKey across restart Without this, agent rows the user already visited come back bold every relaunch now that the rows themselves survive restart (per docs/agent-dashboard-retention-restart.md). Hydrate sanitizes input field-by-field (rejects null/non-object/array, prototype-pollution keys, non-finite/non-positive values) and applies a 7-day TTL paralleling HYDRATE_MAX_AGE_MS in agent-hooks/server.ts so hard-quit/crash paths can't grow the persisted map forever. Co-authored-by: Orca <help@stably.ai> * docs(agent-dashboard): drop in-tree retention/restart design doc Doc was a working artifact for this branch; the rationale lives in commit history and the comments next to the persistence/hydrate code. Scrubs the three call-site references that named it. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>