protocol, cli: pin the frozen-surface corners a pre-release review left open #354
No reviewers
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis!354
Loading…
Reference in a new issue
No description provided.
Delete branch "protocol/issue-347-cheap-before-freeze"
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?
Closes #347.
Items 1, A, B and C of the issue were moved to #351 by the 2026-09-22 triage; this PR carries items 2–6 only.
What changed
Item 2 — the
_UNSPECIFIEDmode branch. The handshake description indocs/reference/ipc.mdnow names which sideof the unknown-mode split each value falls on: a nonzero value the daemon does not define is the newer peer's and earns
Refused { UnknownMode }, while theCONNECTION_MODE_UNSPECIFIEDsentinel0is malformed and takes the corruptionpath.
No new test was needed. The behavior the issue asked to pin is already pinned:
an_unreadable_hello_that_is_not_a_future_mode_closes_unansweredincrates/felis-daemon/src/serve/tests.rsdrives ahand-encoded
Hellowith mode0and asserts the daemon closes without writing a frame, beside the value-9 test thatpins the typed refusal. The issue's premise ("whether the daemon takes the typed-refusal path or the corruption path is
unpinned") holds for the documentation, not for the tests.
Item 3 — the
ConnEnd.countcriterion. TheEnd { stream_id, count }bullet now sorts a new frame by the request:only the values it asked for are results, while an acknowledgement, a loss marker or a family trailer escorts them
without joining the count, a trailer included when it carries data
Endhas no field for. That classifies all threeprecedents the bullet names, which asking whether a family-agnostic terminal would carry the frame did not.
Item 4 —
error.kindmay not narrow. The "Frozen forv:1" paragraph indocs/reference/cli.mdadds "ornarrowed", with the clause that says what that forbids.
Item 5 —
--timeout 0.0sets a deadline that has already passed, so nothing is waited for and the verb exits1undertimeout. That is what the code does today, on both flags the CLI epoch freezes:sessions send --wait --timeout 0: neither the admission confirmation nor the mark watch gets a chance to finish.Stated in the clap help and in the
sendbullet ofdocs/reference/cli.md, pinned bysend_wait_timeout_zero_gives_up_at_once.notifications subscribe --once --timeout 0: the subscription waits for no notification, and the stream's terminalis an error object of kind
timeout. Stated in that flag's clap help and its cli.md bullet, pinned bynotifications_once_timeout_zero_gives_up_at_once.The help-page insta snapshot was regenerated for both.
Both waits check the deadline before reaching for a frame rather than only racing it.
tokio::time::timeout_atpollsits inner future before an expired timer, so a daemon that answered the subscribe with its ack and a notification in
one flush left
--timeout 0printing that notification and exiting0.drain_frames(the mark watch) alreadyguarded this way; the notification loop and the admission confirmation now do too.
notifications_timeout_zero_outranks_an_already_readable_notificationpins it with a fake daemon that puts bothframes in the reader's read-ahead before the CLI polls, and fails on the pre-fix code.
No schema change:
felis-cli-v1.schema.jsonmentionstimeoutonly as anerror.kindtoken, andSessionsSendParamsin the bridge schema carriessession,textandraw— the bridge has no wait, so it has notimeout input to annotate.
Item 6 — why relay payload version
0is malformed. The reference now gives the reason the explanation doc holds:the version word is how a writer that predates it is told apart, and such a writer puts its entry count where the
version belongs with a zero high half.
Verified
just fmt-check— cleanjust lint(clippy, workspace, all targets, all features) — cleanjust prose-check— 0 hitsjust docs-links— 1234 OK, 0 errorscargo nextest run --all-features -p felis-daemon -p felis-cli— 918 passed, 7 skippednotifications_timeout_zero_outranks_an_already_readable_notification50 timesout of 50; with the guard it passes 50 out of 50.
--timeout,UnknownModeand the count criterion acrossdocs/,skills/,README.md:no other page restates them.
notifications subscribe --timeout 0the waysessions senddefines it