From e4b51e14d142d208451e70a4c852e005d683a86b Mon Sep 17 00:00:00 2001 From: elkaix Date: Tue, 11 Aug 2026 21:54:08 -0400 Subject: [PATCH] test: make the midpoint budget case event-driven and drop a duplicate suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI failed on 37b53fd with two suites red, neither a product defect. The same content had passed as PR #5's check minutes earlier. t14_midpoint_warning_continues_same_job asked for a job to complete inside a window of (ceiling/2, ceiling) and then spent seven serialized poll cycles crossing it, each spawning a node process, against an 8-second ceiling. Every unit of runner slowness ate the margin until the loop cancelled at its deadline — behaving exactly as designed — and the case read that as failure. It had already failed this way on c2f2ea9 nine days earlier. Drive completion from the event instead of from the clock. The fixture's MAESTRO_TEST_JOB_TERMINAL_FLAG, which tests/job-lock.sh already uses, reports the job as running until a named file exists. The case now waits for the halfway warning, then creates that file, so completion is causally after the warning and one poll cycle away rather than seven. The ceiling lives in a single variable the assertion pattern derives from, so the two can no longer drift apart. All four assertions are unchanged. tests/shared-git-dir.sh re-ran the entire lease suite that tests/run.sh had already run and passed in the same job, piping it through `tail -1` so a failure inside it could not be diagnosed at all. It added no coverage, cost ~55s, and doubled the chance that any timing-sensitive lease case failed the build. Its other checks stay; the re-run goes. 42.87s to 2.07s. The remaining changes widen nine event waits from 5s to 30s across liveness, lease, and provenance-edge. These are preventive, not fixes for anything observed: each loop breaks as soon as its event arrives, so a larger bound costs nothing when the host is healthy and removes a false negative when it is not. A genuinely absent event still fails, only later. t19 is deliberately unchanged. It fails in the Codex sandbox because ps reports no process start identity there, so the contender fails closed instead of waiting; it passes on the GitHub runner and on developer hosts. Verified with the full suite under a fabricated empty HOME and /bin/bash 3.2, which is what the runner actually provides: 18 passed, 0 failed. --- tests/lease.sh | 6 +++--- tests/liveness.sh | 28 ++++++++++++++++------------ tests/provenance-edge.sh | 4 ++-- tests/shared-git-dir.sh | 4 +--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/lease.sh b/tests/lease.sh index da783fc..f8f0d7c 100755 --- a/tests/lease.sh +++ b/tests/lease.sh @@ -1031,7 +1031,7 @@ EOF } run_reclaimer B "$shim:$PATH" & bpid=$! - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do [ -e "$state/b-paused-once" ] || [ -e "$state/B-ready" ] || { sleep 0.05; continue; } break done @@ -1039,7 +1039,7 @@ EOF { kill "$bpid" 2>/dev/null || :; echo "reclaimer B did not reach acquisition"; return 1; } run_reclaimer A "$PATH" & apid=$! - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do [ -e "$state/A-ready" ] && [ -e "$state/B-ready" ] || { sleep 0.05; continue; } break done @@ -1255,7 +1255,7 @@ t48_prelaunch_interrupt_releases_without_poison() ( pid=$! set +m count=0 - while [ ! -e "$marker" ] && [ "$count" -lt 100 ]; do + while [ ! -e "$marker" ] && [ "$count" -lt 600 ]; do sleep 0.05 count=$((count + 1)) done diff --git a/tests/liveness.sh b/tests/liveness.sh index ff3cd78..3a47a11 100644 --- a/tests/liveness.sh +++ b/tests/liveness.sh @@ -736,7 +736,7 @@ t10_watchdog_signal_is_terminal() { ) > "$state/output" 2>&1 & pid=$! set +m - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do [ -s "$state/status.pid" ] && grep -q '^status task-fake0000-aaaaaa --json$' "$state/calls.log" && break sleep 0.05 @@ -791,7 +791,7 @@ t11_loop_signal_is_terminal() { ) > "$state/output" 2>&1 & pid=$! set +m - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do grep -q '^status task-fake0000-aaaaaa --json$' "$state/calls.log" && break sleep 0.05 done @@ -831,7 +831,7 @@ t12_loop_signal_reaps_verifier() { ) > "$state/output" 2>&1 & pid=$! set +m - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do [ -s "$state/child.pid" ] && break sleep 0.05 done @@ -877,7 +877,7 @@ t13_prelaunch_generation_fence() { ) > "$state/output" 2>&1 & pid=$! set +m - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do grep -q '^--help$' "$state/calls.log" && break sleep 0.05 done @@ -898,31 +898,35 @@ t13_prelaunch_generation_fence() { } t14_midpoint_warning_continues_same_job() { - local repo state pid warnings tasks + local repo state pid warnings tasks ceiling=12 warning repo=$(new_repo budget-midpoint-repo) state="$TEST_ROOT/budget-midpoint-state" + warning="^MAESTRO_BUDGET: .*continuing to the ${ceiling}s hard ceiling" mkdir -p "$state" : > "$state/calls.log" status_empty > "$state/status.json" - # Pin verification consumes the first phase; leave five running poll samples before completion. - printf 'running\nrunning\nrunning\nrunning\nrunning\nrunning\ncompleted\n' > "$state/phases" set -m ( cd "$repo" && exec env HOME="$TEST_HOME" PATH="$TEST_PATH" \ MAESTRO_TEST_CALL_LOG="$state/calls.log" \ - MAESTRO_TEST_JOB_PHASE_FILE="$state/phases" \ + MAESTRO_TEST_JOB_TERMINAL_FLAG="$state/complete" \ MAESTRO_TEST_STATUS="$state/status.json" \ - MAESTRO_MAX_DISPATCH_SEC=8 \ + MAESTRO_MAX_DISPATCH_SEC="$ceiling" \ bash "$LOOP" --plan "$TEST_ROOT/plan.md" --verify true \ --max-iters 1 --max-idle 30 --poll 1 ) > "$state/output" 2>&1 & pid=$! set +m - wait_bounded "$pid" 11 + for _ in $(seq 1 240); do + grep -q "$warning" "$state/output" && break + sleep 0.05 + done + grep -q "$warning" "$state/output" && : > "$state/complete" + wait_bounded "$pid" 17 [ "$WAIT_TIMED_OUT" -eq 0 ] || { echo "midpoint completion exceeded bound"; return 1; } [ "$WAIT_RC" -eq 0 ] || { echo "rc=$WAIT_RC want 0: $(tr '\n' ' ' < "$state/output")"; return 1; } - warnings=$(grep -c '^MAESTRO_BUDGET: .*continuing to the 8s hard ceiling' "$state/output" || true) + warnings=$(grep -c "$warning" "$state/output" || true) tasks=$(grep -c '^task ' "$state/calls.log" || true) [ "$warnings" -eq 1 ] || { echo "midpoint warnings=$warnings want 1"; return 1; } [ "$tasks" -eq 1 ] || { echo "task starts=$tasks want 1"; return 1; } @@ -1093,7 +1097,7 @@ t19_waiting_contender_signal_does_not_cancel_owner() ( ) > "$state/output" 2>&1 3>&1 & pid=$! set +m - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do grep -q 'waiting for the write lease' "$state/output" && break sleep 0.05 done diff --git a/tests/provenance-edge.sh b/tests/provenance-edge.sh index c9f833e..791d5a4 100644 --- a/tests/provenance-edge.sh +++ b/tests/provenance-edge.sh @@ -111,7 +111,7 @@ EOF PATH="$shim:$PATH" write_lock_release ) > "$state/holder.out" 2>&1 & holder=$! - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do [ -e "$state/lock-removed" ] && break sleep 0.05 done @@ -190,7 +190,7 @@ t7_orphan_baseline_is_published_before_reclaim_handoff() { printf '%s\n' "$?" > "$state/reclaimer.rc" ) & reclaimer=$! - for _ in $(seq 1 100); do + for _ in $(seq 1 600); do [ -e "$state/publishing" ] && break sleep 0.05 done diff --git a/tests/shared-git-dir.sh b/tests/shared-git-dir.sh index d64a68f..5cf34d9 100755 --- a/tests/shared-git-dir.sh +++ b/tests/shared-git-dir.sh @@ -63,6 +63,4 @@ SUB_RC=$(cat "$D/sub-rc.txt" 2>/dev/null) N=$(mktemp -d); F=$(cd "$N" && bash -c "set -uo pipefail; . '$LIB'; write_lock_path"); rm -rf "$N" case "$F" in */.maestro-write.lock) ;; *) echo "VERIFY FAIL: non-git fallback = $F"; exit 1;; esac -[ -f "$ROOT/tests/lease.sh" ] || { echo "VERIFY FAIL: missing $ROOT/tests/lease.sh"; exit 1; } -bash "$ROOT/tests/lease.sh" 2>&1 | tail -1 | grep -qE '[1-9][0-9]* passed, 0 failed' || { echo "VERIFY FAIL: lease suite regressed"; exit 1; } -echo "VERIFY PASS: shared worktree/submodule lease path, contention=11, fallback intact, lease suite green" +echo "VERIFY PASS: shared worktree/submodule lease path, contention=11, fallback intact"