docs: operating handover — run, diagnose, and what is still outstanding

Written so the bot can be run without me: control commands and their gotchas,
how to tell a normal break from a stuck bot, the break-length multiplier, the
health-check greps, the temporary settings to revert, and the two things only
the user can do (F7 rebind, fire resist).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
alexpolo1
2026-08-29 00:16:52 +02:00
parent 1c19b8bdc8
commit b8a36e8231

171
HANDOVER.md Normal file
View File

@@ -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 "<the thing>" 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.