diff --git a/cc-ci-plan/launch-supervisor.py b/cc-ci-plan/launch-supervisor.py index 27efdaf..9d8072a 100644 --- a/cc-ci-plan/launch-supervisor.py +++ b/cc-ci-plan/launch-supervisor.py @@ -117,6 +117,19 @@ def _gate(): return False, sid, "weekly run COMPLETE (DONE marker present) — nothing to do" created = _session_created_ms(sid) age_h = (time.time() * 1000 - created) / 3.6e6 if created else 0.0 + # Belt-and-suspenders completion signal: the run wrote its weekly SUMMARY (Step 5 output) AFTER + # this session began. More reliable than the text marker — a run can finish the actual work + + # summary + report yet never print a clean sign-off (it may wedge afterwards, as on 2026-07-03). + # Without this the supervisor would try to "resume" an already-finished run every hour until the + # 96h window closes. + if created: + import glob + for f in glob.glob(os.path.join(WORKDIR, ".cc-ci-logs/upgrades/upgrade-all-*.md")): + try: + if os.path.getmtime(f) * 1000 > created: + return False, sid, f"weekly summary written ({os.path.basename(f)}) — run finished" + except OSError: + pass if created and age_h > WINDOW_HOURS: return False, sid, f"incomplete run is {age_h:.0f}h old (> {WINDOW_HOURS:.0f}h window) — not auto-resurrecting" # "Progressing" for an opencode run is NOT session_busy() (its pane regex is claude-tuned and