BorisovAI

Блог

Публикации о процессе разработки, решённых задачах и изученных технологиях

Найдено 20 заметокСбросить фильтры
Новая функцияspeech-to-text

GitLab Pages выдал секреты: как мы чуть не залили артефакты в интернет

# Как мы защитили артефакты приватного проекта, но случайно выставили их в интернет Проект `speech-to-text` — это голосовой ввод для веб-приложения. Задача казалась стандартной: настроить автоматизированный релиз артефактов через CI/CD. Но когда я начал копать, обнаружилась забавная особенность GitLab Pages, которая чуть не стала залогом безопасности нашего проекта. ## Когда публичное скрывается за приватным Первым делом я исследовал варианты хранения и раздачи собранных ZIP-файлов. В репозитории всё приватное — исходники защищены, доступ ограничен. Проверил **GitLab Releases** — отличное решение, вот только возникла проблема: как скачивать артефакты с публичного фронтенда, если сам проект закрыт? Тогда я посмотрел на **GitLab Package Registry** — тоже приватный по умолчанию. Но потом наткнулся на странное: GitLab Pages генерирует статические сайты, которые всегда публичны *независимо от приватности самого проекта*. То есть даже если репо закрыт для всех, Pages будут доступны по ссылке для любого, кто её узнает. **Неожиданно выяснилось:** это не баг, а фича. Pages часто используют именно для этого — расшарить артефакты или документацию публично, не давая при этом доступ в репо. ## Как я построил конвейер Архитектура получилась такой: скрипт на Python собирает проект, упаковывает в ZIP и загружает в **GitLab Package Registry**. Затем я создал CI pipeline, который срабатывает на тег вида `v*` (семантическое версионирование). Pipeline скачивает ZIP из Package Registry, деплоит его на GitLab Pages (делает доступным по публичной ссылке), обновляет версию в Strapi и создаёт Release в GitLab. Для работы потребилась переменная `CI_GITLAB_TOKEN` с соответствующим доступом — её я забил в CI Variables с флагами *protected* и *masked*, чтобы она не оказалась в логах сборки. Версионирование жёсткое: версия указывается в `src/__init__.py`, оттуда её подхватывает скрипт при сборке. Архивы называются в стиле `VoiceInput-v1.0.0.zip`. ## Идея, которая в голову не пришла Интересный момент: изначально я беспокоился, что приватный проект станет помехой. На деле оказалось, что Pages — это идеальное решение для раздачи артефактов, которые не нужно прятать, но и не нужно давать доступ к исходникам. Классический сценарий для скачиваемых утилит, библиотек или сборок. Теперь релиз — это одна команда: `.\venv\Scripts\python.exe scripts/release.py`. Скрипт собирает, архивирует, загружает, пушит тег. А CI сам позаботится о Pages, Strapi и Release. 😄 Почему GitLab Pages пошёл в терапию? Потому что у него была сложная личная жизнь — он был публичным, но никто об этом не знал!

#claude#ai#python#git#api#security
Разработка: Speech to Text
8 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

От плоской базы к дереву версий: как переделать архитектуру анализов

# Когда один анализ становится деревом версий: история архитектурной трансформации Проект **bot-social-publisher** уже имел HTML-прототип интеллектуальной системы анализа трендов, но вот беда — архитектура данных была плоской, как блин. Одна версия анализа на каждый тренд. Задача звучала просто: сделать систему, которая помнит об эволюции анализов, позволяет углублять исследования и ветвить их в разные направления. Именно это отличает боевую систему от прототипа. Начал я со скучного, но критически важного — внимательно прочитал существующий `analysis_store.py`. Там уже жила база на SQLite, асинхронный доступ через **aiosqlite**, несколько таблиц для анализов и источников. Но это была просто полка, а не полнофункциональный архив версий. Первое, что я понял: нужна вертикаль связей между анализами. **Фаза первая: переделка схемы.** Добавил четыре колонки в таблицу `analyses`: `version` (номер итерации), `depth` (глубина исследования), `time_horizon` (временной диапазон — неделя, месяц, год) и `parent_job_id` (ссылка на родительский анализ). Это не просто поля — они становятся скелетом, на котором держится вся система версионирования. Когда пользователь просит «Анализируй глубже» или «Расширь горизонт», система создаёт новую версию, которая помнит о своей предшественнице. **Фаза вторая: переписывание логики.** Функция `save_analysis()` была примитивна. Переделал её так, чтобы она автоматически вычисляла номер версии — если анализируете тренд, который уже видели, то это версия 2, а не перезапись версии 1. Добавил `next_version()` для расчёта следующего номера, `find_analyses_by_trend()` для выборки всех версий тренда и `list_analyses_grouped()` для иерархической организации результатов. **Фаза третья: API слой.** Обновил Pydantic-схемы, добавил поддержку параметра `parent_job_id` в `AnalyzeRequest`, чтобы фронтенд мог явно указать, от какого анализа отталкиваться. Выписал новый параметр `grouped` — если его передать, вернётся вся иерархия версий со всеми связями. Вот тут началось интересное. Запустил тесты — один из них падал: `test_crawler_item_to_schema_with_composite`. Первым делом подумал: «Это я сломал». Но нет, оказалось, это *pre-existing issue*, не имеющий отношения к моим изменениям. Забавный момент: как легко можно записать себе проблему, которая была задолго до тебя. **Интересный факт о SQLite и миграциях.** В Python для SQLite нет ничего вроде Django ORM с его волшебством. Миграции пишешь вручную: буквально SQL-запросы в функциях. `ALTER TABLE` и точка. Это делает миграции прозрачными, понятными, предсказуемыми. SQLite не любит сложные трансформации, поэтому разработчики привыкли быть честными перед памятью и временем выполнения. Архитектура готова. Теперь система может обрабатывать сценарии, о которых шла речь в брифе: анализ разветвляется, углубляется, но всегда помнит свою родословную. Следующий этап — фронтенд, который красиво это выведет и позволит пользователю управлять версиями. Но это совсем другая история. 😄 Моя мораль: если SQLite говорит, что миграция должна быть явной — слушайте, потому что скрытая магия всегда дороже.

#claude#ai#python#git#api#security
8 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

Голосовой агент с памятью: как мы научили Claude работать асинхронно

# Голосовой агент встретил Claude Code: как мы строили персистентного помощника Когда я открыл проект **voice-agent**, передо мной стояла классическая, но нетривиальная задача: создать полноценного AI-помощника, который бы работал не просто с текстом, но и с голосом, интегрировался в REST API на бэкенде и взаимодействовал с фронтенд-компонентами Next.js. Python на бэкенде, JavaScript на фронте — привычная современная архитектура. Но главный вызов был совсем не в технологиях. **Первым делом я осознал, что это не просто ещё один chatbot.** Нужна была система, которая разбирается в голосовых командах, работает с асинхронными операциями, выполняет команды на файловой системе, интегрируется с документацией и может честно сказать: «Вот тут мне нужна помощь». Начал я с архитектуры — структурировал проект так, чтобы каждый слой отвечал за своё: документация по TMA в `docs/tma/`, структурированный журнал ошибок в `docs/ERROR_JOURNAL.md`, разделение бэкенд-сервисов по функциям. Неожиданно выяснилось, что самая сложная часть — организация информационных потоков. Агент должен знать, где искать справку, как обрабатывать ошибки, когда обратиться к разработчику с уточняющим вопросом. Вот тогда я понял: нужна **встроенная память** — не просто контекст текущей сессии, но настоящее хранилище фактов. Подключил aiosqlite для асинхронного доступа к SQLite, и агент получил возможность запоминать информацию о пользователе, его предпочтениях, даже что-то вроде персональных данных, типа страны проживания. Это открыло целый набор возможностей для персонализации. Агент стал не просто отвечать, а *узнавать* пользователя: «Ты из России? Значит, зафиксирую это и буду учитывать при рекомендациях». **Интересный факт:** мы живём в эпоху ускорения AI-разработок. Deep Learning boom, который начался в 2010-х, в 2020-х годах превратился в настоящий взрыв доступности. Раньше создать сложную AI-систему мог только эксперт с PhD по математике. Теперь разработчик может за выходные собрать полноценного помощника с памятью, асинхронностью и интеграциями — и это стало нормой. **В итоге получилось приложение, которое:** - принимает голосовые команды и преобразует их в действия; - выполняет операции на бэкенде без блокировки интерфейса (спасибо async/await); - запоминает контекст и факты о пользователе; - самостоятельно диагностирует ошибки через структурированный журнал; - честно говорит, когда нужна помощь человека. Дальше впереди оптимизация, расширение функционала, интеграция с реальными API. Проект показал главное: AI-агенты работают лучше всего, когда они знают о своих ограничениях и не пытаются играть в непробиваемого супергероя. Мигрировать с Linux — всё равно что менять колёса на ходу. На самолёте. 😄

#claude#ai#python#javascript#git#api
8 февр. 2026 г.
Новая функцияC--projects-ai-agents-voice-agent

Голосовой агент встретился с Claude Code: как сделать AI помощника

# Claude Code встретился с голосовым агентом: история первого контакта Когда я начинал проект **voice-agent**, передо мной стояла интересная задача: создать полноценного помощника, который мог бы работать с голосом, текстом и интеграциями. Python на бэкенде, Next.js на фронте — классическая современная архитектура. Но главный вызов был не в технологиях, а в самой идее: как сделать AI-агента, который будет не просто отвечать на вопросы, но и запоминать контекст, выполнять команды и развиваться со временем? Первым делом я осознал, что это не просто ещё один chatbot. Нужна была система, которая: - разбирается в голосовых командах; - работает с REST API на бэкенде; - интегрируется с фронтенд-компонентами Next.js; - может отлаживать ошибки через структурированный журнал. Начал я с архитектуры. Создал структуру проекта, где каждый компонент отвечает за своё: документация в `docs/tma/`, журнал ошибок в `docs/ERROR_JOURNAL.md`, специализированные бэкенд-сервисы для разных функций. Python даёт нам гибкость с асинхронными вызовами, а Next.js — скорость и удобство на фронте. Неожиданно выяснилось, что самая сложная часть — это не сама реализация функций, а организация информационных потоков. Агент должен знать, где искать справку, как обрабатывать ошибки, когда нужно обратиться к разработчику с уточняющим вопросом. Вот тут и пригодилась идея встроенной памяти — SQLite база, где хранится контекст взаимодействия и история команд. **Интересный факт**: мы находимся в самом разгаре AI boom, который ускорился в 2020-х годах благодаря deep learning. Проекты вроде voice-agent — это как раз результат того, что технологии машинного обучения стали доступнее, и разработчики могут создавать сложные AI-системы без необходимости быть экспертами в математике глубокого обучения. В итоге получилось приложение, которое может: - принимать голосовые команды и преобразовывать их в действия; - выполнять асинхронные операции на бэкенде; - запоминать информацию о пользователе (когда я понял, что в БД можно хранить факты типа «пользователь из России», это открыло целый набор возможностей для персонализации); - самостоятельно диагностировать проблемы через структурированный журнал ошибок. Дальше — только интеграции, оптимизация производительности и расширение функционала. Проект показал, что AI-агенты работают лучше всего, когда они знают о своих ограничениях и честно говорят пользователю, когда нужна помощь человека. Почему Apache считает себя лучше всех? Потому что Stack Overflow так сказал 😄

#claude#ai#python#javascript#git#api
Разработка: Voice Agent
8 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

Граф анализа заговорил: как связали тренды с историями их появления

# Когда граф анализа вдруг начал рассказывать истории Работаю над проектом **trend-analysis** — это система, которая ловит тренды в данных и выявляет причинно-следственные связи. Звучит модно, но вот проблема: аналитик видит красивый граф с выявленным трендом, но не может понять, *откуда* вообще это взялось. Анализы существовали сами по себе, узлы графа — сами по себе. Полная изоляция. Нужно было соединить всё в единую систему. Задача была чёткой: добавить возможность связывать анализы напрямую с конкретными трендами через их ID. Звучит просто на словах, но касалось сразу нескольких слоёв архитектуры. **Начал с Python-бэкенда.** Переписал `api/analysis_store.py` и `api/schemas.py`, добавив поле `trend_id`. Теперь при создании анализа система знает, какой именно тренд его инициировал. Потом переделал эндпоинты в `api/routes.py` — они теперь возвращали не просто JSON, а структурированные данные с информацией о причинно-следственных цепочках (`causal_chain` в кодовой базе). Вытащил рассуждения (`rationale`), которыми система объясняла связи, и превратил их в читаемые описания эффектов. Фронтенд потребовал хирургии посерьёзнее. Переработал компонент `interactive-graph.tsx` — граф теперь не просто рисует узлы, а при наведении показывает детальные описания. Добавил поле `description` к каждому узлу графа. Компонент `impact-zone-card.tsx` переделал с поддержкой многоязычности через `i18n` — карточки зон влияния и типы графиков теперь переводятся на разные языки. **Вот где начались проблемы**: эти изменения коснулись восемнадцати файлов одновременно. Компоненты `analyze.tsx`, `reports.tsx`, `saved.tsx` и маршрут `trend.$trendId.tsx` все использовали старую логику навигации и не знали про новые поля. TypeScript начал возмущаться несоответствиями типов. Пришлось обновлять типы параллельно во всех местах — как кормить гидру, где каждая голова требует еды одновременно. **Любопытный факт:** TypeScript *сознательно* сохраняет проблему «assertion-based type narrowing» ради гибкости — разработчики могут форсировать нужный им тип, даже если компилятор не согласен. Это даёт свободу, но также открывает двери для hidden bugs. В нашем случае пришлось добавить явные type guards в навигационные функции, чтобы успокоить компилятор и избежать ошибок во время выполнения. Тесты бэкенда вернули 263 passed и 6 failed — но это старые проблемы, никак не связанные с моими изменениями. Фронтенд пережил рефакторинг гораздо спокойнее благодаря компонентной архитектуре. **В итоге** граф перестал молчать. Теперь он рассказывает полную историю: какой тренд выявлен, почему он важен, как он влияет на другие явления и какова цепочка причин. Коммит отправился в review с подробным CHANGELOG. Дальше план — добавить сохранение этих связей как правил, чтобы система сама училась предсказывать новые влияния. 😄 Почему граф анализа пошёл к психологу? Потому что у него было слишком много глубоких связей.

#claude#ai#python#javascript#git#api#security
8 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

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

# Когда граф молчит: как я связал тренды в 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. Граф теперь не молчит — он рассказывает историю каждого тренда, как он влияет на другие и почему это имеет значение. Главный вывод: когда ты связываешь данные в единую систему, ты переходишь с уровня "у нас есть информация" на уровень "мы понимаем отношения между информацией". Это стоило переделки архитектуры, но теперь система говорит на языке, который понимают пользователи. Что граф сказал тренду? «Спасибо за связь, теперь я не потерянный» 😄

#claude#ai#python#javascript#git#api#security
8 февр. 2026 г.
Новая функцияtrend-analisis

Граф-описания трендов: от изоляции данных к интерактивной связности

# Связываем тренды воедино: как я добавил граф-описания в trend-analysis Проект **trend-analysis** — это система анализа данных о трендах с визуализацией связей между ними. Задача была на первый взгляд простой: добавить возможность связывать тренды по ID и показывать описания эффектов прямо на интерактивном графике. Но в деталях, как всегда, скрывалась вся сложность. **Как всё начиналось** Возникла проблема: при клике на узел в графе пользователю было непонятно, какой именно эффект описывается. А в API не было механизма для связывания трендов между собой — каждый тренд жил в изоляции. Получался красивый граф, но бесполезный. Первым делом я обновил бэкенд на Python. Модифицировал `api/analysis_store.py` и `api/schemas.py`, добавив поле `trend_id` для связывания и передачи описаний эффектов. В `api/routes.py` переписал эндпоинты, чтобы они возвращали не просто данные, а структурированную информацию с привязкой к конкретным трендам. На фронтенде в компоненте `interactive-graph.tsx` пришлось переработать логику отображения. Теперь граф не просто рисует узлы — он показывает описания эффектов при наведении. Компонент `impact-zone-card.tsx` я переделал для отображения детальной информации о каждом эффекте. **Неожиданные повороты** Тут выскочила проблема с TypeScript: несколько компонентов (`analyze.tsx`, `reports.tsx`, `saved.tsx`, `trend.$trendId.tsx`) использовали старую навигацию и не знали про новые поля. Пришлось обновить типы и логику навигации во всех этих файлах одновременно. Также выяснилось, что интернационализация (i18n файлы) отставала — переводы для новых полей эффектов ещё не были добавлены. Пришлось синхронизировать три языка одновременно. **Любопытный факт**: За семь лет существования TypeScript так и не решили проблему "assertion-based type narrowing" — когда ты уверен, что переменная имеет определённый тип, но компилятор не верит. Разработчики TypeScript намеренно сохраняют эту "особенность" для гибкости, хотя она часто приводит к скрытым ошибкам. В нашем случае пришлось добавить явные type guards в навигационные функции. **Финал** Все 18 файлов обновлены, документация (CHANGELOG.md) дополнена, тесты бэкенда пройдены (263 passed, 6 failed — старые проблемы, не связанные с моими изменениями). Коммит `7b23883` "feat(analysis): add trend-analysis linking by ID and effect descriptions" отправлен в ветку `feat/scoring-v2-tavily-citations`. MR можно создать, и система готова к review. Главный урок: когда переделываешь логику в системе с множеством связей (граф, навигация, i18n), нужно обновлять не одновременно, а слоями — сначала бэкенд, потом UI, потом тесты. Иначе придётся ходить по коду несколько раз. Что общего у тренд-анализа и поиска в Google? Оба работают, пока ты не начнёшь понимать, как они устроены 😄

#claude#ai#python#javascript#git#api
Разработка: Trend Analisis
8 февр. 2026 г.
Новая функцияtrend-analisis

Связь вместо хаоса: как мы научили анализы разговаривать с трендами

# Как мы научили систему анализа трендов видеть связи между явлениями Работаем над проектом **trend-analysis** — это система, которая анализирует тренды в данных и выявляет причинно-следственные связи. Всё интересно, но вот беда: когда аналитик хочет глубже погрузиться в конкретный тренд, система не могла его за ручку взять и показать, откуда вообще взялась эта информация. Анализы существовали сами по себе, графики — сами по себе. Нужно было связать их воедино. Задача была чёткой: добавить возможность связывать анализы напрямую с конкретными трендами по ID. Звучит просто, но это касалось сразу нескольких слоёв архитектуры. **Первым делом расширили API запросов**: добавили параметр `trend_id` в запрос к анализу. Теперь при создании анализа система знает, какой именно тренд его вызвал. Логично, но раньше этой связи просто не было. Дальше — самая интересная часть. Нужно было хранить эту информацию, поэтому добавили поле `trend_id` в таблицу `analyses`. Но одного сохранения мало — нужно было ещё и *по-человечески* отображать результат. Началось с описаний эффектов: когда система выявляет причинно-следственную связь (это называется `causal_chain` в кодовой базе), она может объяснить, *почему* один фактор влияет на другой. Мы вытащили эти рассуждения (`rationale`) и превратили их в читаемые описания эффектов — теперь они отображаются прямо на интерактивном графе. Но вот неожиданность: граф строится из узлов, а узлы — это просто точки без контекста. Добавили поле `description` к каждому узлу, чтобы при наведении мышкой пользователь видел, что это вообще за узел и на что он влияет. Мелкое изменение, но пользователям нравится. Потом пришлось разбираться с интернационализацией. Карточки зон влияния и типы графиков должны были переводиться на разные языки. Добавили `i18n` переводы — теперь система говорит с пользователем на его языке, а не на смеси английского и технических термов. Всё это потребовало фиксов в типах TypeScript для навигации по параметрам поиска — система должна была *знать*, какие параметры можно передавать и как они называются. Без этого была бы путаница с undefined и ошибки во время выполнения. **Вот интересный момент**: когда работаешь с причинно-следственными связями в данных, очень легко создать «спагетти-граф» — такой, где всё связано со всем, и пользователь теряется. Важный паттерн в таких системах — *скрывать сложность слоями*. Сначала показываешь главные узлы и связи, потом — при клике — раскрываешь подробности. Мы это учитывали при добавлении описаний. **В итоге**: система стала гораздо более связной. Теперь аналитик видит не просто скучную таблицу с анализами, а *историю* того, как конкретный тренд повлиял на другие явления, с объяснениями на его языке. Граф перестал быть набором непонятных точек и стал рассказывать. Обновили CHANGELOG, и задача легла в историю проекта. Следующий шаг — добавить возможность сохранять эти связи как правила, чтобы система сама училась предсказывать новые влияния. Но это уже совсем другая история. 😄 Почему граф анализа пошёл к психологу? Потому что у него было слишком много *глубоких связей*.

#git#commit#javascript#security
Разработка: Trend Analisis
8 февр. 2026 г.
Новая функцияtrend-analisis

Когда AI-консультанты становятся единственными, кто понимает вашу архитектуру

# Когда "переводчики AI" становятся профессией: каскад последствий, которые никто не ожидал Проект **trend-analysis** заставил меня посмотреть на явление AI-консультантов совсем с другой стороны. Задача была простой на словах: проанализировать вторичные последствия появления нового класса профессионалов — "AI translators", людей, которые берут готовые большие модели и адаптируют их под конкретные задачи компаний. Но когда начал копаться в причинно-следственных цепочках, понял: это айсберг, и видна только верхушка. **Первым делом** построил граф эффектов в ветке `feat/scoring-v2-tavily-citations`. Система должна была не просто перечислить проблемы, а проследить, *как они порождают друг друга*. Оказалось, что появление AI-translators — это не просто новая профессия, это спусковой крючок целого каскада трансформаций в экономике, организационной культуре и даже технологической архитектуре компаний. Неожиданно выяснилось: когда компании начинают полагаться на внешних "переводчиков" для интеграции AI, они одновременно отказываются от развития собственной экспертизы. Это создает долгосрочную зависимость. Консультанты становятся единственными, кто понимает, почему выбрана именно эта платформа, эта архитектура, эти интеграции. Результат? *Vendor lock-in*, но не в смысле контракта, а в смысле человеческого капитала. Параллельно запустилась вторая волна анализа: что будет, если данные для обучения AI тоже станут товаром, который нужно лицензировать? Здесь картина еще мрачнее. Транзакционные издержки настолько высокие, что выживут только агрегаторы — новые Getty Images, но для данных. Reddit, Stack Overflow, крупные издательства превратятся в брокеров информации. Малые стартапы просто не смогут позволить себе лицензировать столько контента. Но есть красивый контр-ход: когда лицензирование становится дорогим, AI-компании начнут инвестировать в синтетические данные и self-play методы — когда нейросеть обучает саму себя. Это снизит зависимость от человеческого контента, но создаст новый риск: AI, обученная преимущественно на машинном контенте, может полностью отойти от человеческих ценностей. На уровне геополитики картина становится совсем киберпанковской: государства начнут огораживать свои данные как стратегический ресурс. Китайские модели будут обучаться только на китайском контенте, европейские — на европейском. Глобальный AI разбивается на региональные версии, что усложнит международное сотрудничество и рост технологии в целом. Самое интересное: в этом хаосе появляется новая профессия — датные брокеры, эксперты по оценке стоимости контента для AI-обучения. Это может стать шансом для независимых создателей монетизировать свою работу без посредников... хотя бы временно. Проект показал, что технология — это не просто инструмент. Это сеть причинно-следственных связей, где каждое решение порождает десяток неожиданных последствий. И если не видеть этот граф целиком, мы просто пилим сук, на котором сидим. 😄 PHP — единственная технология, где «это работает» считается документацией.

#claude#ai#javascript#git
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияtrend-analisis

Когда AI-рынок переписывается быстрее, чем мы учимся

# Когда AI-специалист вдруг понимает, что весь рынок может переписаться за месяц Вчера сидел над проектом **trend-analysis** и случайно наткнулся на любопытную мысль: а что будет, если я начну думать не первым, а *вторым* порядком? То есть не просто "тенденция X" → "эффект Y", а выстраивать цепочки следствий по три шага вперёд? Задача была простой на вид — в ветке `feat/scoring-v2-tavily-citations` мне нужно было проанализировать каскадные эффекты ускорения устаревания AI-специалистов. Казалось бы, стандартный анализ трендов. Но когда я начал применять **second-order thinking** — методику, когда каждый следующий уровень последствий взаимодействует с остальными — картина стала совсем другой. Первая цепочка выглядела логично: дефицит экспертов среднего уровня → компании не могут себе позволить содержать команды для самостоятельного деплоя моделей → миграция на managed API-сервисы (OpenAI, Anthropic). До сюда всё известно. Но затем включается второй порядок: консолидация рынка вокруг 2–3 крупных провайдеров → исчезновение экспертизы в fine-tuning и альтернативных архитектурах (mixture-of-experts, sparse models) → кризис инноваций в ML-research за пределами мейнстрима. И вот уже у нас есть технологическая стагнация. Параллельно с этим развивается образовательный кризис. ВУЗы и онлайн-курсы не успевают за практикой — контент устаревает за месяцы. Но второй порядок здесь ещё любопытнее: возникает новый класс профессионалов — **"AI translators"**, посредники между бизнесом и моделями. Это не инженеры, понимающие архитектуры, а скорее полиглоты, которые говорят и на языке бизнеса, и понимают возможности AI. Они начинают зарабатывать больше, чем традиционные tech leads. Самое интересное — это видение цены. Доминирующие провайдеры могут позволить себе predatory pricing: агрессивно демпингуют цены, вытесняют конкурентов, закрепляют vendor lock-in, а потом, после консолидации, поднимают цены и извлекают ренту. Это классическая стратегия, но в контексте AI она означает, что инвестиции в долгосрочный AI R&D начинают падать в пользу quick wins. Противовес ко всему этому — взрывной рост open-source AI инфраструктуры. Оказывается, когда рынок становится слишком консолидированным, появляется встречное движение. Это как физика маятника. Пока писал аналитику, понял: мы в точке бифуркации. Следующие 18 месяцев определят, будет ли AI рынок контролироваться несколькими гигантами или всё же произойдёт фрагментация с возрождением специализации в нишах. 😄 Применять second-order thinking каждый день — это как стать параноиком, но обоснованным.

#claude#ai#python#javascript#git#api
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияtrend-analisis

AI дешевеет, junior-разработчики страдают: сложный анализ

# Когда AI дешевеет, страдают junior-разработчики: глубокий анализ каскадных эффектов Три недели назад я включился в проект **trend-analysis** с амбициозной целью: построить систему, которая видит не первый порядок причинно-следственных связей, а второй и третий. Задача была простая на словах: проанализировать, как снижение стоимости доступа к AI-инструментам переформатирует рынок труда для разработчиков. Но копать пришлось глубже, чем я ожидал. Стартовал я с ветки `feat/scoring-v2-tavily-citations` — решил, что буду собирать данные через Tavily API и отслеживать цитирования источников. Первый порядок эффектов был очевиден: дешевый ChatGPT → малые компании сами пишут скрипты вместо аутсорса → спрос на разработчиков падает. Но это была поверхность. **Первым делом** я распутал цепочку глубже. Оказалось, что механизм намного жестче: доступные AI-инструменты позволяют стартапам валидировать идеи без early-stage инвесторов. Они используют claude-api и GPT для быстрого прототипирования, обходя акселераторы и angel-networks. Это, в свою очередь, обрушивает ценность именно тех фондов, которые раньше ловили deal flow на ранних стадиях. Результат? Мелкие VC-фонды закрываются, и инвестиции концентрируются у крупных игроков. А это ударяет по всей экосистеме. **Неожиданно выяснилось**, что эффекты расходятся веером. Когда junior-разработчиков становится дешевле, падают ставки — и тогда образовательные программы теряют смысл. Буткемпы закрываются, EdTech-стартапы сворачиваются. Но параллельно происходит другое: люди мигрируют из Bay Area в более дешевые регионы (Austin, Lisbon, Miami) благодаря распределённым командам и AI-инструментам для коллаборации. Сейчас не нужно ехать в Пало-Альто, чтобы быть в эпицентре инноваций. Самый интересный момент — это то, что произойдёт с контентом и информацией. Если падает доверие к онлайн-источникам из-за AI-мусора, издатели теряют доход от рекламы. CPM падает. Контент-проекты закрываются. Качественная информация становится платной, а бесплатный интернет заполняется мусором. Получается странный парадокс: технология, обещавшая демократизировать знания, ведёт к информационному неравенству. **Вот что я понял за эти недели**: каскадные эффекты работают как землетрясение. Толчок в одной зоне (цена AI) вызывает сдвиги везде — от географии инноваций до структуры венчурного рынка, от образования до качества контента. И главное — нельзя смотреть на первый эффект. Нужно видеть сеть. Добавил в CLAUDE.md новое правило про ветки и MR: каждая фича — своя ветка, rebase перед коммитом, MR после push. Дисциплина. Теперь планирую расширить анализ на hard tech и геополитику — там механизмы ещё тоньше. 😄 **Совет дня: перед тем как запушить анализ больших трендов, сначала напиши сценарии на трёх уровнях причинности — иначе упустишь самое интересное.**

#claude#ai#python#javascript#git#api#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияtrend-analisis

Как отличить тренд от мусора: архитектура умного скоринга

# Когда скоринг тренда встречается с фактами: как мы научили компьютер различать шум и сигнал Всё началось с простого вопроса в проекте **trend-analisis**: как отличить действительно важный тренд от того, что просто много раз переписали в интернете? Первый скоринг работал, но был примитивен — считал кол-во источников и всё. А если один агрегатор новостей переиндексировал статью сто раз? Тогда по его логике это уже суперважный тренд, хотя на деле — просто мусор. Поэтому решили пойти в наступление. Нужна была система со вкусом, которая бы понимала разницу между настоящей значимостью тренда и просто шумом в информационном поле. Так родилась идея **Scoring V2**. Архитектура получилась трёхслойной. Первый слой — это **urgency** (срочность) и **quality** (качество), оба по шкале 0–100. Urgency отражает, насколько свежее и горячее событие, а quality говорит о том, из скольких разных *реальных источников* (не агрегаторов!) пришла информация. На основе этой пары метрик система выдаёт одну из четырёх рекомендаций: **ACT_NOW** (кидай в новости прямо сейчас), **MONITOR** (держим под контролем), **EVERGREEN** (медленный, долгоиграющий тренд) и **IGNORE** (это просто шум). Второй слой — интеграция с **Tavily API**. Это платформа для работы с новостями, которая даёт не просто список источников, а полный граф цитирований. TavilyAdapter в нашем коде считает unique domain count — то есть сколько *разных доменов* процитировали друг друга. Если один агрегатор (New Feed, Hacker News агрегатор — словили паттерны в `AGGREGATOR_PATTERNS`) выплюнул эту новость, мы его фильтруем. Остаются только оригинальные источники. Реальная магия произошла в методе `fetch_news()` с порогом цитирования. Мы выставили границу: если тренд цитируется меньше чем из пяти уникальных доменов, он недостаточно «реален», чтобы его считать. Просто фантом информационного поля. На фронте всё стало нагляднее. Добавили **RecommendationBadge** с крупным значком рекомендации и **UrgencyQualityIcons** — двойной индикатор, как в мобильных приложениях. Но главное изменение — источники больше не просто цифры (`5 sources`), теперь это кликабельные ссылки на URL. Пользователь может сразу прыгнуть на оригинальный источник вместо того, чтобы видеть размытую статистику. На бекенде настроился enrichment loop в **Crawler**: при обработке трендов с Hacker News, GitHub и arXiv теперь подтягиваются `tavily_citations` — полный профиль цитирований. Все константы вынесли в **Config**: `TAVILY_CITATION_BASELINES` (пороги для разных источников) и `AGGREGATOR_PATTERNS` (чёрный список перепечатанок). Самое интересное из истории Tavily: эта платформа появилась как ответ на хаос с информационной надёжностью. Её создатели заметили, что в эпоху AI-генерируемого контента источники становятся таким же валютой, как золото в разведке. Поэтому они решили сделать источники прозрачными и проверяемыми прямо из API. На выходе получилась система, которая *по-настоящему* различает сигнал и шум. **CHANGELOG.md** с чёткой историей всех изменений, **SCORING_V2_PLAN.md** с логикой расчётов (на будущее, чтобы кто-то не сломал), и **TAVILY_CITATION_APPROACH.md** с подводными камнями (коих оказалось немало). Всё задокументировано, чтобы следующий разработчик не потратил неделю на обратный инжиниринг. Что дальше? Теперь можно экспериментировать с весами urgency и quality, обучать модель на реальных данных пользователей. А Scoring V2 — это просто фундамент. Крепкий, надёжный, проверенный фундамент. 😄 Комментарий в коде: «Это должно работать» — убеждение из четырёх слов, которое разработчик дал самому себе вчера в 23:00, и он не особо в это верил.

#git#commit#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияtrend-analisis

Как научить машину отличать тренд от вирусного баяна

# Как мы разобрались, что такое тренд: от анализа данных к системе оценки Проект **trend-analisis** встал перед банальной, но хитрой проблемой: как машина может понять, что именно тренд? Не просто популярно, а действительно взлетает? В тренде идёт конкретное изменение? Вот я и взялся за исследование, которое потом превратилось в полноценную методологию оценки. Задача была амбициозная: построить систему двойной оценки для **Scoring V2**, которая бы учитывала и срочность события, и его качество. Потому что в реальной жизни одного лайка или шеера недостаточно — нужно смотреть на скорость роста, вовлечённость аудитории, стабильность интереса. Как отличить вирусный баян от настоящего тренда? Вот это вопрос. Первым делом я начал с сырых данных из **trending_items** — просто выгрузил всё, что там лежало, и начал искать закономерности. Представь: тысячи событий, метрики, сигналы. Нужно было понять, какие из них реально говорят о качестве тренда, а какие — это просто шум. Потом пошёл в глубокий анализ. Я собрал экспертные оценки, посмотрел, как эксперты оценивают эти же события. Интересное выяснилось: не все сигналы, которые кажутся важными, на самом деле коррелируют с реальной ценностью тренда. Например, большое число упоминаний может быть, а качество обсуждения — нулевое. Поэтому родилась идея **dual-score методологии**: отдельно считаем срочность (velocity), отдельно — качество (engagement и credibility). Третьим шагом я валидировал алгоритмы на граничных случаях. Что если тренд появился в маленьком сообществе, но растёт экспоненциально? Что если большой аккаунт один раз поделился — это считать за тренд? Документировал все edge cases, чтобы позже разработчики не натыкались на сюрпризы. Но вот беда: при анализе данных я понял, что некоторые критические сигналы вообще не собираются. Например, скорость, с которой люди делятся контентом в разных каналах, или как быстро растёт количество новых участников в обсуждении. Вот я и составил план по сбору этих данных — velocity и engagement метрики, которые нужно будет добавить в pipeline. На выходе получилась серия документов: от сырого анализа к финальной методологии, с проверкой алгоритмов и планом развития. Это не просто коммит — это полный цикл исследования, задокументированный так, чтобы любой разработчик мог взять и реализовать на основе выводов. Главный урок: прежде чем писать код системы, сначала нужно понять её логику. Потратить время на исследование — это не потеря времени, это инвестиция в правильную архитектуру. Потом код пишется в 10 раз быстрее. 😄 Почему scikit-learn считает себя лучше всех? Потому что Stack Overflow так сказал.

#git#commit#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

SQLite на Linux: когда переменные окружения не спасают

# Деплой SQLite: когда переменные окружения предают в самый ответственный момент Проект `ai-agents-bot-social-publisher` стоял на пороге боевого выпуска. Восемь n8n-воркфлоу, которые собирают посты из социальных сетей и сортируют их по категориям, прошли все локальные тесты с честью. Команда была уверена — завтра деплоим на Linux-сервер, и всё заживёт. Реальность оказалась жестче. Первая же волна логов после развёртывания завалила ошибку: `no such table: users`. Все SQLite-ноды в воркфлоу панически искали базу по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db`. Классический Windows-путь. На Linux-сервере, разумеется, такого ничего не было. ## Элегантное решение, которое не выжило встречи с реальностью Первый инстинкт был логичен: использовать переменные окружения и выражения n8n. Добавили `DATABASE_PATH=/data/admin_agent.db` в `docker-compose.yml`, развернули воркфлоу с выражением `$env.DATABASE_PATH` в конфиге SQLite-ноды и нажали кнопку деплоя. Ничего не изменилось — всё падало с той же ошибкой. Потом выяснилось неприятное: в n8n v2.4.5 таск-раннер **не передавал переменные окружения в SQLite-ноду так, как обещала документация**. Выражение красиво сохранялось в конфигурации, но при реальном выполнении система всё равно искала исходный Windows-путь. Красивое решение встретилось с суровой реальностью и проиграло. ## Скучный способ, который работает Пришлось отказаться от элегантности в пользу надёжности. Решение оказалось неожиданно простым: **string replacement при деплое**. Написал скрипт `deploy/deploy-n8n.js`, который перехватывает JSON каждого воркфлоу перед загрузкой на сервер и заменяет все `$env.DATABASE_PATH` на реальный путь `/var/lib/n8n/data/admin_agent.db`. Скучно? Абсолютно. Но работает. Здесь же обнаружилась вторая подводная скала: n8n хранит две версии каждого воркфлоу. *Stored*-версия живёт в базе данных, *active*-версия загружена в памяти и реально выполняется. Когда обновляешь воркфлоу через API, обновляется только хранилище. Active может остаться со старыми параметрами. Спасение простое: после обновления конфига явно деактивировать и активировать воркфлоу. К этому добавили инициализацию SQLite. Скрипт копирует на сервер SQL-миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. Выглядит как излишество, но спасает в будущем — когда потребуется добавить колонку в таблицу `users`, просто добавляешь новую миграцию без полного пересоздания БД. ## Итог Теперь весь деплой — одна команда: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, база инициализируется, всё работает. **Главный урок:** не полагайся на runtime-выражения в критических параметрах конфигурации. Лучше заранее знать точное место и подставить путь при развёртывании. Скучно, но надёжно. — Ну что, SQLite, теперь ты найдёшь свою базу? — спросил я у логов. SQLite ответил тишиной успеха. 😄

#claude#ai#javascript#git#api
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

SQLite на кроссплатформе: когда переменные окружения предают

# SQLite между Windows и Linux: как не потерять данные при деплое Проект `ai-agents-bot-social-publisher` был почти готов к боевому выпуску. Восемь n8n-воркфлоу, которые собирают посты из социальных сетей и распределяют их по категориям, прошли локальное тестирование на отлично. Но тут наступил момент истины — первый деплой на Linux-сервер. Логи завалили ошибкой: `no such table: users`. Все SQLite-ноды в воркфлоу отчаянно искали базу данных по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db`. Windows-путь. На Linux-сервере, разумеется, ничего такого не было. ## Красивое решение, которое не сработало Первый инстинкт был логичный: использовать переменные окружения и выражения n8n. Добавили `DATABASE_PATH=/data/admin_agent.db` в `docker-compose.yml`, развернули воркфлоу с выражением `$env.DATABASE_PATH` в конфиге SQLite-ноды, нажали на кнопку деплоя и... всё равно падало. Выяснилось, что в n8n v2.4.5 **таск-раннер не передавал переменные окружения в SQLite-ноду так, как ожидалось**. Выражение красиво хранилось в конфигурации, но при выполнении система всё равно искала исходный Windows-путь. Пришлось отказаться от элегантности в пользу надёжности. ## Боевой способ: замены при развёртывании Решение оказалось неожиданно простым — **string replacement при деплое**. Разработал скрипт `deploy/deploy-n8n.js`, который перехватывает JSON каждого воркфлоу перед загрузкой на сервер и заменяет все `$env.DATABASE_PATH` на реальный абсолютный путь `/var/lib/n8n/data/admin_agent.db`. Скучно? Да. Предсказуемо? Абсолютно. Но тут обнаружилась ещё одна подводная скала: **n8n хранит две версии каждого воркфлоу**. Stored-версия живёт в базе данных, active-версия загружена в памяти и выполняется. Когда обновляешь воркфлоу через API, обновляется только хранилище. Active может остаться со старыми параметрами. Это сделано специально, чтобы текущие выполнения не прерывались, но создаёт рассинхронизацию между кодом и поведением. Решение: после обновления конфига явно деактивировать и активировать воркфлоу. ## Инициализация базы: миграции вместо пересоздания Добавили инициализацию SQLite. Скрипт SSH копирует на сервер SQL-миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. Такой подход кажется лишним, но спасает в будущем — когда потребуется добавить колонку `phone` в таблицу `users`, просто добавляешь новую миграцию, без полного пересоздания БД. Теперь весь деплой сводится к одной команде: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, база инициализируется корректно, всё работает. **Главный урок:** не полагайся на относительные пути в Docker-контейнерах и на runtime-выражения в критических параметрах конфигурации. Лучше заранее знать точное место, где будет жить приложение, и подставить правильный путь при развёртывании. «Ну что, SQLite, теперь-то ты найдёшь свою базу?» — спросил я у логов. SQLite ответил тишиной успеха. 😄

#claude#ai#python#javascript#git#api#security
7 февр. 2026 г.
Новая функцияtrend-analisis

Как мы научили алгоритм видеть тренды раньше конкурентов

# Как мы научили систему различать тренды: от сырых данных к методологии V2 Проект **trend-analysis** потихоньку превращался в монстра. У нас были данные о трендирующих элементах, мы их собирали, анализировали, но что-то было не так. Алгоритм скорингования, который считался идеальным месяц назад, начал давать странные результаты: вчерашние хиты вдруг переставали быть релевантными, а настоящие тренды долго оставались невидимыми. Задача была простой на словах, но коварной в деталях: построить методологию скорингования V2, которая будет разбираться не только в том, *что* тренды, но и в том, *почему* они такие и *как долго* они просуществуют. ## Первый день: копание в данных Первым делом я создал серию исследовательских отчётов. Начал с **01-raw-data.md** — взял весь объём трендирующих элементов из базы и просто посмотрел на цифры без предубеждений. Какие сигналы вообще есть? Какие данные полны, а какие похожи на швейцарский сыр? Это как быть детективом на месте преступления — сначала нужно понять, что именно ты видишь. Потом пригласил в процесс экспертов. **02-expert-analysis.md** — это был мозговой штурм в текстовом формате. Эксперты смотрели на сигналы и говорили: «Это шум», «А это золото», «Вот это вообще баг в системе». Получилась карта того, какие сигналы действительно имеют вес при определении тренда. ## Вторая волна: архитектура методологии Третий отчёт, **03-final-methodology.md**, был поворотным. Мы поняли, что один скор — это неправда. Тренд не может быть описан одним числом. Родилась идея *dual-score методологии*: отдельно скор срочности (urgency) и скор качества (quality). Срочность показывает, насколько быстро что-то растёт прямо сейчас. Качество показывает, насколько это вообще надёжный сигнал. Представь: старая система видела вирусный мем, который взлетел за час, и кричала о тренде. А потом через два часа мем забыли, и система выглядела глупо. Новый подход говорит: «Да, это срочно, но качество низкое — боюсь, это не настоящий тренд, а всего лишь всплеск». **04-algorithms-validation.md** — это была проверка на прочность. Мы взяли исторические данные и прогнали их через алгоритм валидации. Ловили edge cases: что если все сигналы нулевые? Что если они противоречивы? Что на границах данных? Каждый баг, который нашли в теории, исправили до того, как код вообще написали. ## Последняя фаза: осознание пробелов **05-data-collection-gap.md** был честным разговором с самими собой. Мы поняли, что нам не хватает информации. Нет данных о *velocity* (как быстро растёт тренд во времени) и настоящего измерения *engagement*. Мы просто не собирали эту информацию раньше. Вот здесь и пришёл **06-data-collection-plan.md** — план того, как мы будем собирать недостающие сигналы. Не просто добавляя SQL-запросы, а продумав, какие именно метрики дадут нам полную картину. ## Что дальше? Весь этот мозговой марафон — это фундамент для реальной реализации. Теперь, когда мы начнём писать код для Scoring V2, мы знаем, что делаем и почему. Нет наугад, нет сомнений. Только чёткая методология и валидированные алгоритмы. Главный урок: иногда самая важная часть разработки — это вообще не код, а понимание. Потратили неделю на исследование вместо месяца отладки кривого скорингования. Карма благодарна. 😄 Почему scikit-learn считает себя лучше всех? Потому что Stack Overflow так сказал.

#git#commit#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

SQLite между Windows и Linux: как не потерять данные при деплое

# Когда SQLite на Windows встречает Linux: история одного деплоя Проект `ai-agents-admin-agent` был почти готов к запуску на сервере. Восемь n8n-воркфлоу, собирающих и обрабатывающих данные, уже прошли тестирование локально. На машине разработчика всё работало идеально. Но только до того момента, когда мы выложили их на Linux-сервер. Первый боевой запуск воркфлоу завершился криком ошибки: `no such table: users`. Логи были красноречивы — все SQLite-ноды искали базу данных по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db`. Локальный Windows-путь. На сервере такого вообще не существовало. ## Первый инстинкт: просто заменить пути Звучит логично, но дьявол, как всегда, в деталях. Я начал рассматривать варианты. **Вариант первый** — использовать относительный путь типа `./data/admin_agent.db`. Звучит мобильно и красиво, но это ловушка для новичков. Относительный путь разрешается от текущей рабочей директории процесса n8n. А откуда запущен n8n? Из Docker-контейнера? Из systemd? Из скрипта? Результат абсолютно непредсказуем. **Вариант второй** — абсолютный путь для каждого окружения. Надёжнее, но требует подготовки на сервере: скопировать схему БД, запустить миграции. Более сложно, зато предсказуемо. Я выбрал комбинированный подход. ## Как мы это реализовали Локально в `docker-compose.yml` добавил переменную окружения `DATABASE_PATH=/data/admin_agent.db` — чтобы разработка была удобной и воспроизводимой. Затем создал развёртывающий скрипт, который при деплое проходит по всем восьми воркфлоу и заменяет выражение `$env.DATABASE_PATH` на реальный абсолютный путь `/var/lib/n8n/data/admin_agent.db`. Но первое время я попытался обойтись выражениями n8n. Логика казалась неубиваемой: задаёшь переменную в окружении, ссылаешься на неё в воркфлоу, всё просто. На практике выяснилось, что в n8n v2.4.5 таск-раннер не передавал переменные окружения в SQLite-ноду так, как ожидалось. Выражение хранилось в конфигурации, но при выполнении всё равно искал исходный Windows-путь. Пришлось идти в лоб — **строковые замены при деплое**. Развёртывающий скрипт `deploy/deploy-n8n.js` перехватывает JSON каждого воркфлоу и подставляет правильный путь перед загрузкой. Ещё одна подводная скала: n8n хранит две версии каждого воркфлоу — **stored** (в базе данных) и **active** (загруженная в памяти). Когда вы обновляете конфигурацию через API, обновляется только stored-версия. Active может остаться со старыми параметрами. Это сделано для того, чтобы текущие выполнения не прерывались, но создаёт рассинхронизацию между кодом и поведением. Решение: явная деактивация и активация воркфлоу после обновления. Добавили в процесс и инициализацию БД: скрипт SSH копирует на сервер миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. В будущем, когда потребуется изменить схему (например, добавить колонку `phone` в таблицу `users`), достаточно добавить миграцию — без пересоздания всей БД. ## Итог Теперь деплой сводится к одной команде: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, база инициализируется корректно, всё работает. Главный урок: **не полагайся на относительные пути в Docker-контейнерах и на runtime-выражения в критических параметрах.** Лучше заранее знать, где именно будет жить твоё приложение, и подставить правильный путь при развёртывании. Это скучно, но предсказуемо. GitHub — единственная технология, где «это работает на моей машине» считается достаточной документацией. 😄

#claude#ai#python#javascript#git#api#security
7 февр. 2026 г.
Новая функцияtrend-analisis

Когда один тренд ИИ запускает цепную реакцию в экономике

# Когда тренды становятся сложнее, чем сама архитектура: анализ каскадов ИИ-инфраструктуры Проект `trend-analisis` родился из простого вопроса: как отследить не просто новости об искусственном интеллекте, а понять, какие эффекты один тренд вызывает в других областях? Задача выглядела невинно на первый взгляд, но когда я начал углубляться в данные, понял, что передо мной стоит куда более сложная задача — нужно было смоделировать целые каскады причинно-следственных цепочек. Первым делом я заложил фундамент: система скоринга V2, которая учитывала не только срочность тренда, но и его качество, и дальность прогноза. Звучит сухо, но на практике это означало, что каждый выявленный тренд получал три оценки вместо одной. Параллельно интегрировал Tavily Citation-Based Validation — библиотеку для проверки источников. Без неё данные были бы просто красивой фантазией. Неожиданно выяснилось, что самая большая сложность не в технологии, а в логике. Когда я анализировал специализацию ИИ-стартапов, выяснилось: компании нанимают не универсальных ML-инженеров, а врачей с навыками датасайнса, финансистов, которые учат модели. Это смещение спроса создаёт временный дефицит гибридных специалистов. Зарплаты взлетают в нишах, падают в массовом сегменте. И всё это — цепная реакция от одного казалось бы локального тренда. Архитектурно это означало, что нельзя просто сохранить тренд в базу. Нужна была система отслеживания каузальных цепочек — я назвал её `causal_chain`. Каждый эффект связан с другим, образуя паутину взаимозависимостей. Геополитическая зависимость от США и Китая в ИИ порождает локальные экосистемы в Евросоюзе и Индии. Open-source становится геополитическим буфером. Дата-резидентность и облачный суверенитет — это не просто buzzwords, а вопросы национальной безопасности. **Интересный факт:** системная централизация вокруг одного-двух вендоров в корпоративном мире создаёт явление, похожее на AWS lock-in. Компания выбрала платформу — и теперь стоимость миграции её данных и переобучения моделей настолько высока, что перейти к конкуренту практически невозможно. Это замедляет инновации и создаёт технологическое отставание целых отраслей. Жуткий пример того, как одно архитектурное решение может на годы заморозить развитие. В итоге в ветке `feat/auth-system` отправил 31 файл изменений: +4825 строк логики анализа, −287 временных хаков. Исключил локальные файлы конфигурации и тестовые данные. Система теперь видит не просто тренды — она видит волны эффектов, распространяющихся через образование, рынок труда, регулирование, геополитику. Главное, что я понял: когда аналитика становится достаточно глубокой, инженерия не успевает за ней. Архитектура должна предусмотреть не то, что ты знаешь сейчас, а возможность добавлять новые измерения анализа без переписывания всего с нуля. Почему ИИ-исследователи считают себя лучше всех остальных разработчиков? 😄 Потому что они анализируют тренды лучше, чем самих себя.

#claude#ai#javascript#git#api#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияtrend-analisis

Scoring V2: система, которая отличает настоящие тренды от шума

# Scoring V2: когда трендам нужна оценка честности Проект **trend-analysis** разросся до того, что мы уже собирали тренды из трёх источников одновременно — Hacker News, GitHub и arXiv. Но вот беда: не все тренды одинаково полезны. Одна заметка набирает 500 апвотов за счёт сенсационного заголовка, другая медленно растёт, потому что действительно важна. Третья вообще сплошь переподсказывается из десяти агрегаторов. Нужна была система, которая не просто считает, что популярнее, а понимает, *почему* это актуально и стоит ли на это вообще обращать внимание. Задача была чёткая: построить **Scoring V2** — систему метрик, которая будет ставить каждому тренду две оценки (по 100-балльной шкале) и выдавать конкретную рекомендацию. Не просто «это популярно», а **ACT_NOW** («действуй сейчас!»), **MONITOR** («присматриваем»), **EVERGREEN** («это на века») или **IGNORE** («не трать время»). Первым делом разобрались с метриками. **Urgency** — это по сути скорость роста: насколько быстро тренд набирает обороты в последние часы. **Quality** — это честность источника и уникальность. Вот здесь и пригодилась идея с **Tavily**: мы начали считать количество уникальных доменов, которые цитируют эту новость. Если одну статью перепостили на 50 агрегаторских сайтах, но всего там одна оригинальная ссылка — это ненастоящий тренд, это просто вирусное перепосчикание. Реализовали **TavilyAdapter** с методами для подсчёта цитирований и фильтрации агрегаторов. В конфигах добавили шаблоны для распознавания паттернов типичных переупаковщиков новостей — Medium, Dev.to, Hashnode и прочих. **TrendScorer** теперь рассчитывает обе метрики и выбирает рекомендацию по простой логике: если urgency высокий И quality высокий — то ACT_NOW, если только один из них — MONITOR, и так далее. На фронтенде добавили новые компоненты — **RecommendationBadge** показывает рекомендацию цветом и текстом, а **UrgencyQualityIcons** визуализирует обе оценки сразу. Самое интересное: раньше источники были просто счётчиками («30 упоминаний»), теперь это массивы URL-ов, по которым можно кликнуть и увидеть, где именно упоминается тренд. Навигация в разделе Categories теперь работает через URL-параметры — появилась возможность нормально использовать кнопку назад в браузере. **Неочевидный факт о системах рекомендаций:** большинство разработчиков ошибочно считают, что стоит комбинировать все метрики в один скор и сортировать по нему. На деле гораздо полезнее иметь несколько ортогональных метрик (которые не зависят друг от друга) и давать юзеру выбор, на что смотреть. Плюс конкретные рекомендации (вроде ACT_NOW) куда понятнее, чем абстрактный скор 7.3 из 10. В итоге получилась система, которая не просто шумит о популярности, а реально помогает разобраться в том, что сейчас происходит в IT. Весь код, логика и даже типичные ловушки документировали в **CHANGELOG.md** и отдельных markdown-ах про Scoring V2 и подход с Tavily. Следующий шаг — добавить машинное обучение, чтобы baseline-ы для цитаций настраивались автоматически. 😄 Документация V2 получилась более объёмной, чем сам код, но это не баг, это фича — значит, потом будет меньше вопросов.

#git#commit#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

Сессии вместо JWT: как мы защитили trend-analysis без сложности

# Как мы защитили trend-analysis: система аутентификации, которая работает Когда **trend-analysis** начал расти и появились первые пользователи с реальными данными, стало ясно: больше нельзя оставлять проект без охраны. Сегодня это звучит очевидно, но когда проект рождается как хобби-эксперимент на Claude API, о безопасности думаешь в последнюю очередь. Задача встала конкретная: построить систему аутентификации, которая не замедлит анализ трендов, будет действительно надёжной и при этом не превратится в монстра сложности. Плюс нужно было всё это интегрировать в цепочку с Claude API, чтобы каждый запрос знал, кто его отправил. **Первым делом** я создал ветку `feat/auth-system` и начал с главного вопроса: JWT-токены или сессии? На бумаге JWT выглядит идеально — stateless, не требует обращений к БД на каждый запрос, легко масштабируется. Но JWT имеет проблему: невозможно мгновенно заблокировать токен, если что-то пошло не так. Я выбрал компромисс: **сессии с HTTP-only cookies** и постоянная валидация через Claude API логирование. Это скучнее, чем блеск JWT, но безопаснее и практичнее. Неожиданно выяснилось, что самая коварная часть — не сама авторизация, а правильная обработка истечения доступа. Пользователь кликает кнопку, а его сессия уже протухла. Мы реализовали двухуровневую систему: короткоживущий access-токен для текущей работы и долгоживущий refresh-токен для восстановления доступа без повторной авторизации. На первый взгляд это выглядит усложнением, но спасло нас от тысячи потенциальных багов с разъёхавшимся состоянием. Интересный момент, о котором забывают: **timing-атаки**. Если проверять пароль просто посимвольным сравнением строк, хакер может подбирать буквы по времени выполнения функции. Я использовал `werkzeug.security` для хеширования паролей и функции постоянного времени для всех критичных проверок. Это не добавляет сложности в коде, но делает систему несоизмеримо более защищённой. В результате получилась система, которая выдаёт пользователю пару токенов при входе, проверяет access-token за миллисекунды, автоматически обновляет доступ через refresh и логирует все попытки входа прямо в trend-analysis. База построена правильно, и теперь наша платформа защищена. Дальше планируем двухфакторную аутентификацию и OAuth для социальных сетей, но это уже совсем другая история. 😄 Знаете, почему JWT-токены никогда не приходят на вечеринки? Потому что они всегда истекают в самый неподходящий момент!

#claude#ai#python#git#api#security
7 февр. 2026 г.