@@ -991,6 +991,61 @@ it.layer(
991991 } ) ,
992992 ) ;
993993
994+ it . effect ( "strips replayable CSI and DCS traffic while preserving setters" , ( ) =>
995+ Effect . gen ( function * ( ) {
996+ const { manager, ptyAdapter } = yield * createManager ( ) ;
997+ yield * manager . open ( openInput ( ) ) ;
998+ const process = ptyAdapter . processes [ 0 ] ;
999+ expect ( process ) . toBeDefined ( ) ;
1000+ if ( ! process ) return ;
1001+
1002+ process . emitData ( "prompt " ) ;
1003+ // DECRQM/DECRPM, XTVERSION, and kitty-keyboard CSI query/reply traffic.
1004+ process . emitData ( "\u001b[?2026$p\u001b[?2026;2$y\u001b[>q\u001b[?u\u001b[?31u" ) ;
1005+ // DECRQSS and XTGETTCAP query/reply traffic in 7-bit DCS form.
1006+ process . emitData ( "\u001bP$q m\u001b\\\u001bP1$r0m\u001b\\" ) ;
1007+ process . emitData ( "\u001bP+q544e\u001b\\\u001bP1+r544e=1b\u001b\\" ) ;
1008+ // The same DCS traffic in 8-bit form.
1009+ process . emitData ( "\u0090$q m\u009c\u00901$r0m\u009c" ) ;
1010+ process . emitData ( "\u0090+q544e\u009c\u00901+r544e=1b\u009c" ) ;
1011+ // Setters and cursor movement share final bytes with query families but
1012+ // have visible terminal-state value and must survive replay.
1013+ process . emitData ( '\u001b[!p\u001b["p\u001b[4 q\u001b[u' ) ;
1014+ process . emitData ( "done\n" ) ;
1015+
1016+ yield * manager . close ( { threadId : "thread-1" } ) ;
1017+
1018+ const reopened = yield * manager . open ( openInput ( ) ) ;
1019+ assert . equal ( reopened . history , 'prompt \u001b[!p\u001b["p\u001b[4 q\u001b[udone\n' ) ;
1020+ } ) ,
1021+ ) ;
1022+
1023+ it . effect ( "handles CSI and DCS query sequences split across output chunks" , ( ) =>
1024+ Effect . gen ( function * ( ) {
1025+ const { manager, ptyAdapter } = yield * createManager ( ) ;
1026+ yield * manager . open ( openInput ( ) ) ;
1027+ const process = ptyAdapter . processes [ 0 ] ;
1028+ expect ( process ) . toBeDefined ( ) ;
1029+ if ( ! process ) return ;
1030+
1031+ process . emitData ( "before " ) ;
1032+ process . emitData ( "\u001b[?2026$" ) ;
1033+ process . emitData ( "pafter " ) ;
1034+ process . emitData ( "\u001bP$q " ) ;
1035+ process . emitData ( "m\u001b" ) ;
1036+ process . emitData ( "\\after " ) ;
1037+ process . emitData ( "\u009b?3" ) ;
1038+ process . emitData ( "1uafter " ) ;
1039+ process . emitData ( "\u0090+q544e" ) ;
1040+ process . emitData ( "\u009cafter\n" ) ;
1041+
1042+ yield * manager . close ( { threadId : "thread-1" } ) ;
1043+
1044+ const reopened = yield * manager . open ( openInput ( ) ) ;
1045+ assert . equal ( reopened . history , "before after after after after\n" ) ;
1046+ } ) ,
1047+ ) ;
1048+
9941049 it . effect (
9951050 "preserves clear and style control sequences while dropping chunk-split query traffic" ,
9961051 ( ) =>
0 commit comments