- 21.2B: resolve_cwd returns repo_identity (git:<path> stripped) not scaffold_location; worktree override; unknown project raises; no repo → refuse; 8 held-outs incl. old-bug reproduction. - 21.2C: wait_guard covers time.sleep(N) (inline + heredoc), polling loops (while/until + status on full command), repeated delay+status; 7 new held-outs; legitimate cases still pass. - 21.2D: canonical hook source at config/mimo-hooks/event-wait-guard.ts; scripts/install_mimo_hook.py verifies hash; drift test detects canonical↔installed divergence. - 21.2G: programme_gates.py — mandatory gates end in PASS/BLOCKED/ WAIVED_BY_USER only; GateDemotionError prevents mandatory→optional demotion; 6 held-outs.
63 lines
2.4 KiB
Python
63 lines
2.4 KiB
Python
"""test_wait_guard_normal_forms.py — T21.2 §21.2C: normal model-generated
|
|
wait spellings covered by the guard."""
|
|
from __future__ import annotations
|
|
import sys
|
|
from pathlib import Path
|
|
REPO = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(REPO / "src"))
|
|
from rune import wait_guard as wg # noqa: E402
|
|
|
|
|
|
def test_212c2_bash_c_sleep():
|
|
assert wg.classify_wait(
|
|
"bash -c 'sleep 500; curl -s $API/actions/runs'")[
|
|
"classification"] in ("UNJUSTIFIED_WAIT_POLL", "UNJUSTIFIED_SLEEP")
|
|
|
|
|
|
def test_212c2_time_sleep_inline():
|
|
r = wg.classify_wait(
|
|
"python3 -c 'import time; time.sleep(500)'; curl -s $API/commits/abc/status")
|
|
assert r["classification"] in ("UNJUSTIFIED_WAIT_POLL", "UNJUSTIFIED_SLEEP")
|
|
|
|
|
|
def test_212c2_time_sleep_heredoc():
|
|
r = wg.classify_wait(
|
|
"python3 - <<'PY'\nimport time; time.sleep(500)\nPY\ncurl -s $API/commits/abc/status")
|
|
assert r["classification"] in ("UNJUSTIFIED_WAIT_POLL", "UNJUSTIFIED_SLEEP")
|
|
|
|
|
|
def test_212c2_polling_loop_while():
|
|
r = wg.classify_wait(
|
|
"while true; do STATUS=$(curl -s $API/commits/abc/status); "
|
|
"if [ $STATUS = success ]; then break; fi; sleep 60; done")
|
|
assert r["classification"] in ("UNJUSTIFIED_WAIT_POLL", "UNJUSTIFIED_SLEEP")
|
|
|
|
|
|
def test_212c2_polling_loop_until():
|
|
r = wg.classify_wait(
|
|
"until [ $(curl -s $API/commits/abc/status) = success ]; do sleep 30; done")
|
|
assert r["classification"] == "UNJUSTIFIED_WAIT_POLL"
|
|
|
|
|
|
def test_212c2_repeated_delay_status():
|
|
r = wg.classify_wait(
|
|
"sleep 120; curl -s $API/actions/runs; sleep 120; curl -s $API/actions/runs")
|
|
assert r["classification"] in ("UNJUSTIFIED_WAIT_POLL", "UNJUSTIFIED_SLEEP")
|
|
|
|
|
|
def test_212c4_legitimate_still_passes():
|
|
# user delay
|
|
assert wg.classify_wait("sleep 45")["classification"] == "USER_REQUESTED_DELAY"
|
|
# short backoff
|
|
assert wg.classify_wait("curl -s $A; sleep 4; curl -s $A")[
|
|
"classification"] == "NO_WAIT"
|
|
# heredoc docs
|
|
cmd = "cat > f.md <<'EOF'\nsleep 540; poll CI\nEOF\necho done"
|
|
assert wg.classify_wait(cmd)["classification"] == "NO_WAIT"
|
|
# non-polling long sleep
|
|
assert wg.classify_wait("sleep 120\nmake build")[
|
|
"classification"] == "NO_WAIT"
|
|
# watchdog script (bounded retry in a .py file)
|
|
assert wg.classify_wait("python3 scripts/ci_event_wait.py --sha abc --deadline 900")[
|
|
"classification"] == "NO_WAIT"
|