Skip to content

Native chat: recover interrupted messages before opening and retry cleanup in the background - #28122

Closed
brennanb2025 wants to merge 69 commits into
mainfrom
brennanb2025/settle-split-5
Closed

brennanb2025 wants to merge 69 commits into
mainfrom
brennanb2025/settle-split-5

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 62 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2222 $\color{#cf222e}{\Huge{\mathbf{−}}}$​451 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1771
Prod 115 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​3066 $\color{#cf222e}{\Huge{\mathbf{−}}}$​918 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2148

ELI5

After an agent stopped unexpectedly, a native chat could keep showing work in progress or leave queued messages stranded. Cleanup also waited on database locks, which could freeze Orca while it tried to save housekeeping changes.

This change gives failed background cleanup one bounded retry path. Startup opens only chats whose saved records show recovery is owed. Opening a chat first recovers the earlier process's messages, so Stop preserves unsent text as queued cards and older connected clients receive the same message state. If saving fails, the chat still opens and background recovery retries.

What Changed

  • Background cleanup and automatic queue sends fail immediately on database contention and retry after one or two seconds. After about three minutes of unsuccessful attempts, automatic sends show the existing retry action. A later wake re-derives the work.
  • Startup finds recovery candidates from existing records and generation-end signals. It no longer replays every saved chat. Other leftovers of an already-released chat settle in the background when that chat is opened.
  • Before a freshly opened journal is published, earlier handed messages become uncertain delivery and earlier unhanded personal messages become ordinary paused queue cards. This includes replay of a newly created chat's first prompt. These writes retain main's ordinary database wait, up to five seconds per transaction; failures do not refuse the open.
  • Stop withdraws only this process's eligible messages. A failed old-message conversion cannot cause Stop to erase the recovery card that is still owed. Canonical message identity, text, options and accepted ordering are retained.
  • A failed automatic send holds that card until its own committed transition or removal. Deleting, replaying or refusing an action on another card cannot clear the hold.
  • A helper that is no longer observed after a failed reconnection uses the existing uncertain state across history, queued snapshots and status, even if saving cleanup fails. Observed and actively acquiring helpers keep their working state. This changes no process-death evidence or lease.

Intentional differences: recovery is selective and lazy per chat rather than a host-wide replay; bookkeeping fails open; background writes do not wait on locks. A failed reconnection now uses the existing full history refresh used for unexpected agent exits. This can return a loaded older history window to the latest messages; older messages remain available. Foreground History preparation adds no owner probe, stop or eviction; the existing background ownership reconciliation can still run. The common pattern gives old work its canonical recovery meaning before dependent use; this change follows that ordering with Orca's existing journal operations. No temporary difference, new saved field, new wire operation or minimum connected-client version is introduced.

Why

Publishing raw earlier-process messages before recovery let existing actions and historical clients interpret them as current work. Recovering those messages through the journal removes that ordering gap without adding a second actionable queue in readers. All other cleanup stays off the foreground path, with one retry coordinator and obligations re-derived from existing state.

A chat's own start, attach or send still checks only that chat. The background every-chat ownership pass is separate, so an unrelated chat's slow check cannot hold a person's action. Losing contact with an SSH host remains uncertainty, never proof that its process exited. Folder workspaces use the same journal path without requiring Git.

Linked Issue

Part 5 of the work tracked in #26867; parts #28092, #28103, #28104 and #28111 are merged. This PR remains the final part on main.

Visual Proof

Real main-versus-branch Electron QA is pending. No completion claim is made from fixture tests or source review.

Testing

  • Initial CI compatibility repair: the streamed-text journal test passes the new options object; its named test passed and the remaining transaction callers were scanned for obsolete boolean arguments.
  • Recovery and helper fixes: source review accepted 875a814. On M4Air, the corrected five-file packet passed 67/68; its sole history fixture was repaired and the current catalog/create packet passed 17/17. This is not a full-suite or final merged-head pass. The final main merge passed the normal pre-commit hook; full lint and typecheck run in CI.
  • Main-versus-branch Electron QA with real signed-in agents, full-window screenshots, exact-head CI and final readiness remain required.

Review

Full review path: this changes recovery, saved journals, ordering and mixed-version behavior. At least 17 inherited review passes are recorded; a three-model design ruling selected recovery before publication. The source verification accepted recovery before publication; narrow final merge verification continues without restarting that round count.

Author: @BrennanKB5.

Agent skill upstream boundary

  • Not applicable; no upstream skill-installer source or assets are copied.

Checklist

  • Explained the problem, user-facing change, mechanism and alternatives.
  • Cross-platform, SSH, folder workspace and connected-client behavior considered.
  • Real Electron comparison and screenshots complete.
  • Exact-head full PR workflow green.
  • Final review status and readiness checks complete.

Each journal item row, subagent roster entry and background-task entry now
records ownerFence: the lease fence of the agent run whose output produced it.
Optional, persisted, no row version bump and no migration. The journal's
itemFence() returns it, so the turn-verdict rules and per-run provider activity
read the producing run rather than the writer's fence.
… record death first

The host decides what work is current in one place
(structured-agent-session-current-work.ts) from the lease, the exit this host
saw, the runtimes it replaced, its live child and each item's provenance.
Every host reader (queue, Stop, prompt answers, commands, status feed, idle
sweep, teardown snapshot, history pages and frames, orchestration mailbox)
reads it, so a dead agent's leftovers stop reading Working or holding the queue
even when their cleanup write failed. The journal's activeTurnId()/liveTurnScope()
become the raw runningTurn().

On exit the host records the child's end first and signals generationEnded,
which republishes frames, the status feed and settlement waits and wakes the
queue drain with no journal row. Pages and frames carry optional working and
actionablePromptIds fields.
…wers to a stopped agent plainly

Desktop and mobile prefer the host's working and actionablePromptIds fields
when present (merged across batches like latestTurn) and fall back to today's
row derivation against an older host. A prompt an ended agent raised stops
looking active; answering it is refused before any provider sees it, with
"<Agent> has stopped, so your answer was not sent. Send a message to continue."
Cancelling it only dismisses it in the journal: it no longer triggers the
chat's Stop, pauses the queue or withdraws queued cards.
… run left

An exit now settles, in one lifecycle batch planned at its own turn in the
write queue, everything its run left (turn, calls, prompts, reasoning,
unanswered sends) plus leftovers of earlier ended runs, and only the subagent
roster entries and background tasks those runs observed, by each entry's own
provenance. Main's stale settle moves to stale-state-settlement.ts with fence
scoping; dead-generation-settlement.ts becomes a planner;
leftover-settlement.ts combines them.

Resume eligibility widens in one case: this host saw the root exit at the
lease's fence and the release write failed; the acquisition replaces the
owner only once a probe proves it gone.
…ator; heal at startup; opening a chat only reads

Background bookkeeping (an exit's settlement and release, the queue's
automatic send) runs with SQLite's busy timeout at 0 through typed background
handles, so another program holding the chat database no longer freezes the
app for 5 s per write. One retry coordinator per database connection keeps
the set of chats that still owe work, wakes on any commit or a 1 s then 2 s
timer, and gives up after about 3 minutes, keeping the owed set. Every lease
write that ends a generation signals it (onGenerationEnded).

Startup re-derives what an earlier process left (settlement, unsent sends kept
as cards, the reopen mark, rewind recovery) in the background, scoped so it
never stops a surviving agent on a hidden chat. Opening a chat writes nothing
but a brand-new chat's first epoch: the open-time and start-time settles, the
roster sweep at open and the delivery loop's restart hold are removed.
…l until a caller needs it

Nothing outside the projection calls it in this part; Part 5 exports it for the start-failure row.
…wner checks into the main case

Drops the epoch-replacement case (Part 2 rewind test reads the same values through the same rebuild) and the corrupt-value case (no version writes one).
…nd the still-live rewind case

The flow cases keep every outcome: dead leftovers read as nothing, Stop has nothing to stop, a waiting card drains, a live owner publishes as before, and a rewind never promotes dead work.
…plit-3

# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-current-work.test.ts
…ack each

Keeps desktop and phone Working from the host (with the older-host fallback), the reducer merge contract, the ended question Cancel that only dismisses, the agent-named refusal and the resolution receipt. Drops per-helper prompt tests, the transcript-placement test, the stop-note client reduction, the Steer cards that match main, and per-reason refusal rows.
…ws and the per-entry scoping flow

Drops the no-added-delay timing check, the frame-once check, two stamping unit cases and the Codex combined case (the roster flow test covers its outcome).
…s as its row provenance

Moved here from Part 4 so it sits beside stampJournalEntryProvenance.
…plit-5

# Conflicts:
#	src/main/codex/codex-subagent-roster-retention.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-current-work.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-exit-delivery.test.ts
…epoch holds no rows; fewer, flow-level tests

The reconciliation load skips a chat whose saved epoch is named but empty, as the earlier founding
check did: opening it would write a fresh epoch with a person's 5 s lock wait, outside the chat's
lane. The open-path comments now name that case as the second exception to "only reads".

Tests: one startup suite on the scan fixture (heal reaches unopened chats, the empty epoch, an
unloadable journal, a busy lane, the replay/latch/read-only scopes, a hidden survivor never stopped);
one lock suite (dying agent, relaunch, long lock, rewind, drain, dead-turn frames, refused hold); one
leftover suite (retry settles in one commit while a send goes out and a stale answer is refused,
reads write nothing, a live owner is untouched). Unit suites of the retry's wake, budget and
generation-end signal, and per-branch cases already covered by a flow, are dropped.
Restores the ten-chats-one-lock budget test (a bug that happened in review, J-4). To stay under the
production lines, drops the unloadable-journal startup case (a review-round finding), the live-owner
settle case (the replaced-server recovering-owner test asserts the same nothing-settled outcome), and
a duplicated surviving-owner helper.
…plit-1

# Conflicts:
#	src/main/acp/acp-timeline-grok-subagent-retention.test.ts
#	src/main/acp/acp-timeline-grok-subagents.test.ts
…n removed its body helper

Main #27947 writes one row per subagent and deleted journal-subagent-group-body; a roster row from an older build is still what this case reads.
…amping

Main's #27947 writes one saved row per subagent, and each background task already has its own row,
so an item's own ownerFence names the run of every entry a producer still writes. Per-entry stamps
inside a row mattered only for the shared roster rows saved before #27947, and no run writes into
those any more, so the row's own provenance settles them correctly. Removes the entry stamping,
the optional ownerFence on roster entries and background tasks, and their tests.
…plit-2

Brings in main 6741f4f through part 1. Main's history page now reads with a
HistoryReader, so the published current work moves to agent-session-published-work.ts and
lays over each finished page. Main's new Stop path (chat-stop target, acceptance, unconfirmed
note, targeted cancel) and the per-subagent row writer read what runs through the host's
current-work projection, as the rest of this part does.
…eservation clears it

A chat attached directly (a send from the phone or the CLI) reserves its
lease before any reader opens it, and the reservation clears the death
evidence the release kept. The store now announces that proof with the
reservation, as it does for a reservation over a proven-dead owner, so a
settlement that failed before quit still ends the turn at the known exit
time. The open no longer captures it.
main moved journal-atomic-terminal-settlement.test.ts into a registered .spec.ts
(#29163); this branch's edit (the observed-exit test settler) is carried there.
Registrations take main's createAcpAdapter shape with this branch's producer
argument.
main moved four journal suites into registered .spec.ts files (#29163); this
branch's edits to them are carried into those files unchanged. main's thread-goal
reader put journal-store.ts one line over its limit; holdReopenFromOpen becomes a
one-line arrow.
@brennanb2025
brennanb2025 changed the base branch from brennanb2025/settle-split-4 to main October 16, 2026 22:48
… 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.
main's #28966 lets a journal transaction commit streamed rows without the per-commit fsync;
this PR's background writes ride the same transaction. The two are one options object
(`{ background?, streamed? }`), so a background streamed write is both.
@brennanb2025
brennanb2025 marked this pull request as ready for review October 16, 2026 23:17
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 64916f9a-34d9-448f-982c-ee2c045229be
📥 Commits

Reviewing files that changed from the base of the PR and between 9178512 and d0b282f.

📒 Files selected for processing: 25
  • src/main/ai-vault/ai-vault-local-scan-progress.ts
  • src/main/ai-vault/ai-vault-scan-coordinator.test.ts
  • src/main/ai-vault/ai-vault-scan-progress-flow.test.ts
  • src/main/ai-vault/session-scanner-discovery.ts
  • src/main/ai-vault/session-scanner-scope-walk.test.ts
  • src/main/ai-vault/session-scanner-zcode-sources.ts
  • src/main/ai-vault/session-scanner.ts
  • src/main/ai-vault/session-scope-cwd.ts
  • src/main/native-chat/agent-session-wire/agent-session-published-work.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-accept-then-deliver.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-child-exit.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-exit-ends-record.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-earlier-process.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-lifetime.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-mutation-context.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-provider-started-catalog.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-subscribers.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unfinished-work.ts
  • src/main/runtime/claude-structured-idle-releases-unknown.test.ts
  • src/renderer/src/components/right-sidebar/AiVaultScanProgressStrip.test.tsx
  • src/renderer/src/components/right-sidebar/AiVaultScanProgressStrip.tsx
  • src/renderer/src/components/right-sidebar/ai-vault-session-refresh.ts
🚧 Files skipped from review as they are similar to previous changes: 1
  • src/main/ai-vault/session-scanner-discovery.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

📝 Walkthrough

The changes move journal repair and stale-state settlement from conversation opening to startup and background reconciliation. Journal and record-store writes can use background options that avoid waiting on SQLite locks. New retry, lease-generation tracking, and queued-send handling coordinate recovery work. Read and status projections also use observed execution state. Tests cover startup scans, lock contention, leftover settlement, queued sends, and related session flows.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to d0b28

The changes move journal recovery out of chat opening into startup and background reconciliation. The one open concern is a test fixture that can hang if its helper worker fails early. This does not affect production behavior but should be fixed before merge. Real Electron checks and exact-head CI are still pending.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 55.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 111 functions across 106 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely summarizes the primary changes: recovering interrupted messages before chat publication and retrying cleanup in the background.
Description check Passed The description is detailed and covers the change, rationale, linked issue, testing status, review context, compatibility considerations, and checklist. It clearly discloses that Electron QA, screensh…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description is detailed and covers the change, rationale, linked issue, testing status, review context, compatibility considerations, and checklist. It clearly discloses that Electron QA, screenshots, full CI, and final readiness checks remain incomplete.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟠 Major · Pass the transaction options as an object. · journal-streamed-text-revision.test.ts:43

src/main/native-chat/agent-session-journal/journal-streamed-text-revision.test.ts:43
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Pass the transaction options as an object.

JournalHostDatabase.transaction expects JournalWriteOptions & { streamed?: boolean }. This call still passes the primitive true, so it cannot type-check.

🐛 Suggested fix
-    }, true)
+    }, { streamed: true })

Source: Pipeline failures


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7d00008a-244d-40f5-aae8-993bf6b79472
📥 Commits

Reviewing files that changed from the base of the PR and between 17a2bce and dad3af9.

📒 Files selected for processing: 124
  • config/scripts/vitest-sqlite-runtime-files.mjs
  • src/main/acp/acp-structured-host-restore-failed.test.ts
  • src/main/native-chat/agent-session-journal/journal-context-controller.ts
  • src/main/native-chat/agent-session-journal/journal-context-rewind.ts
  • src/main/native-chat/agent-session-journal/journal-database.ts
  • src/main/native-chat/agent-session-journal/journal-epoch-controller.ts
  • src/main/native-chat/agent-session-journal/journal-epoch-replacement.ts
  • src/main/native-chat/agent-session-journal/journal-host-database.ts
  • src/main/native-chat/agent-session-journal/journal-lifecycle-batch-appender.ts
  • src/main/native-chat/agent-session-journal/journal-open-failure.ts
  • src/main/native-chat/agent-session-journal/journal-pending-submission-recovery.ts
  • src/main/native-chat/agent-session-journal/journal-queued-messages.ts
  • src/main/native-chat/agent-session-journal/journal-row-writer.ts
  • src/main/native-chat/agent-session-journal/journal-store-collaborators.ts
  • src/main/native-chat/agent-session-journal/journal-store-contracts.ts
  • src/main/native-chat/agent-session-journal/journal-store-open.ts
  • src/main/native-chat/agent-session-journal/journal-store-restore.ts
  • src/main/native-chat/agent-session-journal/journal-store.ts
  • src/main/native-chat/agent-session-journal/journal-streamed-text-revision.test.ts
  • src/main/native-chat/agent-session-journal/journal-subagent-item.spec.ts
  • src/main/native-chat/agent-session-journal/journal-subagent-liveness.spec.ts
  • src/main/native-chat/agent-session-journal/journal-subagent-liveness.ts
  • src/main/native-chat/agent-session-journal/journal-submission-writer.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold.ts
  • src/main/native-chat/agent-session-journal/queued-message-bookkeeping-failure.spec.ts
  • src/main/native-chat/agent-session-journal/queued-message-holds.ts
  • src/main/native-chat/agent-session-journal/queued-message-reopen-floor.ts
  • src/main/native-chat/agent-session-journal/queued-message-store.spec.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-accept-then-deliver.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-acquire-isolation.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-context.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-orchestration.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-reconciliation.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-test-conversation.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-background-lock.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-background-writes.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-child-close.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-child-exit.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-exit-ends-record.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-client-delivery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversation-close.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversation-open.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversations.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-crash-turn-end.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-current-work.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-current-work.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-delivery-loop.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-exit-delivery.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-delivery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-lifetime.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-mutations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-runtime-state.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-tabs.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-idle-sweep.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-lease-release.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-leftover-settlement-triggers.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-leftover-settlement.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-leftover-settlement.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-mutation-context.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-observed-exit.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-provider-child-record.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-provider-child.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-abandonment.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-card-holds.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-compact.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-message-rig.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-newer-orca.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-pause-lift.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-pause.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-publication.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-stop-row.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-wiring.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-readable-restorer.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-backoff.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-load.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-pass.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-retry.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-visit.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-recovery-resolution.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-replaced-server-turn.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-resend-ledger-refusal.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-rest-test-rig.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-context-clear.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-interruption-test-harness.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-provider-output.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-reconcile.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-restore.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-restore.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-stream-duration.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-retry-budget.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-retry.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reveal.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-send-open-stale-turn.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-send-options.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stale-turn-open.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-start-failure-row.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-startup-candidates.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-startup-scan.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-startup-scan.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stop-event-binding.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stop-event-restart.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stopping.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-task-queue.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unadjudicated-owner-queue.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unrun-send-hold.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unsent-send-hold.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-wedged-profile-migration.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-write-lock.test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-rewind-recovery.ts
  • src/main/runtime/agent-session-death-evidence-persistence.test.ts
  • src/main/runtime/agent-session-generation-end.ts
  • src/main/runtime/agent-session-record-store.ts
  • src/main/runtime/agent-session-store-transactions.ts
  • src/main/runtime/orca-runtime-tests/repository-project-operations-part-02.spec.ts
  • src/main/runtime/structured-agent-session-mobile-restore.test.ts
  • src/main/runtime/structured-agent-session-startup-tab-restore.test.ts
  • src/main/runtime/structured-agent-session-tab-index-seed.ts
  • src/main/sqlite/sqlite-read-failure.ts
  • src/renderer/src/components/native-chat/NativeChatSubagentRun.tsx
  • src/shared/agent-session-lease-adjudication.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

@brennanb2025

brennanb2025 commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

After an agent stopped unexpectedly, cleanup could delay opening chats, and deferring recovery exposed older messages as current work. Stop could then discard the recovery card still owed for an unsent message. A failed automatic send could lose its hold when a different card changed, and an unobserved helper could remain Working after a failed reconnection.

The source fixes recover earlier messages before a chat is published, keep Stop scoped to this process's sends, retire only the changed card's hold, and show unobserved helper work through the existing uncertain state. Other cleanup stays in one bounded background retry path. Foreground recovery uses the ordinary journal writer and opens the chat even if recovery cannot save; background ownership reconciliation can still run afterward. A failed reconnection uses the existing full refresh, which can return loaded older history to the latest messages; older messages remain available.

At least 17 accumulated review passes remain recorded. The selected recovery-before-publication design and source were independently checked, followed by narrow integration reviews. Main’s formatting fix #30137 is now included, and the corrective merge at 69e277f was accepted in source review. Its CI run found that the existing failed-reconnection refresh call was missing its optional argument in the shared callback type. Current pushed head d0b282f fixes that type declaration only; the normal commit hook passed and its single CI watch is pending. Source acceptance does not establish runtime readiness.

M4Air fixture validation: an earlier corrected five-file packet passed 67 of 68 tests; its sole failure was an invalid off-page history fixture. After correcting that fixture, the current catalog/create packet passed all 17 tests. These runs are not a full-suite or final merged-head pass. The earlier QA driver probes used an incomplete setup and do not establish that a driver is unavailable. The recorded working isolated-driver setup will be used inside the admitted QA checkout after final-head CI passes. The failed Windows low-spec dispatch was released without a process action, and its QA ticket is closed. No real Electron run or screenshots exist yet. Main-versus-branch Electron QA with real signed-in agents, screenshots, exact-head CI and the final readiness checker remain required. The PR is not ready to merge.

For Brennan's review

Main-versus-branch screenshots are pending. The main judgment points are recovery before publication, helper state after failed reconnection, and the intended history refresh that may return a reader to the latest messages. Exact final-head links and screenshots will be added after validation.

@brennanb2025 brennanb2025 changed the title Native chat: background writes fail fast with one retry, heal at startup, opening a chat only reads (5/5, rebuild of #26867) Native chat: recover interrupted messages before opening and retry cleanup in the background Oct 18, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6184f0f9-136f-4126-95da-e352672ed352
📥 Commits

Reviewing files that changed from the base of the PR and between dad3af9 and 9178512.

📒 Files selected for processing: 77
  • src/main/ai-vault/session-scanner-discovery.ts
  • src/main/antigravity/antigravity-acp-runtime-probe.ts
  • src/main/grok/grok-transcript-import.ts
  • src/main/ipc/pty/runtime/spawn-preflight.ts
  • src/main/ipc/pty/spawn-pane-env.ts
  • src/main/native-chat/agent-session-journal/adopted-transcript-source.ts
  • src/main/native-chat/agent-session-journal/journal-legacy-import.ts
  • src/main/native-chat/agent-session-journal/journal-stop-acceptance.ts
  • src/main/native-chat/agent-session-journal/journal-store.ts
  • src/main/native-chat/agent-session-journal/journal-streamed-text-revision.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-bounded-frames.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-page.ts
  • src/main/native-chat/agent-session-wire/agent-session-published-work.ts
  • src/main/native-chat/agent-session-wire/agent-session-subscriber-catch-up.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-accept-then-deliver.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-context.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-attach-failure.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-background-lock.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-chat-stop-target.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-client-delivery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversation-open.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-current-work.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-delivery-loop.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-earlier-sends.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-history-result.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-delivery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-runtime-state.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-status-feed.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-idle-sweep.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-launch-env.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-leftover-settlement.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-mutation-context.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-open-child-work.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-open-recovery.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-provider-started-catalog.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-abandonment.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-compact.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-messages.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-pass.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-retry.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reconciliation-visit.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-context-clear.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-resumed-child-owner.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-reveal.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stale-state-settlement.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-startup-scan.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-journal-projection.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-ownership.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-ownership.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stop-acceptance.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-subscribers.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-turns.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unsent-send-hold.test.ts
  • src/main/native-chat/agent-session-wire/structured-conversation-command-admission.test.ts
  • src/main/native-chat/codex-adoption-preparation.ts
  • src/main/native-chat/session-file-resolver.ts
  • src/main/native-chat/structured-agent-cli-conversations.ts
  • src/main/native-chat/structured-agent-cli-source.ts
  • src/main/native-chat/structured-agent-session-source-admission.test.ts
  • src/main/native-chat/transcript-opencode-sqlite-query.test.ts
  • src/main/native-chat/transcript-opencode-sqlite-query.ts
  • src/main/omp/omp-session-cwd-lookup.test.ts
  • src/main/runtime/orca-runtime-structured-agent-session-create-intent.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-adoption-replay.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-create.ts
  • src/main/runtime/session-tabs/structured-session-create-support.ts
  • src/main/runtime/spawned-pty-env-fixtures.ts
  • src/main/runtime/structured-agent-session-codex-held-sends.test.ts
  • src/main/runtime/structured-agent-session-create-adoption.ts
  • src/renderer/src/store/slices/floating-editor-file-id-layout-owner.test.ts
  • src/shared/structured-agent-session-create.test.ts
  • src/shared/structured-agent-session-mutation.ts
💤 Files with no reviewable changes: 1
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-ownership.test.ts
🚧 Files skipped from review as they are similar to previous changes: 1
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversation-open.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

@brennanb2025

brennanb2025 commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor Author

Closing without merging, by Brennan's decision: the stale Working bug this targeted is already fixed on main by the earlier parts (#28103, #28104, #28111). The one remaining fix, a failed bookkeeping write before handover no longer rejecting queued messages that are safe to send, moves to #30405.

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