The controller learns stillness from the host, and motion stops reading as congestion #407

Merged
enricobuehler merged 3 commits from worktree-abr-phase3 into main 2026-08-27 09:22:24 +00:00
Owner

ABR overhaul Phase 3 (planning PR #20, RFC §4.1–4.3 + the §7 Q4 floor amendment — signed off). Static content used to poison the controller against the first moment of motion (field chain step 5), and a frame-driven source could never climb at all (the documented dead band at abr.rs's ¾ wall-clock gate).

Wire (§4.1): the host marks idle-keepalive re-encodes with USER_FLAG_REPEAT (whole-frame + streamed paths — FrameMsg/ChunkMsg already knew) and advertises it in a new trailing Welcome byte host_caps2 / HOST_CAP2_REPEAT_MARK — the second capability byte the 0x80 wall predicted, same append discipline, placeholder chain extended one link (an Opus session forced to emit the audio block writes its own defaults; roundtrip-tested under both ciphers, 88/120 bytes). Old clients ignore both; against an old host the client keeps every legacy rule — active_frames reaches the controller as Option, None meaning "unknown", never "all active".

Controller:

  • Idle windows are neutral (§4.1): no OWD/decode/encode baseline training, no climb credit, no re-probe-clock advance, never a climb — while loss/flush/drop keep full power. The pinned unloaded_clean_windows_never_authorize_a_climb is extended, not deleted. The head-to-head test runs the same wire history against both host vintages: the legacy host backs off at motion onset (its baselines trained on keepalive dribble), the marking host climbs.
  • fps-normalized utilization (§4.2): the ¾ gate measures per-frame delivery at the source's own rate, floored at 4 active frames. The proven-headroom cap prorates with it — it bounds the next target's projected wire rate at ×1.5 over proven delivery — or the two gates deadlock exactly where the fix is needed (found while writing the scenario test; the no-deadlock invariant is restored and documented).
  • Bounded, fast recovery (§4.3): the proven mark becomes a two-bucket windowed max (~30–60 s), and the first active window after ≥3 s of stillness re-arms slow start with the cooldown cleared — the ~103 s additive crawl from the floor becomes a bounded multiplicative step, never past ×1.5 over recently-proven delivery.
  • FLOOR_KBPS 5000 → 2000 (§7 Q4) with a one-shot log warning below the old fence; client-settings doc updated.

Verified: punktfunk-core --features quic — all 500 lib tests green natively, including six new field-shaped scenarios; clippy --all-targets clean; cargo fmt --check clean; the regenerated C header is committed with the R21 prefixes. Host-side compile leans on ci / rust + a windows-host.yml dispatch on the branch. Field validation is the A/B rig (RFC §6) — this PR is what the rig exists to measure.

ABR overhaul **Phase 3** (planning PR #20, RFC §4.1–4.3 + the §7 Q4 floor amendment — signed off). Static content used to poison the controller against the first moment of motion (field chain step 5), and a frame-driven source could never climb at all (the documented dead band at `abr.rs`'s ¾ wall-clock gate). **Wire (§4.1):** the host marks idle-keepalive re-encodes with `USER_FLAG_REPEAT` (whole-frame + streamed paths — `FrameMsg`/`ChunkMsg` already knew) and advertises it in a new trailing Welcome byte `host_caps2` / `HOST_CAP2_REPEAT_MARK` — the second capability byte the `0x80` wall predicted, same append discipline, placeholder chain extended one link (an Opus session forced to emit the audio block writes its own defaults; roundtrip-tested under both ciphers, 88/120 bytes). Old clients ignore both; against an old host the client keeps every legacy rule — `active_frames` reaches the controller as `Option`, `None` meaning "unknown", never "all active". **Controller:** - **Idle windows are neutral** (§4.1): no OWD/decode/encode baseline training, no climb credit, no re-probe-clock advance, never a climb — while loss/flush/drop keep full power. The pinned `unloaded_clean_windows_never_authorize_a_climb` is extended, not deleted. The head-to-head test runs the same wire history against both host vintages: the legacy host backs off at motion onset (its baselines trained on keepalive dribble), the marking host climbs. - **fps-normalized utilization** (§4.2): the ¾ gate measures per-frame delivery at the source's own rate, floored at 4 active frames. The proven-headroom cap **prorates with it** — it bounds the next target's projected *wire* rate at ×1.5 over proven delivery — or the two gates deadlock exactly where the fix is needed (found while writing the scenario test; the no-deadlock invariant is restored and documented). - **Bounded, fast recovery** (§4.3): the proven mark becomes a two-bucket windowed max (~30–60 s), and the first active window after ≥3 s of stillness re-arms slow start with the cooldown cleared — the ~103 s additive crawl from the floor becomes a bounded multiplicative step, never past ×1.5 over *recently*-proven delivery. - **`FLOOR_KBPS` 5000 → 2000** (§7 Q4) with a one-shot log warning below the old fence; client-settings doc updated. **Verified:** `punktfunk-core --features quic` — all **500** lib tests green natively, including six new field-shaped scenarios; clippy `--all-targets` clean; `cargo fmt --check` clean; the regenerated C header is committed with the R21 prefixes. Host-side compile leans on `ci / rust` + a `windows-host.yml` dispatch on the branch. Field validation is the A/B rig (RFC §6) — this PR is what the rig exists to measure.
enricobuehler added 2 commits 2026-08-27 08:42:29 +00:00
Static content used to poison the client's ABR against the first moment
of motion (the 2026-08-26 field chain, step 5), and a frame-driven
source could never climb at all (the documented dead band). Four
changes, per the signed-off RFC §4.1–4.3 + §7 Q4:

- The host marks idle-keepalive re-encodes on the wire
  (USER_FLAG_REPEAT; whole-frame and streamed paths) and says so in a
  new trailing Welcome byte (host_caps2 / HOST_CAP2_REPEAT_MARK — the
  second capability byte the 0x80 wall predicted, same append
  discipline, placeholder chain extended one link). Old clients ignore
  both; against an old host the client keeps every legacy rule.
- Idle windows (every AU a repeat) are NEUTRAL: they train no OWD/
  decode/encode baselines, accrue no climb credit or re-probe
  authority, and never authorize a climb — loss/flush/drop keep their
  full power. The pinned climb-gate test is extended, not deleted.
- Utilization is measured per frame at the source's own rate: a 35 fps
  menu on a 90 Hz config climbs when its frames run full. The
  proven-headroom cap prorates with it — it bounds the next target's
  projected WIRE rate at ×1.5 over what was delivered — or the two
  gates would deadlock exactly where the fix is needed.
- Recovery is bounded and multiplicative: the proven mark is a
  two-bucket windowed max (~30–60 s) instead of all-session, and the
  first active window after ≥3 s of stillness re-arms slow start with
  the cooldown cleared — the ~103 s additive crawl from the floor
  becomes seconds, never past ×1.5 over recently-proven delivery.
- FLOOR_KBPS drops 5000 → 2000 (RFC §7 Q4), with a one-shot log
  warning on the first descent below the old fence; the client-settings
  doc says so.

punktfunk-core --features quic: all 500 lib tests green natively,
including six new field-shaped scenarios (frame-driven climb, idle
neutrality head-to-head vs a legacy host, bounded onset re-arm,
windowed proven decay, floor + warning, idle-never-climbs).
chore(core): prefix the two new exported constants in the C header (R21)
ci / bun-nix (pull_request) Successful in 39s
ci / docs-drift (pull_request) Failing after 36s
ci / docs-site (pull_request) Successful in 1m2s
ci / web (pull_request) Successful in 1m16s
apple / swift (pull_request) Successful in 2m9s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 2m49s
android / android (pull_request) Successful in 6m6s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 6m16s
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 2m44s
ci / rust (pull_request) Successful in 15m42s
2b107f5a18
enricobuehler added 1 commit 2026-08-27 09:03:14 +00:00
chore(ci): baseline the two new wire constants — protocol internals, not knobs
apple / swift (pull_request) Successful in 2m13s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
android / android (pull_request) Successful in 5m57s
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 3m1s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 6m18s
ci / bun-nix (pull_request) Successful in 20s
ci / docs-drift (pull_request) Successful in 23s
ci / docs-site (pull_request) Successful in 1m44s
ci / web (pull_request) Successful in 1m52s
ci / rust-arm64 (pull_request) Successful in 2m34s
ci / rust (pull_request) Successful in 7m24s
cba7587684
enricobuehler merged commit b97fa1186f into main 2026-08-27 09:22:24 +00:00
enricobuehler deleted branch worktree-abr-phase3 2026-08-27 09:22:30 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#407