Read in:
Русский

Философия

Зачем публиковать знания графом, а не книгой. Как AI меняет правила игры. Почему подписка, а не разовая продажа. Ниже — все статьи, свежие сверху; тематическую подборку смотрите в боковом меню.

Анатомия trip2g: 15 месяцев кода

trip2g — платформа для публикации Obsidian-заметок с подпиской и интеграцией с Telegram. Go-монолит + $mol-фронтенд + SQLite.

Через 15 месяцев разработки я решил посчитать, что внутри.

Съёмка демо — это тест

Чтобы записать чистое видео фичи, приходится пройти весь её happy path на настоящем продукте. Всплывают ровно те баги, которые иначе ждали бы живого демо перед клиентом.

Мы собирались записать видео онбординга: скачать стартовый vault, поставить плагин, сохранить заметку, увидеть её на сайте. Ничего экзотического, ровно тот путь, которым идёт каждый новый пользователь. Запись заняла на несколько дней больше плана, и почти вся задержка была не про видео. Дубль за дублем падал, потому что продукт на живом проде отказывался делать то, что по всем тестам умел. В этом и оказалась ценность. Съёмка — репетиция демо, и она ловит демо-баги, пока они стоят пересъёмку, а не доверие клиента.

Видео: скоро будет. Готовая запись появится здесь.

Агент докладывает команде сам

Когда работаешь с агентом весь день, команда не видит ничего. Коммит появится к вечеру, если появится. Что агент делал шесть часов — тайна. Этот скил закрывает пробел: после каждого хода агент автоматически пишет короткий отчёт и отправляет его в trip2g.

Хорошая инструкция для MCP помогает дешёвой модели быстрее находить ответы

О чём это: замеренный A/B на двух дешёвых моделях. Я подключил Claude Haiku и GPT-5.4-nano к базе документации trip2g через MCP и задал каждой по восемь вопросов. Сначала с короткой инструкцией в контексте, потом без неё. Те же инструменты, те же вопросы. С инструкцией Haiku искал на 26% быстрее и на 41% реже выгружал заметки целиком. А nano, который и сам по себе бережлив, в ней почти не нуждался. Читать, если вы держите базу знаний за MCP и не уверены, окупается ли инструкция.

Короткий ответ: хорошая инструкция не делает дешёвую модель умнее. Она исправляет расточительное поведение по умолчанию. Загвоздка в том, что не всякая дешёвая модель расточительна. На Haiku инструкция дала явный выигрыш. На nano, который и без подсказки читает аккуратно, инструкция почти ничего не дала и даже стоила токенов. Обе истории ниже, потому что честный вывод как раз в контрасте.

Алертам место в базе знаний

О чём это: мы написали alert-sink, небольшой открытый сервис, который превращает вебхуки Alertmanager в заметки об инцидентах в инстансе trip2g. Каждый алерт становится markdown-заметкой, заметки складываются в постоянную историю инцидентов с поиском, а база знаний может сама рассказывать про инциденты в Telegram-группе. Читать, если ваша история инцидентов сейчас живёт в скроллбэке чата.

Алерты сегодня работают по принципу «выстрелил и забыл». Prometheus замечает проблему, Alertmanager кидает сообщение в Telegram или на почту, кто-то реагирует или нет, и на этом запись заканчивается. Через месяц вы спрашиваете «а когда эта нода флапала в прошлый раз?», и честный ответ такой: листай чат и надейся. Сам Alertmanager показывает только то, что горит прямо сейчас. История живёт либо как time series в Prometheus, ограниченная retention, либо как сообщение, которое давно уехало вверх.

Меня это раздражало довольно долго, потому что решение тут не мониторинговый продукт. Это место, куда записывать.

Налог на универсальность

Сколько стоит универсальный инструмент — тем, кто на нём строит, и тем, кто им пользуется.

Универсальный инструмент делает любую задачу возможной, но почти никогда — дешёвой. Каждый сценарий использования — это отдельная стройка поверх платформы. Цену этой стройки легко недооценить заранее, а сам процесс легко полюбить сильнее, чем результат. Вот вторая половина и есть ловушка: инструмент приглашает строить инструмент вместо того, чтобы им пользоваться. У социологов для этого есть термин (смещение целей), у каждого второго гаража — Жигули, которые чинят тридцать лет, а у trip2g — квитанция: «простой шаблон канбан-доски», который потребовал шесть заходов правок в ядро. Универсальность — это обещание и налог одновременно. Дисциплина в том, чтобы платить налог осознанно, когда его требует контент, и замечать момент, когда начал платить его для удовольствия.

Это парный текст к «У универсальных инструментов нет короткого питча». Тот говорит: платформу объясняют через дверь. Этот добавляет: двери не бесплатны.

Дороги, которые мы не выбрали

Фичи, которые мы построили и удалили — или посчитали и не стали строить. С числами, которые решили.

Стихотворение Фроста про две дороги обычно читают как гимн смелому выбору. У самого Фроста дороги были «примерно одинаковы», а «менее исхоженная» — красивая история, которую путник сочиняет потом, со вздохом. Здесь без вздохов. Эти дороги — не героические развилки: мы по ним прошли, померили и вернулись, обычно в тот же день. Не «дорога, которой шли немногие». Просто дорога, которую попробовали и оставили.

Страницы продуктов обычно перечисляют, что построено. Эта страница перечисляет, что построено и удалено — или оценено и отвергнуто. Не потому, что идеи глупые: почти все они — рекомендации из учебника. А потому, что мы померили их на нашей системе, и числа сказали «нет». Платформа, которая просит доверить ей ваши заметки, должна показывать, как принимает решения. Включая отмены.

Markdown как операционная система

О чём это: trip2g как буквальная операционная система. Заметки — файловая система, MCP — системные вызовы, федерация — сеть, агенты — процессы. Каждая строка в карте помечена тем, насколько она реальна, так что видно, где метафора заслужена, а где нет. Читать, если хотите решить, реальна ли «Markdown ОС» или это просто ярлык.

trip2g начинался как способ превратить Obsidian-хранилище в сайт. По дороге он принял форму операционной системы. Заметки — это файловая система. MCP-эндпоинт — интерфейс системных вызовов, через который ходят агенты. Федерация — сетевой стек. Правка заметки может запустить агента. Всё это уже работает на main, включая кусок, на котором метафора и держится: агенты как процессы влились в основную ветку вместе с рантаймом fleet. Это честная версия заявления: оставшиеся зазоры помечены явно.

Рамку мы позаимствовали. Статья «Markdown as an Operating System» формулирует мысль одной строкой: ваша ОС работает на бинарниках, а ваши ИИ-агенты должны работать на Markdown. Корень ещё старше — Unix, где «всё есть файл». Версия trip2g: всё есть заметка.

У универсальных инструментов нет короткого питча

Почему Obsidian невозможно объяснить одной фразой, почему у trip2g та же проблема — и почему это свойство инструмента, а не провал маркетинга.

Универсальный инструмент не помещается в одну фразу: каждый заходит в него через свою дверь. Obsidian тому пример. «Редактор markdown с вики-ссылками и плагинами» — формально верно и мимо сути. Дело не в маркетинге. Obsidian — не фича, а субстрат, и что он значит, решают не разработчики, а те, кто на нём строит. У trip2g та же природа и та же проблема. Честный выход — перестать искать единственно верный питч. Верных много, и каждый работает только на своего читателя.

Проси точку поворота, а не интервал

Языковая модель хорошо видит, где разговор поворачивает, и плохо считает арифметику по таймкодам. Моя первая попытка нарезать транскрипты звонков на темы это игнорировала: я просил у модели блоки [начало–конец], а она не сводила интервалы. Починил это не острый промпт и не модель побольше. Починил другой вопрос: спрашивай, где каждая тема начинается (один реальный таймкод из транскрипта), а интервалы досчитает код. Тогда самая дешёвая модель расставила переходы на 100% по порядку и на 97% по реальным таймкодам и обошла модель побольше.

Полгода я винил SQLite в собственном баге

О чём это: история про ошибку SQLITE_BUSY, которую я полгода ловил, валил на SQLite и в итоге нашёл в собственном пуле соединений. Наполовину боевая история, наполовину — довод в пользу того, чтобы держать базу внутри одного процесса. Читать, если вы хоть раз видели «database is locked» и думали, что зря выбрали SQLite.

Ошибка была моя. Где-то полгода trip2g под нагрузкой сыпал SQLITE_BUSY и database is locked, и примерно столько же я раз за разом решал, что виноват SQLite. Нет. Это я настроил пул соединений так, что он врал мне, сколько у меня писателей. В тот день, когда я наконец это понял, я перестал бояться держать базу внутри собственного процесса и начал получать от этого удовольствие.

Я пришёл сюда после многих лет на Postgres. В Postgres ты не думаешь, сколько у тебя писателей. Открываешь пул на тридцать соединений, все пишут когда хотят, а сервер разруливает. Поэтому когда я перевёл trip2g на один встроенный SQLite-файл, модель показалась неправильной на ощупь. Один писатель за раз, даже в режиме WAL? Это читалось как ограничение, которое надо обходить, а не контракт, под который надо проектировать. Я месяцами относился к нему как к первому и всё это время тихо злился на движок.

База данных разбирала свои запросы заново

После запуска кеша анонимных страниц мы снова запустили профилировщик. Рендеринг исчез с горячего пути. Треть CPU ушла в парсер SQL.

Сервер тот же: cx23, 2 vCPU, €6,49/мес на Hetzner. В профиле под нагрузкой вместо прежнего косинусного поиска стояли _yy_reduce и планировщик запросов. База данных разбирала одни и те же SQL-строки на каждый запрос и сразу выбрасывала скомпилированный результат.

Кеш страниц и неожиданное узкое место

Профилировщик показал: обычная страница документации в 30 раз дороже кастомного лендинга. Мы думали наоборот.

Под нагрузкой стояли два варианта. Jet-главная: кастомный лейаут с mesh-сеткой, фирменным дизайном, ручной вёрсткой. И страница документации в default-темплейте, которую получаешь без всякой настройки. Казалось бы: дорогой рендер у того, что сложнее. Профилировщик сказал: docs-страница — ~28 мс/запрос, Jet-главная — ~0,9 мс/запрос. В тридцать раз медленнее. И всё это в одном месте: синхронный поиск по косинусному сходству по всем эмбеддингам заметок на каждый запрос, подписанный «похожие заметки».

Что такое вайбкодинг

Вайбкодинг — это когда программу пишут, диктуя задачу ИИ на обычном языке, и принимают его код, не читая и не проверяя. Термин придумал Андрей Карпаты в твите 2 февраля 2025 года: «полностью отдаёшься вайбу… забываешь, что код вообще существует; я всегда жму „Accept All" и больше не читаю диффы». Сначала он имел в виду одноразовые проекты на выходные. За 2025 год смысл сузился. Теперь так называют крайний случай — без понимания и без ревью. Это отличают от «инженерии с ИИ», где человек всё равно читает, тестирует и может объяснить каждую строку. Главный признак вайбкодинга — не использование ИИ, а отсутствие понимания у человека. Поэтому одно и то же занятие хвалят за демократизацию софта и ругают за тихий поток багов, дыр и техдолга.

Сеть trip2g на прерываемых нодах

Короткий итог. Сеть знаний trip2g (markdown-вольты на SQLite) можно держать на прерываемых (preemptible) нодах: они в 2-3 раза дешевле и могут исчезнуть в любой момент. В синтетическом тесте сеть это переживает: нода умирает, поднимается на другой машине и восстанавливает свои данные за ~35 секунд, теряя не больше 1 секунды записей. Держит данные не локальный диск, а копия в объектном хранилище (Litestream). Ниже по деталям: что проверял, как это работает и где границы.

Проверял на расходном двухнодовом кластере, настоящий power-off через Hetzner API. Тест синтетический, не прод: он показывает, что механизм держит, а не что потерь не будет.

Что такое корпус знаний (markdown)

Корпус знаний (синоним — база знаний) это папка заметок в markdown, по которым ходишь как по связанному графу. Та же штука, что пользователи Obsidian называют «vault». Разница в одном: у нас корпус не привязан к Obsidian.

Построили бенчмарк синка — а тормозило совсем не то

Мы пересматривали синхронизацию Obsidian в trip2g и собирались ускорить медленное хеширование. Потом построили бенчмарк и измерили. Тормозило в другом месте — один забытый флаг превращал пуш на 3 секунды в пуш на 4 минуты.

Главное число — холодный пуш 2000 заметок с 2000 маленьких картинок:

xychart-beta
    title "Холодный пуш: 2000 заметок + 2000 картинок (секунды, меньше — лучше)"
    x-axis ["CLI до фикса", "CLI после фикса", "Плагин Obsidian"]
    y-axis "секунды" 0 --> 240
    bar [231.8, 8.8, 6.0]

Все числа — с изолированного стенда (векторный поиск выключен, локальный сервер). История ниже.

Тестирование скилов агента автономным циклом

Чтобы агент надёжно выполнял сложный скил, недостаточно написать инструкцию красивыми словами. Нужен цикл: гоняем агента, проверяем артефакты bash-чекером, ловим стабильные ошибки и правим структуру инструкции — не текст. За три итерации скил создания лендинга прошёл путь от 4 фейлов до 0. Сама идея цикла подсмотрена у Anthropic, материалы которого собрал агент Николая Сенина через knowlu.me и опубликовал на его trip2g-инстансе. Мой агент достал их через MCP-эндпоинт его сайта.

Один эндпоинт, много баз знаний

Спустя чуть больше месяца после первого коммита про федерацию наш публичный
trip2g-хаб запущен: один MCP-эндпоинт ищет сразу по нескольким независимым базам
знаний.
Демо — меньшая часть. Ставка — сеть: базы принадлежат разным людям,
доступны по одному адресу, и любой агент может по ним искать без центрального
реестра.

Чиним Obsidian Canvas на минимальном Linux

Ubuntu 24.04 LTS aarch64, VMware на Mac, без десктопного окружения — dwm под голым X11, startx из TTY. Obsidian 1.12.7 (проверено и Flatpak, и AppImage).

Canvas открывается. Ноды рендерятся. Клик работает. Но перетаскивать существующие ноды нельзя, и рёбра между ними не рисуются. Новые ноды, созданные через тулбар, тащатся нормально. Консоль молчит.

Решение: плагин из двух файлов, который переписывает все не-мышиные pointer-события в pointerType: "mouse" до того, как их увидят обработчики Obsidian. Установить, перезапустить — готово. Ниже — корневая причина и тупики, если интересно понять, почему так.

Агент ведёт дневник команды

Каждое утро агент читает, что делали участники команды вчера, и пишет дневную заметку. По понедельникам — недельную. Никто ничего не вводит вручную: данные берутся из trip2g-инстансов участников через MCP.

Knowledge-as-a-Service

Новая бизнес-модель для экспертов: не продажа знаний, а аренда доступа к живой системе.

Dogfooding: ешь свою собачью еду

Dogfooding

Dogfooding — философия разработки, где команда использует собственный продукт в реальной работе. Термин появился в Microsoft в 80-х: "eating your own dog food".

Contentless CMS

CMS без контента внутри. Звучит как парадокс, но в этом суть.

Контент-инфраструктура для совместной работы людей и AI

trip2g — контент-инфраструктура. Люди и AI-агенты работают с одним и тем же контентом на равных. Контент не лежит мёртвым грузом — он течёт между участниками и трансформируется на каждом шаге.

Не CMS, где "создал и опубликовал". Не wiki, где только люди редактируют. Не генератор статических сайтов, где "собрал и выложил". Это программируемая платформа, где контент течёт между людьми, ботами, AI-агентами, Telegram, Obsidian — и меняется на каждом переходе.

Админка как универсальный конфиг

Каждая функция требует настроек. Telegram-бот — токен и группы. OAuth — ключи от Google и GitHub. Patreon — API-токен и уровни подписки.

Можно было сделать отдельный редактор для каждой сущности. Форма для бота, форма для OAuth, форма для Patreon. Но это дублирование.