From c252ac4d5468f89270df5e107da19b4800754751 Mon Sep 17 00:00:00 2001 From: Godopu Date: Fri, 2 Oct 2026 08:23:31 +0900 Subject: [PATCH] fix(followups): F5 - no test switch in the stall watcher stall_watch read MAM_TEST_UNRELIABLE_AGENT to pretend an adapter's agent_status was unreliable (PR #41 M7). The branch is gone. S13 now runs the real stall_watch.main() in a process where the adapter itself reports agent_status_reliable = False (_UNRELIABLE_MAIN), and checks the same things as before: no idle notice or nudge, the blocked notice, and the "idle judgement off" log line. A static check keeps MAM_TEST_ out of the watcher (fails at 0051fd6). Without the seam S13 fails on this tree. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HCGpJXhSZasJLU38ksDghe --- .agents/skills/lib_py/stall_watch.py | 2 -- tests/test_issue30_stall_watch.py | 26 ++++++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.agents/skills/lib_py/stall_watch.py b/.agents/skills/lib_py/stall_watch.py index ebee84f..a311f84 100644 --- a/.agents/skills/lib_py/stall_watch.py +++ b/.agents/skills/lib_py/stall_watch.py @@ -225,8 +225,6 @@ class StallWatch(object): name = resolve_agent(args.agent, args.target) adapter = get_adapter(name) if name else None reliable = bool(adapter.agent_status_reliable) if adapter else True - if os.environ.get("MAM_TEST_UNRELIABLE_AGENT") == args.agent: - reliable = False self.st = WatchState(idle_s=float(os.environ.get("MAM_STALL_IDLE_S", "600")), reliable=reliable) self.fail_s = float(os.environ.get("MAM_STALL_HERDR_FAIL_S", "120")) self.once = set() diff --git a/tests/test_issue30_stall_watch.py b/tests/test_issue30_stall_watch.py index 27790be..c1a63e5 100644 --- a/tests/test_issue30_stall_watch.py +++ b/tests/test_issue30_stall_watch.py @@ -193,11 +193,20 @@ def _kill(p: subprocess.Popen) -> None: p.wait() -def _watch(env: dict, reg: Path, jid: str, target: str, agent: str) -> subprocess.Popen: +# The real watcher's main() in a process whose `agent` adapter reports an +# agent_status that cannot drive the idle judgement (S13) - the production +# code has no switch for it. +_UNRELIABLE_MAIN = ("import sys; from lib_py.agents.registry import get_adapter; " + "type(get_adapter(sys.argv[1])).agent_status_reliable = property(lambda self: False); " + "import lib_py.stall_watch as sw; sys.exit(sw.main(sys.argv[2:]))") + + +def _watch(env: dict, reg: Path, jid: str, target: str, agent: str, unreliable: bool = False) -> subprocess.Popen: tok = _record(reg, jid)["dispatch_token"] - return subprocess.Popen([sys.executable, "-m", "lib_py.stall_watch", "--job", jid, - "--registry-dir", str(reg), "--target", target, "--agent", agent, - "--expect-dispatch-token", tok], + argv = ["--job", jid, "--registry-dir", str(reg), "--target", target, "--agent", agent, + "--expect-dispatch-token", tok] + entry = ["-c", _UNRELIABLE_MAIN, agent] if unreliable else ["-m", "lib_py.stall_watch"] + return subprocess.Popen([sys.executable, *entry, *argv], env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) @@ -444,13 +453,12 @@ def test_s12_the_watcher_can_only_publish_progress(): def test_s13_unreliable_agent_status_turns_idle_off_but_keeps_blocked(box): _, state, reg, env = box - env["MAM_TEST_UNRELIABLE_AGENT"] = "claude" jid = _job(env, reg) agent = _proc("exec sleep 300") try: _agent(state, "creator-claude-t", "claude", agent.pid, "idle", _pane("claude"), detection="Do you want to proceed?") - w = _watch(env, reg, jid, "creator-claude-t", "claude") + w = _watch(env, reg, jid, "creator-claude-t", "claude", unreliable=True) time.sleep(5) assert _details(reg, jid) == [] and not _prompts(state) st = json.loads(state.read_text()) @@ -464,6 +472,12 @@ def test_s13_unreliable_agent_status_turns_idle_off_but_keeps_blocked(box): _kill(agent) +def test_s13_the_unreliable_case_needs_no_switch_in_the_product(): + """PR #41 M7: the test sets the adapter up (_UNRELIABLE_MAIN); the watcher + reads no environment variable to pretend an adapter is unreliable.""" + assert "MAM_TEST_" not in STALL_WATCH.read_text() + + # --------------------------------------------------------------------------- # scope - the #34 rule reaches the python herdr calls # ---------------------------------------------------------------------------