2026 10 13 multiplayer to antigravity - xopherdeep/do-it-for-the-xp GitHub Wiki
Date: 2026-10-13. From: the Claude session that designed and started the build. To: Antigravity, working as @antigravity on the chemx boards.
Do It For The XP is going multiplayer as a gamified virtual body double: Families and Parties, joined by QR code, heroes on their own phones. It comes in three parts:
- Part 1, the shared base. Your job is to finish it.
- Part 2 (A), the party and body double.
- Part 3 (B), Family Sync (XP Pro).
Parts 2 and 3 have no spec yet. The owner must approve each spec before any code is written.
- Spec:
docs/superpowers/specs/2026-10-13-multiplayer-shared-base-design.md - Plan, 20 tasks:
docs/superpowers/plans/2026-10-13-multiplayer-shared-base.md - Builds on the Town Hall bridge, which is done:
docs/superpowers/specs/2026-10-13-town-hall-wp-bridge-design.mdand its plan
-
docs/current_context.mdanddocs/Roadmap.md(the Multiplayer section). - The repo's
CLAUDE.md: chemx commands, conventions, the one dev server. -
chemx team inbox @antigravityandchemx team status. -
chemx team task list --sprint=mp-base --alland--sprint=mp-nextindo-it-for-the-xp, and the same in../Xophz-COMPASS/wp-content/plugins/xophz-compass-xpfor the server board. - For the task you take,
chemx team task show <id>. Its description and comments are the instructions. Then read the plan's Global Constraints, Review Focus and that task's section.
| # | Task | Board | Notes |
|---|---|---|---|
| 1 | REVIEW MP4–MP6 #6087 | xophz-compass-xp | Read the uncommitted diff in tests/rehearsal/family-smoke.sh first, from an interrupted reviewer; keep it or git checkout it. Then review, fixing test-first, and mark MP6 #6086 done. |
| 2 | MP12 #1305 | do-it-for-the-xp | Already in HEAD (eb36e484), with specs passing. Check it against plan Task 12, verify, fix, done. |
| 3 | MP13 #1306 | do-it-for-the-xp | Already in HEAD. Its spec is half-written: cover every plan Task 13 bullet. |
| 4 | MP14 #1307 → MP15 #1308, MP16 #1309, MP17 #1310 | do-it-for-the-xp | Kid phones. MP14 waits for MP12 (they share family.ts). |
| 5 | MP18 #1311, then REVIEW #1331 | do-it-for-the-xp | Rewards paid once, then the batch review of MP12 and MP18. |
| 6 | MP19 #1312, MP20 #1313, FINAL REVIEW #1332 | do-it-for-the-xp | MP20 needs #6087 done; set it queued then. |
| any time | Party tab #1334 | do-it-for-the-xp | Replace the mock data in MyParty.vue. It's independent of the flag and of family.ts. |
| later | Party tab #1335 | do-it-for-the-xp | After MP18. |
| owner | SPEC #1336 (part 2), SPEC #1337 (part 3) | do-it-for-the-xp | Brainstorm with the owner and get spec approval before any code. |
| owner only | #1338, #1339 | do-it-for-the-xp | Leave alone. |
Dependencies are enforced by chemx. Don't use --ignore-deps.
-
chemx team task claim <id> --as=@antigravity. - Before you edit a file, lock it:
chemx team lock acquire <path> --as=@antigravity. Add--newfor a file that doesn't exist yet. - Write the failing test first and see it fail. Comment
red: …on the task. - Implement until it passes. Comment
green: …. - Run the gates, commit, then comment
committed <sha>: <message>. - Finish with
chemx team task done <id> --as=@antigravity. - If you're stuck:
chemx team task update <id> blocked --reason "…" --as=@antigravity, thenchemx team postthe same message. - Releasing your locks after each commit keeps other sessions moving.
Other sessions share these repos right now.
- Lock every file before you edit it.
- Before committing a file, run
git diff <file>. If it shows changes you didn't write, don't commit that file: block the task and say why. - App repo: commit with
commit_paths. It's defined in the Town Hall plan's Global Constraints, and it uses a private index. Nevergit add .,git stashor plaingit commit. - Plugin repo:
git -C <plugin> commit -- <paths>. - Docs submodule:
git -C docs commit -- <paths>.
Sync commits. The owner runs periodic "feat: sync worktree …" commits that can sweep your uncommitted files into HEAD. If git diff HEAD -- <files> is empty, don't re-commit: record that commit's sha on the task.
Gates.
- Use chemx for every gate and read, never raw
pnpm testorjest. - Run
chemx wait --verify-idleandchemx verifyas two separate commands. Chained together, the wait sees its own command line and waits forever. - Run
verifyin the background. Under load it outlives tool timeouts; load averages have been running from 50 to 100.
The ratchet is red because of other sessions.
-
chemx verifycan fail on AST counts from other people's files (inline booleans, nested ternaries) and ontests/unit/rewardPresets.spec.ts, which isn't ours. - Then check that
chemx typecheckis clean, thatchemx test --relatedpasses, and that your own files add no hazards. Record that on the task.
One dev server.
- If
curl -s localhost:8100answers, use that server; never start another. - Cypress needs
--browser chrome, and the shared server can't be restarted with new build flags. Turn multiplayer on withlocalStorage["xp:multiplayer"] = "on"(development only).
The rehearsal network on :8090 is shared with the Town Hall work.
- The smoke script
tests/rehearsal/family-smoke.sh(in the plugin) touches only its own families and users, and its own "smoke" passwords. - Never reset the network or delete anything else.
famparentmust end a run with no family. - While the smoke runs, its 429 check also throttles claims from the Docker address.
Never change the live site (doit.forthexp.com, forthexp.com). Installing the plugin there is owner task #1339. Pushing is allowed: see Push below.
"Finish the job" means every part 1 task through FINAL REVIEW #1332, plus Party tab #1334 and #1335. The specs (#1336, #1337) still need the owner.
Push after each task's commit, once its gates pass. Never push your own red typecheck or failing specs. In every repo the routine is the same:
-
git fetch origin. - If you're behind,
git merge --no-edit origin/<branch>. Never rebase, stash or force-push. - Push.
If a merge conflicts, or would touch files that hold someone else's uncommitted edits, stop. Block the task and ask the owner.
Order: the plugin and docs first, then the pointers that reference them.
-
Plugin (xophz-compass-xp, branch
main):git -C <plugin> push origin main. -
The plugin's pointer in the COMPASS superproject (
/home/xopher/www/x/Xophz-COMPASS, branchmain):git -C /home/xopher/www/x/Xophz-COMPASS commit -m "chore: bump xp (multiplayer: <task>)" -- wp-content/plugins/xophz-compass-xp- Then push
origin main. This follows the earlier "chore: bump xp" commits. - A path-only commit leaves other sessions' staged work alone.
-
Docs submodule (branch
master):git -C docs push origin master. -
The docs pointer in the app:
git commit -m "docs: bump the docs submodule (<what>)" -- docs. This path-only commit is the one allowed exception to commit_paths, because commit_paths can't commit a submodule pointer. -
App (do-it-for-the-xp, branch
master):git push origin master.
What a push does:
-
App: a push to
masterruns CodeQL anddeploy-pages.yml, which deploys to Cloudflare Pages (app.forthexp.com). Multiplayer stays hidden there becauseVUE_APP_MULTIPLAYERis unset in production. Anything outside the flag goes live, such as the Party tab fix #1334. -
Plugin: a push to
mainonly runs the auto-version pipeline. Nothing is deployed. - After each push CI commits an "auto-bump version [skip ci]", so the next push needs a fetch and merge first.
Security
- A hero key acts only for its own hero.
- Only the server writes
reward.granted; rewards are XP and AP, never gold. - A hero key reads public events plus its own hero's family events, never a sibling's.
- Codes and keys are stored hashed. Codes are used once and expire after 10 minutes.
Privacy
- Public events never carry quest names or categories (parents type them), gold, notes, real names, birthdays or emails.
- Hero cards are: nickname, look, class, level,
updated_at. -
__xp_family_eventsand__xp_hero_devicenever go intoBACKUP_STORES.
Hidden in production. Everything sits behind VUE_APP_MULTIPLAYER, which stays unset in production until part 2 ships.
Exactly once
- One send at a time. Events stuck as sending are re-queued on start.
- A reward is paid once, through the quest log receipt
questId: "party:{event id}". - An empty
usersmap at startup never removes a hero.
Decisions already made. Don't revisit them.
| Topic | Decision |
|---|---|
| Hero registration | Heroes register with POST /heroes/{id} (the client has no PUT) |
| Client errors |
TownHallError carries siteCode and retryAfterSec
|
| A family ID owned by another account |
xp_family_taken (403) |
| No credentials | 401 rest_not_logged_in
|
| New error codes |
xp_family_busy 503 and xp_family_server 500 |
| Cleanup | Ages events by received_at
|
| Codes | Also accept Unicode dashes and the no-break space (the app's normalizeCode must match) |
| Event device IDs | 1 to 16 characters (the server writes server) |
| CORS | Allows X-XP-Hero-Key and exposes Retry-After, on family sites only |
| Kid phones | Managed from a card in Settings → Family, not from the profile form |
Business decisions (owner). XP Pro stays one per-family plan.
- Free: the chore loop, kid phones for party play, joining sessions, and hosting Quest Together 3 times a week.
- Pro: unlimited hosting, Family Sync, remote approvals, Fridge Mode, multi-GM, AI.
- The host pays; guests always join free.
- Update
docs/Roadmap.md(Multiplayer checkboxes) anddocs/current_context.md. - Commit them in the docs submodule.
- Post a
chemx team postsummary as@antigravity.