Skip to content

ADR-066: Multiplayer mechanics extending ADR-033

Status: Accepted (retroactive — already shipped) Date: 2026-05-23 (decisions made Apr 27 – May 9; documented retroactively) Context: ADR-033 established the team primitive and team-level judgment layer. Several follow-on multiplayer mechanics were decided in conversation between Apr 27 and May 9 and shipped to production, but never formally documented. The conversation audit (docs/research/audits/conversation-decisions-audit.md, items 1, 2, 3, 5, 10) surfaced this gap. This ADR consolidates those decisions retroactively so future contributors aren't reading the code and asking "why does multiplayer work this way?" without a reference.

Decision

Five multiplayer mechanics extending ADR-033, all currently shipped:

  1. Multiplayer is invite-link-only. The public lobby surface (browse open multiplayer games) was removed. Multiplayer rounds are entered via shared invite code or link. Public discovery may return later with privacy controls.

  2. Team attribution to a round = the round-starter's team. When a multiplayer round begins, the team associated with that round is determined by the user who started it. If the starter belongs to multiple teams, they pick at round-creation time.

  3. Team context block on the team profile. Parallel to the per-user personal_context field, teams have a team-context document that the team owner can fill in. When present, this context conditions multiplayer scenario generation against the team's actual situation. Team-context scenarios are grey-locked behind "team profile filled in" — same pattern as personal scenarios behind personal_context.

  4. All multiplayer surfaces use the same "Create / Join with code" entry pattern as solo. Quick Round, Story, and Campaign multiplayer modes all follow the same UX shape for round entry. Cross-mode consistency is treated as a UX principle, not a per-mode design choice.

  5. "Stand / Change runner-up choice" UI is parity-matched to solo. ADR-021 simplified the post-discussion action surface; that simplification applies equally in multiplayer mode. The runner-up selection mechanic should look and behave the same regardless of mode.

Rationale

Why invite-only: "if you're playing a multiplayer game, you're trying to create trust with other people, but if you don't know who those people are every single time you play, then you're not going to be able to make predictions about them. There's no point of having a multiplayer game." (Apr 30 conversation.) Random-stranger multiplayer doesn't serve the trust-building thesis the multiplayer mode exists for. Public discovery is a future feature with different design constraints, not a v1 affordance.

Why round-starter's team: Avoids requiring all participants to agree on team attribution at round-creation time — friction-heavy. The starter already chose to start; let their choice carry. Multi-team users pick once at creation; everyone else inherits.

Why team context block: Personal context proved high-leverage for individual scenario quality. Team-level context is the natural extension when scenarios are generated for team-aware play. The grey-lock pattern mirrors personal scenarios — a working alternative to upfront onboarding friction.

Why cross-mode UX parity: The "Create / Join" pattern was already working in solo. Reinventing per-mode created cognitive load with no benefit. Consistency reduces support burden and makes the mode menu legible.

Why Stand/Change parity: ADR-021 was a simplification ADR. Re-introducing complexity in one mode would undo that work.

Alternatives Considered

  • Keep public multiplayer lobby: Rejected. Trust-building doesn't work with strangers; the surface produces low-value sessions.
  • Per-participant team-attribution vote: Rejected. Too much friction for a question that rarely matters.
  • Separate "team game" mode distinct from regular multiplayer: Rejected. Would have created mode proliferation; the team-context block achieves the same effect inside the existing mode.

Discussion

Most of these decisions were made quickly in the flow of building features rather than as standalone design conversations — which is exactly why they didn't get ADR'd at the time. The audit-driven re-documentation here is the corrective. ADR-033 was the strategic decision (teams as a primitive); these are the mechanical decisions that followed, individually small but collectively load-bearing for how multiplayer currently works.

The public-lobby removal in particular is worth flagging: it's a real product call (multiplayer = trust mode, not discovery mode) that has implications for growth and onboarding. Without this ADR, a future contributor might re-introduce the lobby as an "obvious" missing feature.

Consequences

  • The "trust-building thesis" of multiplayer is now load-bearing on invite distribution. If no one shares invites, multiplayer is invisible. Growth path: in-product invite affordances, team-formation flows, possibly campaign invitations.
  • Team context block creates a new surface that needs maintenance (validation, length limits, who-can-edit rules — see ADR-068 follow-up if extended).
  • Cross-mode UX parity becomes a maintenance principle: any new multiplayer surface must follow the Create/Join pattern, not invent its own.

Key files: - src/app/play/[sessionId]/page.tsx — multiplayer session entry, Stand/Change UI - src/app/solo/page.tsx — solo Create pattern that multiplayer matches - src/types/database.tsteams table (team primitive from ADR-033) - docs/research/audits/conversation-decisions-audit.md — source items 1, 2, 3, 5, 10