Restore live sessions immediately after app resume - #4160
Merged
Conversation
11 tasks
Foregrounding now reconnects every host without waiting for scheduled backoff, while cached turns, timelines, agents, and workspaces remain internally consistent until authoritative catch-up arrives. Replica persistence is keyed and incremental so ordinary updates avoid whole-directory serialization.
Stream turn closure now wakes queued-message delivery, while same-turn snapshots retain local cancellation state. Offline liveness remains visible until an authoritative close arrives.
Directory baseline replacement must preserve independently accepted timeline changes until the deferred flush. Keep the reconnect and persistence fixes while removing the session-data facade and broad read-hook migration.
boudra
force-pushed
the
investigate-relay-timeline-reconnect-lag
branch
from
September 5, 2026 12:09
6760ab2 to
54d94c3
Compare
Contributor
|
| Filename | Overview |
|---|---|
| packages/app/src/runtime/host-runtime.ts | Coordinates foreground reconnection, replica ownership, persistence, and serialized queue draining. |
| packages/app/src/runtime/directory-sync/agent-replica.ts | Moves agent mutations and turn-liveness reconciliation behind the directory replica while preserving newer live state. |
| packages/app/src/runtime/replica-cache/index.ts | Persists keyed row mutations with deferred serialization and preserves pending timeline writes during baseline replacement. |
| packages/app/src/navigation/host-runtime-bootstrap.ts | Applies the current native app state before bootstrap and forwards subsequent lifecycle transitions. |
| packages/client/src/daemon-client.ts | Updates reconnect and catch-up behavior supporting immediate restoration after resume. |
| docs/data-model.md | Describes the durable replica row model while removing the previously flagged implementation-level flush description. |
| docs/timeline-sync.md | Documents queue dispatch and turn-liveness lifecycle contracts. |
Sequence Diagram
sequenceDiagram
participant App as App lifecycle
participant Runtime as Host runtime
participant Cache as Replica cache
participant Directory as Directory replica
participant Daemon as Daemon
App->>Runtime: foreground / setAppVisible(true)
Runtime->>Daemon: reconnect registered hosts immediately
Runtime->>Cache: hydrate cached host rows
Cache-->>Directory: agents, workspaces, projects, timelines
Daemon-->>Directory: authoritative snapshot and deltas
Directory->>Directory: preserve newer live turn state
Directory->>Cache: persist touched rows and checkpoint
Directory-->>Runtime: notify when authoritative turn becomes idle
Runtime->>Runtime: drain queued message
Reviews (4): Last reviewed commit: "docs: remove cache implementation recap" | Re-trigger Greptile
Initialize visibility before host bootstrap so a background mount cannot leave reconnect enabled. Seed sidebar fixtures through the workspace owner so cache hydration preserves their rows.
Keep submission acknowledgement separate from turn liveness: disconnect preserves the running turn until authoritative catch-up. Wait for confirmed running chrome before exercising queued cancellation so the alternate-send shortcut cannot race turn startup.
This was referenced Sep 7, 2026
Legoless
added a commit
to Legoless/paseo
that referenced
this pull request
Sep 9, 2026
Port of getpaseo#4160 and getpaseo#4444. Flush the replica cache when hidden, reconnect every host immediately on resume, and keep daemon reconnect backoff running while backgrounded. Disconnect no longer clears turn liveness so queued messages still drain after a backgrounded turn finishes.
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.
Linked issue
Refs #2991. This covers queues stranded after an unobserved turn completion; the original report has not been reproduced directly.
Type of change
Reasoning
Returning to the app could show cached chat while host directories and running indicators waited for reconnect backoff and catch-up. This reconnects every registered host immediately on foreground, restores cached directory/chat/turn state, and preserves live output received before catch-up completes.
Directory updates now persist only touched rows, with serialization deferred until flush. Replacing a directory baseline preserves pending timeline writes, fixing a race that discarded newly accepted chat-cache changes.
The scope is limited to these behavior and persistence improvements. The session-data facade and broad read-hook migration have been removed; a full data-layer ownership redesign is deferred. Against the rebased main: 65 files, +2208/-1158; production code is 32 files and net +285 lines, down from 133 files and net +992.
Goals
Non-goals
Supersedes
QA
The pending timeline-write regression failed before the fix and passes afterward. A failing-first lifecycle regression also verifies mounting while inactive/backgrounded applies the current state before bootstrap. Added coverage also verifies that clearing a timeline survives directory baseline replacement.
The sidebar and shortcut fixture failures found by CI are fixed by seeding through the existing workspace owner; all seven tests pass on two consecutive focused runs. All 29 startup/lifecycle tests pass.
Focused app coverage passed for cache, directory synchronization, host lifecycle, turn state, activity presentation, subagents, archive, and workspace behavior. Selected command output:
The provider-acknowledgement reconnect and queued-cancellation journeys also pass three consecutive runs each (
--repeat-each=3: 6 passed in 1.7m). They verify that submission settlement survives disconnect, the last known running turn remains visible offline and becomes idle after authoritative catch-up, and the next queued turn remains interruptible.The browser tests use an isolated daemon: a long disconnected run resumes into one latest-tail update with older history still reachable; an unchanged resume preserves a scrolled-up timeline.
Root
npm run typecheck,npm run lint,npm run format, andgit diff --checkpass. Lint reports zero warnings and errors.Browser resume behavior is verified. Android loaded the current bundle, but resume/catch-up/queue/cache-recovery journeys remain unverified because another session reserved the emulator during setup. iOS and packaged Electron were not retested. Native foreground behavior and older cache hydration remain the main manual QA gaps.
Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatpasses