fix(id_order): reserve startup when resume resolves an unrecorded uuid (Issue #63)
This commit is contained in:
1 parent
c747374aa6
commit
d115bf7156
2 files changed
+72
-13
No files matched your search
@@ -122,12 +122,14 @@ def blockers(state: Dict[str, Any], cwd: str, agent: str, me: str,
|
||||
prev_epoch = int(m.get("prev_epoch") or 0)
|
||||
prev_end_epoch = int(m.get("prev_end_epoch") or 0)
|
||||
|
||||
pinned_for_attempt = bool(cur_own) and (
|
||||
cur_own != prev_own
|
||||
or (status == "running" and row_epoch > prev_epoch)
|
||||
)
|
||||
if pinned_for_attempt:
|
||||
continue
|
||||
if status == "running":
|
||||
pinned_for_attempt = bool(cur_own) and (
|
||||
cur_own != prev_own or row_epoch > prev_epoch
|
||||
)
|
||||
if not pinned_for_attempt:
|
||||
found.append(m_sess)
|
||||
found.append(m_sess)
|
||||
else:
|
||||
ended_after_attempt = (
|
||||
end_epoch > max(m_at, prev_end_epoch)
|
||||
@@ -231,14 +233,15 @@ def wait(cwd: str, agent: str, session: str, owner_pid: int,
|
||||
markers = _read_and_prune_markers(dpath, session, is_alive=is_alive)
|
||||
blks = blockers(state, cwd, agent, session, markers, is_alive=is_alive)
|
||||
if not blks:
|
||||
if not uuid and owner_pid and owner_pid > 0:
|
||||
prev_row = next(
|
||||
(
|
||||
s for s in (state.get("herdr_sessions") or [])
|
||||
if isinstance(s, dict) and s.get("name") == session
|
||||
),
|
||||
None,
|
||||
)
|
||||
prev_row = next(
|
||||
(
|
||||
s for s in (state.get("herdr_sessions") or [])
|
||||
if isinstance(s, dict) and s.get("name") == session
|
||||
),
|
||||
None,
|
||||
)
|
||||
already_recorded = bool(uuid) and own_id(prev_row, agent) == uuid
|
||||
if not already_recorded and owner_pid and owner_pid > 0:
|
||||
write_marker(dpath, session, owner_pid, cwd, agent, prev_row=prev_row)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -978,3 +978,59 @@ def test_canonical_cwd_distinguishes_underscore_hyphen_and_nested_paths_with_sym
|
||||
res_hyphen = decide_resume(state_stopped, "hyphen-agy", "agy", str(ws_hyphen), home=str(home))
|
||||
assert res_hyphen["uuid"] == UB
|
||||
assert res_hyphen["notes"] == []
|
||||
|
||||
|
||||
def test_id_order_resolved_but_unrecorded_resume_uuid_reserves_startup_until_recorded(tmp_path, monkeypatch):
|
||||
"""When a single stopped post-discovered row with no own_id resolves a uuid from disk,
|
||||
id_order.wait reserves startup (writes a marker) until that uuid is recorded on the row."""
|
||||
from lib_py.agents import id_order
|
||||
from lib_py.agents.session_ids import decide_resume
|
||||
|
||||
home = tmp_path / "home"
|
||||
ws = tmp_path / "ws"
|
||||
ws.mkdir(parents=True)
|
||||
yaml_path = tmp_path / "agent-sessions.yaml"
|
||||
monkeypatch.setenv("HOME", str(home))
|
||||
monkeypatch.setenv("AGENT_SESSIONS_YAML", str(yaml_path))
|
||||
|
||||
_agy_conv(home, UA, time.time() - 10)
|
||||
_agy_cache(home, {ws: UA})
|
||||
|
||||
old_epoch = int(time.time()) - 100
|
||||
row_a = _row("same-ws-creator-agy", "agy", ws, old_epoch, status="stopped", agy_conversation_id_own=None)
|
||||
state = {"herdr_sessions": [row_a]}
|
||||
yaml_path.write_text(yaml.safe_dump(state))
|
||||
|
||||
dec = decide_resume(state, "same-ws-creator-agy", "agy", str(ws), home=str(home))
|
||||
assert dec["uuid"] == UA
|
||||
|
||||
proc_a = subprocess.Popen(["sleep", "120"])
|
||||
proc_b = subprocess.Popen(["sleep", "120"])
|
||||
try:
|
||||
# Admit A with resolved (but not yet recorded) uuid UA -> writes startup marker
|
||||
assert id_order.wait(
|
||||
str(ws), "agy", "same-ws-creator-agy", proc_a.pid, uuid=UA,
|
||||
yaml_path=str(yaml_path), home=str(home), wait_s_val=0,
|
||||
) == 0
|
||||
|
||||
# While A has not yet recorded UA on its row, B must be refused at cap 0
|
||||
assert id_order.wait(
|
||||
str(ws), "agy", "same-ws-reviewer-agy", proc_b.pid, uuid="",
|
||||
yaml_path=str(yaml_path), home=str(home), wait_s_val=0,
|
||||
) == 1
|
||||
|
||||
# Once A records UA on its row (via update_yaml_resumed.sh), B is released
|
||||
recorded_a = _row(
|
||||
"same-ws-creator-agy", "agy", ws, old_epoch + 50,
|
||||
pid=proc_a.pid, status="running", agy_conversation_id_own=UA,
|
||||
)
|
||||
yaml_path.write_text(yaml.safe_dump({"herdr_sessions": [recorded_a]}))
|
||||
assert id_order.wait(
|
||||
str(ws), "agy", "same-ws-reviewer-agy", proc_b.pid, uuid="",
|
||||
yaml_path=str(yaml_path), home=str(home), wait_s_val=0,
|
||||
) == 0
|
||||
finally:
|
||||
proc_a.kill()
|
||||
proc_b.kill()
|
||||
proc_a.wait()
|
||||
proc_b.wait()
|
||||
Reference in new issue
Block a user