Repository navigation
Fix cold-start continuation recovery after session replacement - #150
Merged
Merged
Conversation
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
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.
Summary
Fix a cold-start race that reports
invalidRequest / listTimelineDateswith "Continuation does not belong to this query, session and budget".The local timeline can begin paging before authentication restoration finishes. When account reconciliation replaces the Worker session, Expected-owner reads follow the replacement binding, but an embedded continuation still belongs to the previous execution. Retrying it with the new session and budget incorrectly turns a recoverable stale traversal into invalid input, even when the graph generation is unchanged.
Before dispatching an Expected read, validate the embedded continuation's original session. If that session has been revoked, return
Stale_readso the existing business reducer restarts from its retained boundary without the expired cursor. Keep strict query, item-budget and byte-budget validation for continuations from the current session. Direct/Sealed ownership and cancellation checks remain unchanged.Only the coordinator implementation and its existing pure regression test are changed. No public contract, Dune, Swift UI, dependency or personal graph changes.
Regression coverage
The new public coordinator regression failed against the original implementation, then passed with the fix. It covers all eight typed continuation families, admitted and Full-queued handover, a continuation submitted after session replacement, a fresh read after rejection, and same-session item/byte mismatches remaining invalid input. Existing generation, direct/Sealed and cancellation tests still pass.
The investigation also checked the exact rejection predicates: continuation ownership, query key, item limit and byte limit. This does not claim exhaustive coverage of every malformed field or identity combination.
Cold-start Simulator reproduction
Used an isolated iPhone 13 / iOS 26.1 Simulator with production native runtime, view tree and reducers, a synthetic 31-day graph with one root per day, memory-only fixture keys and an offline authentication provider. The provider varies
currentUserIDcompletion timing and deliberately fails token retrieval; no real account, credentials or graph were used.f63732d7f7df94c6294fb61c99a2866b734eeff1: cold launches with 0/20 ms authentication delay stopped at 21/28 of the initial 30 roots. At 0 ms, the actual Error info screen showed the exact continuation error,listTimelineDates, graph generation 1 andworkerService / coordination / invalidInput.3ef0938c11e348711c19f98541ef9dfedb0cb03d: all six delays, 0/20/50/100/250/1000 ms, completed the initial 30 roots. The 0/20/50 ms logs show cursorless recovery. The final 0 ms Error info inspection showed only the intentionally simulated token failure, with no continuation orlistTimelineDateserror.The disposable fixture was checkpointed into DELETE journal mode before each launch for portable initial mirror inspection. Test hosts and synthetic setup are outside the PR. These are source-bound experimental host-restamped Simulator builds with
cross_abi_validated=false, not real-device or complete iOS ABI acceptance.Validation on the exact head
dune build @all app/native_embed.exe.o: passed.dune runtest --force: passed.git diff --check: passed.spec-dev-tool check --all: fails on pre-existing document format/section errors; baseline and fix produce byte-identical output. No decision documents changed.Base:
mainatf63732d7f7df94c6294fb61c99a2866b734eeff1. Head:3ef0938c11e348711c19f98541ef9dfedb0cb03d. No merge or release is included.