diff --git a/tools/btconsole.py b/tools/btconsole.py index 0ee91bc..323b57f 100644 --- a/tools/btconsole.py +++ b/tools/btconsole.py @@ -414,6 +414,26 @@ class Relay: return sum(1 for c in self.console_conns if c.acked) def _check_launch_gate(self): + # BACK-TO-BACK MISSIONS (2026-07-18): a previous mission finished + # (launches_sent==2) and now all seats have RE-ACKED -- i.e. every pod + # exited, re-ran join.bat, and reconnected fresh. Reset the launch + # state so the relay (and the operator's LAUNCH button) re-arm for a + # new round -- no Stop/Start needed. The binary needs nothing: a + # rejoined pod is a brand-new process at WaitingForLaunch. (Only ever + # reached on a pod ACK, which never happens mid-mission.) + if self.launches_sent >= 2 and self._pods_ready() >= len(self.roster): + print("[relay] all seats rejoined after the last mission -- " + "re-arming for a NEW mission", flush=True) + self.launches_sent = 0 + self.stop_sent = False + self.stop_requested = False + self.mission_started_at = None + self.launch_at = None + self.launch_requested = False + self._launch_blocked_warned = False + self.eggs_done_at = None + # fall through -> the normal gate re-prints WAITING FOR OPERATOR + # GLOBAL launch: arm the timer when the LAST pod has ACKED its egg # (auto mode), or wait for the operator's 'launch' command (manual # mode -- the operator app's Launch button writes it to our stdin). @@ -522,6 +542,11 @@ class Relay: f"{len(self.console_conns)} pod(s)", flush=True) if self.launches_sent == 2: self.mission_started_at = time.time() + # CONSUME the launch: clear the timer + the request so the NEXT + # LAUNCH press is a fresh, deliberate new-mission request (else the + # back-to-back block would re-fire while this mission is running). + self.launch_at = None + self.launch_requested = False if self.mission_length > 0: print(f"[relay] mission clock: {self.mission_length:.0f}s " "(StopMission at expiry)", flush=True) diff --git a/tools/btoperator.py b/tools/btoperator.py index d4db344..6dfe97b 100644 --- a/tools/btoperator.py +++ b/tools/btoperator.py @@ -85,7 +85,12 @@ class SessionMonitor: self.eggs = int(m.group(1)) changed = True if self.RE_RELAY_READY.search(line): + # WAITING FOR OPERATOR = pods are ready to launch. Reset + # `launched` so the LAUNCH button re-enables -- this fires + # again for a NEW mission after the pods rejoin (back-to-back + # missions, 2026-07-18), not only the first time. self.ready = True + self.launched = False changed = True m = self.RE_RELAY_REG.search(line) if m: