1@README.md 2 3- **This is the one crate under `packages/` that is native-only and does 4 NOT build for `wasm32-unknown-unknown`.** `../CLAUDE.md`'s "no 5 `std::fs`/`std::net`/threads/windowing" rule is about every OTHER crate 6 here staying portable to the browser build; this one is sockets 7 (`tokio::net`, `axum`), threads (its own MCP-server thread) and files 8 (`sessions.rs`, `states.rs`) on purpose, because that is what serving MCP 9 and remembering sessions/snapshots IS. It lives under `packages/` rather 10 than a new top-level directory because it is a plain buck2 `rust_library` 11 like every other package, just not a portable one - `apps/native` is its 12 only consumer and always will be, since a browser build has no local 13 process for an agent to talk to. 14- **Why this crate exists at all, measured 2026-09-20:** before the split, 15 `mcp.rs`/`proxy.rs`/`sessions.rs`/`states.rs` were part of `apps/native`'s 16 own tip crate. Every edit to `apps/native` or `packages/panels` forced 17 buck2 to re-run that crate's ONE rustc invocation, which re-expanded 18 rmcp's `#[tool_router]`/`#[tool]` proc-macros and schemars' `JsonSchema` 19 derive on every single hot-patch cycle, whether or not anything in this 20 code had changed. As its own buck2 target, this crate is recompiled only 21 when ITS OWN source changes. 22- **Deliberately not hot-patch-flagged.** No `-Csave-temps`/`-Clink-dead-code` 23 in `BUCK`. An edit here is not meant to be part of the fast iteration loop 24 `tools/hotpatch` serves - it needs a `restart`. If that ever stops being 25 true (e.g. wanting to hot-patch a tool's description text), add the two 26 flags the same way `packages/panels/BUCK` does, and `patch.sh`'s existing 27 first-party-dependency scan will pick this crate up with no other change. 28- **A new `Request` variant breaks `apps/native` until it is answered, on 29 purpose.** `App::answer` matches every variant with no wildcard arm, so the 30 compiler names the one place the console is actually read. Add the variant 31 and the tool here, then the arm there — never a `_ => {}` to make the build 32 go quiet, which would leave the tool hanging on a reply that never comes 33 (the caller waits on the oneshot until the window closes). 34- **A reader that can be absent returns `Option<T>`, and the tool says so in 35 words**, not with a JSON `null`: null reads to a client as this tool 36 failing, where the truth is about where the game is. 37- `Request`'s `SaveState`/`LoadState`/`HotPatch` variants and the tool 38 methods that build them are the actual channel contract with the app; the 39 UI-thread handling of every `Request` variant stays in `apps/native` 40 (`app.rs`'s `App::answer`), not here - this crate only ASKS, it never 41 touches the console.