report: clear+re-pin the session id at launch (fixes un-watchdogged report runs)

Regression from the 2026-08-04 session-pinning work: lu._session_id() prefers the
pin file, but launch-report.py never cleared or re-established it. A surviving pin
from a PREVIOUS report run points at a session whose last message already carries
RECIPE REPORT COMPLETE, so the shared watchdog evaluates _completed()=True and
exits within one poll ('run completed — exiting'), leaving the CURRENT run
unwatched. Observed live: the 2026-08-07 finish-run's report step was watched by a
watchdog that quit after 3 minutes against an Aug-4 pin, then the report session
ended early with nothing to resume it.

start() now archives stale titles, clears the pin, snapshots existing ids, and
re-pins the new session after launch — the same contract launch-upgrader.start()
already follows. Scopes the shared helpers via UPGRADER_SESSION=<report session>.
This commit is contained in:
autonomic-bot
2026-08-10 15:41:48 +00:00
parent d441c6caaf
commit 242a6d9659
+21 -1
View File
@@ -73,14 +73,30 @@ def start(mode, date):
# Unique-name invariant (same as upgrader/supervisor): archive-rename every older session
# titled SESSION so the one this launch creates is the ONLY 'cc-ci-report' in the web UI.
# Archived names start with 'archive-' (operator convention 2026-08-04).
#
# AND clear the stale session PIN. The pin file is what the shared watchdog resolves via
# lu._session_id(); if a PREVIOUS run's pin survives, the watchdog inspects that old (already
# DONE_MARKER-bearing) session, declares "run completed" and exits within one poll — leaving
# the new run unwatched. That regression silently un-watchdogged the 2026-08-07 finish-run's
# report step (pin dated 2026-08-04). The pin is re-established after launch, below.
_lu = None
_prev_ids = set()
try:
os.environ["UPGRADER_SESSION"] = SESSION # scope the shared helpers to THIS session name
import importlib.util as _ilu
_spec = _ilu.spec_from_file_location(
"launch_upgrader", os.path.join(os.path.dirname(os.path.realpath(__file__)), "launch-upgrader.py"))
_lu = _ilu.module_from_spec(_spec); _spec.loader.exec_module(_lu)
_lu._archive_stale_titles(SESSION)
_rows = _lu._server_get("/session") or []
_rows = _rows if isinstance(_rows, list) else _rows.get("data", [])
_prev_ids = {s.get("id") for s in _rows}
try:
_lu.STATE_SID_FILE.unlink()
except OSError:
pass
except Exception as e:
log(f" (archive-rename skipped: {e})")
log(f" (archive-rename/pin-clear skipped: {e})")
kf = Path(LOG_DIR) / f".kickoff-{SESSION}.txt"
kf.write_text(build_kickoff(date))
@@ -102,6 +118,10 @@ def start(mode, date):
log(f"starting {SESSION} (backend={BACKEND}, tier={TIER}, model={MODEL}, date={date or 'today'})")
subprocess.run(["tmux", "new-session", "-d", "-s", SESSION, "-c", cwd, cmd])
subprocess.run(["tmux", "pipe-pane", "-o", "-t", SESSION, f"cat >> '{LOG_DIR}/{SESSION}.log'"])
if BACKEND == "opencode" and _lu is not None:
# Re-establish the pin on THIS run's session, so the watchdog (spawned below) resolves the
# new session rather than falling back to a title lookup or a stale pin.
_lu._pin_new_session(_prev_ids)
if BACKEND == "opencode":
if OPENCODE_SHARE:
log(f" attached to {OPENCODE_SERVER} → http://oc.commoninternet.net +public --share link")