client-core: map each grid message to its renderer effect #468

Merged
natsukium merged 1 commit from client-core-renderer-effect into main 2026-09-26 01:25:47 +09:00
Owner

Closes #442.

Why

Every frontend that draws a felis session mirrors some grid messages into its renderer (theme/palette overrides, the rehydrate-time color reset, reverse video), and each carried its own copy of that mapping. The copies had already drifted: felis-web-component's handles only theme colors, and felis-reel was about to become a third copy.

What

  • felis_client_core::renderer_effect::{RendererEffect, renderer_effect}: a pure const fn from &GridMsg to Option<RendererEffect>. It names every GridMsg variant and every ModeFlags field (no _, no ..), so a new message or mode flag fails to build until it is classified; this also closes the .. gap noted in the issue plan.
  • felis-client's event handler replaces its five inline arms with renderer_effect plus an exhaustive apply_renderer_effect; CursorState and Attention handling is unchanged.
  • Docs: architecture/overview.md (client-core seam: why data, not a trait) and reference/workspace.md (crate responsibilities).

The issue's second test ("felis-client routes through renderer_effect") is covered structurally instead: felis-client no longer has its own mapping, and its apply function matches RendererEffect exhaustively.

Verification

  • just check green. On the first run, felis-daemon serve::tests::force_detach_evicts_every_subscriber_and_keeps_the_session failed once at load average 12. It passed 8/8 in isolation and on the full rerun, and this change does not touch the daemon.
  • Unit tests pin the effect of each renderer-affecting message, including ModeFlags with every other flag set.
  • pi review (sol): PASS, no findings.
Closes #442. ## Why Every frontend that draws a felis session mirrors some grid messages into its renderer (theme/palette overrides, the rehydrate-time color reset, reverse video), and each carried its own copy of that mapping. The copies had already drifted: felis-web-component's handles only theme colors, and felis-reel was about to become a third copy. ## What - `felis_client_core::renderer_effect::{RendererEffect, renderer_effect}`: a pure `const fn` from `&GridMsg` to `Option<RendererEffect>`. It names every `GridMsg` variant and every `ModeFlags` field (no `_`, no `..`), so a new message or mode flag fails to build until it is classified; this also closes the `..` gap noted in the issue plan. - felis-client's event handler replaces its five inline arms with `renderer_effect` plus an exhaustive `apply_renderer_effect`; `CursorState` and `Attention` handling is unchanged. - Docs: `architecture/overview.md` (client-core seam: why data, not a trait) and `reference/workspace.md` (crate responsibilities). The issue's second test ("felis-client routes through `renderer_effect`") is covered structurally instead: felis-client no longer has its own mapping, and its apply function matches `RendererEffect` exhaustively. ## Verification - `just check` green. On the first run, `felis-daemon serve::tests::force_detach_evicts_every_subscriber_and_keeps_the_session` failed once at load average 12. It passed 8/8 in isolation and on the full rerun, and this change does not touch the daemon. - Unit tests pin the effect of each renderer-affecting message, including `ModeFlags` with every other flag set. - pi review (sol): PASS, no findings.
client-core: map each grid message to its renderer effect
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 15s
darwin / darwin docs-only no-op (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 16s
windows / windows docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 56s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Successful in 3m37s
windows / frontend smoke (Windows) (pull_request) Successful in 1m2s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Failing after 2m36s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m9s
pr / nix flake check (pull_request) Successful in 35s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m42s
pr / wire schema is compatible with the base (pull_request) Successful in 12s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 24s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Successful in 12s
3f367bde25
Every frontend that draws a felis session has to mirror some grid
messages into its renderer (theme and palette overrides, the
rehydrate-time color reset, reverse video), and each carried its own
copy of that mapping. The copies had already drifted: the web
component's handles only theme colors, in an older shape, and drops
palette, reset and reverse-video messages without an error.

`renderer_effect` in felis-client-core returns the effect as data, and
felis-client applies it with an exhaustive match. Data rather than a
renderer trait: the core cannot name a GPU renderer, and a trait defined
there could not be implemented for felis-render-wgpu's `Renderer` from a
frontend crate without a newtype in each. The function names every
`GridMsg` variant and every `ModeFlags` field, so a new message or a new
mode flag fails to build until someone decides whether the renderer
needs it.

Assisted-by: Claude Code
natsukium deleted branch client-core-renderer-effect 2026-09-26 01:25:47 +09:00
Commenting is not possible because the repository is archived.
No description provided.