Files
hermes-agent/tests/tools/test_delegate_sync_failure_echo_policy.py
Victor Kyriazakos cd3de040ab feat(notifications): opt-in suppression of user-channel warning notifications
Squash of the 54 commits on victor-kyriazakos:feat/user-channel-warning-suppression
(PR #112302, head f45c640e55) so the contributor's authorship survives a rebase-merge;
the commits interleave with a cron delivery-ledger rework that the salvage removes in
follow-up commits, so per-commit cherry-picks were not practical.

Adds display.suppress_warning_notifications (global + per-platform, default false):
one resolver (gateway/warning_notifications.py), BasePlatformAdapter.emit_warning /
emit_media_warning / warning_text, a notification_category classification carried
through wakes, queues and persistence, and render/present boundaries for CLI/TUI.
2026-09-18 01:43:35 +05:30

48 lines
2.6 KiB
Python

"""Salt R11-B1: synchronous child failure echo above the CLI spinner is an automatic diagnostic presentation
and honors display.suppress_warning_notifications under the parent's turn snapshot; the child result and the
relayed subagent.complete event are never gated."""
import json
import pytest
def configure(home, setting, monkeypatch):
home.mkdir(exist_ok=True)
monkeypatch.setenv('HERMES_HOME', str(home))
(home/'config.yaml').write_text(json.dumps({'display': {} if setting is None else {'suppress_warning_notifications':setting}}))
def test_sync_failure_real_run_to_spinner_three_modes(tmp_path, monkeypatch):
from tools.delegate_tool import _run_single_child
from tools.delegate_tool_progress import _build_child_progress_callback
from agent.notification_presentation import notification_policy_snapshot
from tests.tools.test_delegate_output_schema import _StubChild, _StubParent
rows=[]
for setting in (None,False,True):
configure(tmp_path/f'sync-{setting}',setting,monkeypatch)
import io
from contextlib import redirect_stdout
from agent.display import KawaiiSpinner
from agent.notification_presentation import notification_config_snapshot
buffer=io.StringIO();events=[]
parent=_StubParent();parent.session_id='parent'
with redirect_stdout(buffer):parent._delegate_spinner=KawaiiSpinner('delegating')
parent.tool_progress_callback=lambda *a,**kw:events.append({'args':a,'kwargs':kw})
child=_StubChild([])
def fail(**kwargs):raise RuntimeError('SYNC_REAL_CHILD_CRASH')
child.run_conversation=fail
child.tool_progress_callback=_build_child_progress_callback(0,'actual failing child',parent)
config=notification_config_snapshot()
assert config['display'].get('suppress_warning_notifications') is setting
with notification_policy_snapshot(parent,'cli',config):
result=_run_single_child(0,'actual failing child',child,parent)
assert result['status'] in ('error','failed') and 'SYNC_REAL_CHILD_CRASH' in str(result)
rows.append({'setting':setting,'lines':buffer.getvalue().splitlines(),'events':events,'result':result})
# absent/false: legacy echo present; true: echo suppressed. Result and relayed event untouched in all modes.
assert any('SYNC_REAL_CHILD_CRASH' in s for s in rows[0]['lines']), rows[0]
assert any('SYNC_REAL_CHILD_CRASH' in s for s in rows[1]['lines']), rows[1]
assert not any('SYNC_REAL_CHILD_CRASH' in s for s in rows[2]['lines']), rows[2]
for row in rows:
assert any(e['args'][0] == 'subagent.complete' for e in row['events']), row['events']