/** * venv-holder-select.ts * * Pure Windows venv-holder selection logic (testable without Electron). * * The pre-update handoff kills Hermes-OWNED venv daemons (the memory plugin's * hindsight daemon) so the updater never races a mapped shim. External * holders (a user terminal running `hermes`, unrelated scripts) must NOT be * killed — current design reports them via scanVenvBlockers and ABORTS the * handoff instead (main.ts releaseBackendLock / applyUpdates). */ /** Ordinal case-insensitive prefix check for Windows paths. */ export function hasWindowsPathPrefix(exePath: string, venvScriptsDir: string): boolean { const prefix = `${venvScriptsDir}\\` return exePath.length >= prefix.length && exePath.slice(0, prefix.length).toLowerCase() === prefix.toLowerCase() } /** * True when a process is a Hermes-owned venv daemon: its exe lives under * `\Scripts\` (ordinal case-insensitive prefix) AND its cmdline * references `hindsight_api.main` (the memory daemon the memory plugin * spawns DETACHED — it outlives Hermes and holds venv shims mapped). */ export function isHermesOwnedVenvDaemon( exePath: string | null | undefined, cmdline: string | null | undefined, venvScriptsDir: string ): boolean { if (!exePath || !cmdline) { return false } return hasWindowsPathPrefix(exePath, venvScriptsDir) && /hindsight_api\.main/i.test(cmdline) }