From a1b55fd4f9c0f4bfc31230f0c761423fd5958f85 Mon Sep 17 00:00:00 2001 From: afjcjsbx Date: Mon, 4 May 2026 14:10:42 +0200 Subject: [PATCH] fix(seahorse): enforce target token thresholds for leaf summaries --- pkg/seahorse/short_compaction.go | 6 +-- pkg/seahorse/short_compaction_test.go | 64 +++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/pkg/seahorse/short_compaction.go b/pkg/seahorse/short_compaction.go index 30e290926..0dfb1330f 100644 --- a/pkg/seahorse/short_compaction.go +++ b/pkg/seahorse/short_compaction.go @@ -602,8 +602,8 @@ func (e *CompactionEngine) generateLeafSummary( } } - // Check if level 1 succeeded - if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) < inputTokens { + // Level 1 only succeeds if it actually reaches the requested target size. + if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) <= targetTokens { return content, nil } @@ -627,7 +627,7 @@ func (e *CompactionEngine) generateLeafSummary( return "", err } } - if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) < inputTokens { + if content != "" && tokenizer.EstimateMessageTokens(providers.Message{Content: content}) <= aggressiveTarget { return content, nil } diff --git a/pkg/seahorse/short_compaction_test.go b/pkg/seahorse/short_compaction_test.go index ea7dcb52d..da07cdab7 100644 --- a/pkg/seahorse/short_compaction_test.go +++ b/pkg/seahorse/short_compaction_test.go @@ -3,6 +3,7 @@ package seahorse import ( "context" "fmt" + "strings" "sync" "sync/atomic" "testing" @@ -697,6 +698,69 @@ func TestGenerateLeafSummaryEscalationToAggressive(t *testing.T) { } } +func TestGenerateLeafSummaryEscalatesWhenLevel1MissesTarget(t *testing.T) { + var calls []string + normalContent := strings.Repeat("n", 1000) // ~404 tokens: below input, above target + aggressiveContent := strings.Repeat("a", 450) // ~184 tokens: within aggressive target + escalateComplete := func(ctx context.Context, prompt string, opts CompleteOptions) (string, error) { + if contains(prompt, "Aggressive summary policy") { + calls = append(calls, "aggressive") + return aggressiveContent, nil + } + calls = append(calls, "normal") + return normalContent, nil + } + + s := openTestStore(t) + ce, _ := newTestCompactionEngineWithStore(s, escalateComplete) + + msgs := []Message{ + {Role: "user", Content: "hello world", TokenCount: 500}, + {Role: "assistant", Content: "response", TokenCount: 500}, + } + + content, err := ce.generateLeafSummary(context.Background(), msgs, "") + if err != nil { + t.Fatalf("generateLeafSummary: %v", err) + } + if content != aggressiveContent { + t.Fatalf("expected aggressive summary after level 1 missed target") + } + if len(calls) != 2 || calls[0] != "normal" || calls[1] != "aggressive" { + t.Fatalf("expected normal then aggressive calls, got %v", calls) + } +} + +func TestGenerateLeafSummaryAcceptsContentAtTargetBoundary(t *testing.T) { + exactTargetContent := strings.Repeat("x", 488) // (488 + 12) * 2 / 5 = 200 tokens + var aggressiveCalled bool + complete := func(ctx context.Context, prompt string, opts CompleteOptions) (string, error) { + if contains(prompt, "Aggressive summary policy") { + aggressiveCalled = true + } + return exactTargetContent, nil + } + + s := openTestStore(t) + ce, _ := newTestCompactionEngineWithStore(s, complete) + + msgs := []Message{ + {Role: "user", Content: "hello world", TokenCount: 286}, + {Role: "assistant", Content: "response", TokenCount: 286}, + } + + content, err := ce.generateLeafSummary(context.Background(), msgs, "") + if err != nil { + t.Fatalf("generateLeafSummary: %v", err) + } + if content != exactTargetContent { + t.Fatalf("expected level 1 summary at target boundary to be accepted") + } + if aggressiveCalled { + t.Fatal("did not expect aggressive retry when level 1 hit target exactly") + } +} + func TestGenerateLeafSummaryEscalationToTruncation(t *testing.T) { // Both normal and aggressive return empty, should escalate to level 3 truncation emptyComplete := func(ctx context.Context, prompt string, opts CompleteOptions) (string, error) {