Files
VerseVDI-Data-Plane/openspec/changes/truthful-fixed-frame-qualification/design.md
T
sechmachine 22433e5c45
Verify Data Plane / gateway (push) Successful in 4m46s
test(gateway): measure qualification wire capacity
2026-08-09 23:01:42 +07:00

9.0 KiB

Context

The current harness sends one fixed 1,179-byte payload per logical sample. It reaches the production path but does not represent encoded frames at 60/120 FPS or exercise realistic fragmentation, reassembly, queue bytes, and keyframe pressure.

The complete-frame fixture also must preserve the pinned Apollo source schedule. For each frame it derives packets per millisecond from the raw UDP block size at 80% of 1 Gbps, limits source batches to both 64 KiB and 64 packets, and carries the next-send time into the following frame. Waiting is context-cancellable. This is qualification-fixture behavior only; production transport and queue behavior remain unchanged.

Because the bounded fixture uses loopback rather than a physical 1 Gbps link, v8 writes the first shard of a batch successfully, captures that actual monotonic emission start, and schedules the next batch no earlier than that start plus the current batch's raw-block serialization interval. The persistent schedule carries across frames. A delayed batch therefore remains late instead of collapsing overdue batches into a catch-up burst.

The retained v6 qualification run passed its then-current checks but is superseded because its tight-loop sender contradicted the pinned Apollo schedule. Private Linux runs 123 and 124 remain failed evidence. One local v8 sustained run passed on Darwin, but it is neither Linux proof nor normative Section 7 evidence.

The later Darwin non-sustained pre-CI invocation was not green and was not retried. Its 1440p120 profile delivered the exact 6,250,000 bytes in 120 frames plus all 6,483 source and warm-up shards with zero drops, but measured 46,973.13 kbps over an implied approximately 1.0644383 seconds and failed the 5% throughput gate. Private Linux full verification/artifact retention and the replacement v9 normative run remain open.

Private Linux run 125 at the frozen v8 harness head is retained as failed evidence. Its exact 33-datagram gap between successful fixture writes and production MediaIngress equaled the Linux socket's 33 measured kernel UDP drops. The complete-frame queue, fair pacer, QUIC fragmentation, and public decoder were downstream and did not account for the loss.

The one authorized v8 Section 7 invocation at production candidate 55afea72a1487fa071501615d806e68efc0a436b was consumed and failed. Its directory gateway-rc10-55afea7 is retained byte-for-byte with two partial processing files and no manifest. The failure occurred at payload sequence 16801 after 16,834 provider frames had been recovered and enqueued; the provider queue reached 15 entries and dropped one valid frame while source-write and ingress accounting remained balanced at the diagnostic boundary. This attempt is failed evidence and is not eligible for retry or relabeling.

The production fair pacer previously limited instantaneous recovery to 5 ms by moving an overdue flow's schedule to now-5ms, but silently discarded every additional valid scheduling interval. Repeated host stalls therefore accumulated complete frames in the existing provider queue until its 250 ms residence horizon correctly expired one. The repair keeps the 5 ms instantaneous ceiling, carries only the remaining debt up to that existing horizon, and shortens later nominal intervals by at most one twenty-first. That 20/21 interval is exactly 5% above nominal rate; once the debt reaches zero, the flow returns to its unchanged nominal interval. Per-flow debt and the shared nominal fair-share calculation preserve the existing eight-flow fairness and rolling aggregate cap through the existing 25% and 50% capacity changes.

Private Linux run 127/job 481 at exact source 122080ab342d20585d9a45db0017337b9ece570a is retained as failed evidence. TestQualificationLossAndSteppedThroughputBounds reported the 25% step's 11-second convergence sentinel and a 5,207,475-byte five-second maximum. No artifact was uploaded and the run was not retried. The retained log /private/tmp/versevdi-gitea-run-127-job-481.log has SHA-256 2b368413d4b0e954c64ba6f6dcefb1e165166d773b6d8f84ee372bc2c92ff5f1. The failure exposed a measurement-unit defect: capacity samples were emitted only after complete logical-payload reassembly and were compared with a payload-derived target even though the pacer reserves encoded public datagram bytes. It did not establish a production pacer defect, and 122080ab is superseded as a final source candidate.

Qualification v9 observes every raw public QUIC datagram immediately after the independent client's ReceiveDatagram returns and before the existing decoder/reassembler. Capacity convergence and rolling five-second maxima use those monotonic receive times and encoded lengths. Their target bytes per second and five-second cap derive from qualificationMediaPacerKbps(profile, reduction) * 1000 / 8. Complete logical-payload observations remain separate and continue to own payload integrity, loss, reorder, latency, throughput, and queue assertions. The first public delivery at or after a step anchors the four consecutive 250 ms windows so an arbitrary control-plane timestamp cannot split the first observed datagram pair. The delivery-after-step boundary, 90%-105% window bounds, ten-second convergence ceiling, and rolling-five-second 105% gate are unchanged.

The ingress repair follows reviewed behavior rather than copying implementation source:

  • Apollo adc5c5a0bd80831ce495434bb16aee2cd4175fb8, GPL-3.0, src/stream.cpp:1463-1474,1573-1627, supplies the 80%-of-1-Gbps raw-block pacing, 64-KiB/64-packet batch cap, and cross-frame send schedule used by the fixture.
  • Moonlight common-C pin 2ea47752c3051d72a64bcca190024e8b354fa1ef, GPL-3.0, src/VideoStream.c:28-35,331-333 and src/PlatformSockets.c:364-405, supplies the reviewed 2,048-video-packet receive-buffer request and dedicated receive-thread behavior. The cited VideoStream.c blob is byte-identical at the local standalone 703a06946861ff82cd33e5e13c59c1b017f7ded9 checkout.

The native provider therefore requests 2,048 * 1,072 = 2,195,456 bytes with SetReadBuffer() on the connected video socket immediately after dialing it. A setter error aborts setup; an OS-imposed cap is accepted without privilege or getter dependence. A dedicated drain owns a fixed 2,048-slot FIFO pool. Every slot is 1,433 bytes (apolloMediaMaximumPacket + 1), so oversized datagrams remain observably invalid rather than being truncated into the accepted range; packet storage is 2,934,784 bytes (about 2.80 MiB) plus fixed index and timestamp metadata. The existing single decrypt/FEC processor consumes those slots. When every slot is occupied, the drain keeps reading into one fixed 1,433-byte scratch buffer and counts each accepted-size discard in both ingress and drop telemetry; oversized datagrams retain the existing rejection semantics. Socket close cancels the blocking read, and media channels close only after the unchanged audio reader, video drain, and video processor exit. Audio and control behavior are unchanged.

Goals / Non-Goals

Goals:

  • Deterministically generate complete variable-size frame units at exact profile frame rates and target bitrates.
  • Include bounded periodic keyframes while preserving exact aggregate bytes.
  • Measure the existing production path and independent reassembly with frame-level accounting.

Non-Goals:

  • A real encoder, codec parsing, a second simulator, or a normative run before immutable Protocol publication.

Decisions

  • Derive bytes per fixed interval from bitrate and FPS, distribute integer remainder deterministically, and shift bounded bytes into periodic keyframes while keeping the interval total exact.
  • Carry a deterministic frame index/pattern only in the generated payload bytes; no codec semantics are claimed.
  • Keep the existing path/impairment/resource driver and change its unit from datagram payload to complete frame.
  • Keep video decrypt/FEC single-threaded; only the bounded connected-socket drain is separated so crypto stalls cannot become unexplained kernel loss.
  • Preserve valid scheduling debt after bounded host stalls instead of converting it into provider-queue residence; repay it within the existing fair pacer without a new queue, interface, or configured headroom.
  • Classify constrained-capacity evidence from actual public datagram observations and configured wire capacity; do not infer transport timing from completed logical frames.

Risks / Trade-offs

  • [Keyframes can exceed queue budget] → use the reviewed 1 MiB frame ceiling and production byte-bound queue.
  • [Short smoke windows have rounding effects] → assert exact generated totals and report measured duration separately from normative ten-minute gates.
  • [A stalled video processor exhausts the user-space pool] → keep draining into one fixed scratch buffer and attribute accepted-size overflow to existing ingress/drop counters rather than kernel loss or unbounded allocation.
  • [Debt repayment creates a burst or aggregate oversubscription] → retain the 5 ms instantaneous ceiling and limit repayment to a 20/21 nominal interval per flow, with every rolling five-second aggregate window bounded to 105%.