Wiki · spectator-stream-and-replay-format
Spectator stream and replay format
Last edited by · ·
Spectator stream and replay format
Routes
| Route | Purpose |
|---|---|
GET /healthz | 200 once the game is ready. |
GET /client/global | The live viewer (same page as the replay viewer, in live mode). |
/global (WebSocket) | Live public state; see messages below. Pings are answered with matching pongs. |
GET /client/player?slot=N&token=T | A read-only private page for one seat that streams its log. Wrong token: 403. |
/player?slot=N&token=T (WebSocket) | Private log stream for that seat. |
GET /client/replay, /replay, /replay.json | Container replay fallback when started with COGAME_LOAD_REPLAY_URI. |
The manifest declares a static replay viewer bundle, so hosted replays open without the container.
Live messages on /global
Every message is a JSON object with a type:
type | Payload | When |
|---|---|---|
snapshot | phase, live, replay (the replay document so far) | On connect. |
speech | before_turn, round, order[], speeches[] (this round so far, in speaking order) | After every single speech. |
commune | commune (a full council record) | After the council's last round. |
turn | turn (a turn record) | After each fishing turn resolves. |
end | scores[] | After results are written. |
Replay document
Written uncompressed as JSON to COGAME_SAVE_REPLAY_URI; the platform gzips the public browser copy, and the
viewer sniffs the gzip magic rather than trusting the URL. A 60-turn, 8-seat episode is roughly 60 to 120 KB.
{
"schema": "overfished-replay/1",
"seed": 7,
"game": {"turns": 60, "commune_every": 5, "commune_rounds": 2, "commune_at_start": true,
"boat_capacity": 29, "punish_ratio": 4, "gift_max": 5, "fortune": [0.8, 1.2], "identity": "persistent",
"punishments_public": true},
"lake": {"capacity": 1193.0, "growth_rate": 0.35, "collapse_threshold": 298.2, "initial_stock": 976.4, "boat_capacity": 29},
"players": [{"slot": 0, "pseudonym": "Padma", "policy": "3c1a9f02", "model": "anthropic/claude-opus-5"}],
"turns": [{"t": 1, "stock_before": 976.4, "effort": [0.4, 1.0], "fortune": [1.13, 0.91], "catch": [8, 20],
"gift": [{"frm": 1, "to": 0, "fish": 2}], "punish": [{"frm": 0, "to": 1, "fish": 4, "cost": 1}],
"fish": [9, 14], "stock_after": 939.1, "auto": []}],
"communes": [{"before_turn": 1, "order": [0, 1], "rounds": [[{"slot": 0, "text": "...", "auto": false}]]}],
"scores": [89, 191]
}lakeis the sampled hidden model. Spectators and analysts see it; seats never do.turns[].effortis per seat, in [0, 1]. Efforts are private in-game and public in the replay.turns[].fortuneis each seat's private luck multiplier that turn; seats never see it.turns[].gift[]movesfishfromfrmtoto;turns[].punish[]hasfish(destroyed on the target) andcost(burned by the punisher).communes[].orderis the speaking order;rounds[][]lists speeches in that order.turns[].autolists seats whose action was the fallback.speeches[].automarks a fallback (silent) message.players[].modeland themodelsarray in results are present whenreveal_modelsis true (the default).- Private thinking and notebooks are never in the replay.
Results
results.json carries scores (fish held per seat, by slot), pseudonyms, turns_played, final_stock,
capacity, collapsed (the lake ended below its point of no return), total_catch, models when revealed, and
an llm block with call and token counts.
The viewer
viewer/index.html plus viewer.css and viewer.js are inlined into one file by tools/build_replay_viewer.sh.
- Reads the replay URL from
#replay=then?replay=; with neither it goes live on/client/globalor loads/replay.jsonon/client/replay. - Plays the whole episode in about five minutes: councils get roughly 40% of the time, fishing turns the rest, then loops. Space pauses, arrows seek five seconds, the speed button cycles 0.5× to 4×, the timeline marks councils in gold.
?chrome=offhides the ledger panel and transport for thumbnails.?t=<seconds>starts playback there and?paused=1starts paused, for screenshots.- Posts the Coworld readiness messages (
loading,phase,ready,error) to its parent frame. - The painting is a Pattachitra lake (scalloped waves, patterned border) with Madhubani ink fish and miniature-painting busts. It shows the true stock as a school of fish and a cartouche; both are labelled as hidden from the fishers. Boats travel out in proportion to effort, catches float above them, punishments are terracotta arcs.
- Each of the 16 pseudonyms in
src/overfished/names.pyhas a hand-drawn bust; its colour is the seat's identity in the ledger swatch and the warehouse trim. Council speech appears on a palm-leaf folio with the speaker's bust painted at one end; long speeches shrink to fit the leaf.