Files
hermes-agent/tests
Royalaid 965a548788 fix(gateway): serialize config mutations and finish the router off-loop sweep
Two follow-ups to the off-loop move, from external review (both verified,
the second larger than reported):

- Config read-modify-write handlers moved to worker threads could now
  interleave — _CONFIG_LOCK covers each load/save individually, never the
  span between them; the event loop used to serialize these accidentally.
  New _CONFIG_MUTATION_LOCK (worker-threads only, so it can never block
  the loop) held across the whole load→mutate→save span in all seven RMW
  handlers. update_config_raw skipped: it's a full-document replace with
  no server-side read, so a lock cannot close its client-side window.

- The review flagged two skills routes still taking _SKILLS_PROFILE_LOCK
  on the event loop; a systematic audit of hermes_cli/web_routers/ found
  24 on-loop routes (skills 5, mcp 9, tools 10, cron 1). All moved to the
  same inner-_run + asyncio.to_thread pattern, mutating ones under the
  mutation lock, uniform lock order (_SKILLS_PROFILE_LOCK →
  _CONFIG_MUTATION_LOCK). Await-safe _config_profile_scope routes, plain
  def routes, and already-threaded routes unchanged.

Regression tests: concurrent theme+font updates both survive (fails with
the lock nulled: "theme write lost to a concurrent font write"); event
loop stays responsive while the profile lock is held during GET
/api/skills. 214 tests passing across the touched suites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 13:28:28 +05:30
..