# memory — JANKENBOTS

Durable memory for this project. Read at session start, update before session end. Date format: `YYYY-MM-DD`. Deep design detail lives in `DESIGN.md` (the full record carried over from the idea's `plan.md`); this file is the distilled decisions + live work.

> **Location:** this project lives at **`/mnt/f/jankenbots/jankenbots`** (Windows `F:\jankenbots\jankenbots`) so the Unity Editor (Windows-only) and the git repo/docs share one folder. `~/claude/projects/jankenbots` is a **symlink** to it. Work from either path. **Name:** the game is **JANKENBOTS** (working title was JANKENSTEIN; the archived idea folder keeps the old name at `~/claude/archive/ideas/jankenstein/`).

## Decisions & rationale

- **Concept (locked).** ~25-player friendslop build-brawl: teams build a janky physics robot from themed scrap; **each teammate pilots one functional part** (pillar #6 — "you build your control scheme, not a robot"); death → free-roaming ragdoll **gremlin**. 8 design pillars in `DESIGN.md`.
- **Engine: Unity** (2026-07-10). Decided after a 3-angle netcode/prior-art study. The physics-party genre is overwhelmingly Unity (Fall Guys, Gang Beasts, Human Fall Flat, PEAK, Lethal Company, Party Animals, Stumble Guys, Trailmakers, Besiege, Robocraft); the two UE physics-heavy titles both swapped UE physics for Bullet. An earlier Unreal-MCP-tooling edge was correctly overridden. **The defining risk is networked physics at ~25-player scale — no shipped game occupies that quadrant.**
- **Control feel v0.1 — driving = symmetric** (2026-07-10). Each locomotion part = one pilot applying *literal force* ("you are the left tread") — the only model that generalises to arbitrary scrap contraptions and the one that keeps pillar #6. Tread pilot verbs: **snap-to-cruise throttle** (both slam forward = easy straight; coordination lives in the in-between), **lock-pivot** (called-play turns), **passive lean** (nobody idle). Asymmetric (throttle/steer split) held as the fallback if the prototype groans.
- **Weapons = three-body call-and-response** (2026-07-10). A weapon pilot perturbs the drivers' world → turn simultaneous chaos into rhythm: wind-up **telegraphs a brace**, a **braced bonus** makes drive+strike a combo, weapon doubles as engine/counterweight. Generalises to **5 archetypes** — Punch / Grinder / Grip (later tier) / Guard / Passive. The **weapon mix is a build-time chaos dial** (over-building self-punishes = pillar #6 made mechanical).
- **Team size & lobby math** (2026-07-10). Team **3–5** (3 = smallest full driver+driver+weapon triangle; 5 = coordination/budget ceiling); lobby **≥2 teams**; sweet spot 5 teams of 5. Unequal sizes balanced by a **flat build budget** (small team = concentrated & nimble; big team = distributed & tippy → equal power, different character), reinforced by physics (bigness = top-heavy, self-limiting) + coordination tax; matchmaking buckets pre-made friend groups & prefers equal sizes, NPC-fills the rest. **No living "roamer" — everyone is in the bot; off-bot = gremlins (dead) only.** Style vote needs ≥3 teams (2-team lobbies use fight-result + spectator vote).
- **Prototype netcode = Unity NGO + Relay, host-authoritative** (2026-07-10). Chosen for the *throwaway* first prototype (free, first-party, friends join by code, no port-forwarding). **This does NOT commit the final architecture** — server-authoritative state sync vs Photon Quantum deterministic lockstep is still deferred until the game is proven fun.

## Open questions / TODOs

- [ ] **▶ M1 BUILD COMPLETE — only the 2-human playtest remains** (see `docs/prototype-plan.md`). Done so far (2026-07-10, all compiling clean + pushed): **packages** (NGO 2.13.0 + `com.unity.services.multiplayer` 2.2.4 — the *unified* SDK that supersedes the deprecated standalone relay/lobby packages; pulls transport 6.5.0 + core/auth), **4 scripts** in `Assets/Scripts/{Net,Bot}/`, **scene** `Assets/Scenes/M1_Arena.unity` (NetworkManager+UnityTransport+NetworkBootstrap, ground/cam/light, set as build scene), **replicated Player capsule prefab** (`Assets/Prefabs/Player.prefab`, registered as `NetworkConfig.PlayerPrefab`).
  - **✅✅✅ SHOVE BALL + FOLLOW CAMERA BUILT & SMOKE-VERIFIED (2026-07-12) — M1 build is DONE.** Wired both into `M1_Arena` via MCP, solo-host smoke test passed (ball spawns + rests on ground + shoves under force; camera moves to bot+offset and frames it). Committed `b21f2d9`. **Shove ball** = in-scene `NetworkObject` sphere `ShoveBall` (1.5m, Rigidbody 10kg, linearDamping/angularDamping 0.5, Interpolate, Continuous) at world `(0,0.75,6)` (6m in front of the bot's +Z spawn facing, resting on the Plane at y=0); `SphereCollider` + `Assets/Physics/ShoveBall.physicsMaterial` (dyn/stat friction 0.4/0.5, bounce 0.3, Average combines); `NetworkRigidbody`+`NetworkTransform` → host-authoritative, exactly mirroring the Bot. **NO custom script** (passive prop; host PhysX + NetworkRigidbody replicate it for free — correct M1-minimal call). **Follow camera** = `Assets/Scripts/Camera/FollowCamera.cs` (plain client-local MonoBehaviour, NOT networked) on `Main Camera`, `target`=Bot chassis, `worldOffset (0,8,-12)`. Deliberately **position-follow-only** (fixed world offset + separately-slerped look-at, ignores the bot's roll/yaw) so the janky bot's spin/tip doesn't nauseate; escalation lever if it feels detached = follow bot YAW only. Auto-finds "Bot" by name if `target` empty. **Control-scheme note confirmed this session:** TreadPart v0.1 is **forward + steer only, NO reverse** (throttle W/↑ is forward-only per its own comment; turning = asymmetric throttle or lock-pivot; lean=anti-tip). **Unity 6 (6000.5.3f1) API gotchas hit:** `PhysicMaterial`→`PhysicsMaterial`, `PhysicMaterialCombine`→`PhysicsMaterialCombine`, Rigidbody `.drag`/`.angularDrag`→`.linearDamping`/`.angularDamping` (old names still readable but set the new ones). `NetworkBootstrap` is in the **global namespace** (no `Jankenbots.Prototype`), `HostGame()` is async `Task<string>`. **▶ ONLY M1 STEP LEFT = the real 2-human friends playtest over Relay** (this session's test was solo host + a scripted impulse as a ball-shove proxy). Then M2 = hammer.
  - **✅ GIT LFS ACTIVE FOR BINARY ASSETS (2026-07-12).** `git lfs install` done repo-wide; `.gitattributes` routes images/audio/video/models/fonts/native-libs (+ binary `.asset` exceptions: `LightingData.asset`, `*.cubemap`) through LFS, while Unity YAML **text** assets (`.unity/.prefab/.mat/.asset/.anim/.controller`) stay normal mergeable git text (do NOT LFS those). **Forgejo LFS works** — server has LFS enabled + locking support; `git lfs` auths via the **Basic** credential from `~/.git-credentials` (the REST `Authorization: token` scheme does NOT work for the LFS batch endpoint, but plain `git push`/lfs picks up Basic auth from the stored cred automatically — no extra setup). First real art landed: 4 Asset Store packs (**Floreswa** characters, **Junk Car Parts**, **Junkyard models**, **LB3D** lowpoly) = 159 LFS binaries (png/obj/fbx/jpg), pushed clean (commit `7ebc175`). **Workflow when importing more assets:** Package Manager ▸ My Assets ▸ **Download THEN Import** (Download alone doesn't put files in `Assets/`); then `git add Assets/` (add the whole dir so folder-sibling `.meta`s come along — `git add Assets/Pack` MISSES `Assets/Pack.meta`), verify with `git lfs ls-files`, push. **Perftest junk** (`Assets/Resources/PerformanceTestRun*.json` from the Performance Testing package) is gitignored — not source.
  - **✅ BUILD + FORGEJO-RELEASE PROCESS ESTABLISHED (2026-07-12).** Distribute playtest builds to friends as **Forgejo release assets** (Forgejo 11.0.15 at `git.rdx4.com`, repo has `has_actions:true` + runners, but we do NOT use CI — the local-MCP-build path is far faster, no Unity-license-in-CI hassle). **Process:** (1) build via MCP `manage_build action=build target=windows64|linux64 output_path=F:/jankenbots/builds/<plat>/JANKENBOTS.exe|.x86_64` → returns a `job_id`; poll `manage_build action=status job_id=…` until `result:succeeded` (a ~empty M1 scene builds in ~65s, ~105MB uncompressed; the exe appears on disk BEFORE status flips to succeeded — wait for the status, don't trust file presence). Build scene = `M1_Arena` (the only enabled build scene); default platform is StandaloneWindows64. (2) `zip` is NOT installed in WSL → archive with `python3 -c "import shutil; shutil.make_archive('NAME','zip',root_dir='.',base_dir='FOLDER')"` (win zip ≈40MB). Builds live in `F:/jankenbots/builds` (= `/mnt/f/jankenbots/builds`, OUTSIDE the repo — don't commit them). (3) **Forgejo release via API** with the token from `~/.git-credentials` (`sed -E 's#https?://[^:]+:([^@]+)@.*#\1#'`, 40-char token, user megaproxy): `POST /api/v1/repos/megaproxy/jankenbots/releases` (JSON `{tag_name,target_commitish=<sha>,name,body,prerelease:true}`) → capture `id`; then upload each asset `POST /releases/{id}/assets?name=FILE.zip -F attachment=@path`. **Release `m1-playtest-2026-07-12` (id 19)** now carries **ALL THREE** zips — Windows + macOS + Linux — https://git.rdx4.com/megaproxy/jankenbots/releases/tag/m1-playtest-2026-07-12 . Add more assets to the SAME release id rather than making a new one. **All standalone targets now installed & build clean (Win64/OSX/Linux64).** **Linux gotcha (RESOLVED):** needed **Linux Build Support (Mono)** installed in Unity Hub (Installs ▸ 6000.5.3f1 ▸ ⚙ Add modules → check the box AND click Install/Continue — checking alone doesn't download it) THEN a **full Editor restart**. Nasty trap: after a mid-session module drop, `BuildPipeline.IsBuildTargetSupported` falsely returns **True** (it re-scanned the modules folder) while the build pipeline still throws `UnityException: Build target 'StandaloneLinux64' not supported` and writes NO output — only a genuine restart loads the module into the running process. Verify a fresh Editor via a NEW `session_id` in `mcpforunity://instances`. **macOS gotcha:** unsigned `.app` → recipient bypasses Gatekeeper (right-click ▸ Open, or `xattr -dr com.apple.quarantine JANKENBOTS.app`); zipping from WSL over `/mnt/f` (mounts 777) preserves the Mach-O/x86_64 exec bit (linux binary also needs `chmod +x` on the recipient side, noted in release body). Restarting the Editor DROPS MCP — reconnect via `/mcp` and re-`set_active_instance` (hash stable across restarts: `jankenbots@47f7b88ac88d97d3`). **Background publish pattern that worked (2026-07-12):** fire `manage_build`, then a detached Bash watcher script that polls the output dir for a stable size, zips via `shutil.make_archive`, and uploads to the release via the Forgejo API — lets the build run without blocking (Unity build blocks the Editor main thread, so MCP scene edits must wait until it finishes anyway; use that window for filesystem-only agent work).
  - **✅ CAPSULE REPLICATION VERIFIED (2026-07-11) — M1 netcode thesis proven.** Two clients over Relay (host = original editor via MCP, client = ParrelSync clone), both capsules spawned + drove independently + replicated **bidirectionally, smooth**. The `input→ServerRpc→host-physics→NetworkTransform` loop works over real Relay. **ParrelSync 1.5.2** installed for local 2-client testing (clone at `../jankenbots_clone_0`, symlinks Assets+ProjectSettings; open it via `ClonesManager.OpenProject` or the ParrelSync menu; its MCP loses the port fight so only the original is MCP-controllable).
  - **✅✅ TWO-TREAD BOT DRIVES — M1 CORE THESIS VALIDATED (2026-07-11).** Two clients over Relay, each piloting one tread of the shared bot; coordinating both to drive straight **"feels good"** (user's words). First attempt the bot was too hot + top-heavy and launched off on a nudge → tuned to stable: cruiseForce 450, linearDamping 1.5, angularDamping 6, maxAngularVelocity 3, **centerOfMass (0,-0.6,0)** (serialized override, implicitCom=false → persists). These are baked into the scene Bot. **Gotchas found:** (1) the step-2 `PlayerPrefab` capsule still auto-spawns per client and PlayerDriver ALSO reads WASD → despawn capsules (or clear PlayerPrefab) for a clean bot test — in the real game players are seats, not free capsules; (2) each re-host mints a NEW Relay join code (old ones die) — stale codes were the cause of a failed join; (3) recompiling scripts mid-session forces the ParrelSync clone to recompile → don't Join during compile. Remaining M1: shove ball + follow camera (step 5-6), then the REAL verdict = a live 2-human friends playtest (the auto-drive was a solo proxy).
  - **✅ SHARED BOT BUILT (2026-07-11), solo-smoke-verified; awaiting 2-pilot drive test.** In-scene `Bot` NetworkObject in M1_Arena: chassis Cube (Rigidbody 60kg + NetworkObject + NetworkTransform + NetworkRigidbody + SeatManager) with two child treads `Tread_L`/`Tread_R` (TreadPart, side Left/Right) at world ±1.2 X. In-scene bot auto-spawns on host; seat claim + gating verified solo. **DESIGN FIX (important):** the two drafts were mis-wired — TreadPart gated on NetworkObject `IsOwner` (needs per-tread ownership → impossible, NGO forbids nested NetworkObjects in a spawned prefab) while SeatManager's `OwnsSeat/PilotOf` API sat unused. Rewrote TreadPart to **seat-based gating**: both treads share the chassis NetworkObject; a client drives the tread whose seat it holds (`PilotOf(side)==LocalClientId`), host re-validates `OwnsSeat` on the RequireOwnership=false RPC. Also swapped TreadPart to `Keyboard.current` (New-only input). Controls: **W/↑ throttle · Shift pivot · A/D lean**. Moved SeatManager OnGUI below the bootstrap panel (was overlapping).
  - **✅ UGS GATE CLEARED + HOST PATH VERIFIED (2026-07-10).** Cloud project **jankenbots** (`cloudProjectId a0d222ae-c79b-4120-bc0d-947bfd7600cb`, org `megaproxy`) is linked (has been in ProjectSettings since project creation) AND **Relay is now activated in the dashboard** (the missing step — done via cloud.unity.com ▸ Development ▸ Products ▸ Relay; there is NO enable toggle, opening the product page activates it). Verified by an in-editor Play-mode smoke test: `UnityServices.State=Initialized`, anonymous auth signed in, `HostGame()` created a real Relay allocation + join code, host's Player capsule auto-spawned (`IsSpawned`, owner=0). **The host half of M1-step-2 works end-to-end.** Still unverified: a *remote client joining* + peer-to-peer replication (needs a 2nd instance — standalone build via `manage_build` or a ParrelSync clone).
  - **Next build steps:** (5) shared bot = chassis Rigidbody + 2 `TreadPart` treads + `SeatManager` (⚠ `TreadPart` still reads legacy `Input.GetAxis` — swap to `Keyboard.current` like PlayerDriver was, project is Input-System-**New-only**); (6) shove ball + follow cam; (7) 2-friends feel test over Relay (needs a standalone build via `manage_build` or a ParrelSync clone for the 2nd client).
  - **Verified Relay API gotcha (baked into NetworkBootstrap):** with the unified SDK, `new RelayServerData(allocation, "dtls")` does NOT exist — use `AllocationUtils.ToRelayServerData(allocation, "dtls")` (`AllocationUtils` is in `Unity.Services.Relay.Models`). Corrected via live editor reflection.
- [x] **Project location decided + unified** — `F:\jankenbots\jankenbots` (git + Unity + docs together), symlinked `~/claude/projects/jankenbots`. Unity `.gitignore`/`.gitattributes` in place.
- [x] **Unity project created** — fresh URP + Input System template (`Assets/`, `SampleScene`, `InputSystem_Actions`). Still to add: NGO + Relay + Lobby packages (part of M1 above).
- [x] **Unity MCP working** — CoplayDev server on `127.0.0.1:8067`, portproxy `8068→8067`, `.mcp.json` → `172.27.208.1:8068/mcp`; handshake verified (v3.4.4). **Tools only load when Claude is started from this project folder** with Unity open + server running.
- [ ] **Netcode architecture (deferred, the real risk)** — dedicated server-authoritative state sync (Robocraft 2 blueprint) vs Photon Quantum lockstep (Stumble Guys precedent). Decide *after* the fun is proven + the 25-player physics spike. Netcode target ≈ 25–30 primary rigid bodies + gremlins/debris.
- [ ] **The 25-player physics/netcode spike** — two ~30-joint bots colliding at arena scale, ≥100 ms latency, min-spec. The make-or-break gate before scaling up.
- [ ] Remaining **design** questions (detail in `DESIGN.md`): build-coupling tightness, hidden per-player agenda, at-scale voting, part taxonomy, scavenge-contest rules, art style, progression (cosmetic-only), final name (working title JANKENSTEIN; alts BODGEBOTS / SCRAPYARD SCRUM / CLANKERS / RUSTBUCKETS / JALOPY WARS).

## Session log

### 2026-07-12 (session 5 — arena pass: bigger arena + container walls + rigged player avatar)
- **Built out the arena + the first player character.** (1) **Arena → 150×150m** (Ground scale 15, dirt re-tiled to 24× to hold ~6m/tile). (2) **Walls** = `ArenaWalls` (4 invisible BoxCollider physics walls, 4m tall, sealed corners, half-extent 75) + `Junkyard_Walls` (96 cargo containers, 24/side @ 6.25m pitch, from `Assets/Junkyard models/Models/Cargo/Cargo*.obj`, purely decorative — physics is the invisible walls). (3) **Rigged player avatar** — new pack `Hodaart Low Poly Character Collection 3` (humanoid-rigged, Mixamo skeleton, ships Idle/Walk/Run clips + URP mats). `Assets/Prefabs/PlayerCharacter.prefab` = Character 01 + CharacterController + NetworkObject + `OwnerAuthNetworkTransform` + `PlayerAvatar`, Animator w/ humanoid avatar + `PlayerLocomotion.controller` (Idle/Walk/Run 1D blend tree on `Speed`). Registered as `NetworkConfig.PlayerPrefab` (auto-spawn ON again). **Verified in play:** spawns, visible, poses in Idle (rig animates), owner-auth. All committed (`beb17ea`), Hodaart in LFS.
- **DESIGN CONTEXT (from user):** full-game loop = players are these rigged characters; they **run around a timed junkyard gathering scrap to build the bot**, then **drive from player stands** we'll build around the arena. So the avatar (run-around) and the tread controls are SEPARATE systems. ⚠️ **Known tension:** `PlayerAvatar` and `TreadPart` both read WASD — fine now (test avatar without claiming a seat), but the player-stand flow must gate one vs the other. Also: PlayerPrefab is `PlayerCharacter` again, so for a clean **bot-only** test you'd re-clear PlayerPrefab (avatar + tread double-drive on WASD otherwise).
- **KEY MCP GOTCHAS (cost real time this session — heed them):**
  - **`execute_code` (CodeDom) references only the LAST SUCCESSFULLY COMPILED `Assembly-CSharp`.** New script types are INVISIBLE to execute_code until the scripts compile **clean** AND the domain reloads. If a script has ANY compile error, Unity keeps the old assembly and execute_code silently can't see your new types (error: "type ... does not exist in namespace"). Workflow: write script → `refresh_unity(force, wait_for_ready)` → **`read_console` for errors** → confirm via reflection probe (`System.Type.GetType("NS.Type, Assembly-CSharp")`) before referencing the type in execute_code. Existing game types (e.g. `Jankenbots.Prototype.SeatManager`) DO resolve in execute_code, so it's not a general limitation — it's the fresh-compile timing.
  - **`[DisallowMultipleComponent]` is in `UnityEngine`, not `Unity.Netcode`.** (That typo failed the whole Assembly-CSharp compile → new types vanished → see above.)
  - **Prefab editing: use `PrefabUtility.LoadPrefabContents(path)` → mutate → `SaveAsPrefabAsset(root, path)` → `UnloadPrefabContents`.** The `InstantiatePrefab`+unpack+`SaveAsPrefabAsset(instance)` path DROPPED the components I'd added to the instance root — LoadPrefabContents is the reliable editor for an existing prefab asset.
  - **Owner-authoritative NetworkTransform** = subclass `NetworkTransform` and `protected override bool OnIsServerAuthoritative() => false;` (right for player avatars; the bot/ball stay server-auth default).
  - **`HostGame()` races the async sign-in on Start** — calling it too early throws "player is already signing in". Poll `AuthenticationService.Instance.IsSignedIn` (or just retry) before hosting in a fresh play session.
- **▶ RESUME:** arena + avatar are in. Still owed / next: build **player stands** around the arena (drive-from-stand flow that gates avatar-vs-tread input), swap the grey bot chassis/treads + shove ball for scrap models, and the real 2-human playtest. Screenshots this session confirmed the look (container ring + dirt + character all cohesive).

### 2026-07-12 (session 4 — M1 build finished: shove ball + follow camera)
- **▶ RESUME HERE next session:** the entire M1 build is done (bot drives, shove ball, follow camera — all in `M1_Arena`, all smoke-verified). **The ONE thing left in M1 is the real 2-human friends playtest over Relay** — flip off any `debugAutoDriveFull`, don't rely on scripted proxies, get two actual people each on one tread pushing the ball around. That playtest is the true fun verdict. After it → **M2 = add a hammer** (first weapon). See the "SHOVE BALL + FOLLOW CAMERA" ✅✅✅ block above for every value/gotcha.
- Fanned out two Sonnet subagents (camera-script author + ball-networking designer) while MCP was down, then wired both into the scene via MCP once the editor came back. Ball needs no script; camera is `FollowCamera.cs`. Confirmed the control scheme is **forward + steer, no reverse**. 2 commits pushed (`87f929b` camera script, `b21f2d9` scene+ball+material). Unity-6 physics API renames noted in the block above.

### 2026-07-11 (session 3 — M1 bot drives, thesis validated)
- **▶ RESUME HERE next session:** M1 core is proven (two-tread bot drives over Relay, feels good). **Remaining M1:** (1) build the **shove ball** (big physics sphere) + a **follow camera** framing the bot — makes coordination purposeful; (2) run the **real 2-human friends playtest** (this session used a host-side `debugAutoDriveFull` auto-drive as a solo proxy — flip it off / don't rely on it with real players); then **M2 = add a hammer**. To bot-test cleanly: despawn the player capsules or clear `NetworkConfig.PlayerPrefab` (they double-drive on WASD), and remember each re-host = a NEW Relay code.
- Built the whole M1 bot this session via MCP + ParrelSync 2-client testing; tuned physics live after it launched off; validated it drives straight with two pilots. All committed + pushed (see the M1-progress TODO block above for the full state, gotchas, and verified API/tuning values). ParrelSync clone editor can be closed between sessions; reopen via ClonesManager when needed.

### 2026-07-10 (session 2 — M1 build start)
- **Started Milestone 1 via a research/draft workflow + serial in-editor build.** Ran a 9-agent workflow (verified NGO/Relay API research → adversarial verify → draft 4 scripts → integration plan); the verify agent installed the packages to reflect against the *live* editor, catching two hallucinated Relay APIs before any code hit the project. Then serially, all main-loop MCP work (packages/scene/prefabs are stateful/single-editor → NOT parallelized): dropped scripts (compile clean, 0 errors), built `M1_Arena` scene + NetworkManager, made the replicated Player capsule prefab, fixed PlayerDriver input for New-only Input System. 4 commits pushed. **Stopped at the UGS-link gate** (see TODO) — nothing is runtime-testable until that's linked.
- **Runtime host smoke-test (solo, no 2nd client):** enter Play via `manage_editor play`, then `execute_code` to call `nb.HostGame()` and poll `read_console` — saw QosJob region pings + `Hosting with join code XXXXXX`. Note: the `editor/state` resource's background tick FREEZES (goes stale) during playmode transitions, but direct `execute_code`/`read_console` commands still work — probe with those, don't trust the stale state snapshot.
- **MCP resource URI correction:** editor state is `mcpforunity://editor/state` (not `/editor_state`); project info `mcpforunity://project/info`. `find_gameobjects` wildcard `*` returns nothing — search by name/component/path. `execute_code` uses CodeDom (C# 6) by default → fully-qualify `UnityEngine.Object`, no C#12 syntax.

### 2026-07-10 (session 1 — promotion + setup)
- **Promoted from `ideas/jankenstein` to a real project.** Scaffolded the WSL-side project home (this repo): filled `CLAUDE.md`, seeded this `memory.md` from the idea's `plan.md`, carried the full design record over as `DESIGN.md`, added `docs/prototype-plan.md`. Idea folder archived to `archive/ideas/jankenstein`.
- Decided to build a **basic networked prototype first** (user wants to test the coordination feel with real friends — local split-screen won't capture the social/voice-chat core). Stack: **Unity NGO + Relay**, host-authoritative, throwaway netcode. Milestone 1 = one shared bot, each player one tread.
- **Consolidated the project + seeded Unity MCP config** (`.mcp.json` → `unity` HTTP server at `172.27.208.1:8080/mcp`, `.claude/settings.local.json`, `docs/mcp-setup.md` runbook), Unity `.gitignore`/`.gitattributes` (no LFS yet).
- **Renamed JANKENSTEIN → JANKENBOTS and unified folders.** User created the Unity project at `F:\jankenbots\jankenbots` (named it jankenbots). Moved the seeded repo (git history + docs + `.mcp.json`) **into** the Unity project root so it's one folder; renamed the Forgejo repo `jankenstein → jankenbots` + updated the remote; re-pointed the symlink to `~/claude/projects/jankenbots`. Unity project is a fresh URP/Input-System template (has `Assets/`, `SampleScene`, `InputSystem_Actions`). **MCP status: ✅ WORKING (verified 2026-07-10, mcp-for-unity-server v3.4.4).** Server binds `127.0.0.1:8067` (HTTP mode), bridged to WSL via `netsh portproxy 0.0.0.0:8068→127.0.0.1:8067`; Claude reaches `http://172.27.208.1:8068/mcp` (`.mcp.json`). **Key gotcha:** 8080 is unusable — it's in a Hyper-V/WinNAT reserved range (WSL2), bind fails with WSAEACCES/Errno 13; use a non-reserved port + a *distinct* proxy port. Full detail in `docs/mcp-setup.md`. **Session wrapped here** — everything committed & pushed; resume by opening a fresh Claude session from this folder (Unity open, MCP server running) and starting Milestone 1.

## External references

- Full design record: `DESIGN.md` (this repo) — control feel v0.1, weapon archetypes, lobby math, tech direction, netcode prior art.
- Prototype build-plan: `docs/prototype-plan.md`.
- Wiki (orientation): http://192.168.1.249:6876/projects/jankenbots
- Idea-phase history: `~/claude/archive/ideas/jankenstein/` (original brainstorm `plan.md` + session logs).
- Netcode prior art (Rocket League GDC talk, Fall Guys/Robocraft/Stumble Guys case studies, Gaffer On Games) — cited in `DESIGN.md` → References.
- **Unity MCP setup runbook:** `docs/mcp-setup.md`. Server = CoplayDev/unity-mcp in **HTTP mode host-side**; Claude (WSL) connects at `http://172.27.208.1:8080/mcp` (`.mcp.json` committed). Bridge pattern mirrors the UE servers (host-side HTTP + host-IP). Not yet stood up — needs the editor + package installed.
