1@README.md 2 3- **Never edit the bot.** A behaviour the host needs is a change here, in 4 `shim/host.c`, or a compiler flag in `../../third-party/c/BUCK` - with the 5 evidence in `../../research/zbanks-alttp.md`. Only a change no host can 6 make from outside becomes a carried patch, by the rules in 7 `../../third-party/c/CLAUDE.md`. 8- **A new `rando::PATCHES` row changes the cartridge CRC**: every `home` 9 state made before it is refused. Remake them (`apps/zbanks --make-home`, 10 the window's `roms/<rom>.states/` included). 11- **One bot per process.** Its state is C globals; `Bot::start` panics on a 12 second call. Do not try to run two for comparison in one process. 13- **The pointers `base()` returns are cached by the bot for ever** 14 (`ap_snes.c:60-61`). The WRAM mirror and ROM copy are leaked on purpose and 15 must never move or be freed; everything reaches the console by copying 16 through them in `tick`, `load` and `save`. 17- **A new ROM table read by the bot is a Japanese address.** Find the table's 18 bytes in `~/src/github.com/spannerisms/jpdasm`, locate them in the USA ROM, 19 check the whole table matches, and add a `JP_TO_US` row. 20- **`rando::patch_rom` changes the cartridge's CRC**, which every snapshot 21 records: states for a bot must be made from the patched image. 22- Not wasm: the C and the signal handler make it native-only, and 23 `src/outcomes.rs` writes `goal_outcomes.jsonl`. States still come through 24 the `States` trait, never `std::fs` in `lib.rs`. 25- **The given-up watch (`zb_watch_goals`) reads goals after they leave the 26 list.** That is safe only because upstream never frees one: 27 `ap_goal_fail` and `ap_goal_complete` both just `LL_EXTRACT` (ap_plan.c). 28 A refresh from upstream that starts freeing goals turns this into a 29 use-after-free; check those two functions on every refresh. 30- **Permafailed vs completed is `attempts > 3`**, upstream's own threshold in 31 `ap_goal_fail`. Three things test it in the shim and the crate now: the 32 given-up watch above, `zb_completed_count` (`recovery::Recovery`'s progress 33 signal), and the outcome ring `zb_note_outcome` fills (`Outcome::completed`). 34 If a carried patch or a refresh changes that threshold, change all of them. 35- **`src/stall.rs` and `src/recovery.rs` are shared by the window and 36 headless.** They depend on `//packages/alttp:alttp` (for `stall.rs`'s 37 `alttp::Place`) but nothing app-specific - no window, no MCP, no 38 filesystem. `apps/native` used to keep its own copy of `stall.rs`; it now 39 does `use zbanks::stall;`, so there is one definition of "stalled" for 40 both `apps/native` and `apps/zbanks`, not two that can drift. 41- **A goal's identity string is duplicated by convention in three places**: 42 `decisions::goal_choice::identity`, `shim/host.c`'s `zb_note_outcome`, and 43 what `outcomes.rs` stores (`"{kind}|{node}|{screen}"`). This crate cannot 44 depend on `decisions` (the dependency runs the other way). Change all 45 three together or a restart's outcomes stop matching the goals offered.