getLastChar was checking the last character of the full event.prompt,
which includes Conversation/Sender metadata blocks appended by OpenClaw
after the actual message. This meant end symbols like 🔚 at the end of
the message body were invisible — the last char was always backtick or
whitespace from the metadata JSON block.
Fix: strip trailing '(untrusted metadata)' blocks before extracting
the last character. This only affects non-humanList senders (humanList
senders bypass end symbol check via human_list_sender reason).
1. DM bypass: when neither senderId nor channelId can be extracted from
the prompt (DM sessions lack untrusted conversation info), skip the
no-reply gate and allow the message through with end-marker injection.
2. Tool visibility: change whispergateway_tools registration from
optional=true to optional=false so all agents can see the tool
without needing explicit tools.allow entries.