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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HCGpJXhSZasJLU38ksDghe
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-02 08:23:31 +09:00
1 parent fb1b93c665
commit c252ac4d54
2 files changed
+20 -8

No files matched your search

-2
View File
@@ -225,8 +225,6 @@ class StallWatch(object):
name = resolve_agent(args.agent, args.target) name = resolve_agent(args.agent, args.target)
adapter = get_adapter(name) if name else None adapter = get_adapter(name) if name else None
reliable = bool(adapter.agent_status_reliable) if adapter else True 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.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.fail_s = float(os.environ.get("MAM_STALL_HERDR_FAIL_S", "120"))
self.once = set() self.once = set()
+20 -6
View File
@@ -193,11 +193,20 @@ def _kill(p: subprocess.Popen) -> None:
p.wait() 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"] tok = _record(reg, jid)["dispatch_token"]
return subprocess.Popen([sys.executable, "-m", "lib_py.stall_watch", "--job", jid, argv = ["--job", jid, "--registry-dir", str(reg), "--target", target, "--agent", agent,
"--registry-dir", str(reg), "--target", target, "--agent", agent, "--expect-dispatch-token", tok]
"--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) 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): def test_s13_unreliable_agent_status_turns_idle_off_but_keeps_blocked(box):
_, state, reg, env = box _, state, reg, env = box
env["MAM_TEST_UNRELIABLE_AGENT"] = "claude"
jid = _job(env, reg) jid = _job(env, reg)
agent = _proc("exec sleep 300") agent = _proc("exec sleep 300")
try: try:
_agent(state, "creator-claude-t", "claude", agent.pid, "idle", _pane("claude"), _agent(state, "creator-claude-t", "claude", agent.pid, "idle", _pane("claude"),
detection="Do you want to proceed?") 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) time.sleep(5)
assert _details(reg, jid) == [] and not _prompts(state) assert _details(reg, jid) == [] and not _prompts(state)
st = json.loads(state.read_text()) 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) _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 # scope - the #34 rule reaches the python herdr calls
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------