diff --git a/gateway/display_config.py b/gateway/display_config.py index 78e8bc9afa..832f5cb2f2 100644 --- a/gateway/display_config.py +++ b/gateway/display_config.py @@ -79,7 +79,9 @@ _PLATFORM_DEFAULTS: dict[str, dict[str, Any]] = { "discord": _TIER_HIGH, # Tier 2 — edit support, often customer/workspace channels - "slack": _TIER_MEDIUM, + # Slack: tool_progress off by default — Bolt posts cannot be edited like CLI; + # "new"/"all" spam permanent lines in channels (hermes-agent#14663). + "slack": {**_TIER_MEDIUM, "tool_progress": "off"}, "mattermost": _TIER_MEDIUM, "matrix": _TIER_MEDIUM, "feishu": _TIER_MEDIUM, diff --git a/tests/gateway/test_display_config.py b/tests/gateway/test_display_config.py index 2192d67bc9..07d5c82a5f 100644 --- a/tests/gateway/test_display_config.py +++ b/tests/gateway/test_display_config.py @@ -186,12 +186,18 @@ class TestPlatformDefaults: assert resolve_display_setting({}, plat, "tool_progress") == "all", plat def test_medium_tier_platforms(self): - """Slack, Mattermost, Matrix default to 'new' tool progress.""" + """Mattermost, Matrix, Feishu, WhatsApp default to 'new' tool progress.""" from gateway.display_config import resolve_display_setting - for plat in ("slack", "mattermost", "matrix", "feishu", "whatsapp"): + for plat in ("mattermost", "matrix", "feishu", "whatsapp"): assert resolve_display_setting({}, plat, "tool_progress") == "new", plat + def test_slack_defaults_tool_progress_off(self): + """Slack defaults to quiet tool progress (permanent chat noise otherwise).""" + from gateway.display_config import resolve_display_setting + + assert resolve_display_setting({}, "slack", "tool_progress") == "off" + def test_low_tier_platforms(self): """Signal, BlueBubbles, etc. default to 'off' tool progress.""" from gateway.display_config import resolve_display_setting @@ -241,7 +247,7 @@ class TestConfigMigration: }, }, } - config_path.write_text(yaml.dump(config)) + config_path.write_text(yaml.dump(config), encoding="utf-8") monkeypatch.setenv("HERMES_HOME", str(tmp_path)) # Re-import to pick up the new HERMES_HOME @@ -251,7 +257,7 @@ class TestConfigMigration: result = cfg_mod.migrate_config(interactive=False, quiet=True) # Re-read config - updated = yaml.safe_load(config_path.read_text()) + updated = yaml.safe_load(config_path.read_text(encoding="utf-8")) platforms = updated.get("display", {}).get("platforms", {}) assert platforms.get("signal", {}).get("tool_progress") == "off" assert platforms.get("telegram", {}).get("tool_progress") == "all" @@ -268,7 +274,7 @@ class TestConfigMigration: "platforms": {"telegram": {"tool_progress": "verbose"}}, }, } - config_path.write_text(yaml.dump(config)) + config_path.write_text(yaml.dump(config), encoding="utf-8") monkeypatch.setenv("HERMES_HOME", str(tmp_path)) import importlib @@ -276,7 +282,7 @@ class TestConfigMigration: importlib.reload(cfg_mod) cfg_mod.migrate_config(interactive=False, quiet=True) - updated = yaml.safe_load(config_path.read_text()) + updated = yaml.safe_load(config_path.read_text(encoding="utf-8")) # Existing "verbose" should NOT be overwritten by legacy "off" assert updated["display"]["platforms"]["telegram"]["tool_progress"] == "verbose" diff --git a/tests/gateway/test_verbose_command.py b/tests/gateway/test_verbose_command.py index c34167b2e4..c3743e5915 100644 --- a/tests/gateway/test_verbose_command.py +++ b/tests/gateway/test_verbose_command.py @@ -134,7 +134,7 @@ class TestVerboseCommand: """Cycling /verbose on Telegram doesn't change Slack's setting. Without a global tool_progress, each platform uses its built-in - default: Telegram = 'all' (high tier), Slack = 'new' (medium tier). + default: Telegram = 'all' (high tier), Slack = 'off' (quiet Slack default). """ hermes_home = tmp_path / "hermes" hermes_home.mkdir() @@ -161,8 +161,8 @@ class TestVerboseCommand: platforms = saved["display"]["platforms"] # Telegram: all -> verbose (high tier default = all) assert platforms["telegram"]["tool_progress"] == "verbose" - # Slack: new -> all (medium tier default = new, cycle to all) - assert platforms["slack"]["tool_progress"] == "all" + # Slack: off -> new (first /verbose cycle from quiet default) + assert platforms["slack"]["tool_progress"] == "new" @pytest.mark.asyncio async def test_no_config_file_returns_disabled(self, tmp_path, monkeypatch):