run.sh created .venv on first run and then only ever launched the app. When
the crdt-sync pin moved to v0.9.0 nothing ran pip, so the venv sat at 0.6.0
for months and surfaced as an ImportError on LogCodec at startup. The venv is
isolated (ENABLE_USER_SITE=False), so it could not fall back to the healthy
0.9.0 in user site-packages that the systemd units use.
Reconcile against requirements.txt and refuse to launch if that fails, rather
than starting on dependencies we already know are wrong.
Gated on a sha256 stamp of requirements.txt: pip re-resolves the two git pins
over the network (~5.5s) on every call, and this is a screen locker that has
to start when the network is down. The stamp is only written on success, so a
failed install retries on the next launch instead of being remembered as done.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCUN9mdfJzJXqEZatHnUCD