Summary
Capturing one message on a live session reads the whole session's external-source object state. load_current_mutations (crates/tracedecay-rusqlite-runtime/src/repository/external_source.rs) selects every current object of the binding joined with its mutation history (SELECT history.mutation_json, ... FROM external_source_objects_v2 AS current LEFT JOIN external_source_mutations_v1 ... WHERE current.binding_id = ?1), and the same for external_source_projected_objects_v2. A transcript binding gains a current object per message, so each capture costs O(session length).
Evidence
Found while fixing #2607 (isolated test profile, the session_store_read_cost fixture: one live Codex session, 500-word title, one message per capture). Per-statement read attribution with a local SQLite trace scaffold, averaged over three single-message captures:
| live session length |
external_source_objects_v2 current-state read per capture |
whole capture read per message |
| 16 messages |
~12 KB |
~350 KB |
| 128 messages |
~107 KB |
~750 KB |
The drain and temporal refresh of the same messages stay within 1.13x over the same growth after #2607's fix, so capture is now the part of a streamed message's ingest that grows with the session.
Expected
Capturing k new messages reads O(k) external-source objects plus bounded binding state: look up only the objects the commit mutates instead of materializing the binding's full current state.
Summary
Capturing one message on a live session reads the whole session's external-source object state.
load_current_mutations(crates/tracedecay-rusqlite-runtime/src/repository/external_source.rs) selects every current object of the binding joined with its mutation history (SELECT history.mutation_json, ... FROM external_source_objects_v2 AS current LEFT JOIN external_source_mutations_v1 ... WHERE current.binding_id = ?1), and the same forexternal_source_projected_objects_v2. A transcript binding gains a current object per message, so each capture costs O(session length).Evidence
Found while fixing #2607 (isolated test profile, the
session_store_read_costfixture: one live Codex session, 500-word title, one message per capture). Per-statement read attribution with a local SQLite trace scaffold, averaged over three single-message captures:external_source_objects_v2current-state read per captureThe drain and temporal refresh of the same messages stay within 1.13x over the same growth after #2607's fix, so capture is now the part of a streamed message's ingest that grows with the session.
Expected
Capturing k new messages reads O(k) external-source objects plus bounded binding state: look up only the objects the commit mutates instead of materializing the binding's full current state.