Skip to content

Observer reuses a window's decoded claims while its rows are unchanged - #4777

Merged
trissim merged 1 commit into
mainfrom
claude-laptop/observer-fingerprint
Nov 15, 2026
Merged

trissim merged 1 commit into
mainfrom
claude-laptop/observer-fingerprint

Conversation

@trissim

@trissim trissim commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

What

On every #comms message the observer re-decoded all open threads' notification windows, even the N−1 whose evidence didn't move. Decoding the four-table claim join (FieldCodec) is ~a third of the observer child's per-ping CPU — measured observer child 6.6–7.5% per ping, over the 5% target, scaling with open threads.

Fix

The decode is a pure function of the raw join rows. capture() now hashes the raw rows and reuses the decoded claims when the hash is unchanged for the same (root, selection), decoding only the window(s) whose rows actually moved. The hash covers the whole join — claim, triage context, queue pointer, published response — so any change re-decodes. Consumption, bus responses and stored inputs are never cached and are read fresh every pass, so nothing displayed can go stale. Cache is bounded to the most recent selections (a sliding window makes a new selection value each move); root is optional so callers outside the observer loop decode fresh.

Supersedes #4776's batch (it batched reads but not the decode, so it didn't move the number): removes prime/read_batch/sliced.

Correctness

The reuse is gated by a byte-exact hash of the whole raw join, so the decoded claims are only reused when the rows are identical — a pure-function cache. Every other evidence source is read fresh.

Tests

Notification + observation suite: 112 passed. The 3 failures (test_named_target_contracts, test_outbound_transcript_source::...read_contention..., test_recipient_activity_index::...archived_duplicate_birth) fail identically on origin/main — pre-existing, zero added by this change (verified by running the same set on main: 3 failed there too).

🤖 Generated with Claude Code

https://claude.ai/code/session_01XbFMSnLEc51gw21bLFFRK1

On every #comms message the observer re-decoded all open threads' notification
windows, even the N-1 whose evidence did not move. Decoding the four-table claim
join (FieldCodec) is ~a third of the observer child's per-ping CPU (observer child
6.6-7.5% per ping, over the 5% target).

The decode is a pure function of the raw join rows. capture() now hashes those raw
rows and reuses the decoded claims when the hash is unchanged for the same
(root, selection), decoding only the window(s) whose rows actually moved. The hash
covers the whole join -- claim, triage context, queue pointer and published response
-- so any change re-decodes; consumption, bus responses and stored inputs are never
cached and are read fresh every pass, so nothing displayed can go stale. The cache is
bounded to the most recent selections (a sliding window makes a new selection each
move). root is optional: callers outside the observer loop decode fresh.

This supersedes PR #4776's batch (it batched reads but not the decode, so it did not
move the number; removed prime/read_batch/sliced). Notification + observation suite:
112 passed, same 3 pre-existing main reds as the baseline, zero added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbFMSnLEc51gw21bLFFRK1
@trissim
trissim merged commit 4464703 into main Nov 15, 2026
1 of 3 checks passed
@trissim

trissim commented Nov 15, 2026

Copy link
Copy Markdown
Contributor Author

Installed (core-446470384) and measured, 6 throwaway-Toad runs, observer child on ping: 3.7, 4.8, 5.0, 5.2, 5.9, 6.2% (median ~5.1%), idle ~1.6%. Was 6.6-7.5% before. The cache moved it ~30% and removed the scaling with open-thread count (now the observer decodes only the one window a ping changes, not all N). It sits at the 5% line, not comfortably under: the per-ping floor is the single changed window's decode, which is inherent to showing the new message. Going lower means decoding only the changed rows within that window - diminishing returns. Clean landing: notification+observation suite had zero added failures over main's baseline of 3.

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