quit the game cleanly on stop, so best times survive

Where they live: `HKCU\Software\Brightsoft\Minesweeper X` in the prefix's
`user.reg`. `Time1/2/3` are beginner, intermediate and expert; `Name1/2/3` are
the names, which is why the name you type sticks as the default. Nothing is
stored beside the executable except the recordings.

Why they were always empty: the game holds that whole key in memory and commits
it ONLY on a clean exit. `stop()` sent SIGTERM. So every restart of this sidecar
threw away every record set since the last one — six wins in one evening left a
Best Times table reading 9999.99, which is what started this.

`stop()` now drives Game > Exit and waits for the process to go before reaping.
It runs FIRST, ahead of even reaping x11vnc, because it needs the display alive
and it is racing PM2's clock.

── how it was pinned down ──

Not by reading. `user.reg` grew by 848 bytes at the exact moment the game
exited, which named the file. Writing `Time1="12.34"` / `Name1="Pastilhas"`
into it by hand and restarting made the game display them, which proved the key
and the load path. Then switching difficulty and stopping cleanly wrote
Width/Height/Mines through from 30/16/99 to 8/8/10, which proved the write path
carries in-memory state — beginner is 8x8 here, not the 9x9 I had assumed.

── the part this does NOT fix ──

`pm2 restart` will usually still cut it short: PM2 SIGKILLs 1600ms after
SIGTERM by default and a full stop takes about 5.6 seconds. That is not new —
this sidecar's teardown has always exceeded that budget — but it does mean the
fix only reliably applies to an explicit POST /stop. Raising it needs a
`kill_timeout` on `Pm2App` in the platform's plugins/ecosystem.ts, which has no
such field. Left alone rather than decided quietly; it is in the README.

Also reverted: the 12.34 "Pastilhas" beginner record was my probe, not a game.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: de3ed4e6-f88a-429c-94e6-a760336ba83b
This commit is contained in:
2026-08-23 23:50:37 +00:00
co-authored by Claude Opus 5
parent 34fad8be35
commit 035c374563
3 changed files with 86 additions and 0 deletions
+22
View File
@@ -47,6 +47,28 @@ The download needs a browser `User-Agent`; the site answers `403` to curl's defa
auto-save the recording.
- `run/` — pid state, logs, and `vnc.sock`. **Mode 0700, and that is load-bearing.**
## Best times live in the registry, and only a clean exit writes them
`HKCU\Software\Brightsoft\Minesweeper X` in the prefix's `user.reg` — `Time1/2/3` for beginner,
intermediate and expert, `Name1/2/3` for the names, plus every other setting the game has. Nothing is
stored beside the executable except the recordings.
**The game holds all of it in memory and commits it only when it exits cleanly.** `stop()` sent SIGTERM,
so every restart of this sidecar discarded every record set since the last one: six wins in one evening
left a Best Times table reading 9999.99. `stop()` now drives Game → Exit first and waits.
Two things about that worth knowing before trusting it:
- **`pm2 restart` will usually cut it short.** PM2 SIGKILLs 1600ms after SIGTERM by default and a full
stop here takes about 5.6 seconds, so the quit rarely finishes. `Pm2App` in the platform's
`plugins/ecosystem.ts` has no `kill_timeout` field to raise. An explicit `POST /stop` always completes.
- **A dialog blocks it**, like every other command that drives the menu, and it gives up rather than
clicking blindly. The log says so and the reap proceeds.
Diagnosed by watching `user.reg` grow by 848 bytes at the moment the game exited; confirmed by writing a
time into the key by hand and seeing the game display it, then by switching difficulty and watching a clean
stop write `Width`/`Height`/`Mines` through to disk.
## Two gaps, both from having no window manager
Worth knowing before you conclude something is broken. Neither is hard to fix; neither is fixed.