From 854b14a52e7ac814bb27fc721a5f6c28446ccd89 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 9 Aug 2026 21:15:46 +0200 Subject: [PATCH] fix(validation): a leg that never ran must say so, not blame the arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The V3b run on .21 died with `open portal capturer: timed out waiting for the ScreenCast portal` — a GNOME consent dialog nobody answered — and the kit reported "arm A is not the in-process arm". That is false: the arm was constructed correctly (`PUNKTFUNK_ENCODE_WORKER=off` is right there in the captured env header), it simply never reached encoder-open, so the line the assert looks for could not exist. A red that points at the wrong thing costs the same debugging time as a green that hides a real one. `spike_failure_reason` now runs BEFORE any arm-identity assert in v2, v3a and v3b, and names the actual cause: the portal timeout gets its own message saying the dialog appears on the HOST's own screen and cannot be answered from inside a stream — which is precisely the situation that produced this failure, since the operator was watching the box through a game session at the time. Falls back to the first ERROR line, then to "no PUNKTFUNK_PERF window at all", so a spike that dies some other way still reports that rather than a misattribution. --- scripts/validate-encode-worker.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/scripts/validate-encode-worker.sh b/scripts/validate-encode-worker.sh index 9208ef3b..115c9b3a 100755 --- a/scripts/validate-encode-worker.sh +++ b/scripts/validate-encode-worker.sh @@ -400,6 +400,28 @@ assert_worker_arm() { return $rc } +# Why an arm produced nothing — checked BEFORE any arm-identity assert. +# +# "this arm is not the in-process arm" is a LIE when the truth is "capture never came up", and it +# sends the reader looking at the wrong thing entirely. That cost a real V3b run on .21: a GNOME +# consent dialog went unanswered, the spike died before opening an encoder, and the kit blamed the +# arm construction — which was correct all along. Prints a human reason and returns 0 when the arm +# never got far enough to be judged; returns 1 when the run is judgeable. +spike_failure_reason() { + local log="$1" line + if logs_have "$log" 'timed out waiting for the ScreenCast portal'; then + printf '%s' "the xdg ScreenCast portal was never answered. GNOME and KDE raise a CONSENT DIALOG on the host's own screen, and it cannot be answered from inside a stream — approve it there, or run a leg that needs no portal" + return 0 + fi + line="$(log_cat "$log" | LC_ALL=C grep -E 'ERROR' | head -1 | sed 's/^.*ERROR[[:space:]]*//')" + if [ -n "$line" ]; then printf '%s' "$line"; return 0; fi + if [ "$(perf_windows "$log")" = 0 ]; then + printf '%s' "the spike never encoded a frame — no PUNKTFUNK_PERF window in the log at all" + return 0 + fi + return 1 +} + assert_inline_arm() { local log="$1" tag="$2" rc=0 if ! logs_have "$log" "$L_OFF"; then @@ -798,6 +820,7 @@ leg_v2() { wait_spike "$OPT_SECONDS" local log="$SPIKE_LOG" + if why="$(spike_failure_reason "$log")"; then fail V2 "the run never got as far as an encoder: $why"; return 0; fi if ! assert_worker_arm "$log" V2; then fail V2 "the session did not run in the worker — see $log"; return 0 fi @@ -874,6 +897,8 @@ leg_v3a() { wait_spike "$OPT_SECONDS" local b_log="$SPIKE_LOG" + if why="$(spike_failure_reason "$a_log")"; then fail V3a "arm A never ran: $why"; return 0; fi + if why="$(spike_failure_reason "$b_log")"; then fail V3a "arm B never ran: $why"; return 0; fi assert_inline_arm "$a_log" V3a || { fail V3a "arm A is not the in-process arm — see $a_log"; return 0; } assert_worker_arm "$b_log" V3a || { fail V3a "arm B is not the worker arm — see $b_log"; return 0; } @@ -909,6 +934,8 @@ leg_v3b() { wait_spike "$OPT_SECONDS" local b_log="$SPIKE_LOG" + if why="$(spike_failure_reason "$a_log")"; then fail V3b "arm A never ran: $why"; return 0; fi + if why="$(spike_failure_reason "$b_log")"; then fail V3b "arm B never ran: $why"; return 0; fi assert_inline_arm "$a_log" V3b || { fail V3b "arm A is not the in-process arm — see $a_log"; return 0; } assert_worker_arm "$b_log" V3b || { fail V3b "arm B is not the worker arm — see $b_log"; return 0; } if ! logs_have "$b_log" "$L_GRANTED"; then