Commit Graph
3 Commits
Author SHA1 Message Date
Bohdan Triapitsyn 89f7c37d60 fix: make session ordering follow activity lifecycle
Session lists now promote a conversation when it starts working and again when it settles, instead of reacting to every streaming timestamp update. This keeps ordering responsive without bringing back the sidebar churn removed by the recent performance work.

Apply the same user-visible order across Recent, project and worktree groups, session switchers, mobile navigation, widgets, the command palette, and the desktop tray. Preserve pinned priority, freeze timestamp fallback ordering, and keep child-session activity scoped to siblings under the same parent so it never moves the root conversation.

Seed reconnect snapshots without synthetic jumps, clear ephemeral ranks on deletion and runtime changes, and cover lifecycle transitions, mixed root/child trees, metadata-only updates, and project-group ordering with regression tests.
2026-07-23 15:45:53 +03:00
Bohdan Triapitsyn 85400459e9 perf: overhaul session loading, caching, and runtime isolation (#2360)
Improve OpenChamber responsiveness under large session workloads while fixing
cache, synchronization, and persistence correctness across runtimes, projects,
directories, and worktrees.

- prioritize selected and visible sessions during bootstrap and defer
  non-critical enrichment work
- reduce redundant message loading, event processing, store publication, and
  hidden sidebar work
- prevent stale session and message requests from overwriting newer
  authoritative state
- preserve existing data when authoritative fetches fail instead of treating
  failures as successful empty responses
- scope session materialization, messages, drafts, queues, todos, pins,
  permissions, folders, tabs, Git state, and pull request data by runtime and
  directory identity
- harden runtime switching, reconnect, cleanup, mutation reconciliation, and
  persisted-state ordering
- preserve live subagent Task linkage when metadata arrives after an older
  message request or while streaming parts are suspended
- coalesce overlapping tail refreshes without losing newer refresh demand
- improve cold-session loading by moving deferrable work out of the critical
  bootstrap path
- isolate URL authentication, mobile credentials, native secrets, and other
  runtime-owned state across endpoint changes
- bound long-lived caches and remove avoidable allocations from event and
  rendering hot paths
- limit virtualization to archive collections where it improves rendering
  without disrupting active sidebar layout
- stabilize session folders, pin ordering, expanded state, and persisted
  sidebar behavior
- open skill files through the same secure editor and outside-workspace grant
  flow used by file navigation, including worktree sessions
- expand regression coverage for stale completions, runtime collisions,
  reconnect behavior, persistence races, authoritative empty results, and
  subagent refresh ordering
- document the updated synchronization, cache ownership, performance, and
  runtime-isolation invariants
2026-07-21 20:52:20 +03:00
Bohdan Triapitsyn 89aa389e6c fix(tray): show live activity for every session, not just one
The tray showed the busy indicator for at most one session at a time.
Several gaps in how per-session status was sourced stacked up to that:

- Status was derived by iterating each sync child store's session list,
  so a busy session missing from the list (created moments earlier from
  another window, the tray, or the API while session.created raced or
  the list got trimmed) was invisible even though the store's
  session_status map already held its busy entry.
- The upstream /session/status endpoint is directory-scoped — querying
  it without a directory only covers the server's own cwd, so there was
  no authoritative cross-project snapshot to fall back on.
- Status events for directories without a child store were dropped by
  the sync dispatcher, so sessions in unopened projects always rendered
  idle.

Fix, layer by layer:

- Add a cross-project session-status store (sync/global-session-status)
  fed two ways: the sync dispatcher now records status-bearing events
  (session.status / session.idle / session.error) for ALL directories,
  and the tray polls /session/status per visible-session directory to
  seed initial state and reconcile missed events. Snapshots clear stale
  entries both by directory key and by session id, so canonicalized
  (realpath) directory mismatches can't strand a busy entry.
- Read live status straight from each child store's session_status map
  instead of via its session list, and never let one store's idle entry
  clobber another store's busy/retry for the same session.
- Resolve a session as active when either source (child stores or the
  cross-project map) reports busy/retry, instead of letting the synced
  store's idle shadow the fallback.

Verified end-to-end in the dev shell: two sessions running concurrently
in different projects — including a brand-new session in the open
project root, the exact case that failed — now both show busy in the
tray, and both return to idle when they finish.
2026-06-10 14:01:10 +03:00