Skip to content

fix(session-continuation): recover image history and settled turns - #2168

Merged
beruro merged 1 commit into
developfrom
junyu/fix-windows-conversation-recovery
Oct 8, 2026
Merged

beruro merged 1 commit into
developfrom
junyu/fix-windows-conversation-recovery

Conversation

@beruro

@beruro beruro commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Local Agent conversation continuation can fail in two related ways reported on Windows: historical images reach exact native transfer as filesystem references, and a completed Force Send turn repeatedly fails to recover its native user anchor, blocking later queued requests even after restart.

Agent image paths in agent_messages are valid persisted data. The authoritative frontend reader incorrectly used the display projection, bypassing existing strict image embedding and dropping the producing user event's durable turn identity. Restart recovery also removed only the accepted user from its pre-turn prefix, leaving that turn's generated output behind. An irreparable completed anchor mismatch was then treated as indefinitely retryable.

Solution

  • Add an opt-in native-transfer projection to agent_load_messages. Reuse the effective compacted native frame and strict image resolver, embedding retained images and restoring turnIntentId from session-scoped producing events by durable message ID. Display reads keep their existing behavior.
  • Construct the recovery prefix before the accepted user and its output. Preserve the completed anchor mismatch as a blocked recovery after bounded authoritative rereads, release the restart-adopted lifecycle generation, and let the durable queue advance without resending the accepted turn.
  • Add regressions at the Rust persistence/IPC boundary, authoritative adapter, continuation lifecycle, and queue owner. Cover repeated prompts, cross-session identity isolation, unavailable files, compacted-away images, restart recovery, and dispatching the next request exactly once.

Both fixes restore the same local conversation continuation contract. Historical recovery is read-only; no database cleanup, schema migration, or dependency changes are required.

Potential risks

  • Windows hardware and the original affected databases were unavailable. Regression fixtures exercise the reported boundaries, but the original Windows sessions and live provider workflows still need verification.
  • The IPC argument is optional and defaults to the existing display projection. Frontend and backend should ship together so authoritative reads receive embedded images and durable identity metadata. Reverting this patch restores previous behavior without data recovery because persisted rows are unchanged.
  • Retained images whose files are actually missing continue to fail exact transfer visibly. A completed turn that still has no recoverable anchor now fails visibly and releases its queue owner after bounded rereads; transient recovery retains existing pending semantics.
  • Image embedding remains on the blocking worker and uses the existing resolver. The identity lookup is session-scoped and invocation-local, with no new persistent cache or timer. Windows CPU/RSS and repeated-open lifecycle measurements were not run, so the performance verification verdict remains blocked; no measured performance improvement is claimed.

Verification

  • GitHub CI: frontend typecheck/lint/tests, secret scan, CodeQL, dependency boundaries, circular dependencies, queue authority, typed lint, and PR policy passed. Both macOS and Windows workspace Clippy jobs failed on the existing AtomicUsize::fetch_update call at src-tauri/crates/search/src/code/commands/text_search.rs:27, which the CI toolchain now deprecates. Verified the identical call exists in base develop commit 5ec548d09; this PR does not modify that file. This prevents a green workspace Clippy result and does not establish that all remaining Rust targets pass.

Passed on the final committed source:

  • pnpm exec vitest run --config config/vitest.config.ts src/engines/SessionCore/hooks/session/__tests__/useQueueDispatch.intervention.test.ts src/engines/SessionCore/conversations/localConversationContinuation.test.ts src/engines/SessionCore/conversations/localConversationSettledTail.test.ts src/engines/SessionCore/sync/adapters/__tests__/createRustAgentAdapter.authoritative.test.ts src/api/tauri/rpc/schemas/__tests__/agentSessionMessages.test.ts — 5 files, 153 tests passed.
  • cargo test --manifest-path src-tauri/Cargo.toml -p agent_core native_transfer --lib -- --test-threads=1 — 4 tests passed using the shared local Cargo target directory.
  • The freshly compiled agent_core test binary with foundation::persistence::db_helpers::messages:: --test-threads=1 — 32 existing persistence/history tests passed.
  • pnpm typecheck:fast, changed-file ESLint with --max-warnings 0, pnpm check:test-placement, and pnpm check:queue-authority — passed.
  • git diff --name-only -z | node scripts/ci/check-changed-file-length.cjs — passed for changed production TypeScript files.
  • rustfmt --edition 2021 --check --config skip_children=true on changed Rust files — passed. The normal commit hook also passed lint-staged formatting/lint checks, TypeScript validation, and cargo clippy --lib --message-format=short -p agent_core.
  • git diff --check origin/develop...HEAD — passed. Fetched develop again before publication; the branch is based on its latest commit 5ec548d09. Reviewed all 17 changed files for scope and accidental sensitive/generated content.

No UI layout or controls change, so screenshots would not substantiate this fix; behavior is verified at persistence, recovery, and queue boundaries. Windows live reproduction, provider end-to-end execution, and CPU/RSS measurements were not run. No full-suite claim is made.

@beruro
beruro merged commit 454f558 into develop Oct 8, 2026
15 of 17 checks passed
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