Skip to content

fix(native-chat): remove superseded chat history rows and return their space - #36053

Merged
AmoabaKelvin merged 133 commits into
mainfrom
brennanb2025/bug-native-chat-journal-grows-to-20-gib-request
Nov 1, 2026
Merged

AmoabaKelvin merged 133 commits into
mainfrom
brennanb2025/bug-native-chat-journal-grows-to-20-gib-request

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1202 $\color{#cf222e}{\Huge{\mathbf{−}}}$​2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1200
Prod 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​207 $\color{#cf222e}{\Huge{\mathbf{−}}}$​7 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​200

ELI5

Every time an agent revised a message or a plan, Native Chat saved another full copy of it and never threw the old copies away. One user's chat database reached about 20 GiB. Orca now deletes the copies nothing reads any more, a little at a time in the background, and gives the space back to the disk.

What Changed

Before: since #36024, each chat change is saved as keyed records. A key's newest record is what a chat opens from, and every older revision stays on disk forever. A busy chat streams dozens of revisions per message, so the file keeps growing.

After: the existing background sweeper (a minute after launch, then every six hours, at a 10% duty cycle) runs three bounded steps:

  • deletes retired chat histories, as it already did;
  • deletes superseded records (journal-outcome-compaction.ts). For each key it keeps the first record, the newest record, and every removal record (tombstones, removed turns, deleted values), and deletes the revisions in between. Each page is one transaction over at most 32 records and reads no saved content;
  • runs incremental_vacuum(32) pages (journal-incremental-vacuum.ts), so the file shrinks on databases created with incremental auto-vacuum, which every journal database has been since feat(native-chat): one structured-chat journal database per host, owned by one process #23613. A database without it keeps its size and reuses the freed pages for later saves.

Cleanup reads each record's own format declaration and understands both formats Orca writes today, including the native input and queue records added since #36024. An unknown format or field stops cleanup for that chat at that record, so nothing at or after it is deleted. Later healthy chats are still cleaned.

Design decisions kept from the original PR:

Changed in the takeover:

  • Merged origin/main and moved imports to main's new module locations.
  • Removed this branch's reader change that refused a whole chat when a prefix-position record names a key the prefix lacks. Main appends that key instead, a deliberate choice made in 1bf4ca375fb. Cleanup never touches the prefix or a key's newest record, so it doesn't need the stricter reader, and reverting keeps the reader identical to main's.
  • Tightened two tests (see Testing).

Phone and paired-client messages are unchanged.

Why

The saved format already stores whole values per key, so the middle revisions are redundant for every reader. Deleting them in small paced pages fixes the growth without blocking a send or a chat open and without migrating anything. Keeping the first record per key preserves what a #36024-only reader needs. Stopping at the first unknown record keeps a newer build's data safe from an older build's cleanup.

Linked Issue

Part of #34916. This stops the growth for everything saved since #36024. History saved before #36024 stays as it is (the 10-30 decision), so a file that is already large, like the reporter's, shrinks only by what was saved after upgrading.

Visual Proof

N/A: nothing visible changes. Chats open, page history and render exactly as before; only the database file gets smaller.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

Reporter-scale run (macOS, this head, shared machine at load 5–18). I generated 310 chats with 2,565,165 changes (#34916 has 310 sessions and 2,578,668 rows) through the real writer: streamed assistant messages and tool calls, cloned by SQL into a skewed mix of small and very large chats.

Before After first pass
Database file 15.5 GB 1.34 GB
Saved records 5,252,740 361,340
Chats whose restored state matches the pre-cleanup hash 310 / 310
  • Cleanup work: 11.8 min of compaction (164,686 pages) plus 18 min of vacuum (108,161 pages) when run back to back. At the 10% duty cycle the first pass takes about 5 hours of wall time. Later passes over unchanged chats took 1.5 ms in total.
  • Peak size between passes: the file never grew past its starting size. The WAL stayed at about 4–6 MB because the checkpoint worker keeps up between pages.
  • Page cost: compaction p50 1.6 ms, p99 46 ms; vacuum p50 3.4 ms, p99 118 ms. The rare slow pages, up to 3.7 s and 4.5 s at load 18, are IO waits rather than cleanup work. Instrumented again at lower load, pages over 100 ms used 0–3 ms of CPU against 100–375 ms of wall time. Turning off the commit fsync for cleanup pages made no consistent difference in an A/B (fix, baseline, fix), so the PR keeps the host's normal durability.
  • Save latency during cleanup: a 4 KB streamed message save every 50 ms through the real journal, timed from when each save was due, so time spent waiting behind a cleanup page counts. With no cleanup running: p50 1.85 ms, p99 8.2 ms, max 36 ms. During a paced pass (9.3% duty, 20,541 pages): p50 1.76 ms, p99 6.4 ms, max 88 ms.

#36024's own reader and writer on cleaned data. I ran these on a checkout of the #36024 merge commit (2cc33b8d898):

Focused tests. Compaction, compaction scaling, storage admission, projection bootstrap and streams, outcome scaling and wire, sweeper, mixed-epoch replacement, checkpoint integration and attachment wiring all pass, plus changed-file oxlint and oxfmt. Test audit changes:

  • The failed-deletion test now drives the same compaction to completion. It fails when a failed page is skipped instead of retried, which I checked with a mutation.
  • The non-incremental vacuum check now uses a real file with free pages, replacing an assertion on pragma calls against an empty in-memory database.
  • Removed two assertions that couldn't fail.

Risk

The riskiest part is deleting saved data. A wrong keep rule would lose part of a chat's history.

  • Guards against that: cleanup keeps every key's first and newest record and every removal record, and stops at any format or field this build doesn't know. Tests pin those rules for both formats, for writes landing between pages, and for rewinds and epoch replacements mid-pass. The reporter-scale run checked all 310 chats against their pre-cleanup state.
  • Older builds: a fix(native-chat): save each chat change as keyed records and reopen from the newest #36024 build reads cleaned format-1 chats identically, as tested above.
  • Performance: the first pass at reporter scale runs for hours at 10% duty. Saves during it measured the same as without it, but on a machine with slow or contended disks a single cleanup commit can wait on IO the way any save can.
  • Back out: a plain revert stops cleanup. Records already deleted were redundant, so nothing a revert would need is lost.

Level: Medium

AI Disclosure

Review

Two review rounds (Codex plus a Claude reviewer), each with no P0 or P1.

  • Accepted: the reader-refusal change was an unneeded reversal of main's behaviour, so I reverted it.
  • Not fixed (P3): one chat that keeps throwing a storage error holds back cleanup of later chats until the error clears. It is retried every pass and logged.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Ensure no issues in: Security, Cross-platform support (Linux, Windows, Mac), Remote SSH, Mobile, general backwards compatibility, performance

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • I stated the risk: what could break, for whom, and how to back it out
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

brennanb2025 and others added 10 commits October 29, 2026 10:30
Publish versioned reducer checkpoints atomically, checkpoint through the chat write queue, and backfill closed chats without retiring journal rows.

Co-Authored-By: Codex <noreply@openai.com>
Delete fully superseded item and lifecycle rows inside the paced checkpoint job, retain first/latest cursor touches and current witnesses, and reclaim incremental-vacuum pages. Allow catch-up to cross retired prefix rows.

Co-Authored-By: Codex <noreply@openai.com>
@brennanb2025
brennanb2025 marked this pull request as ready for review October 29, 2026 19:15
@greptile-apps

greptile-apps Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable new issues were found.

Summary

This PR removes old chat revisions covered by saved state and returns freed space on databases that support it.

  • The background job removes superseded chat rows after saved state covers them.
  • Chat catch-up continues even when cleanup leaves gaps in row numbers.

No actionable new issues were found. No previous review threads were supplied. Tests were inspected but not run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Background maintenance] --> B[Save current chat state]
  B --> C[Check retained rows]
  C --> D{Complete prefix?}
  D -- Yes --> E[Compare replay with saved state]
  D -- No --> F[Use saved state]
  E --> G[Delete middle touches in small groups]
  F --> G
  G --> H[Return freed pages]
  B --> I[Reopen from saved state and newer rows]
  G --> J[Clients catch up through retained touches]
Loading

Reviews (2) · Last reviewed commit: "Validate checkpoint authority before ret..." · Reviewed by Greptile

…er it is frozen

The fold comment claimed an unheld prefix-ordinal value only moves that key;
a prefix read differently can also show a key twice or bring back one the
tail deleted. The marker version now states the rule: a build that reads old
rows into different keys or values keys that reading off a new marker
version, and duplication or resurrection is never intended.
…elds this build adds

The open check compared whole snapshots, so a field main starts setting would
fail the required cross-version job until a release ships it. It now compares
the release's items, sends and cards, in order and by value, allowing added
fields; the byte-identity and restore-equals-live checks are unchanged.
…thout parsing or walking it again or keeping its text
…batch's encode stays linear in its mutations
@brennanb2025
brennanb2025 changed the base branch from main to brennanb2025/journal-saved-state October 31, 2026 06:49
@brennanb2025
brennanb2025 changed the base branch from brennanb2025/journal-saved-state to main October 31, 2026 07:43

@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
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a6a2f4d5-bed5-4e89-af96-c7fdb4748fca
Commits

Reviewing files that changed from the base of the PR and between ef5a30d and 3c72e29.

Files selected for processing: 197
  • config/flaky-test-pattern-baseline.txt
  • src/main/acp/acp-structured-host-restore-failed.test.ts
  • src/main/acp/acp-structured-launch-resolution.test.ts
  • src/main/acp/acp-structured-unknown-window-usage.test.ts
  • src/main/codex/codex-structured-journal-settlement-rollback.test.ts
  • src/main/codex/codex-structured-journal-translation-turn-lifecycle.test.ts
  • src/main/codex/codex-structured-thread-catch-up-echo.spec.ts
  • src/main/codex/codex-structured-thread-catch-up.test.ts
  • src/main/codex/codex-thread-catch-up-contract-test-fixture.ts
  • src/main/codex/codex-thread-catch-up-rewind.test.ts
  • src/main/codex/codex-turn-lifecycle-completion.test.ts
  • src/main/codex/codex-turn-lifecycle-contract-test-fixture.ts
  • src/main/codex/codex-turn-lifecycle-history.test.ts
  • src/main/jsonl-rpc/timeline-lane.test.ts
  • src/main/native-chat/agent-session-journal/__fixtures__/journal-input-prefix.json
  • src/main/native-chat/agent-session-journal/__fixtures__/journal-outcome-format-1-values.json
  • src/main/native-chat/agent-session-journal/__fixtures__/journal-outcome-format-1.json
  • src/main/native-chat/agent-session-journal/journal-approval-revision-validation.spec.ts
  • src/main/native-chat/agent-session-journal/journal-atomic-settlement-contract-test-fixture.ts
  • src/main/native-chat/agent-session-journal/journal-atomic-settlement-oversized.spec.ts
  • src/main/native-chat/agent-session-journal/journal-atomic-settlement-rollback.spec.ts
  • src/main/native-chat/agent-session-journal/journal-atomic-terminal-settlement.spec.ts
  • src/main/native-chat/agent-session-journal/journal-compaction-scaling.test.ts
  • src/main/native-chat/agent-session-journal/journal-cursor.ts
  • src/main/native-chat/agent-session-journal/journal-damage.test.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-contract-test-fixture.ts
  • src/main/native-chat/agent-session-journal/journal-epoch-replacement-receipts.spec.ts
  • src/main/native-chat/agent-session-journal/journal-epoch-replacement.spec.ts
  • src/main/native-chat/agent-session-journal/journal-epoch-replacement.ts
  • src/main/native-chat/agent-session-journal/journal-epoch-rollover.ts
  • src/main/native-chat/agent-session-journal/journal-host-database-test-support.ts
  • src/main/native-chat/agent-session-journal/journal-host-database.spec.ts
  • src/main/native-chat/agent-session-journal/journal-host-database.ts
  • src/main/native-chat/agent-session-journal/journal-incremental-vacuum.ts
  • src/main/native-chat/agent-session-journal/journal-item-provenance.spec.ts
  • src/main/native-chat/agent-session-journal/journal-lifecycle-batch-appender.spec.ts
  • src/main/native-chat/agent-session-journal/journal-lifecycle-boundaries.spec.ts
  • src/main/native-chat/agent-session-journal/journal-mixed-epoch-replacement.test.ts
  • src/main/native-chat/agent-session-journal/journal-open.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-cleanup.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-codec.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-compaction.test.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-compaction.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-format-1-decode.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-format-1.test.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-format-1.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-format.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-scaling.test.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-sweeper.test.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-table.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-wire.test.ts
  • src/main/native-chat/agent-session-journal/journal-outcome-write.ts
  • src/main/native-chat/agent-session-journal/journal-projection-bootstrap.test.ts
  • src/main/native-chat/agent-session-journal/journal-projection-failure.test.ts
  • src/main/native-chat/agent-session-journal/journal-projection-streams.test.ts
  • src/main/native-chat/agent-session-journal/journal-projection-test-support.ts
  • src/main/native-chat/agent-session-journal/journal-read-row.ts
  • src/main/native-chat/agent-session-journal/journal-received-content.test.ts
  • src/main/native-chat/agent-session-journal/journal-reducer-transition.ts
  • src/main/native-chat/agent-session-journal/journal-row-context-usage.spec.ts
  • src/main/native-chat/agent-session-journal/journal-row-schema-version.spec.ts
  • src/main/native-chat/agent-session-journal/journal-row-schema.test.ts
  • src/main/native-chat/agent-session-journal/journal-row-schema.ts
  • src/main/native-chat/agent-session-journal/journal-row-table.ts
  • src/main/native-chat/agent-session-journal/journal-row-writer.ts
  • src/main/native-chat/agent-session-journal/journal-saved-state.test.ts
  • src/main/native-chat/agent-session-journal/journal-sequence-replay.spec.ts
  • src/main/native-chat/agent-session-journal/journal-state-codec.ts
  • src/main/native-chat/agent-session-journal/journal-state-layout.ts
  • src/main/native-chat/agent-session-journal/journal-state-schema.ts
  • src/main/native-chat/agent-session-journal/journal-storage-admission.test.ts
  • src/main/native-chat/agent-session-journal/journal-storage-row-schema.ts
  • src/main/native-chat/agent-session-journal/journal-storage-schema.ts
  • src/main/native-chat/agent-session-journal/journal-storage-strict.ts
  • src/main/native-chat/agent-session-journal/journal-store-collaborators.ts
  • src/main/native-chat/agent-session-journal/journal-store-contract-test-fixture.ts
  • src/main/native-chat/agent-session-journal/journal-store-contracts.ts
  • src/main/native-chat/agent-session-journal/journal-store-restore.ts
  • src/main/native-chat/agent-session-journal/journal-store-schema.spec.ts
  • src/main/native-chat/agent-session-journal/journal-store.spec.ts
  • src/main/native-chat/agent-session-journal/journal-store.ts
  • src/main/native-chat/agent-session-journal/journal-streamed-revision-contract-test-fixture.ts
  • src/main/native-chat/agent-session-journal/journal-streamed-revision-resolved-lifecycle.test.ts
  • src/main/native-chat/agent-session-journal/journal-streamed-text-revision.test.ts
  • src/main/native-chat/agent-session-journal/journal-terminal-settlement-validation.spec.ts
  • src/main/native-chat/agent-session-journal/journal-terminal-time-validation.spec.ts
  • src/main/native-chat/agent-session-journal/journal-terminal-validation-test-fixture.ts
  • src/main/native-chat/agent-session-journal/journal-transition-collections.ts
  • src/main/native-chat/agent-session-journal/journal-unknown-content.spec.ts
  • src/main/native-chat/agent-session-journal/journal-unknown-row-kind.spec.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold-contract-test-fixture.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold-queue.spec.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold-recovery.spec.ts
  • src/main/native-chat/agent-session-journal/journal-unsent-send-hold.spec.ts
  • src/main/native-chat/agent-session-journal/journal-write-projection.ts
  • src/main/native-chat/agent-session-journal/queued-message-pause-contract-test-fixture.ts
  • src/main/native-chat/agent-session-journal/queued-message-pause-held-cards.spec.ts
  • src/main/native-chat/agent-session-journal/queued-message-pause.spec.ts
  • src/main/native-chat/agent-session-journal/queued-message-reopen-pause.spec.ts
  • src/main/native-chat/agent-session-journal/queued-message-stop-pause.spec.ts
  • src/main/native-chat/agent-session-journal/queued-message-stored-row.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-batches.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-byte-limits.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-large-identities.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-history-page.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-journal-batch.ts
  • src/main/native-chat/agent-session-wire/agent-session-stop-note-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/agent-session-stop-note-paging.test.ts
  • src/main/native-chat/agent-session-wire/agent-session-stop-note-projection.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-actionable-prompts.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-append-delivery.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-contract-test-actions.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-ends-session.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-plan-card.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-queue-cards.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-clear-rewind.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-conversations.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-budget.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-restart.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption.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-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-late-settlement-cancelled.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-late-settlement-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-late-settlement.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-mutation-context.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-newer-content-host.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-prompt-cancel.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queue-import-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queue-import-retained-history.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queue-import-reuse.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queue-import-scaling.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-legacy-import.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-queued-legacy-journal.test-fixture.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-refused-card.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-failure-filing.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-offer-newer-orca.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-ownership.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-progress.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-rewind.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-verdict.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stale-verdict-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stale-verdict-persistence.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stale-verdict-prompts.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stop-event.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-stop-receipts.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-subscriber-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-subscriber-oversized-removal.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-subscriber-publication.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-subscribers.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-transition-contract-test-fixture.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-transition-rollback.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-transition.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-unopened-tab.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-wire-admission.test.ts
  • src/main/runtime/orchestration/structured-worker-journal-page.test.ts
  • src/main/runtime/rpc/methods/orchestration/worker-start-card-contract-test-fixture.ts
  • src/main/runtime/rpc/methods/orchestration/worker-start-card-operations.test.ts
  • src/main/runtime/rpc/methods/orchestration/worker-start-card-population.test-fixture.ts
  • src/main/runtime/rpc/methods/orchestration/worker-start-card-scenario.test-fixture.ts
  • src/main/runtime/rpc/methods/orchestration/worker-start-card.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-at-rest-context.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-at-rest-lease.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-at-rest-options.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-at-rest.test.ts
  • src/main/runtime/rpc/methods/structured-agent-session-rest-contract-test-fixture.ts
  • src/main/runtime/structured-agent-runtime-registrations.ts
  • src/main/runtime/structured-agent-session-attachment-wiring.test.ts
  • src/main/runtime/structured-agent-session-attachment-wiring.ts
  • src/main/runtime/structured-agent-session-codex-interrupt-order.test.ts
  • src/main/runtime/structured-agent-session-codex-settlement-order.test.ts
  • src/main/runtime/structured-chat-dispatch-worker-lifecycle.test.ts
  • src/main/sqlite/sqlite-read-failure.ts
  • src/shared/agent-session-journal-open-union.ts
  • src/shared/agent-session-journal-schemas.ts
  • src/shared/wsl-move/wsl-move-storage-dispositions.ts
  • tests/e2e/cross-version-wire/agent-session-interrupted-tool-downgrade.unit.test.ts
  • tests/e2e/cross-version-wire/agent-session-newer-chat-refusal.unit.test.ts
  • tests/e2e/cross-version-wire/agent-session-outcome-chat-downgrade.unit.test.ts
  • tests/e2e/cross-version-wire/agent-session-stop-event-downgrade.unit.test.ts
  • tests/e2e/cross-version-wire/cross-version-stop-note-scenarios.ts
  • tests/e2e/cross-version-wire/kept-card-downgrade.unit.test.ts
  • tests/e2e/cross-version-wire/release-checkout.ts
  • tests/e2e/cross-version-wire/released-chat-continuation.ts
  • tests/e2e/cross-version-wire/released-chat-queue.ts
  • tests/e2e/cross-version-wire/released-chat-upgrade.unit.test.ts
  • tests/e2e/cross-version-wire/released-chat-writers.ts
  • tests/e2e/journal-restored-consumers.unit.test.ts
Files with no reviewable changes: 2
  • src/main/native-chat/agent-session-wire/structured-agent-session-prompt-cancel.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-newer-content-host.test.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.

Comment on lines +174 to +177
const close = releaseModuleExport<(stateDirectory: string) => void>(
support,
'closeTestJournalHostDatabase'
)

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.

Minor · Stability & Availability · Quick win

Await the release's closeTestJournalHostDatabase before you read the database.

The current closeTestJournalHostDatabase is async. It awaits the checkpoint close and then closes the connection. These lines type the release export as (stateDirectory: string) => void and do not await it. If the release's closeAll() leaves that handle open, the close runs concurrently with the next steps. In the first test, databaseBytes() hashes the .db and -wal files while the connection can still checkpoint or truncate the WAL. The byte-equality assertion can then fail intermittently. In the second test, this build's openTestJournalHostDatabase can open the file while the release's connection is still open.

If a release returns void, awaiting it is still harmless. Type the export as returning void | Promise<void> and await each call.

Proposed fix
-      const close = releaseModuleExport<(stateDirectory: string) => void>(
+      const close = releaseModuleExport<(stateDirectory: string) => void | Promise<void>>(
         support,
         'closeTestJournalHostDatabase'
       )
 ...
         await older.closeAll()
-        close(directory)
+        await close(directory)
 ...
-      releaseModuleExport<(stateDirectory: string) => void>(
+      await releaseModuleExport<(stateDirectory: string) => void | Promise<void>>(
         support,
         'closeTestJournalHostDatabase'
       )(directory)

Also applies to: 199-199, 284-287

brennanb2025 and others added 7 commits October 31, 2026 01:46
…ve-chat-journal-grows-to-20-gib-request

# Conflicts:
#	src/main/native-chat/agent-session-journal/journal-storage-admission.test.ts
… prefix lacks

Cleanup never deletes a key's newest record or touches the input prefix, so it
needs no new reader check. Refusing the whole chat over one such key reversed
main's deliberate append fallback and is out of this change's scope.
@AmoabaKelvin
AmoabaKelvin merged commit 2a5ec2b into main Nov 1, 2026
47 of 48 checks passed
AmoabaKelvin added a commit that referenced this pull request Nov 2, 2026
Resolve import conflicts from main's module moves. #37216 stopped the
journal sink refusing writes under backpressure, so drop the tests that
forced a sink refusal and keep one that proves a time-gated tail is saved
before an incoming stream evicts it. Move the scheduled plan owner check
out of codex-structured-session-acquire.ts to stay under its line cap.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

This merged before its review finished. The review loop's last verdict was not ready. These things are still open:

1. Cleanup freezes the app on large journals (must fix before this ships in a release). Tracked in STA-13374.
On a 310-chat, 24.9 GB test journal (the size of the original report in #34916), the cleanup's delete-and-commit steps ran on the Electron main thread. On a paired server they run on orcad's serving thread. One cleanup commit blocked that thread for at least 4.5 seconds, and the slowest single cleanup step took 5.4 seconds. Cleanup starts 60 seconds after launch, and the first pass on that journal took about 2 h 47 min. A user with a big journal can therefore see repeated multi-second freezes of the window, sends and phone updates for hours after upgrading. A follow-up PR will fix this. A measurement run currently queued decides between two designs: smaller, byte-bounded cleanup steps with lighter disk sync and checkpoints kept off the main thread, or moving journal saving off the main thread. Requirement: no slowdown anywhere compared with main.

2. Not yet tested on the merged code.
#36430 added a second saved format, and this PR was adapted to clean it up. The earlier full-size results were all measured on chats saved in the first format, before that adaptation. Still owed on the merged code:

  • the full 310-chat test on chats saved by current main, with and without returning freed space to the disk;
  • the four 30-minute streaming tests (Claude, Codex, and the shared path other agents use);
  • the check that the previous two stable releases still open chats this cleans, and refuse newer-format chats cleanly with nothing lost;
  • a real-app run with Claude and Codex.

3. Related, tracked separately.

The prefix-position check removed in 3415066 is fine to leave out. Cleanup never deletes the newest copy of anything, so this PR doesn't need it.

audichuang pushed a commit to audichuang/orca that referenced this pull request Nov 3, 2026
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.

2 participants