Webhook (Flask) and polling (momo-telegram-bot) consumed the same
Telegram update_id, causing /menu callbacks to fire twice. Add a
shared dedup module backed by telegram_update_dedup table (300s TTL,
60s cleanup) with in-memory fallback, wired into both paths.
Polling launcher now skips startup when webhook is configured to
prevent dual-consumption at the source.
38 tests across webhook, menu keyboards, telegram_api, dedup guard,
and trend bot service.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>