From f77ff3074d468d0d561603745c6a319efe99c5d5 Mon Sep 17 00:00:00 2001 From: Levi Neuwirth Date: Fri, 24 Jul 2026 14:02:25 -0400 Subject: [PATCH] test(vterm): write CRLF from the raw-mode probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The diagnostic added in the previous commit answered the question on its first macOS run: rendered prefix: 6/15 bytes ("VTERM_") — child text rendered only partially So the child wrote and the host received part of the marker, but stripping escapes did not rejoin the rest: other repainted cells sit between the two pieces, not just cursor moves. Six characters is exactly what fits before the right margin of this session's 40-column child. The probe writes bare `\n`, and the supervisor's PTY trampoline runs `stty raw`, which clears OPOST — so a lone `\n` moves down without returning to column 1 and every line staircases five columns right. After twenty lines the marker starts in the right margin, wraps mid-word, and reaches the host as two pieces that no contiguous match can join. That also explains the intermittency: the wrap column depends on whether pmacs has already resized the PTY from the requested 40 columns to the window width, which races the child's first writes. Write explicit carriage returns so every line returns to column 1 and the markers start there. The fixture was wrong about its own line discipline; the emulator was behaving correctly throughout. The escape-stripped matching and the rendered-prefix diagnostic from the previous commit are kept: they are what produced this answer, and they keep the next such failure legible. Test-only; no runtime code. Co-Authored-By: Claude Opus 5 (1M context) --- tests/vterm_stage2_acceptance.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/vterm_stage2_acceptance.rs b/tests/vterm_stage2_acceptance.rs index ff1737a..65bd9e8 100644 --- a/tests/vterm_stage2_acceptance.rs +++ b/tests/vterm_stage2_acceptance.rs @@ -735,12 +735,22 @@ fn real_tui_terminal_smoke_restores_host_after_output_input_resize_scroll_copy_a " data = b''\n", " while marker not in data:\n", " data += os.read(0, 4096)\n", + // CRLF, not bare LF. The supervisor's PTY trampoline runs + // `stty raw`, which clears OPOST, so a lone `\n` moves DOWN + // without returning to column 1 and every line staircases five + // columns right. Against this session's 40-column child that + // walks the readiness marker into the right margin, where it + // wraps mid-word and reaches the host as two pieces separated by + // other repainted cells — unmatchable, and intermittent because + // the column depends on whether pmacs has resized the PTY to the + // window width yet. Explicit carriage returns keep every write + // column-stable, so the markers below start at column 1. "os.write(1, b'\\x1b[?1049h\\x1b[2J')\n", - "for i in range(20): os.write(1, b'alt%02d\\n' % i)\n", + "for i in range(20): os.write(1, b'alt%02d\\r\\n' % i)\n", "os.write(1, b'VTERM_ALT_READY')\n", "read_until(b'ALT_GATE\\n')\n", "os.write(1, b'\\x1b[?1049l')\n", - "for i in range(40): os.write(1, b'main%02d\\n' % i)\n", + "for i in range(40): os.write(1, b'main%02d\\r\\n' % i)\n", "os.write(1, b'VTERM_MAIN_READY\\x07')\n", "data = read_exact(18)\n", "open({:?}, 'wb').write(data)\n",