fix(update): drop the cached live plugin catalog on boot after a code change

Bundled/sealed app updates never run hermes update's maintenance tail, so
their pre-update catalog snapshot stayed authoritative for the cache TTL.
Add a boot home step (once per installed revision, per profile) that drops
the active home's cache (#119340).
This commit is contained in:
Brooklyn Nicholson
2026-09-24 23:32:15 -05:00
committed by brooklyn!
parent f4a86aa135
commit 76e2111c14
2 changed files with 31 additions and 0 deletions

View File

@@ -149,6 +149,20 @@ def step_state_db_guard() -> dict:
return {"ok": False, "error": message}
def step_drop_live_plugin_catalog() -> dict:
"""Drop the active home's cached live plugin catalog after a code change.
Bundled/sealed app updates never run ``hermes update``'s maintenance tail,
so without this a pre-update snapshot out-votes the newer in-tree catalog
for the rest of its TTL (#119340). Per home, like the boot record.
"""
from hermes_constants import get_hermes_home
from hermes_cli.plugin_catalog import invalidate_live_cache_for_home
invalidate_live_cache_for_home(get_hermes_home())
return {"ok": True}
def step_adopt_blessed_checkout(project_root: Path | None = None) -> dict:
"""One-time adoption of shipped stampless installs (birth certificate).
@@ -285,6 +299,7 @@ HOME_STEPS: tuple = (
("migrate_config", step_migrate_config),
("sync_skills", step_sync_skills),
("state_db_guard", step_state_db_guard),
("drop_live_plugin_catalog", step_drop_live_plugin_catalog),
("expose_cli", expose_cli),
)

View File

@@ -128,6 +128,22 @@ def test_state_db_guard_passes_valid_db(tmp_path, monkeypatch):
assert step_state_db_guard() == {"ok": True}
# ── step_drop_live_plugin_catalog ────────────────────────────────────
def test_boot_drops_the_live_plugin_catalog_cache(tmp_path, monkeypatch):
"""Bundled-app updates skip `hermes update`'s tail; the boot step covers them (#119340)."""
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
cache = tmp_path / "cache" / "plugin-catalog.json"
cache.parent.mkdir()
cache.write_text("{}", encoding="utf-8")
assert ("drop_live_plugin_catalog", post_update.step_drop_live_plugin_catalog) in post_update.BOOT_HOME_STEPS
assert post_update.step_drop_live_plugin_catalog() == {"ok": True}
assert not cache.exists()
assert post_update.step_drop_live_plugin_catalog() == {"ok": True} # absent cache is fine
# ── machine-step registry ────────────────────────────────────────────