fix(id_order): server_not_running is unknown and cap 0 asks no herdr (Issue #63)

PR #69 review round 3 (rebuttal overruled; codex r2 applied as written).

- A failed `agent list`, herdr's server_not_running included, is unknown and
  keeps an orphaned marker; only a successful list without the name prunes.
- No probe floor: probes get only the time left until the wait deadline, so
  MAM_ID_ORDER_WAIT_S=0 asks herdr nothing (unknown, kept) and the refusal
  says so.
- The timeout message reports the last definite answer of this wait, so an
  alive orphan whose final probe ran out of time still reads as alive.
- Tests follow: server_not_running and cap 0 keep the marker and refuse;
  delayed-probe bound is the cap itself; probing tests use a small cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-23 10:24:39 +09:00
1 parent 8f64174b6b
commit 7cac6f613e
2 files changed
+35 -34

No files matched your search

+20 -10
View File
@@ -1165,12 +1165,13 @@ def test_id_order_create_waits_for_orphan_herdr_session_of_a_killed_create(
["bash", str(create_sh), "--workspace", str(ws), "--agent", "agy",
"--role", "reviewer", "--session", name_b, "--no-onboard"],
capture_output=True, text=True, cwd=str(mam_sandbox),
env=dict(os.environ, MAM_ID_ORDER_WAIT_S="0"), timeout=120,
env=dict(os.environ, MAM_ID_ORDER_WAIT_S="3"), timeout=120,
)
res = create_b()
assert res.returncode == 1, res.stdout + res.stderr
assert name_a in res.stderr and "kill-session -t " + name_a in res.stderr
assert "its herdr session is alive" in res.stderr
assert name_b not in _read_rows(mam_sandbox)
assert name_b not in json.loads(Path(mock_herdr).read_text()).get("agents", {})
@@ -1186,9 +1187,9 @@ def test_id_order_create_waits_for_orphan_herdr_session_of_a_killed_create(
def test_id_order_herdr_probes_stay_within_the_wait_cap(tmp_path, monkeypatch):
"""PR #69 review r2 P2: probes of dead-owner markers get the time left until
max(deadline, start + PROBE_FLOOR_S), shared by all markers, so a slow herdr
cannot hold the wait (and its lock) past the cap; an expired probe is unknown."""
"""PR #69 review r2 P2: probes of dead-owner markers get only the time left
until the wait deadline, shared by all markers, so a slow herdr cannot hold
the wait (and its lock) past the cap; cap 0 asks nothing (unknown, kept)."""
from lib_py.agents import id_order
home = tmp_path / "home"
@@ -1219,17 +1220,20 @@ def test_id_order_herdr_probes_stay_within_the_wait_cap(tmp_path, monkeypatch):
rc = id_order.wait(str(ws), "agy", "new-agy", os.getpid(), yaml_path=str(yaml_path),
home=str(home), wait_s_val=cap, poll=0.05, pane_state=slow_probe)
elapsed = time.monotonic() - t0
bound = max(cap, id_order.PROBE_FLOOR_S)
bound = cap
assert rc == 1, cap
assert elapsed < bound + 0.6, (cap, elapsed)
assert budgets and max(budgets) <= bound + 0.01, (cap, budgets)
if cap == 0:
assert elapsed < 0.3 and all(b <= 0 for b in budgets), (elapsed, budgets)
assert len(list(Path(dpath).glob("orphan-*.json"))) == 2, cap
def test_id_order_real_probe_against_mock_herdr_fails_closed(mam_sandbox, mock_herdr):
"""PR #69 review r2 P1: lib.sh mam_id_order_wait with the real probe (sandbox
copy, mock herdr). A listed orphan blocks; an unlisted one is pruned; a failed
`agent list` keeps the marker and refuses; herdr's server_not_running prunes."""
`agent list` (server_not_running included) keeps the marker and refuses;
with MAM_ID_ORDER_WAIT_S=0 herdr is not asked and the marker is kept."""
from lib_py.agents import id_order
ws = mam_sandbox / "probe-ws"
@@ -1249,14 +1253,14 @@ def test_id_order_real_probe_against_mock_herdr_fails_closed(mam_sandbox, mock_h
state.update(kw)
Path(mock_herdr).write_text(json.dumps(state))
def wait_b():
def wait_b(cap="2"):
for f in Path(dpath).glob(f"{name_b}.json"):
f.unlink()
id_order.write_marker(dpath, name_a, dead.pid, str(ws), "agy", herdr_server="probe-ws")
return subprocess.run(
["bash", "-c", 'source "$1" && mam_id_order_wait "$2" agy "$3"', "_", str(lib), str(ws), name_b],
capture_output=True, text=True, cwd=str(mam_sandbox), timeout=120,
env=dict(os.environ, MAM_ID_ORDER_WAIT_S="0", HERDR_SESSION_NAME="probe-ws"),
env=dict(os.environ, MAM_ID_ORDER_WAIT_S=cap, HERDR_SESSION_NAME="probe-ws"),
)
try:
@@ -1273,10 +1277,16 @@ def test_id_order_real_probe_against_mock_herdr_fails_closed(mam_sandbox, mock_h
set_mock(force_error_code="server_not_running")
res = wait_b()
assert res.returncode == 0, res.stderr
assert not marker_a.exists()
assert res.returncode == 1, res.stderr
assert "herdr could not tell whether its session is gone" in res.stderr
assert marker_a.exists()
set_mock()
res = wait_b(cap="0")
assert res.returncode == 1, res.stderr
assert "MAM_ID_ORDER_WAIT_S=0 leaves no time to ask herdr" in res.stderr
assert marker_a.exists()
res = wait_b()
assert res.returncode == 0, res.stderr
assert not marker_a.exists()