fix(hosted-rooms): local_profiles skips the profile-delete tombstone dir
`hermes profile delete` leaves `profiles/.deleted/<name>` behind. `HostedRoomService.local_profiles()` fed every subdirectory name to the roster, so `.deleted` failed `validate_roster`'s identifier check and `plan_next_task` raised on every cycle for every room until the directory was removed by hand (#106847, bug 2). Skip dot-dirs and tombstoned profiles, using the same `named_profile_is_deleted` predicate `hermes_cli.profiles` uses to list live profiles. Refs #106847
This commit is contained in:
@@ -2073,3 +2073,19 @@ def test_peer_recovery_replays_the_same_execution_generation(tmp_path: Path):
|
||||
assert recovered["task_id"] == "task-1"
|
||||
assert recovered["execution_generation"] == 1
|
||||
assert recovered["prompt"] == "Recover the accepted review."
|
||||
|
||||
|
||||
def test_local_profiles_skips_delete_tombstones_and_dot_dirs(tmp_path: Path):
|
||||
"""`hermes profile delete` leaves ``profiles/.deleted/<name>``; neither the tombstone dir nor a
|
||||
tombstoned profile is a roster member (#106847: ``.deleted`` failed validate_roster every cycle)."""
|
||||
from hermes_constants import mark_named_profile_deleted
|
||||
|
||||
profiles = tmp_path / "profiles"
|
||||
(profiles / "ops").mkdir(parents=True)
|
||||
(profiles / "gone").mkdir()
|
||||
mark_named_profile_deleted(profiles / "gone")
|
||||
assert (profiles / ".deleted").is_dir()
|
||||
|
||||
service = HostedRoomService(_server(), db_path=tmp_path / "shared-state.db")
|
||||
|
||||
assert service.local_profiles() == ("default", "ops")
|
||||
|
||||
@@ -124,9 +124,15 @@ class HostedRoomService:
|
||||
return self.db_path.parent
|
||||
|
||||
def local_profiles(self) -> tuple[str, ...]:
|
||||
from hermes_constants import named_profile_is_deleted
|
||||
|
||||
profiles, profiles_dir = {"default"}, self.root / "profiles"
|
||||
if profiles_dir.is_dir():
|
||||
profiles.update(path.name for path in profiles_dir.iterdir() if path.is_dir())
|
||||
# ``profiles/.deleted/`` is the tombstone dir `hermes profile delete` leaves behind, not a
|
||||
# profile: feeding it to validate_roster failed plan_next_task on every cycle (#106847).
|
||||
profiles.update(
|
||||
path.name for path in profiles_dir.iterdir()
|
||||
if path.is_dir() and not path.name.startswith(".") and not named_profile_is_deleted(path))
|
||||
return tuple(sorted(profiles))
|
||||
|
||||
def bindings(self) -> tuple[HostedRoomBinding, ...]:
|
||||
|
||||
Reference in New Issue
Block a user