* fix(irc): chunk PRIVMSG by UTF-8 byte budget so long non-ASCII messages are not truncated
IRC caps a full protocol line at 512 bytes, but sendPrivmsg split outbound
text by UTF-16 code units against the 350 char default. Multi-byte text such
as CJK or emoji produced lines far beyond 512 bytes and servers silently
dropped the tail of every oversized chunk. The chunker now also enforces a
UTF-8 byte budget derived from the line framing overhead, splitting on code
point boundaries and preferring spaces, while ASCII chunking is unchanged.
* test(irc): move loopback IRC server helper to shared test helpers
The colocated node:net import tripped the network-runtime-boundary PR diff
scan for extensions/irc/src. The loopback server now lives in test/helpers,
outside the scanned network runtime paths, and the CJK, emoji, and ASCII
chunking cases keep driving the real client over a real TCP socket.
* fix(irc): decouple byte budget from character cap and move loopback helper to irc test-support
The byte budget is now derived only from the 512-byte line limit and framing
overhead, independent of messageChunkMaxChars, so low character caps with
multibyte text keep advancing instead of dropping the message. The loopback
IRC server helper moves from test/helpers to the extension-local package-root
test-support surface so extension tests stay off repo helper bridges and raw
socket use stays outside extensions/irc/src.
* fix(irc): enforce UTF-8 wire limits
* test(irc): satisfy loopback harness lint
* test(irc): avoid implicit Promise return
* test(irc): handle loopback close errors
* fix(irc): preserve boundary word splitting
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(irc): chunk PRIVMSG on UTF-16 boundary to avoid lone surrogates
sendPrivmsg split long messages with String.slice on a UTF-16 code-unit
index, so an emoji (or other astral character) straddling the split
point was cut into a lone high/low surrogate, sending broken bytes in
the PRIVMSG to the IRC server.
Slice each chunk with sliceUtf16Safe so a surrogate pair is never split.
When the budget is too small to fit even the leading astral character,
emit that character whole so chunking still makes progress.
Adds a socket-level test (fake net/tls socket) asserting no PRIVMSG
chunk contains a lone surrogate, including the one-code-unit budget
edge case, while the existing space-preferring split is preserved.
* refactor(irc): make surrogate-safe chunking direct
* fix(irc): preserve one-unit chunk limits
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(irc): prevent ghost nick collisions on rejoin after network delay
* test(irc): add regression tests for fallback nick uniqueness
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: wendy-chsy <wan.wenyan@xydigit.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>