Plan and tracking
- Plan of record:
docs/ONLINE_COOP_PLAN.md(decisions D1–D14, risks, phase gates). Work is tracked in the Linear project KH2 Multiplayer (vuhlp workspace); close an issue with its evidence (scenario report, screenshots or clips). - Pace (D14, D15). The next milestone is agent-played two-PC co-op through the TT → HB 1 → LoD 1 first visits, through real doors with no warps (D15, VUH-2337). Pick work that moves that route. An issue is done when it has landed on main and one live run shows it, with the report or clip on the issue; reserve sealing and independent review for inject code near the save. Keep at most six started issues, ship features default-on or park them with a reason, and delete merged or proof worktrees under
.local/when a lane closes. If rig and test churn outpaces product code for two days, stop tooling and build the next route feature. - Only one agent drives live KH2 at a time (the "live lane"). Other agents work offline: network/protocol code, headless Ghidra, tooling, docs. The scenario runner enforces this with the rig lock
build/rig/rig.lock: if it's held by a live process, don't launch KH2 — ask the holder (its pid and command are in the file).
Scenarios (the live regression suite)
python tools/scenario/run.py tools/scenario/scenarios/boot_to_goa.json --repeat 5
- A scenario is JSON steps (boot, warp, input, press, wait, assert, capture, …) with Python assertions over live state. Format, helpers and the example scenarios:
docs/SCENARIOS.md. - Each run writes
build/scenarios/<stamp>_<name>_<n>/report.md+report.jsonwith captures and logs. A crash or hang produces a bundle (minidump + inject log), fails the run, kills its instances, and the runner moves on. - Rig capabilities: before a live run, rehearsal, demo or evidence post, read the
kh2-rigskill (.agents/skills/kh2-rig/SKILL.md). It indexes existing tools (launch, capture, in-renderer videokh2ctl clip, scenarios, Mac relay, input stand-ins, closure, Linear media upload) and their gotchas. Extend it instead of rediscovering. - Evidence: close a live-behavior issue with a passing scenario report (and its captures/clips) attached to the Linear issue. Write the scenario first when the behavior can be checked from memory or the hit log; add it under
tools/scenario/scenarios/so it joins the suite. - Exit codes: 0 pass, 1 fail (or save changed), 2 crash/hang, 3 rig unavailable (lock held or a non-rig KH2 is running — James may be playing; wait).
Safety rules
- Never write James's save under
OneDrive/Documents/My Games/KINGDOM HEARTS HD 1.5+2.5 ReMIX/— Steam Cloud syncs it. Never save in-game during automation. Backstops: the inject DLL's save guard redirects every write open in that folder tobuild/rig/logs/save_sandbox_<pid>/and denies deletes, moves and copies there ([saveguard]lines in the log), and the scenario runner fails the suite if any save file's SHA-256 changes. Neither is a licence to try: don't attempt an in-game save without James's approval. - Launch, restart and kill KH2 only through
kh2ctl launch/restart/kill: the rig kills only processes it launched and refuses to restart while a KH2 it didn't launch is open (James may be playing). Agents never runrestart-kh2.ps1; it kills every KH2 process. - No public network exposure, accounts or third-party services without James.
Proportional rigor
Match verification to what a change can break. On 2026-10-04 four live runs in a row failed in test setup, and each one-line harness fix took about an hour of freezing, sealing and independent review. Don't repeat that.
- Full rigor (pinned inputs, independent review, sealed results): code that runs inside the game (inject DLL, memory writes, hooks), anything near James's save, and acceptance runs for a Linear gate.
- Just change it and run it: scenario fixtures and harness steps (timing, ordering, movement helpers, budgets), diagnostics and logging that don't change behaviour, and docs. Read the report; if it fails, fix and rerun.
- Use the deterministic test as the everyday regression (e.g. the forced resync for VUH-1508); keep long or flaky acceptance runs for when a change is ready.
- When the last two attempts failed in setup or harness work rather than in the feature, stop polishing evidence and shorten the path to an actual attempt.
- Record limits once, in the result file. Status and result write-ups are for James: short, plain language, run ID and evidence path, no hash dumps or stacked qualifiers.
General Guidelines
- Refer to
docs/as the primary source of truth, and always keep up to date with code changes - See
docs/CODEBASE_MAP.mdfor the full directory/file inventory - See
docs/DEVELOPMENT_WORKFLOW.mdfor the build/inject/test loop - See
docs/LESSONS_LEARNED.mdbefore starting any RE work - Always write detailed commit messages
Cheat Engine MCP
- Before using Cheat Engine MCP tools, verify CE is attached to the running KH2 process by calling
pingandget_process_info. If the process is not attached or the game is not running, do not proceed with memory reads/writes/scans — prompt the user to launch KH2 and attach CE first. - When you need the user to do something in-game that cannot be automated via
kh2ctl(e.g., trigger a specific breakpoint scenario, engage a particular enemy, enter a cutscene, or perform a complex sequence not covered by the CLI), stop and make a clear, explicit request to the user before continuing. Do not assume the user has done it or proceed without confirmation. Wait for the user to confirm they have completed the action before resuming analysis. For actions that can be automated (loading saves, basic movement, button presses), prefer usingkh2ctlinstead of asking the user.
Launching KH2 (the rig)
kh2ctl launch # launch + inject the current DLL build; reports pid, log, hooks
kh2ctl restart # kill rig instances, rebuild the DLL, launch + inject
kh2ctl instances # KH2 processes and which ones the rig owns
kh2ctl kill --all # kill rig-launched instances only
Run from the desktop session (KH2 crashes at startup from session 0). Logs: build/rig/logs/kh2coop_inject_<pid>.log. Requires steam_appid.txt (containing 2552430) in the game directory to bypass the launcher; already placed there. See docs/DEVELOPMENT_WORKFLOW.md.
KH2 Control CLI / MCP
Use kh2ctl as the canonical local control surface for automated KH2 testing. See docs/KH2_CONTROL_CLI.md for the full command set and current limitations.
Build: cmake --build build --target kh2ctl --config Release
Rules:
- Prefer
kh2ctlover ad-hoc PowerShell/UI scripting when testing KH2 flows. boot-load-saveis known broken (keys land before the title menu exists; seedocs/KH2_CONTROL_CLI.md). Load saves with the scenario runner'sbootstep, which checks each menu move in a capture.- Use
player-input/player-move/player-pressfor native slot-0 control (goes through inject DLL's raw input collector hook). - Friend-slot gameplay automation should go through mailbox-backed
kh2ctl input/move/presscommands. avatarctl(build/Release/avatarctl.exe) drives a KH2 instance's AvatarBridge without a network:synthruns a puppet around a circle,record/replaycapture and replay the local avatar stream into a puppet slot,fake-localstands in for the DLL,peekprints the bridge. Usage is intools/avatarctl/main.cpp.
Testing Principle
Tests follow stabilization, not implementation. Write regression tests only after an interface stops changing. For live KH2 memory code (GameBridgePC, CameraController, etc.), manual smoke tests against a running game process are the real validation. Reserve unit/integration tests for stabilized boundaries like the codec, protocol, and networking layer.
External Reference Repos
OpenKH (~/openkh) — KH2 modding toolkit. See docs/OPENKH_REFERENCE.md. Use for animation IDs, entity types, party slot mapping, world IDs. Do NOT use for runtime memory offsets (those come from KH2Offsets.hpp).
KH2 Lua Library (~/kh2-lua-library) — Community runtime memory addresses for all PC versions. Use for non-Steam-Global builds, unit slot internal offsets, save file structure, game state detection. Do NOT use for entity transforms, camera, or animation RE.
Ghidra, headless (scripts/ghidra.ps1) — no GUI needed, safe for several agents at once (read-only). -Setup builds the fully analyzed project in build/ghidra/kh2_full once; then -Decompile 0xRVA[,0xRVA] prints the function with its callers/callees, and -Xrefs 0xRVA [-Window 0x40] [-MaxDecomp 3] lists every read/write near an address and decompiles the users. RVAs match pointer_map_v1.md. Prefer this to ~/kh2.gpr, which lacks data xrefs.
Ghidra + GhidraMCP (~/GhidraMCP) — Static binary analysis via MCP against a running Ghidra GUI. Use for renaming/annotating interactively. Use Ghidra for static analysis, CE (or the rig's probes) for dynamic analysis. Cross-reference both.
LuaBackend (~/kh2-tools/LuaBackend) — Lua scripting engine with frame hook via DLL proxy. Reference for hook mechanisms, Lua API, memory access patterns.
KHPCPatchManager (~/kh2-tools/KHPCPatchManager) — Binary patching tool. Reference for mod distribution packaging.
Character Mod Examples (~/kh2-tools/mods/) — Four reference mods (axel-mix, dual-wield-roxas, vanitas-remaster, master-trio) showing character swap/addition techniques. Key patterns for multiplayer: memt_0.list for party composition, ObjEntry for custom entities, AtkpList for attack parameters.
Swarm Coordination
For multi-agent sessions, load the swarm-mcp skill (or swarm-planner/swarm-implementer for specific roles). Those skills contain the full coordination protocol.
