fix(issue-19): close the trap race, select daemons by argv shape, align docs with the polling fallback
Review round 1 (claude PASS, agy PASS) recommendations: - reconcile.sh: `_sub_stop` falls back to `$!` for the window before `_sub_pid=$!` (R-1); lock identity compared as (st_dev, st_ino). - lib.sh legacy start_watchdog prints nothing when opted out and no daemon runs, byte-identical to the python body. - conftest/test: `_is_subscriber_daemon_argv` selects only `bash|sh <root>/.../reconcile.sh --subscribe`, never a brief-carrying wrapper that quotes the words or a prefix-colliding sibling root (R-2); one new unit test for the selector. - monitor SKILL.md / VERSIONS.md: the polling fallback checks the lock file's presence only and does not exclude a second daemon; measurement wording uses the argv-shape criterion instead of raw pgrep. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
4da4a50682
commit
c096cb455b
6 files changed
+69
-16
No files matched your search
@@ -58,11 +58,14 @@ def _run_helper(sandbox: Path, snippet: str, env=None) -> subprocess.CompletedPr
|
||||
|
||||
|
||||
def _daemons_for(sandbox: Path) -> list:
|
||||
"""Same argv-token selection as the conftest reaper (review R-2)."""
|
||||
from conftest import _is_subscriber_daemon_argv
|
||||
|
||||
out = subprocess.run(["pgrep", "-f", "reconcile.sh --subscribe"], capture_output=True, text=True).stdout.split()
|
||||
hits = []
|
||||
for pid in out:
|
||||
args = subprocess.run(["ps", "-o", "args=", "-p", pid], capture_output=True, text=True).stdout
|
||||
if str(sandbox) in args:
|
||||
if _is_subscriber_daemon_argv(args, str(sandbox)):
|
||||
hits.append(int(pid))
|
||||
return hits
|
||||
|
||||
@@ -210,6 +213,25 @@ def test_create_session_without_opt_out_spawns_a_daemon_the_reaper_removes(mam_s
|
||||
# 2. the sandbox reaper
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_reaper_selects_only_the_daemon_argv_shape(tmp_path):
|
||||
"""Review R-2: a process that quotes the words in a brief, or lives under
|
||||
a sibling root that is a string prefix, must never be selected."""
|
||||
from conftest import _is_subscriber_daemon_argv
|
||||
|
||||
root = str(tmp_path / "sbx1")
|
||||
daemon = "bash {}/.agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh --subscribe --idle-timeout 0".format(root)
|
||||
assert _is_subscriber_daemon_argv(daemon, root)
|
||||
assert _is_subscriber_daemon_argv("/bin/sh " + daemon.split(" ", 1)[1], root)
|
||||
# sibling root that is a prefix of this one
|
||||
assert not _is_subscriber_daemon_argv(daemon, root[:-1])
|
||||
assert not _is_subscriber_daemon_argv(daemon, root + "0")
|
||||
# brief-carrying wrapper that merely quotes the words and the path
|
||||
quoting = "python3 -m lib_py.delegation.cli submit --prompt 'note: reconcile.sh --subscribe under {}/.agents/skills/x'".format(root)
|
||||
assert not _is_subscriber_daemon_argv(quoting, root)
|
||||
# the real reconcile.sh in a different mode
|
||||
assert not _is_subscriber_daemon_argv(daemon.replace("--subscribe", "--once"), root)
|
||||
assert not _is_subscriber_daemon_argv("", root)
|
||||
|
||||
def test_sandbox_reaper_terminates_daemons_anchored_in_the_sandbox(mam_sandbox, monkeypatch):
|
||||
from conftest import _reap_subscriber_daemons, _subscriber_daemon_pids
|
||||
from lib_py.delegation import daemon
|
||||
|
||||
Reference in new issue
Block a user