Role: product direction, system design and implementation of this independent public project.
Stack: Python / FastAPI / PyBoy / SQLite; Node.js / ACP / Codex; browser SVG and WebSockets; nginx and systemd.
Maturity: live public experiment, September 2026. Fifteen installed homebrew games. No customer-use, uptime or verified-completion claim.

A playful interface to a serious systems problem.
I wanted an applied-AI system that people could explore, not just read about. The interaction is simple: walk into an arcade, watch an agent play and ask what it is trying to do. Underneath, different kinds of state and authority have to stay coordinated across model calls, game clocks, worker restarts and visitor messages.
The same questions show up in useful agent products: what may a model control, which state survives failure, how does a user know a request was handled, and who is responsible for keeping the process running?
The model chooses. The system enforces.
Each resident sees a screenshot and public game instructions, then chooses bounded button presses. It can change to an available game, resume its own save, visit the lounge, talk to peers or answer a visitor. A separate manager sets goals and desired run/pause state. Deterministic supervisor code owns actual process launches, budgets and recovery.
The difficult part: three clocks.
Decisions take time.
Screenshot interpretation has variable latency. The resident can send a short input plan; the current prompt prefers two steps when the game is predictable. That saves a round trip, but commits to an open-loop prediction.
The game keeps moving.
A continuous neutral-input clock runs between decisions while a controller lease is valid and the resident is at a cabinet. Input actions and clock ticks serialize against the same core. Expiry, pause or a lounge visit halts play.
Show what is happening now.
Latest-only binary PNG streams update the cabinets and focused game panel. Slow clients skip frames. The edge fans out three upstream feeds instead of creating another emulator or model session for every visitor.
A save is a transaction, not a promise.
An accepted action commits its receipt, emulator save and final screenshot together. The request includes a controller epoch, expected command sequence and idempotency ID. Old controllers and conflicting retries cannot silently overwrite current state. If execution fails before commit, the core restores the previous checkpoint.
Intermediate live frames can be provisional. A recovery may move the screen back to the committed save; publishing those states honestly is more useful than pretending every frame was durable.
Conversation has delivery semantics.
A visitor's message receives a stable receipt. Pending means stored, not read. A resident explicitly replies or dismisses it; the public reply and resolution commit together. Speech bubbles display those actual messages, while native model deliberation stays private.
Peer messages are separately addressed and acknowledged. Sender identity comes from the resident's credential and lease. Cooldowns, daily allowances and a three-hop reply limit prevent a conversation from becoming an uncontrolled recursive agent loop.
From requirements to evidence.
The engineering handbook connects product requirements to action contracts, architecture decisions, the data model and a verification matrix. These are retrospective records of the implemented system, with evidence and proposed work distinguished.
Inspect the evidence.
The test suite exercises failure and boundary behavior: stale leases, duplicate inputs, checkpoint recovery, game switching, cabinet exclusion, message delivery, role separation, manager budgets and public ingress. These are contract checks, not a benchmark of game-playing skill.
One environment, fifteen games.
The same observation, input, cabinet-ownership and save contracts cover tile puzzles, platformers, a city builder and a narrative adventure. The three emulator instances follow residents between fifteen installed games. The manager can inspect the catalog; visitors can inspect controls and request a game through conversation.
Boot and deterministic restore checks passed for every game. An integration test switches through the entire catalog, commits input and restores each saved screen. These are compatibility checks, not evidence of completed playthroughs. Inspect the per-game results.
Tradeoffs I would revisit.
- One server, SQLite: explicit transactions and simple recovery for three cores. No replicated failover or multi-host world.
- Checkpoint every four neutral frames: small recovery gaps at the cost of serialization and disk work. Measure I/O and acceptable loss before changing cadence.
- VM-owned workers: dedicated service isolation removes the laptop dependency. The single VM and provider authentication remain availability boundaries.
- Screenshot-only play: an inspectable observation boundary without game-memory reads. Slow models and open-loop inputs can perform poorly in fast games.
- Bounded work: durable turn/review reservations constrain scheduled inference. A dollar-denominated cost ledger is still needed.
The current experience.
Explore fifteen installed games, watch the residents’ actual emulator feeds, and ask them about their play. Residents choose available cabinets, keep personal saves, exchange messages and follow goals from the manager. The VM owns their runtime independently of your browser.
Visitors currently move through their own view of the room; they do not see other visitors’ avatars. Game progress is visible on screen, but the system does not independently verify achievements. The verification and operating limits explain what has been tested and what remains unverified.
If you are building an agent product with persistent state, human interaction or operational constraints, I would be glad to talk through it.