Close inbox projection under one transaction

The old `prepareRun` projection drifted: append-to-shadow, thread-event,
and `markAgentInboxDelivered` ran as three independent writes, so a
crash between the append and the delivered mark replayed the same
inbox row on the next run and double-populated the transcript.

v46 installs `agent_message_projections` keyed by (message_id,
session_id) as the idempotent gate. The projection closure now wraps
the ledger claim, the shadow append, the thread-event write, and the
delivered-mark inside one `BEGIN IMMEDIATE` transaction (exposed via
`AppDatabase.withTransaction`). `claimProjection` returns false on a
replay, so the whole closure short-circuits — no double transcript,
no double thread event.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-19 15:46:12 -04:00
1 parent 213837af1d
commit cb0ac485da
5 files changed
+133 -26

No files matched your search

+2
View File
@@ -10,6 +10,7 @@ import { createMigrationsV42V42 } from "./migrations/v42-v42";
import { createMigrationsV43V43 } from "./migrations/v43-v43";
import { createMigrationsV44V44 } from "./migrations/v44-v44";
import { createMigrationsV45V45 } from "./migrations/v45-v45";
import { createMigrationsV46V46 } from "./migrations/v46-v46";
import {
columnExists,
nowIso,
@@ -195,6 +196,7 @@ export function runMigrations(
...createMigrationsV43V43(deps),
...createMigrationsV44V44(deps),
...createMigrationsV45V45(deps),
...createMigrationsV46V46(deps),
];
for (const migration of migrations) {