2525 run_headless_jsonl ,
2626 signal_canceller ,
2727)
28+ from python_agent_harness .entry .view import FilteredDeltaStream
29+ from python_agent_harness .io .text_filter import strip_final_check
2830from tests .support import (
2931 plan_cleanup , # noqa: F401,E402 (side-effect: auto-remove /tmp plan dirs)
3032 session_sandbox , # noqa: F401,E402 (side-effect: redirect SESSION_DIR)
@@ -478,19 +480,24 @@ def test_events_emitted_as_json_lines(self):
478480 self .assertEqual (
479481 lines [0 ], {"seq" : 1 , "type" : "start" , "prompt" : "do it" , "warnings" : ["w1" ]}
480482 )
481- self .assertEqual (lines [1 ], {"seq" : 2 , "type" : "delta" , "text" : "hello " })
483+ # "hello " streams as "hello": the delta filter holds trailing
484+ # whitespace (strip_final_check would rstrip it away if a
485+ # [FINAL CHECK] block followed) and releases it at the message
486+ # boundary below.
487+ self .assertEqual (lines [1 ], {"seq" : 2 , "type" : "delta" , "text" : "hello" })
488+ self .assertEqual (lines [2 ], {"seq" : 3 , "type" : "delta" , "text" : " " })
482489 self .assertEqual (
483- lines [2 ], {"seq" : 3 , "type" : "notify" , "kind" : "tool_start" , "data" : ["Read" ]}
490+ lines [3 ], {"seq" : 4 , "type" : "notify" , "kind" : "tool_start" , "data" : ["Read" ]}
484491 )
485492 self .assertEqual (
486- lines [3 ], {"seq" : 4 , "type" : "notify" , "kind" : "error" , "data" : "no quota" }
493+ lines [4 ], {"seq" : 5 , "type" : "notify" , "kind" : "error" , "data" : "no quota" }
487494 )
488- self .assertEqual (lines [4 ], {"seq" : 5 , "type" : "log" , "message" : "warming up" })
495+ self .assertEqual (lines [5 ], {"seq" : 6 , "type" : "log" , "message" : "warming up" })
489496 # the error seen during the run is reported on the result line
490497 self .assertEqual (
491- lines [5 ],
498+ lines [6 ],
492499 {
493- "seq" : 6 ,
500+ "seq" : 7 ,
494501 "type" : "result" ,
495502 "answer" : "Done." ,
496503 "errors" : ["no quota" ],
@@ -500,6 +507,113 @@ def test_events_emitted_as_json_lines(self):
500507 # each line is compact single-line JSON: no embedded newlines
501508 self .assertTrue (all ("\n " not in line for line in out .getvalue ().splitlines ()))
502509
510+ def test_delta_stream_filters_final_check_block (self ):
511+ """The [FINAL CHECK] block never reaches the delta stream, not even
512+ as a half-streamed prefix: the tail is withheld until the block is
513+ ruled out, so concatenated deltas equal the filtered answer."""
514+ out = io .StringIO ()
515+ view = JsonlView (out = out )
516+ view .emit_start ("p" , [])
517+ view .on_delta ("Done. " )
518+ view .on_delta ("\n \n [FINAL" )
519+ view .on_delta (" CHECK]\n - Goal: g\n - Status: SUCCESS\n - Evidence: e" )
520+ view .emit_result ("Done." )
521+ lines = self ._lines (out )
522+ deltas = [line ["text" ] for line in lines if line ["type" ] == "delta" ]
523+ # exactly what the TUI shows -- no "[FINAL" fragment leaks out
524+ self .assertEqual ("" .join (deltas ), "Done." )
525+ full = "Done. \n \n [FINAL CHECK]\n - Goal: g\n - Status: SUCCESS\n - Evidence: e"
526+ self .assertEqual ("" .join (deltas ), strip_final_check (full ))
527+
528+ def test_delta_stream_releases_tail_when_block_ruled_out (self ):
529+ """A header that never completes into a block is real content and
530+ must still be streamed (released when the message ends)."""
531+ out = io .StringIO ()
532+ view = JsonlView (out = out )
533+ view .emit_start ("p" , [])
534+ view .on_delta ("see the " )
535+ view .on_delta ("[final check] section" )
536+ view .emit_result ("x" )
537+ lines = self ._lines (out )
538+ deltas = [line ["text" ] for line in lines if line ["type" ] == "delta" ]
539+ self .assertEqual ("" .join (deltas ), "see the [final check] section" )
540+
541+ def test_delta_stream_holds_only_ambiguous_tail (self ):
542+ """Ordinary prose streams through unheld: a bracket that cannot
543+ start a header is not mistaken for a block in flight."""
544+ out = io .StringIO ()
545+ view = JsonlView (out = out )
546+ view .emit_start ("p" , [])
547+ view .on_delta ("line one\n " )
548+ view .on_delta ("see [1] and [2] here" )
549+ lines = self ._lines (out )
550+ deltas = [line ["text" ] for line in lines if line ["type" ] == "delta" ]
551+ self .assertEqual ("" .join (deltas ), "line one\n see [1] and [2] here" )
552+
553+ def test_delta_stream_resets_on_tool_start_and_retry (self ):
554+ """A message boundary starts a fresh filtered stream: the next
555+ message's [FINAL CHECK] must not be confused with the previous
556+ message's already-emitted text."""
557+ out = io .StringIO ()
558+ view = JsonlView (out = out )
559+ view .emit_start ("p" , [])
560+ view .on_delta ("First answer." )
561+ view .on_notify ("tool_start" , ["Bash" ])
562+ view .on_delta (
563+ "Second answer.\n \n [FINAL CHECK]\n - Goal: g\n - Status: SUCCESS\n - Evidence: e"
564+ )
565+ view .emit_result ("x" )
566+ lines = self ._lines (out )
567+ deltas = [line ["text" ] for line in lines if line ["type" ] == "delta" ]
568+ self .assertEqual ("" .join (deltas ), "First answer.Second answer." )
569+
570+ def test_delta_stream_retry_discards_partial (self ):
571+ out = io .StringIO ()
572+ view = JsonlView (out = out )
573+ view .emit_start ("p" , [])
574+ view .on_delta ("partial " )
575+ view .on_notify ("retry" )
576+ view .on_delta ("fresh start" )
577+ view .emit_result ("x" )
578+ lines = self ._lines (out )
579+ deltas = [line ["text" ] for line in lines if line ["type" ] == "delta" ]
580+ self .assertEqual ("" .join (deltas ), "partial fresh start" )
581+
582+ def test_delta_stream_parity_holds_for_every_chunk_split (self ):
583+ """The invariant: concatenating the emitted chunks equals
584+ strip_final_check over the whole message, whatever the network
585+ chose as chunk boundaries. Checked exhaustively for every single
586+ split point plus the char-by-char worst case, because the leak
587+ this guards against only appears at specific boundaries (a
588+ half-streamed header, a decoration run before one)."""
589+ messages = [
590+ "Done. \n \n [FINAL CHECK]\n - Goal: g\n - Status: SUCCESS\n - Evidence: e" ,
591+ "A.\n \n **[FINAL CHECK]**\n - **Goal**: g\n - **Status**: s\n - **Evidence**: e" ,
592+ "A.\n \n ## Final Check\n Goal: g\n Status: s\n Evidence: e" ,
593+ "a\n \n > **[FINAL CHECK]**\n > Goal: g\n > Status: s\n > Evidence: e" ,
594+ "a\n \n > \n [FINAL CHECK]\n Goal: g\n Status: s\n Evidence: e" ,
595+ "s**[FINAL CHECK]**Goal: g Status: s Evidence: e" ,
596+ "[FINAL CHECK]\n - Goal: g\n - Status: s\n - Evidence: e" , # check-only
597+ "see the [final check] section" , # header that never completes
598+ "let me do the final check now" ,
599+ "line one\n see [1] and [2] here" ,
600+ "use 2 * 3 and a_b and #1 in prose" ,
601+ ]
602+ for msg in messages :
603+ want = strip_final_check (msg )
604+ # every single split point, and one chunk per character
605+ splits = [[i ] for i in range (1 , len (msg ))] + [list (range (1 , len (msg )))]
606+ for cuts in [[]] + splits :
607+ stream = FilteredDeltaStream ()
608+ parts , prev = [], 0
609+ for cut in cuts :
610+ parts .append (msg [prev :cut ])
611+ prev = cut
612+ parts .append (msg [prev :])
613+ got = "" .join (stream .feed (p ) for p in parts ) + stream .flush ()
614+ with self .subTest (msg = msg [:30 ], cuts = cuts [:3 ]):
615+ self .assertEqual (got , want )
616+
503617 def test_events_before_start_are_buffered_behind_start_line (self ):
504618 """The worker starts before emit_start runs, so early events must
505619 be buffered and flushed after start — start is always first."""
@@ -515,11 +629,15 @@ def test_events_before_start_are_buffered_behind_start_line(self):
515629 view .emit_result ("ok" )
516630 lines = [json .loads (line ) for line in out .getvalue ().splitlines () if line ]
517631 self .assertEqual (lines [0 ]["type" ], "start" )
518- self .assertEqual (lines [1 ], {"seq" : 2 , "type" : "delta" , "text" : "early " })
632+ # trailing whitespace is held by the delta filter and released at
633+ # the tool_start boundary, so "early " arrives as two deltas --
634+ # buffering preserves their order behind the start line
635+ self .assertEqual (lines [1 ], {"seq" : 2 , "type" : "delta" , "text" : "early" })
636+ self .assertEqual (lines [2 ], {"seq" : 3 , "type" : "delta" , "text" : " " })
519637 self .assertEqual (
520- lines [2 ], {"seq" : 3 , "type" : "notify" , "kind" : "tool_start" , "data" : ["Bash" ]}
638+ lines [3 ], {"seq" : 4 , "type" : "notify" , "kind" : "tool_start" , "data" : ["Bash" ]}
521639 )
522- self .assertEqual (lines [3 ], {"seq" : 4 , "type" : "delta" , "text" : "live" })
640+ self .assertEqual (lines [4 ], {"seq" : 5 , "type" : "delta" , "text" : "live" })
523641 self .assertEqual (lines [- 1 ]["type" ], "result" )
524642
525643 def test_concurrent_emit_and_start_never_corrupts_stream (self ):
0 commit comments