Skip to content

fix(server): hydrate provider history atomically - #2763

Closed
timigod wants to merge 10 commits into
getpaseo:mainfrom
timigod:repair/hydration-atomic-current-main
Closed

fix(server): hydrate provider history atomically#2763
timigod wants to merge 10 commits into
getpaseo:mainfrom
timigod:repair/hydration-atomic-current-main

Conversation

@timigod

@timigod timigod commented Aug 1, 2026

Copy link
Copy Markdown

Successor to #2723. This keeps the replacement narrowly focused on provider-history hydration atomicity; it does not close or modify the earlier pull request.

What changes

  • installs the per-agent hydration gate synchronously when hydration is admitted, before the session queue drain can yield
  • stages provider history and commits it through one awaited atomic durable replacement
  • releases queued live session events and direct timeline writers only after history is installed
  • serializes concurrent hydration generations without opening a between-generation writer gap
  • preserves the prior timeline on provider-stream or durable-replacement failure and leaves hydration retryable

Non-goals

Verification

  • focused manager, stream-coalescing, session, agent-storage, and timeline-store tests: 348 passed
  • timeline-window daemon E2E: 11 passed
  • persistence/restart daemon E2E: 2 passed
  • server and CLI build: passed
  • all-workspace typecheck: passed
  • repository lint and formatting checks: passed
  • diff checks: passed

Upstream baseline observations

Two additional daemon E2Es were attempted and fail identically on the detached upstream base (9ddc3e0c4253b4cf3a1a7b864b7a92294cf2e8d4):

  • agent-refresh-rehydrates-timeline.e2e.test.ts sees an empty initial Claude import before reaching refresh
  • timeline-reconnect-contract.e2e.test.ts times out waiting for an existing provisional live event

Those unrelated baseline behaviors are intentionally not changed here.

@timigod
timigod marked this pull request as ready for review August 1, 2026 20:43
@timigod

timigod commented Aug 1, 2026

Copy link
Copy Markdown
Author

Independent final rereview: #2763 is READY at 68837a9 (tree ee048eb043a9fff35f1b9a07d7606322046cfc6b; base 048b82f). 262 changed-server tests passed, 4 skipped; typecheck and diff clean; no P0-P2 findings. Integration note: #2765 is an independent material-progress branch, not a semantic superset. When rebasing either order, preserve this PR reserved-occurrence reconciliation and admission-terminal child retention while layering #2765 checkpointing; union tests are required.

@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes provider-history hydration transactional and ordered with live timeline activity.

  • Adds a synchronous, per-agent hydration gate and serialized hydration generations.
  • Stages provider history before atomically replacing durable and in-memory timeline state.
  • Buffers timeline writers, session events, and provider-subagent updates until hydration completes.
  • Adds file-backed atomic replacement support and focused concurrency, rollback, and restart tests.

Confidence Score: 4/5

The stale-session replay path should be fixed before merging because a concurrent reload can apply buffered events from the old provider session to its replacement.

Hydration buffers events by agent ID, while replay resolves that ID after reload has installed a new session, allowing old-session output to mutate the replacement session.

Files Needing Attention: packages/server/src/server/agent/agent-manager.ts

Important Files Changed

Filename Overview
packages/server/src/server/agent/agent-manager.ts Adds hydration admission, generation serialization, reconciliation, and buffered replay, but stale session events can cross a concurrent reload boundary.
packages/server/src/server/agent/file-agent-timeline-store.ts Adds per-agent serialized atomic timeline replacement with cache updates only after durable success.
packages/server/src/server/agent/agent-timeline-store-types.ts Extends the durable timeline interface with atomic replacement and committed-row access.
packages/server/src/server/bootstrap.ts Wires the file-backed durable timeline store into daemon startup.
packages/server/src/server/session.ts Adjusts refresh handling to await the new reload and hydration behavior.

Sequence Diagram

sequenceDiagram
  participant H as Hydration caller
  participant M as AgentManager
  participant P as Provider session
  participant D as Durable timeline store
  participant L as Live writers/events
  H->>M: hydrateTimelineFromProvider()
  M->>M: Install per-agent gate
  L-->>M: Buffer live operations
  M->>P: streamHistory()
  P-->>M: Staged history events
  M->>D: replaceCommitted(rows)
  D-->>M: New epoch
  M->>M: Replace in-memory timeline
  M->>M: Replay buffered operations
  M-->>H: Hydration complete
Loading

Reviews (1): Last reviewed commit: "fix(server): close hydration reconciliat..." | Re-trigger Greptile

Comment on lines +3169 to +3172
activeHydration.bufferedOperations.push({
kind: "session_event",
run: async () => this.processSessionEvent(agentId, event, activeHydration.token),
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Stale events cross session reloads

When a session reload occurs while hydration has buffered an event from the old session, replay looks up the replacement by the same agent ID and dispatches the stale event through it, corrupting the replacement session's timeline, provider-subagent projection, or turn state.

Knowledge Base Used: Agent Orchestration

@timigod

timigod commented Aug 1, 2026

Copy link
Copy Markdown
Author

Superseded by independently accepted union PR #2779 at exact head 2d1c4bdec65baa5b8844e3d448f4fa991b8bb226. #2779 preserves this PR's full invariant set while resolving its semantic overlap with the sibling PR. This branch/history is retained; no branch deletion.

@timigod timigod closed this Aug 1, 2026
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