
- **2026-06-04 — P6g (`s_conf.c` `find_Oline`) merged.** Ported the O-line lookup `m_oper` uses to resolve `OPER <name> <pass>` to an O-line; the cleanest remaining self-contained `s_conf.c` leaf, same shape as the P6e `find_admin`/`find_me` bite.
  - **Cluster choice / why now.** Of the remaining `s_conf.c` symbols (`find_conf*`, `attach_conf`/`detach_conf`, `rehash`, `lookup_confhost`), `find_Oline` is the only read-only leaf with a **client** L2 path — `m_oper` (already Rust, `s_user.rs:1996`) calls it directly. The `find_conf*` family (`find_conf`/`find_conf_host`/`find_conf_host_sid`/`find_conf_ip`/`find_conf_exact`/`find_conf_name`/`find_conf_entry`) is reached only from still-C `s_bsd.c`/`s_serv.c` server-link/registration handling → a separate later bite (P6h) with an S2S gate; the `attach`/`detach`/`rehash` mutating cluster is later still.
  - **Guard / partial port.** `#if !defined(PORT_SCONF_FINDOLINE_P6)` wraps the C def (`s_conf.c:1033-1061`), mirroring the P6e `PORT_SCONF_FINDADMIN_P6` guard; `-DPORT_SCONF_FINDOLINE_P6` added to the `s_conf_link.o` compile in `build.rs`. The plain `s_conf.o` (cref oracle) keeps the C def → `cref_find_Oline` stays available for L1.
  - **Config-resolved body.** `CONF_OPS == CONF_OPERATOR == 128` (bindgen const). Faithful translation: `match`/`match_ipmask` keep the IRC convention (0 == matched, nonzero == no match), the `match(host,userhost) && match(host,userip) && (!strchr('/') || match_ipmask)` triple-continue is preserved verbatim, and the `clients < MaxLinks(Class(tmp))` early-return vs the `tmp2` over-limit fallback is byte-for-byte. Depends only on already-ported leaves (`match_`, `match_ipmask` [P6d], `mycmp`, `max_links`).
  - **Classification.** Utility/callee — not in `msgtab`. → **L1 + L2, NO S2S**: `find_Oline` has no `IsServer(cptr)` branch and formats no remote-user fields; it reads only the local client (`m_oper` is a local-client command).
  - **L1** (`ircd-testkit/tests/s_conf_find_oline_diff.rs`): hand-chained `conf` list of O-line entries (name/host strings, a `make_class()` with set `maxLinks`, a `clients` counter) + a `make_client`/`make_user` client; both `conf` and `cref_conf` pointed at the same head; `c_find_Oline` == `cref_find_Oline` across name match + the **inverse** name mismatch, host glob mismatch, CIDR in-range hit vs out-of-range (`/24` adjacent) miss, the `clients >= MaxLinks` over-limit `tmp2` fallback (and an in-limit entry preferred over an earlier over-limit one), wrong-status skip, and empty list. Zero diff.
  - **L2** (`ircd-golden/tests/golden_s_conf_find_oline.rs`, fixture `find_oline.conf`): a registered `alice` runs `OPER carol secret` (name matches the `O|*@10.0.0.0/8|secret|carol|…` O-line but its host CIDR misses the 127.0.0.1 client → `find_Oline` NULL → 491 ERR_NOOPERHOST) then `OPER alice secret` (`*@*` → 381 RPL_YOUREOPER); byte-identical vs reference-C. This adds the host/CIDR-miss branch the existing `golden_s_user_oper.rs` `*@*` O-line cannot reach (it only exercises the hit + name-miss). No canonicalizer masking needed.

- **2026-06-04 — P6h (`s_conf.c` `find_conf*` family) merged.** Ported the seven read-only conf/Link-list lookups — the bite the P6g note named ("a separate later bite (P6h) with an S2S gate"). These are the read-only half of `s_conf.c`'s remaining surface; the mutating `attach`/`detach` family, the K-line lookups, and `rehash` are still C.
  - **Cluster choice.** `find_conf_exact` (global `conf`, user@host match + CONF_OPERATOR over-limit skip), `find_conf_name` (global `conf`, NULL-name/`match`), `find_conf`/`find_conf_host`/`find_conf_host_sid`/`find_conf_ip` (a passed `Link*` chain), `find_conf_entry` (global `conf`, full port+host+passwd+name match with CONF_ILLEGAL masked off). Every one is read-only; `find_conf_ip` does an in-place `@`-split of `tmp->host` it restores before continuing/returning — preserved byte-for-byte.
  - **Guard / partial port.** One shared `#if !defined(PORT_SCONF_FINDCONF_P6)` wraps s_conf.c:994-1212 (nesting the existing P6g `find_Oline` guard inside); `-DPORT_SCONF_FINDCONF_P6` added to the `s_conf_link.o` compile. The plain `s_conf.o` (cref oracle) keeps the C defs for L1.
  - **Config-resolved body.** Config-independent loops; only the bit values (`CONF_OPERATOR`=128, `CONF_SERVER_MASK`=56, `CONF_HUB`, `CONF_ILLEGAL` — bindgen consts) + struct layout matter. Reused the existing `bad_ptr()`/`max_links()`/`match_`/`mycmp` helpers; `index`→`strchr`, `bcmp`→`memcmp`, `sizeof(IN_ADDR)`→`size_of::<in6_addr>()` (AFINET=AF_INET6).
  - **Classification.** Utility/callee — not in `msgtab`. Callers (all still C, resolve to the Rust defs via the link seam): `s_serv.c` `m_server`/`m_server_estab` (the C/N-line `find_conf`, `find_conf_host` CONF_LEAF, `find_conf_host_sid` CONF_HUB, `find_conf_name` CONF_QUARANTINED_SERVER), `s_bsd.c` (server connect + registration: `find_conf`, `find_conf_ip`, `find_conf_host`, `find_conf_exact`), `s_misc.c` (`find_conf_name`). → **L1 + S2S, no client-only L2.**
  - **L1** (`ircd-testkit/tests/s_conf_find_conf_diff.rs`): hand-built parallel conf lists / `Link` chains, both `conf` and `cref_conf` pointed at the same head; `c_find_conf*` == `cref_find_conf*` pointer-for-pointer across each fn's positive + inverse — name/host/status/port/passwd-BadPtr-asymmetry misses, the CONF_OPERATOR over-limit skip (later in-limit op preferred), the server-mask `mycmp`-exact vs non-server `match`-glob split, the `>HOSTLEN`/BadPtr NUL early-outs, the empty-passwd-vs-sid-mask gate, and the `find_conf_ip` host-string-restored assertion. **The differential caught a real bug in the first draft:** I had translated C's `!match(tmp->passwd, sid)` sid gate as `match_(...) != 0` (inverted) — C's `!match` is true when the passwd-mask *matches* the sid (entry eligible), so it is `== 0`. Fixed; zero diff.
  - **S2S** (`ircd-golden/tests/golden_s2s_s_conf_find_conf.rs`): the s2s.conf fixture's `C|…peer.test`/`N|…peer.test` + `H|*||peer.test` lines mean `Peer::link()` drives `find_conf` (C/N accept), `find_conf_host` (no L line → not leaf), and `find_conf_host_sid` (empty-passwd hub gate) during `m_server_estab`. A faithful port → byte-identical burst (EOB + UNICK alice) + post-link routing (remote-user introduce → local WHOIS 311). The existing 37-test `golden_s2s_*` suite + registration goldens are the broader regression gate for the same establishment path.

- **2026-06-05 — P6i (`s_conf.c` K-line lookup family) merged.** Ported the four read-only lookups named in the PLAN P6 row — `find_kill`, `find_two_masks`, `find_conf_flags`, `find_denied` — the read-only remainder of `s_conf.c` after the P6h `find_conf*` bite.
  - **Cluster choice.** Of the remaining `s_conf.c` symbols (`find_kill`/`find_two_masks`/`find_conf_flags`/`find_denied`, the mutating `attach`/`detach`/`attach_confs*` family, `rehash`, `find_bounce`), the K-line lookups are the read-only leaves — the established P6 bite shape. They share no private statics (each walks the global `kconf`/`tkconf`/`conf` lists or `svrtop`); `find_bounce` (the RPL_BOUNCE sender) sits between `find_conf_flags` and `find_denied` and stays C (separate concern, its own future bite). The mutating `attach`/`detach`/`rehash` cluster is later still.
  - **Guard / partial port.** One macro `PORT_SCONF_FINDKILL_P6`, three `#if !defined(...)` regions (find_kill at s_conf.c:2143, find_two_masks+find_conf_flags at :2302, find_denied at :2484 — find_bounce between them left C). `-DPORT_SCONF_FINDKILL_P6` added to the `s_conf_link.o` eval recipe in `build.rs`. The plain `s_conf.o` cref oracle keeps the C defs → `cref_find_kill` etc. for L1. RED was the undefined-symbol link error for find_kill/find_two_masks/find_conf_flags/find_denied (callers: s_serv.rs `check_version`, s_user.rs `register_user`, ircd.c:289/471); GREEN confirmed via `nm target/debug/ircd` (all four `T` from Rust).
  - **Config-resolved body.** TKLINE on → find_kill's `tklines ? tkconf : kconf` two-pass `findkline:` goto (translated to a labeled `'findkline: loop`) compiles. KLINE off (kconf seeded from config K/k lines, not the runtime /KLINE). TIMEDKLINES off → the `reply`/`now`/`check_time_interval` block is not compiled, so `timedklines` is an inert `_` arg. Bit values (CONF_TKILL/TOTHERKILL/KILL/OTHERKILL/DENY/NOCONNECT_SERVER/VER) + `ConfClass(x)=x->class->class` are the only config inputs.
  - **Faithfulness notes.** find_kill: the unresolved (`ip==NULL`) vs resolved host branches, the `=`-prefixed numeric-only skip, the `match`/`match_ipmask` `/`-split, the `status==CONF_(T)KILL ? username : ident` `check` selection, the `!port || port==acpt->port` gate, and the ERR_YOUREBANNEDCREEP `sendto_one` (with the `BadPtr`→`"*"` / `": "`/`""` comment formatting) are byte-for-byte. find_denied: the `isdigit(passwd)`→`atoi`→CONF_NOCONNECT_SERVER `find_client` cross-check and the `!`-reversed `svrtop` `bcptr->name` scan (returning `conf` head for a satisfied reversed mask). Reused `match_`/`match_ipmask`/`mycmp`/`bad_ptr`/`reply`/`me_name`/`max_links`; added inetntop/ipv6string/find_client/svrtop/aServer imports + strncasecmp/strpbrk.
  - **Classification.** Utility/callees — none in `msgtab`. → **L1 + L2 (find_kill) + S2S (find_two_masks); find_denied L1-only.**
  - **L1** (`ircd-testkit/tests/s_conf_find_kill_diff.rs`): hand-built parallel kconf/tkconf/conf/svrtop state, both live globals + `cref_*` globals pointed at the same heads; `c_find_*` == `cref_find_*` over each fn's positive + inverse (9 tests, zero diff). find_kill: tkconf hit, expired-TK→kconf fallthrough, OTHERKILL→ident vs KILL→username, port match/mismatch, CIDR in/out, '='-numeric-only skip on a resolved client, resolved-hostname match, IsKlineExempt(user->flags) short-circuit, no-user guard (the HOSTLEN guard is unreachable — sockhost/username are fixed 64/11-byte buffers — so it is documented, not tested). find_two_masks/find_conf_flags: status/host/name/no-slash/prefix/strpbrk-empty inverses. find_denied: host-scan hit, reversed present/absent, name+port miss, digit-passwd empty-inner-loop, no-D-line. **A test bug (set `cptr->flags` instead of `user->flags`) was caught by the differential agreeing both returned -1 — confirming the port reads user->flags correctly.**
  - **L2** (`ircd-golden/tests/golden_s_conf_find_kill.rs`, `kline.conf`): a client from 127.0.0.1 hits `K|127.0.0.1|Banned from this server|*|0|` during register_user → killed mid-registration with `465 ERR_YOUREBANNEDCREEP` + `ERROR :Closing Link … (K-lined: …)`, byte-identical. Exercises the unresolved host match (sockhost == ip string → ip=NULL → `match(host,sockhost)`), the `*` user-mask, the zero-port gate, the `*comment=passwd` path. The miss path is covered by every other registration golden.
  - **S2S** (`ircd-golden/tests/golden_s2s_s_conf_find_two_masks.rs`, `vline_reject.conf` = s2s.conf + `V|*||peer.test|`): the peer's SERVER line reaches m_server_estab `check_version` → `find_two_masks(name,"id/info",CONF_VER)` matches the `*` version mask + `peer.test` name mask → "Bad version" exit before the burst (no EOB), byte-identical. The no-match path (no V-line → 0 → link proceeds) runs on every other `golden_s2s_*` link. find_conf_flags's match path needs a 3-token `id|misc` version (its `misc` branch) → covered at L1; its no-match path runs on every link. **find_denied** is reachable only from `try_connections` (server auto-connect timer + outbound connect) — not reachable in the golden harness → L1 only, documented.

- **2026-06-05 — P6j (`s_conf.c` `find_bounce`) merged.** Ported the RPL_BOUNCE sender named in the P6i note ("`find_bounce` (RPL_BOUNCE sender — separate concern), … its own future bite"). It is the read-only remainder of `s_conf.c` after the P6i K-line lookups; what stays C is now only the mutating cluster (`attach_conf`/`detach_conf`/`attach_confs`/`attach_confs_host`/`det_confs_butmask`/`attach_Iline`/`count_cnlines`), `rehash`, and the initconf-private `lookup_confhost`/`ipv6_convert`.
  - **Cluster choice.** `find_bounce` (s_conf.c:2407) is a self-contained read-only walk of the global `conf` list for `CONF_BOUNCE` (B-line) entries; it shares no private statics with the mutating family. The P6i bite deliberately left it C ("find_bounce sits between find_conf_flags and find_denied and stays C") because it is a *sender*, not a lookup — its observable is emitted bytes, not a return value, so it needs a different L1 shape.
  - **Guard / partial port.** New macro `PORT_SCONF_FINDBOUNCE_P6`, one `#if !defined(...)` region around s_conf.c:2407–2480. `-DPORT_SCONF_FINDBOUNCE_P6` added to the `s_conf_link.o` eval recipe in `build.rs`. The plain `s_conf.o` cref oracle keeps the C def → `cref_find_bounce` for L1. RED was the undefined-symbol link error for `find_bounce` (callers: Rust `s_user.rs` m_nick/m_user, C `s_bsd.c:1809`, C `s_conf.c:631/637` in still-C `count_cnlines`); GREEN confirmed via `nm target/debug/ircd` (`T find_bounce` from Rust).
  - **Config-resolved body.** `CONF_BOUNCE`=262144, `RPL_BOUNCE`=10 (bindgen consts). Three `fd`-keyed dispatch modes preserved byte-for-byte: `fd>=0` early rejection (cptr==NULL, class+host unknown → for an empty-host B-line, `sprintf(rpl, replies[RPL_BOUNCE], ME, "unknown", name, port)` + `strcat("\r\n")` + a **raw `sendto(fd,…)`** syscall); `fd==-1` ("too many", class known → a bare-number B-line host `!strchr('.')&&(isdigit||'-')` is matched against `class` via `atoi`); `fd==-2` (host known, class not a number → the class-number branch is skipped, host glob/`match_ipmask` only). On a match the reply goes via the variadic `sendto_one(cptr, …, BadTo(cptr->name), name, port)`. The `if/else if` ladder faithfully reproduces C's outer-if (class-number) / outer-else (`strchr('/')`→match_ipmask else `match`) nesting. Reused `reply`/`me_name`/`bad_to`/`match_`/`match_ipmask`; added `strcat`/`sendto` to the module's libc extern block (`sprintf`/`strlen`/`strchr`/`isdigit`/`atoi` were already there).
  - **Classification.** Utility/callee — not in `msgtab`. → **L1 + L2, NO S2S** (no `IsServer` branch, no remote-user fields; reads only the global `conf` + the local `cptr`).
  - **L1** (`ircd-testkit/tests/s_conf_find_bounce_diff.rs`): `find_bounce` returns `void`, so the differential captures **sent bytes**, not a return value. Both `conf` and `cref_conf` point at the same hand-built B-line head; `me.name`/`cref_me.name` set identically. fd<0 cases diff `cptr->sendQ` (`dbuf_map`) after `sendto_one`; fd>=0 cases pass a `socketpair` write end as `fd` and non-blocking `recv` the peer. 9 tests, byte-identical: host-glob hit (`:irc.test 010 * bounce.elsewhere 7000 :…\r\n`) vs miss (`continue`→empty), CIDR `/8` in-range vs out-of-range, numeric host on `fd==-1` (class==atoi hit, class≠atoi miss) vs the `fd==-2` skip (numeric host falls to host-match → miss), non-CONF_BOUNCE-entry skip + first-matching-B-line-wins (later B-line never reached), the `fd<0 && cptr==NULL` up-front guard (no-op, no UB), empty conf list, and the fd>=0 empty-host `unknown` write vs non-empty-host no-op. (Fixed mid-port: `person()` must set `acpt` non-NULL — `send_message` does `(*to).acpt->sendM += 1`.)
  - **L2** (`ircd-golden/tests/golden_s_conf_find_bounce.rs`, fixture `bounce.conf`): the only reachable client path under the locked config is the **server-only P-line** rejection in `m_nick` (Rust). `bounce.conf` makes the listener server-only (`P||||16667|0|S|`, the `S`=`PFLAG_SERVERONLY` flag in P-line field `tmp3`) and adds `B|127.0.0.1||bounce.elsewhere|7000|`. A client connecting from 127.0.0.1 sends NICK → `IsConfServeronly(cptr->acpt->confs->value.aconf)` → `find_bounce(cptr,-1,-1)` → `010` bounce (host-match branch: `match("127.0.0.1","127.0.0.1")==0`, `BadTo("*")`) → `exit_client(… "Server only port")`. Byte-identical reference-C vs Rust.
  - **No S2S** — `find_bounce` has no `IsServer` branch. The `fd>=0` raw-`sendto` early-rejection branch (caller `s_bsd.c` all-connections-in-use) needs MAXCLIENTS live connections → unreachable in the golden harness, covered at L1 only.

- **2026-06-05 — P6k (`s_conf.c` attach/detach mutating cluster) merged.** Ported the connected component of conf-attachment mutators named in the P6h–P6j "still C: the mutating family" notes — the bulk of `s_conf.c`'s remaining surface.
  - **Cluster choice.** `attach_conf` (s_conf.c:800), `detach_conf` (722), `det_confs_butmask` (389), `attach_confs` (938), `attach_confs_host` (969), + the private statics `is_attached` (781), `add_cidr_limit`/`remove_cidr_limit` (667/698). These form one connected component over shared statics + the `cptr->confs`/global-`conf`/class-refcount/CIDR-patricia mutation: `det_confs_butmask`→`detach_conf`→`remove_cidr_limit`/`free_class`/`free_conf`; `attach_confs`/`attach_confs_host`→`attach_conf`→`is_attached`/`add_cidr_limit`. `attach_Iline` + `count_cnlines` (callers of this core) stay C — a later bite (P6l) — and resolve to the Rust defs at link.
  - **Guard / partial port.** New macro `PORT_SCONF_ATTACH_P6`, three `#if !defined(...)` regions (det_confs_butmask at :389; the CIDR statics + detach_conf + is_attached + attach_conf at :666–905; attach_confs + attach_confs_host at :932–996 — the existing P6e find_admin + P6h find_conf guards sit between them). `-DPORT_SCONF_ATTACH_P6` added to the `s_conf_link.o` eval recipe in `build.rs`. The plain `s_conf.o` cref oracle keeps the C defs → `cref_attach_conf` etc. for L1. RED was the undefined-symbol link error for the five exported symbols (callers: s_serv.rs m_server_estab, s_user.rs m_oper/m_umode, s_bsd.c register/connect, s_conf.c:631 count_cnlines); GREEN confirmed via `nm target/debug/ircd` (all five `T` from Rust).
  - **Config-resolved body.** ENABLE_CIDR_LIMITS on → `add_cidr_limit`/`remove_cidr_limit` compile and are called from attach/detach. `pnode->data` is a `*mut c_void` used as an integer counter (C void-ptr arith = +1 byte; cast to long for the cap compare) → `((*pnode).data as usize).wrapping_add(1) as *mut c_void` + `(*pnode).data as usize as c_long >= cidr_amount`. YLINE_LIMITS_IPHASH on → attach_conf's per-host limit loop walks `hash_find_ip(cptr->user->sip)`/`iphnext` (ported faithfully, only entered when a ConfMax*Local/Global > 0). YLINE_LIMITS_OLD_BEHAVIOUR off → the max-links gate is `ConfLinks(aconf) >= ConfMaxLinks(aconf) && ConfMaxLinks > 0` → -3.
  - **Faithfulness notes.** detach_conf's global-conf-removal loop (`for (aconf2=&conf; ...)`) doesn't break after free — it reads `aconf3->next` into `*aconf2`, NULs `aconf3->next`, frees, and re-reads `*aconf2` (the successor) next iteration — preserved verbatim via raw `*mut *mut aConfItem` walking. The `--aconf->clients <= 0 && IsIllegal` short-circuit, the `ConfMaxLinks==-1 && ConfLinks==0` free_class+NULL, and attach_conf's get_client_ping/ConfLinks++ tail are byte-for-byte. attach_confs/attach_confs_host keep the non-server `match` / server-mask `mycmp`-exact split and always call attach_conf when the outer condition holds (the `first` check is the inner guard, not a gate on the attach). Reused match_/mycmp/bad_ptr; added free_class/free_link/make_link/get_client_ping/hash_find_ip/patricia_match_ip/patricia_make_and_lookup_ip/patricia_remove imports + the conf_is_illegal/my_connect inline macro helpers.
  - **Classification.** Utility/callees — none in `msgtab`. → **L1 + L2, NO S2S** (no IsServer branch, no remote-user fields).
  - **L1** (`ircd-testkit/tests/s_conf_attach_diff.rs`): unlike the read-only P6e–P6j lookups, these MUTATE shared state, so the two impls can't share it. Each scenario runs identically on two fully-isolated worlds via an `Api` of fn-pointers — LIVE (Rust port) over `conf`/`istat`/`classes`, CREF over `cref_conf`/`cref_istat`/`cref_classes`, each built with its own allocators — returning a `Vec<i64>` of observations (return codes, refcounts, chain shape, is_conflink delta, freed-ness) asserted equal. 8 tests, zero diff: attach happy-path + is_attached idempotency + detach round-trip (re-attach clean, counts back to baseline); IsIllegal -1 + Y-line-max -3 gates + the under-cap inverse; ENABLE_CIDR_LIMITS amount=2 admits 2 same-CIDR clients, rejects the 3rd with -4, freed slot reusable after detach; free-class on maxLinks==-1; illegal-conf removal from the global conf list (pointer gone, survivor head); det_confs_butmask keeping only the masked conf; attach_confs glob-vs-mycmp + attach_confs_host host match, each with its miss. `mk_class` wipes the struct (make_class is a bare MyMalloc — uninitialized maxH* would trip the IPHASH loop and differ between worlds; caught as the first SIGSEGV).
  - **L2** (`ircd-golden/tests/golden_s_conf_attach.rs`, `ylinemax.conf`): class 10 maxlinks 1 + an I-line binding 127.0.0.0/8. alice registers and takes the only slot (ConfLinks 0→1); bob hits the same I-line and is rejected mid-registration via attach_conf -3 EXITC_YLINEMAX → "Too many connections" exit, byte-identical. Adds the one client-reachable attach branch the existing all-success registration goldens never hit; the success + detach paths are covered pervasively by the registration + golden_s2s_* suite (confirmed green: golden_registration, golden_s2s_link/server/squit/quit/find_conf).
  - **No S2S** — attach_conf/detach_conf have no IsServer branch and format no remote-user fields. The server-link wrappers (attach_confs C/N in m_server_estab, det_confs_butmask on SQUIT) are exercised by the 37-test golden_s2s_* link-establishment + teardown suite.

- **2026-06-05 — P6l (`s_conf.c` `attach_Iline` + `count_cnlines`) merged.** Ported the two callers of the P6k attach/detach core that the P6k note explicitly deferred ("`attach_Iline`/`count_cnlines` (callers of this core) stay C — a later bite (P6l)"). **With these gone, the only `s_conf.c` that stays C is `rehash` + the initconf-private `lookup_confhost`/`ipv6_convert`.**
  - **Cluster choice.** `attach_Iline` (s_conf.c:485) — the I-line lookup used during *local client* registration: scan the global `conf` for the best `CONF_CLIENT` (I) line whose port/name/host/password match `cptr`, set the +r / kline-exempt conf flags onto `cptr->user->flags`, copy the resolved host into `cptr->sockhost` if the conf permits, then `attach_conf(cptr, aconf)`. `count_cnlines` (s_conf.c:648) — read-only walk of a passed `Link` chain returning the single `CONF_NOCONNECT_SERVER` (N) line (NULL if 0 or >1 of each C/N). Both are direct callers of the P6k core (`attach_Iline`→`attach_conf`/`find_bounce`); grouping them is the natural final `s_conf.c` bite before `rehash`.
  - **Guard / partial port.** New macro `PORT_SCONF_ILINE_P6`, one `#if !defined(...)` region wrapping s_conf.c:483–664 (the `UHConfMatch` macro — used only by `attach_Iline` — through the end of `count_cnlines`). `-DPORT_SCONF_ILINE_P6` added to the `s_conf_link.o` eval recipe in `build.rs`. The plain `s_conf.o` cref oracle keeps the C defs → `cref_attach_Iline`/`cref_count_cnlines` for L1. RED was the undefined-symbol link error for `attach_Iline` (s_bsd.c:929 check_client) + `count_cnlines` (s_bsd.c:1025 check_server); GREEN confirmed via `nm target/debug/ircd` (both `T` from Rust).
  - **Config-resolved body.** UNIXPORT off → the `IsUnixSocket(cptr)` / `aconf->host[0]=='/'` unix-path branch and the `#ifdef UNIXPORT` block drop out; only the `strchr('/')`→`match_ipmask` (CIDR) vs `UHConfMatch` (glob) host split compiles. XLINE off → the `IsConfXlineExempt`→`ClearXlined` block drops out. NO_DNS_LOOKUP on → clients register numeric, so `attach_Iline` is normally called with `hp == NULL` (the `add_local_domain`/`uhost` name-match path is the rare branch, ported faithfully + exercised at L1 with a constructed `hostent`). `UHConfMatch(x,y,z)` = `match(x, index(x,'@') ? y : y+z)`. `ConfClass(aconf)` = `(*(*aconf).class).class`.
  - **Faithfulness notes.** The `for`-loop with many `continue`s is rendered as a `loop` that advances `aconf = (*aconf).next` at the top so each `continue` mirrors the for-increment (the `break` paths — password-no-fall + the final attach — still exit cleanly). The password check is `!BadPtr(passwd) && strcmp(cptr->passwd, aconf->passwd) != 0` (C's `!StrEq` = `strcmp != 0`); `SetRestricted`/`SetKlineExempt` write `cptr->user->flags`; `get_sockhost(cptr, uhost+ulen)` copies the host tail. `count_cnlines` keeps the dead `cline` tracking verbatim (C assigns it but returns only `nline`). Reused `attach_conf`/`find_bounce`/`match_`/`match_ipmask`/`bad_ptr`/`bad_to`/`reply`/`me_name`; added `add_local_domain`/`get_sockhost`/`hostent`/`ERR_PASSWDMISMATCH`/`FLAGS_GOTID` imports + six `is_conf_*` flag helpers + `conf_class`/`uh_conf_match`.
  - **Classification.** Utility/callees — neither in `msgtab`. → **L1 + L2 (attach_Iline), L1 (count_cnlines), NO S2S.**
  - **L1** (`ircd-testkit/tests/s_conf_iline_diff.rs`): `attach_Iline` MUTATES (`attach_conf`) → two fully-isolated worlds via an `Api` of fn-pointers (the P6k `s_conf_attach_diff.rs` pattern); each scenario returns a `Vec<i64>` (return code, `aconf->clients`, class `links`, `cptr->confs` chain length, `cptr->user->flags`, `cptr->sockhost` bytes, `sendQ` bytes) asserted equal LIVE vs CREF. 8 tests, zero diff: happy glob match + the no-matching-I-line `-2` inverse; the port gate (skip vs attach); CIDR `*@10.0.0.0/8` in-range hit / out-of-range miss; empty host/name match-any; password fall-through (`F` flag → skip to the next I-line vs no-`F` → `464` sent + `-8`, second never tried) + correct-passwd attach; `CFLAG_RESTRICTED`/`CFLAG_KEXEMPT` → `FLAGS_RESTRICT`/`FLAGS_EXEMPT` on `user->flags` + the no-flag inverse; hp!=NULL name match on `user@fullname` + `get_sockhost` copy + the non-matching-name `-2` inverse. `count_cnlines`: exactly-one-N → that N, zero-N → NULL, two-N → NULL, non-server entries skipped, empty chain → NULL.
  - **L2** (`ircd-golden/tests/golden_s_conf_iline.rs`, `iline_pass.conf`): the only I-line — `I|*@127.0.0.0/8|secret|||10||` — carries a password and no `F` flag, so a client from 127.0.0.1 sending no `PASS` mismatches and, with no fall-through, is rejected mid-registration → `attach_Iline` emits `464 ERR_PASSWDMISMATCH` + returns `-8` (EXITC_BADPASS) → `register_user` exits with `ERROR :Closing Link … (Bad password)`, byte-identical reference-C vs Rust. Exercises the `!BadPtr && !StrEq` mismatch + the no-fall-through `sendto_one` path the all-success registration goldens (passwordless I-lines) never hit. The success path is covered pervasively by every other registration golden.
  - **No S2S** — neither function has an `IsServer` branch or formats remote-user fields. `count_cnlines`'s server-link reachable path (`check_server` on every inbound SERVER) is exercised by the existing 37-test `golden_s2s_*` link-establishment suite (golden_s2s_link/server/squit/quit confirmed green).

- **2026-06-05 — P6m (`s_conf.c` finalize: `rehash` + `ipv6_convert` + `lookup_confhost` + the data globals) merged.** Ported the last three `s_conf.c` functions and moved its last three data globals — **`s_conf.c` is now FULLY Rust, `s_conf.o` dropped outright** (the P6a..P6l `s_conf_link.o` partial port is gone). This closes the `s_conf.c` strand the P6l note named ("the only `s_conf.c` that stays C is `rehash` + the initconf‑private `lookup_confhost`/`ipv6_convert`").
  - **Cluster choice.** The complete remaining `nm --defined-only s_conf_link.o` set was `rehash`/`ipv6_convert`/`lookup_confhost` (T) + `conf`/`kconf`/`networkname` (B) + the file-static `rcsid` (r, unreferenced → vanishes for free). Porting all six drops the `.o`. `rehash` reaches `initconf`/`lookup_confhost`/`ipv6_convert`, so the three functions are one natural final bite; the globals must move with them (they were the last s_conf.c-owned data).
  - **Drop mechanism.** Added `s_conf.o` to `PORTED`, removed the `"s_conf.o" => "s_conf_link.o"` entry in `link_objs()` + the whole `s_conf_link.o` `make --eval` recipe in build.rs. The cref oracle keeps the full unguarded `s_conf.o` (CREF_OBJS) so the `cref_*` symbols survive for every existing s_conf L1 diff. RED was the undefined-symbol link error for rehash/ipv6_convert/lookup_confhost/conf/kconf/networkname (callers: list.rs `delist_conf`, s_serv.rs `report_configured_links`/`m_connect`/`m_rehash`, s_conf.rs's own already-ported lookups, ircd.c SIGHUP); GREEN confirmed via `nm target/debug/ircd` (all six `T`/`B` from Rust).
  - **Data-global move.** `conf`/`kconf`/`networkname` flip from `use ircd_sys::bindings::{…}` to `#[no_mangle] pub static mut` defs in s_conf.rs (the `tkconf`/`classes`/`msgtab` pattern). list.rs + s_serv.rs keep importing them from bindings — those externs resolve to the new Rust defs at link. Only s_conf.rs had to stop importing them (can't import + define the same name); also removed its now-conflicting `ipv6_convert` import + the P6f `extern { fn lookup_confhost }` decl + the P6f `networkname` import.
  - **Config-resolved bodies.** `rehash` (s_conf.c:1231): ULTRIX off (no fork/pidfile), USE_SYSLOG off, TKLINE on (the `sig=='t'` → `tkline_expire(1)` block compiles). The two `aConfItem**` walk loops (the in-use/ILLEGAL marking pass + the post-initconf flush) are rendered as raw `*mut *mut aConfItem` `loop`s preserving C's `*tmp = tmp2->next` vs `tmp = &tmp2->next` branch exactly; `IsMe(acptr)` = `status == STAT_ME` inline; `NextClass(FirstClass())` = `(*classes).next`, `MaxLinks(x)=-1` = `(*x).maxLinks=-1`; `mysrand(timeofday)` casts to `u32`; the `read_motd(IRCDMOTD_PATH)` path comes from `ircd_sys::MOTD_PATH`. `ipv6_convert` (s_conf.c:1444): faithful pointer arithmetic — the `user@` copy-with-'@', the `/cidr` NUL-off before `inetpton`, the `j=len-1`/`buf+j` splice, the `*(s-1)='/'` restore (C's post-incremented `s` = my `slash.add(1)`), non-IP passthrough (`t=orig`). `lookup_confhost` (s_conf.c:2101): `BadPtr` guards, `@`-tail, `isalpha||isdigit` first-char gate, `inetpton` (nonzero=stored) else `gethost_byname` (still-C) `h_addr_list[0]` copy else `minus_one` fill + badlookup; `AND16(ipnum)==255` (all 0xff) → `bzero` 16 bytes.
  - **IRCDMOTD_PATH plumbing.** `read_motd` is already Rust (s_misc.rs) but `IRCDMOTD_PATH` is a recursively-expanded Makefile path var, not a header `#define` (absent from bindgen). build.rs expands it via `make --eval=__ircd_print_motd` and emits `cargo:rustc-env=IRCD_MOTD_PATH=…`; ircd-sys/src/lib.rs re-exports it as `pub const MOTD_PATH = env!("IRCD_MOTD_PATH")` (rustc-env applies only to the emitting crate, so the const bridges it to ircd-common). The Rust `rehash` builds a temporary `CString` from it — `read_motd` only opens the path, never retains it.
  - **Classification.** Utility/callees — none in `msgtab`. `rehash` is reached from Rust `m_rehash` (oper REHASH) + still-C `ircd.c` (SIGHUP); `ipv6_convert`/`lookup_confhost` from the Rust `initconf` at boot/rehash. → **L1 (ipv6_convert) + L2 (existing REHASH + initconf goldens), NO S2S** — none has an `IsServer` branch or formats remote-user fields (REHASH server propagation is `m_rehash`'s concern, ported in P5rr).
  - **L1** (`ircd-testkit/tests/s_conf_rehash_diff.rs`): `c_ipv6_convert` vs `cref_ipv6_convert` over bare-v6 (`::1`), `2001:db8::1`, v4-mapped (`::ffff:127.0.0.1`), `user@v6`, `v6/cidr`, `user@v6/cidr`, and non-IP passthrough (`*@*`, `notanip`, `notanip/24`, `bob@notanip`) on independent input copies, asserting byte-identical output **and** that the in-place `@`/`/` poke was restored. `lookup_confhost` is `static` in the unguarded oracle (the symbol-rename only renames globals → no `cref_lookup_confhost`) so it has no L1 shape → covered by the initconf/boot golden (`initconf` calls it on every conf host). `rehash` reopens listeners / forks iauth / resets the resolver fd → no isolated-L1 shape → covered by the L2 REHASH transcript.
  - **L2** (`golden_s_serv_maint` REHASH: `rehash_success_matches_reference` 382 + `rehash_reject_matches_reference` 481 now drive the Rust `rehash`, byte-identical; `golden_s_conf_initconf` STATS y/i/o over the boot-parsed config exercises `lookup_confhost`/`ipv6_convert`). Regression: `golden_registration`, `golden_s2s_link`, `golden_s2s_s_conf_find_conf`, `golden_s_conf_iline`/`attach` + all s_conf L1 diffs stay green (the conf/kconf data-global move touches every conf consumer).
  - **No S2S** — none of the three has an `IsServer` branch or remote-field formatting. The REHASH command's server-to-server propagation lives in `m_rehash` (P5rr); `rehash` itself only reloads local config + the resolver/iauth fds.

- **2026-06-05 — P6n (`res_comp.c` — BIND DNS wire-format primitives) merged.** The pure wire-format leaf of the resolver, ported outright to `ircd-common/res_comp.rs`; `res_comp.o` added to `PORTED` and dropped (no partial `_link.o` — every symbol is portable).
  - **Cluster choice** — `res_comp.c` is the foundation the rest of the resolver builds on: `res_mkquery.c` (`ircd_dn_comp`/`ircd__putshort`/`ircd__putlong`) and `res.c` proper (`ircd_dn_expand`/`ircd_getshort`/`ircd_getlong`/`__ircd_dn_skipname`) both call into it. It is the natural first DNS bite — fully self-contained, pure, no event-loop entanglement. The remaining resolver TUs (`res_mkquery.c`, `res_init.c`, `res.c` proper) stay C for a later P6 cluster.
  - **Config** — no gates touch this TU. The `#if 0` block (`res_hnok`/`res_ownok`/`res_mailok`/`res_dnok`) is dead code (not compiled); the `NEXT`-gated `res_getshort` is absent. `nm --undefined-only cbuild/res_comp.o` = only libc (`memcpy`/`strchr`/`__errno_location`) → zero ircd-internal deps.
  - **Classification** — utility/leaf TU: none of its 7 public symbols appear in `msgtab`. The seven are global (`T`) so each has a `cref_` oracle → fully L1-diffable. The 7 BIND `static` helpers (`ns_name_ntop`/`_pton`/`_unpack`/`_pack`/`_uncompress`/`_compress`/`_skip`, `special`/`printable`/`mklower`/`dn_find`) have no oracle → ported as private Rust fns, covered transitively through the public entry points.
  - **Faithfulness** — faithful raw-pointer/`unsafe` port mirroring the C pointer arithmetic exactly (label-length bytes, the `0xc0` compression-pointer encode/decode, the `dnptrs`/`lastdnptr` table walk + mutation in `dn_find`/`ns_name_pack`, `dn_comp`'s post-increment `*dnptrs++` so `dn_find` sees `dnptrs[1..]`). `errno` set via `*libc::__errno_location()` to `EMSGSIZE`/`ENOENT` on every error path so callers observe the identical side effect. The `goto next` in `dn_find` became a labelled `'outer` loop. Constants `NS_CMPRSFLGS=0xc0`/`NS_MAXCDNAME=255`/`MAXCDNAME=255` from `nameser_def.h`.
  - **L1** (`ircd-testkit/tests/res_comp_diff.rs`, 9 tests, zero diff) — get/put value match + big-endian byte order + put→get round-trip; `dn_comp`→`dn_expand` pack/expand round-trip (incl. root `.`); the compression-pointer reuse (two suffix-sharing names) diffed as buffer-relative `dnptrs` offsets + the emitted wire bytes against `cref_`; a hand-built compressed-pointer message (`0xc0` indirection) → identical decoded string + consumed-octet count; `dn_skipname` over plain/compressed/truncated names; and the inverse error paths — dstsiz-too-small (expand + comp), malformed out-of-range pointer — each returning `-1` from both with matching `errno`.
  - **L2 / S2S** — none. Pure wire-format leaf with no client- or server-reachable command path under the locked config (the resolver proper that uses these is still C; `m_dns` debug output does not surface compression internals). End-to-end DNS coverage arrives when the resolver proper is ported under a fixture nameserver.
  - **Plan** — `docs/superpowers/plans/2026-06-05-p6n-res_comp.md`.

- **2026-06-05 — P6o (`res_mkquery.c` → `res_mkquery.rs`) merged.** The BIND-derived DNS query-packet builder `ircd_res_mkquery`, the second resolver leaf after P6n. **`res_mkquery.o` dropped outright** (added to `PORTED`; no `_link.o`).
  - **Cluster choice** — `nm cbuild/res_mkquery.o`: one defined symbol (`ircd_res_mkquery`); undefined deps are `ircd_dn_comp`/`ircd__putshort`/`ircd__putlong` (Rust, P6n), `ircd_res`/`ircd_res_init` (stay C, res_init.o), `memmove`/`__h_errno_location`/libc. Dropping it leaves every dep defined, so it's a clean single-function bite.
  - **Layout hazard / HEADER bitfields** — the function writes the 12-byte DNS header through a `HEADER *` bitfield struct (`nameser_def.h:249`: `id:16`/`opcode:4`/`rd:1`/`rcode:4`/`qdcount:16`/`ancount:16`/`arcount:16`). Rather than hand-reproduce gcc's little-endian bitfield packing, the port uses the **bindgen `HEADER`** type (`ircd_sys::bindings`, asserted size 12) and its `set_*` accessors, which are byte-identical to the C layout by construction. `htons` reproduced as `u16::to_be`; `h_errno = NETDB_INTERNAL` via an `extern "C" { fn __h_errno_location() }`. `bzero`→`ptr::write_bytes`, `bcopy`→`ptr::copy`.
  - **Config-resolved body** — `DEBUG` off → the `RES_DEBUG` `printf` block is not compiled (not ported). Three op cases: QUERY/NS_NOTIFY_OP (shared question-section path + the optional additional-record branch when `data != NULL`), IQUERY (answer section), default → `-1`.
  - **Classification** — utility/leaf, not in `msgtab`; callers are the still-C `res.c` resolver (`query_name`/`do_query_name`/`do_query_number`). No client/server command path under NO_DNS_LOOKUP ⇒ **L1 only**, like P6n.
  - **L1** (`ircd-testkit/tests/res_mkquery_diff.rs`) — `c_res_mkquery` (`#[link_name]` → Rust) vs `cref_ircd_res_mkquery`, byte-identical packets (return length + emitted bytes) over: QUERY with/without RES_RECURSE (the `rd` bit), NS_NOTIFY_OP with `data==NULL` (matches QUERY) and `data!=NULL` (the additional-record `dn_comp`+T_NULL+ttl+rdlength+arcount path), IQUERY with `datalen>0` and `==0`; plus the `-1` inverses — unknown op, NULL buf, `buflen<HFIXEDSZ`, and the question-section `buflen -= QFIXEDSZ < 0` / `dn_comp < 0` overflow at several small buflens. Both resolver-state globals (`ircd_res`, `cref_ircd_res`) are pinned identically with `RES_INIT` set (skips the nondeterministic `ircd_res_init`/`res_randomid` gettimeofday+getpid path) and the shared `++id` side effect is diffed after every call. A process-global `RES_LOCK` serializes the parallel `#[test]` threads (the globals are shared across threads in the one test process — without the lock the `id` races and the header bytes diverge). Zero diff over 7 tests.
  - **No S2S/L2** — pure wire-format leaf, no `IsServer`/remote-field/command path. End-to-end DNS coverage lands with the resolver proper (`res.c` + `res_init.c`) under a fixture nameserver.

- **2026-06-05 — P6p (`res_init.c` resolver-state bootstrap) merged.** Ported `ircd/res_init.c` outright to `ircd-common/res_init.rs` → `res_init.o` dropped; only `res.c` (the resolver proper) is still C in P6.
  - **Cluster choice.** The smaller, self-contained of the two remaining DNS files. `nm cbuild/res_init.o` defines `ircd_res` (B), `ircd_res_init`/`ircd_res_randomid` (T), and the file-static `res_setoptions` (`.isra.0`); `nm --undefined-only` shows zero ircd-internal deps — only libc + `inetpton` (the P1 `support.rs` symbol). Same self-contained-leaf shape as P6n/P6o → drop the `.o` (add to `PORTED`), no `_link.o`.
  - **Config-resolved body.** Verified `DEBUG`/`NEXT`/`RESOLVSORT`/`RFC1535`/`HAVE_GETIPNODEBYNAME`/`USELOOPBACK`/`__BIND_RES_TEXT` all OFF in `cbuild/{setup,config}.h` + `build.rs` defines. So: `ircd_res` is a plain zero-init BSS global (no `= {RES_TIMEOUT,}`); `ircd_res_init` is the simple path only (defaults → `LOCALDOMAIN` block → `/etc/resolv.conf` parse loop with the `MATCH` macro + `inetpton(AF_INET6,…)` nameservers → `gethostname` fallback → the `#ifndef RFC1535` default-`dnsrch` derivation `LOCALDOMAINPARTS=2`/`MAXDFLSRCH=3` → `RES_OPTIONS` env → `options |= RES_INIT`), no NetInfo/`ircd_netinfo_res_init`, no sortlist; `res_setoptions` handles `ndots:` (clamp to `RES_MAXNDOTS=15`), `inet6` (→`RES_USE_INET6=0x2000`), `debug` (no-op, DEBUG off); `res_randomid` = `0xffff & (tv_sec ^ tv_usec ^ getpid())`.
  - **Faithfulness.** Raw-pointer port mirroring the C: `strncpyzt`→`strncpy`+NUL; the two near-identical search-list tokenizers inlined faithfully (the `LOCALDOMAIN` one breaks on `\n`, the file `search` one doesn't); `dnsrch[]` pointers walk into `defdname`; nsaddr `sin6_addr`=in6addr_any (16 zero bytes) / `sin6_family`=AF_INET6 / `sin6_port`=htons(53); `ndots` written via the bindgen `set_ndots` bitfield accessor. `ircd_res` defined as `#[no_mangle] static mut` via `MaybeUninit::zeroed().assume_init()` (the `s_misc.rs::ircst` idiom); `res_mkquery.rs`/`res.c`/`s_bsd.c` keep importing `ircd_res`/`ircd_res_init` from bindgen and resolve to the Rust defs at link (the conf/kconf-globals mechanism).
  - **Classification.** Utility/leaf (none in `msgtab`); no `IsServer`/remote-field path.
  - **L1.** `ircd-testkit/tests/res_init_diff.rs`: zero diff vs `cref_ircd_res_init`. Both `ircd_res`/`cref_ircd_res` zeroed + `.id` pinned `0x4321` per test (skip the nondeterministic `res_randomid`); env-set + both inits + env-restore under a process-global `RES_LOCK` (parallel `#[test]` threads share the env + globals). The result structs diffed field-by-field (scalars/bitfields, 3× `nsaddr_list` `sockaddr_in6` bytes, `defdname` bytes, `dnsrch[]` as offsets into `defdname`). The differential makes the `/etc/resolv.conf`+`inetpton` path host-robust (both read the same file → identical, or both skip it); the host-independent branches run on every CI host via env — `plain` (default-`dnsrch`), `LOCALDOMAIN` (search tokenizer), `RES_OPTIONS` `ndots:3 inet6` and `ndots:99` (the `RES_MAXNDOTS` clamp). `res_randomid` nondeterministic → only `& 0xffff` smoke-tested (the one symbol with no L1 diff).
  - **L2/S2S.** None — pure leaf, no client/server command path under `NO_DNS_LOOKUP`. Boot+registration (`golden_registration`) and the resolver-adjacent `golden_s_dns` goldens stay byte-identical, confirming the Rust `ircd_res_init`/`ircd_res` (called from `s_bsd.c` at startup) boot the server identically to reference-C. End-to-end DNS coverage (L2/L4) arrives when the resolver proper `res.c` is ported under a fixture nameserver.

- **2026-06-05 — P6q (`res.c` cache-hash leaves) merged.** First bite of the `res.c` port — the last C file. `res.c` is one large connected cluster (resolver socket + request queue + hostent cache) over file-statics with only 11 `_ext.h`-exported entry points; the dependency floor is the **hostent cache**, whose foundation is the two pure hash leaves `hash_number`/`hash_name`. Ported bottom-up so the cache core (`make_cache`/`update_list`/`find_cache_*`/`rem_cache`, P6r+) can build on Rust hashes.
  - **Cluster choice** — only `hash_number`/`hash_name` (pure: read solely their argument, touch no module state → zero data-global exposure), keeping this bite about establishing the new `res.c` static seam on a trivially verifiable pair before the gnarly cache core.
  - **Guard / seam** — new three-way `RES_CACHE_LINKAGE` macro in `res.c`: `extern` under `-DPORT_RES_CACHE_P6q` (res_link.o LINK build: bodies `#ifndef`'d out → Rust defines them, still-C walkers resolve to Rust at link), empty under `-DRES_CACHE_EXPOSE` (cref oracle res.o: GLOBAL → `cref_hash_*` for L1), else `static` (plain). `build.rs`: res_link.o gains `-DPORT_RES_CACHE_P6q`; a new step recompiles the cref `res.o` with `-DRES_CACHE_EXPOSE` (overwrites the plain one — res.o is consumed only by `libcref.a`, the link set uses res_link.o, so the real binary is untouched). RED confirmed: dropping the C bodies left 8 undefined `hash_name`/`hash_number` refs from the still-C walkers (res.c:1084/1088/1282/1316/1337/1382/1583/1600) — the exact port checklist.
  - **Config-resolved body** — neither function is config-gated; `ARES_CACSIZE`=1009.
  - **Faithfulness** — `hash_number`: `hashv = ip[0]; for i in 1..16 { hashv = 2*hashv + ip[i] }` over a **wrapping `u_int`** (the doubling overflows 32 bits for large addresses — `% ARES_CACSIZE` applied only at the end), reads exactly 16 bytes (sizeof struct in6_addr; AFINET=AF_INET6) → `wrapping_add`/wrapping double. `hash_name`: sum bytes until the first `.`/NUL, `% 1009`; `char` is **signed** on x86-64, so a high-bit byte promotes to a negative `int` before the unsigned `+=` — replicated via `*p as i32 as u32` + `wrapping_add` for 8-bit-clean parity. Mutable `*mut` args (C `u_char*`/`char*`). Returns `c_int` in `[0,1009)`.
  - **Classification** — utility/leaf, **not in `msgtab`**, no client/server command path (the resolver is inert under `NO_DNS_LOOKUP`; the cache never populates at runtime).
  - **L1** — `ircd-testkit/tests/res_hash_diff.rs`: Rust `hash_number`/`hash_name` (`#[link_name]` → the only def once res_link.o drops the C bodies) vs `cref_` over crafted corpora — 16-byte v6 addrs (zero, all-0xff overflow, single-bit, ::ffff: v4-mapped, every-byte-high-bit, random), names (empty, dot-first, no-dot, embedded-dot, case-sensitive, UTF-8/0xff high-bit, long label); each result range-checked `[0,1009)`. Zero diff. Both pure → no global state / no `RES_LOCK`.
  - **L2 / S2S** — none. No client/server command reaches these under the locked config; `golden_s_dns` + the registration/boot goldens (which boot the full ircd + still-C resolver, exercising the C cache walkers that now call the Rust hashes) confirm no regression. End-to-end DNS coverage arrives when the resolver proper is ported under a fixture nameserver.

- **2026-06-05 — P6r (`res.c` cache removal/expiry core) merged.** Second bite of the `res.c` port (after P6q's `hash_number`/`hash_name`). Ported the **removal/expiry** connected component — the half of the hostent cache that *deletes* entries — to `ircd-common/res.rs`, built directly on the P6q Rust hashes. `res.c`'s only remaining strands are the resolver proper (socket + request queue + answer parser) and the cache **build/insert/lookup** half.
  - **Cluster choice.** Bottom-up from the cache floor: `rem_list` (static), `rem_cache` (static), `expire_cache` (global, res_ext.h), `flush_cache` (global, res_ext.h). They form a clean connected component — `expire_cache`/`flush_cache` both call `rem_cache`; `rem_cache`/`rem_list` call only the P6q hashes + touch the cache data structures — with no dependency on the still-C build/insert/lookup half (`add_to_cache`/`update_list`/`find_cache_*`/`make_cache`). The two public entry points give clean `cref_` L1 symbols; the two statics are exposed via the generalized `RES_CACHE_LINKAGE`.
  - **Seam.** `-DPORT_RES_CACHE_REM_P6r` added to the `res_link.o` recipe. `RES_CACHE_LINKAGE` now fires `extern` under either `PORT_RES_CACHE_P6q` **or** `PORT_RES_CACHE_REM_P6r` (res_link.o defines both), so the `rem_cache`/`rem_list` forward decls + definitions de-static; their bodies (+ `expire_cache`/`flush_cache`) are wrapped in `#ifndef PORT_RES_CACHE_REM_P6r`. RED (after fixing a static-vs-non-static decl mismatch on the definitions) was the four undefined refs: `flush_cache` (Rust `s_conf.rs` rehash), `expire_cache` (C `ircd.c:1195`), `rem_list` (C `res.c:1379` find_cache_number), `rem_cache` (C `res.c:1119` add_to_cache) — the exact port checklist. GREEN confirmed via `nm target/debug/ircd` (all four `T` from Rust).
  - **Data-global exposure.** The Rust removal core + the L1 live world need `cachetop`/`cainfo` (already `RES_DNS_STATIC`-exposed for m_dns) **plus** `hashtable[]`/`incache`. `RES_DNS_STATIC` now also blanks `static` under `RES_CACHE_EXPOSE` (so the cref oracle res.o exposes `cref_cachetop`/`cref_cainfo`/`cref_hashtable`/`cref_incache`/`cref_reinfo` for the L1 isolated worlds), and `hashtable`/`incache` moved onto it. In res_link.o (which has `PORT_DNS_M_DNS`) all four stay **defined-global** — C owns the storage, the Rust core + the L1 live world extern them, same as P6k's `conf`. No extern/definition split needed (so no `= NULL`/array-initializer churn). `res.rs` adds `static mut hashtable: [CacheTable; 1009]` + `static mut incache: c_int` to its extern block + `local_base()`/`hashtable_base()` helpers.
  - **Faithfulness.** Raw-pointer walks mirroring the C `aCache **` chains exactly. `rem_list` captures `cp->list_next` first, unlinks from `cachetop` only, `MyFree`s, returns the saved successor — and (the C quirk preserved) does **not** decrement `incache`, touch `cainfo`, or unlink the hash buckets (leaving the freed entry's bucket refs dangling). `rem_cache`'s hostp-clearing loop walks `local[]` from `highest_fd` down; the bucket-by-`hash_name`/`hash_number` unlinks use `hp->h_addr` = `h_addr_list[0]`; `MyFree(x)` → guarded `libc::free` (the macro's re-NULL is moot — the struct is freed; `*h_addr_list` is one contiguous block freed once, then the pointer array). `expire_cache` captures `list_next` before the possible free and returns `(next > now) ? next : now + AR_TTL`.
  - **Classification.** Utility/leaf — none in `msgtab`. **L1 only** — the resolver is inert under `NO_DNS_LOOKUP`, the cache never populates at runtime, so no client/server command path reaches these. No S2S (no `IsServer`/remote-field path).
  - **L1** (`ircd-testkit/tests/res_cache_rem_diff.rs`): the P6k two-isolated-worlds pattern. A `World` bundles fn-pointers + global base pointers (`cachetop`/`hashtable`/`incache`/`cainfo` **and** `local`/`highest_fd` — the hostp loop reads s_bsd globals, which are renamed to `cref_local`/`cref_highest_fd` in the archive, so each world must own its own). Entries are hand-built mimicking `add_to_cache` (one contiguous 16×n address block with `h_addr_list[i]` pointing into it + per-name strdup'd aliases, so `rem_cache`'s frees match `make_cache`'s layout), then the public fns are driven and `Vec<i64>` observations asserted equal. 4 tests, zero diff: **flush_cache** (3 mixed single/multi-alias/multi-addr entries → `cachetop`/buckets empty, `incache` delta 0, `ca_dels`==3; round-trip re-insert + re-flush clean), **expire_cache** (two past + two future at `now=5000` → past removed, survivors kept in order, `incache` -=2, `ca_expires` delta 2, return = min-future 7000; the all-future inverse returns min expireat not `now+AR_TTL`; empty-cache returns `now+AR_TTL`), **rem_cache hostp** (a per-world `local[0]->hostp` at the doomed entry is NULLed, an unrelated `local[1]->hostp` untouched), **rem_list** (returns the successor, unlinks the middle from `cachetop`, `incache` **unchanged** — the leak-by-design quirk — then head + last removal empties the list). A process-global `Mutex` (poison-tolerant) serializes the `#[test]`s (shared cache + s_bsd globals).
  - **No L2/S2S.** Resolver inert under `NO_DNS_LOOKUP`; `golden_s_dns` (oper DNS stats + empty `DNS l` cache dump) + `golden_registration` stay byte-identical, confirming the still-C `add_to_cache`/`find_cache_number` now call the Rust `rem_cache`/`rem_list` (+ the P6q hashes) without regression. End-to-end DNS coverage arrives when the resolver proper is ported under a fixture nameserver.
  - **Plan** — `docs/superpowers/plans/2026-06-05-p6r-res-cache-rem.md`.

- **2026-06-05 — P6s (`res.c` cache lookup/reorder half) merged.** Third bite of the `res.c` port (after P6q's hashes + P6r's removal core). Ported the **lookup/reorder** connected component — the half of the hostent cache that *finds* entries and *reorders/merges* them — to `ircd-common/res.rs`. `res.c`'s only remaining strands are the resolver proper (socket + request queue + answer parser) and the cache **build/insert** half (`make_cache`/`add_to_cache`, → P6t).
  - **Cluster choice.** Bottom-up from the cache floor: `update_list` (static) is the shared leaf both finders call; `find_cache_name`/`find_cache_number` (static) are the lookup entry points. A clean connected component — the finders call `update_list` (+ the already-Rust P6r `rem_list` in `find_cache_number`'s degenerate branch) and touch only `cachetop`/`hashtable`/`cainfo` + `mycmp`/`MyRealloc`/`mystrdup`; no dependency on the still-C build/insert half. Splitting the cache "build/insert/lookup" remainder into lookup (P6s) then build/insert (P6t) keeps the bite small, matching the P6q/P6r cadence.
  - **Seam.** `-DPORT_RES_CACHE_LOOKUP_P6s` added to the `res_link.o` recipe; the three-way `RES_CACHE_LINKAGE` now fires `extern` under `PORT_RES_CACHE_P6q` **or** `PORT_RES_CACHE_REM_P6r` **or** `PORT_RES_CACHE_LOOKUP_P6s` (res_link.o defines all three guards), GLOBAL under `RES_CACHE_EXPOSE` (cref oracle), else static. The three forward decls (res.c:84/85/91) + definitions flip `static` → `RES_CACHE_LINKAGE`; the bodies (update_list … find_cache_number, res.c:1140–1406) wrap in `#ifndef PORT_RES_CACHE_LOOKUP_P6s`. RED was the undefined-symbol link error for `find_cache_name`/`find_cache_number` (still-C callers `gethost_byname_type`:410, `proc_answer`:776, `gethost_byaddr`:440, `make_cache`:1440/1456 — the exact port checklist; `update_list` had no still-C reference once the finders dropped, but Rust defines it for the finders to call). GREEN via `nm target/debug/ircd | grep -E ' T (update_list|find_cache_name|find_cache_number)$'`. (A C-comment gotcha: `gethost_*/proc` and `find_cache_*/cref` each contain a literal `*/` that prematurely closed the seam comment → reworded.)
  - **Config-resolved bodies.** No gates touch these (`DEBUG` off → the `Debug(...)` blocks vanish). `IN_ADDR`=`in6_addr` (sizeof 16, AFINET=AF_INET6); `WHOSTENTP(x)`=OR of the 16 `s6_addr` bytes; `S_ADDR`=`s6_addr`. `ResRQ.he` is the inline `hent` (`h_addr_list:[in6_addr;35]`, `h_aliases:[*char;35]`); `aCache.he` is the libc `hostent` (`**char` lists). Constants T_A=1/T_PTR=12/T_AAAA=28, MAXALIASES/MAXADDRS=35, FLG_*.
  - **Faithfulness.** Raw-pointer translation of the C for-loops with post-increment index walks (`for (i=0,s=h_name; s; s=h_aliases[i++])` → `s = *aliases.offset(i); i+=1` at the loop tail), incl. the `find_cache_name` full-list fallback's **fixed-`s`=alias[0] quirk** (`s` set only in the init, never in the increment → it only ever compares alias[0]). `update_list`'s T_PTR alias-merge reallocs `h_aliases` by one + `mystrdup`s the new name; the T_A/T_AAAA addr-merge reproduces the double-`MyRealloc` exactly — realloc the contiguous IP block (`*h_addr_list[0]`) to `addrcount*16`, realloc the pointer array to `addrcount+1`, repoint each pointer into the (possibly moved) block, NULL-terminate, `bcopy` the new IP into the last slot (`*--ab`) — then the `addrcount>1` → clear `FLG_PTR_FWD|VALID` vs the single-addr `FLG_PTR_PEND_REV`/`FLG_PTR_PEND_FWD` logic. `find_cache_number`'s second loop preserves the C for-loop `continue`→increment semantics (every guard incl. the `cp = rem_list(cp)` degenerate-reap falls through to the trailing `cp = cp->list_next`). `bcmp`→16-byte slice compare; `MyRealloc`/`mystrdup`/`mycmp` are the Rust ports resolved at link.
  - **Classification.** Utility/leaf — none in `msgtab`. → **L1 only.** No `IsServer`/remote-field path; the resolver is inert under `NO_DNS_LOOKUP` so no client/server command populates the cache at runtime.
  - **L1** (`ircd-testkit/tests/res_cache_lookup_diff.rs`): the P6k/P6r two-isolated-`World`s pattern (fn-pointers + global base pointers: `cachetop`/`hashtable`/`cainfo` + `find_cache_*`/`update_list`/`hash_*`). `insert()` builds entries à la `add_to_cache` (contiguous addr block); `make_rptr()` builds a `ResRQ` per world (each owns its pointers → compare CONTENTS not pointers). 6 tests, zero diff: **update_list reorder-only** (rptr=NULL: head move keeping relative order, `ca_updates` bump, repeat on the head = no-op); **find_cache_name** hashed hit + reorder + `ca_na_hits` / name-miss (counter unchanged, order kept) / flags-gate miss / the alias full-list fallback (h_name & alias[0] in distinct hash buckets); **find_cache_number** hashed hit + `ca_nu_hits` / absent-addr miss / FLG_PTR_VALID gate miss / the multi-addr fallback (lookup the 2nd of two addresses, found only via the full-list scan); **update_list T_PTR alias merge** (append a new name) + the already-present (= cached h_name) no-growth inverse; **update_list T_A addr merge** (append a new IP, addrcount→2 flag clear) + the already-present no-growth inverse (single-addr `FLG_PTR_PEND_FWD` set). A process-global `Mutex` serializes the `#[test]`s; each scenario `reset()`s its world's cache + buckets and snapshots counter deltas.
  - **No L2/S2S.** Resolver inert under `NO_DNS_LOOKUP`; `golden_s_dns` (oper DNS stats + empty `DNS l`) + `golden_registration` stay byte-identical, confirming the still-C `proc_answer`/`gethost_*`/`make_cache` now call the Rust lookup/reorder core (+ the P6q hashes + P6r removal) without regression. End-to-end DNS coverage arrives when the resolver proper is ported under a fixture nameserver.
  - **Plan** — `docs/superpowers/plans/2026-06-05-p6s-res-cache-lookup.md`.
