Compositor-to-Rust reveal stream: host and QEMU checkpoint
Source branch impl/card-reveal-stream, based on 99ac8e48cc3147a736fb7ba2366bb0cb6eb0b9d9.
Sender revisions ea920846ae44d602c21953b0cbb97f2289662590 and
e185c9d7ee9314688a9dce3ffe9c5a6de0e4c4ae implement the compositor
sender and runtime fixture. The Rust client owns
the separately developed receiver/rendering half. The existing coherent-shell
tasks 1.1, 1.2, 2.1, 4.2 and 4.4 still require integrated runtime and board
proof; no task is completed by this host check.
SWAY_K230_CARD_REVEAL_STREAM=1 opts the touch-first card route into one
nonblocking Unix stream per bottom drawer or top shade gesture. The configured
SWAY_K230_CARD_SURFACE_SOCKET must equal
$XDG_RUNTIME_DIR/k230-shell-rust.sock; the runtime directory must be owned
and private and the socket must be owned, mode 0600. Without this flag the
fixed-argv SWAY_K230_CARD_SURFACE_HELPER route remains the separate rollback
behavior. The stream never forks a helper on each movement.
Each newline JSON message is at most 128 bytes with exact bounded fields:
{"v":1,"kind":"reveal","surface":"drawer","phase":"update","seq":123,"progress":350}
surface is drawer or shade; phase is begin, update, finish, or
cancel; seq is unique per gesture stream. Progress is an integer 0–1000
following vertical travel, including reversal. A qualified release sends
finish target 1000; an early release sends target 0. The client settles from
the latest update. The compositor owns touch classification, live app/deck
pixels, and focus; the Rust client owns only its transparent overlay pixels
and local settle. Its layer can map during tracking with an empty input region;
the card adapter keeps that same layer above live cards without treating its
own reveal as a takeover. Once settled open, the normal overlay gate applies.
Writes and connection checks are nonblocking. A bounded current frame, latest coalesced update, and terminal frame preserve begin→latest update→finish/cancel order under backpressure; no unbounded motion queue forms. A connection or write failure closes the stream, drains the owned contact and leaves the live app/deck scene available. EOF after a complete terminal message is normal for the client; EOF before it is a client-side cancel. The host test covers exact fields, frame bounds, sequence separation, private socket rejection, and an idle finger pause longer than the connection/write deadline.
Commands and results from the exact sender revision:
python3 tests/test_card_shell_reveal.py PASS 1 native stream/socket case
python3 tests/test_card_shell_route.py PASS 1 fixed-helper regression case
python3 tests/test_card_shell_chrome.py PASS 1 chrome case
python3 tests/test_card_shell_state.py PASS 25 native policy cases
git diff --check PASS
nix build .#card-shell --max-jobs 1 --cores 4 --no-link --print-out-paths
PASS /nix/store/13mxaxxmldpmcx418d6cq9bjvcc72ifb-k230-card-shell
CARD_SHELL_SWAY=/nix/store/6a0jd8i6sg8ix6j9mkhz72wnb4h5diyg-sway-unwrapped-riscv64-unknown-linux-gnu-1.12/bin/sway CARD_SHELL_CLIENT=/nix/store/6nskh3ldk3ya7mwxbb258qszrxhw2i61-card-composition-probe-client-0.1/bin/card-composition-probe-client python3 tests/test_card_shell_touch_first_runtime.py
PASS 1 actual cross-built Sway under headless QEMU
The QEMU test observed three separate streams (drawer finish open, shade
finish closed after reversal, shade second-contact cancel), no per-motion
helper invocation, and an actual k230-shell-drawer layer painted above the
live card during tracking. The sender’s built unwrapped Sway is the ELF path
above; the card package’s .sway-wrapped is a shell script and cannot be
passed directly to qemu-riscv64-static. The fixture uses a native socket
collector and magenta layer fixture, not the Rust receiver. Build log:
/tmp/k230-card-reveal-build.log; retained local headless log:
/tmp/k230-card-reveal-e185-qemu/sway.log. These /tmp files are local
diagnostics, not committed artifacts.
Remaining gates: integrated Rust client mapping and captured pixels on begin, intermediate movement, reversal, and settle; client disconnect, source-unmap/privacy and keyboard ownership tests; then reserved real-finger/panel presentation and existing frame CPU/cadence budgets. The current QEMU test proves stream semantics and overlay stacking, not Rust pixels, actual output presentation, physical touch, or final shell acceptance.