- Fix channelId extraction: ctx.channelId is platform name ('discord'), not
the Discord channel snowflake. Now extracts from conversation_label field
('channel id:123456') and sessionKey fallback (':channel:123456').
- Fix extractDiscordChannelId: support 'discord:channel:xxx' format in
addition to 'channel:xxx' for conversationId/event.to fields.
- Fix sender identification in message_received: event.from returns channel
target, not sender ID. Now uses event.metadata.senderId for humanList
matching so human messages correctly reset turn order.
- Fix per-channel turn order: was using all server-wide bot accounts from
bindings, causing deadlock when turn landed on bots not in the channel.
Now dynamically tracks which bot accounts are seen per channel via
message_received and only includes those in turn order.
- Always save sessionChannelId/sessionAccountId mappings in before_model_resolve
regardless of turn check result, so downstream hooks can use them.
- Add comprehensive debug logging to message_sent hook.
- Add sessionAccountId Map to track sessionKey -> accountId
- Save accountId in before_model_resolve when resolving accountId
- Use sessionChannelId/sessionAccountId fallback in before_message_write
- Add sessionChannelId Map to track sessionKey -> channelId
- Save channelId in before_model_resolve when we have derived.channelId
- Fix message_sent to use sessionChannelId fallback when ctx.channelId is undefined
- Add debug logging to message_sent
- Remove async/await from before_message_write hook
- Use fire-and-forget for sendModeratorMessage (void ... .catch())
- OpenClaw's before_message_write is synchronous, not async