You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Dock snapshot polling scales O(N) with every process the session ever observed #15
Risk (from the arc-4 delta review; not currently user-visible)
Since the #14 fix, the dock snapshot feed uses session.processes().list_all() on the ~250ms UI snapshot cadence (200ms deadline). At Lash 9debf5aab, list_all() → ProcessWorkObserver::observe_records awaits get_process_lease once per record, serialized on the same tokio_rusqlite connection live turns write through. Observer edges are deleted only on session deletion and lash-cli never calls prune_terminal_processes, so record count N grows monotonically for the session's lifetime (every subagent spawn adds one). On a deadline breach the snapshot returns processes: None and the dock silently stops updating.
Today N is small (a handful of subagent spawns per session), so this is a scaling cliff, not a live bug — but it is monotonic and silent.
Fix directions (either suffices)
Drive terminal-row visibility off the ProcessChanged event stream instead of polling list_all() (poll list() for running rows only; terminal rows enter via events and expire via the existing 10s window), or
Bound the poll: upstream ProcessListFilter gains a terminal-recency filter / bounded query (filed as Lash feedback), or CLI-side prune via prune_terminal_processes on a slow cadence.
Lash: crates/lash-core/src/process/observation.rs:234 (per-record lease await); crates/lash-sqlite-store/src/process_registry.rs:362 (edges deleted only with the session).
Re-scoped after PR #17 (pin 46dfed8ea): upstream landed the FIG-2311 asks — ProcessListFilter.retired_since_ms + batched lease reads — and the dock snapshot now polls list_observed_by with Any status and a retention-derived horizon, so per-record serialized lease lookups and unbounded result sizes are gone. Residual: list_observed_by still fetches all observer records at the registry and filters in memory (observer edges only die with the session), so the scan itself remains O(N-ever-observed). That SQL pushdown is tracked upstream as FIG-2488; keeping this open, narrowed to adopting whatever bounded observer read lands there (or moving terminal-row discovery to the ProcessChanged stream).
Activity
SamGalanakis commentedon Sep 8, 2026
Re-scoped after PR #17 (pin 46dfed8ea): upstream landed the FIG-2311 asks —
ProcessListFilter.retired_since_ms+ batched lease reads — and the dock snapshot now pollslist_observed_bywithAnystatus and a retention-derived horizon, so per-record serialized lease lookups and unbounded result sizes are gone. Residual:list_observed_bystill fetches all observer records at the registry and filters in memory (observer edges only die with the session), so the scan itself remains O(N-ever-observed). That SQL pushdown is tracked upstream as FIG-2488; keeping this open, narrowed to adopting whatever bounded observer read lands there (or moving terminal-row discovery to the ProcessChanged stream).