Follow felis to 105b0899: the 1.0 wire reset, minor 10, and a daemon-free socket path #1
Loading…
Reference in a new issue
No description provided.
Delete branch "follow-felis-105b0899"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follows felis from
d563c5e5(2026-08-15) to105b089979369fd310757375af3df7900ae7e523.felis reset its wire-break baseline to 1.0 (
f56f5529) and has since carried the protocolminor to 10, so this is a rename-and-remove bump, not an additive one.
What felis changed, and what it forced here
ShadowGrid→ShadowScreen; the grid is reached throughscreen()and the hyperlink anchor table now lives on that screenpane.rs/keys.rs/compositor.rsrenamed;RowAnsiOptions.linksfed fromgrid.hyperlink_table(), and the "the anchor table is the shadow's, not the grid's" caveat deleted with the thing it warned aboutcodec::decodetakes the body alone, andFrameWriter::sendframes, gates and flushes in one callPaneno longer carries anEncodingor hand-rolls aFrame;sendis one lined3633c9a)sendCapabilitiesbitset → typedOfferOffer::window(false)(a host terminal has no vsync to pace a pull against, so the daemon eager-pushes); the roster peek offersOffer::ops()live_onlyrefuses a corpse (MINOR_LIVE_ONLY_ATTACH)first_sessionpicked the row itself, so the attach isAttachIntent::Automatice6a9d86b,88ee1b0c)first_sessionfilters!exited && idle_seconds.is_some(): an absentidle_secondsmeans attached elsewhere,exitedmeans a shell that will never answerMINOR_ATOMIC_CREATE) and carriesenv_base(MINOR_ENV_BASE)create_with(env_base::fill_for_local(SpawnArgs::default(), false)), mirroringfelis-client-core::dial— the daemon may have been auto-spawned from a login long past, and its own environment names the wrongSSH_AUTH_SOCKInputMsg::Resizetakes aRequestedDimsat wire widthapply_resizewidens tou32; the daemon clampsImageShadow::applyreturns aResult;virtual_placements()returns a slicedefault_socket_pathmoved tofelis-transport, wrapped byfelis-client-core::local_socket::resolve_local_socketfelis-daemondependency is dropped, not repointed (the manifest'sTODO(dep-trim)is resolved). Resolving throughlocal_socketalso reads theFELIS_SOCKETstamp, so a felis-tui launched inside a felis window now reaches the daemon that spawned it rather than the bare platform defaultTyped build identity (
5c22e3fe), operation ids, and theOpsSwitchscope fields need noadaptation: felis-tui neither reports a build nor drives a switch.
Also in here
fix(verify): scope the isolated daemon to its own socket path— a standalone fix aheadof the bump, and the reason it is first.
scripts/pty_verify.pyinheritedFELIS_SOCKET,which the socket resolver reads ahead of the
XDG_RUNTIME_DIRdefault, so a run startedinside a felis window attached to the user's own daemon despite the fresh runtime dir. Its
cleanup then filtered
felis-daemonprocesses on the basenamedaemon.sock— which everydaemon's argv contains — and
SIGTERMed them. Together that killed this host's productiondaemon three times before it was caught. Now the stamp is popped and the filter matches the
full isolated path.
ShadowGridin the prose, the moved felis doc paths, and the cross-host notethat claimed local image bytes travel over shm. They do not — felis's IPC boundary is the
socket, with no shared memory by design; shm is a producer→daemon Kitty transfer mode. That
contradiction is felis's own and is filed as natsukium/felis#194.
Verified
All four CI gates, through the flake dev shell, exactly as
.forgejo/workflows/ci.ymlruns them:End-to-end against a real felis-daemon built at the pinned rev
(
felis-daemon 0.1.0 (105b0899…), protocol1.10), on an isolated socket, never the user's:15/15 checks pass — status bar, pane labels, both separators, true-colour passthrough, OSC 8
hyperlinks, curly underline + underline colour, OSC 66 sized text, Kitty image transmit and
clipped placement, Unicode-placeholder placement, and sentinel suppression.
Three roster paths were then exercised by hand against that same isolated daemon, because the
harness only ever covers the cold-start create:
create_with→ one session,idle_seconds: 0.felis sessions spawn, then felis-tui: it attached theexisting row (the session's
rowswent 24 → 23 asapply_resizelanded on it) and creatednothing new.
felis sessions send <id> --key ctrl+d, roster shows"exited": true; felis-tui skipped that row and created a fresh live session, which is the!exitedfilter doing its job.The isolated daemon was stopped with
felis --socket <path> daemon stop; the host's owndaemons were confirmed alive before and after.
Open / not in this PR
packages.defaultyet: theTODO(package)inflake.nixstill stands, because abuildRustPackageneeds acargoLock.outputHashesentry per felis rev and the rev stillmoves.
Pushframes (Reattach,RetargetHost,Evicted).SessionExitedneedsno handling — a pane whose reader task ends is already pruned, and the last one quits — but a
felis switchaimed at a felis-tui pane is silently a no-op. Out of scope here; it is afeature, not a break.
MinorTooOldratherthan degraded. That is felis's own designed behaviour (
create_withis atomic-create only),shared with felis's GUI client, and is worth knowing if you point this build at a stale daemon.