From a8189243d7201f2cbad4dd175a7686262bcfd13d Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Wed, 28 Oct 2026 22:09:32 +0100 Subject: [PATCH] docs(openspec): propose follow-leader-to-lobby --- .../changes/follow-leader-to-lobby/design.md | 39 ++++++++++++++++++ .../follow-leader-to-lobby/proposal.md | 40 +++++++++++++++++++ .../specs/party-follow/spec.md | 40 +++++++++++++++++++ .../changes/follow-leader-to-lobby/tasks.md | 24 +++++++++++ 4 files changed, 143 insertions(+) create mode 100644 openspec/changes/follow-leader-to-lobby/design.md create mode 100644 openspec/changes/follow-leader-to-lobby/proposal.md create mode 100644 openspec/changes/follow-leader-to-lobby/specs/party-follow/spec.md create mode 100644 openspec/changes/follow-leader-to-lobby/tasks.md diff --git a/openspec/changes/follow-leader-to-lobby/design.md b/openspec/changes/follow-leader-to-lobby/design.md new file mode 100644 index 0000000..363ec8a --- /dev/null +++ b/openspec/changes/follow-leader-to-lobby/design.md @@ -0,0 +1,39 @@ +# Design + +## Context + +`FollowPolicy.shouldTriggerWarp` warps only when the leader connects to a non-lobby server; `FollowPolicy` then +moves local members who are in a lobby (mode `lobby`) or everyone (mode `always`). Velocity's `ServerConnectedEvent` +carries the previous server, so the proxy knows where the leader came from. + +## Decisions + +### 1. Rule: "were together, or idle in a lobby" + +On `party.warp` with target `T` and origin `F`, a local member `M` on server `S` (not the leader, `S ≠ T`) follows if +mode is `always`, or `S = F`, or `S` is a lobby. The rule needs no notion of "game" vs "lobby" for the target, so +lobby → lobby alignment falls out of it, and a member in another game is never pulled out. + +### 2. When the proxy asks for a warp + +Every `ServerConnectedEvent` of a party leader that has a previous server requests a warp to the new server with +`fromServer` = previous server. The first connection after login (no previous server) requests none. Members moved by +a warp are not leaders, so warps never cascade. `/party warp` sends no origin, so it keeps today's behaviour (members +in a lobby follow). + +### 3. API + +`WarpRequest` gains `fromServer` (optional, at most 64 characters); the service copies it into the `party.warp` +payload as `from`. Old plugins send no origin and ignore the field in events; a new plugin talking to an old service +gets events without `from` and falls back to the lobby rule. No version negotiation is needed. + +Rejected: tracking each member's "last server with the leader" in the service (more state, and the proxy already +sees the move); warping only when the leader returns to a lobby from a game (lobby → lobby alignment would still be +missing). + +## Risks / Trade-offs + +- A leader hopping between lobby instances drags lobby members along each time; that is the intent (the party stays + together) and costs one server switch per member. +- A member who just left the round on their own to another lobby instance is moved to the leader's lobby; acceptable, + since they are idle in a lobby. diff --git a/openspec/changes/follow-leader-to-lobby/proposal.md b/openspec/changes/follow-leader-to-lobby/proposal.md new file mode 100644 index 0000000..34897e0 --- /dev/null +++ b/openspec/changes/follow-leader-to-lobby/proposal.md @@ -0,0 +1,40 @@ +# Proposal + +**Ships as:** `feat(party)`: one code pull request `feat(party): bring the party back to the lobby with its leader`. + +## Why + +The first test on the team proxy showed the follow working one way only. When the leader went from `Lobby-2` to +`Bounce-1`, the member followed within a second. When the leader returned with `/lobby`, the member stayed in the +finished round and, after typing `/lobby` themselves, landed on `Lobby-1` while the leader was on `Lobby-2`. The +party falls apart exactly when players expect it to stay together: after a round, and in the lobby itself, where the +lobby's own server selection knows nothing about parties. + +## What Changes + +- **One follow rule for every move of the leader:** a member follows the leader to the new server if the member was + on the server the leader just left (they were together), or if the member is in a lobby. A member in another game + stays. This covers game → lobby (the round ends), lobby → game (as today) and lobby → other lobby instance. +- **The leader's lobby moves trigger a warp too** (today only moves to non-lobby servers do). +- **Warps name their origin:** `POST /v1/parties/{id}/warp` takes an optional `fromServer`; the `party.warp` event + carries it as `from`. The 0.2.0 plugin ignores it and keeps its old behaviour. +- Follow mode `always` is unchanged: every member follows every move. + +## Capabilities + +### New Capabilities +None. + +### Modified Capabilities +- `party-follow`: when a warp is requested and who follows. + +## Out of Scope + +- Party-aware lobby selection in Titan (sending the whole party to one lobby instance at login). The proxy aligns the + party after the leader's first move instead. +- Moving members out of a game they are playing in follow mode `lobby`. + +## Impact + +- Backend: warp request and event payload (`fromServer` / `from`), OpenAPI. +- Plugin: server-connected listener, `FollowPolicy`, event handler, tests. diff --git a/openspec/changes/follow-leader-to-lobby/specs/party-follow/spec.md b/openspec/changes/follow-leader-to-lobby/specs/party-follow/spec.md new file mode 100644 index 0000000..156c2f7 --- /dev/null +++ b/openspec/changes/follow-leader-to-lobby/specs/party-follow/spec.md @@ -0,0 +1,40 @@ +# Spec Delta + +## Purpose +The party follows its leader onto the same server. + +## MODIFIED Requirements + +### Requirement: Warp on leader move +When the proxy sees a party leader connect from one server to another, the proxy SHALL request a warp of the party to the new server's name and SHALL name the server the leader left as the warp's origin. + +#### Scenario: Leader joins a game from the lobby +- **GIVEN** A leads a party with B, both on `Lobby-1` +- **WHEN** A is connected to `Bounce-2` +- **THEN** B is connected to `Bounce-2` + +#### Scenario: Leader returns to the lobby +- **GIVEN** A leads a party with B, both on `Bounce-2` +- **WHEN** A is connected to `Lobby-2` +- **THEN** B is connected to `Lobby-2` + +#### Scenario: First server after login +- **WHEN** the leader logs in and is connected to `Lobby-1` +- **THEN** no warp is requested + +### Requirement: Who follows +When a proxy receives `party.warp`, it SHALL connect each of its local members except the leader who is not already on the target server to that exact server if follow mode is `always`, or if the member is on the warp's origin server, or if the member is on a lobby server. + +#### Scenario: Member in another game +- **GIVEN** follow mode `lobby` and member C is on `Tamias-1` +- **WHEN** the leader moves from `Bounce-2` to `Lobby-2` +- **THEN** C stays on `Tamias-1` + +#### Scenario: Other lobby instance +- **GIVEN** member B is on `Lobby-1` +- **WHEN** the leader moves from `Bounce-2` to `Lobby-2` +- **THEN** B is connected to `Lobby-2` + +#### Scenario: Target full +- **WHEN** a member's connection to the target is refused +- **THEN** the member stays where they are and is told why diff --git a/openspec/changes/follow-leader-to-lobby/tasks.md b/openspec/changes/follow-leader-to-lobby/tasks.md new file mode 100644 index 0000000..5d88d3d --- /dev/null +++ b/openspec/changes/follow-leader-to-lobby/tasks.md @@ -0,0 +1,24 @@ +# Tasks + +## 1. Backend + +- [ ] 1.1 `WarpRequest.fromServer` (optional, max 64); `PartyService.warp` puts it into the `party.warp` payload as + `from`; OpenAPI updated. +- [ ] 1.2 Tests: warp with and without origin. + +## 2. Plugin + +- [ ] 2.1 Server-connected listener: a leader's move with a previous server requests a warp with `fromServer`; no + warp without a previous server. +- [ ] 2.2 `FollowPolicy`: follow if mode `always`, member on the origin, or member on a lobby; skip the leader and + members already on the target. +- [ ] 2.3 Tests with fakes: game → lobby (co-player follows, member in another game stays, other lobby instance + aligns), lobby → game (as before), lobby → lobby, first login, event without `from`. + +## 3. Documentation + +- [ ] 3.1 README: the follow rule. + +## 4. Pull request + +- [ ] 4.1 Open the code pull request `feat(party): bring the party back to the lobby with its leader`.