ea2499bcfe
The stale-.pyc bug class (#6207, #60242, live WhatsApp report: gateway ImportError 'cannot import name parse_model_flags_detailed' after /update) has one shared shape: the checkout's .py files change while __pycache__ retains bytecode from the previous revision, and a later process trusts the stale .pyc. Update-time clears can never fully close this class: 'hermes update' always executes the PRE-pull updater code, so hardening added to it takes effect one update late — and a manual 'git pull' never runs the updater at all. Class fix: - Launch-time guard in main(): compare the checkout fingerprint (cheap file reads via _read_git_revision_fingerprint, no git subprocess) against a .bytecode-fingerprint stamp; sweep __pycache__ once when they diverge. Covers manual pulls, old updaters, ZIP restores — every entry point (CLI, gateway service, desktop backend) passes through main(). - Record the stamp at all three update-time clear sites (git path pre- install, git path post-install, ZIP path) so a normal update never triggers a redundant launch sweep. - Sibling site: 'hermes plugins update' + dashboard plugin update now clear __pycache__ under the plugin dir after git pull (plugin trees live outside the repo guard). E2E validated: reproduced the stale-pyc shadowing (same-size same-mtime source swap → old symbol wins in a fresh process), confirmed the launch sweep restores the new symbol, no-ops when the checkout is unchanged, and re-sweeps on the next pull. Sabotage-tested: reverting the sweep fails 4 of the new tests.