refactor(state): dict-dispatch persistence-error classifier, unify WHERE/placeholder builders, compact docstrings across state modules

This commit is contained in:
Teknium
2026-09-02 20:18:08 -07:00
parent 3c9a51bbf1
commit ff3ebf509f
5 changed files with 372 additions and 549 deletions
+22 -37
View File
@@ -15,9 +15,7 @@ except ImportError: # pragma: no cover - stripped/scaffold installs only
psutil = None # type: ignore[assignment]
# Field evidence: pytest fixture rows landed in the production state.db and a
# pytest-spawned child flipped the journal mode under the live WAL writer,
# destroying committed transcripts; any HERMES_HOME escape (fixture ordering, a
# child spawned without it, a shell exporting the real home) fell through silently.
# pytest-spawned child flipped the journal mode under the live WAL writer.
#: Env twin of ``_STATE_DB_GUARD_BYPASS`` for child processes (a module global
#: cannot cross a process boundary, and ancestry arms the guard there).
@@ -26,29 +24,23 @@ _STATE_DB_GUARD_BYPASS_ENV = "HERMES_STATE_DB_GUARD_BYPASS"
def _real_platform_state_root() -> Optional[Path]:
"""The REAL platform-default Hermes root. Avoids ``Path.home()`` /
``hermes_constants``: tests monkeypatch Path.home to a tempdir while this
module is imported lazily, which would misidentify the hermetic home as
production or miss the real one. ``expanduser`` reads HOME/passwd, which the
conftest never rewrites."""
``hermes_constants`` (tests monkeypatch Path.home to a tempdir); ``expanduser``
reads HOME/passwd, which the conftest never rewrites."""
try:
home = Path(os.path.expanduser("~"))
if sys.platform == "win32":
base = os.environ.get("LOCALAPPDATA", "").strip()
root = (
Path(base) / "hermes"
if base
else Path(os.path.expanduser("~")) / "AppData" / "Local" / "hermes"
)
root = Path(base) / "hermes" if base else home / "AppData" / "Local" / "hermes"
else:
root = Path(os.path.expanduser("~")) / ".hermes"
root = home / ".hermes"
return root.resolve()
except Exception:
return None
#: Exported by the hermetic conftest alongside the HERMES_HOME redirect (value:
#: the isolation root). Unlike PYTEST_* (scrubbed by tests that rebuild a child
#: env) it is OURS and inherits by default, so a child carrying it that resolves
#: a production DB is by definition an isolation escape.
#: Exported by the hermetic conftest alongside the HERMES_HOME redirect. Unlike
#: PYTEST_* it is OURS and inherits by default, so a child carrying it that
#: resolves a production DB is by definition an isolation escape.
_TEST_ISOLATION_MARKER_ENV = "HERMES_TEST_ISOLATION"
@@ -70,18 +62,15 @@ _PYTEST_ANCESTOR: Optional[bool] = None
def _process_looks_like_pytest(proc: Any) -> bool:
"""True when *proc*'s command line is a pytest invocation (``pytest ...`` or
``python -m pytest``). Unreadable cmdline => not pytest: guessing the other
way would refuse production opens for unrelated reasons."""
"""True when *proc*'s command line is a pytest invocation. Unreadable cmdline
=> not pytest: guessing the other way would refuse production opens."""
try:
cmdline = proc.cmdline() or []
except Exception:
return False
for arg in cmdline:
try:
# Split on both separators on every host: os.path.basename is
# POSIX-only under Linux and would leave a Windows-style path
# intact, making the matcher's answer depend on the platform.
# Split on both separators on every host so the answer is platform-independent.
name = str(arg).strip('"').strip("'").replace("\\", "/").rsplit("/", 1)[-1].lower()
except Exception:
continue
@@ -91,10 +80,9 @@ def _process_looks_like_pytest(proc: Any) -> bool:
def _has_pytest_ancestor() -> bool:
"""True when an ancestor process is a pytest run. A child spawned with a
rebuilt env loses PYTEST_* and the HERMES_HOME redirect together — aiming at
production AND disarming the guard in one step; ancestry survives that.
Fails open without psutil / on walk errors (never block real user runs)."""
"""True when an ancestor process is a pytest run: a child spawned with a
rebuilt env loses PYTEST_* and the HERMES_HOME redirect together, ancestry
survives that. Fails open without psutil / on walk errors."""
global _PYTEST_ANCESTOR
if _PYTEST_ANCESTOR is not None:
return _PYTEST_ANCESTOR
@@ -109,15 +97,13 @@ def _has_pytest_ancestor() -> bool:
def _in_test_context() -> bool:
"""Test run by environment or ancestry. Env first (two dict lookups); the
memoised ancestry walk runs at most once per real ``hermes`` invocation."""
"""Test run by environment or ancestry (memoised; env checked first)."""
return _running_under_pytest() or _has_pytest_ancestor()
def _is_production_state_db(resolved: Path, root: Path) -> bool:
"""*resolved* is ``<root>/state.db`` or ``<root>/profiles/<name>/state.db``.
Deeper scratch paths (repo worktrees under ~/.hermes/hermes-agent/...) are
deliberately NOT matched so hermetic tests cannot false-positive."""
"""*resolved* is ``<root>/state.db`` or ``<root>/profiles/<name>/state.db``;
deeper scratch paths (repo worktrees) are deliberately NOT matched."""
if resolved.parent == root:
return True
try:
@@ -128,16 +114,15 @@ def _is_production_state_db(resolved: Path, root: Path) -> bool:
# Last SessionDB() init error, per-process; surfaced by /resume-style slash
# commands so users know WHY. Only SessionDB.__init__ writes it (kanban_db
# failures are reported via their own callers, by design).
# commands so users know WHY. Only SessionDB.__init__ writes it.
_last_init_error: Optional[str] = None
_last_init_error_lock = threading.Lock()
def _set_last_init_error(msg: Optional[str]) -> None:
"""Record (or clear with None) the most recent state.db init failure.
__init__ only SETs on failure and never clears on success: a concurrent
successful open would erase the cause another thread's /resume is about to format."""
"""Record (or clear with None) the most recent init failure. __init__ never
clears on success: a concurrent open would erase the cause another thread's
/resume is about to format."""
global _last_init_error
with _last_init_error_lock:
_last_init_error = msg