docs(net): N4 accepted - Opus review PASS; AP-125 filed; F1/F5 fixed

The N4 review confirmed the draw-order reclaim design (invariant attacked
from five angles, held) and NAK fidelity down to the decomp''s x87
comparison masks. This acceptance commit settles the two process debts it
found: AP-125 (standalone control packets vs retail''s CoalesceData
piggyback - the ACE-safety divergence that has shipped since N3''s ack and
N4''s NAK) now has its register row; the false rounding-bug justification
in AckNakScheduler (0.6 x 1e7 rounds UP under IEEE-754, truncation never
lost a tick) is rewritten as the defensive hardening it actually is; and
Admission.Process''s defaulted draw-ordinal is now ulong.MaxValue so an
accidental cleartext repark can never head a bubble-shift chain. Core.Net
737/737 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-29 15:40:34 +02:00
parent 852a59e388
commit 396838bb40
4 changed files with 19 additions and 7 deletions

View file

@ -136,9 +136,13 @@ internal sealed class AckNakScheduler
_sessionIteration = sessionIteration;
_stats = stats;
_send = send;
// Round, don't truncate: 0.6 has no exact double form and
// 0.6 × 10^7 truncates to 5,999,999 ticks — one tick short, which
// would open the STRICT gate at exactly 0.6 s elapsed.
// Round rather than truncate — defensive hardening only. At the
// frequencies in play (10 MHz Stopwatch/VirtualClock, 1 GHz Linux)
// 0.6 × Frequency rounds to the exact integer under IEEE-754 double
// multiplication (the 0.6 representation error is below the half-ulp
// at that magnitude), so truncation would be equivalent; Math.Round
// keeps the gate exact for any hypothetical frequency where the
// product lands below the integer. (N4 review F1.)
_ackGateTicks = (long)Math.Round(AckGateSeconds * clock.Frequency);
_nakGateTicks = (long)Math.Round(NakGateSeconds * clock.Frequency);
// ReceiverData::SharedInit @ 0x00548EF0 (from Init @ 0x00548FA0)

View file

@ -194,9 +194,16 @@ internal sealed class InboundSequenceTracker
{
public static Admission Dropped => new(true, null, 0);
/// <summary>
/// The default draw-order is <see cref="ulong.MaxValue"/>, NOT 0:
/// the one-arg form is the cleartext path (no word, no ordinal), and
/// an accidental repark of a defaulted admission must sort ABOVE
/// every real parked word instead of silently heading every
/// bubble-shift chain (N4 review F5 — ordinal 0 would).
/// </summary>
public static Admission Process(
uint? verifyKey,
ulong verifyKeyDrawOrder = 0) =>
ulong verifyKeyDrawOrder = ulong.MaxValue) =>
new(false, verifyKey, verifyKeyDrawOrder);
}