Field notes · The same private repo, the week after the quality sprint · August 2026

Three products, one week

The quality sprint spent four days making the ground boring so the next stretch could build on it. This is that stretch, and it built in three directions at once: the platform grew a real SDK, a module registry, and an event spine; trivia — the game people can actually play — picked up pub rounds and a question catalog; and Battleship arrived as a server with no client, on purpose. The test suite ran from 312 to 463 to keep up, because moving faster kept finding spots where coverage was thinner than it looked — and each one got fixed the same week it surfaced.

3
tracks · platform, trivia, battleship
6
ADRs · 3 days
463
tests · was 312
32
PRs merged · Aug 10–12
2
game modules · 1 playable
1
new round style · pub recap

Set in Pizza's own design tokens, like every dispatch before it.

The week

Faster, on purpose

Monday didn't open with code. It opened with a question the repo had earned the right to ask out loud: should a party-game platform really be hand-rolling its own realtime stack, or just paying a managed service? A short retro walked the defect history since July, sorted it by layer, and came back with a clear answer — the realtime core isn't where the pain lives. The biggest single source of trouble was deploy plumbing a managed transport would never have touched, and the two pieces the project genuinely did reinvent — reconnect plumbing and wire validation — are by now sunk, hardened assets.

"This project is not re-inventing PubNub; it is building the part PubNub's customers still have to build after they pay."

the realtime retro, filed Monday morning — verdict: keep the stack, revisit at v0.3 (#156)

Decision recorded, follow-up parked, and by early afternoon the first platform ADR was up. That's the whole retro story this time — no incident, no all-nighter, just a build-or-buy question answered on the record so the week could spend its energy building. From Monday afternoon on, three tracks ran in parallel: the platform itself, the game already running on it, and the skeleton of the game that comes next.

Platform

An SDK, a registry, and fences that hold

The platform work arrived the way this repo likes to arrive: decisions first. Six ADRs in three days, each naming which earlier decision it extends, amends, or supersedes — no silent contradictions.

ADR-0015

A lint-enforced game SDK. src/sdk/ is now the only import surface between games and platform — a fence ESLint patrols in both directions.

ADR-0016

Config-driven round rules. The engine is mechanism, the game is policy: a GameDefinition says how rounds close, who participates, which phases run.

ADR-0017

Per-seat content. The secrecy boundary is server vs each client — contentFor renders a view per seat, because two fleets can't share a board.

ADR-0018

A module registry. Games are registered once at boot and selected per room; an unknown module refuses loudly rather than ever deleting a room.

ADR-0019

Deferred reveal. A reveal is now a predicate, not a boolean — a round can hold its answers and disclose them all at once as a recap.

ADR-0020

An event spine. One append-only telemetry stream behind a sink interface — JSONL today, SQLite later; games emit only through a namespaced emitter.

The theme running through all six is boundaries you can verify instead of boundaries you remember. Games could always only see the platform through interfaces; now the fence is mechanical — src/games/** can import only from the SDK, the platform can't reach into games, and ESLint fails the build on either trespass. The registry takes the stance the question pools took back in v0.1 — refuse, don't delete: a stored room whose module has left the registry gets a typed refusal and stays recoverable, because a rollback should restore your game, not discover it deleted. And the restructure that carried all of this — services, a reusable round runtime, the SDK barrels — landed as structure-only changes asserting zero behavior difference, which is a claim you can only make out loud with a test suite standing behind it.

The platform even absorbed the design system: theme.css moved out of trivia's directory into the shared client — a clean rename, 100% similarity — because tokens that style the game picker, the join shell, and whatever game mounts beneath them aren't trivia's property anymore. That game picker is real, too: the host's pre-game shell now selects a game per room, and the player's join shell mounts whichever module the room names.

Trivia

The game you can play got better

While the platform grew under it, trivia kept shipping like a product.

Pub rounds. ADR-0019's whole point. A pub-style round holds every reveal to the end and plays back one group recap at the round boundary — phones stay quiet mid-round, the results land all at once, and the room reacts together instead of one question at a time. Deferred reveal shipped as a predicate on the round rules, so it's configuration, not a fork of the engine — and the classic instant-reveal mode is exactly what it was before.

A question catalog. The question pools grew a runtime catalog — topics, labels, live counts — served by the platform and rendered in the host's pre-game shell. Question counts moved from free-text to a 1–10 dropdown, draws are randomized instead of first-N, and a count the pool can't satisfy is blocked in the form and refused by the server. The fence pattern again, one layer up.

Rooms with addresses. A room is now addressed by a stable id in the URL, so a reloaded host tab lands back in its own room, and a finished game gets an actual finished-game page instead of a dead lobby. Client-side room storage migrated to its third schema version in place — legacy entries upgrade on load and stay stable afterward.

Battleship

A server with no client (yet)

The second game module merged this week: Battleship — boards, volleys, last fleet standing — as a server module with its own wire-level integration tests and a README that is mostly a list of what it deliberately isn't yet. No ship placement, no client halves, no final-ranking polish; the client is filed as its own work (#163).

That sounds like half a feature, and it's the half that matters. Battleship exists to be the platform's second real consumer. It's why per-seat content is in the SDK at all — a trivia question goes to everyone, but a fleet grid goes only to its owner — and it's what turns the registry from a formality into a choice. The last dispatch put it plainly: you need ≥2 modules for a choice to mean anything. As of this week the host's pre-game screen lists both games — Battleship's card marked "coming soon," because the second option doesn't have a face yet.

QA

Speed shook the gaps loose

A restructure week is a stress test for a test suite, and the honest result is: the suite held, and it also grew by 151 tests — 312 to 463, 32 files to 44 — because moving faster kept exposing places where the coverage was thinner than the confidence.

The gates got wider, and hungrier. The review and verify gates now run on every PR, not only PRs targeting main — platform work happens on stacked branches, and stacked PRs skipping review was exactly the kind of quiet gap this process exists to close. The reviewer also outgrew its allowance again: the turn budget that went from 12 to 50 last dispatch went to 100 this week, for the boring reason that platform-sized PRs are bigger than feature-sized ones. And the reviews kept earning it — a mid-week multi-agent pass (find, then refute-by-default verify) over the pub-recap work caught a real reload gap in the recap window before it ever met a player, fixed in the same commit that swept the docs.

The receipts stay honest, just lighter this time:

Loose ends

Still on the bench

Matter-of-fact, tracked by number, in the series tradition:

Next

v0.3 calls in

Every dispatch in this series has ended one layer further out — the game, the pipeline, the process, and now the platform itself. The next layer is the fun one: v0.3 is where Claude calls in — an MCP server over the question pool, with a generate-and-verify content pipeline behind it, exactly where the case study's roadmap said it would be. The platform is finally shaped for a caller like that: registered games, typed rules, per-seat views, and an event spine to watch it all happen.

The week's scoreboard reads well. The platform can register a second game, hide a fleet from the seat next to it, and write down its own history as it goes. It still doesn't have a version number. Some weeks you cut the release; this one built the thing worth releasing.