fix(intake): resolve the hermes CLI per call, prefer the release shim

The shared checkout's venv is deleted and recreated by release cutovers; a
cutover mid-run left every intake tick failing ENOENT on
<checkout>/venv/bin/python. ~/.local/bin/hermes is repointed by the release
recipe itself, so resolve it fresh on each call and keep the checkout venv as
a fallback.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nirav Patel
2026-08-22 22:33:38 -04:00
co-authored by Claude Fable 5
parent eb0033b952
commit 2952b0c289
+22 -3
View File
@@ -380,11 +380,30 @@ def comment(state: dict, ledger_id: str, content: str, what: str,
# ── Intake: Pulse posts -> ledger + kanban ───────────────────────────────────
def kanban_cmd() -> list[str]:
"""How to invoke hermes' kanban CLI, resolved fresh on every call.
The shared checkout's venv is not stable: a release cutover can delete or
replace it mid-run (observed 2026-08-23 — every intake tick failed with
ENOENT on `<checkout>/venv/bin/python`). The `~/.local/bin/hermes` shim is
repointed by the release recipe itself, so it is the durable entry point;
the checkout venv stays as a fallback for installs that have no shim.
"""
override = cfg("PULSE_BRIDGE_HERMES_PY", "")
if override:
return [override, "-m", "shiva_cli.main"]
shim = HOME / ".local/bin/hermes"
if os.access(shim, os.X_OK):
return [str(shim)]
return [f"{HERMES_DIR}/venv/bin/python", "-m", "shiva_cli.main"]
def kanban(*args: str, timeout: int = 60) -> str:
cmd = kanban_cmd()
cwd = HERMES_DIR if os.path.isdir(HERMES_DIR) else str(HOME)
out = subprocess.run(
[f"{HERMES_DIR}/venv/bin/python", "-m", "shiva_cli.main",
"kanban", *args],
capture_output=True, text=True, timeout=timeout, cwd=HERMES_DIR,
[*cmd, "kanban", *args],
capture_output=True, text=True, timeout=timeout, cwd=cwd,
env={**os.environ, "HERMES_HOME": HERMES_HOME_DIR})
if out.returncode != 0:
raise RuntimeError(f"kanban {args[0]} rc={out.returncode}: "