Skip to content

gateway: close the full mutation run's last survivors; client cut mid-upload is not billed (D259) - #121

Merged
jaredLunde merged 3 commits into
mainfrom
mutants-3
Oct 4, 2026
Merged

jaredLunde merged 3 commits into
mainfrom
mutants-3

Conversation

@jaredLunde

Copy link
Copy Markdown
Contributor

The final batch of the full cargo-mutants run over gateway core (usage, translate, proxy, peek, circuit_breaker, route): 59 full-suite survivors (43 from the 329-survivor re-test, 16 from shard 27 and the mutants a load-flaky replica test had falsely "caught").

Verdict count
Real gap, new test 25
Dead code simplified/deleted 15
Equivalent, exact exclude_re (each checked with --list) 9
Already killed or removed on main 10

Every kill verified by applying the mutant and watching the targeted test fail.

Bug (D259, low, billing): a managed client that closed mid-upload was billed an input estimate — pingora marks a prematurely closed body done, so body_delivered saw it as delivered. New client_body_cut_short rejects pingora's premature-close errors. Test: cut_short::a_client_that_closes_mid_upload_is_not_billed_an_estimate (Content-Length and chunked).

Behaviour changes from simplification: scan_buffered drops its : depth guard to agree with the two scanners it replaced (differed only on invalid JSON; corpus cases pin it); find_event_end accepts \n\r\n as an event end, as the SSE spec allows.

Notable new coverage: /{provider} body over budget refused before reading; anthropic-version only on translated walks; error_while_proxy failover/no-failover on resets and reused-connection timeouts; error-after-output still billed an estimate; large-body re-run skips an unserved candidate; Chat→Responses reasoning items.

Known gap (not fixed): a client that stalls mid-upload is still failed over when the upstream read timeout fires.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk

jaredLunde and others added 3 commits October 4, 2026 09:03
…s survivors (D259)

59 survivors of the full beyond-ai suite (triage3: proxy 25, usage 10, translate 4, peek 2,
route 2; triage4: proxy 3, translate 7, peek 2, usage 4). Every kill verified by hand-applying the
mutant and running the targeted test.

Bug (D259): a client that closed mid-upload (a Content-Length body with bytes still to come, a
chunked body without its last chunk) was billed an input estimate as if the provider had the
whole request. Pingora marks such a body done (is_body_done), so body_delivered read the half the
provider was sent as delivered and logging's no_head path estimated it. body_delivered now also
rejects a downstream premature-close error (client_body_cut_short, pingora's context string, as
h2_body_unsent does). Found while killing the error_while_proxy Downstream mutant.

Real gaps (new tests):
- Admission: a declared /{provider} body past the budget is refused before a byte is read; a BYO
  request takes no tenant slot; a body of exactly MAX_REQUEST_BODY streams through.
- Headers: anthropic-version is added only to a translated walk, never to a Messages relay; a
  translated and a signed JSON answer are chunked to an HTTP/1.1 client.
- error_while_proxy: a reset before a small body is sent fails over (header-won walk); a client
  that resets mid-upload is not failed over; a read timeout on a reused connection is not resent.
- Billing: an error event after output is billed an estimate.
- Large bodies: a FullBody re-run skips an unserved candidate (PDF on grok-build-0.1).
- Units: route first_key with 2 and 3 keys, the key cooldown expires, InputTally's two-chain cut
  on long plain runs, the bounded Anthropic usage head, OaiToResp reasoning items (index change,
  text after a signature, a whole signed thinking block, one summary part per item), a tool call
  opened with its arguments, str_value decodes an escaped value.

Dead or simplified: scan_buffered's ':' and '-' depth guards (now as unguarded as the two walks it
replaces; the ':' guard diverged from them on invalid JSON, pinned by two corpus cases);
InputTally::text's aux guards; TALLY's PUNCT1 / DIGITS3 arms (same as the default arm);
map_request's a == b arm (already gone); the request buffer's pre-size now reads
RequestCtx::rewrites_body after the context is built; tracks_terminal and keep_usage_head
helpers; find_event_end accepts any blank line (a \n then \r\n blank line too, as SSE allows), so
its look-behind is gone; de_service_tier's visit_some (serde_json's deserialize_any never calls it).

Equivalent, excluded with reasons: MAX_CATALOG_OUTPUT_TOKENS's > vs >=, KEY_NODES' 1 + n vs 1 * n,
InputTally::run's cut gate, tracks_terminal widened, keep_usage_head widened, the FullBody
unserved guard (true; pinned by a catalog invariant test), str_value's raw fast path (false),
de_service_tier's expecting.

Already handled before this pass: tally_eager (now its own fn, excluded), the >= on the replay
buffer (past_replay_buffer, verified killed), de_service_tier's visit_none / visit_u64 (excluded),
the FullBody reset mask's << (killed by claims_reliability).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk
@jaredLunde
jaredLunde enabled auto-merge (squash) October 4, 2026 16:12
@jaredLunde
jaredLunde merged commit 563fae2 into main Oct 4, 2026
16 of 19 checks passed
@jaredLunde
jaredLunde deleted the mutants-3 branch October 4, 2026 16:23
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