Skip to content

Commit 9a97dbd

Browse files
secupclaude
andcommitted
diag: BUG-ANCHOR-WAIT-NO-ACK-STALL — marginal bursts rejected in full-anchor-wait emit no ACK → 44s RTO stall (MPG@25 batch quantifies ~+30% prize); the top throughput lever, fix designed for next session
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019btwFxDt7D19SZSqPYvZnk
1 parent 7b809d5 commit 9a97dbd

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

docs/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ Verified: ctest 85/85; good@20 PASS 1600 bps.
8484

8585
---
8686

87+
## 2026-07-14 — diag: MPG@25 natural batch + BUG-ANCHOR-WAIT-NO-ACK-STALL (the marginal-SNR throughput lever, ~+30%)
88+
89+
MPG@25 natural (F279-F283, ACE off, no force): 1.80/2.48/1.38/2.32/2.81,
90+
mean 2.16. 16QAM reachable (1-2 switches/run) but never sustained — the ladder
91+
settles at the more-robust QPSK R3/4. Goodput inversely tracks CW-fails, and
92+
the driver is BUG-ANCHOR-WAIT-NO-ACK-STALL (filed KNOWN_BUGS): marginal burst
93+
heads (corr 0.15-0.32) fall below the weak_accept floor (~0.45) → rejected in
94+
full-anchor-wait → no ACK → 44.68 s sender RTO. Clean run F283 (4 fails) hit
95+
2.81; killing the stall lifts the mean toward that ceiling ≈ +30%. This is the
96+
top throughput lever — bigger than PAPR/higher-QAM at the SNRs the fleet lives.
97+
98+
---
99+
87100
## 2026-07-13 — feat(papr): ACE built + rig A/B — proven SAFE (guaranteed non-negative), gain ~0.8 dB below the 3-pair noise floor; stays default-off
88101

89102
ACE (src/ofdm/papr_ace.hpp, ULTRA_ACE_PAPR, default off) extends outer

docs/KNOWN_BUGS.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,43 @@ Fixed/obsolete historical deep dives belong in `docs/CHANGELOG.md`.
2727
(~1.2 Hz clock/jitter wander over the 144 ms training window explains it exactly; sim reads
2828
10.1 dead-on). The operator display should eventually show BOTH numbers.
2929

30+
### BUG-ANCHOR-WAIT-NO-ACK-STALL: marginal-SNR bursts rejected in full-anchor-wait emit NO ACK → sender 44 s RTO stall (THE marginal-SNR throughput lever, quantified ~+30%)
31+
32+
- **Discovered/quantified 2026-07-14 (operator-caught "we didn't even ACK at
33+
SNR 25"; MPG@25 natural batch F279-F283).** The receiver, while in
34+
full-anchor-wait, runs a light DATA sync on each incoming burst. At marginal
35+
SNR the burst-head correlations arrive at **0.15-0.32**, below the
36+
weak_accept floor (~0.44-0.45, `signal_policy.hpp` evaluateLightSyncCandidate
37+
:262-278 requires corr ≥ max(weak_floor 0.45, min_confidence-0.08)). So the
38+
burst is REJECTED (`Full-anchor wait rejected DATA fallback`,
39+
sync_controller.cpp:817), in streaks of 2-5. A rejected burst never reaches
40+
group-decode → **NO ACK is emitted** → the sender waits its full RTO
41+
(**44.68 s** at window-16, burst airtime 21.5 s × 2) before resending as a
42+
full-anchor burst the receiver finally accepts.
43+
- **Cost (measured):** each stall ≈ 44 s dead air. MPG@25 batch: goodput
44+
inversely tracks CW-fails/stalls — F283 clean (4 fails) = **2.81 kbps** vs
45+
rough F281 (1015 fails) = 1.38; mean 2.16. Eliminating the stall lifts the
46+
mean toward the ~2.8 clean-epoch ceiling ≈ **+30% at this SNR** — bigger than
47+
any PAPR/QAM lever. Forensics: ~/Documents/ultra_forensics/{F283_mac,nat25_pi5}.log.
48+
- **KEY (the elegant fix): even a FAILED (0/N) decoded group still emits a
49+
tone-burst ACK with the cumulative base UNCHANGED** ("no progress, resend") —
50+
which breaks the 44 s silence and gets an immediate resend. So the receiver
51+
does NOT need to decode the weak burst; it only needs to NOT be silent.
52+
- **Fix approaches (next session — protocol/sync path, rig-validate; ACK
53+
contract has regressed before, build carefully):**
54+
1. ACK-LIVENESS ACCEPT: when a burst is rejected in full-anchor-wait but
55+
light_found with clear energy (corr above a low floor, e.g. 0.15 — a real
56+
burst, weak sync), still let it into the decode path so a group-ACK (even
57+
0/N) is emitted. Risk: false-lock on noise / misaligning the next real
58+
sync — bound with an energy floor + the correct-base 0/N ACK is harmless.
59+
2. IMMEDIATE ANCHOR-NACK: on reject-with-energy, send a bare "resend full
60+
anchor" tone NACK immediately (needs a group-less NACK tone type). Cleaner
61+
semantically, more protocol surface.
62+
3. RTO CAP for the anchor-reject case: the receiver knows instantly it can't
63+
sync; the sender shouldn't wait 44 s. (Blunt; approach 1 is better.)
64+
- Related: [[project_turnaround_rxq_defeats_warmsync]] (warm-sync defeat /
65+
echo-clear), the ACK-contract family.
66+
3067
### BUG-FILE-CRC-MISMATCH: complete 51200/51200 file assembled with WRONG CONTENT (P0)
3168
- Status: **FIXED 2026-07-05 late evening.** Root-caused by 3-agent forensics (write-map + code audit + adversarial verify) over the preserved run; rig gate LIFTED.
3269
- Mechanism (confirmed, single event in all logs): the LDPC false-positive BIT-FLIP SALVAGE (frame_v2.cpp Case 2). Under status.allSuccess() every CW is a VALID codeword, so the true error is a codeword DIFFERENCE (>= d_min, tens of bits) — a 1-bit "repair" can never be genuine there. The salvage searched ~5k bit positions for a 16-bit CRC syndrome match (~7.8% collision odds vs garbage), hit one at t=38.4 ("FALSE POSITIVE RECOVERED (1-bit flip frame byte 584 bit 3)"), and delivered a corrupted 616-byte chunk (file[616:1232), seq=2) that was ACKed and never resent. Receiver assembly was proven flawless (78 chunks, perfect tiling, all era boundaries exact ACK-edge requeues).

0 commit comments

Comments
 (0)