From 75936f11c621ef25e729989992f313bbb76048a4 Mon Sep 17 00:00:00 2001 From: Godopu Date: Fri, 2 Oct 2026 08:08:26 +0900 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_01HCGpJXhSZasJLU38ksDghe --- tests/test_issue21_acceptance.py | 39 ++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/tests/test_issue21_acceptance.py b/tests/test_issue21_acceptance.py index 7faaa77..4d8b2e2 100644 --- a/tests/test_issue21_acceptance.py +++ b/tests/test_issue21_acceptance.py @@ -16,6 +16,8 @@ import subprocess import time from pathlib import Path +import pytest + 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 ctl) @@ -253,19 +255,46 @@ def test_a7_reviewer_test_output_stays_out_of_the_source_and_the_sandbox(wt_repo # 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 wt2 = _wt(main, "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"]) try: - lstart = subprocess.run(["ps", "-p", str(holder.pid), "-o", "lstart="], capture_output=True, - text=True).stdout.strip() + lstart = _marker_lstart(holder.pid, env) + 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" content = f"pid={holder.pid}\nlstart={lstart}\nstarted={time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n" marker.write_text(content) - env = {**os.environ, "WORKSPACE_ROOT": str(main), "MAM_LOOP_MARKER": str(marker), "MAM_LOOP_NO_FREEZE": "1"} - env.pop("MAM_LOOP_PY", None) + env["MAM_LOOP_MARKER"] = str(marker) res = subprocess.run(["bash", _skill(main, "multi-agent-mux-loop", "scripts", "run_loop.sh"), "--creator", "c", "--task", "t", "--worktree", str(wt2), "--base", "HEAD", "--review-only", "--reviewer", "r"],