Files
juliusbrussee__caveman/engine/contextwindow/contextwindow_test.go
Julius Brussee 82864c8f4c feat: ship Caveman 2.0.0 — engine, proxy, SDKs, unified CLI
Single-commit port of the Caveman 2 tree onto the original repo history
(candidate caveman-2@88878a4 applied over main@3098342). No unrelated-history
merge; original history untouched.

Preserved v1 surfaces:
- skills/caveman/SKILL.md byte-for-byte, plus plugin mirror and caveman.skill zip
- legacy CI (Node 18/20/22 installer + Python 3.11 suites) alongside engine-ci
- cli/install.js compatibility shim forwarding to bin/install.js
- .codex/config.toml ships both hooks and codex_hooks for older Codex (#617)
- README Trendshift + Skills.sh badges and local star-history asset
- v1.10.0-pinned curl installs; benchmarks/tmp-starcharts ignore rules

Fixed for public same-repo release:
- SECURITY.md vulnerability reporting points at this repository
- release-binaries.yml publishes to this repo via job-scoped GITHUB_TOKEN
  (cross-repo PAT removed); binary-release environment still gates signing
- packages/cli/PUBLISHING.md rewritten for packages/ layout and same-repo flow
- profile-contract and provider-catalog lanes skip lane-scope gates on
  initial import so the launch PR can gate on their real validation steps
- ANNOUNCEMENT.md network claim corrected: compression is local; requests
  still go to the provider you configured

Caveman 2 stays opt-in: bin-v1.0.0 binaries and @caveman-ai/cli publish
separately after this lands and soaks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BLvb5QniwYjmcawyssQNw9
2026-08-11 16:46:10 +02:00

86 lines
3.1 KiB
Go

package contextwindow_test
import (
"slices"
"testing"
"time"
"github.com/JuliusBrussee/caveman/engine/contextwindow"
)
func TestPackSelectsBM25RelevantItemsWithinBudget(t *testing.T) {
now := time.Date(2026, 6, 19, 12, 0, 0, 0, time.UTC)
items := []contextwindow.Item{
{ID: "intro", Text: "general project overview and team notes", Tokens: 20, Timestamp: now.Add(-4 * time.Hour)},
{ID: "deploy", Text: "deploy failed because the migration lock timed out with ERROR in postgres", Tokens: 30, Timestamp: now.Add(-3 * time.Hour)},
{ID: "billing", Text: "billing dashboard color adjustments and copy polish", Tokens: 25, Timestamp: now.Add(-2 * time.Hour)},
{ID: "logs", Text: "postgres migration retry succeeded after lock release", Tokens: 30, Timestamp: now.Add(-time.Hour)},
}
got := contextwindow.Pack("postgres migration deploy failure", items, contextwindow.Options{MaxTokens: 60, Now: now})
ids := selectedIDs(got.Items)
if !slices.Contains(ids, "deploy") || !slices.Contains(ids, "logs") {
t.Fatalf("selected ids = %v, want deploy and logs", ids)
}
if slices.Contains(ids, "billing") {
t.Fatalf("selected ids = %v, unrelated billing item should be deferred", ids)
}
if got.TokensUsed > 60 {
t.Fatalf("tokens used = %d, exceeds budget", got.TokensUsed)
}
if got.DeferredCount != 2 || got.TokensSaved <= 0 {
t.Fatalf("bad accounting: %+v", got)
}
}
func TestPackKeepsPinnedItemsWhenTheyFit(t *testing.T) {
items := []contextwindow.Item{
{ID: "system", Text: "system instruction keep this exact rule", Tokens: 25, Pin: true},
{ID: "match", Text: "rare alpha beta gamma query terms", Tokens: 30},
{ID: "extra", Text: "rare alpha beta gamma more query terms", Tokens: 30},
}
got := contextwindow.Pack("rare alpha beta gamma", items, contextwindow.Options{MaxTokens: 55})
ids := selectedIDs(got.Items)
if ids[0] != "system" {
t.Fatalf("selected ids = %v, pinned system item must remain in original order", ids)
}
if len(ids) != 2 || got.TokensUsed != 55 {
t.Fatalf("selected ids/tokens = %v/%d, want exactly pinned plus one match", ids, got.TokensUsed)
}
}
func TestPackUsesRecencyWhenQueryIsEmpty(t *testing.T) {
now := time.Date(2026, 6, 19, 12, 0, 0, 0, time.UTC)
items := []contextwindow.Item{
{ID: "old", Text: "old context", Tokens: 20, Timestamp: now.Add(-24 * time.Hour)},
{ID: "recent", Text: "recent context", Tokens: 20, Timestamp: now.Add(-10 * time.Minute)},
}
got := contextwindow.Pack("", items, contextwindow.Options{MaxTokens: 20, Now: now})
ids := selectedIDs(got.Items)
if len(ids) != 1 || ids[0] != "recent" {
t.Fatalf("selected ids = %v, want recent", ids)
}
}
func TestPackReservesTokens(t *testing.T) {
items := []contextwindow.Item{
{ID: "a", Text: "alpha one", Tokens: 20},
{ID: "b", Text: "alpha two", Tokens: 20},
}
got := contextwindow.Pack("alpha", items, contextwindow.Options{MaxTokens: 40, ReserveTokens: 25})
if got.TokensUsed != 0 || got.DeferredCount != 2 {
t.Fatalf("reserved budget should defer all items, got %+v", got)
}
}
func selectedIDs(items []contextwindow.Selected) []string {
out := make([]string, len(items))
for i, item := range items {
out[i] = item.ID
}
return out
}