Commit Graph

66 Commits

Author SHA1 Message Date
Josh Creek cd30098eca feat: add authenticated queue HTTP API 2026-08-31 21:13:10 +01:00
Josh Creek caa875f15c fix: fence concurrent queue mutations 2026-08-31 21:09:58 +01:00
Josh Creek bc7136b2cb feat: add ranked season window policy 2026-08-31 21:08:10 +01:00
Josh Creek e13a64756f feat: add authoritative rating outcome scoring 2026-08-31 21:07:04 +01:00
Josh Creek 63332435d2 feat: classify match integrity separately from delivery 2026-08-31 21:05:54 +01:00
Josh Creek 4e66c5758c docs: reflect current multiplayer implementation status 2026-08-31 21:04:58 +01:00
Josh Creek 723f8aea5d test: verify offline matchmaking pipeline 2026-08-31 21:04:22 +01:00
Josh Creek c0d1c33f54 feat: add executable multiplayer SLO checks 2026-08-31 21:02:29 +01:00
Josh Creek 3dde0ffb79 feat: add credential-safe multiplayer observability 2026-08-31 21:01:30 +01:00
Josh Creek 0364d3f172 test: add offline Steam and allocator fakes 2026-08-31 21:00:31 +01:00
Josh Creek 1902084523 test: add multiplayer control-plane fuzz targets 2026-08-31 20:59:29 +01:00
Josh Creek bbabd259b6 docs: complete multiplayer threat model 2026-08-31 20:58:11 +01:00
Josh Creek 217ae263cd feat: add rebuildable candidate cache 2026-08-31 20:56:13 +01:00
Josh Creek 3b5f50023b feat: enforce ranked admission policy 2026-08-31 20:55:11 +01:00
Josh Creek 518df3a73a fix: bind reconnects to verified Steam identity 2026-08-31 20:54:16 +01:00
Josh Creek 893db17c03 feat: add authenticated supervisor drain 2026-08-31 20:52:37 +01:00
Josh Creek 7ce28559d2 feat: add revisioned resync reducer 2026-08-31 20:51:46 +01:00
Josh Creek b1b4608dd8 docs: synchronize multiplayer progress checklist 2026-08-31 20:50:24 +01:00
Josh Creek e702661388 feat: add ticket and session policy 2026-08-31 20:49:45 +01:00
Josh Creek dfe8d46d99 feat: add casual bot backfill policy 2026-08-31 20:48:10 +01:00
Josh Creek 9c6d48ae2c feat: add initial connect no-show policy 2026-08-31 20:46:52 +01:00
Josh Creek 81e68bb5fa feat: add assignment readiness gate 2026-08-31 20:45:29 +01:00
Josh Creek 2b8bce5e4b feat: add deterministic allocation policy 2026-08-31 20:43:56 +01:00
Josh Creek 9810ee543f fix: propagate allocated transport ports 2026-08-31 20:42:19 +01:00
Josh Creek a0195987bd feat: add Agones readiness supervisor core 2026-08-31 20:40:51 +01:00
Josh Creek 698413cd91 feat: validate allocated assignment manifest 2026-08-31 20:38:56 +01:00
Josh Creek ecc78b7a2a feat: add result transaction SQL boundary 2026-08-31 20:37:49 +01:00
Josh Creek a616b7637e feat: add serializable matchmaking store boundary 2026-08-31 20:36:43 +01:00
Josh Creek 7c4b64b50a feat: add durable matchmaking metadata schema 2026-08-31 20:35:34 +01:00
Josh Creek 637b522486 test: harden result annotation reconciliation 2026-08-31 20:34:50 +01:00
Josh Creek 864e4e8aaf feat: add durable result policy core 2026-08-31 20:33:16 +01:00
Josh Creek b04f3318b9 feat: add ranked reconnect policy 2026-08-31 20:31:16 +01:00
Josh Creek cc2cd80a01 feat: add ranked season rollover policy 2026-08-31 20:29:11 +01:00
Josh Creek 1793eb7621 feat: add canonical matchmaking rating engine 2026-08-31 20:25:07 +01:00
Josh Creek 7643dbc439 feat: add matchmaking proposal policy 2026-08-31 20:23:17 +01:00
Josh Creek cf212d94f9 feat: validate matchmaking latency evidence 2026-08-31 20:21:55 +01:00
Josh Creek 997175c753 docs: track queue domain progress 2026-08-31 20:20:59 +01:00
Josh Creek b79d358db9 feat: add deterministic matchmaking team partitioning 2026-08-31 20:18:43 +01:00
Josh Creek 07fe144b2f feat: add deterministic matchmaking candidate selection 2026-08-31 20:17:53 +01:00
Josh Creek d864ce2475 feat: add allocated server compatibility config 2026-08-31 20:13:22 +01:00
Josh Creek 5b8638e15e feat: define matchmaking state transitions 2026-08-31 20:10:51 +01:00
Josh Creek af8592082e docs: define matchmaking launch SLOs 2026-08-31 20:07:41 +01:00
Josh Creek 835233672f fix multiplayer snapshot disconnect race 2026-08-31 20:05:40 +01:00
Josh Creek 8d4a0640e2 docs: finalize scalable matchmaking plan 2026-08-31 19:57:49 +01:00
Josh Creek bcc12aad19 docs(multiplayer-todo): add Phase 8 task breakdown for matchmaking and autoscaling
multiplayer-next.md carried the Phase 8 checklist but not the numbered
tasks with acceptance criteria that work actually gets picked up from.
That format lives in multiplayer-todo.md section 7, which already hosts
Phase 7 as in-progress, so Phase 8 goes there too.

Tasks 8.1-8.20 across four groups: backend service (identity, rating
store, Glicko-2, queue), server orchestration and autoscaling, playlists
and client UI, and keeping Docker/CI green. Section 0's short list gains
an index entry, and the status header now says Phase 8 is a 1.0 launch
blocker and the first phase to add a component outside the Godot
project.

Three entries are measured findings rather than plans, each of which
would break a naive implementation: stdout block-buffering making a
log-grep readiness probe hang forever, the hardcoded 7777/udp port
preventing more than one match per host, and compose.phase6-smoke.yml's
dependence on the exact behaviour allocation work would change.

Also fixes a now-false cross-reference: a Phase 4 note read 'not
Phase 8' meaning 'not a later phase', written when no Phase 8 existed.
CLAUDE.md's 'never add new work to multiplayer-todo.md' rule gains the
new-phase exception it always had in practice - Phase 7 was already
there.
2026-08-31 18:49:59 +01:00
Josh Creek 23c1c3d231 ci: add ENet integration coverage 2026-08-21 19:57:59 +01:00
Josh Creek 9e4609d5b3 docs(multiplayer): add concise next-work checklist 2026-08-21 18:56:02 +01:00
Josh Creek 6bafdc7794 feat(multiplayer): add Steam transport foundation 2026-08-21 18:52:07 +01:00
Josh Creek 624d1c6b78 docs(multiplayer): add a single index of outstanding work, and record the identity defect
The document had no one place that answered "what is left". Outstanding
items were spread across two phase-gate lines, two phase tables, §11, and
prose buried in the phase notes - and the name-keyed slot-reservation
hijack, which an adversarial review demonstrated with a real three-process
run, was not written down anywhere at all. It existed only in a
conversation.

New §0 indexes everything not done, in four groups: verification a
machine cannot do (the Phase 4 playtest, the Phase 5 3v3 gate), known
defects left unfixed with their severity, the one open architectural
question, and the two unstarted phases. Each row points at the detailed
write-up rather than duplicating it, and the phase gates now point back.

§11 gains the identity defect in full: reservations match on
slot.player_name and nothing else, with no uniqueness constraint on names
anywhere, so a peer joining during the 30s window with a departed
player's name is handed their slot, ship and team. A bespoke token would
be half of task 7.4 thrown away, so it stays deferred - with the
consequence stated plainly rather than implied, and listed as a
precondition of Phase 6's internet-facing gate.

Also refreshes the stale status paragraph and task 5.10 for the replay
log's reject recording, write-failure handling, close(), and dump tool.
2026-08-21 16:51:52 +01:00
Josh Creek ff725e1ffa feat(multiplayer): §6.3 late joiners take a vacated slot at the next kickoff
"Spectate now, take the slot at the next kickoff" was a print statement.
The server logged it and never acted; on the client, _is_spectator was
assigned once in _on_match_config_received and never revisited - and that
handler returns early whenever _slots is non-empty, so no rebroadcast
could promote an in-match spectator. The reconnect path only worked
because a returning player is a fresh process.

Server: late joiners are queued in arrival order and the queue is drained
from _begin_kickoff, before the reset transforms are read, so a promoted
player's ship is placed by that same kickoff and the controller swap
lands on an already-frozen body. A slot is available only once its player
has gone AND their 30s reservation has lapsed - §6.4 outranks §6.3, since
taking a reserved slot would quietly break the reconnect promise.
_abort_if_abandoned now counts a waiting spectator as somebody present,
or the one person queued for the slot that just opened is dumped to the
lobby at the moment they were about to get it.

Client: new broadcast slot_assigned (reliable, channel 0). Broadcast
because every client holds its own slot list and one naming the wrong
peer keeps flying somebody else's ship as a remote body; reliable because
no per-snapshot field would re-converge a client that missed it. The
promoted client undoes what made the body remote - fresh interpolator,
physics interpolation back on, offsets cleared - and deliberately does
not unfreeze, clearing _local_prediction_ready so the next snapshot
teleports it to a real authoritative pose first. The controller-attach
block moved to _take_local_ownership rather than being copied.

New --role=host-latejoin/--role=client-latejoin and
--slot-reservation-seconds=. Verified 4/4 both sides: queued, NOT
promoted merely because the reservation lapsed, takes the slot at the
kickoff, same ship instance, and both peers independently measure ~45.7m
under its input. Control with a 90s reservation: kickoff fires, nothing
is promoted, the slot still reads the departed player's name.
2026-08-21 16:47:35 +01:00