@@ -936,7 +936,7 @@ describe("compaction governor", () => {
936936 } ) ;
937937} ) ;
938938
939- describe ( "provider-aware idle recompress (CL-8745 )" , ( ) => {
939+ describe ( "cache expiry never folds (CL-8914 )" , ( ) => {
940940 const MINUTE_MS = 60_000 ;
941941
942942 function ttlInferenceDone (
@@ -984,142 +984,48 @@ describe("provider-aware idle recompress (CL-8745)", () => {
984984 } as ReactorInboundEvent ;
985985 }
986986
987- test ( "fires past the provider TTL while under threshold, meter-only on empty" , ( ) => {
987+ test ( "idle pings past any provider cache window return null" , ( ) => {
988+ // The governor holds no TTL table: an unarmed idle re-entry never
989+ // produces a compact, whatever the provider's cache economics. Staleness
990+ // on the outgoing prompt is the anthropic-cache-prompt transform's job.
988991 let continuations = 0 ;
989992 let nowMs = 10_000_000 ;
990- const governor = createCompactionGovernor (
991- ( ) => continuations ++ ,
992- "" ,
993- [ ] ,
994- ( ) => nowMs ,
995- ) ;
996- governor . noteInferenceDone (
997- ttlInferenceDone (
998- { provider : "anthropic" , model : "claude-opus-4-6" } ,
999- false ,
1000- ) ,
1001- tenTurns ,
1002- ) ;
1003-
1004- // Inside the 5-minute Anthropic window: no fire.
1005- nowMs += 4 * MINUTE_MS ;
1006- expect (
1007- governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1008- ) . toBeNull ( ) ;
1009-
1010- // Past the window: the same fold as the threshold path (same compactor,
1011- // so the fresh tail stays raw) with an attributable reason.
1012- nowMs += MINUTE_MS + 1 ;
1013- expect (
1014- governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1015- ) . toBeNull ( ) ;
1016- expect ( continuations ) . toBe ( 0 ) ;
1017- } ) ;
1018-
1019- test ( "production LastCycleSource: anthropic fires at 5m, codex never does" , ( ) => {
1020- // Harness stamps { sourceId, provider, model } with a bare model, not
1021- // slash-form "anthropic/claude-opus-4-6". Anthropic's 5-minute window
1022- // must come from provider, not a dummy model string. Codex has no
1023- // published 5-minute expiry, so it must stay quiet past the old 10-minute
1024- // guess as well.
1025- let nowMs = 15_000_000 ;
1026- const clock = ( ) => nowMs ;
1027- const anthropic = createCompactionGovernor ( ( ) => undefined , "" , [ ] , clock ) ;
1028- const codex = createCompactionGovernor ( ( ) => undefined , "" , [ ] , clock ) ;
1029- anthropic . noteInferenceDone (
1030- ttlInferenceDone (
1031- { provider : "anthropic" , model : "claude-opus-4-6" } ,
1032- false ,
1033- ) ,
1034- tenTurns ,
1035- ) ;
1036- codex . noteInferenceDone (
1037- ttlInferenceDone (
1038- {
1039- sourceId : "codex/work" ,
1040- provider : "codex-responses" ,
1041- model : "gpt-5.6-luna" ,
1042- } ,
1043- false ,
1044- ) ,
1045- tenTurns ,
1046- ) ;
1047-
1048- nowMs += 5 * MINUTE_MS + 1 ;
1049- expect (
1050- anthropic . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1051- ) . toBeNull ( ) ;
1052- expect (
1053- codex . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1054- ) . toBeNull ( ) ;
1055-
1056- nowMs += 30 * MINUTE_MS ;
1057- expect (
1058- codex . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1059- ) . toBeNull ( ) ;
1060- } ) ;
1061-
1062- test ( "does not idle-recompress DeepSeek or ollama" , ( ) => {
1063- let nowMs = 20_000_000 ;
1064993 const clock = ( ) => nowMs ;
1065- const deepseek = createCompactionGovernor ( ( ) => undefined , "" , [ ] , clock ) ;
1066- const local = createCompactionGovernor ( ( ) => undefined , "" , [ ] , clock ) ;
1067- deepseek . noteInferenceDone (
1068- ttlInferenceDone ( "deepseek/deepseek-chat" , false ) ,
1069- tenTurns ,
1070- ) ;
1071- local . noteInferenceDone (
1072- ttlInferenceDone ( "ollama/llama3.1" , false ) ,
1073- tenTurns ,
1074- ) ;
1075-
1076- nowMs += 90 * MINUTE_MS ;
1077- expect (
1078- deepseek . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1079- ) . toBeNull ( ) ;
1080- expect (
1081- local . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1082- ) . toBeNull ( ) ;
1083- } ) ;
1084-
1085- test ( "production ollama LastCycleSource never fires cache-ttl-recompress" , ( ) => {
1086- // Harness stamps { sourceId, provider, model } with a bare model. Ollama is
1087- // buildOpenAISource: sourceId "ollama/default", provider openai-compatible,
1088- // Keying TTL off the bare model would miss the ollama sourceId. Local
1089- // inference stays disabled.
1090- let nowMs = 25_000_000 ;
1091- const governor = createCompactionGovernor (
1092- ( ) => undefined ,
1093- "" ,
1094- [ ] ,
1095- ( ) => nowMs ,
1096- ) ;
1097- governor . noteInferenceDone (
1098- ttlInferenceDone (
1099- {
1100- sourceId : "ollama/default" ,
1101- provider : "openai-compatible" ,
1102- model : "llama3" ,
1103- } ,
1104- false ,
1105- ) ,
1106- tenTurns ,
1107- ) ;
1108-
1109- nowMs += 5 * MINUTE_MS + 1 ;
1110- expect (
1111- governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1112- ) . toBeNull ( ) ;
1113- } ) ;
1114-
1115- test ( "stays inert with no observed cache write" , ( ) => {
1116- const governor = createCompactionGovernor ( ( ) => undefined ) ;
1117- expect (
1118- governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1119- ) . toBeNull ( ) ;
994+ const sources = [
995+ { provider : "anthropic" , model : "claude-opus-4-6" } ,
996+ {
997+ sourceId : "codex/work" ,
998+ provider : "codex-responses" ,
999+ model : "gpt-5.6-luna" ,
1000+ } ,
1001+ { provider : "deepseek" , model : "deepseek-chat" } ,
1002+ {
1003+ sourceId : "ollama/default" ,
1004+ provider : "openai-compatible" ,
1005+ model : "llama3" ,
1006+ } ,
1007+ { provider : "custom-proxy" , model : "unknown-model" } ,
1008+ ] ;
1009+ for ( const source of sources ) {
1010+ const governor = createCompactionGovernor (
1011+ ( ) => continuations ++ ,
1012+ "" ,
1013+ [ ] ,
1014+ clock ,
1015+ ) ;
1016+ governor . noteInferenceDone ( ttlInferenceDone ( source , false ) , tenTurns ) ;
1017+ expect (
1018+ governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1019+ ) . toBeNull ( ) ;
1020+ nowMs += 90 * MINUTE_MS ;
1021+ expect (
1022+ governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1023+ ) . toBeNull ( ) ;
1024+ }
1025+ expect ( continuations ) . toBe ( 0 ) ;
11201026 } ) ;
11211027
1122- test ( "defers to the armed threshold path while over threshold " , ( ) => {
1028+ test ( "an armed threshold fold is not disturbed by idle re-entry " , ( ) => {
11231029 let nowMs = 30_000_000 ;
11241030 const governor = createCompactionGovernor (
11251031 ( ) => undefined ,
@@ -1128,9 +1034,9 @@ describe("provider-aware idle recompress (CL-8745)", () => {
11281034 ( ) => nowMs ,
11291035 ) ;
11301036 governor . noteInferenceDone ( inferenceDone ( overThreshold ) , tenTurns ) ;
1131- // Fixture provider "p" has no TTL. Threshold arming still owns this session.
1037+ // Threshold arming owns the over-threshold session and fires at the tool
1038+ // pause; a message.received re-entry is not its trigger.
11321039 nowMs += 5 * MINUTE_MS + 1 ;
1133- // Threshold arming owns the over-threshold session: no TTL double-fold.
11341040 expect (
11351041 governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
11361042 ) . toBeNull ( ) ;
@@ -1139,11 +1045,10 @@ describe("provider-aware idle recompress (CL-8745)", () => {
11391045 ) . toBeNull ( ) ;
11401046 } ) ;
11411047
1142- test ( "fires cache-ttl-recompress in the hysteresis gap (over-threshold, no growth)" , ( ) => {
1143- // Characterization, not a bug: after a threshold compact, a post-compact
1144- // infer at the same usage clears `pending` via growth hysteresis, so the
1145- // threshold path no longer owns the session. Idle past the provider TTL
1146- // still folds — same window- and cap-bounded path as under-threshold.
1048+ test ( "the hysteresis gap does not fold on cache expiry" , ( ) => {
1049+ // After a threshold compact, a post-compact infer at the same usage
1050+ // clears `pending` via growth hysteresis — the exact re-entry where the
1051+ // removed TTL path used to fire.
11471052 let nowMs = 70_000_000 ;
11481053 const governor = createCompactionGovernor (
11491054 ( ) => undefined ,
@@ -1174,37 +1079,7 @@ describe("provider-aware idle recompress (CL-8745)", () => {
11741079 ) . toBeNull ( ) ;
11751080 } ) ;
11761081
1177- test ( "after threshold compact and gap TTL, growth-armed compact stays blocked until a tool_call" , ( ) => {
1178- // Threshold compact (consecutive=1) plus TTL fire in the hysteresis gap
1179- // (consecutive=2) fills the shared cap. Later growth that would re-arm
1180- // the threshold path stays blocked until a tool_call occupancy resets it.
1181- let nowMs = 80_000_000 ;
1182- const governor = createCompactionGovernor (
1183- ( ) => undefined ,
1184- "" ,
1185- [ ] ,
1186- ( ) => nowMs ,
1187- ) ;
1188- governor . noteInferenceDone (
1189- inferenceDone ( overThreshold , "" , "anthropic" ) ,
1190- tenTurns ,
1191- ) ;
1192- expect (
1193- governor . interceptActions ( toolDone ( ) , inferAction , capabilities ) ,
1194- ) . not . toBeNull ( ) ;
1195- expect ( governor . resumeAfterCompact ( emptyMessage ( ) ) ) . toBe ( "infer" ) ;
1196-
1197- governor . noteInferenceDone (
1198- inferenceDone ( overThreshold , "" , "anthropic" ) ,
1199- tenTurns ,
1200- ) ;
1201- nowMs += 5 * MINUTE_MS + 1 ;
1202- expect (
1203- governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1204- ) . toBeNull ( ) ;
1205- } ) ;
1206-
1207- test ( "does not fold under an outstanding tool batch, fires once it settles" , ( ) => {
1082+ test ( "an outstanding tool batch does not change idle re-entry" , ( ) => {
12081083 let continuations = 0 ;
12091084 let nowMs = 40_000_000 ;
12101085 const governor = createCompactionGovernor (
@@ -1221,7 +1096,6 @@ describe("provider-aware idle recompress (CL-8745)", () => {
12211096 expect (
12221097 governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
12231098 ) . toBeNull ( ) ;
1224- // The batch settles (threshold path uninvolved: under threshold).
12251099 expect (
12261100 governor . interceptActions ( toolDone ( ) , inferAction , capabilities ) ,
12271101 ) . toBeNull ( ) ;
@@ -1231,28 +1105,7 @@ describe("provider-aware idle recompress (CL-8745)", () => {
12311105 expect ( continuations ) . toBe ( 0 ) ;
12321106 } ) ;
12331107
1234- test ( "one fire per window, then the shared consecutive-compact cap stops the spiral" , ( ) => {
1235- let continuations = 0 ;
1236- let nowMs = 50_000_000 ;
1237- const governor = createCompactionGovernor (
1238- ( ) => continuations ++ ,
1239- "" ,
1240- [ ] ,
1241- ( ) => nowMs ,
1242- ) ;
1243- governor . noteInferenceDone (
1244- ttlInferenceDone ( "anthropic/claude-opus-4-6" , false ) ,
1245- tenTurns ,
1246- ) ;
1247-
1248- nowMs += 5 * MINUTE_MS + 1 ;
1249- expect (
1250- governor . interceptIdleContinuation ( emptyMessage ( ) , capabilities ) ,
1251- ) . toBeNull ( ) ;
1252- expect ( continuations ) . toBe ( 0 ) ;
1253- } ) ;
1254-
1255- test ( "a raced operator message past the TTL still folds, then re-infers" , ( ) => {
1108+ test ( "a raced operator message past the window does not fold" , ( ) => {
12561109 let continuations = 0 ;
12571110 let nowMs = 60_000_000 ;
12581111 const governor = createCompactionGovernor (
0 commit comments