Skip to content

Transfer debounce and spectator listener#31

Merged
vladmesh merged 6 commits into
mainfrom
vladmesh/w3-debounce-spectator
Jul 10, 2026
Merged

Transfer debounce and spectator listener#31
vladmesh merged 6 commits into
mainfrom
vladmesh/w3-debounce-spectator

Conversation

@vladmesh

Copy link
Copy Markdown
Owner

Summary:

  • cherry-picked spectator listener, disconnect grace-period, spectator WS endpoint, and live observe feed from sprint/020-control-interfaces
  • adapted frontend live feed to current main without donor identity/role slices
  • closed session-disconnect-debounce in BACKLOG and added STATUS activity

Verification:

  • make check-backend
  • make check-frontend
  • docker compose test_websocket.py 3x, 29 passed each run

Notes:

  • added fileParallelism: false for Vitest because the full frontend suite had existing cross-file timing/isolation failures in parallel mode, while affected files passed independently and the serial full suite passed

vladmesh and others added 6 commits July 10, 2026 12:57
… feed)

SessionLiveFeed opens a dedicated spectator WsClient (?spectate=true) and
renders a read-only event feed in a new SessionView 'live' tab for DM/admin.
WsClient.connect gains a { playerId?, spectate? } options form. Broke the
latent wsClient<->gameStore import cycle (surfaced by importing WsClient from
a component): wsClient now reads identity via loadIdentity() from identitySlice
(type-only gameStore import) instead of useGameStore.getState().
…vict

The grace-period debounce deferred BOTH stop_round and eviction. Deferring
stop_round left a player-less round loop advancing NPC turns during the grace
window: for a real player a network blip silently costs combat turns, and
because every session draws from one process-global dice RNG, overlapping
orphaned rounds shifted the RNG nondeterministically.

That is what flaked test_player_state_xp::test_rest_status_updated_after_kill
in CI (1 failed / 159 passed): at the failure moment several arena/OA sessions
whose sockets had already closed were still ticking combat (visible as
consecutive_failures_end_turn in the backend log), draining the shared seeded
RNG so the combat_test player's attacks no longer killed the 1-HP dummy within
the message budget, and no xp_gained event was observed.

Fix: on the last player leaving, stop the round at once (restoring pre-PR
behavior) and defer only the registry eviction via the grace timer. A reconnect
inside the window cancels the eviction and restarts the round through the
player WS path's idempotent start_round. This is a code fix, not a test change:
the behavior (round advancing with nobody connected) was the regression.

Also: BACKLOG vitest-load-flakes -> [x] mitigated (fileParallelism:false, already
in this PR; note the proper long fix is per-file isolation, not whole-run
serialization).

Three consecutive make test-integration runs green (160 passed, ~11.5s each);
make check-backend green (2381 passed).
@vladmesh
vladmesh merged commit c94fb35 into main Jul 10, 2026
4 checks passed
@vladmesh
vladmesh deleted the vladmesh/w3-debounce-spectator branch July 10, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant