re: fix the bind failure; witness search window was too narrow

Two harness problems, one fixed and verified, one diagnosed.

Bind: three consecutive attempts failed and the session aborted rather than
flying an unattended craft, which is last iteration's guard working as intended.
The cause is that entities2 self finds the player by motion between two samples,
so a craft sitting still at mission start is invisible. The session now holds the
throttle for three seconds before each attempt. Verified: the next run bound
immediately and produced 11 losses with zero confirmed arrivals, making fourteen
runs without one. One increase, 10 to 11, was surfaced and correctly not counted.

Witness: the frame-rate-band selection is still unreliable. It found only five
candidates in band and reported 0 of 5 moved in samples where craft were being
destroyed, and a counter genuinely running at 24/s cannot fail to advance across
a 15 s sample -- it would gain about 360. They are bursty counters that moved
during the 3 s calibration and then stopped.

The cause is mine. When the witness was bolted into wave7_probe the candidate
search was narrowed to a 4 MB window, while timer_probe searched the whole 32 MB
region and found 286 candidates with a clean cluster near 17/s. The narrowing
was never justified, it was just cheaper to write. Now searches the full region
once at startup, which is a one-off cost rather than per sample, and warns
explicitly when fewer than eight witnesses are available so a weak vote is
visible instead of silently trusted. Not yet run.

Worth recording: this is the third attempt at this witness, and all three
failures share one pattern -- a shortcut in selecting the witness rather than in
the voting logic. Each was caught only because the flagged samples contradicted
the loss events in the same output. That internal contradiction is the real
check and should survive into any future version.
This commit is contained in:
Sylpheed RE agent
2026-08-24 17:30:03 +00:00
parent 2b98105ac0
commit 1afe1b7134
4 changed files with 81 additions and 3 deletions

View File

@@ -84,8 +84,18 @@ def main():
# timer_probe's approach instead -- collect every candidate, keep the modal
# rate cluster, and call a stall only when a MAJORITY of that cluster fails
# to advance.
lo = gmem.va_to_off(0xBC000000)
a = os.pread(fd, 1 << 22, lo); time.sleep(3.0); b = os.pread(fd, 1 << 22, lo)
# 4 MB was too narrow: it yielded 5 candidates at a nominal 24/s that then
# failed to advance in 15 s windows where craft were being destroyed, i.e.
# they are bursty, not frame counters. timer_probe searched the WHOLE 32 MB
# region and found 286 with a clean cluster at ~17/s. Pay the one-off cost.
lo, hiw = gmem.va_to_off(0xBC000000), gmem.va_to_off(0xBE000000)
span = hiw - lo
def grab():
out, pos = bytearray(), lo
while pos < hiw:
n = min(1 << 24, hiw - pos); out += os.pread(fd, n, pos); pos += n
return bytes(out)
a = grab(); time.sleep(3.0); b = grab()
cands = []
for k in range(0, min(len(a), len(b)) - 3, 4):
va, vb = struct.unpack_from('>I', a, k)[0], struct.unpack_from('>I', b, k)[0]
@@ -101,6 +111,8 @@ def main():
pick = max(band, key=lambda r: rates[r]) if band else (
rates.most_common(1)[0][0] if rates else None)
ticks = [o for o, r in cands if r == pick][:32]
if len(ticks) < 8:
print('WARNING: only %d witnesses; stall detection is weak' % len(ticks))
print('tick witnesses: %d candidates, using %d at %s/s (frame-rate band)'
% (len(cands), len(ticks), pick)
if ticks else 'tick witnesses: NONE -- RUN UNVALIDATED')

View File

@@ -9,8 +9,15 @@ CFG=/tmp/nav-live.json
# The bind is intermittent and a failed bind means no pilot, no kills and a
# completely uninformative run. Retry before giving up, and abort if it never
# takes rather than silently flying an unattended craft.
# entities2 self finds the player by MOTION between two samples, so a craft that
# is sitting still at mission start is invisible and the bind fails -- three
# times in a row on the run that added this retry. Nudge the throttle first so
# there is something to see, then bind.
BOUND=0
for try in 1 2 3; do
python3 "$SD/pad.py" set "rt=1" >/dev/null 2>&1 || true
sleep 3
python3 "$SD/pad.py" clear >/dev/null 2>&1 || true
if python3 "$SD/entities2.py" self 0x130 "$CFG" >/dev/null 2>&1; then BOUND=1; break; fi
echo "--- bind attempt $try failed, retrying"; sleep 5
done