Campaign N slice N4 completes the AckNakScheduler NAK branch and closes
the ACE cleartext-reject keystream hazard - the slice that makes S2C
loss actually RECOVER.
NAK emission (SharedNet::EnqueueNaks @ 0x00543BD0):
- One cleartext exact-flags RequestRetransmit per sweep behind the
STRICT 0.6 s gate on the ONE shared timestamp (the x87 0x41-mask test
at 0x00543C03 proceeds only on strictly-greater; the ack's gate stays
>=). Never an ack in a NAK sweep; a NAK delays the next ack by 2.0 s
and vice versa (landmine #7).
- Body = u32 count + ids ascending, capped at 114 (ReceiverData::GetNaks
@ 0x005490C0, cap 0x72; the m_cbData = 4*count+4 store at 0x00543C3E);
header Sequence borrowed from highestIDSent_ without incrementing;
cleartext or ACE ignores it (landmine #6, NetworkSession.cs:283-284) -
and a NAK never refreshes ACE's 60 s timeout.
- Control-header rule decided once for BOTH ack and NAK: Time = the
interval id, Iteration = the session iteration, matching retail's
shared header build (FlowQueue::TransmitNewPackets @ 0x00547A60, the
stack build at 0x00547A84). ACE reads neither field inbound.
- Gate ticks now round instead of truncate: 0.6 has no exact double
form, and truncation opened the strict gate exactly AT the boundary.
RejectRetransmit reclaim (divergence register AD-51, ACE adaptation):
- ACE's RejectRetransmit consumes a FRESH sequence, cleartext, with NO
keystream word, and is cached (ACE NetworkSession.cs:299-304,
:722-725, :743-748) - the one place ACE breaks retail's gap-walk
invariant that every missing id was word-bearing (retail cleartext
always borrows live sequences). Unhandled, the gap walk parks a word
for the reject's id and the inbound stream runs permanently one word
ahead - the N2 desync class reintroduced through the reject path.
- Fix: on a VALIDATED cleartext reject, InboundSequenceTracker removes
the mis-park, shifts every later-drawn parked word down one position
(per-word draw ordinals; ascending wrap-safe id <=> ascending draw
order), and pools the excess word, consumed lowest-draw-order-first
ahead of fresh ISAAC draws. Exact for any number of interleaved
rejects in ANY arrival order - a plain reclaim FIFO is not: a reject
arriving after a higher encrypted arrival crosses the parked chain,
and two out-of-order rejects pool their excess words out of draw
order (both orderings pinned by tests).
- Reject BODY ids keep N2's discard: word-bearing server-side,
consumed-in-place. The pool is provably empty against retail servers.
N3 advisories folded (all five): honest transitional-state wording (the
empty N3 NAK branch could silently disconnect a loopback session at
ACE's 60 s timeout, witness [net-tick] acks/s=0), the
ReceiverData::SharedInit @ 0x00548EF0 (from Init @ 0x00548FA0)
citation, the FlowQueue::Empty pump-order wording (TransmitNaks ->
TransmitAcks -> TransmitNewPackets with the interval increment LAST @
0x00548A9D; our clock-first Sweep is cosmetic vs ACE), the
Time/Iteration rule above, and the stale WorldSession budget-break
comment rewritten to the sweep reality.
Tests: 737 Core.Net green (14 new in NakEmissionTests + updated N3
pins): strict-gate boundary, shared timestamp both directions,
NAK-xor-ack exclusivity, full wire-shape + 114-cap pins, model-served
retransmission round trip, five tracker reclaim proofs, the 130 s
virtual prune -> fresh-sequence reject system test (victim abandoned,
later traffic decodes, pool drains to zero), 10 s long-loss survival
(NAKs on the gate cadence, zero acks, heal inside the window), and the
capstone soak: 2% seeded bidirectional loss x 10,000 messages -> zero
message loss both ways, ACE crypto headroom 256 at convergence, every
ledger drained (cache at the single watermark entry - retail's Flush
prunes STRICTLY below the ack). Full solution Release: 9,758 passed /
5 skipped. Connected world-lifecycle gate PASS
(logs/connected-world-gate-20260729-150238); canonical nine-stop soak
PASS (logs/connected-r6-soak-20260729-150856).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>