IRC: the name list arrives whether or not it is wanted #156

Closed
opened 2026-09-10 15:45:07 -04:00 by Salastil · 2 comments
Owner

no-implicit-names is ratified and unrequested. It stops the server sending
RPL_NAMREPLY automatically on join, leaving the client to ask with NAMES when it
actually wants one.

Worth having on a client that joins many channels at once — autojoin on a busy account
means a burst of name lists for channels nobody has opened yet.

Done looks like: joining twenty channels does not fetch twenty member lists nobody
asked for.

Found by the 2026-09-10 coverage review, which measured IRC against the IRCv3
capability registry rather than against a feature list. moho requests 12 capabilities
plus SASL, covering 15 of the 25 client-relevant ratified extensions — WeeChat
supports around 35. This is one of the ten missing ones, filed separately because each
is independently doable.

`no-implicit-names` is ratified and unrequested. It stops the server sending `RPL_NAMREPLY` automatically on join, leaving the client to ask with `NAMES` when it actually wants one. Worth having on a client that joins many channels at once — autojoin on a busy account means a burst of name lists for channels nobody has opened yet. **Done looks like:** joining twenty channels does not fetch twenty member lists nobody asked for. Found by the 2026-09-10 coverage review, which measured IRC against the IRCv3 capability registry rather than against a feature list. moho requests 12 capabilities plus SASL, covering **15 of the 25 client-relevant ratified extensions** — WeeChat supports around 35. This is one of the ten missing ones, filed separately because each is independently doable.
Salastil added the featureprotocollow priority labels 2026-09-10 15:45:07 -04:00
Salastil removed the protocol label 2026-09-10 15:53:23 -04:00
Author
Owner

Left open deliberately while the other thirteen IRC tickets were done, because the honest version of this is bigger than the others and is worth deciding on rather than half-doing.

Both Libera and Ergo advertise no-implicit-names, so it is available. But requesting it and then sending NAMES on join anyway gains nothing at all — same traffic, same moment, just asked for rather than volunteered. The benefit in the ticket (joining twenty channels does not fetch twenty member lists nobody asked for) only arrives if the roster is fetched lazily: on join the channel gets no member list, and NAMES plus the WHO from #148 are sent when a conversation is actually opened.

That is a real behaviour change rather than a capability: the daemon would need a notion of a buffer being looked at, which it does not currently have — getBacklog is the closest thing and is not quite the same question. Worth doing, worth doing on purpose.

One thing that changed underneath this while the others were done: capabilities are now negotiated from CAP LS rather than requested blindly, so adding this one is a single line once the lazy-roster question is settled.

Left open deliberately while the other thirteen IRC tickets were done, because the honest version of this is bigger than the others and is worth deciding on rather than half-doing. Both Libera and Ergo advertise `no-implicit-names`, so it is available. But requesting it and then sending `NAMES` on join anyway gains nothing at all — same traffic, same moment, just asked for rather than volunteered. The benefit in the ticket (joining twenty channels does not fetch twenty member lists nobody asked for) only arrives if the roster is fetched **lazily**: on join the channel gets no member list, and `NAMES` plus the `WHO` from #148 are sent when a conversation is actually opened. That is a real behaviour change rather than a capability: the daemon would need a notion of a buffer being *looked at*, which it does not currently have — `getBacklog` is the closest thing and is not quite the same question. Worth doing, worth doing on purpose. One thing that changed underneath this while the others were done: capabilities are now negotiated from `CAP LS` rather than requested blindly, so adding this one is a single line once the lazy-roster question is settled.
Author
Owner

Done in nobilis 8927d11 — the lazy version, since the cheap one gains nothing.

The roster is now asked for when a conversation is opened rather than when the channel is joined, and no-implicit-names is what stops the server volunteering the half it owns. An account that autojoins twenty channels was fetching twenty member lists at connect — and, since #148 landed, twenty WHOs beside them — every one about a room nobody had looked at.

It hangs off requestMemberList, which already meant exactly this: Discord answers it from the other direction, because it only sends a member list for the channel being looked at. The two services now share one moment with one meaning.

Once per channel per connection; after that the roster keeps itself current from the joins, parts, nick and mode changes that arrive anyway, and a reconnect clears the marks because a rejoin is a different set of people.

One ordering bug worth naming: the asked mark goes after the check for a live connection, not before. A conversation can be opened while its account is still connecting — the buffer exists in scrollback and the socket does not — and marking it asked there would have spent the one chance to ask on a connection that could not carry it.

Verified against testnet.ergo.chat. Before opening, the roster held only what the JOIN revealed and carried no rank; after opening, the rank was there — NAMES arriving on open rather than on join. The empty prefix beforehand is itself the proof the server had stopped volunteering one: without the capability it would have sent it regardless.

Done in nobilis [8927d11](https://git.salastil.com/Salastil/nobilis/commit/8927d11) — the lazy version, since the cheap one gains nothing. The roster is now asked for when a conversation is **opened** rather than when the channel is joined, and `no-implicit-names` is what stops the server volunteering the half it owns. An account that autojoins twenty channels was fetching twenty member lists at connect — and, since #148 landed, twenty WHOs beside them — every one about a room nobody had looked at. It hangs off `requestMemberList`, which already meant exactly this: Discord answers it from the other direction, because it only sends a member list for the channel being looked at. The two services now share one moment with one meaning. Once per channel per connection; after that the roster keeps itself current from the joins, parts, nick and mode changes that arrive anyway, and a reconnect clears the marks because a rejoin is a different set of people. One ordering bug worth naming: the *asked* mark goes after the check for a live connection, not before. A conversation can be opened while its account is still connecting — the buffer exists in scrollback and the socket does not — and marking it asked there would have spent the one chance to ask on a connection that could not carry it. **Verified against testnet.ergo.chat.** Before opening, the roster held only what the JOIN revealed and carried no rank; after opening, the rank was there — NAMES arriving on open rather than on join. The empty prefix beforehand is itself the proof the server had stopped volunteering one: without the capability it would have sent it regardless.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Salastil/moho#156