Leg 2 of the MTU program (planning design/shard-payload-reneg.md), stacked on #37's verdict machinery. Leg 1 taught the host to diagnose a constrained path and clamp the next session; this makes the current session heal at the ~3–10 s verdict mark — and uses the same machinery, inverted, to grow a proven 9000-MTU LAN to ~8.9 KB shards (~6× fewer packets per frame).
Per-frame geometry: the reassembler's strict shard_bytes firewall becomes per-frame pinning — a frame's first-arriving packet pins its shard size (bounds-checked to [MIN_SHARD_PAYLOAD, receive ceiling], even), later packets must match the pin, and the per-frame block ceiling derives from the pinned size. The reorder race between the ordered control stream and unordered video dies structurally: old-geometry frames in flight complete under their own pin while new frames arrive under the new one, and no cross-geometry splice can land in one buffer. The in-flight budget stays byte-based and exact.
MAX_DATAGRAM_BYTES 2048 → 9216: every receive path accepts sealed jumbo datagrams. Grep verdict: no embedder uses the constant directly ⇒ no C ABI bump; the regenerated header rides along. Static buffers won over resize-on-ack: the recvmmsg-ring delta is 128 × ~7 KiB ≈ 896 KiB per client session, lazily allocated, hosts unaffected.
Hello::max_shard_payload: u16 (trailing append, 0/absent = legacy): one field is both the renegotiation capability flag and the jumbo ceiling. Advertised by the shared pump (all client families) and the probe.
Phases 1–2 — the messages and the driver (34ad3cc6)
MSG_SHARD_PAYLOAD_CHANGED/_ACK (0x08/0x09). Asymmetric by design: a shrink re-keys at the next AU immediately after sending (pinning makes ordering irrelevant; the ack is telemetry); a grow emits nothing above the old size until the ack — the ack is the gate even though client buffers would fit.
Client: one dispatch arm in the shared pump control task — validate against the advertised bounds, ack; out-of-bounds gets silence, not an ack, so a buggy host can never read a granted grow out of garbage.
Host: the wire_mtu watcher grows a driver arm — a below-ceiling verdict still records the learned budget (session 2 starts right) and now shrinks session 1 live; with the jumbo opt-in (PUNKTFUNK_JUMBO=1, or PUNKTFUNK_WIRE_MTU > 1500 — one knob, derived) it raises the QUIC MTUD probe ceiling (per-endpoint; a few extra failed probes toward non-jumbo peers, zero cost otherwise), sends the ack-gated grow after a settled-at-sealed-jumbo proof, then stays alive as the revert guard: quinn's blackhole detection lowering current_mtu shrinks the wire back through the same path.
Apply point: Session::set_shard_payload drained in the send loop next to the adaptive-FEC target, gated on no open streamed AU.
PyroWave sessions are gated out (implementation finding beyond the plan): their clients parse chunk-aligned AUs in windows of the Welcome value read once over the C ABI, so a mid-stream re-key would corrupt the parse — they keep the leg-1 next-session clamp, which is codec-independent and fully consistent (everything derives from the one Welcome::shard_payload). This also settles the plan's open question on the two wire_chunk consumers — both are PyroWave-only. Lifting the gate later = per-frame window over the C ABI (v15), its own leg.
Legacy peers are inert both ways: no advertisement ⇒ no driver; an old host never sends the message.
Verification (the 0.23.0 lesson: geometry changes breed sizing bugs)
Mixed-geometry reorder-torture proptest (48 cases): frames of different sizes and wire shapes shuffled into one delivery with per-frame recoverable loss — every frame must arrive byte-identical and the in-flight budget must return to exactly zero.
Sealed-loopback session tests asserting delivered frames (never absence of errors): mid-stream shrink → jumbo grow → revert through one continuous crypto/replay stream; the old-geometry reorder race; cross-geometry splice rejection; firewall bounds non-vacuous both ways.
The low-MTU chunk-aligned guarantee pinned at the clamp shapes a constrained path actually produces (1216 WARP budget, 512 floor) with real loss (d1c4cb18).
The field reporter's VPN box for the shrink leg (expect black → WARN → heals in-session), a 9000-MTU NIC+switch pair for the grow leg (check whether the .42/.173 encode boxes support jumbo first), and the Android on-device memory reading.
Leg 2 of the MTU program (planning `design/shard-payload-reneg.md`), stacked on #37's verdict machinery. Leg 1 taught the host to *diagnose* a constrained path and clamp the **next** session; this makes the **current** session heal at the ~3–10 s verdict mark — and uses the same machinery, inverted, to grow a proven 9000-MTU LAN to ~8.9 KB shards (~6× fewer packets per frame).
### Phase 0 — client-side groundwork (`290d760e`, separately shippable)
- **Per-frame geometry**: the reassembler's strict `shard_bytes` firewall becomes per-frame **pinning** — a frame's first-arriving packet pins its shard size (bounds-checked to `[MIN_SHARD_PAYLOAD, receive ceiling]`, even), later packets must match the pin, and the per-frame block ceiling derives from the pinned size. The reorder race between the ordered control stream and unordered video dies structurally: old-geometry frames in flight complete under their own pin while new frames arrive under the new one, and no cross-geometry splice can land in one buffer. The in-flight budget stays byte-based and exact.
- **`MAX_DATAGRAM_BYTES` 2048 → 9216**: every receive path accepts sealed jumbo datagrams. Grep verdict: no embedder uses the constant directly ⇒ **no C ABI bump**; the regenerated header rides along. Static buffers won over resize-on-ack: the recvmmsg-ring delta is 128 × ~7 KiB ≈ **896 KiB per client session**, lazily allocated, hosts unaffected.
- **`Hello::max_shard_payload: u16`** (trailing append, 0/absent = legacy): one field is both the renegotiation capability flag and the jumbo ceiling. Advertised by the shared pump (all client families) and the probe.
### Phases 1–2 — the messages and the driver (`34ad3cc6`)
- `MSG_SHARD_PAYLOAD_CHANGED`/`_ACK` (0x08/0x09). Asymmetric by design: a **shrink** re-keys at the next AU immediately after sending (pinning makes ordering irrelevant; the ack is telemetry); a **grow** emits nothing above the old size until the ack — the ack is the gate even though client buffers would fit.
- Client: one dispatch arm in the shared pump control task — validate against the advertised bounds, ack; out-of-bounds gets **silence**, not an ack, so a buggy host can never read a granted grow out of garbage.
- Host: the `wire_mtu` watcher grows a driver arm — a below-ceiling verdict still records the learned budget (session 2 starts right) **and now shrinks session 1 live**; with the jumbo opt-in (`PUNKTFUNK_JUMBO=1`, or `PUNKTFUNK_WIRE_MTU` > 1500 — one knob, derived) it raises the QUIC MTUD probe ceiling (per-endpoint; a few extra failed probes toward non-jumbo peers, zero cost otherwise), sends the ack-gated grow after a settled-at-sealed-jumbo proof, then stays alive as the **revert guard**: quinn's blackhole detection lowering `current_mtu` shrinks the wire back through the same path.
- Apply point: `Session::set_shard_payload` drained in the send loop next to the adaptive-FEC target, gated on **no open streamed AU**.
- **PyroWave sessions are gated out** (implementation finding beyond the plan): their clients parse chunk-aligned AUs in windows of the `Welcome` value read **once** over the C ABI, so a mid-stream re-key would corrupt the parse — they keep the leg-1 next-session clamp, which is codec-independent and fully consistent (everything derives from the one `Welcome::shard_payload`). This also settles the plan's open question on the two `wire_chunk` consumers — both are PyroWave-only. Lifting the gate later = per-frame window over the C ABI (v15), its own leg.
- Legacy peers are inert both ways: no advertisement ⇒ no driver; an old host never sends the message.
### Verification (the 0.23.0 lesson: geometry changes breed sizing bugs)
- Slice-wire regression suite re-run at shard **512 / 1216 / 1408 / 8908** (exact-multiple sweep, lossy + reversed roundtrips, sentinel path, in-flight budget).
- Mixed-geometry **reorder-torture proptest** (48 cases): frames of different sizes and wire shapes shuffled into one delivery with per-frame recoverable loss — every frame must arrive byte-identical and the in-flight budget must return to exactly zero.
- Sealed-loopback session tests asserting **delivered frames** (never absence of errors): mid-stream shrink → jumbo grow → revert through one continuous crypto/replay stream; the old-geometry reorder race; cross-geometry splice rejection; firewall bounds non-vacuous both ways.
- The low-MTU chunk-aligned guarantee pinned at the clamp shapes a constrained path actually produces (1216 WARP budget, 512 floor) with real loss (`d1c4cb18`).
- Gates: mac core **297/297** `--features quic` + clippy `-D warnings` + fmt; pf-lxcheck container host clippy `-D warnings` + host `native::` + core 297/297 Linux; `cargo ndk` arm64-v8a + armeabi-v7a; header drift committed.
### Still owed (on-glass)
The field reporter's VPN box for the shrink leg (expect black → WARN → heals in-session), a 9000-MTU NIC+switch pair for the grow leg (check whether the .42/.173 encode boxes support jumbo first), and the Android on-device memory reading.
Phase 0 of mid-session shard-payload renegotiation (planning
design/shard-payload-reneg.md), stacked on the leg-1 MTU resilience. All
three legs are client-side and forward-compatible: deployed clients that
carry them accept a mid-session shard change the moment a future host
sends one, and nothing changes on the wire until then.
- W0.1 — the reassembler's strict shard_bytes firewall becomes per-frame
pinning: a frame's first-arriving packet pins that frame's shard size
(bounds-checked to [min_shard_bytes, max_shard_bytes], even), later
packets must match the pin, and the per-frame block ceiling derives
from the pinned size (a session-level cap would reject legitimate
post-shrink frames). The reorder race between an ordered control
message and unordered video dies structurally: old-geometry frames in
flight complete under their own pin while new frames arrive under the
new one, and no cross-geometry splice can land in one buffer. The
in-flight budget stays byte-based and exact.
- W0.2 — MAX_DATAGRAM_BYTES 2048 → 9216: every receive path (transport
RECV_BUF, the recvmmsg ring) now accepts sealed jumbo datagrams
(9000-MTU LAN ≈ 8908-byte shards). Static buffers over resize-on-ack:
the ring delta is 128 × ~7 KiB ≈ 896 KiB per client session, lazily
allocated, hosts unaffected. Grep verdict: no embedder uses the
constant directly, so no C ABI bump — the regenerated header rides
along (drift gate).
- W0.3 — trailing Hello field max_shard_payload: u16 (0/absent =
legacy), the append-with-placeholder discipline of video_caps/
client_caps. One field is both the renegotiation capability flag and
the jumbo ceiling; core's pump advertises it for all client families,
the probe too.
- Host seam for Phase 1, dead until wired: Packetizer::set_shard_payload
(re-derives the block ceilings; construction delegates to it) +
Session::set_shard_payload (host-only, Config::validate parity).
Verification (the 0.23.0 lesson — geometry changes breed sizing bugs):
the slice-wire suite re-runs at shard 512/1216/1408/8908 (exact-multiple
sweep, lossy + reversed roundtrips, sentinel path, in-flight budget);
mid-stream shrink→grow→revert delivery; the old-geometry reorder race;
cross-geometry splice rejection; firewall bounds non-vacuous both ways;
a 48-case mixed-geometry reorder-torture proptest asserting per-frame
byte-identical DELIVERY and an exactly-zero final budget; and a sealed
loopback session test (continuous crypto/replay) delivering frames
across live re-keys — every test asserts delivered frames, never the
absence of errors.
core: 294/294 --features quic + clippy -D warnings (macOS), fmt.
Phases 1-2 of design/shard-payload-reneg.md, on top of the Phase 0
per-frame geometry. The leg-1 watcher stops merely diagnosing the
constrained path and heals the CURRENT session; the same machinery,
inverted, takes a proven jumbo LAN up to ~8.9 KB shards.
- Messages: MSG_SHARD_PAYLOAD_CHANGED (0x08, host→client, {shard_payload
u16}) and MSG_SHARD_PAYLOAD_ACK (0x09, the echo). Asymmetric by
design: a shrink re-keys the packetizer at the next AU immediately
after sending (per-frame pinning makes ordering irrelevant; the ack is
telemetry), a grow emits nothing above the old size until the ack —
the ack is the gate even though client buffers are statically sized.
- Client: one dispatch arm in the shared pump control task (all client
families) — validate against the advertised receive bounds, ack;
out-of-bounds requests get SILENCE, not an ack, so a buggy host can
never read a granted grow out of garbage.
- Host driver: the wire_mtu watcher grows a ShardReneg arm — on a
below-ceiling verdict it still records the learned budget (session 2
starts right) and now also shrinks session 1 at the ~3-10 s verdict
mark; with the jumbo opt-in (PUNKTFUNK_JUMBO=1, or PUNKTFUNK_WIRE_MTU
> 1500 — one knob, derived) it sends the ack-gated grow after a
settled-at-sealed-jumbo proof and then stays alive as the revert
guard: quinn's blackhole detection lowering current_mtu shrinks the
wire back through the same path. The QUIC MTUD probe ceiling rises
from 1472 to the sealed jumbo size with the opt-in (per-ENDPOINT: a
few extra failed probes toward non-jumbo peers, zero cost otherwise).
- Apply point: Session::set_shard_payload drained in the send loop next
to the adaptive-FEC target, gated on no open streamed AU (a streamed
frame's shard-aligned tiling derives from the size it began with).
- Renegotiation is gated OFF for PyroWave sessions: their clients parse
chunk-aligned AUs in windows of the Welcome value pinned at session
start (read once over the C ABI), so a mid-stream re-key would corrupt
the parse — those sessions keep the leg-1 next-session clamp. This
also settles the plan's open question on the two wire_chunk consumers:
both are PyroWave-only, so the gate covers them entirely.
- Legacy peers are inert both ways: no Hello advertisement → the host
never constructs the driver; an old host never sends the message.
core: 296/296 --features quic + clippy -D warnings (macOS), fmt; the
regenerated header carries the new message ids (drift gate).
PyroWave sessions are gated out of mid-session renegotiation, so a
constrained path serves them through the leg-1 SESSION-START clamp. This
pins the consistency that guarantee rests on: everything chunk-aligned
derives from the one Welcome::shard_payload number — the host
packetizes at it, the client's C-ABI parse window reads it back, and
partial delivery zero-fills exact windows of it — verified at the two
clamp shapes a constrained path actually produces (1216, the
WARP/Tailscale budget, and the 512 floor) over the sealed loopback wire
with real loss.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Leg 2 of the MTU program (planning
design/shard-payload-reneg.md), stacked on #37's verdict machinery. Leg 1 taught the host to diagnose a constrained path and clamp the next session; this makes the current session heal at the ~3–10 s verdict mark — and uses the same machinery, inverted, to grow a proven 9000-MTU LAN to ~8.9 KB shards (~6× fewer packets per frame).Phase 0 — client-side groundwork (
290d760e, separately shippable)shard_bytesfirewall becomes per-frame pinning — a frame's first-arriving packet pins its shard size (bounds-checked to[MIN_SHARD_PAYLOAD, receive ceiling], even), later packets must match the pin, and the per-frame block ceiling derives from the pinned size. The reorder race between the ordered control stream and unordered video dies structurally: old-geometry frames in flight complete under their own pin while new frames arrive under the new one, and no cross-geometry splice can land in one buffer. The in-flight budget stays byte-based and exact.MAX_DATAGRAM_BYTES2048 → 9216: every receive path accepts sealed jumbo datagrams. Grep verdict: no embedder uses the constant directly ⇒ no C ABI bump; the regenerated header rides along. Static buffers won over resize-on-ack: the recvmmsg-ring delta is 128 × ~7 KiB ≈ 896 KiB per client session, lazily allocated, hosts unaffected.Hello::max_shard_payload: u16(trailing append, 0/absent = legacy): one field is both the renegotiation capability flag and the jumbo ceiling. Advertised by the shared pump (all client families) and the probe.Phases 1–2 — the messages and the driver (
34ad3cc6)MSG_SHARD_PAYLOAD_CHANGED/_ACK(0x08/0x09). Asymmetric by design: a shrink re-keys at the next AU immediately after sending (pinning makes ordering irrelevant; the ack is telemetry); a grow emits nothing above the old size until the ack — the ack is the gate even though client buffers would fit.wire_mtuwatcher grows a driver arm — a below-ceiling verdict still records the learned budget (session 2 starts right) and now shrinks session 1 live; with the jumbo opt-in (PUNKTFUNK_JUMBO=1, orPUNKTFUNK_WIRE_MTU> 1500 — one knob, derived) it raises the QUIC MTUD probe ceiling (per-endpoint; a few extra failed probes toward non-jumbo peers, zero cost otherwise), sends the ack-gated grow after a settled-at-sealed-jumbo proof, then stays alive as the revert guard: quinn's blackhole detection loweringcurrent_mtushrinks the wire back through the same path.Session::set_shard_payloaddrained in the send loop next to the adaptive-FEC target, gated on no open streamed AU.Welcomevalue read once over the C ABI, so a mid-stream re-key would corrupt the parse — they keep the leg-1 next-session clamp, which is codec-independent and fully consistent (everything derives from the oneWelcome::shard_payload). This also settles the plan's open question on the twowire_chunkconsumers — both are PyroWave-only. Lifting the gate later = per-frame window over the C ABI (v15), its own leg.Verification (the 0.23.0 lesson: geometry changes breed sizing bugs)
d1c4cb18).--features quic+ clippy-D warnings+ fmt; pf-lxcheck container host clippy-D warnings+ hostnative::+ core 297/297 Linux;cargo ndkarm64-v8a + armeabi-v7a; header drift committed.Still owed (on-glass)
The field reporter's VPN box for the shrink leg (expect black → WARN → heals in-session), a 9000-MTU NIC+switch pair for the grow leg (check whether the .42/.173 encode boxes support jumbo first), and the Android on-device memory reading.
Phases 1-2 of design/shard-payload-reneg.md, on top of the Phase 0 per-frame geometry. The leg-1 watcher stops merely diagnosing the constrained path and heals the CURRENT session; the same machinery, inverted, takes a proven jumbo LAN up to ~8.9 KB shards. - Messages: MSG_SHARD_PAYLOAD_CHANGED (0x08, host→client, {shard_payload u16}) and MSG_SHARD_PAYLOAD_ACK (0x09, the echo). Asymmetric by design: a shrink re-keys the packetizer at the next AU immediately after sending (per-frame pinning makes ordering irrelevant; the ack is telemetry), a grow emits nothing above the old size until the ack — the ack is the gate even though client buffers are statically sized. - Client: one dispatch arm in the shared pump control task (all client families) — validate against the advertised receive bounds, ack; out-of-bounds requests get SILENCE, not an ack, so a buggy host can never read a granted grow out of garbage. - Host driver: the wire_mtu watcher grows a ShardReneg arm — on a below-ceiling verdict it still records the learned budget (session 2 starts right) and now also shrinks session 1 at the ~3-10 s verdict mark; with the jumbo opt-in (PUNKTFUNK_JUMBO=1, or PUNKTFUNK_WIRE_MTU > 1500 — one knob, derived) it sends the ack-gated grow after a settled-at-sealed-jumbo proof and then stays alive as the revert guard: quinn's blackhole detection lowering current_mtu shrinks the wire back through the same path. The QUIC MTUD probe ceiling rises from 1472 to the sealed jumbo size with the opt-in (per-ENDPOINT: a few extra failed probes toward non-jumbo peers, zero cost otherwise). - Apply point: Session::set_shard_payload drained in the send loop next to the adaptive-FEC target, gated on no open streamed AU (a streamed frame's shard-aligned tiling derives from the size it began with). - Renegotiation is gated OFF for PyroWave sessions: their clients parse chunk-aligned AUs in windows of the Welcome value pinned at session start (read once over the C ABI), so a mid-stream re-key would corrupt the parse — those sessions keep the leg-1 next-session clamp. This also settles the plan's open question on the two wire_chunk consumers: both are PyroWave-only, so the gate covers them entirely. - Legacy peers are inert both ways: no Hello advertisement → the host never constructs the driver; an old host never sends the message. core: 296/296 --features quic + clippy -D warnings (macOS), fmt; the regenerated header carries the new message ids (drift gate).