fleetd #637: scale LeadContextGauge's HIGH threshold with the effective auto-compact window #657

Closed
agent wants to merge 1 commits from worker/637-context-gauge-threshold-466eb5-16 into main
9 changed files with 391 additions and 25 deletions
@@ -1075,7 +1075,33 @@ public final class Fleetd {
*/
static FleetMcp.LeadConfigDirSource leadConfigDirSource(Supplier<Map<String, FleetConfig.Profile>> profiles,
Map<String, FleetConfig.Leader> leaders) {
return new FleetMcp.LeadConfigDirSource(leadConfigDirLookup(profiles, leaders));
return new FleetMcp.LeadConfigDirSource(leadConfigDirLookup(profiles, leaders),
leadContextWindowLookup(profiles, leaders));
}
/**
* Per-lead-name factory for the effective auto-compact window {@link LeadContextGauge} scales
* its HIGH threshold against — the same {@code fleet.leaders.<name>.profile} link {@link
* #leadConfigDirLookup} already follows, one step further to that profile's own {@link
* FleetConfig.Profile#effectiveAutoCompactWindow()}. A lead entry that names no
* {@code profile:}, or whose named profile is not configured, or whose profile resolves no
* window at all, returns {@code null} — {@link LeadContextGauge} then falls back to its own
* fixed HIGH threshold.
*/
static Function<String, Long> leadContextWindowLookup(Supplier<Map<String, FleetConfig.Profile>> profiles,
Map<String, FleetConfig.Leader> leaders) {
return leadName -> {
FleetConfig.Leader lead = leaders.get(leadName);
if (lead == null || lead.profile() == null || lead.profile().isBlank()) {
return null;
}
FleetConfig.Profile leadProfile = profiles.get().get(lead.profile());
if (leadProfile == null) {
return null;
}
Integer window = leadProfile.effectiveAutoCompactWindow();
return window == null ? null : window.longValue();
};
}
/**
@@ -1100,19 +1126,32 @@ public final class Fleetd {
*/
static Function<String, LeadContextGauge.Reading> leadContextLookup(LeadContextGauge gauge, AgentControl agents,
Supplier<Map<String, String>> liveLeadTerminals, Function<String, String> configDirForLeadName) {
return leadContextLookup(gauge, agents, liveLeadTerminals, configDirForLeadName, _ -> null);
}
/**
* As above, additionally resolving each lead's effective auto-compact window (normally {@link
* #leadContextWindowLookup}'s return) and passing it through to {@link LeadContextGauge#read},
* so the heartbeat's own HIGH reading scales with that lead's real window instead of always the
* gauge's fixed fallback.
*/
static Function<String, LeadContextGauge.Reading> leadContextLookup(LeadContextGauge gauge, AgentControl agents,
Supplier<Map<String, String>> liveLeadTerminals, Function<String, String> configDirForLeadName,
Function<String, Long> windowForLeadName) {
return terminal -> {
String leadName = liveLeadTerminals.get().get(terminal);
if (leadName == null) {
return LeadContextGauge.Reading.unknown();
}
String configDir = configDirForLeadName.apply(leadName);
Long effectiveWindow = windowForLeadName.apply(leadName);
Agent live;
try {
live = agents.get(terminal);
} catch (RuntimeException e) {
return LeadContextGauge.Reading.unknown();
}
return gauge.read(configDir, live.sessionId(), live.agentType());
return gauge.read(configDir, live.sessionId(), live.agentType(), effectiveWindow);
};
}
@@ -1129,6 +1168,14 @@ public final class Fleetd {
leadContextLookup(gauge, agents, liveLeadTerminals, configDirForLeadName));
}
/** As above, additionally threading the effective-window lookup through. */
static LeadHeartbeatLoop.LeadContextSource leadContextSource(LeadContextGauge gauge, AgentControl agents,
Supplier<Map<String, String>> liveLeadTerminals, Function<String, String> configDirForLeadName,
Function<String, Long> windowForLeadName) {
return new LeadHeartbeatLoop.LeadContextSource(
leadContextLookup(gauge, agents, liveLeadTerminals, configDirForLeadName, windowForLeadName));
}
/**
* fleetd #248 / fleetd#201 Unit 5: package-private factory for the per-target backend-error
* pattern lookup {@link CompletionResolver} classifies a pane scrape against. Closes over the
@@ -405,7 +405,8 @@ final class FleetdAssembly {
TimeUnit.SECONDS.toNanos(hb.idleAfterSeconds()), hb.backoffMs(), hb.quietNudgeCap(),
metrics,
Fleetd.leadContextSource(leadContextGauge, router.leadAgents(), leads,
Fleetd.leadConfigDirLookup(() -> config.get().profiles(), leaders)),
Fleetd.leadConfigDirLookup(() -> config.get().profiles(), leaders),
Fleetd.leadContextWindowLookup(() -> config.get().profiles(), leaders)),
Boolean.TRUE.equals(hb.contextHighNudge()), requireOperatorConfirm);
heartbeat.start();
} else {
@@ -798,6 +798,25 @@ public record FleetConfig(
return isSubscription() ? SUBSCRIPTION_CREDENTIAL_ID : profile;
}
/**
* The auto-compaction window a launched Claude Code session actually runs on: {@code env:
* CLAUDE_CODE_AUTO_COMPACT_WINDOW} when it parses as an integer, since that environment
* variable wins over the {@code --autocompact} flag {@link #autoCompactWindow} produces (see
* {@code ClaudeCodeArguments}); {@link #autoCompactWindow} otherwise. {@code null} when
* neither resolves to a usable number.
*/
public Integer effectiveAutoCompactWindow() {
String envValue = env.get(CLAUDE_CODE_AUTO_COMPACT_WINDOW_ENV);
if (envValue == null) {
return autoCompactWindow;
}
try {
return Integer.valueOf(envValue.trim());
} catch (NumberFormatException e) {
return autoCompactWindow;
}
}
/** True when this profile's workers are granted a forge token to open their own PR (CB-302). */
public boolean hasGitToken() {
return gitTokenEnv != null && !gitTokenEnv.isBlank();
@@ -2184,6 +2203,12 @@ public record FleetConfig(
static final int AUTO_COMPACT_WINDOW_MIN = 100_000;
/** Highest {@code autoCompactWindow} Claude Code's {@code --autocompact <tokens>} flag accepts. */
static final int AUTO_COMPACT_WINDOW_MAX = 1_000_000;
/**
* The {@code env:} key a launched Claude Code session reads for its auto-compaction window,
* ahead of the {@code --autocompact} launch flag {@code autoCompactWindow} produces (see
* {@link Profile#effectiveAutoCompactWindow()}).
*/
static final String CLAUDE_CODE_AUTO_COMPACT_WINDOW_ENV = "CLAUDE_CODE_AUTO_COMPACT_WINDOW";
/**
* Reject a profile whose {@code autoCompactWindow:} is set but outside the token band Claude
@@ -2265,13 +2290,13 @@ public record FleetConfig(
if (!(entry.getValue() instanceof Map<?, ?> profile)
|| !(profile.get("autoCompactWindow") instanceof Number window)
|| !(profile.get("env") instanceof Map<?, ?> env)
|| !env.containsKey("CLAUDE_CODE_AUTO_COMPACT_WINDOW")) {
|| !env.containsKey(CLAUDE_CODE_AUTO_COMPACT_WINDOW_ENV)) {
continue;
}
Object kind = profile.get("kind");
boolean claudeCode = kind == null || String.valueOf(kind).isBlank()
|| Profile.KIND_CLAUDE_CODE.equalsIgnoreCase(String.valueOf(kind));
Object envValue = env.get("CLAUDE_CODE_AUTO_COMPACT_WINDOW");
Object envValue = env.get(CLAUDE_CODE_AUTO_COMPACT_WINDOW_ENV);
if (claudeCode && !String.valueOf(window).equals(String.valueOf(envValue))) {
String name = String.valueOf(entry.getKey());
names.add(name);
@@ -97,14 +97,19 @@ public final class LeadContextGauge {
static final long DEFAULT_CACHE_TTL_MILLIS = 5_000;
/**
* Live tokens at or above this count report {@link State#HIGH}. On the host this was measured
* on, auto-compaction actually fires around 267,000–270,000 tokens, but the point of a HIGH
* state is to warn before that happens, not at it — 200,000 is the standard Claude context
* window size and a sensible built-in default: no config key is required to pick it, and a
* lead crossing it is already deep enough into its window that a compaction is foreseeable.
* Fallback HIGH threshold used when a caller resolves no effective auto-compact window for the
* lead being read (see {@link #read(String, String, String, Long)}) — the built-in default so
* no config key is required to get a warning at all.
*/
static final long HIGH_THRESHOLD_TOKENS = 200_000;
/**
* The fraction of a resolved effective auto-compact window that HIGH warns at, so the warning
* margin scales with the window instead of only ever meaning something against the fixed
* {@link #HIGH_THRESHOLD_TOKENS} fallback.
*/
static final double HIGH_THRESHOLD_FRACTION = 2.0 / 3.0;
/** The only peer kind this reader understands ({@code Agent.agentType()}'s wire value). */
private static final String CLAUDE_AGENT_TYPE = "claude";
@@ -167,6 +172,17 @@ public final class LeadContextGauge {
* transcript format
*/
public Reading read(String configDir, String sessionId, String agentType) {
return read(configDir, sessionId, agentType, null);
}
/**
* @param effectiveWindowTokens the caller's resolved effective auto-compact window for this
* lead's own profile, or {@code null} when it cannot be resolved.
* HIGH fires at {@link #HIGH_THRESHOLD_FRACTION} of this value;
* {@code null} (or a non-positive value) falls back to the fixed
* {@link #HIGH_THRESHOLD_TOKENS}
*/
public Reading read(String configDir, String sessionId, String agentType, Long effectiveWindowTokens) {
if (sessionId == null || sessionId.isBlank()) {
return Reading.unknown();
}
@@ -182,12 +198,20 @@ public final class LeadContextGauge {
if (cached != null && now - cached.readAtMillis() < ttlMillis) {
return cached.reading();
}
Reading fresh = readUncached(base, sessionId);
Reading fresh = readUncached(base, sessionId, highThreshold(effectiveWindowTokens));
cache.put(cacheKey, new CacheEntry(fresh, now));
return fresh;
}
private Reading readUncached(String base, String sessionId) {
/** {@link #HIGH_THRESHOLD_FRACTION} of {@code effectiveWindowTokens}, or the fixed fallback. */
private static long highThreshold(Long effectiveWindowTokens) {
if (effectiveWindowTokens == null || effectiveWindowTokens <= 0) {
return HIGH_THRESHOLD_TOKENS;
}
return (long) (effectiveWindowTokens * HIGH_THRESHOLD_FRACTION);
}
private Reading readUncached(String base, String sessionId, long highThreshold) {
diskReads.incrementAndGet();
Path file = findTranscript(base, sessionId);
if (file == null) {
@@ -199,7 +223,7 @@ public final class LeadContextGauge {
} catch (IOException e) {
return Reading.unknown();
}
return parse(tail);
return parse(tail, highThreshold);
}
/**
@@ -258,7 +282,7 @@ public final class LeadContextGauge {
* read raced — see the "torn final line" section of the class javadoc) is skipped, not fatal.
* Only when none of the remaining lines parse does this report {@link State#UNKNOWN}.
*/
private Reading parse(TailRead tail) {
private Reading parse(TailRead tail, long highThreshold) {
String text = new String(tail.bytes(), StandardCharsets.UTF_8);
List<String> lines = new ArrayList<>(List.of(text.split("\n", -1)));
if (!lines.isEmpty() && lines.get(lines.size() - 1).isEmpty()) {
@@ -299,7 +323,7 @@ public final class LeadContextGauge {
if (tokens == null) {
return new Reading(State.UNKNOWN, null, compactions);
}
State state = tokens >= HIGH_THRESHOLD_TOKENS ? State.HIGH : State.OK;
State state = tokens >= highThreshold ? State.HIGH : State.OK;
return new Reading(state, tokens, compactions);
}
@@ -284,10 +284,23 @@ public final class FleetMcp {
* no profile, or that profile sets no {@code configDir} override — either
* way {@link LeadContextGauge} then falls back to its own built-in default,
* exactly as before this ticket
* @param windowFor lead name → that lead's profile's effective auto-compact window (see
* {@code dev.ltms.fleet.config.FleetConfig.Profile
* #effectiveAutoCompactWindow()}), or {@code null} when it cannot be
* resolved — either way {@link LeadContextGauge} falls back to its own
* fixed HIGH threshold
*/
public record LeadConfigDirSource(Function<String, String> configDirFor) {
/** Inert source — every lead reads {@link LeadContextGauge}'s built-in default {@code configDir}. */
public static LeadConfigDirSource none() { return new LeadConfigDirSource(_ -> null); }
public record LeadConfigDirSource(Function<String, String> configDirFor, Function<String, Long> windowFor) {
/** Inert source — every lead reads {@link LeadContextGauge}'s built-in defaults. */
public static LeadConfigDirSource none() { return new LeadConfigDirSource(_ -> null, _ -> null); }
/**
* Constructor that resolves no window — every lead this source answers for keeps
* {@link LeadContextGauge}'s fixed HIGH threshold.
*/
public LeadConfigDirSource(Function<String, String> configDirFor) {
this(configDirFor, _ -> null);
}
}
/**
@@ -2153,7 +2166,8 @@ public final class FleetMcp {
m.put("self", true);
}
String configDir = leadConfigDirs.configDirFor().apply(name);
m.put("context", contextView(contextGauge, live, configDir));
Long effectiveWindow = leadConfigDirs.windowFor().apply(name);
m.put("context", contextView(contextGauge, live, configDir, effectiveWindow));
return m;
}
@@ -2163,12 +2177,15 @@ public final class FleetMcp {
* {@code fleet.leaders.<name>.profile} → that profile's own {@code configDir:} — or {@code null}
* when the lead's entry names no profile, or that profile sets no override, in which case
* {@link LeadContextGauge#read} falls back to its own built-in default
* ({@code <user.home>/.claude}).
* ({@code <user.home>/.claude}). {@code effectiveWindowTokens} is the same lead's resolved
* auto-compact window, or {@code null} when it cannot be resolved, in which case the gauge
* falls back to its own fixed HIGH threshold instead.
*/
private static Map<String, Object> contextView(LeadContextGauge contextGauge, Agent live, String configDir) {
private static Map<String, Object> contextView(LeadContextGauge contextGauge, Agent live, String configDir,
Long effectiveWindowTokens) {
String sessionId = live == null ? null : live.sessionId();
String agentType = live == null ? null : live.agentType();
LeadContextGauge.Reading reading = contextGauge.read(configDir, sessionId, agentType);
LeadContextGauge.Reading reading = contextGauge.read(configDir, sessionId, agentType, effectiveWindowTokens);
Map<String, Object> c = new LinkedHashMap<>();
c.put("state", reading.state().name().toLowerCase());
if (reading.tokens() != null) {
@@ -461,9 +461,9 @@ public final class LeadHeartbeatLoop {
.append(reading.compactions()).append(' ').append(compactionWord).append(" so far.");
} else {
// A HIGH reading always carries a non-null token count today: LeadContextGauge only
// reaches HIGH by comparing a number against HIGH_THRESHOLD_TOKENS. That invariant
// lives in another class and nothing asserts it, so this branch does not rely on it —
// it drops the token clause rather than printing "null tokens".
// reaches HIGH by comparing a number against a threshold. That invariant lives in
// another class and nothing asserts it, so this branch does not rely on it — it drops
// the token clause rather than printing "null tokens".
sb.append(" (").append(reading.compactions()).append(' ').append(compactionWord)
.append(" so far).");
}
@@ -0,0 +1,96 @@
package dev.ltms.fleet;
import dev.ltms.fleet.config.FleetConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
* {@link Fleetd#leadContextWindowLookup} is the factory wired into {@code
* FleetMcp.LeadConfigDirSource} and {@code LeadHeartbeatLoop.LeadContextSource} so {@link
* dev.ltms.fleet.lead.LeadContextGauge} scales its HIGH threshold against a lead's own profile's
* effective auto-compact window instead of always the gauge's fixed fallback — the same {@code
* fleet.leaders.<name>.profile} link {@link Fleetd#leadConfigDirLookup} already follows, one step
* further to {@link FleetConfig.Profile#effectiveAutoCompactWindow()}.
*/
class FleetdLeadContextWindowLookupTest {
private static FleetConfig.Profile profileWithWindow(String name, Integer autoCompactWindow,
Map<String, String> env) {
return new FleetConfig.Profile(name, null, "claude-sonnet-5", null, null, null,
"tab", "fleet", "w #{n}", null, null, null, null, null, null, env,
null, null, true, null, null, null, null, null, autoCompactWindow, null);
}
private static FleetConfig.Leader leadOnProfile(String profile) {
return new FleetConfig.Leader(profile, "lead: primary", 1, "lead:", 10, "claude", "claude-sonnet-5");
}
@Test
@DisplayName("a lead on a profile that sets autoCompactWindow resolves to that window")
void leadOnAProfileWithAutoCompactWindowResolvesToIt() {
Map<String, FleetConfig.Profile> profiles =
Map.of("opus", profileWithWindow("opus", 250_000, Map.of()));
Map<String, FleetConfig.Leader> leaders = Map.of("primary", leadOnProfile("opus"));
Function<String, Long> lookup = Fleetd.leadContextWindowLookup(() -> profiles, leaders);
assertEquals(250_000L, lookup.apply("primary"));
}
@Test
@DisplayName("yaml and env disagree: the lookup resolves the env value, not the yaml one")
void yamlAndEnvDisagreeLookupResolvesTheEnvValue() {
Map<String, FleetConfig.Profile> profiles = Map.of("opus",
profileWithWindow("opus", 250_000, Map.of("CLAUDE_CODE_AUTO_COMPACT_WINDOW", "150000")));
Map<String, FleetConfig.Leader> leaders = Map.of("primary", leadOnProfile("opus"));
Function<String, Long> lookup = Fleetd.leadContextWindowLookup(() -> profiles, leaders);
assertEquals(150_000L, lookup.apply("primary"));
}
@Test
@DisplayName("a lead entry with no `profile:` resolves to null, not a thrown exception")
void recogniseOnlyLeadWithNoProfileResolvesToNull() {
Map<String, FleetConfig.Profile> profiles =
Map.of("opus", profileWithWindow("opus", 250_000, Map.of()));
FleetConfig.Leader recogniseOnly = new FleetConfig.Leader(null, "lead: primary", 1, "lead:", 10,
"claude", "claude-sonnet-5");
Map<String, FleetConfig.Leader> leaders = Map.of("primary", recogniseOnly);
Function<String, Long> lookup = Fleetd.leadContextWindowLookup(() -> profiles, leaders);
assertNull(lookup.apply("primary"));
}
@Test
@DisplayName("a lead naming a profile that is not configured resolves to null, not a thrown exception")
void leadOnAnUnconfiguredProfileResolvesToNull() {
Map<String, FleetConfig.Leader> leaders = Map.of("primary", leadOnProfile("ghost-profile"));
Function<String, Long> lookup = Fleetd.leadContextWindowLookup(Map::of, leaders);
assertNull(lookup.apply("primary"));
}
@Test
@DisplayName("a lead on a profile that resolves no window at all resolves to null")
void leadOnAProfileWithNoWindowResolvesToNull() {
Map<String, FleetConfig.Profile> profiles =
Map.of("opus", profileWithWindow("opus", null, Map.of()));
Map<String, FleetConfig.Leader> leaders = Map.of("primary", leadOnProfile("opus"));
Function<String, Long> lookup = Fleetd.leadContextWindowLookup(() -> profiles, leaders);
assertNull(lookup.apply("primary"));
}
@Test
@DisplayName("an unrecognised lead name resolves to null, not a thrown exception")
void unrecognisedLeadNameResolvesToNull() {
Function<String, Long> lookup = Fleetd.leadContextWindowLookup(Map::of, Map.of());
assertNull(lookup.apply("ghost-lead"));
}
}
@@ -0,0 +1,65 @@
package dev.ltms.fleet.config;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
* {@link FleetConfig.Profile#effectiveAutoCompactWindow()} resolves the window a launched Claude
* Code session actually runs on, not just the {@code autoCompactWindow:} launch flag — {@code env:
* CLAUDE_CODE_AUTO_COMPACT_WINDOW} overrides that flag, so a profile setting both resolves from the
* environment variable.
*/
class FleetConfigProfileEffectiveAutoCompactWindowTest {
private static FleetConfig.Profile profile(Integer autoCompactWindow, Map<String, String> env) {
return new FleetConfig.Profile("sonnet", null, "claude-sonnet-5", null, null, null,
"tab", "fleet", "w #{n}", null, null, null, null, null, null, env,
null, null, true, null, null, null, null, null, autoCompactWindow, null);
}
@Test
@DisplayName("yaml and env disagree: the env var wins, not the yaml key")
void yamlAndEnvDisagreeEnvWins() {
FleetConfig.Profile p = profile(250_000, Map.of("CLAUDE_CODE_AUTO_COMPACT_WINDOW", "150000"));
assertEquals(150_000, p.effectiveAutoCompactWindow(),
"the two inputs must give DIFFERENT thresholds (150,000 vs 250,000) and the env value must win");
}
@Test
@DisplayName("only autoCompactWindow set: that value resolves")
void onlyAutoCompactWindowSetResolvesToIt() {
FleetConfig.Profile p = profile(250_000, Map.of());
assertEquals(250_000, p.effectiveAutoCompactWindow());
}
@Test
@DisplayName("only the env var set: that value resolves")
void onlyEnvVarSetResolvesToIt() {
FleetConfig.Profile p = profile(null, Map.of("CLAUDE_CODE_AUTO_COMPACT_WINDOW", "150000"));
assertEquals(150_000, p.effectiveAutoCompactWindow());
}
@Test
@DisplayName("neither set: resolves to null")
void neitherSetResolvesToNull() {
FleetConfig.Profile p = profile(null, Map.of());
assertNull(p.effectiveAutoCompactWindow());
}
@Test
@DisplayName("an unparseable env value falls back to autoCompactWindow rather than throwing")
void unparseableEnvValueFallsBackToAutoCompactWindow() {
FleetConfig.Profile p = profile(250_000, Map.of("CLAUDE_CODE_AUTO_COMPACT_WINDOW", "not-a-number"));
assertEquals(250_000, p.effectiveAutoCompactWindow());
}
}
@@ -0,0 +1,91 @@
package dev.ltms.fleet.lead;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@code LeadContextGauge}'s HIGH threshold scales with the caller's resolved effective
* auto-compact window, so the margin it warns at makes sense against a window that can legally sit
* as low as {@code 100_000}, not only against the fixed fallback. These properties pin that
* scaling, its boundary, and the fallback used when no window is resolvable.
*/
class LeadContextGaugeHighThresholdTest {
private static final String SESSION_ID = "55555555-5555-5555-5555-555555555555";
private static String usageLine(long tokens) {
return "{\"type\":\"assistant\",\"message\":{\"role\":\"assistant\",\"usage\":{"
+ "\"input_tokens\":" + tokens + ",\"cache_read_input_tokens\":0,\"cache_creation_input_tokens\":0}}}";
}
private static String writeTranscript(Path configDir, String sessionId, long tokens) throws IOException {
Path projectDir = configDir.resolve("projects").resolve("some-project-slug");
Files.createDirectories(projectDir);
Files.writeString(projectDir.resolve(sessionId + ".jsonl"), usageLine(tokens) + "\n", StandardCharsets.UTF_8);
return configDir.toString();
}
@Test
@DisplayName("an effective window of 100000 reports HIGH strictly below 100000")
void effectiveWindowOf100000ReportsHighStrictlyBelow100000(@TempDir Path tmp) throws IOException {
// 90,000 is below the 100,000 window itself, but above a fixed 200,000 fallback would ever
// reach — only a threshold that scales with the window can report HIGH here.
String configDir = writeTranscript(tmp, SESSION_ID, 90_000);
LeadContextGauge gauge = new LeadContextGauge();
LeadContextGauge.Reading reading = gauge.read(configDir, SESSION_ID, "claude", 100_000L);
assertEquals(LeadContextGauge.State.HIGH, reading.state(),
"90,000 tokens against a 100,000 effective window must already be HIGH, with margin to spare "
+ "before a compaction at the window itself");
}
@Test
@DisplayName("the boundary sits strictly between OK and HIGH on both sides")
void boundarySitsStrictlyBetweenOkAndHighOnBothSides(@TempDir Path tmp) throws IOException {
long window = 100_000L;
long threshold = (long) (window * (2.0 / 3.0)); // 66,666
String belowConfigDir = writeTranscript(tmp.resolve("below"), SESSION_ID, threshold - 1);
LeadContextGauge belowGauge = new LeadContextGauge();
assertEquals(LeadContextGauge.State.OK,
belowGauge.read(belowConfigDir, SESSION_ID, "claude", window).state(),
"one token short of the threshold must stay OK");
String atConfigDir = writeTranscript(tmp.resolve("at"), SESSION_ID, threshold);
LeadContextGauge atGauge = new LeadContextGauge();
assertEquals(LeadContextGauge.State.HIGH,
atGauge.read(atConfigDir, SESSION_ID, "claude", window).state(),
"exactly at the threshold must already be HIGH");
}
@Test
@DisplayName("with no effective window resolvable, the threshold is still the fixed 200000 default")
void noEffectiveWindowFallsBackToTheFixed200000Default(@TempDir Path tmp) throws IOException {
String belowConfigDir = writeTranscript(tmp.resolve("below"), SESSION_ID, 199_999);
LeadContextGauge belowGauge = new LeadContextGauge();
assertEquals(LeadContextGauge.State.OK,
belowGauge.read(belowConfigDir, SESSION_ID, "claude", null).state(),
"one token short of the fixed default must stay OK when no window is resolvable");
String atConfigDir = writeTranscript(tmp.resolve("at"), SESSION_ID, 200_000);
LeadContextGauge atGauge = new LeadContextGauge();
assertEquals(LeadContextGauge.State.HIGH,
atGauge.read(atConfigDir, SESSION_ID, "claude", null).state(),
"the fixed default must still be 200,000 when no window is resolvable");
String legacyConfigDir = writeTranscript(tmp.resolve("legacy"), SESSION_ID, 200_000);
LeadContextGauge legacyGauge = new LeadContextGauge();
assertEquals(LeadContextGauge.State.HIGH,
legacyGauge.read(legacyConfigDir, SESSION_ID, "claude").state(),
"the 3-arg read() (no window argument at all) must behave exactly like passing a null window");
}
}