Final HEAD263d6bf: claude, agy and grok PASS (delta review of the lifecycle-lock commits on top of theirab842f1PASS), codex PASS (its own round after F1/F2). Full suite at263d6bf: 906 passed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
6.1 KiB
Issue #18 — final follow-up review
Reviewed HEAD 263d6bf30d4681ef677d9917b136501b831ab584, base 139bdd4. Reviewed the complete new delta from 2b1d590 and the cumulative lifecycle delta from ab842f1, carrying forward the unchanged branch review from jobs 6ff39140 and d1eb9f50. The brief's introductory HEAD is stale; its supplied correction diff matches the actual follow-up commit. Working tree was clean at the initial and final source checks.
PASS. Both findings from the previous review are resolved. No remaining blocking finding was identified in the reviewed scope.
Closure evidence
F1: parent/child shutdown lock cycle — resolved
heartbeat.lifecycle_lock(blocking=False) now reports unavailable ownership without waiting. The exiting timer uses that mode and only reads/compares/removes the pidfile when it acquires ownership. A parent performing stop/replacement can retain the lifecycle lock while waiting for the child to exit; the child no longer needs that lock to finish. The parent removes the old pidfile while it still owns the lifecycle operation.
I independently repeated the prior reproduction with a real idle timer, interval 60, no in-flight heartbeat, and stop_timer(drain=2) in a temporary registry. Result:
idle_stop_seconds: 0.15
returncode: 0
The previous revision took 2.09 seconds and exited through SIGKILL (-9). The new regression also verifies an idle timer stops well before a ten-second drain budget without the failure-to-drain warning.
F2: untracked child after PID-file failure — resolved
After a successful spawn, failure while recording the PID now kills and waits for that exact Popen process before releasing lifecycle ownership. Cleanup removes an empty/partial pidfile attributable to that attempted owner and propagates the original exception. Failures before successful spawn do not write a PID, and the context manager releases the lock.
Independent checks injected ENOSPC at two boundaries: opening the PID file for writing, and writing after two PID digits had already been flushed. Both used actual owned subprocesses and temporary registries. Results:
open failure: child_returncode=-9, pidfile_exists=False, lock_reusable=True
partial-write fault: child_returncode=-9, pidfile_exists=False, lock_reusable=True
Lock reuse was verified with nonblocking flock acquisition. All owned processes were reaped and temporary resources removed. The added tests separately cover pre-spawn failure and post-spawn PID-file failure; both pass.
Lifecycle and cumulative consistency
- Concurrent starts remain serialized. The observe/drain/spawn/PID publication operation still holds the per-job lifecycle lock. The previous controlled concurrency check established that a second caller cannot enter the ownership body while the first holds it. The concurrent-start regression passes at this HEAD; nonblocking behavior is used only by exiting-timer cleanup.
- Lock ordering remains sound in the reviewed paths. Draining does not hold the registry/sequence lock, so admitted publishers can finish their registry work. Terminal
raise_barrierreleases the registry lock before acquiring lifecycle ownership for stop. The former child-exit dependency is removed. - Terminal ordering remains protected. Starts check terminal record/barrier status while owning the lifecycle operation. If the barrier appears after that check, terminal stop subsequently drains the published owner. Heartbeat admission checks the barrier under the sequence lock. The sequential replacement, in-flight terminal, concurrent-owner and post-barrier-start tests pass.
- PID cleanup preserves the current owner. When exit cleanup acquires ownership, it still compares the file contents with its own PID before unlinking. When ownership is busy, it does not touch that file. Spawn-failure cleanup runs before another compliant owner can publish its PID.
- Earlier accepted findings remain closed: R1 remote attempt rollback, R2 command-group timeout cleanup, R4 replayed-state liveness renewal, and B2 watched-agent death. Their focused regressions pass. The wrapper's protocol acknowledgement and disk-based liveness behavior, remote signature/attempt checks and registry transition boundary remain unchanged.
- Documentation and version: MESSAGING.md and VERSIONS.md now describe lifecycle serialization, nonblocking child cleanup and failed-spawn ownership cleanup. VERSIONS.md correctly counts 31 issue-18 tests. v4.5.0 lockstep remains intact; the public contract/remote additions justify the MINOR release. N/K/T defaults remain 30/4/180 with derived idle 120; documented wrapper grace can extend final closure beyond initial K×N silence detection.
Validation
PYTHONDONTWRITEBYTECODE=1 .venv/bin/python -m pytest -p no:cacheprovider \
tests/test_issue18_liveness_contract.py tests/test_version_consistency.py -q
34 passed in 114.18s; no skips
git diff 139bdd4...HEAD --check
passed
bash -n .agents/skills/lib.sh \
.agents/skills/multi-agent-mux-delegate-job/multi-agent-mux-delegate-job
passed
The 34 tests comprise 31 issue-18 cases and three version checks. Broker-dependent cases ran; one passing run does not establish network timing determinism. The concurrency regression itself uses concurrent threads without forcing the old interleaving; the previously controlled ownership check supplements that coverage. This round's independent checks specifically re-exercised graceful shutdown and both PID-file fault boundaries.
Acceptance 5 remains a single remote-job broker simulation plus runner-label unit coverage, not demonstrated full remote planner/creator/reviewer convergence. Legacy MAM_LOOP_PY=0 remote non-support remains documented. The creator-assigned phase1 suite and a full repository suite were not rerun or claimed as passing here.
No source edits, commits, pushes, issue changes, production monitor operations, real-home purges or direct production job-record edits were performed. Only this report and authorized lifecycle events were written in the workspace. No planner escalation is needed.
[VERDICT: PASS]