···5757- [leveva channel-merge works](leveva-channel-merge-works.md) — split-then-merge of two independent same-name channels preserves both members + op on HEAD; couldn't repro "remote member missing" post-129; two-node port-lock is process-local (use unique ports per test binary)
5858- [leveva LINK_VERSION 021- staleness](leveva-link-version-021-staleness.md) — recurring pre-existing red: PASS-greeting tests/snapshots go stale vs server::LINK_VERSION (021- prefix); fix as a separate prep commit, git-stash to confirm pre-existing
5959- [leveva S2S handshake diagnostics](leveva-link-version-021-staleness.md) — read_link_handshake now surfaces a peer's ERROR refusal + EOF/port hints + a 30s idle timeout (was a blind "did not complete"); a connect{} to a client port like 6667 is the classic cause
6060+- [leveva TS + link fixes (slices 131-133)](leveva-ts-and-link-fixes-131-133.md) — connect-dedup (LinkingSet, no re-dial mid-handshake glare) + server-intro broadcast (announce_linked_peer to siblings); channel-ts/user-ts CAPAB tokens carry timestamps as ENCAP-wrapped unix-NANOSECONDS, oldest wins (deop younger chanops / evict younger nick to its UID); the USERTS-before-UNICK buffering + the cross-task Envelope::ForceNick primitive
···11+---
22+name: leveva-ts-and-link-fixes-131-133
33+description: P11 slices 131-133 — S2S link-establishment fixes (connect dedup + server-intro broadcast) and channel-ts/user-ts timestamp propagation (oldest wins); the ENCAP-ns TS pattern + the ForceNick cross-task primitive
44+metadata:
55+ node_type: memory
66+ type: project
77+ originSessionId: 38e01f00-bed4-46fd-983a-cf57b6a18eca
88+---
99+1010+P11 slices 131–133 (2026-06-13), all leveva-native (no oracle differential for the new bits):
1111+1212+**131 — link-establishment fixes (two production glare bugs from nophica/althyk logs).**
1313+- `link::LinkingSet` (per-`ServerContext` `linking` field): names with an outbound dial in
1414+ flight. `try_begin(name)`→RAII `LinkGuard` or `None` if already dialing. `dial_server` (the
1515+ single chokepoint for ALL outbound dials) skips if already linked, else holds a guard for the
1616+ task's life; `auto_connect_loop` folds `linking.contains` into the `is_linked` predicate. Closes
1717+ the re-dial-while-mid-handshake glare (`… (Operation now in progress)` = EINPROGRESS). Extends
1818+ [[leveva-outgoing-autoconnect]].
1919+- `s2s::server::announce_linked_peer(ctx, new_peer)` broadcasts `:<our_sid> SERVER <name> <hop+1>
2020+ <sid> …` to every OTHER peer (split-horizon), called from `serve_linked_peer` after `peers.link`.
2121+ The burst introduces known servers TO the new peer; `handle_server` only relays DEEPER bursted
2222+ servers — a directly handshake-linked peer was never announced to its siblings. Prefix = OUR sid
2323+ (we're the introducer), NOT `rs.uplink` (which == the peer's own sid for a direct peer).
2424+2525+**The TS-over-ENCAP pattern (132/133).** Both timestamps ride `ENCAP` in **unix nanoseconds**
2626+(leveva's native clock; an IRCnet oracle routes `ENCAP` to `m_nop` and ignores it). Two new CAPAB
2727+tokens in `PeerCaps`: `channel-ts`, `user-ts` (added to `ours()` + `from_capab`). Extends
2828+[[leveva-s2s-peer-caps]]. **Oldest (lowest) TS wins.** When adding ANY new burst ENCAP extension:
2929+the golden canonicalizer (`leveva/tests/harness/mod.rs`) must mask its ts, and
3030+`s2s_skeleton_differential` must exclude the line (the shared `verb_skeleton` allow-lists ENCAP, so
3131+each burst-diffing test pre-filters the native lines). Only `s2s_skeleton_differential` diffs the
3232+burst skeleton; `s2s_netsplit_differential` only checks the post-split QUIT.
3333+3434+**132 — channel-ts.** Channel already had `created_at` (ns). `build_burst` emits `:<sid> ENCAP *
3535+CHANTS <chan> <ns>` after each channel's NJOIN/MODE. `Channels::reconcile_channel_ts(name,
3636+their_ts, their_sid)` adopts `min` and deops the younger side's chanops, keyed by each member's
3737+home server (UID sid prefix): theirs-older⇒deop-not-theirs, theirs-newer⇒deop-theirs, equal⇒Merged.
3838+`s2s::chants::apply_encap_chants` (CHANTS arm in `inbound_encap`, gated on the peer's `channel_ts`
3939+cap) reconciles + relays the deop to local members as a synthetic `-o` MODE. Exact for 2 servers;
4040+3+ approximated; mode-reset deferred.
4141+4242+**133 — user-ts (oldest NICK wins, upgrading slice-112 first-claimant).** The user TS is its
4343+**`signon`** (already stored in NANOSECONDS via `unixnano()`; `registry::signon_of`/`set_signon`).
4444+`unick_intro` emits `:<uid> ENCAP * USERTS <signon_ns>` **BEFORE** the UNICK (the collision needs
4545+the TS synchronously); the USERTS arm of `inbound_encap` buffers it on `PeerLink.pending_user_ts`
4646+(keyed by UID), consumed by `handle_unick`. On a collision (gated on the peer's `user_ts` cap + a
4747+buffered TS): a strictly-older newcomer wins → `evict_holder_to_uid` renames the younger holder to
4848+its UID. **The losing user's nick becomes its UID** (maintainer's rule). A LOCAL loser is forced
4949+across tasks via the NEW `Envelope::ForceNick { wire, new }` (client serve loop + websocket write
5050+the NICK + call `Session::set_nick`; `registry::force_nick_uid` delivers it) — because a session
5151+caches its own nick in another task; a REMOTE loser via `SAVE` toward its server. `golden_s2s_userts`
5252+proves the cross-task path (the serve-loop wiring is otherwise un-unit-testable). When adding an
5353+Envelope variant, fix exhaustive matches in `kill_proptest`/`control_proptest`/`websocket`.
5454+5555+Gate met: leveva 1715/0; leveva-integration 198/0 (incl. real-oracle `s2s_oracle_link`); clippy
5656+clean; build 0 warnings. See [[leveva-slice-recording]], [[leveva-s2s-notify-propagation]].