fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events - #3999
Merged
Conversation
buzz-agent already measures and sends accumulatedCachedInputTokens on the wire, but TurnUsage had no cache field and build_turn_metric_counts hardcoded cache_read_tokens/cache_write_tokens to None on both the turn and cumulative TokenCounts. Every published event permanently lacked the data the harness measured — unrecoverable loss on an append-only archive. Thread the cache-read count through with field-local semantics identical to the existing accumulatedTotalTokens pattern: - SessionState gains last_cached_input to track the committed baseline. - TurnUsage gains turn_cache_read_tokens (None when no baseline or counter decreased) and cumulative_cache_read_tokens (always present; zero when no cache hits reported). - A cumulative counter decrease taints only the cache delta — it does not flip delta_reliable or invalidate the input/output deltas. - build_turn_metric_counts wires turn_cache_read_tokens into turn (when delta_reliable) and Some(cumulative_cache_read_tokens) into cumulative. - cache_write_tokens remains None with an explanatory comment: buzz-agent does not emit a write-side count on the wire today. Tests added: first-turn cumulative passthrough, second-turn delta, field- local decrease taint, zero-both-sides Some(0), setup-notification baseline, and a full wire-parse acceptance test (nonzero accumulatedCachedInputTokens → nonzero cacheReadTokens in cumulative + correct turn delta in pool.rs). Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…end-to-end Thufir's review (REQUEST CHANGES on #3999) identified that accumulated_cached_input_tokens was a defaulted u64, collapsing an absent field (goose: field not reported) and an explicit zero (buzz-agent: provider confirmed no cache hits) into the same value. Downstream, cumulative_cache_ read_tokens was u64 and pool.rs unconditionally wrapped it in Some(...), publishing cacheReadTokens: 0 in every kind:44200 event regardless of whether the harness ever reported the field. This contradicts the TokenCounts contract (None = not reported, not zero) and would have corrupted cache-aware analytics and pricing provenance in the append-only archive. Fix: make the wire field, committed baseline, and cumulative turn field all Option<u64>. The delta is only computed when both snapshots are Some and monotonic. The cumulative field passes through to TokenCounts without any unconditional Some() wrapping. Some(0) is preserved when a harness explicitly reports zero; None is preserved when the field is absent. New tests cover: absent-field → None cumulative; explicit-zero → Some(0); baseline-absent-then-present → no invented delta; baseline-present-then-absent → no delta, None cumulative; end-to-end pool tests for omitted and reported cache fields in kind:44200 output. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
tlongwell-block
pushed a commit
that referenced
this pull request
Jul 31, 2026
…bsub * origin/main: fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999) feat(relay): accept kind:30621 multi-repo projects at ingest (#3171) fix(release): preserve main in desktop PR body (#3979) chore(release): release Buzz Desktop version 0.5.3 (#3972) fix(release): require exact-head approval for desktop tags (#3973) fix(release): make desktop tagging squash-safe (#3965) Revert "chore(release): release Buzz Desktop version 0.5.3" (#3960) docs(nips): add single-coordinate manual-unread override layer and verification model to NIP-RS (#2864) chore(release): release Buzz Desktop version 0.5.3 Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz>
tlongwell-block
pushed a commit
that referenced
this pull request
Jul 31, 2026
…bsub * origin/main: fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999) feat(relay): accept kind:30621 multi-repo projects at ingest (#3171) fix(release): preserve main in desktop PR body (#3979) chore(release): release Buzz Desktop version 0.5.3 (#3972) fix(release): require exact-head approval for desktop tags (#3973) fix(release): make desktop tagging squash-safe (#3965) Revert "chore(release): release Buzz Desktop version 0.5.3" (#3960) docs(nips): add single-coordinate manual-unread override layer and verification model to NIP-RS (#2864) chore(release): release Buzz Desktop version 0.5.3 Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz> Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz>
kalvinnchau
pushed a commit
that referenced
this pull request
Aug 1, 2026
…n-v1 * origin/main: fix(mesh): stop restarting a busy or loading shared-compute node (#3909) fix(desktop): preserve first huddle speech (#3962) feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (#3278) fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999) feat(relay): accept kind:30621 multi-repo projects at ingest (#3171) fix(release): preserve main in desktop PR body (#3979) chore(release): release Buzz Desktop version 0.5.3 (#3972) fix(release): require exact-head approval for desktop tags (#3973) fix(release): make desktop tagging squash-safe (#3965) Revert "chore(release): release Buzz Desktop version 0.5.3" (#3960) docs(nips): add single-coordinate manual-unread override layer and verification model to NIP-RS (#2864) chore(release): release Buzz Desktop version 0.5.3 Signed-off-by: npub122y0pqkertljmedu303rl0aqrj3w8pvu43t6jxm6875lzg6f2pwqegc3xc <5288f082d91aff2de5bc8be23fbfa01ca2e3859cac57a91b7a3fa9f12349505c@buzz.block.builderlab.xyz>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
buzz-agentmeasures and sendsaccumulatedCachedInputTokenson the wire (usage.rs:93).buzz-acpdeserializes it correctly — but then drops it:TurnUsagehad no cache field, andbuild_turn_metric_countshardcodedcache_read_tokens: Noneandcache_write_tokens: Noneinto bothturnandcumulativeTokenCounts. Every kind:44200 event published permanently lacked data the harness measured. The archive is append-only — this is unrecoverable data loss per turn, every turn, until fixed.NIP-AM already specifies the fields (
cacheReadTokens/cacheWriteTokensinsideturnandcumulative). This is a pure threading fix.Changes
crates/buzz-acp/src/usage.rsSessionStategainslast_cached_input: u64to track the committed cache-read baseline.TurnUsagegainsturn_cache_read_tokens: Option<u64>(field-local;Nonewhen no baseline or counter decreased) andcumulative_cache_read_tokens: u64(always present; zero when no cache hits reported).record()computes the cache-read delta with field-local taint semantics: a decrease in the cumulative counter nulls onlyturn_cache_read_tokens— it does not flipdelta_reliableor invalidateturn_input_tokens/turn_output_tokens. Identical to theaccumulatedTotalTokenspattern already present.take()and the setup-notification branch both advancelast_cached_inputin the committed baseline.crates/buzz-acp/src/pool.rsbuild_turn_metric_countswiresturn_cache_read_tokensintoturn.cache_read_tokens(whendelta_reliable) andSome(cumulative_cache_read_tokens)intocumulative.cache_read_tokens.cache_write_tokensremainsNoneon both counts with an explanatory comment: buzz-agent does not emit a write-side count on the wire today.TurnUsagestruct literals in tests updated with the two new fields.Tests
usage.rs— new cache-read section (5 tests):cache_read_first_turn_produces_none_turn_delta_and_passes_cumulative_through— no baseline → delta None, cumulative passes throughcache_read_second_turn_delta_computed_correctly— delta = current − previouscache_read_decrease_nulls_turn_cache_but_leaves_delta_reliable— field-local taint: decrease nulls cache delta only, input/output stay reliablecache_read_zero_payload_after_baseline_produces_zero_delta— zero on both sides →Some(0), notNonecache_read_threads_through_setup_notification_baseline— setup notification baseline correctly seeds the cache counterpool.rs— new acceptance test (1 test):test_build_turn_metric_counts_cache_read_tokens_thread_through— wire-parses a buzz-agent payload with nonzeroaccumulatedCachedInputTokens, runs two turns through the tracker andbuild_turn_metric_counts, and asserts nonzerocacheReadTokensin cumulative + correct per-turn delta inturn; also assertscache_write_tokensisNonethroughoutQuality gates at tip
c6405eb43f532572e3b7775e0dee826dc9cb3f82cargo test -p buzz-acpcargo clippy -p buzz-acp --all-targets -- -D warningscargo fmt --checkNote: the pre-push hook
mobile-testgate fails onorigin/mainbefore this branch (Flutter test inchannels_page_test.dart/compose_bar_test.dart— verified independently). My changes touch onlycrates/buzz-acp/src/; the mobile failure is unrelated and pre-existing.