2026 10 13 multiplayer to antigravity - xopherdeep/do-it-for-the-xp GitHub Wiki

Multiplayer handoff to Antigravity

Date: 2026-10-13. From: the Claude session that designed and started the build. To: Antigravity, working as @antigravity on the chemx boards.

What this is

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:

  1. Part 1, the shared base. Your job is to finish it.
  2. Part 2 (A), the party and body double.
  3. 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.md and its plan

Start every session with

  1. docs/current_context.md and docs/Roadmap.md (the Multiplayer section).
  2. The repo's CLAUDE.md: chemx commands, conventions, the one dev server.
  3. chemx team inbox @antigravity and chemx team status.
  4. chemx team task list --sprint=mp-base --all and --sprint=mp-next in do-it-for-the-xp, and the same in ../Xophz-COMPASS/wp-content/plugins/xophz-compass-xp for the server board.
  5. 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.

What to do, in order

# 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.

Per task

  • chemx team task claim <id> --as=@antigravity.
  • Before you edit a file, lock it: chemx team lock acquire <path> --as=@antigravity. Add --new for 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, then chemx team post the same message.
  • Releasing your locks after each commit keeps other sessions moving.

Watch for

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. Never git add ., git stash or plain git 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 test or jest.
  • Run chemx wait --verify-idle and chemx verify as two separate commands. Chained together, the wait sees its own command line and waits forever.
  • Run verify in 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 verify can fail on AST counts from other people's files (inline booleans, nested ternaries) and on tests/unit/rewardPresets.spec.ts, which isn't ours.
  • Then check that chemx typecheck is clean, that chemx test --related passes, and that your own files add no hazards. Record that on the task.

One dev server.

  • If curl -s localhost:8100 answers, 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 with localStorage["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. famparent must 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.

Push (the owner's instruction, 2026-10-13: finish the job, commit and push)

"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:

  1. git fetch origin.
  2. If you're behind, git merge --no-edit origin/<branch>. Never rebase, stash or force-push.
  3. 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.

  1. Plugin (xophz-compass-xp, branch main): git -C <plugin> push origin main.
  2. The plugin's pointer in the COMPASS superproject (/home/xopher/www/x/Xophz-COMPASS, branch main):
    • 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.
  3. Docs submodule (branch master): git -C docs push origin master.
  4. 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.
  5. App (do-it-for-the-xp, branch master): git push origin master.

What a push does:

  • App: a push to master runs CodeQL and deploy-pages.yml, which deploys to Cloudflare Pages (app.forthexp.com). Multiplayer stays hidden there because VUE_APP_MULTIPLAYER is unset in production. Anything outside the flag goes live, such as the Party tab fix #1334.
  • Plugin: a push to main only 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.

Rules that must stay true (spec, plus decisions made since)

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_events and __xp_hero_device never go into BACKUP_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 users map 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.

End every session with

  • Update docs/Roadmap.md (Multiplayer checkboxes) and docs/current_context.md.
  • Commit them in the docs submodule.
  • Post a chemx team post summary as @antigravity.
⚠️ **GitHub.com Fallback** ⚠️