Repository navigation
fix(native-chat): acting on one chat no longer waits on checks of every other chat - #26555
Conversation
…ry other chat Starting, resuming or switching a chat's agent first ran restart reconciliation, which probed every unreconciled session and committed them together, so one slow or failing probe for another chat delayed or failed this chat's action. Acquisition now reconciles only the addressed session; the explicit startup pass still covers all of them, and an owner that isn't proven still can't be granted a writer. Co-Authored-By: OpenAI Codex gpt-6.1-sol <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sqlite tests - Startup restore no longer lets one chat's failed lease check skip recovery for the others. - Run the two new SQLite-backed tests in the Node runtime project. - Startup reconcile runs the whole-host pass without a placeholder session id. - Test names describe an injected failing/stalling owner check, not an SSH host.
The restore opens with the whole-host pass again and stops per-chat bookkeeping after the first failure, as on main: on a failing store it makes one lease-check write, not one per chat. User actions stay targeted to their own chat.
Review summaryProblem. After Orca restarts, every saved chat's writer lease must be checked before that chat may start or resume an agent. All actions shared one host-wide check. Starting, resuming or creating one chat (even a brand-new one) therefore waited on every other saved chat's process check, and was refused if another chat's record kept changing until the check gave up. User-facing change. After a restart, acting on a chat waits only on that chat's own check, and a new chat starts right away. In the normal case nothing looks different: no new text, notices or settings. Review. The review ran in two rounds, plus a readiness pass over the final diff. Round 1 had three independent reviewers: ownership safety and concurrency, callers/performance/tests, and an architecture challenger that sketched its own design first. Their verdict was to keep the design; it matches the independent sketch. Verified safe:
Fixed in this loop:
Deferred (P3 or lower; none block):
Verified:
Not verified:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (12)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughRestart lease reconciliation now supports checks for one session or all stored sessions. Restart restoration performs a host-wide lease check before per-session reconciliation and recovery resolution. The changes also add tests for targeted reconciliation, concurrent checks, owner-probe outcomes, and acquisition isolation. Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to No actionable issue remains from this review; the change is mergeable after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… reconcile) Part 4 landed as squash 7a78dbd, so this merge is resolved against that squash as the base for its changes: Part 4's own lines come in once, and only what main changed after it meets Part 5. #26555 composed with Part 5's retry: one reconciler with an optional chat id. A chat's own action (start, attach, send, a restored read) reconciles only that chat and never joins a background run; a background run joins a person's run for its target; the every-chat background pass (startup, the retry's store-wide step) lets chat checks in flight finish first and holds no chat's lane. The restore keeps #26555's one every-chat check per pass. After the squash, main kept the acquisition-time settle and open option that Part 5 removes; those stay removed. A failed start records only this process's sends (Part 5) with main's new start-failure causes.
ELI5
When Orca restarts, it double-checks every saved chat before letting any of them start or resume an agent, to make sure the agent from before the restart is really gone. Before this PR, starting, resuming or creating any one chat waited for that check on every saved chat. If one chat's check was slow or failed, a different chat (even a brand-new one) waited too, or was refused. Now each action checks only its own chat. A brand-new chat checks nothing.
What Changed
Problem. After a restart every saved chat's writer lease loads as "unreconciled": the agent process that held it may still be running, so no new writer is allowed until this Orca has checked it (process start time and spawn token for local owners; an owner on another host stays "unverifiable", never "exited"). All actions shared one host-wide check. Attaching (create/resume) or starting an agent in chat X ran or joined a pass that probed every unreconciled saved chat and committed them together. So X waited on every other chat's probe, and was refused if another chat's record kept changing until the pass gave up (
execution_owner_reconciling).Before (user): after a restart, starting or resuming a chat could be slow or refused because of a different chat. A brand-new chat ran the whole check too.
After (user): an action waits only on its own chat's check. A new chat starts right away. Nothing visible changes in the normal case. No new text, notices or settings.
Mechanism.
Why
Catching and ignoring other chats' failures would not remove the wait, and could hand out a writer without proof. Selecting the target before probing keeps unrelated chats out of both the probe and the commit. This extends the existing reconciliation rather than adding a second lease store or changing any recovery verdict.
The common pattern scopes a user action to the conversation it addresses. Differences:
Linked Issue
Maintainer work from the chat-write admission audit; no pre-existing issue.
Visual Proof
Behaviour-only change with no UI difference, so there is no before/after pair. The live check ran on the PR build on Windows (low-spec box) with an isolated profile and a stand-in Claude agent (no real agent or credentials). It created 3 native chats, quit, relaunched, then created a 4th chat and sent in saved chats. Every reply came back in about 3 s with no notice. Zero lease-reconcile warnings in either run's main log.
Restored chat 1 after restart (history kept, no notice):

Restored chat 2 after restart:

Brand-new chat right after restart, answered:

Send in a saved chat after restart (agent resumed with the same session):

Testing
I manually tested these changes (live Windows run above)
Automated tests added/updated
New tests (real SQLite store):
The restore tests pin that restore opens with one whole-host check.
Existing startup tab-restore, restart, recovery and reader-restore suites pass. CI is green on the final head, and the scoped Node typecheck passes.
Not verified live: a real SSH or WSL host, a real Claude/Codex agent, a paired older client, and a live reproduction of the slow-other-chat case. That case needs an injected slow or failing probe, so it is covered by the tests.
Review
Review summary is in a PR comment.
Agent skill upstream boundary
Notes
Security: no new inputs, dependencies or network use. Cross-platform: no platform-specific code changed; the same owner probe runs on macOS, Linux and Windows. SSH/remote: owners on another host stay "unverifiable" as before. Mobile: no mobile-facing surface touched. Backward compatibility: no persisted or wire change. Performance: in the normal case actions do less work (one record instead of all). A few actions arriving while the startup pass is still running may probe their own chat a second time.
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)Author: @BrennanKB5