hermes-agent/tests
Sahil Saghir dfa561092a fix(kanban): machine-global singleton lock for the embedded dispatcher (#41448)
The gateway's embedded dispatcher has no guard against more than one dispatcher
running concurrently. dispatch_in_gateway defaults to true, so a second gateway
for the same profile (a restart race where the old process is slow to exit) — or
any deployment that runs multiple profile gateways with the default — starts a
second dispatcher loop. As #41448 describes, concurrent dispatchers each run
release_stale_claims() against the same boards, double reclaim frequency, and
re-dispatch slow workers before they finish. In practice they also corrupt the
shared kanban SQLite DBs under concurrent write load.

Add _acquire_singleton_lock(): an exclusive, non-blocking fcntl.flock at the
machine-global kanban root (kanban_home()/kanban/.dispatcher.lock — the board is
shared across profiles by design, so this serialises every gateway, not just one
profile). The first gateway to start its dispatcher holds the lock for its
process lifetime; any other gateway finds it contended, logs, and skips
dispatching while still running for messaging. Falls back to config-only control
on non-POSIX or filesystems without flock.

This is more robust than a per-profile guard because the documented model is
"one dispatcher sweeps all boards" — the contention is across profiles, not just
within one. Closes #41448.

Test: lock is exclusive (held, then contended while held, then held again after
release).
2026-06-19 07:35:33 -07:00
..
acp feat(gateway): inject stable human-readable message timestamps 2026-06-16 15:49:59 -07:00
acp_adapter feat(azure-foundry): add Microsoft Entra ID auth 2026-05-18 10:14:38 -07:00
agent feat(gateway): multiplex phase 2 — fail-closed profile credential isolation (Workstream A) 2026-06-19 07:34:15 -07:00
cli feat(billing): /billing terminal billing — interactive TUI + CLI client (#45449) 2026-06-19 01:53:32 +05:30
cron fix: complete cron jobs lock salvage 2026-06-15 06:29:00 -07:00
docker Harden hosted Docker install tree against self-modification (#47490) 2026-06-18 09:09:21 +10:00
e2e fix(gateway): include replied-to media attachments (#46107) 2026-06-14 04:51:50 -07:00
fakes
fixtures/plugins/example-dashboard/dashboard feat(dashboard): nous-blue theme, bulk sessions, schedule picker (#37383) 2026-06-02 12:37:40 -04:00
gateway fix(kanban): machine-global singleton lock for the embedded dispatcher (#41448) 2026-06-19 07:35:33 -07:00
hermes_cli fix(cli): default cli_refresh_interval to 1.0 to keep status bar alive (#49087) 2026-06-19 07:35:06 -07:00
hermes_state test: narrow db._conn before raw SQL so ty stops flagging None-union access 2026-06-18 16:04:58 -05:00
honcho_plugin chore(honcho): replace example Telegram UID with placeholder 2026-06-11 15:06:07 -04:00
integration refactor(gateway): migrate Home Assistant adapter to bundled plugin 2026-06-06 11:46:24 -07:00
openviking_plugin fix(openviking): guard empty tool_id in batch skip set; reuse env_var_enabled 2026-06-19 13:53:39 +05:30
plugins fix(openviking): preserve structured sync attribution 2026-06-19 15:23:41 +08:00
providers fix(models): pass model.base_url to fetch_models in /model picker 2026-06-16 13:09:40 -07:00
run_agent fix(agent): aggregate anthropic aux calls via stream 2026-06-19 17:32:13 +05:30
scripts fix(skills-hub): stop shipping a degenerate index when GitHub taps collapse (#42347) 2026-06-08 15:21:28 -07:00
skills fix(google-workspace): fall back to uv when venv has no pip (#39516) 2026-06-05 13:30:02 +10:00
stress chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
tools feat(tts): add xAI TTS speed and optimize_streaming_latency config knobs 2026-06-19 07:26:56 -07:00
tui_gateway fix(model): persist /model switch by default across sessions 2026-06-19 07:07:06 -07:00
website feat(skills): fix browse cap, add source links + copy buttons + category cleanup (#37143) 2026-06-01 19:52:28 -07:00
__init__.py
conftest.py test(windows): run pytest-timeout in thread mode on Windows 2026-06-19 06:31:56 -07:00
run_interrupt_test.py
test_account_usage.py
test_assistant_ui_tap_compat.py test(deps): guard @assistant-ui cluster on one tap version 2026-06-15 11:55:02 -04:00
test_atomic_replace_symlinks.py fix(utils): copy fallback for atomic replace across devices (#43852) 2026-06-13 14:50:05 -07:00
test_base_url_hostname.py
test_batch_runner_checkpoint.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_bitwarden_secrets.py fix(bitwarden): prevent zip-slip path traversal when extracting bws binary (#40569) 2026-06-06 18:33:44 -07:00
test_cli_file_drop.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_cli_manual_compress.py fix(tests): catch up six stale tests after compression/aux/kanban changes (#28465) 2026-05-18 21:43:59 -07:00
test_cli_skin_integration.py
test_ctx_halving_fix.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_dashboard_sidecar_close_on_disconnect.py fix(dashboard): scope chat sidebar model card to selected profile (#46665) 2026-06-15 12:50:19 -04:00
test_desktop_electron_pin.py fix(desktop): resolve electronDist dynamically + self-heal blocked installs (supersedes #48081/#48082) (#48091) 2026-06-17 18:48:35 -05:00
test_desktop_mac_entitlements.py test(desktop): assert macOS device entitlements are inherited 2026-06-03 07:32:00 +07:00
test_dispatch_session_id.py fix(dispatch): forward session_id into registry.dispatch (#28479) 2026-06-14 00:27:59 -04:00
test_docker_home_override_scripts.py Repair cron ownership on container restart (#41976) 2026-06-10 15:32:34 +10:00
test_docker_stage2_browser_discovery.py fix(docker): discover Playwright headless_shell browser (#35717) 2026-06-01 16:06:44 +10:00
test_docker_webui_install_surface.py fix(docker): support WebUI installs from read-only sources (#48541) 2026-06-19 10:52:16 +10:00
test_dockerfile_tini_compat_shim.py fix(docker): add /usr/bin/tini compatibility shim for legacy wrappers (#34192) (#34382) 2026-06-01 13:32:55 +10:00
test_empty_model_fallback.py test(models): guard Nous silent default against expensive-flagship escalation 2026-06-05 02:54:34 -07:00
test_empty_session_hygiene.py fix: in-memory transcript blocks empty-session prune 2026-06-10 17:37:34 -07:00
test_env_loader_secret_sources.py fix(secrets): only apply external secrets once per HERMES_HOME per process (#32271) 2026-05-25 15:18:55 -07:00
test_evidence_store.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_gateway_streaming_nested_config.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_get_tool_definitions_cache_isolation.py fix(gateway): close residual memory-leak sites under heavy scheduled workload 2026-06-08 06:32:42 -07:00
test_hermes_bootstrap.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_hermes_constants.py fix(cli): detect containerd/CRI cgroup-v2 containers in is_container() (#47131) 2026-06-17 12:11:31 +10:00
test_hermes_home_profile_warning.py
test_hermes_logging.py fix(logging): alias RotatingFileHandler to concurrent-log-handler (salvage #44921) (#46794) 2026-06-17 15:39:04 -05:00
test_hermes_state.py test(sessions): cover title reclaim across a compression lineage 2026-06-19 17:36:18 +05:30
test_hermes_state_compression_locks.py fix(compression): prevent session-id fork from concurrent compressions (#34351) 2026-05-28 21:40:39 -07:00
test_hermes_state_wal_fallback.py fix(kanban): skip redundant WAL pragma on already-WAL connections 2026-05-27 14:31:55 -07:00
test_honcho_client_concurrency.py fix(plugins): thread-safe lazy-singleton helpers; fix honcho TOCTOU (#24759) (#42150) 2026-06-08 09:35:22 -07:00
test_honcho_client_config.py fix(honcho): harden self-hosted setup paths 2026-05-29 22:29:48 -07:00
test_honcho_session_context.py fix(honcho): align user context peer perspective 2026-05-27 10:49:33 -07:00
test_honcho_startup_fail_open.py fix: make Honcho startup fail open 2026-06-01 20:13:42 -07:00
test_install_no_initial_commit.py fix(install): move broken checkout aside instead of deleting it 2026-06-08 02:18:21 -07:00
test_install_ps1_native_stderr_eap.py fix(install): fail fast when uv venv genuinely fails under relaxed EAP 2026-06-18 22:11:35 +05:30
test_install_ps1_uv_powershell_host.py test(install): lock uv installer to a resolved PowerShell host 2026-06-18 16:26:34 +07:00
test_install_sh_browser_install.py
test_install_sh_install_method_stamp.py fix(update): scope install-method stamp to the code tree, not $HERMES_HOME (#48188) 2026-06-18 14:14:41 +10:00
test_install_sh_node_global_prefix.py fix(install): repair existing managed-Node global prefix on re-run 2026-06-14 17:34:11 +07:00
test_install_sh_pythonpath_sanitization.py
test_install_sh_root_fhs_uv_python_path.py test(install): harden uv-python-path regression test against future drift 2026-05-27 13:55:51 -07:00
test_install_sh_setup_wizard_tty_probe.py
test_install_sh_symlink_stomp.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_install_sh_termux_network_prereqs.py
test_install_unmerged_index.py test(installer): regression for unmerged-index update failure 2026-06-13 05:19:44 -07:00
test_ipv4_preference.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_lazy_session_regressions.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_lint_config.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_live_system_guard_self_test.py
test_mcp_serve.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_mini_swe_runner.py
test_minimax_model_validation.py
test_minimax_oauth.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_minisweagent_path.py
test_model_forces_max_completion_tokens.py fix(params): send max_completion_tokens for newer OpenAI families on custom endpoints 2026-06-09 23:22:10 -07:00
test_model_picker_scroll.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_model_tools.py feat(middleware): add adaptive execution intercepts 2026-06-03 11:22:06 -07:00
test_model_tools_async_bridge.py fix(web): run URL SSRF checks off the event loop in async paths 2026-06-04 18:04:47 -07:00
test_ollama_num_ctx.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_output_cap_parsing.py test(agent): cover char-based output-cap overflow parsing (#42741) 2026-06-09 03:17:12 -07:00
test_package_json_lazy_deps.py
test_packaging_metadata.py feat(mcp-catalog): add official Unreal Engine 5.8 MCP server 2026-06-18 09:16:40 -07:00
test_plugin_skills.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_plugin_utils.py fix(plugins): thread-safe lazy-singleton helpers; fix honcho TOCTOU (#24759) (#42150) 2026-06-08 09:35:22 -07:00
test_process_loop_event_loop_warning.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_project_metadata.py fix(deps): align anthropic extra pin with lazy pin + guard whole pin surface (#42335) 2026-06-08 12:11:54 -07:00
test_retry_utils.py
test_run_tests_parallel.py fix(ci): remove pytest-timeout, use per-file timeout only 2026-06-12 13:42:42 -04:00
test_sanitize_tool_error.py
test_slash_worker_watchdog.py feat(slash-worker): self-terminate on parent death via create_time watchdog 2026-06-08 07:03:12 -07:00
test_sql_injection.py
test_state_db_malformed_repair.py fix(state.db): recover from malformed sqlite_master so hidden sessions reappear (#43149) 2026-06-09 18:49:08 -05:00
test_subprocess_home_isolation.py fix: make profile subprocess HOME policy explicit 2026-06-14 03:20:21 -07:00
test_termux_all_extra_compat.py
test_timezone.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_toolset_distributions.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_toolsets.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_trajectory_compressor.py fix(research): keep tool_call/tool_response pairs intact when compressing trajectories 2026-06-07 05:01:27 -07:00
test_trajectory_compressor_async.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_transform_llm_output_hook.py
test_transform_tool_result_hook.py test: stub has_hook in transform_tool_result hook tests 2026-06-03 06:36:46 -07:00
test_tui_gateway_server.py test: narrow db._conn before raw SQL so ty stops flagging None-union access 2026-06-18 16:04:58 -05:00
test_tui_gateway_ws.py feat(desktop): composer status stack, live subagent windows, editable prompts (#44630) 2026-06-12 08:30:06 -05:00
test_tui_mcp_late_refresh.py fix(tui): refresh tool snapshot when MCP discovery lands after agent build (#48403) 2026-06-18 05:41:23 -07:00
test_utils_truthy_values.py
test_web_server.py refactor(desktop): use port 0 for ephemeral port discovery instead of PortPool reservation 2026-06-12 14:02:19 -04:00
test_wheel_locales_e2e.py fix(packaging): ship locales/ i18n catalogs in wheel, sdist, and Nix (#38383) 2026-06-03 12:00:27 -07:00
test_yuanbao_integration.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_yuanbao_markdown.py
test_yuanbao_pipeline.py feat(Yuanbao): support wechat forward msg (#43508) 2026-06-12 02:06:47 -07:00
test_yuanbao_proto.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
test_yuanbao_shutdown.py fix(yuanbao): bound ws.close() so an idle server can't stall shutdown ~5s (#40607) 2026-06-07 17:49:38 -07:00