Skip to content

fix: include pattern description and alternatives in denial messages#13

Merged
juniperbevensee merged 5 commits into
mainfrom
fix/denial-message-includes-pattern-and-alternatives
Jun 1, 2026
Merged

fix: include pattern description and alternatives in denial messages#13
juniperbevensee merged 5 commits into
mainfrom
fix/denial-message-includes-pattern-and-alternatives

Conversation

@juniperbevensee

Copy link
Copy Markdown
Collaborator

Summary

  • Denial messages from check_all_command_guards now include combined_desc (tirith findings + pattern info) so the LLM knows WHAT was blocked
  • Suggests concrete alternatives (download-then-process, jq, native HTTP libs) instead of just "do not retry"
  • Fixes agent retry loops where they'd keep hitting the same block with different URLs because they didn't know what pattern triggered it

Cherry-picked from hermes-swarm 13030af1f. Adapted to the public fork's code structure.

Test plan

  • tests/gateway/test_approve_deny_commands.py — 21/21 pass
  • Deploy and verify OSINT agent stops retrying blocked curl | python3 patterns

🤖 Generated with Claude Code

When check_all_command_guards denied a command (via gateway or CLI),
the LLM only saw generic "BLOCKED" text without knowing WHAT pattern
triggered the block or what to do instead. This caused agents to retry
the same dangerous pattern (e.g. curl | python3) with different URLs,
hitting the same block repeatedly.

Now the denial message includes the combined_desc (tirith findings +
pattern info) and suggests concrete alternatives: download-then-process,
jq, or native HTTP libraries.

Cherry-picked from hermes-swarm 13030af1f.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 29, 2026

Copy link
Copy Markdown

🔎 Lint report: fix/denial-message-includes-pattern-and-alternatives vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9398 on HEAD, 9397 on base (🆕 +1)

🆕 New issues (1):

Rule Count
unresolved-import 1
First entries
tests/gateway/test_approval_admin_gating.py:15: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`

✅ Fixed issues: none

Unchanged: 4974 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

juniperbevensee and others added 4 commits May 29, 2026 14:20
The /approve and /deny handlers had no authorization check — any user
who could message the bot could approve dangerous commands. Now checks
approvals.admin_only config (defaults to true) and uses slash_access
policy to verify admin status before allowing approve/deny.

Covers gateway text commands, Telegram button callbacks, and adds
_is_user_admin() to TelegramAdapter with HSM policy + ALLOWED_USERS
fallback (fail-closed).

Adapted from hermes-swarm a9c36a5d9 for the public fork's architecture.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests asserted old message shape ("NOT consented", "rephrase") that no
longer exists after the denial message fix. Updated to match the new
contract ("Do NOT retry", "different approach"). Added juniperbevensee
to AUTHOR_MAP for attribution check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- quick_commands: add session_store mock to GatewayRunner setup via
  shared _init_runner helper — pre_gateway_dispatch hook now accesses
  it before the quick command branch
- noise_filter: update test_non_telegram_status_is_unchanged to expect
  Discord messages to be suppressed, matching the intentional change in
  61c7b4e that extended filtering to all chat platforms (not just
  Telegram)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MagicMock auto-creates truthy attributes when accessed, which caused
_handle_message to enter the observe_only branch (returns None) instead
of reaching the quick command dispatch. Setting internal, observe_only,
media_urls, media_types, message_id, and channel_prompt explicitly on
the mock event fixes the root cause of the shard-3 CI failures.

Also adds _running_agents_ts, _update_prompt_pending, _draining,
adapters, pairing_store, and related attrs to _init_runner — the
interceptor gauntlet before quick commands needs them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@juniperbevensee juniperbevensee merged commit 0961123 into main Jun 1, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant