Written and agreed before the soak starts, so nothing lives only in a chat message that a compaction or a shift-change could lose. This document IS the pass condition. Silence promotes only if these five criteria hold; evidence against any one of them holds promotion pending investigation, not "let's decide."
The instrument that measures the beta is this session's own telemetry against the currently-running v4.3.0 proxy on the dogfood host (up since 2026-07-28 11:48Z).
- Hit rate: 99.9–100.0% sustained across ~5,250 requests today
cache_creationtokens per turn: ~126 steady-state on typical fires- Warmer: fires every ~30 min, both halves of the 1h TTL tier are observable
If this session's warmer keeps firing and the numbers keep looking like that, criterion 3 is continuously satisfied for free. If the warmer goes quiet, that is not a pass — it is a missing instrument.
The dogfood-host operator restarts the proxy onto the beta build. The current process has ten days of uptime predating every feature in this release; nothing measures until this restart. The 24–48h soak clock starts at the restart, not at merge, not at publish.
The original soak T0 was 2026-08-08T14:58:52Z, the second cutover
(the first cutover on 08-07 22:24Z was rolled back after AITL caught three
gates unset — see feedback-env-gates-are-ship-state). The soak was then
interrupted on 2026-08-08T17:14Z by Q7d expiration on the measuring
account, followed by a home-side power outage covering the recovery window.
Observer coverage did not return until 2026-08-11T15:35Z when this
session resumed via systemd auto-restart.
Ground-truth measurement on 2026-08-11T20:12Z–20:15Z: the proxy
process itself never bounced. systemctl --user show cache-fix-proxy
reports MainPID=380513, ExecMainStartTimestamp=Sat 2026-08-08 14:58:52 UTC, ActiveState=active, SubState=running. All six v4.4.0-beta.0
gates present in the process Environment= line (CACHE_FIX_OUTPUT_GUARD,
CACHE_FIX_TOOL_REWRITE, CACHE_FIX_INSERTION_NORMALIZE,
CACHE_FIX_PREFIXDIFF, CACHE_FIX_REQUEST_CAPTURE=1,
CACHE_FIX_USAGE_LOG_EXTENDED=on), no drift from cutover values.
/health snapshot at 20:12:03Z corroborates: version: 4.4.0-beta.0,
proxy_tree: d077b9e39b3e (matches local/v4.2.1-warmer @ 181570a, the
v4.4.0-beta.0 merge commit).
Interpretation: the runtime state has actually been in the exact soak
configuration continuously since 08-08 14:58:52Z. The outage was observer-
side only. But criterion 1 (proxy uptime) needs Q7d-metered observer
coverage — the outage days have no signal to grade, so they cannot count
toward the soak window even though the process ran through them. Criteria
2 through 5 have the same observer-coverage requirement (all require
usage.jsonl scans of the measuring account's traffic).
New T0: 2026-08-11T20:14:05Z (Chris's decision timestamp in
#cache-proxy room, event id
$bu3Sf-HoXssUi3Vss6rLyt37GUS3u2VYvwvn_Dx-ock). No process bounce; the
reset is metering-window only. Chris's reasoning: bouncing costs a
cache-prefix bust across every active session, and the process state is
already what we want to soak — bounce would work against us. AITL
concurred ($LuqtfCefy_KNCmXs1ggGw8nJkMGUUJoiaSBrOJRw2sw); Proxy Builder
posted the two-source verification ($lt10XkDuKWHRDgOWQwrzsIpPt-sU2Fbfy6VuKfxYMi4);
AITL final concur on skipping the bounce and on this write
($R-B9xONJbQfOXmql3sL_xcAoMs-pZXXLAHPhyPfoPDo).
Outage-window usage.jsonl mining not attempted. The 2.5-day gap
contains AITL's fleet's rows, but the fleet was mostly quiescent because
its agents were on the Q7d block — any criterion-3 signal would be
noise-dominated. Better to spend the mining time on post-reset-T0 clean
data.
24–48h soak window now runs from 20:14:05Z 2026-08-11 through 20:14:05Z 2026-08-12 (minimum) or 2026-08-13 (upper bound).
Each must hold across the full soak window (24–48h). A tripped criterion holds promotion for investigation, not "let's decide."
- No crashes, no unbounded restarts.
/healthresponds throughout.bytesTransferredcounter is monotonic (a reset means a silent respawn the criterion missed).
The guard exists to catch a broken outgoing request body produced by our own mutating extensions, and to forward Claude Code's original bytes instead. A fire is a real defect in one of those extensions — not in Claude Code, and not in anything Anthropic sent back.
- Zero fires over the soak = pass, but only after step (a) below.
- ≥ 1 fire = hold for immediate triage; do not promote.
- Telemetry at
${CLAUDE_CONFIG_DIR:-~/.claude}/cache-fix-snapshots/<key>-guard-events.jsonlcarries class + count + sid, never body content.
Caveat (a): zero fires is also what a guard that never runs produces
— the #cache-proxy push-path bug from 2026-08-07 was a component that
looked healthy because nothing exercised it. Before treating zero as a
pass, confirm the extension is loaded and reached by one deliberate
synthetic fire early in the soak, then zero for the remainder. A guard
proved to fire on demand and then quiet is a much stronger claim than
one silent throughout.
- Hit rate holds ≥ 99.0% on the same session shape.
usage.jsonlcache_read_input_tokens / (cache_read_input_tokens + cache_creation_input_tokens)per turn is the number. cache_creationtokens per turn hold near ~126/turn steady-state.
The creation-token floor is why this criterion has two halves rather than
one. A hit rate can look fine at 99.5% while creation tokens climb from
126 to four figures per turn — the ratio hides the movement behind the
larger denominator. If cache_creation moves upward materially at a
steady hit rate, insertion-normalization (#272) or
deferred-tool-rewrite (#273) is busting the prefix and the ratio will
not surface it. Watch both.
Caveat (a): a quota block longer than the cache TTL produces this
exact signature with no defect present. Before treating a
cache_creation climb as a regression, check usage.jsonl for a gap
immediately preceding it. If the gap exceeds the session's TTL tier
(1h on this host), the spike is reconnection cost, not a bust.
Measured on the dogfood host during the 2026-08-07 16:50Z window, before the soak began:
| Fleet blocked (Q5h exhausted) | 14:57:50Z → 16:50:24Z — 1h53m |
| Cache TTL tier | 1h — every prefix expired mid-block |
| Cold-start turns on reconnect | 9, within 4½ minutes |
Their cache_creation |
895k, 823k, 802k, 705k, 682k, 632k, 447k, 370k, 150k |
| Hit rate on 7 of the 9 | 0% |
Share of the window's total cache_creation |
5.5M of 5.6M |
Read through the two halves of this criterion in isolation, that is an unambiguous prefix-corruption regression: creation tokens four orders of magnitude above the ~126 floor, hit rate at zero. It was a quota block. No extension was involved; the proxy was running v4.3.0 at the time.
The block is self-reinforcing, which is why this is not a rare edge: a block longer than the TTL guarantees the cold restart, because the warmer cannot fire without quota either. The instrument goes down with the thing it measures. Any Q5h exhaustion over an hour produces this, and the fleet exhausted Q5h twice on 2026-08-07 alone.
How to apply during triage:
- Note the timestamp of the first turn showing the spike.
grep '"ts":"<date>T<hour>' ~/.claude/usage.jsonland look backward for a gap in rows.- Gap longer than the TTL tier immediately before the spike → discard that window and resume measuring once hit rate recovers. Not a criterion-3 trip, not a hold.
- Gap absent, or the elevated
cache_creationpersists after hit rate has recovered → that is the real signal. Hold the promote.
The distinguishing feature is persistence, not magnitude. Reconnection cost is a spike that resolves within a few turns as prefixes re-warm; a prefix bust is a sustained elevation that survives a healthy hit rate.
This exclusion does not soften the criterion. It removes one known false positive with a named, checkable signature. Anything that does not match that signature still trips.
- Especially not the pre-#278 last-line-invariant class.
- Absence of 500s alone is not sufficient — pre-existing traffic may have been noisy. The criterion is no NEW class of upstream error that doesn't appear in the v4.3.0 baseline for the same operator's traffic shape.
CACHE_FIX_USAGE_LOG_EXTENDEDis not the beta gate. Flipping it on the dogfood host mid-soak is a separate opt-in probe (needs meter v0.9.1+ installed), not the soak criterion itself.
Hold the promote. Investigate. If the investigation resolves the cause
without needing a code change, document the resolution in this file and
restart the soak clock. If it needs a code change, cut a beta.1, restart
the soak clock from that publish.
#272 insertion-normalization carries needs-sim-validation.
Applied 2026-07-31, never removed. The fork-context case cannot be
sim'd locally — the beta soak IS its sim validation. Waiver landed as a
comment on #272
before this release publishes; label removed in the same action.
- Not exhaustive. If a criterion missed here surfaces during the soak and is obvious (a memory leak, a file-descriptor exhaustion), of course hold the promote and add the criterion here retroactively.
- Not a release-notes document. AITL owns those, separately.
- Not a substitute for
sys_admin's judgment on the observed system. If they see something worrying and none of these criteria named it, their observation still counts.
— Proxy Builder (mechanical); AITL (criteria 3 + 4 refinements + waiver policy); @chris (go / hold gate).