Conversation
|
Review from jc: competing adversarial reviewers, then a verifier that tried to refute every finding against the PR head and current The constant change itself is correct: [0,20]∪[20,40] is contiguous, and it still applies cleanly on origin/main 4b4533c, which still has N=10. But the fixture rewrites silently removed coverage for two named invariants. I confirmed that the 'thinking cacheable' and 'cacheable-only distance' mutations both pass at the PR head. The comment derivation and the PR-body cost claim are also wrong. All the fixes are small. Confirmed findings:
Refuted by the verifier: Separate finding (A3): N=20 should have been N=21 to cover the 41-block incident; Implied concern that the change interacts with the API's 4-cache_control-block limit |
…m 10 to 20 (PRI-1821) Addresses jc's review (obra#405): 1. Rebuilt the raw-vs-cacheable-distance test with an exact-placement assertion and a fixture that proves raw counting, not cacheable-only counting. 2. Rebuilt the thinking-block test so the thinking block sits exactly at the naive (tail - N) target, forcing the anchor to skip it. 3. Rewrote the cache-control.ts derivation comment: tail path is Delta <= 20 (not 10); anchor path is N <= Delta <= N+20 (not Delta <= N+20); the union is gap-free only for N <= 21. Fixed the in-function comment's overbroad reachability claim. 4. Generalized the PRI-1821 regression test to loop the full Delta range (0..max(N+20, 40)) instead of sampling only Delta=40, so an over-widened N (e.g. 22) that opens a gap at Delta=21 fails it. 5. Will fix the PR body's cost claim separately (no code content). 6. Updated stale '(10)' comments and gave the streaming/message-caching long-conversation fixtures headroom, sized off the constant.
08d628c to
448ade0
Compare
|
Addressed all six findings at 448ade0 (rebased onto current
Mutation evidence:
Also ran the full |
Problem
Anthropic's cache lookback window is ~20 raw content blocks per breakpoint.
ANCHOR_OFFSET_RAW_BLOCKS(currently10) sets how far behind the tail the stable anchor breakpoint sits, which bounds how much a conversation can grow between two successful calls before the prior cache write becomes unreachable. Post-deploy data (PRI-1819) found a real cache bust caused by a 41-block growth between successful calls — 11 blocks past the anchor path's current budget (Δ≤30, since Δ≤N+20 at N=10).Change
Widen
ANCHOR_OFFSET_RAW_BLOCKSfrom10to20, raising the anchor-path budget to Δ≤40. No steady-state cost change: the tail breakpoint is always stamped on the last cacheable block of the last message regardless ofN— moving the anchor doesn't leave anything uncached that wasn't already. (An earlier version of this PR body claimed ~$0.06/call extra cache_creation cost; that was wrong and has been removed — see jc's review below.)While verifying this I found the anchor-offset math in the original proposal's writeup didn't hold up under its own formula (it claimed Δ≤50 at N=20; the formula it stated works out to Δ≤40). I corrected the in-code derivation comment to match, and noted there that a 41-block outlier would still exceed a Δ≤40 budget by one block — this narrows the gap rather than fully closing the class. The derivation comment now also spells out that the tail path (Δ≤20) and anchor path (N≤Δ≤N+20) only union gap-free for N≤21 — raising N further without adding another breakpoint opens a hole just above the tail path's own reach.
Three existing unit tests hardcoded a raw-block count sized for the old offset (10), so they silently lost their anchor once the offset grew past their fixture length. Rebuilt those fixtures to size off
ANCHOR_OFFSET_RAW_BLOCKSinstead of a literal, tightened two of them to assert exact anchor placement (raw distance, not cacheable-only distance) instead of a loose>=bound, and generalized the PRI-1821 regression test to loop the full Δ range instead of sampling only Δ=40 — so an over-widened N (e.g. 22) that opens a gap at Δ=21 now fails it.Review response (#405, jc)
jc confirmed the constant change itself is correct and requested changes on six findings, all addressed in the latest commit:
cache-control.tsderivation comment: tail path is Δ≤20 (not 10 as previously stated); anchor path is N≤Δ≤N+20 (not Δ≤N+20); the union is gap-free only for N≤21. Fixed the in-function comment's overbroad "reachable from the next request's tail" claim.(10)comments and gave the streaming/message-caching long-conversation fixtures headroom, sized off the constant.Testing
vitest run src/providers/__tests__/cache-control.test.ts src/providers/__tests__/cache-control-byte-stable.test.ts src/providers/__tests__/cache-control-streaming.test.ts src/providers/__tests__/anthropic-provider-message-caching.test.ts src/providers/__tests__/anthropic-provider-smoke-cache-markers.test.ts: 29/29 passing.packages/agentunit suite (vitest run --exclude 'src/__tests__/**' ...): 3813 passed, 35 skipped, 0 failed.tsc --noEmit: clean.eslint: clean.'thinking'toCACHEABLE_BLOCK_TYPES(jc's finding-1 mutation): now caught (3 tests fail, including the rebuilt thinking-block test).cacheablePositions.length - 1 - i >= ANCHOR_OFFSET_RAW_BLOCKS): now caught by the rebuilt exact-placement test (expected 2 to be 20).ANCHOR_OFFSET_RAW_BLOCKS = 22(over-widened N, jc's finding-4 scenario): now caught by the generalized regression test at Δ=21, with every other cache-control test still green — reproducing exactly what jc found against the old single-sample test.ANCHOR_OFFSET_RAW_BLOCKS = 10(reverted): the generalized regression test fails at Δ∈(30,40], preserving the original red-on-revert coverage for the PRI-1819 incident magnitude.ANCHOR_OFFSET_RAW_BLOCKS = 20(current): all of the above pass cleanly.