fix(storage): retry contended message writes and preserve cancellation - #287
Conversation
|
[P2] Preserve tool completion messages after cancellation Passing the lease signal to every display-message upsert in I reproduced this with the built CLI and a loopback synthetic provider: start a Bash command that creates a marker and then sleeps, send SIGINT after the marker appears, and inspect the persisted display rows and canonical history after the CLI exits.
Both runs exited with code 130 and persisted an aborted turn. The same assertion that the tool message remains in display history passes on the merge base and fails on the PR head (macOS arm64, Node 22.22.2). Please preserve required post-cancellation tool completion projections while allowing blocked writes to stop waiting, and cover ordinary Ctrl+C during tool execution with a regression test that does not involve a foreign writer. |
Change
A foreign SQLite writer that outlasts the native five-second busy timeout can fail v2 message projection, poison the ordered event lane, and terminate an active turn. This change retries message-upsert transaction admission with short native waits and asynchronous backoff within a ten-second budget. The mutation callback is never replayed, and the shared connection timeout is restored before callbacks and asynchronous waits.
Cancellation carries the exact turn lease signal separately from semantic event snapshots. Cancellation stops ordinary display-message lock waits while preserving normal aborted settlement and history reconciliation. An immediately available cleanup write can still commit after cancellation. Complete messages carrying tool calls preserve executed tool facts even during abort cleanup and retain the bounded write-lock retry policy. Unrelated errors and failures after mutation starts still fail closed. The scope is the reproduced v2 message-upsert path; other SQLite writers retain their existing policy.
Related to #282.
Validation
pnpm verify, full profile, all 14 applicable gates on clean commitd44d687d2e8be34f778f6282f9ca9c2c6f7cf466(macOS arm64, Node v26.4.0). Capability coverage: 157 files / 4,217 tests.aborted, no session error, and cancelled assistant output removed from canonical history. This checks durable state in addition to the exit code.perf:fullrequired. The previous full run was INCONCLUSIVE because of excessive sample spread; this is neither a pass nor a confirmed regression. A passing run for the latest PR head and intended base is pending CI and must be linked before merge.Publication and contribution checks
release/public-source.json; the new Vitest file is registered intest/vitest-suites.json. The CLI regression uses the existing BYOK gate.Maintainer handoff
Publication scope or license changes: none beyond the reviewed retry helper and regression test recorded in the source inventory; existing licenses apply.
Shared-source port: pending.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.