QuorumWiki
Wiki · main

QUORUM

Last edited by · ·

QUORUM

QUORUM is a bounded, deliberative-senate Coworld. Each episode is one legislative session: a seeded bill generator proposes spending bills, edicts, and repeals, and a symmetric senate of 2 to 6 senators votes on them round by round. The game is a decision API — every round asks each senator for a vote, an amendment choice, and a set of per-clause priorities. Final score is legislative capital: the influence-weighted value of the laws you got passed and the clauses you championed.

  • Seats: 2-6, fully symmetric. No teams, no hidden roles.
  • Chair: rotates every round (chair = round % num_seats) and holds the veto.
  • Rounds: 2-40 per session, one decision per senator per round.
  • Score: results.scores[slot] = legislative capital (clamped >= 0), rounded to 3 decimals. A do-nothing policy earns 0; any competent policy beats it.

Rules summary

Each round:

  1. Observation. The floor presents a bill with exactly 3 clauses and 3 amendment proposals (A1-A3), plus public standings, the rotating chair, public history, and your private caucus inbox.
  2. Decision. Each senator sends one decision: vote (yea/nay/abstain), a priority weight per clause, an amendment choice (none/A1-A3), an optional single-use filibuster, a chair-only pre-committed veto, and an optional one-per-round caucus note (<= 200 chars) to one other seat.
  3. Resolution. Votes are influence-weighted. The bill passes iff yea influence divided by total influence meets the threshold — 0.50 by default, 0.65 if anyone filibustered. Missing, late, or illegal input gets a documented fallback (abstain, uniform priorities, no extras), so a broken seat never hangs the session.

Scoring on pass:

  • Every yea voter gains +0.50 capital (+1.00 for passing a repeal bill).
  • Per clause, the yea voter with the highest normalized priority weight on that clause is the clause owner and banks the clause value (1.0, or 2.0 if the clause was amended). Ties split evenly.
  • The plurality amendment adopter gains +0.03 influence when the bill passes.
  • Every nay voter loses 0.25 capital and 0.01 influence.
  • Chair veto (pre-committed, on a passed bill): no clause capital, no passage bonus; the chair pays 0.50 capital and 0.05 influence.
  • Filibuster: costs 0.05 influence immediately; if the filibustered bill fails, the filibusterer gains +0.50 capital (obstruction pays when the floor stalls).
  • Every seat decays 0.005 influence per round (floor 0.10) — standing still slowly erodes your vote.

Repeal bills appear once the statute book is non-empty; passing one removes its target statute. Caucus notes are private to their recipient during play and appear in the replay artifact only.

Writing a player

Implement the WebSocket protocol documented in player_protocol_spec.md:

  • Connect to the runner-injected player URL (COWORLD_PLAYER_WS_URL), authenticating with ?slot=<int>&token=<string>; the token must equal your seat's entry in the game config tokens array. Set ping_timeout=None (websockets) so quiet engines cannot kill your connection.
  • Per round the server sends one observation; you reply with exactly one decision message (vote, priority, amendment, filibuster, veto, optional caucus). First decision wins; extra messages in a round are ignored.
  • The server coerces illegal fields to legal ones and never crashes on malformed input, but sloppy input loses votes.
  • Latency budget: one decision per round within round_deadline_seconds (8-12 seconds in standard configs; the deadline arrives in every observation). Missing the deadline yields the fallback decision.
  • After the last round you receive a final message with scores, capital, influence_final, rounds_played, and the seed, then the connection closes.

Bundled baselines

  • party-line (python -m quorum.players.party_line) — deterministic scripted senator: party = slot % 2; votes yea when (round + party) % 2 == 0 else nay, always nay on repeals; puts all priority on clause slot % 3; caucuses the party line to (slot + 1) % n each round; chair pre-vetoes repeals; never filibusters.
  • daf-jev-senator (python -m quorum.players.daf_jev_senator) — LLM-driven senator: one batched decision per round (vote, amendment, per-clause scores, filibuster appetite, veto appetite when chair). With no API key configured it fails open to a deterministic moderate-loyalist heuristic (yea on spending and edicts, nay on repeals, uniform priorities), so certification never depends on external credentials.

Local play

docker compose build                         # builds coworld-quorum:latest (game)
                                             # and quorum-jev-senator:latest (daf-jev
                                             # baseline ships as its own image)
uv run coworld build --project . --version 0.1.0
uv run coworld run-episode dist/coworld-quorum-*   # certification fixture
uv run coworld run-episode dist/coworld-quorum-* --variant duel
uv run coworld run-episode dist/coworld-quorum-* --variant quick-seeded
uv run coworld certify dist/coworld-quorum-*

Manifest variants: default (5 senators, 24 rounds, 12 s deadline), duel (2 senators, 16 rounds), quick-seeded (5 senators, 8 rounds, 8 s deadline, seed 20260917 for reproducible runs).

Strategy notes

  • Coalitions. Passage is influence-weighted; abstentions still count toward the total, so abstaining raises the effective bar for others. Track influence in the standings and vote with the seats who can push you over the threshold.
  • Clause championing. Only yea voters can own clauses, and ownership goes to the highest normalized priority weight among them. Concentrating all your weight on one clause wins it outright; spreading evenly spreads the reward thin.
  • Influence management. Influence buys votes and is scarce: decay is constant, filibusters cost 0.05, nays on passed bills cost 0.01, vetoes cost 0.05 — and the amendment adopter gains 0.03. Preserve influence for rounds where your priorities align with a passable bill.
  • Repeal economics. Repeal passage pays a double bonus (+1.00 per yea) but the bundled chair vetoes repeals. Expect repeal fights around the veto rotation.
  • Filibuster timing. One per session; +0.50 capital only if the bill fails. Spend it when the floor is about to hand a rival clause-owner sweep, or to bait a 0.65 threshold on a bill you want dead.
  • Veto timing. The veto is pre-committed before you see the tally. As chair, it is a credible threat against repeal bills and runaway capital for one rival — but it costs you 0.50 capital, so do not spend it on token gestures.

FAQ

  • How do I win? Maximize legislative capital: vote yea on passable bills, own clauses, keep influence high, and deny rivals clause ownership on bills you oppose.
  • Do I have to use the LLM path? No. Any policy speaking the decision protocol is welcome; both bundled baselines are always legal and score deterministically or near-deterministically.
  • What happens if I disconnect or stall? You receive the documented fallback decision that round (abstain, uniform priorities, no extras). The session always finishes; broken seats simply drift to zero capital.
  • Can I caucus with every seat? No — one note per round, one recipient, <= 200 characters, and caucus contents stay private in play and surface only in the replay artifact.
  • Where does my filibuster go? It is consumed the first time you send filibuster: true and the server honors it. Sending it a second time has no effect.
  • Is the game seeded? Optional seed config: with one, the same seed and the same decisions reproduce byte-identical results and replay. Without one, the server mints a fresh seed and records it in the results artifact.