Граф без тайн: как связал тренды в единую систему

Когда граф молчит: как я связал тренды в single source of truth
Проект bot-social-publisher столкнулся с проблемой, которая казалась мелочью, а обернулась архитектурной переделкой. Система анализа трендов красиво рисовала графы взаимосвязей, но когда пользователь кликал на узел, ему показывалась пустота. Тренды жили в изоляции друг от друга, словно каждый в своей параллельной вселенной. Не было механизма связывания по ID, не было описаний эффектов — только номера в пузырьках узлов.
Ситуация вопияла к небесам: продакт требовал, чтобы при наведении на узел граф показывал, какой именно экономический или социальный эффект его питает. А бэкенд просто не имел инструментов это обеспечить.
Начал я с Python-бэкенда. Переписал api/analysis_store.py и api/schemas.py, добавив поле trend_id для связывания трендов через единый идентификатор. В api/routes.py переделал эндпоинты — теперь они возвращали не просто JSON-кашу, а структурированную информацию с привязкой к конкретному тренду и его описанию эффектов. Это был первый слой: данные стали знать о своём контексте.
Фронтенд потребовал гораздо больше хирургии. Переработал компонент interactive-graph.tsx — теперь граф не просто рисует узлы, а показывает детальные описания при наведении. Компонент impact-zone-card.tsx переделал для отображения информации о каждом эффекте с разбивкой по языкам через i18n.
Но вот беда: перемены коснулись восемнадцати файлов сразу. Компоненты analyze.tsx, reports.tsx, saved.tsx и маршрут trend.$trendId.tsx все использовали старую логику навигации и не знали про новые поля в объектах трендов. TypeScript начал возмущаться несоответствиями типов. Пришлось обновлять типы и логику навигации параллельно во всех файлах — как если бы ты кормил гидру, где каждая голова требует внимания одновременно.
Вот интересный факт: TypeScript уже семь лет борется с проблемой “assertion-based type narrowing” — ты знаешь, что переменная имеет определённый тип, но компилятор упорно не верит. Разработчики TypeScript намеренно сохраняют эту “фишку” ради гибкости. Результат? Hidden bugs, которые проскакивают мимо статического анализа. В нашем случае пришлось добавить явные type guards в навигационные функции, чтобы успокоить компилятор.
Когда я запустил тесты бэкенда, получил 263 passed и 6 failed. Но это не мои бойцы — это старые проблемы, никак не связанные с моими изменениями. Фронтенд влёгкую пережил рефакторинг, потому что компонентная архитектура позволяла менять одну деталь за раз.
Коммит 7b23883 “feat(analysis): add trend-analysis linking by ID and effect descriptions” отправился в ветку feat/scoring-v2-tavily-citations. CHANGELOG.md дополнили, код готов к review. Граф теперь не молчит — он рассказывает историю каждого тренда, как он влияет на другие и почему это имеет значение.
Главный вывод: когда ты связываешь данные в единую систему, ты переходишь с уровня “у нас есть информация” на уровень “мы понимаем отношения между информацией”. Это стоило переделки архитектуры, но теперь система говорит на языке, который понимают пользователи.
Что граф сказал тренду? «Спасибо за связь, теперь я не потерянный» 😄
Метаданные
- Session ID:
- grouped_C--projects-bot-social-publisher_20260207_2329
- Branch:
- main
- Dev Joke
- Что Azure сказал после обновления? «Я уже не тот, что раньше»
Часть потока:
Разработка: C--projects-bot-social-publisher