Add heavy-payload rendering-suppression feature flag for TUI-over-SSH #120

Open
opened 2026-09-05 00:20:10 +09:00 by natsukium · 1 comment
Owner

Migrated from docs/backlog.md (Deferred / Heavy-payload rendering-suppression bit).

Deferred on a missing measurement. An animation-suppression cap (and a possible graphics-pixel sibling) would let the daemon stop shipping image pixel data / animation frames to a subscriber that cannot render them (the heterogeneous-attach case a TUI client introduces). It lands as a feature flag, the third lane of the evolution policy, and not as a minor: a peer declines the stream rather than merely decoding it, which is exactly what an opt-in flag is for (ipc.md "Versioning"; its design record "Open extensibility considerations"). Correctness does not need it: a limited client already drops what its host cannot render (principle 3), so this is a pure bandwidth optimization. Gate it on a measured saving. The local cost to measure: a same-host TUI subscriber pays one socket copy per image, because daemon-to-client pixels are ImageMsg::Chunk frames copied into every window subscriber's socket — the only shm in felis is the Kitty t=s producer-to-daemon transfer, which ends at the image store. Wiring the bit before that copy (and the SSH-stdio equivalent) is measured would add a per-subscriber composer branch with nothing to show for it. Revisit when a real TUI client over --host lets the saving be measured.

Decision: feature flag (not minor) — peer opts out of the stream.

Revisit when a TUI client over --host exists and the bandwidth saving can be measured over SSH-stdio (and the same-host socket copy alongside it).

Refs: docs/reference/ipc.md Versioning, docs/explanation/architecture/ipc.md Open extensibility considerations. Premise corrected per #194 / #200.

Migrated from `docs/backlog.md` (Deferred / Heavy-payload rendering-suppression bit). > Deferred on a missing measurement. An animation-suppression cap (and a possible graphics-pixel sibling) would let the daemon stop shipping image pixel data / animation frames to a subscriber that cannot render them (the heterogeneous-attach case a TUI client introduces). It lands as a **feature flag**, the third lane of the evolution policy, and not as a minor: a peer *declines* the stream rather than merely decoding it, which is exactly what an opt-in flag is for ([ipc.md](reference/ipc.md) "Versioning"; [its design record](explanation/architecture/ipc.md) "Open extensibility considerations"). Correctness does not need it: a limited client already drops what its host cannot render (principle 3), so this is a pure bandwidth optimization. Gate it on a measured saving. The local cost to measure: a same-host TUI subscriber pays one socket copy per image, because daemon-to-client pixels are `ImageMsg::Chunk` frames copied into every window subscriber's socket — the only shm in felis is the Kitty `t=s` producer-to-daemon transfer, which ends at the image store. Wiring the bit before that copy (and the SSH-stdio equivalent) is measured would add a per-subscriber composer branch with nothing to show for it. Revisit when a real TUI client over `--host` lets the saving be measured. Decision: feature flag (not minor) — peer opts out of the stream. Revisit when a TUI client over `--host` exists and the bandwidth saving can be measured over SSH-stdio (and the same-host socket copy alongside it). Refs: `docs/reference/ipc.md` Versioning, `docs/explanation/architecture/ipc.md` Open extensibility considerations. Premise corrected per #194 / #200.
Author
Owner

Correction to the body above (from #194): the clause "locally, image bytes travel over shm and the waste is marginal" is false and always was. felis has no daemon→client shared-memory path; the only shm in the system is the Kitty t=s producer→daemon transfer, which ends at the daemon's image store. Daemon→client pixels are ImageMsg::Chunk frames copied into every window subscriber's socket.

So the deferral stands, but not because the same-host case is free: a same-host TUI subscriber that discards the pixels still pays one socket copy per image, a cost bounded by image size that nobody has measured. Read the body's deferral as "gate the flag on a measured saving", with two numbers to take rather than one — the SSH-stdio saving and the same-host copy.

Scope is unchanged; this issue stays open as it is. The docs are corrected on main by #194 (PR 203) (docs/explanation/architecture/ipc.md "Open extensibility considerations", docs/explanation/architecture/overview.md "No shared memory").

Correction to the body above (from #194): the clause "locally, image bytes travel over shm and the waste is marginal" is false and always was. felis has no daemon→client shared-memory path; the only shm in the system is the Kitty `t=s` producer→daemon transfer, which ends at the daemon's image store. Daemon→client pixels are `ImageMsg::Chunk` frames copied into every window subscriber's socket. So the deferral stands, but not because the same-host case is free: a same-host TUI subscriber that discards the pixels still pays one socket copy per image, a cost bounded by image size that nobody has measured. Read the body's deferral as "gate the flag on a measured saving", with two numbers to take rather than one — the SSH-stdio saving and the same-host copy. Scope is unchanged; this issue stays open as it is. The docs are corrected on `main` by #194 (PR 203) (`docs/explanation/architecture/ipc.md` "Open extensibility considerations", `docs/explanation/architecture/overview.md` "No shared memory").
Sign in to join this conversation.
No description provided.