Planning with beads: how Physical Soccer and Joystick Jammers get built

My loop for new projects is deliberately boring.
- Write the plan. A real document: what the thing is, who it is for, what “done” means, and how we will know.
- Turn it into beads. Every requirement becomes an issue in beads, stored in the repo next to the code, with real dependencies between them.
- Let the graph decide.
br readylists only the beads with no open blockers. That is the whole scheduler. - Run a herd. With herdr and ntm I keep a few agent panes open side by side, each claiming one ready bead, so the work fans out and the graph keeps it honest.
- Review, playtest, write the next beads. My job is steering and taste.
Two of my current projects show what that looks like, and they show two quite different shapes.
Physical Soccer: plan first, then let it flow
Physical Soccer is a party football game where anything can be a controller: phones, pads, keyboards, half a touchscreen. Before a single bead existed, it had a plan: plan.md, now on its fifteenth revision. Each revision closed real gaps. Revision 3 decided who owns the room state. By revision 4 the plan had a journey matrix and dependency cuts, and it said, in so many words, that it was “ready to convert into small, testable tasks”. The revisions kept coming anyway: revision 7 pinned the physics clock (the original game runs at 0.85x wall-clock, so the port carries an explicit time scale).
Then it was converted: a coverage index (plan-beads-map.md) maps every requirement to a bead ID, and every bead carries its own contract (what to build, which checks prove it, which evidence a parent bead needs from its children).
Physical Soccer: beads created vs closed, hour by hour
Physical Soccer: 194 beads, 451 blocking links, 24 layers deep
Why did this one flow so well?
- The plan did the arguing. Fifteen revisions of a document are cheap. Fifteen revisions of code are not. By the time beads existed, the hard decisions (who owns state, how reconnection works, what the relay is allowed to see) were already made.
- Every bead had a contract. “Done” meant named checks passed and evidence was recorded, so an agent could close a bead without asking me what I meant.
- Parents integrate, children prove. Small child beads close with targeted checks; the parent bead re-runs the whole thing. That stops “it works on my slice” from leaking upwards.
- Owner beads are explicit. The things only I can do (feel the controls on a real phone, judge whether it is fun) are beads too, assigned to me and fed by a reviewable build. They block exactly what they should and nothing more.
Joystick Jammers: an ongoing swarm
Joystick Jammers is a party racer and demolition derby: the TV is the arena, phones are the pads. It is in a different phase. The game works, and the job now is polish: player readability, controller latency and reconnect confidence, tutorial and onboarding, wheelies and stunt payoff. That kind of work is discovered by playing, not planned up front.
Joystick Jammers: beads created vs closed
Joystick Jammers: 207 beads, 313 blocking links, 10 layers deep
The coordination rules are written into the repo, so every agent reads them on start:
- Register with MCP Agent Mail under a name, check mail before claiming work and after every edit-and-test cycle.
- Reserve the files you are about to edit (specific paths, never the whole repo), and announce claims, blockers and completion in a thread named after the bead.
- Keep the swarm small: at most five ntm panes including mine, and reuse idle panes as worker, validator or release manager instead of adding agents.
- Use
br(beads in Rust), and ask the graph what matters withbv --robot-triageorbv --robot-next. - Close a bead only when the change is done, the relevant tests pass, and a completion note is posted.
- Do not sit idle waiting for consensus. If a ready bead is unclaimed and you can make progress, claim it, reserve, announce, start.
Deep vs wide
| Project | Beads | Blocking links | Longest chain | Closed | Shape |
|---|---|---|---|---|---|
| Physical Soccer | 194 | 451 | 24 | 64 | planned, deep |
| Joystick Jammers | 207 | 313 | 10 | 114 | polishing, wide |
| This site (previous version) | 99 | 117 | 7 | 85 | small, quick |
The longest chain is the number I watch now. A herd of agents makes a graph wide cheaply: more panes, more parallel beads. Only planning makes it shallow, by finding the dependencies early and cutting them where they are not real. Physical Soccer’s 24-deep chain is the honest critical path of a networked physics game with a relay, two hosts and owner playtests in the loop; Jammers’ 10 layers is what lets a five-pane swarm close two dozen beads a day.
The part that surprised me is how much the graph helps me. When something goes wrong, the fix is usually a better bead (clearer acceptance checks, a missing dependency), not a better prompt. I wrote about that shift in Your Prompts Do Not Matter (Anymore).