a73x

c3ecb3b9

test(e2e): the session's OSC 52 reaches the host terminal

a73x   2026-08-15 16:27

Commit message
test(e2e): the session's OSC 52 reaches the host terminal

The discovery measurement inverted — same instrument, same grep, 0 to 1.
The session writes the escape from a file so it can never arrive as the
shell's echo of a typed line, and the marker beside it is the positive
control: it separates a broken passthrough from a session that never ran.

Verified falsifiable by removing the engine's interception and watching
this scenario, and only this scenario, fail.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

test/e2e.sh
Old New
@@ -770,6 +770,10 @@ cleanup() {
770 "$OUT.as" "$OUT.as.err" "$OUT.as2" "$OUT.as2.err" \ 770 "$OUT.as" "$OUT.as.err" "$OUT.as2" "$OUT.as2.err" \
771 "$OUT.stop" "$OUT.stop2" \ 771 "$OUT.stop" "$OUT.stop2" \
772 "$OUT.pa" "$OUT.pa.err" "$OUT.pa.log" 772 "$OUT.pa" "$OUT.pa.err" "$OUT.pa.log"
773 # The side-channel leg: its capture, the fixture's log, and the script
774 # the session runs. Spelled from $OUT rather than from a variable of its
775 # own, for the reason the M12 controls above are.
776 rm -f "$OUT.clip" "$OUT.clip.err" "$OUT.clip.log" "$OUT.clip.sh"
773 # M14 handoff. The shim, both runtime dirs (each holding its daemon's 777 # M14 handoff. The shim, both runtime dirs (each holding its daemon's
774 # socket), the second key, the unusable config home, and the five 778 # socket), the second key, the unusable config home, and the five
775 # captures. 779 # captures.
@@ -2673,6 +2677,61 @@ PAPID=""
2673 rm_swept "$OUT.pa" "$OUT.pa.err" "$OUT.pa.log" "$OUT.stop" 2677 rm_swept "$OUT.pa" "$OUT.pa.err" "$OUT.pa.log" "$OUT.stop"
2674 ok "local mux auto-start under the pty fixture" 2678 ok "local mux auto-start under the pty fixture"
2675 2679
2680 # --- side channel: an OSC 52 written by the session reaches the HOST tty --
2681 #
2682 # Measured ABSENT on 2026-08-15 (decisions.md, that date): a session emitted
2683 # this exact escape, and the bytes the client wrote to its host terminal
2684 # carried one \x1b[?1049h, one \x1b[?2026h, one marker — and zero of the
2685 # clipboard escape. The daemon's engine had parsed all of it; a client that
2686 # paints a grid forwards nothing that is not grid state. This is the same
2687 # instrument (the fixture's capture is what a host terminal would have
2688 # received) taking the same reading with the path built, and it is the first
2689 # end-to-end evidence that any of it does anything.
2690 #
2691 # The payload is emitted by a FILE the session runs, never typed. The shell
2692 # echoes what is typed, so a needle that could arrive as an echo would pass
2693 # on a client that forwards nothing at all — the M12 rule (tp2), and here it
2694 # is the difference between an assertion and a decoration. The typed line
2695 # names the script and cannot spell the escape.
2696 cat > "$OUT.clip.sh" <<'CLIPSH'
2697 printf '\033]52;c;aGVsbG8gZnJvbSB0aGUgc2Vzc2lvbg==\007'
2698 printf 'CLIPDONE\n'
2699 CLIPSH
2700 # Unquoted heredoc, unlike every other pty script in this file: the send
2701 # verb has to carry $OUT's per-run path. Nothing else in it needs expanding
2702 # — `\n` and `\x1c` are not escapes the shell touches.
2703 set +e
2704 timeout 40 "$PTYCLIENT" --cols 80 --rows 24 --out "$OUT.clip" --err "$OUT.clip.err" \
2705 -- "$MUX" --sock "$SOCK" > "$OUT.clip.log" 2>&1 <<EOF
2706 expect \x1b[?1049h 15000
2707 settle 400 15000
2708 send sh $OUT.clip.sh\n
2709 expect CLIPDONE 15000
2710 settle 400 15000
2711 send \x1c
2712 waitexit 10000
2713 EOF
2714 RC=$?
2715 set -e
2716 [ "$RC" -eq 0 ] || {
2717 echo "e2e FAIL: clipboard scenario did not run: ptyclient exited $RC"
2718 cat "$OUT.clip.log"; cat -v "$OUT.clip.err" 2>/dev/null; exit 1; }
2719 # The positive control, and it is not redundant with the check below: the
2720 # marker travels the ordinary grid path, so a capture holding it is a
2721 # capture of a session that RAN. Without it, "no escape" and "no session"
2722 # are the same failure line.
2723 grep -qa 'CLIPDONE' "$OUT.clip" || {
2724 echo "e2e FAIL: the session never ran (no marker on the host)"; exit 1; }
2725 # Terminator included: the client builds the escape whole or writes nothing
2726 # at all (client.zig, appendTermEvent), and a needle stopping at the payload
2727 # could not tell a complete escape from half of one left painting on the
2728 # user's tty. -F because the needle is bytes, not a pattern.
2729 CLIPESC=$(printf '\033]52;c;aGVsbG8gZnJvbSB0aGUgc2Vzc2lvbg==\007')
2730 grep -qaF "$CLIPESC" "$OUT.clip" || {
2731 echo "e2e FAIL: OSC 52 never reached the host tty"; exit 1; }
2732 rm_swept "$OUT.clip" "$OUT.clip.err" "$OUT.clip.log" "$OUT.clip.sh"
2733 ok "the session's OSC 52 reaches the host terminal"
2734
2676 # --- M14: the ssh→QUIC handoff ----------------------------------------- 2735 # --- M14: the ssh→QUIC handoff -----------------------------------------
2677 # 2736 #
2678 # `mux HOST` fetches QUIC coordinates over ssh once, caches them, and 2737 # `mux HOST` fetches QUIC coordinates over ssh once, caches them, and
@@ -3678,16 +3737,17 @@ DPID=""
3678 3737
3679 # The pins. Literals, not variables set from counting something else — 3738 # The pins. Literals, not variables set from counting something else —
3680 # "assert the literal, never the constant the code under test reads" 3739 # "assert the literal, never the constant the code under test reads"
3681 # (decisions.md, M10). 26 scenario checkpoints; 35 convergence points. 3740 # (decisions.md, M10). 27 scenario checkpoints; 35 convergence points.
3682 # Anyone adding a scenario updates these by hand, on purpose. 3741 # Anyone adding a scenario updates these by hand, on purpose.
3683 # 3742 #
3684 # M18 added three checkpoints and no convergence points: its wall block 3743 # M18 added three checkpoints and no convergence points: its wall block
3685 # asserts through assert_ws_converged, which is deliberately outside 3744 # asserts through assert_ws_converged, which is deliberately outside
3686 # CONV_COUNT (see its comment) — that pin counts assert_converged call 3745 # CONV_COUNT (see its comment) — that pin counts assert_converged call
3687 # sites, and folding the two together would make either number stop 3746 # sites, and folding the two together would make either number stop
3688 # meaning anything. 3747 # meaning anything. The side-channel leg added the 27th and no convergence
3689 [ "$OK_COUNT" = "26" ] || { 3748 # point: its capture is asserted on for a byte the grid does not carry.
3690 echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 26 —" 3749 [ "$OK_COUNT" = "27" ] || {
3750 echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 27 —"
3691 echo " a scenario was added (update the pin) or silently lost" 3751 echo " a scenario was added (update the pin) or silently lost"
3692 exit 1 3752 exit 1
3693 } 3753 }
@@ -3695,4 +3755,4 @@ DPID=""
3695 echo "e2e FAIL: $CONV_COUNT convergence points ran, the pin says 35" 3755 echo "e2e FAIL: $CONV_COUNT convergence points ran, the pin says 35"
3696 exit 1 3756 exit 1
3697 } 3757 }
3698 echo "e2e OK (26 scenarios, 35 convergence points)" 3758 echo "e2e OK (27 scenarios, 35 convergence points)"