Перейти к основному содержанию

Известные неожиданности

Этот файл фиксирует специфичные для репозитория места, которые приводили к ошибкам агентов.

Критерии добавления записи

Добавляйте запись, только если верно всё перечисленное:

  • Это специфично именно для данного репозитория (а не общий совет).
  • Это, скорее всего, повторится у будущих агентов.
  • Есть конкретное решение, которому можно следовать.

Если есть сомнения, спросите разработчика перед добавлением записи.

Шаблон записи

### [Short title]

- **Date:** YYYY-MM-DD
- **Observed by:** agent name or contributor
- **Context:** where/when it happened
- **What was surprising:** concrete unexpected behavior
- **Impact:** what went wrong or could go wrong
- **Mitigation:** exact step future agents should take
- **Status:** confirmed | superseded

Записи

Продакшен-домены приложений на Vercel могут снова переключиться на деплои из ветки Git master

  • Дата: 2026-04-28
  • Кем замечено: Tommaso + Codex
  • Контекст: Проверка зеркал приложений Seedit и 5chan в каталоге приложений Bitsocial Web.
  • Что удивило: У проектов Vercel seedit и 5chan было выставлено gitProviderOptions.createDeployments = "enabled", поэтому пуши в ветку master на GitHub продвигались на продакшен-домены, хотя политика репозитория предполагает, что продакшен-зеркала приложений отдают только релизные артефакты.
  • Последствия: Значки проверенных зеркал в каталоге приложений могут стать недостоверными, потому что продакшен-домены отдают последний коммит разработки вместо релизного ZIP с GitHub, хеш index.html которого записан в about/src/lib/apps-data.ts.
  • Решение: Перед добавлением или обновлением метаданных проверки зеркал изучите проект Vercel командой vercel api /v9/projects/<project-id> и убедитесь, что gitProviderOptions.createDeployments = "disabled". Разворачивайте содержимое релизного ZIP через vercel deploy --prebuilt --prod, а для деплоев разработки используйте seedit-omega.vercel.app или 5chan-omega.vercel.app.
  • Статус: подтверждено

Portless 0.11 переиспользует старое состояние прокси, если лаунчер не форсирует HTTPS

  • Дата: 2026-04-28
  • Кем замечено: Tommaso + Codex
  • Контекст: Перевод обычного потока yarn start со старого адреса прокси http://bitsocial.localhost:1355 на https://bitsocial.localhost.
  • Что удивило: Даже с установленным portless@0.11.1 Portless переиспользовал существующий HTTP-прокси ~/.portless/proxy.port = 1355 и печатал старый адрес с :1355.
  • Последствия: Обновить версии пакетов и документацию недостаточно; yarn start всё ещё может объявлять и использовать старый адрес, если у участника осталось работающее старое состояние Portless.
  • Решение: Стартовые скрипты должны явно поднимать HTTPS-прокси Portless на порту 443 до регистрации маршрутов приложений, чтобы рантайм уходил от сохранённого состояния 1355, а не наследовал его.
  • Статус: подтверждено

Portless меняет канонический локальный URL приложения

  • Дата: 2026-03-18
  • Кем замечено: Codex
  • Контекст: Проверки в браузере и smoke-прогоны
  • Что удивило: Локальный адрес по умолчанию — не обычный порт Vite. Репозиторий ожидает https://bitsocial.localhost через Portless, поэтому проверка localhost:3000 или localhost:5173 может попасть не в то приложение или вообще никуда.
  • Последствия: Браузерные проверки могут падать или подтверждать не ту цель, даже когда дев-сервер полностью исправен.
  • Решение: Сначала используйте https://bitsocial.localhost и обходите его через PORTLESS=0 corepack yarn start только тогда, когда вам действительно нужен прямой порт Vite.
  • Статус: подтверждено

Хуки Commitizen блокируют неинтерактивные коммиты

  • Дата: 2026-03-18
  • Кем замечено: Codex
  • Контекст: Процессы коммитов, выполняемые агентами
  • Что удивило: git commit через Husky запускает Commitizen, который ждёт интерактивного ввода в TTY, из-за чего неинтерактивные оболочки агентов зависают.
  • Последствия: Агент может зависнуть на неопределённое время там, где ожидался обычный коммит.
  • Решение: Для коммитов, создаваемых агентами, используйте git commit --no-verify -m "message". Люди по-прежнему могут пользоваться corepack yarn commit или corepack yarn exec cz.
  • Статус: подтверждено

Corepack обязателен, чтобы не попасть на Yarn classic

  • Дата: 2026-03-19
  • Кем замечено: Codex
  • Контекст: Переход менеджера пакетов на Yarn 4
  • Что удивило: На машине всё ещё есть глобальная установка Yarn classic в PATH, поэтому запуск просто yarn может разрешиться в v1 вместо закреплённой версии Yarn 4.
  • Последствия: Разработчики могут случайно обойти закрепление менеджера пакетов и получить другое поведение установки или другой результат в lock-файле.
  • Решение: Используйте в командах оболочки corepack yarn ... либо сначала выполните corepack enable, чтобы просто yarn разрешался в закреплённую версию Yarn 4.
  • Статус: подтверждено

Фиксированные имена приложений Portless конфликтуют между worktree Bitsocial Web

  • Дата: 2026-03-30
  • Кем замечено: Codex
  • Контекст: Запуск yarn start в одном worktree Bitsocial Web, когда другой worktree уже раздавался через Portless
  • Что удивило: Использование буквального имени приложения Portless bitsocial в каждом worktree приводит к конфликту самого маршрута, даже если базовые порты различаются, поэтому второй процесс падает: имя bitsocial.localhost уже зарегистрировано.
  • Последствия: Параллельные ветки Bitsocial Web могут блокировать друг друга, хотя Portless задуман как раз для того, чтобы они безопасно сосуществовали.
  • Решение: Оставляйте запуск Portless за scripts/start-dev.mjs, который вне канонического случая использует привязанный к ветке маршрут *.bitsocial.localhost и переключается на такой маршрут, когда голое имя bitsocial.localhost уже занято.
  • Статус: подтверждено

Предпросмотр документации раньше жёстко использовал порт 3001

  • Дата: 2026-03-30
  • Кем замечено: Codex
  • Контекст: Запуск yarn start параллельно с другими локальными репозиториями и агентами
  • Что удивило: Корневая dev-команда запускала workspace документации через docusaurus start --port 3001, поэтому вся дев-сессия падала, если порт 3001 уже был занят другим процессом, хотя основное приложение уже работало через Portless.
  • Последствия: yarn start мог убить веб-процесс сразу после его запуска, прерывая посторонние локальные задачи из-за конфликта порта документации.
  • Решение: Оставляйте запуск документации за yarn start:docs, который теперь использует Portless вместе с scripts/start-docs.mjs, чтобы учитывать переданный свободный порт или брать следующий доступный при прямом запуске.
  • Статус: подтверждено

Имя хоста Portless для документации было жёстко зашито

  • Дата: 2026-04-03
  • Кем замечено: Codex
  • Контекст: Запуск yarn start во вторичном worktree Bitsocial Web, когда другой worktree уже раздавал документацию через Portless
  • Что удивило: start:docs всё ещё регистрировал буквальное имя хоста docs.bitsocial.localhost, поэтому yarn start мог падать, хотя about-приложение уже умело избегать конфликтов маршрутов Portless для собственного имени хоста.
  • Последствия: Параллельные worktree не могли надёжно пользоваться корневой dev-командой, потому что процесс документации завершался первым, а затем concurrently убивал остаток сессии.
  • Решение: Оставляйте запуск документации за scripts/start-docs.mjs, который теперь выводит то же привязанное к ветке имя хоста Portless, что и about-приложение, и передаёт этот общий публичный URL в цель dev-прокси /docs.
  • Статус: подтверждено

Оболочки worktree могут не увидеть закреплённую в репозитории версию Node

  • Дата: 2026-04-03
  • Кем замечено: Codex
  • Контекст: Запуск yarn start в Git-worktree, например в .claude/worktrees/* или в соседних чекаутах worktree
  • Что удивило: Некоторые оболочки worktree разрешали node и yarn node в Homebrew Node 25.2.1, хотя репозиторий закрепляет 22.12.0 в .nvmrc, поэтому yarn start мог незаметно запускать dev-лаунчеры под неверным рантаймом.
  • Последствия: Поведение дев-сервера может расходиться между основным чекаутом и worktree, из-за чего баги трудно воспроизвести, и это нарушает ожидаемую в репозитории цепочку инструментов Node 22.
  • Решение: Оставляйте dev-лаунчеры за scripts/start-dev.mjs и scripts/start-docs.mjs, которые теперь перезапускают себя под бинарником Node из .nvmrc, если текущая оболочка использует не ту версию. При настройке оболочки всё равно предпочтительнее nvm use.
  • Статус: подтверждено

Остатки docs-site/ могут скрыть отсутствие исходников документации после рефакторинга

  • Дата: 2026-04-01
  • Кем замечено: Codex
  • Контекст: Уборка монорепозитория после переноса проекта Docusaurus из docs-site/ в docs/
  • Что удивило: Старая папка docs-site/ может остаться на диске с устаревшими, но важными файлами вроде i18n/, даже после того как отслеживаемый репозиторий переехал в docs/. Из-за этого рефакторинг локально выглядит продублированным и может скрыть тот факт, что отслеживаемые переводы документации на самом деле не были перенесены в docs/.
  • Последствия: Агенты могут удалить старую папку как «мусор» и случайно потерять единственную локальную копию переводов документации либо продолжать править скрипты, которые всё ещё указывают на мёртвый путь docs-site/.
  • Решение: Считайте docs/ единственным каноническим проектом документации. Прежде чем удалять локальные остатки docs-site/, восстановите отслеживаемые исходники вроде docs/i18n/ и обновите скрипты и хуки, чтобы они перестали ссылаться на docs-site.
  • Статус: подтверждено

Мультиязычный предпросмотр документации может резко поднять расход RAM во время проверки

  • Дата: 2026-04-01
  • Кем замечено: Codex
  • Контекст: Исправление i18n документации, маршрутизации локалей и поведения Pagefind с помощью yarn start:docs и Playwright
  • Что удивило: Режим предпросмотра документации по умолчанию теперь перед раздачей выполняет полную мультиязычную сборку документации и индексацию Pagefind, и удержание этого процесса вместе с несколькими сессиями Playwright или Chrome может потреблять заметно больше RAM, чем обычный цикл Vite или одноязычный dev-режим Docusaurus.
  • Последствия: Машине может не хватить памяти, браузерные сессии могут падать, а прерванные прогоны могут оставить после себя устаревшие серверы документации или headless-браузеры, которые продолжают есть память.
  • Решение: Для работы с документацией, где не нужны проверки маршрутов локалей или Pagefind, предпочитайте DOCS_START_MODE=live yarn start:docs. Используйте мультиязычный предпросмотр по умолчанию только тогда, когда нужно проверить переведённые маршруты или Pagefind. Держите одну сессию Playwright, закрывайте старые браузерные сессии перед открытием новых и останавливайте сервер документации после проверки, если он больше не нужен.
  • Статус: подтверждено

translate-docs.py может оставить локали документации переведёнными наполовину или со сломанными целями ссылок

  • Дата: 2026-04-06
  • Кем замечено: Codex
  • Контекст: Исправление локализованных маршрутов и контента документации после того, как yarn start:docs отдавал английские страницы деталей или не собирал вывод для локали
  • Что удивило: У конвейера перевода документации оказалось сразу два специфичных для репозитория режима отказа: scripts/translate-docs.py извлекал лишь небольшую часть сообщений DocsHome, когда вызовы tr(...) использовали формы, которые он не разбирал, а переведённый markdown под docs/i18n/** мог содержать машинно-переведённые слаги или артефакты ZXQPLACEHOLDER внутри целей ссылок.
  • Последствия: Локализованные главные страницы могут молча откатываться на английский, локализованные страницы деталей могут выглядеть непереведёнными, а полная yarn docs:build может падать на сломанных ссылках локалей, хотя исходная документация корректна.
  • Решение: После изменения переводов документации или регенерации файлов локалей всегда запускайте yarn docs:build из корня репозитория, проверяйте markdown в docs/i18n/** на ZXQPLACEHOLDER и убеждайтесь, что переведённые ссылки по-прежнему указывают на канонические слаги документации вроде /apps/5chan/, а не на переведённые URL-пути. Если текст DocsHome изменился, убедитесь, что scripts/translate-docs.py всё ещё извлекает все сообщения docs.home.*.
  • Статус: подтверждено

Проверки about-сайта без JS должны идти через маршрут Portless, а не через отдельный SSR-предпросмотр

  • Дата: 2026-04-12
  • Кем замечено: Codex
  • Контекст: Проверка поддержки работы без JS для сайта about/ из worktree с веткой
  • Что удивило: Отдельный SSR-предпросмотр может выглядеть здоровым, пока реальный привязанный к ветке маршрут Portless всё ещё отдаёт не ту оболочку приложения или более старый процесс. В этом репозитории настоящий локальный контракт — это имя хоста Portless из yarn start, а не самодельный сервер предпросмотра.
  • Последствия: Агенты могут ошибочно заявить, что работа без JS в порядке, или пропустить регрессии, которые проявляются только на *.bitsocial.localhost.
  • Решение: Для браузерной проверки about/ всегда поднимайте настоящий локальный сервер через yarn start или yarn start:about и сначала тестируйте привязанный к ветке URL Portless. Если имя хоста Portless выглядит устаревшим, найдите и остановите старый процесс перед повторной проверкой.
  • Статус: подтверждено

chain/ был невидим для yarn build:verify и yarn doctor

  • Дата: 2026-07-05
  • Кем замечено: Codex
  • Контекст: Проверка диффа, затрагивающего только chain/, после того как в монорепозиторий добавили workspace chain/ (отдельное приложение Vite для chain.bitsocial.net).
  • Что удивило: scripts/verify-build.mjs распознавал только префиксы путей about/, docs/ и stats/, поэтому дифф только по chain/ печатал «No targeted build checks matched the current diff» и вообще не запускал сборку, хотя build:chain уже был в корневом package.json. Отдельно от этого yarn doctor был жёстко зашит на react-doctor about -y, поэтому изменения React в chain/src не получали никакого покрытия React Doctor.
  • Последствия: Агентам, проверяющим изменения chain, приходилось знать, что нужно вызывать yarn build:chain напрямую, вместо того чтобы доверять yarn build:verify, а проблемы React в chain/src (эффекты, хуки, мёртвый код) оставались незамеченными для yarn doctor.
  • Решение: В scripts/verify-build.mjs теперь есть ветка для chain/, зеркалящая ветку для about/, а doctor и doctor:verbose теперь запускают react-doctor --project about,chain -y одним вызовом. doctor:score остаётся только для about, потому что --score молча ничего не печатает в сочетании с --project больше чем для одного проекта; если нужна оценка для chain, используйте yarn react-doctor --project about,chain --verbose -y (или --json).
  • Статус: подтверждено

Браузерный P2P работает поверх защищённых WebSockets; pkc-js по умолчанию запрещает WebRTC и WebTransport

  • Дата: 2026-08-02
  • Кем замечено: Claude
  • Контекст: Написание текстов лендинга и документации о том, как работает браузерный P2P в Bitsocial
  • Что удивило: @pkcprotocol/pkc-js поставляется с гейтером соединений по умолчанию, который отклоняет исходящие подключения по WebRTC и WebTransport в браузере — dist/browser/helia/dial-transport-filter.js экспортирует DENIED_DIAL_TRANSPORTS_BY_DEFAULT = ["webrtc", "webrtc-direct", "webtransport"]. Комментарий в исходнике объясняет причину: в браузере эти транспорты добавляют долгие и часто неудачные пути установления соединения (STUN/ICE, ротация certhash), которые замедляют загрузку, тогда как WebSocket работает напрямую и надёжно. У каждого живого пира на панели статуса P2P в блоге показано «Secure WebSocket». Гейтер живёт в node_modules, поэтому ничто в репозитории на него не намекает.
  • Последствия: Очень легко написать технически правдоподобный, но ложный публичный текст — например приписать выходу WebTransport в браузерный Baseline в марте 2026 года заслугу того, что браузерный P2P в Bitsocial стал возможен. Это утверждение успело попасть на лендинг, в сравнительную таблицу и на две страницы документации, прежде чем разработчик его заметил. Неверные утверждения об архитектуре на публичных страницах проверяет ровно та аудитория разработчиков, на которую нацелен сайт.
  • Решение: Никогда не выводите используемые Bitsocial транспорты из того, что в принципе поддерживают libp2p или платформа браузера. Посмотрите текущий список запретов в node_modules/@pkcprotocol/pkc-js/dist/browser/helia/dial-transport-filter.js, убедитесь, что под about/src/ нет переопределения connectionGater, и прочитайте живые метки транспортов на панели «P2P status» в блоге, прежде чем делать любое публичное заявление. Апстрим-изменением, которое действительно разблокировало публикацию из браузера, было исправление монотонного seqno в gossipsub в @libp2p/gossipsub 15.0.21 (май 2026); pkc-js сейчас поставляет 16.0.4.
  • Статус: подтверждено

Относительные ссылки ./page.md со страницы документации без перевода ломают сборку каждой локали

  • Дата: 2026-08-02
  • Кем замечено: Claude
  • Контекст: Добавление новой страницы только на английском, docs/browser-p2p.md, которая ссылалась на существующую документацию через ./peer-to-peer-protocol.md и ./apps/5chan.md
  • Что удивило: Каждая локаль под docs/i18n/<lang>/docusaurus-plugin-content-docs/current/ зеркалит дерево документации. Новая страница, отсутствующая в этих зеркалах, всё равно отображается во всех локалях через откат на английский, но её относительные markdown-ссылки перестают разрешаться: Docusaurus выдаёт /ar/browser-p2p/peer-to-peer-protocol.md/ и валит сборку с «Docusaurus found broken links!». Важно, что yarn build:verify и yarn docs:build:verify собирают только en и проходят чисто; проблему показывает лишь полная yarn docs:build, и она прерывается на первой локали по алфавиту (ar).
  • Последствия: Изменение документации может пройти все быстрые локальные проверки и всё равно сломать продакшен-сборку со всеми локалями. Отказ к тому же выглядит не связанным с изменением, поскольку в ошибке фигурирует путь локали, которую автор не трогал.
  • Решение: На любой странице документации, не зеркалированной в docs/i18n/**, используйте ссылки от корня (/peer-to-peer-protocol/, /apps/5chan/) вместо относительных .md-ссылок; Docusaurus сам подставит к ним префикс локали. Готовый пример — docs/build-your-own-client.md. Прогоняйте полную yarn docs:build, а не только build:verify, прежде чем передавать любое изменение, которое добавляет страницу документации или ссылку на неё.
  • Статус: подтверждено

update-translations.js нужно запускать из about/, а параллельные запуски молча теряют ключи

  • Дата: 2026-08-02
  • Кем замечено: Claude
  • Контекст: Применение 26 переведённых ключей i18next во всех 36 локалях с помощью навыка translate
  • Что удивило: Две отдельные ловушки в одном скрипте. Во-первых, scripts/update-translations.js вычисляет свою цель как path.join(process.cwd(), "public", "translations"), но этот репозиторий хранит переводы в about/public/translations. Запуск задокументированной команды из корня репозитория падает при каждом вызове с «Translations directory not found»: в docs/agent-playbooks/translations.md показано node scripts/update-translations.js ..., что читается как команда из корня репозитория. Во-вторых, каждый вызов — это чтение-изменение-запись по всем 36 файлам локалей, поэтому два одновременных вызова затирают друг друга и один ключ пропадает без единой ошибки. Навык translate прямо предписывает запускать до 4 субагентов параллельно, и каждый из них вызвал бы этот скрипт.
  • Последствия: Форма из корня репозитория падает шумно и тратит целый проход. А вот проблема параллелизма проявляется молча: ключи пропадают из произвольных локалей, а дифф всё равно выглядит правдоподобно.
  • Решение: Запускайте так: cd about && node ../scripts/update-translations.js --key <key> --map <abs-path> --write. Никогда не позволяйте субагентам-переводчикам писать файлы локалей параллельно — пусть они выдают только JSON-словари, а затем применяйте каждый ключ последовательно из родительского агента. После применения программно проверьте, что каждый ключ присутствует во всех 35 неанглийских локалях и что ни одно значение не совпадает побайтово с английским исходником.
  • Статус: подтверждено