The desktop app is a browser now, so it cannot write files. This adds the other
half: a loopback HTTP server that serves the web build and owns the two files
the browser cannot touch -- `~/todo/BACKLOG.md`, which the user's tooling and
the todo MCP server read, and a disk copy of the note log so a wiped Chrome
profile is not a total-loss event for unsynced notes.
Notable details:
- Binds to 127.0.0.1 only. The endpoints overwrite files in the user's home
with no authentication, so a routable bind would let anything on the network
rewrite the backlog.
- Serves explicit content types. CanvasKit refuses a `.wasm` labelled anything
else and the app then renders nothing at all.
- Mirroring to disk is debounced. The store persists on every keystroke, so
mirroring eagerly meant an HTTP request plus a whole-log write per character;
IndexedDB still gets every keystroke, only the durability copy waits.
Separately, this fixes a pre-existing destructive bug found while testing:
`settings_screen_test` did real file I/O and overwrote the user's canonical
`~/todo/BACKLOG.md` with a single fake note on *every* `flutter test` run. It
went unnoticed because the app rewrites the file whenever it launches. The
export destination is now injectable and the test redirects it to a temp dir;
verified that a full suite run leaves the real file byte-identical.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>