fix(app-server): reconcile loaded thread history on resume#30866
Draft
steipete-oai wants to merge 3 commits into
Draft
fix(app-server): reconcile loaded thread history on resume#30866steipete-oai wants to merge 3 commits into
steipete-oai wants to merge 3 commits into
Conversation
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
thread/resumeis called.Motivation
Fixes #21743. Related focus-refresh report: #21177.
When two app-server clients share a thread, one can append work after another client has loaded it. The loaded app-server previously answered
thread/resumefrom stale in-memory history, so Desktop could not discover the external turns until its app-server restarted. This also preserves the ordering requirement identified in #11756 (comment): history hydration and listener attachment remain serialized.Approach
The app-server remains the source of truth rather than introducing a local file or SQLite watcher, which would not generalize to remote app-servers.
For a loaded idle thread, resume now:
The storage and fresh metadata reads run off the listener behind an explicit event-delivery cut. The Finish phase projects the final overlay for the response, drains pre-cut events to prior subscribers only, then resumes normal track-one/dispatch-one delivery. High-volume legacy exec deltas continue draining to existing subscribers while storage is read, and Finish consumes only a finite queue snapshot. This prevents joiner duplicates, listener stalls, and unbounded output buffering.
Busy, incomplete, and conflicting histories fail closed or retry without overwriting live state. The cursor ignores metadata-only appends. After an ambiguous append failure, recovery accepts only identical history or a safe strict extension of the complete in-memory snapshot; older and divergent reads conflict without mutation.
Rejected resumes leave client compatibility settings untouched. Append-only reconciliation also preserves the current server-measured auto-compaction prefill; canonical rewrites and window changes reset it. Imported trailing compaction queues its next-turn lifecycle source exactly once, including cursor-mismatch reconstruction. Point operations such as rollback lease the listener without implicitly subscribing, and lease acquisition is serialized with idle unload.
The one-shot token-budget reminder now carries a distinct contextual marker. Cold resume and live reconciliation derive its delivered latch from the surviving current-window history, so an external reminder is not emitted twice and rollback or compaction rearms it correctly. Older unmarked reminder text remains intentionally indistinguishable from arbitrary configured developer text.
The diff is test-heavy: most added lines cover core reconstruction invariants and cross-process app-server ordering.
The commits retain a review seam between core/storage reconciliation and app-server delivery ordering; the draft keeps them together because the externally observable no-loss/no-duplicate guarantee spans both layers.
Verification
origin/mainunder this managed host's forced policy and skill rootsjust fix -p codex-core,just fix -p codex-app-server, andjust fmtFollow-up
Experimental raw-event opt-in remains thread-scoped. Per-connection raw-event capabilities are a separate architectural change; this PR applies response coverage and redaction only to buffered handoff events.