  - **Callees, all already resolved:** Rust — `collapse` (P1 match_; the `add_modeid` MyClient nick/user/host collapse), `mycmp` (P1; `BanExact`), `make_link`/`free_link` (P2 list), `istat` (P2; `is_bans`/`is_banmem` are `u_long` → `wrapping_add`/`wrapping_sub`, cf. P5u add_invite — a debug `-=` underflow would abort the nounwind extern fn); libc — `MyMalloc`(P2)/`free`/`strncpy`(`strncpyzt_` helper)/`strlen`/`isspace` (added to the extern block; `check_string` passes the char sign‑extended `as c_int` as C does). New imports: `aListItem`/`collapse`/`ERR_BANLISTFULL`/`HOSTLEN`/`MAXBANLENGTH`/`MAXBANS`/`RPL_BANLIST`/`RPL_EXCEPTLIST`/`RPL_INVITELIST`/`RPL_REOPLIST`/`USERLEN`. Inline `ban_len`/`ban_exact` macros + `asterix_ptr`/`strncpyzt_` helpers. The `add_modeid` `(len > MAXBANLENGTH) || (++cnt >= MAXBANS)` short‑circuit modelled as `len > … || { cnt += 1; cnt >= … }` (the `++cnt` block runs only when the left is false — faithful to C's `||`). `bzero(mode, sizeof(Link))` → `ptr::write_bytes(mode,0,1)`.
  - **No L1 — all five are file‑`static` → the `cref_` archive keeps them local (no `cref_add_modeid` oracle, cf. P5v `match_modeid` / P5dd `can_join`).** The data‑op faithfulness is gated at **L2**: ref‑C `set_mode` calls C `add_modeid`/`make_bei`; the Rust build's (still‑C) `set_mode` calls the **Rust** ones — byte‑identical wire output through `set_mode` is the gate.
  - **`format!` per user request — N/A, documented in‑module.** `make_bei` copies arbitrary client‑supplied ban‑mask bytes (`nick`/`user`/`host`, capped NICKLEN/USERLEN/HOSTLEN) via `strncpyzt_` byte copies (a UTF‑8 `String` would corrupt non‑ASCII — the standing P5c/P5f rule); every reject reply (`ERR_BANLISTFULL`, `RPL_BANLIST`/etc.) goes straight to the C variadic `sendto_one`; no sub‑`long` int reaches a sender.
  - **L2 green + L2‑S2S green (the gates).** New `golden_channel_ban` (L2): local chanop alice `+b foo!bar@baz`/`+e *!*@trusted.example`/`+I friend!*@*` add (→ `make_bei` 3‑component split + asterix‑fill + `add_modeid` head‑prepend), the `MODE #chan b`/`e`/`I` query (`367`/`348`/`346` reading the Rust‑built `mlist` + `368`/`349`/`347` terminators), duplicate `+b` (BanExact dedup → re‑`367`, no second node), then `‑b` (→ `del_modeid` + `free_bei`) and the **inverse** re‑query (the ban is gone — mask occurrence count 2→1). New `golden_s2s_ban` (L2‑S2S): a peer **server** sets `:001B MODE #chan +b …` → `set_mode` calls the Rust `add_modeid` with `MyClient(cptr)` **false** (the pure non‑MyClient list‑add arm that skips every `sendto_one`, reachable only over a link), alice's `MODE #chan b` query confirms the ban, then the peer server `‑b` → `del_modeid` + `free_bei` and the re‑query shows it gone. All byte‑identical ref‑C == Rust; full `ircd-golden` suite + the channel L1 diff suite (`channel_leaf/invite/can_send/membership/modes_diff`) green; `cargo build --workspace` 0 warnings; no new canonicalizer masks. **Remaining channel.c (C):** the mode core (`m_mode`/`set_mode`/`send_mode_list`/`send_channel_modes`/`send_channel_members`, sharing the `modebuf`/`parabuf`/`uparabuf` statics) + `reop_channel`/`collect_channel_garbage`/`setup_server_channels`/`free_channel` stay in `channel_link.o`.
- **2026‑06‑03 — P5gg (channel.c mode core — `m_mode`/`set_mode`/`send_mode_list`/`send_channel_modes`/`send_channel_members`) merged.** The MODE command handler (channel.c:1136), the ~860‑line mode parser/applier `set_mode` (:1195), the `+beIR` list emitter `send_mode_list` (:931), and the two server‑burst emitters `send_channel_modes` (:1022) / `send_channel_members` (:1066) ported to `ircd-common/src/channel.rs`, extending the existing `channel_link.o` partial port (`‑DPORT_CHANNEL_P5`). **Fourteenth (final large) channel.c sub‑phase** — the connected component over the shared file‑static scratch buffers `modebuf`/`parabuf`/`uparabuf`. Plan: `docs/superpowers/plans/2026-06-03-p5gg-channel-mode-core.md`.
  - **All five take a plain `#ifndef PORT_CHANNEL_P5` guard — no extern‑prototype switch.** `set_mode`/`send_mode_list` are file‑`static` in C, and after this port have **no remaining C caller** (their only callers — `m_mode` and `send_channel_modes` — port here; `m_njoin`, the only other `modebuf`/`parabuf` user, is already Rust from P5ee) → they become **private Rust `unsafe fn`s** (no `cref_` oracle → L2/L2‑S2S tested). `send_channel_modes`/`send_channel_members` are **exported** (channel_ext.h) and still called by the C `send_server_burst` (s_serv.c:1302‑1311) → `#[no_mangle]` resolves s_serv's calls to the Rust defs at link. `m_mode`'s decl parse.rs imports from `ircd_sys::bindings` resolves once the C def drops. RED confirmed via exactly three undefined symbols (`m_mode`/`send_channel_modes`/`send_channel_members`); the two statics vanished with their sole callers. After the port the C `modebuf`/`parabuf`/`uparabuf` file‑statics have **zero** C users → reuse the existing module‑private `MODEBUF`/`PARABUF` (P5ee in‑call scratch) + new `UPARABUF`.
  - **Callees, all already resolved:** Rust — `canonize` (P5m), `strtoken` (P1), `clean_channelname`/`find_channel`/`is_chan_op` (P5t), `check_channelmask` (P5u), `channel_modes` (P5w), `change_chan_flag` (P5x), `find_chasing` (P5bb), `check_string`/`make_bei`/`free_bei`/`add_modeid`/`del_modeid` (P5ff), `del_invite` (P5u), `find_uid` (P4), `m_umode` (P5h — the non‑channel MODE target route); C extern — the variadic senders (`sendto_one`/`sendto_match_servs_v`/`sendto_channel_butserv`/`sendto_channel_butone`/`sendto_flag`, all already in the block), `myrand` (P2). New imports: `ircstp` (the `is_rreop`/`is_fake` counters), `m_umode`, `SLink__bindgen_ty_1` (the `chops` union init), `ERR_NEEDMOREPARAMS`/`ERR_RESTRICTED`/`ERR_UNKNOWNMODE`, `RPL_CHANNELMODEIS`/`RPL_UNIQOPIS`/the four `RPL_ENDOF{BAN,EXCEPT,INVITE,REOP}LIST`. New `c_int` consts `MODE_DEL`/`MODE_KEY`/`MODE_LIMIT`/`MODE_EXCEPTION`/`MODE_INVITE`/`MODE_REOPLIST`/`KEYLEN`/`MODE_WPARAS` (the imported `MODE_BAN`/… are bindgen `u32` → cast at use; `MODE_UNIQOP`/`MODE_CHANOP`/`MODE_VOICE` == the `CHFL_*` locals). `USE_SERVICES` off (the `check_services_butone` block skipped); `V29PlusOnly` off (the `opcnt >= MAXMODEPARAMS+1` inner guards compile); `JAPANESE` off (no `jp_valid`).
  - **`chops`/`flags[]` + the tri‑state `whatt`.** `set_mode`'s `static Link chops[MAXMODEPARAMS+3]` (in‑call scratch) → a module‑private `static mut CHOPS: [Link; 6]` (const‑init via the `SLink__bindgen_ty_1{cptr: null}` union); `static int flags[]` (the simple‑mode bit↔char table) → a `const SIMPLE_FLAGS: &[(c_int, u8)]` walked in the exact order. `whatt` (C `u_int`, used as both `MODE_ADD`/`MODE_DEL` and the `1`/`-1`/`0` +/- sign tracker across the emission loops) is kept `c_int` — every value (`0x40000000`/`0x20000000`/`0`/`1`/`-1`) compares identically. `mode->mode` is `u_int` → the working copy `new_` is `c_int` (matching C's `int new`), cast on read/write (all bits < 0x40000, no sign issue). The C switch `break`s (break the switch → continue to `curr++`) became a labeled `'sw` block with `break 'sw`; the `'O'`→`'o'`/`'v'` fall‑through is a `proceed`‑bool computed in an `'ob:` labeled block; the `opcnt` reconstruction's `if (tmplen == -1) break;` (breaks the **for** loop) is `break 'recon`, while the per‑item `MODE_KEY` skips are a nested `'emit_key:` block.
  - **`format!` per user request — N/A, documented in‑module.** The whole cluster builds protocol‑byte strings into the `modebuf`/`parabuf`/`uparabuf` scratch (`*mbuf++`, `strcat`, the `+l` `sprintf("%-15d")`) byte‑for‑byte as C (arbitrary client nick/ban‑mask bytes — a UTF‑8 `String` would misframe), then hands them to the C variadic senders; there is no owned ASCII reply to `format!`.
  - **Faithfulness notes.** `set_mode` tail: the sender cascade `s = IsServer(sptr) ? serv->sid : sptr->user ? user->uid : sptr->name`; `sendto_match_servs_v(chptr, cptr, SV_UID, …mbuf, upbuf)` (the UID‑form params in `upbuf`, name‑form in `pbuf`); the fake‑vs‑real branch (`IsServer(cptr) && !IsServer(sptr) && !ischop` → `sendto_flag(SCH_CHAN, "Fake:…")` + `ircstp->is_fake++`, else `sendto_channel_butserv(…pbuf)`); `return ischop ? count : -count`. The `k` key sanitizer (`,`→`.`, the `>0x7f`/`>0xa0` high‑byte mask, KEYLEN truncation) ported on `*mut u8` exactly. `reop` scheduling (`timeofday + LDELAYCHASETIMELIMIT + myrand()%300` for chanop self‑deop / server `+R`; `+r` from server sets `chptr->reop`) writes channel state (not wire — `myrand` non‑determinism is invisible to L2). parseNUH splits `nick!user@host` in place via `strchr`/`strrchr`, `make_bei`, restores the separators.
  - **Bug caught by the burst S2S test (the inverse paid off).** `aListItem.nick`/`user`/`host` are `*mut c_char` **pointers**, not arrays — the first port took `addr_of!((*al).nick)` (address of the pointer field) and `%s` printed the pointer's bytes as garbage (`:000A MODE #chan +b ``…`). The `golden_s2s_mode` relink‑burst diff caught it immediately; fixed to pass `(*al).nick` directly at all three sites (`send_mode_list`, the `beIR` list query, the reconstruction `nuh`). The simpler L2/outbound tests passed *without* this fix (they never serialize a stored `mlist` entry) — only the burst path re‑emits the list, so the S2S coverage was load‑bearing.
  - **L2 + L2‑S2S are the gates (no fresh L1 — set_mode's state mutation is already L1‑covered via the P5x membership + P5ff ban diffs through it).** New `golden_channel_mode_set` (L2): a chanop voices a second member (`+v bob`) — the relay reaches every member via `sendto_channel_butserv`, observed by bob; NAMES shows `+bob`; the **inverse** `-v bob` → NAMES shows plain `bob` (`change_chan_flag` MODE_DEL clears CHFL_VOICE). The 2‑client harness (the per‑host clone limit is 2, the P5cc finding) makes bob both target and observer. New `golden_s2s_mode` (L2‑S2S, 2 scenarios): **outbound** — a local chanop (the peer ops alice on a remote‑NJOIN'd #chan, since a split local client can't create one) sets `+m` then `+l 5`, and the peer receives the UID‑sourced `:000AAAAAA MODE #chan +m` / `+l 5` (`set_mode`'s `sendto_match_servs_v(SV_UID)` tail, `upbuf` form); **link burst** — a populated #chan, then the peer is dropped and **relinks** (the only way to burst a `#` channel: it can't exist before the single harness peer links), so the second burst replays `:000A NJOIN #chan :000AAAAAA` (`send_channel_members`) + `:000A MODE #chan +tnl 10` / `+b *!*@evil.host` (`send_channel_modes` → `channel_modes` + `send_mode_list`). Regression: `golden_channel_modes`/`ban`/`part` (L2) + `golden_s2s_ban`/`membership` (inbound server MODE through the Rust `set_mode`) stay byte‑identical ref‑C == Rust; full `ircd-golden` + `ircd-testkit` (L1) suites green; `cargo build` 0 warnings; no new canonicalizer masks. **Remaining channel.c (C):** only the **lifecycle group** — `reop_channel`/`collect_channel_garbage`/`setup_server_channels`/`free_channel`/`get_channel` — stays in `channel_link.o`. The channel.c mode + handler clusters are now fully Rust.

- **2026‑06‑03 — P5hh (channel.c lifecycle group — `get_channel`/`free_channel`/`reop_channel`/`setup_server_channels`/`collect_channel_garbage` + the `channel` global) merged.** The channel struct's birth/death cluster ported to `ircd-common/src/channel.rs`. **15th and FINAL channel.c sub‑phase** — every symbol channel.c defines now lives in ircd-common, so **`channel.o` is dropped outright** (added to `PORTED` in `ircd-sys/build.rs`; the P5t…P5gg `channel_link.o` second‑compile + its `-DPORT_CHANNEL_P5` link substitution removed entirely; the `cref` oracle keeps the unguarded `channel.o`). Plan: `docs/superpowers/plans/2026-06-03-p5hh-channel-lifecycle.md`.
  - **Symbols.** `get_channel` (channel.c:2226, file‑static, extern‑switched P5aa) + `free_channel` (:2378, file‑static, extern‑switched P5x) → `#[no_mangle] pub unsafe extern "C"` (their `extern`‑block decls in channel.rs removed; the still‑Rust callers `m_part`/`m_join`/`m_njoin`/`remove_user_from_channel`/`setup_server_channels` resolve to them). `reop_channel` (:3911, purely file‑static, `collect_channel_garbage`'s only caller) → private Rust `unsafe fn` (no oracle). `setup_server_channels` (:812) + `collect_channel_garbage` (:4026) are channel_ext.h exports called from `ircd.c:738` (boot) / `ircd.c:1188` (io_loop timer) → `#[no_mangle]`. The `channel` global list head (:52) → `#[no_mangle] pub static mut channel` (replaces the `channel as channel_list` bindgen import; the two read sites in m_list/the GC updated; the still‑C `s_debug` STATS resolves its `extern` decl to it).
  - **Config findings (locked config).** USE_IAUTH on → `setup_server_channels` creates the 14th channel `&AUTH`; CLIENTS_CHANNEL undef → no `&CLIENTS`; JAPANESE off → `get_channel`'s `jp_chname`/`FLAGS_JP` block dead; DEBUGMODE off → `collect`'s `del`/SCH_NOTICE + `reop`'s SCH_NOTICE blocks dead; LOG_SERVER_CHANNELS off → the still‑C `setup_svchans` (send.c) is just the `find_channel` relink loop. `MyFree(chptr)` → plain `free` (the macro's NULL‑out is dead on a by‑value param). The function‑local statics `max_nb`/`split` in `collect_channel_garbage` → module‑private `static mut MAX_NB`/`SPLIT` (persist across calls, faithful). `reop_channel`'s `!CHFL_REOPLIST` arg = the C logical‑not of a nonzero value = `0` (ported literally). istat decrements use `wrapping_sub` (cf. P5u/P5ff).
  - **Classification: utility/callee TU** (none of the six is a `msgtab` handler). `get_channel`/`free_channel`/`reop_channel` are file‑static → the `--prefix-symbols=cref_` rename keeps them **local** (no oracle); `setup_server_channels`/`collect_channel_garbage`/`channel`/`add_to_channel_hash_table` are exported → `cref_*` oracles exist.
  - **L1** (`ircd-testkit/tests/channel_lifecycle_diff.rs`, the two exported entries vs `cref_`; the three statics transitively covered). Both sides drive **separate** process globals (`channel` vs `cref_channel`, separate channel hash tables init'd per‑test via `inithashtables`/`cref_inithashtables` — NULL until boot otherwise, the L1 segfault finding — separate `istat`). (1) `setup_server_channels` create‑cluster: 14 server channels, identical chname/topic/mode.mode/`users==1`‑lone‑chanop walk (`get_channel` CREATE + global‑list prepend + hash insert + `add_user_to_channel` + topic `strcpy` + mode masks + `setup_svchans` relink). (2) **Inverse**: the oracle'd `remove_user_from_channel(mp, &ERRORS)` → `users`→0, history==0 → `free_channel` unlinks `&ERRORS` from both global lists **and** the hash (find now misses), the other 13 survive. (3) `collect_channel_garbage`: hand‑built `&dead` (empty+expired) vs `&live` → identical return `now+CHECKFREQ`, `&dead` freed (gone from list+hash), `&live` kept. **Finding:** `free_channel` re‑checks the *global* `timeofday >= chptr->history` (not collect's `now` param) → the test pins `timeofday`/`cref_timeofday` to `now` so the expired‑free path fires; the `myrand` reop arm needs a live opless `+r` channel (non‑deterministic) → not entered, review‑covered.
  - **No new L2‑S2S.** None of the six has an `IsServer(cptr)` dispatch branch or formats remote‑user fields (`get_channel`'s only client test is `MyClient(cptr)` chname truncation). `get_channel`/`free_channel` are already L2/S2S‑covered transitively by every JOIN/PART golden (`golden_channel*`, `golden_s2s_membership` — remote NJOIN/PART drive `get_channel(CREATE)`/`free_channel`); `collect_channel_garbage`/`reop_channel` are timer‑driven (300 s, unreachable in a short golden). Regression: full `ircd-golden` (83 tests) + `ircd-testkit` L1 suites byte‑identical ref‑C == Rust; `cargo build` 0 warnings; no new canonicalizer masks. **channel.c is now FULLY ported to Rust** — only the channel **lifecycle** remained after P5gg, and this closes it.

- **2026‑06‑03 — P5ii (s_serv.c informational query foundation cluster — `m_version`/`m_time`/`m_admin`) merged.** The three leaf informational query handlers (s_serv.c:109/2534/2547) ported to the new `ircd-common/src/s_serv.rs`. **First `s_serv.c` sub‑phase** — `s_serv.c` is the last (and largest) P5 TU (~3884 lines, ~14 file‑statics, ~40 handlers), ported in clusters; this one establishes the `s_serv_link.o` partial‑port mechanism. Plan: `docs/superpowers/plans/2026-06-03-p5ii-s_serv-informational.md`.
  - **Mechanism — establish `s_serv_link.o` (mirrors `s_user_link.o`).** A second compile of `s_serv.c` with the three ported handlers `#ifdef`'d out (`-DPORT_SERV_P5`), substituted into the link set via the new `"s_serv.o" => "s_serv_link.o"` map entry in `build.rs` `link_objs()`; the cref oracle keeps the unguarded `s_serv.o` in `CREF_OBJS`. The recipe carries the per‑object define `-DIRCDMOTD_PATH="\"$(IRCDMOTD_PATH)\""` (Makefile `s_serv.o` recipe line 346 — needed by the still‑C `m_motd`), driven through `make --eval` so the recursive path var expands identically. All three handlers take a **plain `#ifndef PORT_SERV_P5` guard** — no extern‑prototype switch: none is a file‑`static` and none is anyone's `static` callee. RED→GREEN confirmed: binary links clean (no undefined, no multiple‑definition) and `nm target/debug/ircd | grep ' T \(m_version\|m_time\|m_admin\)$'` shows all three defined in the binary (came from Rust).
  - **Callees, all already resolved.** C externs — `hunt_server` (still C, s_user.c; bindings decl), `find_admin` (still C, s_conf.c; bindings decl), `sendto_one` (variadic P8 trampoline; local `extern "C"` block, fmt `*mut c_char`). Rust — `replies[]` (P3, via `reply(i)`), `date` (P5c s_misc.rs, `date(0)`), `serveropts` (P5b s_debug.rs; the bindgen `[c_char; 0]` incomplete‑array extern → `addr_of!(serveropts) as *mut c_char` resolves to the real 12‑byte Rust static at link). Globals/consts — `me` (`me.name` self‑pointer; `(*me.serv).sid.as_ptr()` for the VERSION SID), `IRC_VERSION` (bindgen `&[u8;7]`), `HUNTED_ISME` (`0u32`). Inlined macros: `ME`=`me.name`, `BadTo`/`BadPtr` (struct_def.h:787), `IsRegistered`=`status >= STAT_SERVER || status == STAT_ME` (struct_def.h:132).
  - **Classification: handler cluster, no L1.** All three are in `msgtab` (`common/parse.c`) at col 1 (`m_version`/`m_time`) or all‑columns (`m_admin`), min‑params 0 → client‑reachable → **L2**. Each has a `hunt_server` forwarding branch (server‑reachable, exactly like P5z `m_list`) → **L2‑S2S**. `m_admin` additionally has the `IsRegistered(cptr)` head‑gate (unregistered clients skip the forward — a local branch, L2‑covered). **No L1** — like `m_list`/`m_topic`/`m_names`, these are pure wire handlers with **no socket‑free data op** (no allocator/list‑mutation/data‑returning lookup), so there is nothing for an L1 differential to drive.
  - **`format!` per user request — N/A, documented in‑module.** None of the three builds an ASCII/numeric reply string of its own — every wire line goes straight to the C variadic `sendto_one(replies[…], …)`; `date()` is the P5c Rust port returning its own static buffer. There is nothing to format.
  - **L2 + L2‑S2S are the gates.** `golden_s_serv_info` (L2): a lone registered client drives `VERSION`→351 RPL_VERSION, `TIME`→391 RPL_TIME (trailing localtime wall‑clock volatile → masked by the existing `canonicalize()` 391 rule), `ADMIN`→256‑259 RPL_ADMINME…RPL_ADMINEMAIL via minimal.conf's `A` line (`find_admin()` non‑null → the admin path, not ERR_NOADMININFO) — reference‑C == Rust byte‑identical. `golden_s2s_s_serv_info` (L2‑S2S): a local client targets `VERSION/TIME/ADMIN peer.test` → `hunt_server` matches the linked peer and forwards each command out the link; the peer receives byte‑identical forwarded lines under ref‑C and Rust (the forwarding short‑circuit the standalone harness can't reach). `cargo build` 0 warnings; full `ircd-golden` + `ircd-testkit` suites green; no new canonicalizer masks.

- **2026‑06‑03 — P5jj (s_serv.c network‑info query cluster — `m_info`/`m_links` + the file‑static `check_link`) merged.** The two remaining leaf network‑info query handlers (s_serv.c:1400/1438) + their shared per‑link load‑health gate `check_link` (s_serv.c:3419) ported into `ircd-common/src/s_serv.rs`, extending the existing `s_serv_link.o` partial port (`‑DPORT_SERV_P5`; three new guard regions). **Second `s_serv.c` sub‑phase.** Plan: `docs/superpowers/plans/2026-06-03-p5jj-s_serv-info-links.md`.
  - **First `s_serv.c` extern‑prototype switch.** `check_link` is file‑`static` in C and still called by the C remnant `m_stats` (×2) / `m_motd` → the **P5u/P5x mechanism**: its forward decl at s_serv.c:36 flips `static`→`extern` under `#ifdef PORT_SERV_P5` (body guarded out) so the C remnant resolves to the Rust `#[no_mangle]` def at link (linkage‑only, faithful). `m_info`/`m_links` take plain `#ifndef` guards (neither is a static / anyone's static callee — their decls parse.rs imports from `ircd_sys::bindings` resolve to Rust). RED→GREEN: binary links clean and `nm target/debug/ircd | grep -E ' T (m_info|m_links|check_link)$'` shows all three defined from Rust (`check_link` is now `T`, was a local `t`).
  - **Callees, all already resolved.** C externs — `hunt_server`, `sendto_one` (variadic P8 trampoline, local block fmt `*mut c_char`). version.c externs (still C) — `infotext` (`[*mut c_char; 0]` incomplete‑array → `addr_of!` + NULL‑walk), `creation`, `generation`. Rust — `replies[]` (P3 `reply()`), `myctime` (P1 support), `collapse`/`match_` (P1), `svrtop` (P2), `ircstp` (P5c). Globals/consts — `me` (`me.name`/`me.firsttime`/`(*me.serv)…`), `bootopt`+`BOOT_PROT`, `timeofday`, `Status_STAT_CLIENT`, `CHREPLLEN`=8192 (config.h:363, baked as a `const c_int` — not a bindgen const, cf. channel.rs). Inlined macros: `ME`/`BadTo`/`BadPtr`, `MyConnect`=`fd>=0`, `IsMasked`=`x && x->serv && x->serv->maskedby != x`, `DBufLength`=`(d)->length`. **Invariant kept:** `acptr->serv->up->name` is `(*(*(*acptr).serv).up).name` (deref the `*mut aClient`, never `.read()` an `aClient` by value).
  - **Classification: handler cluster, no L1.** INFO `{m_nop,m_info,m_info,m_nop,m_unreg}` + LINKS `{m_links×4,m_unreg}` (msgtab col 1, min‑params 0 → client‑reachable → **L2**); each has a `hunt_server` forward (INFO always; LINKS when `parc>2`) → **L2‑S2S**. **No L1** — like P5ii/`m_list`/`m_names`, pure wire handlers with no socket‑free data op. `check_link` *does* mutate `ircstp` counters, but it is file‑`static` → the `‑‑prefix‑symbols=cref_` rename keeps it **local** (no `cref_check_link` oracle), and its non‑zero branches need a remote client over a *loaded* link (SendQ>65536 / link‑age<60s / lastload timing) which a local client never reaches (`MyConnect` → return 0) and which is timing‑non‑deterministic over S2S → the return‑0 path is L2‑covered (every INFO/LINKS), the load branches are **review‑covered** (no deterministic harness path). So no L1 file.
  - **Two new canonicalizer masks (m_info's volatile 371 trailers).** INFO emits, after the deterministic `infotext[]` AUTHORS block, two `371 RPL_INFO` lines that differ between the separately‑built / separately‑booted ref‑C and Rust runs: `:Birth Date: <creation>, compile # <generation>` (version.c build timestamp + per‑build counter) and `:On‑line since <ctime(me.firsttime)>` (boot wall‑clock). Added a 371 rule to `canonicalize()` masking each volatile tail (keeps the label). `infotext[]` itself is byte‑identical across builds → not masked.
  - **`format!` per user request — N/A, documented in‑module.** Every wire line (INFO text/birth/online, the per‑server `364 RPL_LINKS`, the TRYAGAIN/ENDOF replies) goes straight to the C variadic `sendto_one`; `myctime()` returns its own static buffer. `m_links`'s only integer arg is `acptr->hopcount` (`%d`, already `c_int` — the P5c width rule is satisfied). Nothing to format.
  - **L2 + L2‑S2S are the gates.** `golden_s_serv_info_links` (L2): a lone registered client drives `INFO`→a run of `371` (masked birth/online) ending in `374 RPL_ENDOFINFO`, then bare `LINKS`→`364`/`365 RPL_ENDOFLINKS` — ref‑C == Rust byte‑identical; `check_link` returns 0 (local `MyConnect`) so no `263 RPL_TRYAGAIN`. `golden_s2s_s_serv_info_links` (L2‑S2S): the `hunt_server` forwards (`INFO peer.test`, `LINKS peer.test *`) reach the linked peer byte‑identical, **and** the bare‑LINKS tree walk before vs after the peer links (the positive/inverse pair — the lone server sees only `:irc.test 364 alice irc.test irc.test :0 000A L2 Test Server`, then after the link adds `:irc.test 364 alice peer.test irc.test :1 001B Peer Test Server`), the only way to exercise `m_links`'s remote‑server `up->name`/`sid`/`info` field formatting. `cargo build` 0 warnings; full `ircd-golden` + `ircd-testkit` suites green.

- **2026‑06‑04 — P5kk (s_serv.c informational stub cluster — `m_users`/`send_users`/`m_summon`/`m_help`) merged.** The three leaf informational stub handlers (s_serv.c:1500/2154/2247) + the file‑static helper `send_users` (s_serv.c:2202) ported into `ircd-common/src/s_serv.rs`, extending the existing `s_serv_link.o` partial port (`‑DPORT_SERV_P5`). **Third `s_serv.c` sub‑phase.** Plan: `docs/superpowers/plans/2026-06-04-p5kk-s_serv-users-summon-help.md`.
  - **Config‑resolved bodies.** `USERS_RFC1459` off (`config.h:85 #undef`) → `m_users` takes the `send_users` arm: forward via `hunt_server(":%s USERS :%s", 1)` only when `parc>1`, then `send_users` emits `265 RPL_LOCALUSERS` (`is_myclnt`/`is_m_myclnt` ×2) + `266 RPL_GLOBALUSERS` (`is_user[0]+is_user[1]`/`is_m_users` ×2). `ENABLE_SUMMON` off (`config.h:77 #undef`) → `m_summon`, after the `parc<2`/empty `411 ERR_NORECIPIENT` guard, rewrites `parv[1..=4]` (user/host=ME‑or‑parv[2]/chname=`*`/NULL) and forwards via `hunt_server(":%s SUMMON %s %s %s", 2)`; the ISME path emits `445 ERR_SUMMONDISABLED`. `m_help` walks `msgtab[]` (the incomplete‑array extern, `addr_of!` + `cmd.is_null()` terminator) emitting `:%s NOTICE %s :%s` per command.
  - **`send_users` extern‑prototype switch (P5u/P5x).** `send_users` is `static` in C (s_serv.c:52 forward decl) and was GCC‑inlined into both callers as `.isra.0` (no global symbol in the oracle `s_serv.o` → no `cref_send_users`). But it has a **remaining C caller** — the still‑C `m_lusers` (s_serv.c:2386, `if (all) send_users(...)`) — so guarding out its definition left `s_serv_link.o` with an undefined local `send_users` (confirmed at RED: undefined `m_users`/`m_summon`/`m_help`/`send_users`). Fix: the forward decl flips `static`→`extern` under `#ifdef PORT_SERV_P5` and the Rust def is `#[no_mangle] pub extern "C"`, so `m_lusers` resolves to the Rust `send_users` at link. `nm target/debug/ircd | grep -E ' T (m_users|m_summon|m_help|send_users)$'` shows all four defined from Rust.
  - **Callees, all already resolved.** C externs — `hunt_server`, `sendto_one` (variadic P8 trampoline, local block fmt `*mut c_char`). Rust — `replies[]` (P3 `reply()`), `msgtab[]` (parse.rs, `static mut` resolves at link). Globals — `istat` (`istat_t`: `is_myclnt`/`is_m_myclnt`/`is_user[2]`/`is_m_users`, `u_long` counters passed verbatim to the variadic sender), `me`. Inlined macros — `ME`/`BadTo`/`BadPtr`. The `parv` rewrite in `m_summon` is faithful raw‑pointer stores (`*parv.add(n) = …`) into the parser's fixed MAXPARA+1 array.
  - **Classification: handler cluster, no L1.** USERS `{m_nop,m_users,m_users,m_users,m_unreg}` / SUMMON `{m_nop,m_summon,m_summon,m_nop,m_unreg}` / HELP `{m_nop,m_help,m_help,m_nop,m_unreg}` (msgtab col 1, min‑params 0 → client‑reachable → **L2**). `m_users`/`m_summon` each have a `hunt_server` forward → **L2‑S2S**; `m_help` has no forward/`IsServer` path → no S2S. **No L1** — like P5ii/P5jj/`m_list`, pure wire handlers with no socket‑free data op; `send_users` has no `cref_` oracle (inlined) so it too is L2‑covered, not L1.
  - **`format!` per user request — N/A.** Every wire line (the `265`/`266` counts, `411`/`445`, the HELP NOTICEs) goes straight to the C variadic `sendto_one`; nothing is assembled into a Rust string.
  - **L2 + L2‑S2S are the gates.** `golden_s_serv_stubs` (L2): a lone registered client drives `USERS`→`265`+`266`, `SUMMON nobody`→`445`, `HELP`→the NOTICE list anchored on the table's final `:ETRACE` entry — ref‑C == Rust byte‑identical. `golden_s2s_s_serv_stubs` (L2‑S2S): `USERS peer.test` / `SUMMON nobody peer.test` forward via `hunt_server` and the linked peer receives byte‑identical forwarded commands (`m_help`, having no forward, is excluded with a note). `cargo build` 0 warnings; both touched golden binaries green.

- **2026‑06‑04 — P5ll (s_serv.c LUSERS handler — `m_lusers`) merged.** The LUSERS network‑stats handler (s_serv.c:2272) ported into `ircd-common/src/s_serv.rs`, extending the existing `s_serv_link.o` partial port (`‑DPORT_SERV_P5`). **Fourth `s_serv.c` sub‑phase.** This **closes the P5kk `send_users` loop**: `m_lusers`'s `all`‑path tail `if (all) send_users(...)` already resolves to the Rust `send_users` (P5kk), and now both live in Rust. Plan: `docs/superpowers/plans/2026-06-04-p5ll-s_serv-m_lusers.md`.
  - **Guard + RED→GREEN.** A single plain `#ifndef PORT_SERV_P5` guard around the C def (s_serv.c:2272‑2392); `m_lusers` is not a file‑static and not anyone's static callee. RED: `cargo build -p ircd-rs` → exactly one undefined symbol `m_lusers`. GREEN: `nm target/debug/ircd | grep ' T m_lusers$'` → defined from Rust; `cargo build` 0 warnings.
  - **Config‑resolved body (USERS_RFC1459 off).** Three counting paths feed RPL_LUSER{CLIENT 251, OP 252, UNKNOWN 253, CHANNELS 254, ME 255}: (1) bare `LUSERS` or `LUSERS *` → the **`all`** path reads `istat` (`is_serv`/`is_user[0..1]`/`is_unknown`/`is_oper`/`is_service`/`is_myclnt`/`is_myserv`/`is_myservice`) then tails into `send_users` (265/266); (2) `LUSERS <server>` → a remote `find_client`→`IsServer`→`serv->usercnt[0..2]`; (3) `LUSERS <mask>` → walks `svrtop` summing each `asptr->usercnt[]` (the `IsMe` arm grabs `is_myclnt`/…/`is_unknown`), then walks `svctop` counting matching services. `parc>2` forwards via `hunt_server(":%s LUSERS %s :%s", 2)` first.
  - **Callees, all already resolved.** C externs — `hunt_server`, `sendto_one` (variadic P8 trampoline, local block fmt `*mut c_char`). Rust — `collapse`/`match_` (P1), `find_client` (P4 parse.rs), `send_users` (P5kk). Globals — `istat`/`svrtop`/`svctop` (the `aServer.usercnt`/`nexts`/`bcptr` + `aService.servp`/`nexts` chains, raw‑pointer walked, never an `aServer`/`aService` read by value), `replies` (P3 `reply()`), `me`. New inline helpers `is_server`=`status==STAT_SERVER`, `is_me`=`status==STAT_ME` (struct_def.h:136/138).
  - **Faithfulness notes.** The `int` locals (`s_count`/`c_count`/`i_count`/`u_count`/`o_count`/`v_count`/`m_clients`/`m_servers`/`m_services`) stay `c_int`, assigned from `u_long` istat fields with `as c_int` (C's implicit `u_long`→`int` truncation). `istat.is_chan` is passed straight to the `%d` RPL_LUSERCHANNELS variadic as `u_long` — byte‑identical on x86‑64 SysV (the low 32 bits of the arg register match a small positive `int`), exactly as the already‑Rust `send_users` does. **Quirk ported literally:** RPL_LUSERUNKNOWN (253) is emitted with **`parv0`, not `BadTo(parv0)`** (s_serv.c:2380) — every other LUSERS reply uses `BadTo`.
  - **Classification: handler cluster, no L1.** `LUSERS {m_lusers, m_lusers, m_lusers, m_lusers, m_unreg}` (msgtab col 1 client‑reachable + col 2 server‑reachable, min‑params 0 → **L2**); the `hunt_server` forward (`parc>2`) **and** the remote‑server field formatting (`svrtop`/`find_client` `usercnt[]` + server names) → **L2‑S2S**. **No L1** — pure wire handler with no socket‑free data op (the lookups are read‑only counting terminating in `sendto_one`), cf. P5ii/P5jj/P5kk/`m_list`.
  - **`format!` per user request — N/A.** Every wire line (the five LUSER numerics + the `send_users` 265/266) goes straight to the C variadic `sendto_one`; nothing is assembled into a Rust string.
  - **L2 + L2‑S2S are the gates.** `golden_s_serv_lusers` (L2): a lone registered client drives a bare `LUSERS` → 251/254/255 then the `send_users` 265/266 (the `all` path), read through the always‑last `266` anchor — ref‑C == Rust byte‑identical. `golden_s2s_s_serv_lusers` (L2‑S2S): two server‑reachable facets after a peer links — (1) `LUSERS *.test` exercises the `svrtop` mask walk (the `*.test` matches both `irc.test` + `peer.test`, so the 251 server count reflects the link and the `IsMe` 253 arm fires), diffed from the **client** side through the 255 tail; (2) `LUSERS * peer.test` (`parc>2`) forwards via `hunt_server` and the **peer** receives the byte‑identical forwarded command. `cargo build` 0 warnings; both touched golden binaries green.

- **2026‑06‑04 — P5mm (s_serv.c map‑display cluster — `m_map`/`dump_map`/`dump_map_sid`) merged.** The MAP handler (s_serv.c:3748) + its two recursive file‑static tree renderers `dump_map` (plain names, s_serv.c:3666) and `dump_map_sid` (names + usercount + SID + version, s_serv.c:3599) ported into `ircd-common/src/s_serv.rs`, extending the existing `s_serv_link.o` partial port (`‑DPORT_SERV_P5`). **Fifth `s_serv.c` sub‑phase.**
  - **Guard + RED→GREEN.** A single plain `#ifndef PORT_SERV_P5` guard around the contiguous C region (s_serv.c:3599‑3781, all three fns): `dump_map`/`dump_map_sid` are file‑`static` with **no remaining C caller** (only `m_map` calls them, and it ports here too) → private Rust `unsafe fn`s (no `cref_` oracle, like `m_list`/`can_join`); `m_map`'s decl resolves via the parse.rs `msgtab` imports. `nm target/debug/ircd | grep ' T m_map$'` → defined from Rust; `cargo build` 0 warnings.
  - **Module‑private `BUF` (the shared `buf[BUFSIZE]`).** `dump_map`/`dump_map_sid` accumulate the output line in the s_serv.c TU‑wide `static char buf[BUFSIZE]` via raw pointer arithmetic — `pbuf` indexes the current nesting offset (`pbuf + 4` per level), each leaf flushes the **whole** `buf` with `015 RPL_MAP`, and the tree‑char cleanup walks backwards (`pbuf[-2]`/`pbuf[-3]`). `m_map` fills+flushes `buf` entirely in‑call (no cross‑call aliasing with the still‑C users of `buf` — m_stats/report_*/send_server_burst), so a module‑private `static mut BUF: [c_char; BUFSIZE]` + a `buf_base()` helper is faithful (cf. P5aa/P5cc). Pointer ops use `.add()`/`.sub()`/`.offset_from()`; the snprintf `size` arg keeps C's `int`→`size_t` conversion via `size as usize` (negative→huge, faithful UB).
  - **Callees, all already resolved.** C externs — `sendto_one` (variadic P8 trampoline, local block fmt `*mut c_char`), plus `snprintf`/`strcat`/`strlen` (libc, added to the local extern block, faithful to the C). Rust — `match_` (P1), `replies[]` (P3 `reply()`). Globals — `me` (`addr_of_mut!(me)` for `&me`, the tree root), `timeofday`. New inline helpers `is_bursting`=`!(flags & FLAGS_EOB)` (struct_def.h:222) and `map_name`=`IsMasked(root) ? maskedby->name : root->name`; reused `is_masked`/`my_connect`/`bad_to`/`me_name` (P5ii/P5jj).
  - **Faithfulness notes.** `me` is `SetEOB`'d at boot (ircd.c:732) → `IsBursting(&me)` false → `dump_map_sid(&me)` always takes the non‑bursting `"%s %d %s %s"` branch (no wall‑clock `"bursting %ds"` trailer). `dump_map`'s `prevserver` carries the last unmasked server across masked‑subtree boundaries via a `*mut *mut aClient` out‑param + a recursion‑local `prev` (`addr_of_mut!(prev)`), byte‑for‑byte the C `aClient **`. The `%ds` literal (snprintf) is `%d` followed by a literal `s`.
  - **Classification: handler cluster, no L1.** `MAP {m_map, m_map, m_map, m_nop, m_unreg}` (msgtab col 1 client‑reachable + col 2 server‑reachable, min‑params 0 → **L2**). `m_map` has **no `hunt_server` forward** (it always dumps from `&me`), but `dump_map`/`dump_map_sid` format **remote‑server fields** (names, SID, version, usercount) only reachable with a linked peer → **L2‑S2S**. **No L1** — pure wire handlers with no socket‑free data op, terminating in `sendto_one` (cf. P5ii/P5jj/`m_list`/`m_names`).
  - **`format!` per user request — N/A.** Every wire line goes straight to the C variadic `sendto_one`; `dump_map_sid` builds its per‑server token into `buf` via libc `snprintf` (faithful, not a Rust string), `dump_map` via libc `strcat`. Nothing assembled with `format!`.
  - **L2 + L2‑S2S are the gates.** `golden_s_serv_map` (L2): a lone registered client drives `MAP` → `018 RPL_MAPSTART` + a single `015` (`irc.test`) + `017 RPL_MAPEND`, then `MAP s` → `018` + a single `015` with the local server's usercount/SID/version — ref‑C == Rust byte‑identical. `golden_s2s_s_serv_map` (L2‑S2S): the multi‑server tree walk a lone server can't produce — bare `MAP` before vs after the peer links (the positive/inverse pair: the lone server sees only `:irc.test 015 alice :irc.test`, then after the link adds `:irc.test 015 alice : \`- peer.test`), then `MAP s` after the link adds `: \`- peer.test 0 001B 0211030000` (the only way to exercise `dump_map_sid`'s remote `serv->sid`/`verstr`/`usercnt` formatting; the peer is sent an `EOB` first so `IsBursting(peer)` is false). `cargo build` 0 warnings; both touched golden binaries + the s_serv golden regression suite green.
