Repository navigation
perf(desktop): route a group round to the members it concerns - #98610
andredezzy wants to merge 1 commit into
Conversation
Overall: Performance routing: group round now wakes only domain-relevant members instead of whole room, saving model calls. Correctness:
Non-blocking nits:
Verdict: LGTM. |
|
A follow-up adversarial review found two routing failures in the first revision. Substring matching treated Commit Verified: 10 routing tests passed, including the reproduced travel/review false positive and a non-LifeOS coordinator; ESLint and TypeScript passed. |
|
Nice measurement — 8% of model time spent producing I want to check a scope boundary before I write anything that would collide with this. In #95163 I've been scoping backend-hosted group rooms, and one of the open direction questions there (Q2) is where "who answers an unmentioned round" should live. Your PR answers that question client-side with domain-vocabulary matching. There's also #93003, which answers it client-side by falling back to a default owner. Do you see vocabulary matching and designated-owner routing as one feature or two? My read is that they're different mechanisms that could compose — vocabulary matching narrows the roster, an owner catches what matches nothing — but they'd both be selecting in If you consider selection yours, I'll stay out of One thing you may not have hit yet: #103298 (opened today) also rewrites the round loop, for reload durability. Worth a look before you rebase. |
|
I see vocabulary matching and designated-owner routing as separate policies that should share one responder-selection point. This PR owns the relevance filter. Please take the no-match fallback; I am not reserving My preferred order is explicit mentions / I read #95163, #93003, and #103298. Hosted-room execution and reload recovery can reuse the selection contract while keeping their lifecycle state separate. #103298 remains open, so I will not pull its unmerged round-loop changes into this PR. The current revision uses whole-word matching and explicit prefixes; I corrected the stale substring description above. |
A room drives every member on every round, so a six-bot room pays six model calls for a question aimed at one specialist; the other five spend a full call to answer "(pass)". Measured on my own rooms, that was 8% of model time. resolveGroupResponders already narrows the round when the user @-mentions someone. This extends the same seam to the unmentioned case: match each member's domain vocabulary against the text since the last user message, and drive only the members whose domain appears. Two properties keep a wrong guess cheap rather than silent: - No match wakes the whole room, so a question the table does not recognise is never routed into the void. - The coordinator stays in every narrowed round, so a miss is handed to whoever owns the task and costs a round instead of an answer. Stems are matched as whole words. Substring matching read "review" as the Notion term "view"; intentional stems are listed explicitly instead.
daa6402 to
b70ce40
Compare
|
Rebased onto current What changed in the port: the relevance filter goes back inside Rechecked on
@angel12 — the boundary we agreed still holds: this PR owns the vocabulary filter, the no-match fallback is yours. The fallback here is deliberately the crudest thing that cannot lose a message (no match wakes the whole room, and the coordinator stays in every narrowed round), so replacing it should not require touching this code path. CI has never run on this PR; all three workflows expired awaiting approval. Happy to rebase again whenever a maintainer has a window. |
…d driver The branch was 1444 commits behind. The conflicting hunks were the ones already resolved on the fork today, so rerere replayed them: upstream's groupChatRoomKey import sits beside getGroupChatLimits, and its failedMembers field beside the limits carried on the drive context. Routing (NousResearch#98610) deliberately stays out — these are two separate policies and each PR owns one.
|
Thanks @andredezzy — declining this one on design grounds rather than quality: Bot Mode group rounds are serial round-robin by design, and routing a round to a subset of members changes who sees what, which the standing ruling keeps fixed (a faster round never licenses changing visibility or order). Latency work that keeps every member in the loop is welcome. Closing. |
The cost
A group room with no @-mention wakes every member. Each specialist then pays a full model call to conclude the question is not its domain and answer
(pass).The domain gate itself is right — a health bot should not opine on a Notion schema. But it fires after the API bill, not before. Measured across a live five-bot room:
Spent producing the word "(pass)".
Mentions are not the fix. Addressing a room by name on every message is exactly the ceremony a group chat exists to avoid, and the moment a user stops, the whole roster wakes again.
The change
A round with no mention now selects members whose domain vocabulary appears in the round's text. A question naming databases and blocks reaches the Notion specialist; one naming training and sleep reaches health.
Matching uses complete words, with explicit prefixes for inflected terms. Ambiguous Notion vocabulary requires two matches;
notionalone is sufficient. A domain-neutral coordinator joins a matched round so it can redirect the task.Why a wrong guess stays cheap
Relevance is a heuristic over words, so the design assumes it will sometimes miss:
@mentionsand@everyoneare untouched — an explicit address still selects exactly who was named.Tests
Six cases covering both directions: mentions still win, a domain question routes to its specialist and away from the others, the coordinator survives a wrong guess, an unrecognisable question still reaches everyone, and routing reads the whole exchange since the last user message rather than one line.
Verified on
origin/mainwith no other local changes.Scope note
The domain table lives next to the resolver as a plain constant. It could become configuration later, but shipping it as config first would be speculative — there is one consumer, and the right shape of that config is not yet known.