fix(issue-50, issue-55): onboarding and dispatch wait by the registry, one pane claim per server; tests stay out of the real agent homes #56

Merged
Godopu merged 17 commits from fix/issue-50-55 into main 2026-10-12 12:38:55 +00:00
Showing only changes of commit 320aa9f7a0 - Show all commits
+23 -10
View File
@@ -522,30 +522,44 @@ def _onboarding(box: Box, ack: int) -> str:
return a
def _restamp(box: Box, jid: str, created_at: str) -> None:
"""Give a record the test owns another created_at, atomically: a wrapper
scanning the registry must never find the file half-written (an unreadable
record is skipped, which would let it through)."""
rec = box.record(jid)
rec["created_at"] = created_at
tmp = box.jobs / f"{jid}.json.tmp"
tmp.write_text(json.dumps(rec))
os.replace(tmp, box.jobs / f"{jid}.json")
def test_c10_a_pending_onboarding_within_its_ack_budget_blocks_the_session_past_the_signal_window(box):
# review 5a09a13f F-A: the onboarding and the first job are registered in
# the same second (create registers, then injects; the job's wrapper
# registers a moment later), where the FIFO's (created_at, job_id) once
# let a lower id pass the injected onboarding; the second job comes a
# different second
while time.time() % 1 > 0.05:
time.sleep(0.005)
t0 = time.time()
# let a lower id pass the injected onboarding. The tie is made, not timed
# (reviews 98b31bb2 / 352066ec / 244b8072 F-B): once the first job's record
# exists, A takes its created_at - A has no signal and no admission, and the
# pane already holds its prompt, so nothing else depends on the stamp. The
# second job comes a different second.
a = box.register(ack_timeout_sec=180)
known = box.job_ids()
created = 0
for label in ("before", "after"):
if label == "after":
time.sleep(max(0.0, t0 + 31.5 - time.time())) # A is now older than the signal window
time.sleep(max(0.0, created + 31.5 - time.time())) # A is now older than the signal window
proc = box.submit(prompt="work " + label, MAM_DISPATCH_WAIT_S="3")
if label == "before":
prompt = box.herdr("agent", "prompt", SESSION, "Onboarding " + a)
assert prompt.returncode == 0, prompt.stdout + prompt.stderr
b = box.wait_new_job(known)
known.add(b)
print(label, "created", a, box.record(a)["created_at"], b, box.record(b)["created_at"],
"registered at +%.2fs" % (time.time() - t0))
if label == "before":
assert box.record(b)["created_at"] == box.record(a)["created_at"], "the same-second tie this exercises"
_restamp(box, a, box.record(b)["created_at"])
created = calendar.timegm(time.strptime(box.record(a)["created_at"], "%Y-%m-%dT%H:%M:%SZ"))
print(label, "created", a, box.record(a)["created_at"], b, box.record(b)["created_at"],
"at +%.2fs" % (time.time() - created))
assert (box.record(b)["created_at"] > box.record(a)["created_at"]) == (label == "after"), label
rc, out, err = box.finish(proc)
assert rc == 5, (label, out + err)
rec = box.record(b)
@@ -553,7 +567,6 @@ def test_c10_a_pending_onboarding_within_its_ack_budget_blocks_the_session_past_
assert a in err and "still has open jobs in the registry" in err and "stale open job" not in err, (label, err)
assert b not in box.pane_text(), label
assert box.record(a)["status"] == "pending" and "dispatch_wait_at" not in box.record(a), label
created = calendar.timegm(time.strptime(box.record(a)["created_at"], "%Y-%m-%dT%H:%M:%SZ"))
assert 31 <= time.time() - created < 180, "the second answer came past the window, within the budget"