fix(update): name the reason launcher publication was skipped

publish_launchers returned silently when a tree was sealed, external, or
had no managed interpreter. A PM tree promises its launchers — the e2e
driver refuses to let `hermes --version` paper over the gap — so that
last case is a half-finished update, not a quiet no-op, and it currently
gives no way to tell which of the three conditions fired.

Keep the same three conditions and the same returns; log which one.
This commit is contained in:
ethernet
2026-09-18 13:25:12 -04:00
parent 0dab3f5e3f
commit 408d7ef28e

View File

@@ -65,13 +65,26 @@ def check_runtime(project_root: Path) -> str | None:
def publish_launchers(project_root: Path, *, create: bool = True) -> None:
"""Refresh durable commands; bootstrap repairs only existing PATH exposure."""
import logging
from hermes_cli._launchers import ENTRY_POINTS, ensure_install_launchers, expose_cli, resolve_store_python
from hermes_cli.steward import read_install_stamp
root = Path(project_root)
if (_is_sealed(root) or read_install_stamp(root).get("updateMechanism") == "external"
or resolve_store_python(root) is None):
log = logging.getLogger(__name__)
if _is_sealed(root):
log.info("launchers: sealed tree at %s keeps its own", root)
return # Sealed and external/Nix interpreters retain their own launchers.
if read_install_stamp(root).get("updateMechanism") == "external":
log.info("launchers: external runtime at %s keeps its own", root)
return
if resolve_store_python(root) is None:
# A PM tree promises its launchers (tests/install/e2e-assets/
# source-driver.sh refuses to let --version paper over the gap), so
# this skip is a half-finished update, never a quiet no-op.
log.warning("launchers: no managed interpreter under %s; %s not published",
root, root / ".hermes" / "bin")
return
written = ensure_install_launchers(root, root / ".hermes" / "bin")
if len(written) != len(ENTRY_POINTS):
from pm.package import InstallError