- WeComBotSender.resolveWebhookUrl: use custom URL as-is when no %s placeholder
- WeComBotSender: treat unparseable/blank response body as failure
- ConversationService.isAccountCompatibleWithConversation: ignore scene for single chats
- SendService.selectSendAccountCandidates: apply accountTypes filter for non-conversation records
- SendService: replace account type magic numbers with AccountType constants
- WeComChannelAdapter: use AccountType.WECOM_BOT.getCode() instead of literal 6
- admin-web Conversation.vue: fallback to channelType filter when scene is unset
- add tests for single-chat null scene, webhook_url propagation, and custom URL without %s