Skip to content

feat(benchmark): UUID cache-coherency validation on the router-replay path - #2

Open
4D0R wants to merge 8 commits into
mainfrom
uuid-router-replay
Open

feat(benchmark): UUID cache-coherency validation on the router-replay path#2
4D0R wants to merge 8 commits into
mainfrom
uuid-router-replay

Conversation

@4D0R

@4D0R 4D0R commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds --replay-inject-uuids, a cache-coherency check for the --router-replay-file
benchmark path. It brings the mechanics of the existing eval cache-coherency-*
suite to realistic replayed traffic instead of synthetic prompts, so a replay run
can also verify that the served prefix cache stays coherent under the replayed
workload.

How it works

  • Per replayed session, generates N deterministic UUID "stamps"
    (N via computeStampsPerSeries, sized to the session's per-session cached
    region) and injects them as bare, space-separated tokens at the boundary
    between the session's cross-session-shared leading blocks (system/tools) and
    its per-session content — mirroring cache_coherency.go's shared-prefix mode.
    This keeps the shared prefix byte-identical across sessions (so router-replay's
    prefix-cache-hit reproduction is preserved) while the stamps live in a region
    cached within the session, so later turns read them back from cache. A session
    with no shared leading block falls back to tail injection.
  • The model is asked to recite the exact ordered UUID list on the first line and
    then continue normally, so the check composes with forced-output (ignore_eos)
    without constraining output volume.
  • Validation mirrors the coherency eval's two tests — per-stamp presence and
    first-line list conformity (matchesExpectedUUIDList) — plus cross-session
    contamination (FindLeakedUUIDs), surfaced in the auto-summary and the
    per-request JSONL.

Flags

  • --replay-inject-uuids (requires --router-replay-file), --replay-uuid-seed,
    --replay-recite-every-request.
  • Composes with --replay-natural-output / --replay-output-ratio.

Notes

  • FindLeakedUUIDs is consolidated into the benchmark package (shared by the
    eval CLI and replay). Reuses newUUIDGenerator, computeStampsPerSeries,
    matchesExpectedUUIDList, and computeMaxOutputTokens.
  • Unit tests cover stamp determinism, boundary detection, the cache-fidelity
    invariant, first-line conformity, and cross-session contamination.

4D0R and others added 8 commits July 24, 2026 12:09
Presence + cross-conversation contamination checks on the --from-dataset
replay path, modeled on the cache-coherency test. Reusable primitives in
benchmark/replay_uuid.go (UUID gen, marker injection, recite instruction,
validateReplayResponse) and FindLeakedUUIDs moved into the benchmark package.
To be re-targeted to the router-replay path next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…play

Re-targets the per-turn UUID coherency check from the dataset-replay path
(--from-dataset) to the tree-aware router-replay path
(--router-replay-file), composing it with the existing forced-output
feature (ignore_eos + continue-generating instruction).

Design (Option C — boundary injection, with tail fallback): one
deterministic UUID is injected per SESSION at the boundary between its
cross-session-shared leading blocks (system/tools) and its per-session
content. This lands the marker in a region cached WITHIN a session (later
requests repeat it, giving a genuine KV-coherency signal) while leaving the
cross-session shared prefix byte-identical, preserving cache-hit
reproduction against the original capture. A session with no shared
leading block falls back to tail injection.

New benchmark/replay_router_uuid.go: computeBlockSessionCounts (streams a
replay-v3 file once, counting distinct-session references per block hash),
sharedPrefixBlockCount, buildSessionUUIDs, replayReciteFromContextInstruction
(a recite ask that never embeds the UUID itself, so presence reflects
genuine recall), and a max_tokens recite floor (with a one-time warning)
so a tiny captured output budget can't truncate the recite line into a
false PRESENCE_MISS.

benchmark/replay_router_wire.go: buildAnthropicMessagesBody /
buildOpenAIChatCompletionsBody take a new *uuidInjection param (nil =
unchanged); the marker splices into the system prefix at the boundary, or
falls back to the message tail, preserving Anthropic's strict user/
assistant role alternation.

benchmark/replay_router_post.go / replay_router.go: replayPoster carries
the per-session UUID/marker state and builds the injection per request;
after a successful response, validates it via the existing
validateReplayResponse/FindLeakedUUIDs primitives (unchanged, shared with
the eval CLI).

benchmark/auto.go precomputes the per-session UUID array and block-hash
counts once before per-model goroutines spawn, sized from the header +
--replay-series/--replay-series-indices (the same formula the router
stream itself uses), so no lazy-growth is needed.

Drops the dataset-path UUID wiring (replay.go, replay_uuid.go) that
--replay-inject-uuids used before: buildReplayUUIDSets,
computeInScopeAtEachGptTurn, replayTurnInjectable, replayReciteInstruction,
capRecitedUUIDs, and the --replay-uuid-mode / --replay-uuids-per-turn
flags are all removed. --replay-inject-uuids now requires
--router-replay-file and is rejected with --from-dataset (flip of the
previous gate). --replay-recite-every-turn is renamed
--replay-recite-every-request.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…est mechanics

Changes the --replay-inject-uuids feature to mirror cache_coherency.go's
--shared-prefix-per-series mode instead of its own single-marker scheme:

- N bare UUIDs per session (was 1 wrapped "[ref-id: ...]" marker), sized via
  computeStampsPerSeries off each session's per-session cached-region bytes
  (the root request's prefix blocks at/after sharedPrefixBlockCount) — see
  the new computePerSessionCachedChars/requestPrefixBytes helpers.
- Injection is spliced as one system block/message of N bare, space-separated
  UUIDs at the boundary (or tail-fallback), mirroring
  buildCoherencySharedSeriesPrompt's tail, byte-identical across a session's
  own requests.
- Recite instruction now asks for the exact ordered UUID list on the FIRST
  line, then lets the model continue normally (replayReciteFirstLineInstruction),
  replacing the old "find and echo the marker" ask.
- Validation adds first-line output conformity (firstLineConformity, reusing
  matchesExpectedUUIDList) alongside the existing per-UUID presence and
  cross-session leak checks; RequestMetrics/requestDataRecord gain ExactMatch/
  uuid_exact_match, and the auto-summary prints both UUID correctness and
  output conformity, matching the coherency CLI's two-test layout.
- The recite max_tokens floor now scales with N via computeMaxOutputTokens
  instead of a fixed 64-token constant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
buildInjection returns a non-nil *uuidInjection on EVERY request once
--replay-inject-uuids is on -- injection happens every turn so the
stamp stays warm in KV, but only inj.Recite (reciteEveryRequest ||
isLastRequest) says the model was actually asked to recite it. With
--replay-recite-every-request=false, non-final requests were being
scored anyway, guaranteeing a false PRESENCE_MISS/conformity failure
on every turn the model was never asked to recite. Add inj.Recite to
the scoring gate in do() while leaving injection itself ungated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/messages

markerAtBoundary required SharedPrefixLen >= len(effectiveSystemBlocks),
i.e. "the shared run covers at least all system blocks" -- which stays
true even when the cross-session-shared run extends PAST the system
blocks into shared tools or a shared leading message. Splicing the
per-session UUID marker as a system block in that case puts it ahead of
those shared tools/messages on the wire, making them diverge per
session and losing their cross-session prefix-cache hit even though
their content stays byte-identical.

Flip the comparison to SharedPrefixLen <= len(effectiveSystemBlocks):
boundary injection is now eligible only when the shared run ends at or
within the system blocks, falling back to tail injection whenever it
reaches into tools/messages. Applied to both the Anthropic and OpenAI
body builders; behavior is unchanged for the common case where the
shared run is contained within the system blocks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…owed recite

Replace the "N UUID stamps per session, clustered at the shared->per-session
boundary, recite ALL on line 1" scheme with one deterministic UUID injected
inline per qualifying user turn (role==user, has a text block, hash used by
exactly one session), spread through the conversation, and a bounded recite
window per request: first turn + up to 3 most-recent turns, excluding the
current turn, capped at 4. This keeps recite cost/response-budget constant
regardless of session length while spreading coverage across the whole
conversation over time; every visible turn still gets its own inline marker
stamped (keeping it warm in KV) even when it falls outside the recite window.

- replay_router_uuid.go: computeSessionTurnHashes/isQualifyingUserTurn
  replace computePerSessionCachedChars/countSessionsWithUsableBoundary/
  sharedPrefixBlockCount/bareUUIDBlock; buildSessionTurnUUIDs replaces
  buildSessionUUIDs and also returns a uuid->owning-session reverse map;
  uuidInjection is now {StampByHash, Recite, ReciteLabels, ReciteUUIDs};
  replayReciteWindowInstruction replaces replayReciteFirstLineInstruction.
- replay_router_wire.go: buildMessageContent/buildMessages/
  buildOpenAIMessages take a stampByHash param and append the inline
  "[turn-N id: <uuid>]" marker to the stamped message's own synthesized
  text, keyed by its hash for byte-identical replay; boundary/tail-splice
  logic removed from both body builders.
- replay_router_post.go: replayPoster gains turnHashes/hashToTurn/owner
  (drops blockCounts); buildInjection now walks a request's visible turns
  to build StampByHash and derive the recite window; do()'s validation
  scores against inj.ReciteUUIDs and calls the new
  findLeakedUUIDsByOwner scanner instead of validateReplayResponse.
- replay_uuid.go: add uuidRe + findLeakedUUIDsByOwner, an O(response)
  contamination scan via the reverse owner map (FindLeakedUUIDs, whose
  O(population) scan the dataset path and the coherency CLI still use,
  is left untouched).
- replay_router.go: wire the new poster fields in
  runRouterReplayInstance; drop the now-dead requestPrefixBytes helper
  (its only caller, computePerSessionCachedChars, is removed).
- auto.go: precompute replaySessionTurnHashes/replayUUIDSets/
  replayUUIDOwner once per run; startup diagnostic reports turn counts
  instead of the retired boundary-usability stats.
- cli/benchmark_options.go: update --replay-inject-uuids' description.
- Tests rewritten for the new turn/window/contamination model (turn
  identification across instances, window selection at turns 1-6,
  determinism/fidelity, reverse-map contamination scanning).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the router-replay UUID branch up to date with main (multi-endpoint
per-request routing + failover, coherency cold/warm cycle distribution,
.so bumps). Resolved 3 conflicts and reconciled the UUID feature with
main's shared-poster routing:

- replay_router.go / replay_router_post.go / auto.go: main's endpoint
  picker builds one replayPoster per endpoint, shared across concurrent
  sessions. Made all UUID poster state global/read-only (allUUIDSets,
  sessionTurnHashes, owner, reciteEveryRequest, uuidEnabled) and derive
  the per-session sessionIdx per request from seriesNum, so a shared
  poster safely serves any session -- --replay-inject-uuids is safe with
  multi-endpoint specs, no per-session mutation on a shared object.
- cli/eval_commands.go: main's cold/warm cycle-distribution summary +
  findLeakedUUIDs moved to the benchmark package.
- cli/command_misc_cache_coherency_test.go: main's new eval tests +
  dataset-path test prune.

Build, vet, and benchmark/cli tests green.
@4D0R
4D0R requested a review from tigrawap August 4, 2026 14:54
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