Skip to content

Multiplexed housekeeping: one profile's failure no longer skips the rest or leaks its home (salvage #110405) - #120268

Merged
austinpickett merged 1 commit into
mainfrom
austin/fix/statedb-housekeeping-isolation
Sep 23, 2026
Merged

austinpickett merged 1 commit into
mainfrom
austin/fix/statedb-housekeeping-isolation

Conversation

@austinpickett

@austinpickett austinpickett commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

One gap left in the multiplexed gateway's per-profile housekeeping after #117746 and #118006 moved every served profile's state.db sweep onto that loop.

What changed

  • gateway/run_profile_reconcile.py::_for_each_served_profile gives each served profile its own try/except. Before this, one profile's unreadable store or broken .env ended the loop, and _housekeeping_chore only catches at the tick level. Every profile after the failing one lost its state.db archive/prune, curator, skill-sync and MCP-reconcile pass on every tick. This can happen in practice: _init_session_db tolerates a failed launch store and keeps running, and hermes serve hands every served profile's auto-archive to this loop (state.db residuals: serve stands down under a live gateway, recovery survives the first resume, import refuses a held deleted database #117746 C1). A satellite sitting behind a broken launch store had nothing sweeping it. Failures log at debug, like _housekeeping_chore.
  • The companion _profile_runtime_scope unwinding fix (a failed secret hydration leaving the profile's home installed) landed on main independently as 6aaa1c4 while this was open, so it was dropped on rebase. The regression test for it is kept, since this loop makes that path reachable on every tick.

Tests

Two cases added to tests/gateway/test_housekeeping_profile_scope.py. Both use real stores and the real housekeeping loop:

  • test_a_failing_profile_does_not_strand_the_profiles_after_it: the launch store raises in acquire(), and the served profile B must still be swept.
  • test_profile_scope_setup_failure_restores_the_callers_home: secret hydration raises, and the caller's home and secret scope must be restored.

Red on origin/main before the scope fix landed, with both production files reverted:

E       AssertionError: assert [] == [PosixPath('/.../b/state.db')]
E       AssertionError: unpinned store escaped the sandbox: /.../test_profile_scope_setup_failu0/home/.hermes/profiles/b/state.db

The second line comes from a different test in the same worker. The leaked override carried profile B's home into it. With only the isolation fix applied, the scope test still fails with profiles/b == .hermes.

Check Result
tests/gateway/test_housekeeping_profile_scope.py 7 passed
Every tests/gateway + tests/tui_gateway file that references _profile_runtime_scope / _for_each_served_profile / housekeeping (66 files) 745 passed, 1 skipped
ruff, check-windows-footguns.py, check_no_tmp_literals.py, check_compat_pointers.py, git diff --check clean

Not changed

Refs #100896

Supersedes #110405. Thanks @isair: the broken-launch-store isolation case comes from your review rounds on that PR (you're co-author on the commit). Your scope-unwinding fix is also on main now, via 6aaa1c4.

Rebased onto main 2026-09-23: test_housekeeping_profile_scope.py 7/7 pass; the isolation test fails on main's run_profile_reconcile.py and passes with the fix.

@github-actions

github-actions Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 8511560 — fix(gateway): one served profile's failing chore no longer s

debug info

CI timings

CI timings · View report · View job

Wall time 5m54s vs 6m42s (-11.9%). 4 job(s) slower, 8 faster,

  • Python lints / Windows footguns (blocking): -108.0s
  • OS-specific tests / Windows-only tests: -48.0s
  • Python tests / Run tests: -46.0s
  • Python tests / e2e: +25.0s
  • Python lints / ruff enforcement (blocking): -17.0s

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery area/profiles Multi-profile isolation, HERMES_HOME scoping area/sessions Session lifecycle, resume, persistence, history sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Sep 23, 2026
…rest

_for_each_served_profile ran a housekeeping body once per served profile
with no boundary between them, and _housekeeping_chore only catches at the
tick level. One profile's unreadable store or broken .env therefore ended
the loop, and every profile after it lost its state.db archive/prune,
curator, skill-sync and MCP reconcile pass on every tick.

That state is reachable: _init_session_db tolerates a failed launch store
and keeps running, and hermes serve defers each served profile's
auto-archive to this loop (#117746), so a satellite behind a broken launch
store had no sweeper at all.

Each profile now gets its own try/except, logged at debug like
_housekeeping_chore.

Co-authored-by: Baris Sencan <b.sencan@equalsmoney.com>
@austinpickett
austinpickett force-pushed the austin/fix/statedb-housekeeping-isolation branch from 132afcb to 8511560 Compare September 23, 2026 14:12
@austinpickett
austinpickett merged commit d2ef7db into main Sep 23, 2026
34 checks passed
@austinpickett
austinpickett deleted the austin/fix/statedb-housekeeping-isolation branch September 23, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping area/sessions Session lifecycle, resume, persistence, history comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants