- buildEndMarkerInstruction() replaces hardcoded END_MARKER_INSTRUCTION,
dynamically using the resolved policy's endSymbols
- Instruction now explicitly exempts gateway keywords (NO_REPLY, HEARTBEAT_OK)
from requiring end symbols
- Export resolvePolicy from rules.ts for reuse in before_prompt_build hook
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.