@@ -108,9 +108,9 @@ get_new_session_from_output() {
108108}
109109
110110# Test 1: 6 messages (3 user, 3 assistant) -> 3 clean user msgs, skip 1, keep 2
111- # Starts at user message 2 (line 3), keeps lines 3-6 = 4 messages + 1 reference = 5
111+ # Output: marker(1) + kept lines 3-6(4) + reference(1) = 6
112112test_even_messages () {
113- log_test " 6 messages (3 clean user): should keep 4 lines + 1 reference = 5 "
113+ log_test " 6 messages (3 clean user): should produce 1 marker + 4 kept + 1 reference = 6 "
114114
115115 local session_id
116116 session_id=$( create_test_conversation 6)
@@ -128,17 +128,17 @@ test_even_messages() {
128128
129129 local count
130130 count=$( count_messages " $new_file " )
131- if [ " $count " -eq 5 ]; then
132- log_pass " Kept 5 messages (4 + reference)"
131+ if [ " $count " -eq 6 ]; then
132+ log_pass " Kept 6 messages (marker + 4 kept + reference)"
133133 else
134- log_fail " Expected 5 messages, got $count "
134+ log_fail " Expected 6 messages, got $count "
135135 fi
136136}
137137
138138# Test 2: 7 messages (4 user, 3 assistant) -> 4 clean user msgs, skip 2, keep 2
139- # Starts at user message 3 (line 5), keeps lines 5-7 = 3 messages + 1 reference = 4
139+ # Output: marker(1) + kept lines 5-7(3) + reference(1) = 5
140140test_odd_messages () {
141- log_test " 7 messages (4 clean user): should keep 3 lines + 1 reference = 4 "
141+ log_test " 7 messages (4 clean user): should produce 1 marker + 3 kept + 1 reference = 5 "
142142
143143 local session_id
144144 session_id=$( create_test_conversation 7)
@@ -151,17 +151,17 @@ test_odd_messages() {
151151
152152 local count
153153 count=$( count_messages " $new_file " )
154- if [ " $count " -eq 4 ]; then
155- log_pass " Kept 4 messages (3 + reference)"
154+ if [ " $count " -eq 5 ]; then
155+ log_pass " Kept 5 messages (marker + 3 kept + reference)"
156156 else
157- log_fail " Expected 4 messages, got $count "
157+ log_fail " Expected 5 messages, got $count "
158158 fi
159159}
160160
161161# Test 3: 4 messages (2 user, 2 assistant) -> 2 clean user msgs, skip 1, keep 1
162- # Starts at user message 2 (line 3), keeps lines 3-4 = 2 messages + 1 reference = 3
162+ # Output: marker(1) + kept lines 3-4(2) + reference(1) = 4
163163test_minimum_messages () {
164- log_test " 4 messages (2 clean user): should keep 2 lines + 1 reference = 3 "
164+ log_test " 4 messages (2 clean user): should produce 1 marker + 2 kept + 1 reference = 4 "
165165
166166 local session_id
167167 session_id=$( create_test_conversation 4)
@@ -174,10 +174,10 @@ test_minimum_messages() {
174174
175175 local count
176176 count=$( count_messages " $new_file " )
177- if [ " $count " -eq 3 ]; then
178- log_pass " Kept 3 messages (2 + reference)"
177+ if [ " $count " -eq 4 ]; then
178+ log_pass " Kept 4 messages (marker + 2 kept + reference)"
179179 else
180- log_fail " Expected 3 messages, got $count "
180+ log_fail " Expected 4 messages, got $count "
181181 fi
182182}
183183
@@ -335,19 +335,21 @@ test_double_tagging() {
335335 new_session=$( get_new_session_from_output " $output " )
336336 local new_file=" ${TEST_PROJECTS_DIR} /${TEST_PROJECT_DIRNAME} /${new_session} .jsonl"
337337
338- # Should have two [HALF-CLONE ...] tags - the new one prepended to the existing one
339- local first_user_line
340- first_user_line=$( grep ' "type":"user"' " $new_file " | head -1)
338+ # The first user line is the synthetic marker ("Continued from session ...").
339+ # The second user line is the first KEPT message from the original, which
340+ # already had a [HALF-CLONE] tag and should now have a second one prepended.
341+ local kept_user_line
342+ kept_user_line=$( grep ' "type":"user"' " $new_file " | grep -v " Continued from session" | head -1)
341343
342344 # Count occurrences of [HALF-CLONE pattern
343345 local tag_count
344- tag_count=$( echo " $first_user_line " | grep -oE ' \[HALF-CLONE [A-Z][a-z]+ [0-9]+ [0-9]+:[0-9]+\]' | wc -l | tr -d ' ' )
346+ tag_count=$( echo " $kept_user_line " | grep -oE ' \[HALF-CLONE [A-Z][a-z]+ [0-9]+ [0-9]+:[0-9]+\]' | wc -l | tr -d ' ' )
345347
346348 if [ " $tag_count " -eq 2 ]; then
347349 log_pass " Double tagging works - found 2 [HALF-CLONE] tags"
348350 else
349351 log_fail " Expected 2 [HALF-CLONE] tags, found $tag_count "
350- echo " First user line: $first_user_line "
352+ echo " Kept user line: $kept_user_line "
351353 fi
352354}
353355
@@ -397,6 +399,57 @@ test_thinking_blocks_stripped() {
397399 fi
398400}
399401
402+ # Test 11: Progress messages with nested "type":"user" should NOT count as clean user messages
403+ test_progress_with_nested_user_type () {
404+ log_test " Progress messages with nested type:user should not count as clean user messages"
405+
406+ local session_id
407+ session_id=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
408+ local conv_file=" ${TEST_PROJECTS_DIR} /${TEST_PROJECT_DIRNAME} /${session_id} .jsonl"
409+
410+ local uuid1 uuid2 uuid3 uuid4 uuid5 uuid6 uuid7 uuid8
411+ uuid1=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
412+ uuid2=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
413+ uuid3=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
414+ uuid4=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
415+ uuid5=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
416+ uuid6=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
417+ uuid7=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
418+ uuid8=$( uuidgen | tr ' [:upper:]' ' [:lower:]' )
419+
420+ # Conversation: U1, A1, progress(nested user), progress(nested user), U2, A2, U3 CORRECT, A3
421+ # Real clean user messages: U1, U2, U3 = 3. Skip 1, keep 2. Start at U2.
422+ # If progress counted: 5 "clean" msgs, skip 2, start at U2 (or worse, a progress line)
423+ # With the fix: 3 clean msgs, skip 1, start at U2 -> first real content is U2
424+ {
425+ generate_message " $uuid1 " " null" " $session_id " " user" " Question 1"
426+ generate_message " $uuid2 " " $uuid1 " " $session_id " " assistant" " Answer 1"
427+ # Progress messages with nested "type":"user" (simulates subagent Task progress)
428+ echo " {\" type\" :\" progress\" ,\" sessionId\" :\" ${session_id} \" ,\" data\" :{\" message\" :{\" type\" :\" user\" ,\" message\" :{\" role\" :\" user\" ,\" content\" :[{\" type\" :\" text\" ,\" text\" :\" subagent input\" }]}}},\" uuid\" :\" ${uuid3} \" ,\" timestamp\" :\" 2025-01-01T00:00:00.000Z\" }"
429+ echo " {\" type\" :\" progress\" ,\" sessionId\" :\" ${session_id} \" ,\" data\" :{\" message\" :{\" type\" :\" user\" ,\" message\" :{\" role\" :\" user\" ,\" content\" :[{\" type\" :\" text\" ,\" text\" :\" another subagent input\" }]}}},\" uuid\" :\" ${uuid4} \" ,\" timestamp\" :\" 2025-01-01T00:00:00.000Z\" }"
430+ generate_message " $uuid5 " " $uuid2 " " $session_id " " user" " Question 2"
431+ generate_message " $uuid6 " " $uuid5 " " $session_id " " assistant" " Answer 2"
432+ generate_message " $uuid7 " " $uuid6 " " $session_id " " user" " Question 3 CORRECT START"
433+ generate_message " $uuid8 " " $uuid7 " " $session_id " " assistant" " Answer 3"
434+ } > " $conv_file "
435+
436+ local output
437+ output=$( run_half_clone " $session_id " )
438+
439+ local new_session
440+ new_session=$( get_new_session_from_output " $output " )
441+ local new_file=" ${TEST_PROJECTS_DIR} /${TEST_PROJECT_DIRNAME} /${new_session} .jsonl"
442+
443+ # The output from the script should say "3" clean user messages
444+ if echo " $output " | grep -q " Total clean user messages in conversation: 3" ; then
445+ log_pass " Progress messages with nested type:user correctly excluded from count (3 clean, not 5)"
446+ else
447+ local actual_count
448+ actual_count=$( echo " $output " | grep " Total clean user messages" | grep -oE ' [0-9]+' )
449+ log_fail " Expected 3 clean user messages, script counted $actual_count "
450+ fi
451+ }
452+
400453# Main
401454main () {
402455 echo " ================================"
@@ -422,6 +475,7 @@ main() {
422475 test_history_entry
423476 test_double_tagging
424477 test_thinking_blocks_stripped
478+ test_progress_with_nested_user_type
425479
426480 echo " "
427481 echo " ================================"
0 commit comments