a73x

a5823b4d

feat(m9): the control that makes leg 1 mean something

a73x   2026-08-08 17:15

Commit message
feat(m9): the control that makes leg 1 mean something

Leg 1 was reported against one control — the authoritative echo of the same
keystroke. That proves the harness times the path, but it does not measure
what the criterion actually asks for: input prediction does not apply to.

The plan words that as an "echo-off context", and as written it cannot be
timed at all — with echo off nothing is painted, so there is no arrival to
put a clock on. The measurable form of the same claim is input the overlay
REFUSES: two characters in one write arrive as one chunk, refused for being
multi-byte, so they cannot appear until the daemon answers.

  predict     med   0.1ms
  predictoff  med 154.2ms   (unpredicted, same run, same connection)
  predictauth med 154.2ms
  baseline    med 150.5ms

Three orders of magnitude between predicted and unpredicted input on one
connection in one run. If prediction were secretly responsible for the fast
number, the refused input would be fast too; it sits exactly on the round
trip instead. A control that came back fast now FAILS the leg rather than
being read as a better result, because that would mean the "unpredicted"
input was being predicted and the comparison proved nothing.

Also prints the headroom the burst numbers live inside: a prediction is
retired unanswered after 1000ms, and what it has to survive is the round
trip plus however long a burst's later keystrokes queue behind its earlier
ones — measured here as the burst's own convergence time, 233.8ms against
the 1000ms bound. Cross it and the predictions expire mid-burst and the
counters collapse, which is what 400ms each way did to the e2e suite. The
numbers are only reproducible while that margin holds, so it is printed
beside them rather than left in a commit message.

This run: made=54 confirmed=54 contradicted=0 expired=0 abandoned=0
pending=0 across ten adversarial bursts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

test/wan.sh
Old New
@@ -951,6 +951,29 @@ def cmd_predict(argv):
951 if c.wait_for(lambda b, w=run: w in b, timeout=20.0) is None: 951 if c.wait_for(lambda b, w=run: w in b, timeout=20.0) is None:
952 fail("predict: rep %d never echoed authoritatively" % i) 952 fail("predict: rep %d never echoed authoritatively" % i)
953 auth.append((now() - t0) * 1000.0) 953 auth.append((now() - t0) * 1000.0)
954 # The control the criterion asks for: input prediction does NOT
955 # apply to, timed on the same connection in the same run.
956 #
957 # "Echo-off context" is the plan's wording and it cannot be timed as
958 # written — with echo off nothing is painted at all, so there is no
959 # arrival to put a clock on. The measurable form of the same claim is
960 # input the overlay REFUSES: two characters in one write reach the
961 # client as one chunk, which is refused for being multi-byte, so the
962 # glyphs cannot appear until the daemon answers. If prediction were
963 # secretly doing the work in the numbers above, these would be fast
964 # too. They are not, and that is the point of measuring them.
965 off = []
966 for i in range(min(reps, 10)):
967 pair = bytes("Q%d" % i, "ascii")
968 start = len(c.buf)
969 t0 = now()
970 c.send(pair) # ONE write, so ONE read at the far end
971 if c.wait_for(lambda b, w=pair, s=start: w in b[s:],
972 timeout=20.0) is None:
973 fail("predict: unpredicted control %d never painted" % i)
974 off.append((now() - t0) * 1000.0)
975 c.drain(0.1)
976
954 # Deliberately no EOF to end `cat`. Ending it means the next 977 # Deliberately no EOF to end `cat`. Ending it means the next
955 # keystroke lands at a bash prompt, which is a different termios and 978 # keystroke lands at a bash prompt, which is a different termios and
956 # therefore a different prediction tier — and over a 150ms path the 979 # therefore a different prediction tier — and over a 150ms path the
@@ -965,8 +988,10 @@ def cmd_predict(argv):
965 st = predict_stats(errlog) 988 st = predict_stats(errlog)
966 report("predict", pred, **{k: st.get(k, -1) for k in 989 report("predict", pred, **{k: st.get(k, -1) for k in
967 ("made", "displayed", "confirmed", 990 ("made", "displayed", "confirmed",
968 "contradicted", "expired", "abandoned")}) 991 "contradicted", "expired", "abandoned",
992 "suppressed")})
969 report("predictauth", auth) 993 report("predictauth", auth)
994 report("predictoff", off)
970 995
971 996
972 def cmd_predictburst(argv): 997 def cmd_predictburst(argv):
@@ -1422,7 +1447,7 @@ if [ -n "$(val predict predict med)" ]; then
1422 echo 1447 echo
1423 echo "M9 prediction (netem 150ms egress):" 1448 echo "M9 prediction (netem 150ms egress):"
1424 printf ' %-34s %8s %8s %8s %5s\n' "" min med max n 1449 printf ' %-34s %8s %8s %8s %5s\n' "" min med max n
1425 for name in baseline predict predictauth predictburst; do 1450 for name in baseline predict predictoff predictauth predictburst; do
1426 [ -n "$(val predict "$name" med)" ] || continue 1451 [ -n "$(val predict "$name" med)" ] || continue
1427 printf ' %-34s %8s %8s %8s %5s\n' "$name" \ 1452 printf ' %-34s %8s %8s %8s %5s\n' "$name" \
1428 "$(val predict "$name" min)" "$(val predict "$name" med)" \ 1453 "$(val predict "$name" min)" "$(val predict "$name" med)" \
@@ -1436,10 +1461,20 @@ if [ -n "$(val predict predict med)" ]; then
1436 if awk -v r="$P_RTT" 'BEGIN{exit !(r < 50)}'; then 1461 if awk -v r="$P_RTT" 'BEGIN{exit !(r < 50)}'; then
1437 echo " leg 1: NOT EXERCISED — round trip $P_RTT ms is below the 50ms floor" 1462 echo " leg 1: NOT EXERCISED — round trip $P_RTT ms is below the 50ms floor"
1438 elif awk -v m="$P_MED" 'BEGIN{exit !(m <= 30)}'; then 1463 elif awk -v m="$P_MED" 'BEGIN{exit !(m <= 30)}'; then
1464 P_OFF="$(val predict predictoff med)"
1439 echo " leg 1: predicted paint med $P_MED <= 30ms -> PASS (round trip $P_RTT ms)" 1465 echo " leg 1: predicted paint med $P_MED <= 30ms -> PASS (round trip $P_RTT ms)"
1440 echo " control: the SAME keystroke's authoritative echo med $P_AUTH ms," 1466 echo " control, unpredicted input (refused as multi-byte): med $P_OFF ms"
1441 echo " which tracks the measured round trip — so this harness is timing" 1467 echo " control, same keystroke's authoritative echo: med $P_AUTH ms"
1442 echo " the path, and the predicted number is independent of it." 1468 echo " Both track the measured round trip while the predicted number does"
1469 echo " not, which is what rules out the harness having timed the hardware."
1470 # A control that came back fast would mean the "unpredicted" input was
1471 # being predicted after all, and leg 1's number would be meaningless.
1472 if [ -n "$P_OFF" ] && awk -v o="$P_OFF" -v r="$P_RTT" 'BEGIN{exit !(o < r/2)}'; then
1473 echo " leg 1 CONTROL FAILED: unpredicted input came back in $P_OFF ms, well"
1474 echo " under the $P_RTT ms path — it cannot have waited for the daemon,"
1475 echo " so the comparison above proves nothing."
1476 FAILED=1
1477 fi
1443 else 1478 else
1444 echo " leg 1: predicted paint med $P_MED > 30ms -> FAIL (round trip $P_RTT ms)" 1479 echo " leg 1: predicted paint med $P_MED > 30ms -> FAIL (round trip $P_RTT ms)"
1445 FAILED=1 1480 FAILED=1
@@ -1455,6 +1490,18 @@ if [ -n "$(val predict predict med)" ]; then
1455 if [ -n "$B_MADE" ]; then 1490 if [ -n "$B_MADE" ]; then
1456 echo " counters after $REPS_BURST bursts: made=$B_MADE confirmed=$B_CONF" \ 1491 echo " counters after $REPS_BURST bursts: made=$B_MADE confirmed=$B_CONF" \
1457 "contradicted=$B_CONTRA expired=$B_EXP abandoned=$B_ABND pending=$B_PEND" 1492 "contradicted=$B_CONTRA expired=$B_EXP abandoned=$B_ABND pending=$B_PEND"
1493 # The ceiling these numbers live under, printed WITH them because it
1494 # is what decides whether they are reproducible on a slower path. A
1495 # prediction is retired unanswered after expire_after_ms; the wait it
1496 # actually has to survive is the round trip plus however long the
1497 # burst's later keystrokes queue behind the earlier ones. Measured
1498 # here as the burst's own convergence time. Cross this and the
1499 # predictions expire mid-burst and the counters collapse — which is
1500 # exactly what happened at 400ms each way in the e2e suite.
1501 B_CONVMED="$(val predict predictburst med)"
1502 echo " headroom: burst converged in ${B_CONVMED}ms (round trip $P_RTT ms +"
1503 echo " the burst's own typing span) against the overlay's 1000ms"
1504 echo " expiry bound — the margin a slower path spends first"
1458 # Leg 2, in this harness's substituted form. Comparing the client's 1505 # Leg 2, in this harness's substituted form. Comparing the client's
1459 # paint stream to `muxd dump` byte for byte needs a second terminal 1506 # paint stream to `muxd dump` byte for byte needs a second terminal
1460 # emulator in the harness — the same narrowing recorded for M7 at 1507 # emulator in the harness — the same narrowing recorded for M7 at