299b9dba67
Adds three small extensions to the existing event hook system so plugins can observe agent activity without introducing a parallel pub/sub bus (cf. closed PR #34195 which duplicated this surface). Changes to gateway/hooks.py: - HookRegistry.register(event_type, handler, *, name=None) — programmatic registration that pairs with file-system discovery from ~/.hermes/hooks/. Returns a no-arg callable that deregisters that specific handler. Other handlers on the same event are unaffected. - HookRegistry.emit_sync(event_type, context) — companion to the async emit() for hot-path callers that cannot await. Sync handlers run immediately; async handlers are scheduled on the current running event loop (if any) via asyncio.ensure_future, or skipped with a one-time per-handler warning when no loop is available. Like emit(), it never raises and a buggy subscriber can't break the host pipeline. - get_default_registry() / install_as_default(registry) — module-level default registry singleton so plugins and in-process callers can find 'the' registry without threading a reference through every API. The gateway installs its own self.hooks as the default during startup. Changes to tui_gateway/server.py: - _emit() now mirrors every JSON-RPC event onto the default registry as a 'tui:<sub-event>' hook event with context = {session_id, payload}. The mirror runs as a side-effect after write_json and is wrapped in a broad try/except so a subscriber bug can never break TUI dispatch. The gateway.hooks module is imported lazily on first _emit call to keep TUI cold-start cheap. Wildcard semantics unchanged — handlers registered for 'tui:*' fire for every tui:<anything> event, just like the existing 'command:*' pattern. Test coverage: +10 unit tests in tests/gateway/test_hooks.py covering register/unregister, emit_sync sync+async+wildcard+exception paths, and default-registry singleton behavior. New tests/test_tui_gateway_hook_bridge.py exercises the _emit → registry plumbing end-to-end including subscriber exception isolation, wildcard subscriptions, and the lazy resolve cache. Docs: website/docs/user-guide/features/hooks.md gains a 'tui:*' events table, the new 'Programmatic registration' section, and a note that each Hermes process has its own registry (gateway-discovered hooks are loaded independently in each process). Test counts: 38 hooks tests (was 28), 6 new bridge tests. Full ./scripts/run_tests.sh tests/gateway/ tests/test_tui_gateway* run: 6127 tests passed, 0 failed (272 files, 52s on 24 workers).