Independent review found the previous commit could make the unbounded-growth symptom it fixes PERMANENT, and that its argv narrowing re-opened #92401 inside a single install. - other_generations_for_path() counts only LIVE generations. A retired one is already write-fenced (StateDbReplacedError, close-time checkpoint disabled) and leaves the registry only when its holder releases -- which a gateway handle does not do before shutdown. One inode replacement (repair swap, backup restore, snapshot) therefore skipped auto-VACUUM for that path for the whole process lifetime. - _argv_scoped_to_other_home is ranked evidence now. argv[0] is the SHARED install binary for every profile on a host, so it is neutral, never proof of a hold; the process's own --hermes-home / HERMES_HOME= / --profile / -p selection decides which home it serves, and a token naming ANOTHER profile's store is tested before any own-prefix check. argv[0] also stops dismissing a holder of a store whose home is not part of an install layout (a custom HERMES_HOME is served BY the binary under ~/.hermes). - install_root comes from hermes_constants.named_profile_home, not basename(parent) == "profiles": an arbitrary <X>/profiles/<n>/ tree no longer promotes all of <X> to "ours". - The launch profile keeps its gateway.sessions_dir override when its own store is pruned; every other served profile prunes under its own <home>/sessions. Pruning under the wrong dir orphaned transcripts forever. - glob.escape on the request_dump_<id>_* sweep (pre-existing). Tests: the retired-generation test asserted the starvation mechanism; it is replaced by the invariant (a live sibling defers VACUUM) plus a red-on-base test that a retired, write-fenced generation does not. New argv cases cover the shared binary with -p other, another profile's store token, and a non-Hermes <X>/profiles/ tree; the housekeeping fixture now asserts the unpinned store still resolves inside the sandbox before yielding.
24 lines
1.1 KiB
Python
24 lines
1.1 KiB
Python
"""Pruned-session file removal is id-scoped even when the id carries glob metacharacters.
|
|
|
|
``request_dump_<id>_*.json`` was interpolated unescaped, so an id containing ``[``/``?``/``*`` was
|
|
a PATTERN: its own dumps were left behind and another session's could be matched instead.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from hermes_state_sessions import SessionSessionsMixin
|
|
|
|
|
|
def test_remove_session_files_escapes_glob_metacharacters(tmp_path):
|
|
tricky, neighbour = "sess-[ab]-1", "sess-a-1"
|
|
for session_id in (tricky, neighbour):
|
|
(tmp_path / f"{session_id}.jsonl").write_text("{}\n", encoding="utf-8")
|
|
(tmp_path / f"request_dump_{session_id}_0.json").write_text("{}", encoding="utf-8")
|
|
|
|
SessionSessionsMixin._remove_session_files(tmp_path, tricky)
|
|
|
|
assert not (tmp_path / f"{tricky}.jsonl").exists()
|
|
assert not (tmp_path / f"request_dump_{tricky}_0.json").exists(), "own dump was not matched"
|
|
assert (tmp_path / f"{neighbour}.jsonl").exists()
|
|
assert (tmp_path / f"request_dump_{neighbour}_0.json").exists(), "neighbour's dump was removed"
|