iter-101: daemon session correctness — re-watch, concurrent clients, type-aware buffer, --since parity#141
Merged
Merged
Conversation
Theme A — target-switch re-watch: branch on is_top_level in
handle_target_event; on a cross-process top-level switch, purge the
destroyed target's stale buffered resources via
ResourceBuffer::purge_destroyed_target. Tab-scoped watchResources makes
per-target re-watch implicit (documented in kb/rdp/actors/watcher.md).
Theme B — concurrent-client safety: replace eager RPC-writer-slot claim
with lazy claiming (try_claim_rpc_slot); a second concurrent client that
tries to forward gets a structured daemon_busy frame and is not
forwarded, so RDP responses never cross-deliver. Route daemon-local
responses to the requesting client's own connection. recv_reply_from /
recv_event_from surface a daemon control-error frame promptly. Delete the
unused DemuxReader / split_demux / Packet pub API and the _demux decoy.
Theme C — type-aware buffering: ResourceBuffer tracks per-type counts and
evicts type-aware with a TYPE_RESERVED_FLOOR so a network burst cannot
evict console/error entries below their floor.
Theme D — --since parity: one-shot network --since fails with
AppError::Unsupported { error_type: "since_requires_daemon" } instead of
a silent no-op; --since -1 parses via allow_hyphen_values.
Theme E — atomic registry + parity tests: Registry::register uses the
DashMap entry API so a concurrent invalidate_target cannot revive a dead
actor; add e2e error-shape/exit-code parity (connection-refused) daemon
vs --no-daemon.
Tests: unit_registry_register_atomic_no_revive, unit_buffer_eviction_per_type,
unit_concurrent_clients_no_cross_delivery, top_level_switch_purges_buffer,
recv_reply_from_surfaces_daemon_busy_control_error,
e2e_network_since_no_daemon_explicit, e2e_error_shape_parity_daemon.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…idelity Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
iter-101 deleted the dead DemuxReader/split_demux/Packet pub API (425 lines) from transport.rs, shifting the two production .expect()/request() line citations in iter-102's plan (450-453 -> 433-436, 480 -> 463). Corrected against the current file so check-firefox-refs style line citations stay accurate when iter-102 starts.
… iter-101 review test (windows-latest) fails 5 tests (install_skill::* x4, nav_action:: reload_wait_idle_no_traffic_returns_idle_quickly) on PR #141, but neither failing file is touched by iter-101's diff and the identical failures reproduce on prior unrelated branches (iter-100, iter-100b CI runs before iter-101 existed) — confirmed pre-existing, not a regression. Tracked as its own plan per the iteration-99 precedent rather than blocking this PR.
…-sweep) main gained kb/iterations/iteration-107-post-105-live-sweep.md (a different, unrelated plan) between when this branch was cut and now. Renumber the Windows-CI-preexisting-reds plan filed in the previous commit to the next free slot to avoid a duplicate iteration-107.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the daemon session-correctness gaps from the 2026-07 deep review. Five themes, all with deterministic unit/e2e coverage:
handle_target_eventnow branches onis_top_level; a cross-process top-level switch purges the destroyed target's stale buffered resources viaResourceBuffer::purge_destroyed_target. Tab-scopedwatchResourcesmakes per-target re-watch implicit — documented (with what the watcher does/does not re-deliver) inkb/rdp/actors/watcher.md.try_claim_rpc_slot) only when a client forwards its first Firefox-bound message; a second concurrent client gets a structureddaemon_busyframe and is not forwarded, so RDP responses (no correlation IDs) can never cross-deliver. Stream-only--followclients never touch the slot. Daemon-local responses now route to the requesting client's own connection.recv_reply_from/recv_event_fromsurface afrom:"daemon"control-error promptly instead of hanging. The unusedDemuxReader/split_demux/Packetpub API and the_demuxdecoy that gamedcheck-dead-primitivesare deleted.ResourceBuffertracks per-type counts and evicts type-aware with aTYPE_RESERVED_FLOOR(500) so a network burst can't evict console/error entries below their floor. The floor is a soft reservation (a single type can still fill the buffer).--sinceparity. One-shotnetwork --sincenow fails loudly withAppError::Unsupported { error_type: "since_requires_daemon" }(exit 1) instead of a silent no-op; the refusal fires before any connection opens.--since -1parses as space-separated viaallow_hyphen_values.Registry::registeruses theDashMap::entryAPI so a concurrentinvalidate_targetcan no longer revive a dead actor. Addede2e_error_shape_parity_daemonasserting byte-identicalerror_type/exit code (connection-refused) daemon vs--no-daemon.Design decisions recorded in the plan: busy over queue for Theme B; delete the DemuxReader pub API for Theme B task 2.
Carry-over (live cross-process follow test + extended daemon error-parity scenarios) filed as
kb/iterations/iteration-102-daemon-live-coverage.md.Test plan
cargo fmt --checkcleancargo clippy --workspace --all-targets -- -D warningscleancargo test --workspacegreen (1551 tests, 0 failures)check-iteration-ready10/10 PASS (withFF_RDP_LIVE_TESTS=1)unit_registry_register_atomic_no_revive— hammer register/invalidate from two threads + observer asserting monotonic-deathunit_buffer_eviction_per_type— 50 console msgs survive a 10× MAX_EVENTS network floodunit_concurrent_clients_no_cross_delivery+recv_reply_from_surfaces_daemon_busy_control_errortop_level_switch_purges_buffer— purge only on a genuine cross-process switche2e_network_since_no_daemon_explicit— exits 1 withsince_requires_daemon, no results payloade2e_error_shape_parity_daemon— identical error shape daemon vs--no-daemonlive_daemon_follow_survives_cross_process_nav(Firefox-only)🤖 Generated with Claude Code## Claims vs code
<generated 2026-07-09T11:42:40Z by ralph-loop>
ResourceBuffer::purge_destroyed_target→ ✅ matched in diffAppError::Unsupported→ ✅ matched in diffRegistry::register→ ✅ matched in diffTYPE_RESERVED_FLOOR→ ✅ matched in difftarget-switch→ ✅ matched in diff