The pin in scheduler_worker_env.py restores the site-packages *directory* into the
child's PYTHONPATH, but a directory name is not a retention permit. The PM collector
removes an unselected, lease-managed generation once it is old enough and no process
holds its lease, so between the gateway's exit and the worker's next import the very
generation the worker needs can be collected away.
New cron/worker_bootstrap.py closes that gap at the worker entry, before the first
application/dependency import:
- lease_dependencies(): acquire the committed generation's kernel lease (the same
hermes_cli.runtime_state.lease_generation primitive activate_dependencies uses),
so the collector's 'no process holds the lease' safety condition keeps the
generation alive for the worker's whole lifetime. Unconditional and idempotent.
- activate_worker_dependencies(): delegate to pm.environments.activate_dependencies
(the same resolution + site.addsitedir + sys.path reordering the gateway's boot
uses) so the worker's own imports resolve without waiting for the gateway's
handoff. Gated on --external-worker-file in argv, so the in-process gateway path
keeps its exact launch contract and the runner-owns-its-own-deps case stays a
no-op.
Hooked into the top of cron/scheduler.py, after the stdlib-only sys.path pin and
before any Hermes package import, so hermes_yaml -> ruamel.yaml succeeds. Both
degrade to a logged no-op when no dependency generation is committed.
Tests: test_worker_bootstrap_lease_and_activation, _leases_but_skips_activation_in_gateway,
_no_committed_venv_is_noop, and a scheduler-import smoke test. The two home_io_guard
failures in this suite are pre-existing on a clean checkout and unrelated.
Fixes the P2 lifetime finding in @andrexibiza's review of #122290.
(cherry picked from commit 429f0dd191dbf719d05cbbbe3cda6546893b97d0)