diff --git a/HANDOVER.md b/HANDOVER.md new file mode 100644 index 0000000..58ec725 --- /dev/null +++ b/HANDOVER.md @@ -0,0 +1,171 @@ +# Handover — 2026-08-29 + +Everything you need to run this yourself. Written after a long debugging session; +`CLAUDE.md` has the deep detail, this is the operating manual. + +--- + +## Running the bot + +```bash +run_botty.bat # starts the process (idle) +python scripts/hermes_bot_control.py start # begins playing +python scripts/hermes_bot_control.py status # running=X paused=Y +python scripts/hermes_bot_control.py stop # exits the process +``` + +**`start` is idempotent** (fixed 2026-08-28) — pressing it twice is safe. `pause` +and `toggle` are the toggle. Before the fix, a repeated `start` paused the bot +and `status` still said `running=True`; that cost ~5 hours once. + +**Always verify with `status`, not the "OK: command sent" reply.** And check the +log actually moves — `=== BOT START ===` is the proof it began a game. + +### Restarting after a code or config change + +A running bot does **not** pick up edits. Python loads modules at process start. + +```bash +python scripts/hermes_bot_control.py stop +# wait until nothing is listening: +netstat -ano | grep 18899 +run_botty.bat +python scripts/hermes_bot_control.py start +``` + +If `stop` times out, retry it — the socket occasionally needs two attempts. Only +force-kill as a last resort: killing mid-game leaves D2R in a state the bot +cannot re-enter, and you then have to save+exit to the main menu by hand. + +**Only ever run one instance.** Two both bind the control socket and fight over +start/pause, and the logs become nonsense. Check with `tasklist | grep -i python`. + +--- + +## Is it stuck, or just idling? + +The bot sits at the D2R **character-select menu** during a normal break. The +stuck case looks identical. Do not judge by the screen. + +```bash +LAST=$(grep -n "control socket listening" log/log.txt | tail -1 | cut -d: -f1) +tail -n +$LAST log/log.txt | grep -cE "select_char|Restarting bot|Uncaught exception" +``` + +| | Normal break | Stuck | +|---|---|---| +| `status` | `running=True paused=True` | the same | +| `select_char` errors | none | present | +| `Restarting bot` | none | every ~20s | +| Log | quiet | new process repeatedly | + +**The tell is the log filling with restart lines, not the menu.** + +### Break lengths are longer than they look + +`maybe_afk_break` calls `wait(m, m*1.5)` and `wait()` applies its own jitter (up +to 1.44x). They compound: + +| planned | actual | +|---|---| +| 3.9m | 7.1m | +| 11.9m | 19.5m | +| 20:56 | 25.5m | + +So **multiply any break setting by 1.5 x 1.44** before deciding it is safe. A +~25 minute idle is what left D2R unable to re-enter once. `afk_break_max_m` is +capped at 7 for this reason (=> ~15m worst case). + +--- + +## Health check + +```bash +LAST=$(grep -n "control socket listening" log/log.txt | tail -1 | cut -d: -f1) +tail -n +$LAST log/log.txt > /tmp/c.log +echo "games $(grep -c 'game | start' /tmp/c.log) | failed $(grep -c 'game | end .*fail' /tmp/c.log) | deaths $(grep -c 'You have died' /tmp/c.log) | crashes $(grep -c 'Uncaught exception' /tmp/c.log)" +``` + +Useful greps: + +| what | grep | +|---|---| +| Step-by-step timeline | `grep "TL>" log/log.txt` | +| Failure records | `grep "FAIL>" log/log.txt` | +| Stealth manifest at startup | `grep "STEALTH>" log/log.txt` | +| Mana threshold crossings | `grep "MANA>" log/log.txt` | +| Level / exp | `ls -t log/stats/mini_stats_*.json \| head -1` | + +**`FAIL>` gives the whole story of a failed game** — reason, location, the three +slowest steps, and a breadcrumb trail with `!` marking failures. Read the trail, +not just the reason: the step that blew up is often not the one that caused it. + +--- + +## Temporary settings to revert + +| file | setting | now | should be | +|---|---|---|---| +| `config/params.ini` | `session_budget_h` | **20** | 8 | +| `config/params.ini` | `difficulty` | hell | your call | + +`session_budget_h = 20` was raised for a levelling push. It rolls to 13-27h, +which largely disables the stop-for-the-day behaviour that the session-rhythm +work exists to provide. **Put it back to 8 once you have the levels.** It is +uncommitted, so `git checkout config/params.ini` reverts it. + +--- + +## Outstanding + +**PR #39 is open and NOT merged, and the fix is NOT live.** +It makes the pather abort actually fire. The guard has now looked correct and +done nothing twice — most recently `aborts 0, guesses 8` across 152 games. Merge +it, then **restart** to load it, then confirm with: + +```bash +grep -c "aborting traverse" log/log.txt # should become non-zero +grep -c "taking a random guess" log/log.txt # should stop growing +``` + +**Two things only you can do:** + +1. **Rebind F7 → Concentration** in game (hover it in the bind grid, press F7). + Concentration is currently unbound; it is the party aura that buffs your + merc. Then set `concentration=f7` in the profile. +2. **Fire resist** — the chicken rate (~7%) is a gear number, not a config one. + `chicken=0.40` is doing its job; lowering it trades chickens for deaths. + +**Known-stale:** the `CONVICTION` preflight template scores 45.9% while the bind +is provably correct, so every startup logs a false alarm. Cosmetic. + +--- + +## Checking your binds after any gear change + +```bash +python tools/testbed.py spellbook --assets +``` + +Hovers the whole bind grid, reads each skill from its tooltip and each hotkey +from the icon corner, and prints which config keys disagree with the game. Exits +1 on a mismatch. This exists because an Enigma put Teleport on F5 and displaced +Conviction, and `conviction=f5` would have teleported the character mid-fight. + +--- + +## The one habit worth keeping + +Most of what went wrong here was **configured behaviour that never executed**, +and nothing reported it. AFK breaks were 0-for-225 at a configured 5%. The +manifest said `wired` throughout. + +When something should be happening and you are not sure it is, **count it**: + +```bash +grep -c "" log/log.txt +``` + +A zero where you expected a number is the most informative result in this +project. It found the AFK break, the loot-filter clicks, the Chronicle panel, +and the pather abort — twice.