Skip to content

feat(lib): router-side delivery-class filter on multi-room subscribe (the unused-fields perf fix) - #1362

Merged
joelteply merged 2 commits into
canaryfrom
feat/subscribe-delivery-filter
Aug 15, 2026
Merged

feat(lib): router-side delivery-class filter on multi-room subscribe (the unused-fields perf fix)#1362
joelteply merged 2 commits into
canaryfrom
feat/subscribe-delivery-filter

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

The filters existed in AttachRequest and the daemon router all along — the lib surface never exposed them on the multi-room subscribe, so every consumer attached unfiltered. Full measurements in the commit message. Backward compatible: existing callers unchanged (delegate with None); filter re-applied on every reconnect. First consumer is continuum's persona turn stream (Durable-only), which kills the decode-per-spam-event flood at the router.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo

joelteply and others added 2 commits August 15, 2026 12:08
… filter on the multi-room subscribe

AttachRequest has carried kinds/delivery/header filters since the router
grew them, and the daemon compiles them into the router (server.rs:530) —
but the lib's own multi-room subscribe surface never exposed them, so
every consumer attached unfiltered and paid a decode per event to discard
what it never wanted. Measured on a continuum node 2026-08-15: 6,736
events fanned to EVERY persona subscription in 40 minutes, 100% discarded
post-decode; an earlier solve measured 55% of inbound as peer StreamChunks
decoded identically by four minds (O(personas x tokens) in the attention
path).

- daemon_subscribe gains `delivery: Option<Vec<IpcDelivery>>`, applied on
  the initial attach AND every reconnect (a filter that silently vanished
  on the first daemon restart would re-open the flood with no signal).
- New public `subscribe_subscribed_delivery(filter, delivery)`;
  `subscribe_subscribed_filtered` delegates with None — behaviour
  unchanged for every existing caller.
- Non-daemon (in-process broadcast) fallback documented: EventFilter
  remains its only filter; there is no router to filter at.

First consumer: continuum's persona turn stream attaches with
[IpcDelivery::Durable] — a mind that perceives settled room lines stops
receiving peers' stream chunks and ephemeral fan-out at the ROUTER.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
…ter rides the daemon attach (#445 slice 2)

The daemon router has always applied AttachRequest.headers router-side
(server.rs compiles it into the fan-out Filter), but no lib path ever
set it — every subscription attached with HeaderFilter::Any — and the
combinator set had no exclusion shape, so the one thing the measured
spam case needs ('everything EXCEPT airc.heartbeat.*-stamped beacons',
149 of 177 inbound events on a continuum persona subscription) was
inexpressible.

- airc-core: HeaderFilter::Has { key } (presence) + Not(Box<..>)
  (inversion), arms in both matches() and matches_view(), pinned by
  the variant-agreement test + a dedicated exclusion/wire-round-trip
  test (the enum crosses IPC inside AttachRequest, so asymmetric
  serde would mis-filter daemon-side only).
- airc-lib: daemon_subscribe threads a HeaderFilter onto the initial
  AND reconnect attach (same discipline as the delivery filter — a
  filter that vanished on daemon restart would silently re-open the
  flood). subscribe_subscribed_delivery forwards the caller's
  EventFilter.headers_filter, which until now was client-side only.

Exclusion passes unstamped events by construction — Not(Has) is never
an allowlist, so consumers keep receiving everything publishers have
not classified yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
@joelteply
joelteply merged commit 574ce23 into canary Aug 15, 2026
12 checks passed
@joelteply
joelteply deleted the feat/subscribe-delivery-filter branch August 15, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant