Launch with whoever connects + live roster display in the console

The operator no longer has to match the roster row count to the exact
player count (or watch the "empty seats will STALL" warning).  Two
mechanisms:

1. PRESENCE BEACONS: the pod keeps its seat-request TCP connection open
   for the process lifetime; the relay reads a live beacon as "seated"
   and a pre-claim FIN frees the seat (no ghost seats -- a ghost stalls
   every pod at the connection gate).  Reservation expiry spares
   beaconed seats.

2. TRIM-ON-LAUNCH (manual/GUI mode): operator LAUNCH before the roster
   fills shrinks the session to the seats present -- egg [pilots]/pages
   trimmed, seat ids REMAPPED by position (pods re-derive their host id
   from their tag's roster position, so walk-up prefs and beacons re-key
   consistently), roster/expected_ids shrink, eggs release, the launch
   pair fires as ACKs land.

GUI: roster rows now update LIVE from the walk-up requests (SEAT n
PRESENT/FREED lines -> callsign/mech cells + a blue "seated" status
light), and LAUNCH MISSION enables from the first seated player with a
"starts with whoever is here" banner.

Verified 2-node: 2-of-4 trim ran the mission with the requested mechs;
and the mid-roster GAP case -- three joined, the middle player quit
pre-launch (beacon FIN freed the seat), trim remapped seat 4->3 with the
survivor's callsign/mech following, both survivors registered under the
remapped ids and ran the mission.  Also: stdin reader guarded against
sys.stdin=None spawn shapes (the GUI QProcess pipe is the supported
operator channel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-22 14:40:47 -05:00
co-authored by Claude Opus 4.8
parent 95735db5ae
commit 10eee05b20
4 changed files with 158 additions and 5 deletions
+18
View File
@@ -394,6 +394,24 @@ phase). Plan: `~/.claude/plans/partitioned-snuggling-piglet.md`.
name=VIPER/MONGOOSE, both pods launched with `[cyl] table 'thor'/'vulture'` live. The FE
menu->relaunch path itself: awaiting live human verification (env-injected path is what the
e2e run proves). BT_SELF pods skip the request (defaults).
- **LAUNCH WITH WHOEVER CONNECTS (2026-07-22) [T2]**: the operator no longer sizes the roster
to the exact player count. Mechanism: (1) **presence beacons** -- the pod KEEPS its
seat-request TCP connection open for the process lifetime (L4NET `s_seatBeacon`); a live
beacon = a seated player, its FIN before game-side claim FREES the seat (no ghost seats --
a ghost stalls every pod at the connection gate). Reservation expiry spares beaconed seats.
(2) **trim-on-launch** (manual/GUI mode): operator LAUNCH before the roster fills shrinks the
session to the present seats -- egg [pilots] + pages trimmed (`_relay_trimmed.egg`), seat ids
REMAP by position (a pod re-derives its host id from its TAG's position in the received egg,
so prefs/beacons re-key and every pod stays consistent), roster/expected_ids shrink, eggs
release, launch fires as the ACKs land. The GUI: roster rows show live walk-up
callsign/mech requests (SEAT n PRESENT/FREED lines -> table cells + a blue "seated" light),
and LAUNCH enables from the FIRST seated player. Operator flow: set ~8 default rows, let
players trickle in, launch whenever. VERIFIED 2-node: 2-of-4 trim -> mission ran with the
requested mechs; AND the mid-roster GAP case -- 3 joined, the MIDDLE one quit pre-launch
(beacon FIN freed the seat), trim remapped seat 4->3 (the survivor's prefs followed), both
survivors registered under remapped ids and ran the mission. Auto (CLI) mode keeps the
full-roster behavior. Caveat: `sys.stdin` is None under some spawn shapes (pyenv .bat shim
pipelines) -- the stdin reader guards it; the GUI's QProcess pipe is the supported channel.
- **PATIENT WALK-UP (2026-07-18) [T2]**: a pod dialed at a relay that isn't up yet no longer
aborts (release `Fail()` is a bare `abort()` = looked like a "crash", field report). Both the
seat request (`RelayRequestSeat`) and LAN discovery (`BT_RELAY=auto`) now RETRY (2s dials, 30