The image bakes eight extras into /opt/hermes/.venv but never recorded
them as PM's dependency selection. The first generation a container built
(a lazy extra such as fal, a plugin's dependencies) started from an empty
selection, so it carried only what was requested and dropped aiohttp, the
messaging SDKs and mcp. After the next restart the API server, platform
adapters and MCP servers failed to start.
- pm/build_env.py, Dockerfile: --record-selection writes the frozen
build's --extra list to the store facts as the venv selection, as a
bundle build does. enabled-features.json is not written, so the frozen
lazy-install policy stays out of Docker.
- pm/recovery.py: stage2's refresh restores extras the image ships that a
volume's recorded selection lacks, through the normal explicit sync. On
failure the image venv boots and the missing extras stay recorded for
the next attempt. A malformed recorded fact is refused, as
venv_is_current does.
- pm/install.py: share the PEP 685 extra-name key between
_still_declared and the boot reconciliation.
Fixes#135329