diff --git a/README.md b/README.md index f2939ed..695d23e 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,9 @@ endless chain of blocked jobs: again it is a *new* session id and qualifies on its own, so an outage spanning several reset windows still gets retried. What the cap prevents is one conversation being resumed into several concurrent copies. A resume that fails -to launch at all records no attempt and is retried on the next tick. +to launch at all records no attempt and is retried on the next tick; one that +times out records an attempt, because the launch may have registered after the +watchdog stopped waiting for it. `--max-per-day` is the one guard that cannot be derived from anything else. A usage-limit block is self-pacing, because the stated reset time is respected — diff --git a/resume-stalled-sessions.py b/resume-stalled-sessions.py index ce2feda..454a407 100755 --- a/resume-stalled-sessions.py +++ b/resume-stalled-sessions.py @@ -307,6 +307,11 @@ def resume(job, claude_bin, prompt, dry_run): command + [prompt], capture_output=True, cwd=cwd, text=True, timeout=180, check=True, ) + except subprocess.TimeoutExpired: + # The launch may have registered before we gave up, and a second try + # would put two agents on one conversation. + log(f"{job['id']}: resume timed out, counting the attempt") + return True except (OSError, subprocess.SubprocessError) as err: log(f"{job['id']}: resume failed: {err}") return False