v2 plan: sticky-growth test appends turns instead of changing the first user message; note the finding

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 09:54:36 -07:00
co-authored by Claude Fable 5.1
parent 927b2cfc4d
commit 6c8cbbc78d
2 changed files with 19 additions and 7 deletions
@@ -110,6 +110,13 @@ func TestUnknownContextNeverBlocks(t *testing.T) {
}
}
// grow appends later turns to a conversation body without touching its system prompt or first
// user message, so the fingerprint — and therefore the lease — stays the same.
func grow(body string, words int) string {
turn := `,{"role":"assistant","content":"ok"},{"role":"user","content":"` + strings.Repeat("x ", words) + `"}`
return strings.Replace(body, `]}`, turn+`]}`, 1)
}
func TestStickyLeaseSurvivesGrowthUntilItDoesNotFit(t *testing.T) {
small := ctxUpstream(t, "small", 8192, 2)
big := ctxUpstream(t, "big", 131072, 1)
@@ -120,19 +127,18 @@ func TestStickyLeaseSurvivesGrowthUntilItDoesNotFit(t *testing.T) {
if resp.Header.Get(proxy.HostHeader) != "small" {
t.Fatal("setup: first turn must be on small")
}
// Same conversation (same first user message), later turn well under 4096: stays.
longer := strings.Replace(body, `"content":"`, `"content":"`+strings.Repeat("x ", 500), 1)
resp = r.post("/r/v1/chat/completions", longer)
// Same conversation, a later turn well under 4096 tokens: stays.
resp = r.post("/r/v1/chat/completions", grow(body, 500))
drain(resp)
if resp.Header.Get(proxy.HostHeader) != "small" || resp.Header.Get(proxy.LeaseHeader) != "reused" {
t.Errorf("turn 2: %q %q, want small reused", resp.Header.Get(proxy.HostHeader), resp.Header.Get(proxy.LeaseHeader))
}
// A turn that outgrows the slot moves the lease — once — and the move is recorded as an event.
huge := strings.Replace(body, `"content":"`, `"content":"`+strings.Repeat("x ", 30000), 1)
// A turn that outgrows the slot moves the lease — once — and the move is visible in the header.
huge := grow(body, 30000)
resp = r.post("/r/v1/chat/completions", huge)
drain(resp)
if resp.StatusCode != 200 || resp.Header.Get(proxy.HostHeader) != "big" {
t.Fatalf("outgrown turn: %d %q, want 200 from big", resp.StatusCode, resp.Header.Get(proxy.HostHeader))
if resp.StatusCode != 200 || resp.Header.Get(proxy.HostHeader) != "big" || !strings.HasPrefix(resp.Header.Get(proxy.CtxHeader), "moved") {
t.Fatalf("outgrown turn: %d %q ctx=%q, want 200 from big with a moved header", resp.StatusCode, resp.Header.Get(proxy.HostHeader), resp.Header.Get(proxy.CtxHeader))
}
resp = r.post("/r/v1/chat/completions", huge)
drain(resp)