@@ -76,3 +76,52 @@ async def test_prompt_below_threshold_does_not_consolidate(self, consolidator):
7676 consolidator .archive = AsyncMock (return_value = True )
7777 await consolidator .maybe_consolidate_by_tokens (session )
7878 consolidator .archive .assert_not_called ()
79+
80+ async def test_chunk_cap_preserves_user_turn_boundary (self , consolidator ):
81+ """Chunk cap should rewind to the last user boundary within the cap."""
82+ consolidator ._SAFETY_BUFFER = 0
83+ session = MagicMock ()
84+ session .last_consolidated = 0
85+ session .key = "test:key"
86+ session .messages = [
87+ {
88+ "role" : "user" if i in {0 , 50 , 61 } else "assistant" ,
89+ "content" : f"m{ i } " ,
90+ }
91+ for i in range (70 )
92+ ]
93+ consolidator .estimate_session_prompt_tokens = MagicMock (
94+ side_effect = [(1200 , "tiktoken" ), (400 , "tiktoken" )]
95+ )
96+ consolidator .pick_consolidation_boundary = MagicMock (return_value = (61 , 999 ))
97+ consolidator .archive = AsyncMock (return_value = True )
98+
99+ await consolidator .maybe_consolidate_by_tokens (session )
100+
101+ archived_chunk = consolidator .archive .await_args .args [0 ]
102+ assert len (archived_chunk ) == 50
103+ assert archived_chunk [0 ]["content" ] == "m0"
104+ assert archived_chunk [- 1 ]["content" ] == "m49"
105+ assert session .last_consolidated == 50
106+
107+ async def test_chunk_cap_skips_when_no_user_boundary_within_cap (self , consolidator ):
108+ """If the cap would cut mid-turn, consolidation should skip that round."""
109+ consolidator ._SAFETY_BUFFER = 0
110+ session = MagicMock ()
111+ session .last_consolidated = 0
112+ session .key = "test:key"
113+ session .messages = [
114+ {
115+ "role" : "user" if i in {0 , 61 } else "assistant" ,
116+ "content" : f"m{ i } " ,
117+ }
118+ for i in range (70 )
119+ ]
120+ consolidator .estimate_session_prompt_tokens = MagicMock (return_value = (1200 , "tiktoken" ))
121+ consolidator .pick_consolidation_boundary = MagicMock (return_value = (61 , 999 ))
122+ consolidator .archive = AsyncMock (return_value = True )
123+
124+ await consolidator .maybe_consolidate_by_tokens (session )
125+
126+ consolidator .archive .assert_not_awaited ()
127+ assert session .last_consolidated == 0
0 commit comments