Перейти до основного вмісту

Відомі несподіванки

У цьому файлі зібрано специфічні для репозиторію моменти плутанини, які призводили до помилок агентів.

Критерії для запису

Додавайте запис лише тоді, коли виконано всі умови:

  • Це стосується саме цього репозиторію (а не загальна порада).
  • Це, найімовірніше, повториться в майбутніх агентів.
  • Для цього є конкретний спосіб обійти проблему, якого можна дотримуватися.

Якщо ви не впевнені, запитайте розробника, перш ніж додавати запис.

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

### [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 можуть відкочуватися до розгортань з гілки master у Git

  • Дата: 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 змінює канонічну локальну адресу застосунку

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

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

  • Дата: 2026-03-18
  • Помітили: Codex
  • Контекст: Робочі процеси створення комітів агентами
  • Що виявилося несподіваним: git commit запускає Commitizen через Husky і чекає на інтерактивне введення в 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 конфліктують між робочими деревами Bitsocial Web

  • Дата: 2026-03-30
  • Помітили: Codex
  • Контекст: Запуск yarn start в одному робочому дереві Bitsocial Web, коли інше робоче дерево вже роздавало застосунок через Portless
  • Що виявилося несподіваним: Використання буквального імені застосунку Portless bitsocial у кожному робочому дереві призводить до конфлікту самого маршруту навіть тоді, коли базові порти різні, тож другий процес падає, бо bitsocial.localhost уже зареєстровано.
  • Наслідки: Паралельні гілки Bitsocial Web можуть блокувати одна одну, хоча Portless має давати їм безпечно співіснувати.
  • Як обійти: Тримайте запуск Portless за scripts/start-dev.mjs: цей скрипт тепер поза канонічним випадком використовує прив’язаний до гілки маршрут *.bitsocial.localhost і переходить на такий маршрут, коли просте ім’я bitsocial.localhost уже зайняте.
  • Статус: підтверджено

Раніше попередній перегляд документації жорстко задавав порт 3001

  • Дата: 2026-03-30
  • Помітили: Codex
  • Контекст: Запуск yarn start паралельно з іншими локальними репозиторіями та агентами
  • Що виявилося несподіваним: Коренева dev-команда запускала робочу область документації через docusaurus start --port 3001, тому вся сесія розробки падала щоразу, коли 3001 уже займав інший процес, хоча основний застосунок уже працював через Portless.
  • Наслідки: yarn start міг убити вебпроцес одразу після його запуску, перериваючи не пов’язану з цим локальну роботу через конфлікт порту документації.
  • Як обійти: Тримайте запуск документації за yarn start:docs: тепер він використовує Portless разом зі scripts/start-docs.mjs, щоб врахувати переданий вільний порт або перейти на наступний доступний порт при прямому запуску.
  • Статус: підтверджено

Фіксоване ім’я хоста документації в Portless було жорстко задане

  • Дата: 2026-04-03
  • Помітили: Codex
  • Контекст: Запуск yarn start у додатковому робочому дереві Bitsocial Web, коли інше робоче дерево вже роздавало документацію через Portless
  • Що виявилося несподіваним: start:docs усе ще реєстрував буквальне ім’я хоста docs.bitsocial.localhost, тому yarn start міг падати, хоча застосунок about уже вмів уникати конфліктів маршрутів Portless для власного імені хоста.
  • Наслідки: Паралельні робочі дерева не могли надійно користуватися кореневою dev-командою, бо процес документації завершувався першим, а concurrently після цього вбивав решту сесії.
  • Як обійти: Тримайте запуск документації за scripts/start-docs.mjs: тепер він виводить те саме прив’язане до гілки ім’я хоста Portless, що й застосунок about, і підставляє цю спільну публічну адресу як ціль dev-проксі для /docs.
  • Статус: підтверджено

Оболонки в робочих деревах можуть не підхопити закріплену в репозиторії версію Node

  • Дата: 2026-04-03
  • Помітили: Codex
  • Контекст: Запуск yarn start у робочих деревах Git, як-от .claude/worktrees/* або в сусідніх копіях робочих дерев
  • Що виявилося несподіваним: Деякі оболонки в робочих деревах розв’язували node і yarn node у Homebrew Node 25.2.1, хоча репозиторій закріплює 22.12.0 у .nvmrc, тож yarn start міг непомітно запускати лаунчери розробки на неправильному середовищі виконання.
  • Наслідки: Поведінка dev-сервера може розходитися між основною копією та робочими деревами, через що баги важко відтворити, а очікуваний для репозиторію інструментарій Node 22 порушується.
  • Як обійти: Тримайте лаунчери розробки за 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 або на 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/** міг містити машинно перекладені slug-и або артефакти ZXQPLACEHOLDER усередині цілей посилань.
  • Наслідки: Локалізовані головні сторінки можуть непомітно відкочуватися до англійської, локалізовані сторінки з деталями можуть виглядати неперекладеними, а повна збірка yarn docs:build може падати на поламаних посиланнях у локалі, хоча вихідна документація коректна.
  • Як обійти: Після зміни перекладів документації чи регенерації файлів локалей завжди запускайте yarn docs:build з кореня репозиторію, перевіряйте markdown у docs/i18n/** на наявність ZXQPLACEHOLDER і переконуйтеся, що перекладені посилання й далі ведуть на канонічні slug-и документів, як-от /apps/5chan/, а не на перекладені шляхи URL. Якщо текст DocsHome змінився, переконайтеся, що scripts/translate-docs.py усе ще витягує всі повідомлення docs.home.*.
  • Статус: підтверджено

Перевірки сайту about без JS мають використовувати маршрут Portless, а не окремий SSR-перегляд

  • Дата: 2026-04-12
  • Помітили: Codex
  • Контекст: Перевірка підтримки роботи без JS для сайту about/ з робочого дерева гілки
  • Що виявилося несподіваним: Окремий SSR-перегляд може виглядати справним, тоді як справжній прив’язаний до гілки маршрут Portless усе ще віддає не ту оболонку застосунку або старіший процес. У цьому репозиторії реальний локальний контракт — це ім’я хоста Portless із yarn start, а не імпровізований сервер попереднього перегляду.
  • Наслідки: Агенти можуть помилково стверджувати, що робота без JS підтримується, або пропустити регресії, які виявляються лише на *.bitsocial.localhost.
  • Як обійти: Для перевірки about/ у браузері завжди запускайте справжній локальний сервер через yarn start або yarn start:about і спершу тестуйте прив’язану до гілки адресу Portless. Якщо ім’я хоста Portless виглядає застарілим, огляньте й зупиніть старий процес перед повторним тестуванням.
  • Статус: підтверджено

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

  • Дата: 2026-07-05
  • Помітили: Codex
  • Контекст: Перевірка діфа, що стосувався лише chain/, після того як робочу область 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 постачається з типовим connection gater, який відхиляє спроби з’єднання через 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". Цей gater лежить у node_modules, тому ніщо в самому репозиторії на нього не натякає.
  • Наслідки: Дуже легко написати технічно правдоподібний, але хибний публічний текст — наприклад, приписати можливість браузерного P2P у Bitsocial тому, що WebTransport досяг статусу Baseline у браузерах у березні 2026 року. Це твердження потрапило на лендинг, у порівняльну таблицю та на дві сторінки документації, перш ніж розробник його помітив. Хибні твердження про архітектуру на публічних сторінках перевіряє саме та аудиторія розробників, на яку націлений сайт.
  • Як обійти: Ніколи не робіть висновків про те, які транспорти використовує 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 неанглійських локалях і що жодне значення не збігається побайтово з англійським джерелом.
  • Статус: підтверджено