test(followups): F1 - A8 writes the marker lstart as loop_lock.sh reads it
`ps -o lstart=` pads a one-digit day ("Oct 1"); loop_lock.sh's mam_lstart
squeezes the spaces before comparing, but A8 wrote the raw value, so the
live holder's marker looked stale and the second loop was not refused on
the 1st-9th of every month. The test now normalises like the product (the
product is unchanged) and also runs with a `ps` shim that always prints a
padded lstart, so the padded case is checked on every date.
The other tests that record a live lstart (test_o3_scoped_guard
_get_lstart) already normalise; test_o2's markers carry fixed stale values.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HCGpJXhSZasJLU38ksDghe
This commit is contained in:
1 parent
0051fd6c3b
commit
75936f11c6
1 file changed
+34
-5
@@ -16,6 +16,8 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from test_issue21_loop_b import LOCAL_ROWS, _drive, _reviews, _sidecars, _state
|
from test_issue21_loop_b import LOCAL_ROWS, _drive, _reviews, _sidecars, _state
|
||||||
from test_issue21_phase2_loop_a import (REM, _calls, _prepare, _resume, _rows, _run, _skill, _wt, # noqa: F401
|
from test_issue21_phase2_loop_a import (REM, _calls, _prepare, _resume, _rows, _run, _skill, _wt, # noqa: F401
|
||||||
ctl)
|
ctl)
|
||||||
@@ -253,19 +255,46 @@ def test_a7_reviewer_test_output_stays_out_of_the_source_and_the_sandbox(wt_repo
|
|||||||
|
|
||||||
# A8 -------------------------------------------------------------------------
|
# A8 -------------------------------------------------------------------------
|
||||||
|
|
||||||
def test_a8_second_loop_is_refused_before_a_scheduler_exists(ctl):
|
# `ps -o lstart=` pads a one-digit day with a second space ("Oct 1"); this
|
||||||
|
# stands in for it so the padded case runs on every date, not only on the 1st-9th.
|
||||||
|
_PADDED_PS = """#!/bin/sh
|
||||||
|
case " $* " in
|
||||||
|
*" lstart= "*) out=$(/bin/ps "$@") || exit $?; [ -n "$out" ] && echo "Thu Oct 1 08:02:03 2026"; exit 0 ;;
|
||||||
|
esac
|
||||||
|
exec /bin/ps "$@"
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _marker_lstart(pid: int, env: dict) -> str:
|
||||||
|
"""The lstart a marker records, normalised as loop_lock.sh's mam_lstart does
|
||||||
|
(`tr -s ' '`, ends trimmed) - the raw value keeps the padding and never matches."""
|
||||||
|
out = subprocess.run(["ps", "-p", str(pid), "-o", "lstart="], capture_output=True, text=True, env=env).stdout
|
||||||
|
return " ".join(out.split())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("ps", ["real", "padded"])
|
||||||
|
def test_a8_second_loop_is_refused_before_a_scheduler_exists(ctl, tmp_path, ps):
|
||||||
main = ctl
|
main = ctl
|
||||||
wt2 = _wt(main, "wt2")
|
wt2 = _wt(main, "wt2")
|
||||||
_g(main, "worktree", "add", "-q", "--detach", str(wt2))
|
_g(main, "worktree", "add", "-q", "--detach", str(wt2))
|
||||||
|
env = {**os.environ, "WORKSPACE_ROOT": str(main), "MAM_LOOP_NO_FREEZE": "1"}
|
||||||
|
env.pop("MAM_LOOP_PY", None)
|
||||||
|
if ps == "padded":
|
||||||
|
shim = tmp_path / "ps-shim"
|
||||||
|
shim.mkdir()
|
||||||
|
(shim / "ps").write_text(_PADDED_PS)
|
||||||
|
(shim / "ps").chmod(0o755)
|
||||||
|
env["PATH"] = f"{shim}{os.pathsep}{env['PATH']}"
|
||||||
holder = subprocess.Popen(["sleep", "60"])
|
holder = subprocess.Popen(["sleep", "60"])
|
||||||
try:
|
try:
|
||||||
lstart = subprocess.run(["ps", "-p", str(holder.pid), "-o", "lstart="], capture_output=True,
|
lstart = _marker_lstart(holder.pid, env)
|
||||||
text=True).stdout.strip()
|
assert lstart, "ps found no holder"
|
||||||
|
if ps == "padded":
|
||||||
|
assert lstart == "Thu Oct 1 08:02:03 2026", f"the shim was not used: {lstart!r}"
|
||||||
marker = main.parent / f"{main.name}-loop-marker"
|
marker = main.parent / f"{main.name}-loop-marker"
|
||||||
content = f"pid={holder.pid}\nlstart={lstart}\nstarted={time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n"
|
content = f"pid={holder.pid}\nlstart={lstart}\nstarted={time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n"
|
||||||
marker.write_text(content)
|
marker.write_text(content)
|
||||||
env = {**os.environ, "WORKSPACE_ROOT": str(main), "MAM_LOOP_MARKER": str(marker), "MAM_LOOP_NO_FREEZE": "1"}
|
env["MAM_LOOP_MARKER"] = str(marker)
|
||||||
env.pop("MAM_LOOP_PY", None)
|
|
||||||
res = subprocess.run(["bash", _skill(main, "multi-agent-mux-loop", "scripts", "run_loop.sh"),
|
res = subprocess.run(["bash", _skill(main, "multi-agent-mux-loop", "scripts", "run_loop.sh"),
|
||||||
"--creator", "c", "--task", "t", "--worktree", str(wt2), "--base", "HEAD",
|
"--creator", "c", "--task", "t", "--worktree", str(wt2), "--base", "HEAD",
|
||||||
"--review-only", "--reviewer", "r"],
|
"--review-only", "--reviewer", "r"],
|
||||||
|
|||||||
Reference in new issue
Block a user