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:
GodopuandClaude Fable 5.1 committed 2026-09-13 16:11:53 +09:00
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