Merge-workspace review: round 1 (@518beda) claude agy grok PASS, codex NOT PASS (finalize wait measured on the wall clock); fixed in4c86107. Round 2 delta (@4c86107) claude agy grok PASS; codex (24b21b9c, after 817d1650 closed deadline_timeout with no report) found R1 closed and no new defect, but withheld PASS only because its sandbox could not bind the suite's loopback broker. The same two-file suite run here at4c86107: 278 passed. Full suite at518bedaon macOS / Python 3.9: 1711 passed / 1 failed / 38 skipped; the failure (test_issue45_restore, herdr 0.9.3 cwd restore) also fails on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
3.9 KiB
Review: PR #51 round 2 @ 4c86107
- Role: Reviewer (grok)
- Identity: loop
loop-20261007T155310Z-56d5a7, base518bedac5d8ab832347bfc6682b146f3201021f1, head4c86107846d1e037f9a69a1201257725e8673179, treee6f67f6136b8f0cec15ce98400ae7d7710cedf1e, one commit, clean snapshot - Scope:
git diff 518beda HEAD. Two files, +43/−3,git diff --checkclean. Main stayed7209750. - Verified read-only at
/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261007T155310Z-56d5a7/1. Python 3.9.6 from the pr-51 venv. InheritedHERDR_*,MAM_*, andMQTT_*were unset.HOMEandWORKSPACE_ROOTwere the basetemp..mam.envwas not exported.
Codex R1
| Codex | 4c86107 |
|---|---|
R1. _sleep measured the remaining time with time.time(). A wall clock stepped back during the broker re-observe (up to 3 s) or the disk-heartbeat grace (1 s) stretched that one wait by the same amount. A 10 s step back turned 1 s into 11 s and 3 s into 13 s. Bash sleep 1 / sleep "$left" does not follow the wall clock. |
_sleep (wrapper.py:145-156) sets end = time.monotonic() + seconds and computes left from time.monotonic(). The 0.5 s owner poll is min(left, 0.5) on that same remainder. test_u_a_wait_is_not_stretched_by_a_wall_clock_step_back steps the wall clock back 10 s on the first sleep for both 1 s and 3 s. |
Wall clock stays the deadline
The monotonic clock is used only inside _sleep (:150, :153). Everything that decides whether the job is finished still reads the wall clock:
_nowisint(time.time())(:45-46), the same value bash's$(date +%s)returns.finalize_beginbuildsdeadlineandevidence_untilfrom_now(:182-184).- The broker loop takes
left = deadline - _now()and only then calls_sleep(a, min(left, 3))(:208-211). After the sleep it labels the clock wall when_now() >= deadline(:218). - The grace loop's condition, the heartbeat reopen, and the idle-window check all use
_now(:226-240). The sleep inside that loop is_sleep(a, 1)(:239). recent_disk_heartbeatstill ages the events.log timestamp withtime.time()(:115).
A wall step back during one sleep no longer lengthens that sleep. The next loop pass still sees the stepped wall clock and can sleep again until START_TIME + TIMEOUT, which is what the old bash loop did after each fixed sleep. A wall step forward is noticed on the next _now() check, after the current monotonic slice returns. The owner poll does not become a deadline: it only splits the slice _sleep was given.
subprocess.run(..., timeout=10) on ps (:133-134) is unchanged and is not the job deadline.
The test
_SteppedClock (tests/test_issue17_item4_decisions.py:598-616) is the module's time. sleep(dt) adds dt to both clocks and to slept, and subtracts 10 s from the wall clock once. There is no real time.sleep and no thread. monkeypatch.setattr(decide, "time", clock) (:628) replaces the import time the wrapper calls (wrapper.py:35).
For 1 s the fake clock records two 0.5 s sleeps (slept == 1). For 3 s it records six (slept == 3). 0.5 is exact in binary floating point, so the result does not depend on the scheduler. The bound seconds <= slept <= seconds + 0.5 (:630) rejects the old 11 s / 13 s waits. watch_pid=None skips the process check. The same two durations are the ones finalize_end passes: min(left, 3) and 1.
Scope
The commit changes _sleep and adds this test. No label, registry write, event, or stall-watch decision moves. The notes left for a later change (the wrapper importing a package that loads paho, exit "" → 255, lib_int.sh using python3 on PATH, and the 0.2 s text versus the 0.5 s poll) are not in this diff.
Tests
--basetemp=/tmp/b78afollow.yeVKnK. tests/test_issue17_item4_decisions.py and tests/test_issue33_budget.py: 278 passed in 318.09 s, exit 0. Snapshot git status was empty after the run.
[VERDICT: PASS]