既知の想定外の挙動
このファイルでは、エージェントのミスにつながったリポジトリ固有の混乱ポイントを記録します。
エントリの追加基準
次のすべてを満たす場合にのみエントリを追加してください。
- このリポジトリに固有の内容である (一般的な助言ではない)。
- 今後のエージェントでも再発する可能性が高い。
- 実際にたどれる具体的な対処法がある。
判断に迷う場合は、エントリを追加する前に開発者に確認してください。
エントリのテンプレート
### [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
- 経緯: Bitsocial Web のアプリディレクトリで Seedit と 5chan のアプリミラーを検証していたとき。
- 想定外だった点: Vercel の
seeditおよび5chanプロジェクトがgitProviderOptions.createDeployments = "enabled"になっていたため、GitHub のmasterへのプッシュが本番ドメインに昇格されていた。リポジトリのポリシーでは、本番のアプリミラーはリリース成果物だけを配信する想定である。 - 影響: 本番ドメインが、
about/src/lib/apps-data.tsにindex.htmlのハッシュを記録している GitHub リリースの ZIP ではなく最新の開発コミットを配信するため、アプリディレクトリの検証済みミラーバッジが実態と食い違うことがある。 - 対処: ミラー検証のメタデータを追加・更新する前に、
vercel api /v9/projects/<project-id>で Vercel プロジェクトを確認し、gitProviderOptions.createDeployments = "disabled"になっていることを確かめる。リリース ZIP の中身はvercel deploy --prebuilt --prodでデプロイし、開発用のデプロイにはseedit-omega.vercel.appまたは5chan-omega.vercel.appを使う。 - ステータス: 確認済み
ランチャーが HTTPS を強制しない限り、Portless 0.11 は古いプロキシ状態を再利用する
- 日付: 2026-04-28
- 報告者: Tommaso + Codex
- 経緯: 通常の
yarn startフローを、従来のプロキシ URLhttp://bitsocial.localhost:1355から新しい正規 URL へ移行していたとき。移行先はhttps://bitsocial.localhost. - 想定外だった点:
portless@0.11.1をインストールしていても、Portless は既存の~/.portless/proxy.port = 1355の HTTP プロキシを再利用し、従来の:1355付き URL を表示した。 - 影響: パッケージのバージョンやドキュメントを更新するだけでは足りない。貢献者の環境に古い Portless の状態が残っていると、
yarn startは引き続き古い URL を告知し、実際にそれを使ってしまう。 - 対処: アプリのルートを登録する前に、起動スクリプトが明示的にポート
443で Portless の HTTPS プロキシを起動するようにしておく。そうすれば、永続化された1355の状態を引き継ぐのではなく、そこから移行できる。 - ステータス: 確認済み
Portless は正規のローカルアプリ URL を変える
- 日付: 2026-03-18
- 報告者: Codex
- 経緯: ブラウザ検証とスモークフロー
- 想定外だった点: 既定のローカル URL は通常の Vite のポートではない。このリポジトリは Portless 経由の
https://bitsocial.localhostを前提としているため、localhost:3000やlocalhost:5173を確認すると別のアプリに当たるか、まったく何も返ってこないことがある。 - 影響: 開発サーバーが正常に動いていても、ブラウザ検証が失敗したり、誤ったターゲットを検証してしまったりする。
- 対処: まず
https://bitsocial.localhostを使う。Vite のポートへ直接つなぐ必要が明確にある場合にのみ、PORTLESS=0 corepack yarn startで回避する。 - ステータス: 確認済み
Commitizen のフックが非対話的なコミットをブロックする
- 日付: 2026-03-18
- 報告者: Codex
- 経緯: エージェント主導のコミットワークフロー
- 想定外だった点:
git commitは Husky 経由で Commitizen を起動し、対話的な TTY 入力を待つため、非対話的なエージェントのシェルがハングする。 - 影響: 普通のコミットで済むはずの場面で、エージェントが無期限に止まってしまう。
- 対処: エージェントが作るコミットには
git commit --no-verify -m "message"を使う。人間は引き続きcorepack yarn commitやcorepack yarn exec czを使える。 - ステータス: 確認済み
Yarn classic を避けるには Corepack が必要
- 日付: 2026-03-19
- 報告者: Codex
- 経緯: パッケージマネージャーの Yarn 4 への移行
- 想定外だった点: このマシンには
PATH上にグローバルな Yarn classic のインストールが残っているため、素のyarnを実行すると、固定された Yarn 4 ではなく v1 に解決されることがある。 - 影響: 開発者がリポジトリのパッケージマネージャー固定をうっかり回避してしまい、インストールの挙動やロックファイルの出力が変わる。
- 対処: シェルコマンドでは
corepack yarn ...を使うか、先にcorepack enableを実行して素のyarnが固定された Yarn 4 に解決されるようにする。 - ステータス: 確認済み
固定の Portless アプリ名は Bitsocial Web のワークツリー間で衝突する
- 日付: 2026-03-30
- 報告者: Codex
- 経緯: 別のワークツリーがすでに Portless 経由で配信している状態で、ある Bitsocial Web のワークツリーで
yarn startを実行したとき - 想定外だった点: すべてのワークツリーで Portless のアプリ名にリテラルの
bitsocialを使うと、背後のポートが違ってもルート自体が衝突するため、bitsocial.localhostはすでに登録済みだとして 2 つ目のプロセスが失敗する。 - 影響: Portless は複数のブランチが安全に共存できるようにするためのものなのに、並行する Bitsocial Web のブランチ同士が互いをブロックしてしまう。
- 対処: Portless の起動は
scripts/start-dev.mjsに任せる。このスクリプトは、正規のケース以外ではブランチ単位の*.bitsocial.localhostルートを使い、素のbitsocial.localhostという名前がすでに使われている場合はブランチ単位のルートにフォールバックする。 - ステータス: 確認済み
ドキュメントのプレビューはかつてポート 3001 をハードコードしていた
- 日付: 2026-03-30
- 報告者: Codex
- 経緯: 他のローカルリポジトリやエージェントと並行して
yarn startを実行していたとき - 想定外だった点: ルートの開発コマンドがドキュメントのワークスペースを
docusaurus start --port 3001で起動していたため、別のプロセスがすでに3001を使っていると、メインのアプリが Portless を使っているにもかかわらず開発セッション全体が失敗した。 - 影響:
yarn startが起動直後に Web プロセスを落とし、ドキュメントのポート衝突のせいで無関係なローカル作業まで中断されることがあった。 - 対処: ドキュメントの起動は
yarn start:docsに任せる。このコマンドは Portless とscripts/start-docs.mjsを使い、外部から渡された空きポートを尊重するか、直接実行された場合は次に空いているポートへフォールバックする。 - ステータス: 確認済み
ドキュメント用の Portless ホスト名が固定でハードコードされていた
- 日付: 2026-04-03
- 報告者: Codex
- 経緯: 別のワークツリーがすでに Portless 経由でドキュメントを配信している状態で、副次的な Bitsocial Web のワークツリーで
yarn startを実行したとき - 想定外だった点: about アプリは自分のホスト名について Portless のルート衝突を避けられるようになっていたのに、
start:docsは依然としてリテラルのdocs.bitsocial.localhostを登録していたため、yarn startが失敗することがあった。 - 影響: ドキュメントのプロセスが先に終了し、続いて
concurrentlyがセッションの残りも落とすため、並行するワークツリーでルートの開発コマンドを安定して使えなかった。 - 対処: ドキュメントの起動は
scripts/start-docs.mjsに任せる。このスクリプトは about アプリと同じブランチ単位の Portless ホスト名を導出し、その共有 URL を/docsの開発プロキシのターゲットへ注入する。 - ステータス: 確認済み
ワークツリーのシェルはリポジトリが固定した Node バージョンを取り逃すことがある
- 日付: 2026-04-03
- 報告者: Codex
- 経緯:
.claude/worktrees/*や兄弟のワークツリーチェックアウトなどでyarn startを実行したとき - 想定外だった点: リポジトリは
.nvmrcで22.12.0を固定しているのに、一部のワークツリーのシェルではnodeとyarn nodeが Homebrew の Node25.2.1に解決され、yarn startが誤ったランタイムで開発ランチャーを動かしかねなかった。 - 影響: メインのチェックアウトとワークツリーとで開発サーバーの挙動がずれ、バグの再現が難しくなるうえ、リポジトリが想定する Node 22 のツールチェーンにも反する。
- 対処: 開発ランチャーは
scripts/start-dev.mjsとscripts/start-docs.mjsに任せる。これらは、現在のシェルのバージョンが違う場合に.nvmrcの Node バイナリで自身を再実行する。シェルの設定側でもnvm useを優先すること。 - ステータス: 確認済み
リファクタ後、docs-site/ の残骸がドキュメントソースの欠落を隠すことがある
- 日付: 2026-04-01
- 報告者: Codex
- 経緯: Docusaurus プロジェクトを
docs-site/からdocs/へ移した後の、マージ後のモノレポ整理 - 想定外だった点: 追跡対象のリポジトリが
docs/へ移った後も、古いdocs-site/フォルダがi18n/のような古くはあるが重要なファイルを抱えたままディスクに残ることがある。そのためローカルではリファクタが二重になったように見え、追跡対象のドキュメント翻訳が実際にはdocs/へ移されていないという事実が隠れてしまう。 - 影響: エージェントが古いフォルダを「ゴミ」とみなして削除し、ドキュメント翻訳の唯一のローカルコピーを失ったり、すでに存在しない
docs-site/のパスを参照し続けるスクリプトを編集し続けたりする。 - 対処:
docs/を唯一の正規ドキュメントプロジェクトとして扱う。ローカルのdocs-site/の残骸を削除する前に、docs/i18n/のような追跡対象のソースを復元し、スクリプトやフックがdocs-siteを参照しないように更新する。 - ステータス: 確認済み
多言語ドキュメントのプレビューは検証中に RAM を大きく消費しうる
- 日付: 2026-04-01
- 報告者: Codex
- 経緯:
yarn start:docsと Playwright を使って、ドキュメントの i18n、ロケールルーティング、Pagefind の挙動を修正していたとき - 想定外だった点: ドキュメントプレビューの既定モードは、配信の前に多言語ドキュメントのフルビルドと Pagefind のインデックス作成を行うようになった。そのプロセスを起動したまま Playwright や Chrome のセッションを複数動かすと、通常の Vite や単一ロケールの Docusaurus 開発ループよりもはるかに多くの RAM を消費する。
- 影響: マシンのメモリが逼迫してブラウザセッションがクラッシュしたり、中断された実行が古いドキュメントサーバーやヘッドレスブラウザを残してメモリを食い続けたりする。
- 対処: ロケールルートや Pagefind の検証が不要なドキュメント作業では
DOCS_START_MODE=live yarn start:docsを優先する。既定の多言語プレビューは、翻訳されたルートや Pagefind を検証する必要があるときにだけ使う。Playwright のセッションは 1 つに保ち、新しいセッションを開く前に古いものを閉じ、検証が終わって不要になったドキュメントサーバーは停止する。 - ステータス: 確認済み
translate-docs.py はドキュメントのロケールを中途半端な翻訳や壊れたリンク先のまま残すことがある
- 日付: 2026-04-06
- 報告者: Codex
- 経緯:
yarn start:docsが英語の詳細ページを配信したりロケール出力のビルドに失敗したりした後、ローカライズされたドキュメントのルートとコンテンツを修正していたとき - 想定外だった点: ドキュメント翻訳のパイプラインには、このリポジトリ固有の失敗モードが同時に 2 つあった。
scripts/translate-docs.pyは、tr(...)の呼び出しがパースできない書き方だとDocsHomeのメッセージをごく一部しか抽出しなかった。また、docs/i18n/**配下の翻訳済みマークダウンには、リンク先の中に機械翻訳されたスラッグやZXQPLACEHOLDERの残骸が混じることがあった。 - 影響: ローカライズされたホームページが黙って英語にフォールバックしたり、ローカライズされた詳細ページが未翻訳のまま見えたり、元のドキュメント自体は正しいのにロケールのリンク切れで
yarn docs:build全体が失敗したりする。 - 対処: ドキュメント翻訳を変更したりロケールファイルを再生成したりしたら、必ずリポジトリのルートから
yarn docs:buildを実行し、docs/i18n/**のマークダウンにZXQPLACEHOLDERが残っていないか調べ、翻訳されたリンクが翻訳済みの URL パスではなく/apps/5chan/のような正規のドキュメントスラッグを指したままか確認する。DocsHomeの文言が変わった場合は、scripts/translate-docs.pyがdocs.home.*のメッセージをすべて抽出できているかを確かめる。 - ステータス: 確認済み
about サイトの no-JS チェックは、単独の SSR プレビューではなく Portless のルートで行う
- 日付: 2026-04-12
- 報告者: Codex
- 経緯: ブランチのワークツリーから
about/サイトの no-JS 対応を検証していたとき - 想定外だった点: 単独の SSR プレビューが正常に見えていても、実際のブランチ単位の Portless ルートは誤ったアプリシェルや古いプロセスを配信していることがある。このリポジトリでのローカルの本当の契約は、その場しのぎのプレビューサーバーではなく
yarn startが使う Portless のホスト名である。 - 影響: エージェントが no-JS 対応は動いていると誤って主張したり、
*.bitsocial.localhostでしか現れないリグレッションを見逃したりする。 - 対処:
about/のブラウザ検証では、必ずyarn startまたはyarn start:aboutで本物のローカルサーバーを起動し、まずブランチ単位の Portless URL でテストする。Portless のホスト名が古そうに見える場合は、再テストの前に古いプロセスを調べて停止する。 - ステータス: 確認済み
chain/ が yarn build:verify と yarn doctor から見えていなかった
- 日付: 2026-07-05
- 報告者: Codex
- 経緯:
chain/ワークスペース (chain.bitsocial.net向けのスタンドアロン Vite アプリ) をモノレポに追加した後、chain/ だけの差分を検証していたとき。 - 想定外だった点:
scripts/verify-build.mjsはabout/、docs/、stats/のパスプレフィックスしか認識していなかったため、ルートのpackage.jsonにすでにbuild:chainがあるにもかかわらず、chain/ だけの差分では "No targeted build checks matched the current diff" と表示され、ビルドが一切実行されなかった。さらにyarn doctorはreact-doctor about -yにハードコードされていたため、chain/src配下の React の変更は React Doctor のカバレッジがゼロだった。 - 影響: chain の変更を検証するエージェントは、
yarn build:verifyを信頼する代わりにyarn build:chainを直接呼ぶ必要があると知っていなければならず、chain/srcの React の問題 (エフェクト、フック、デッドコード) はyarn doctorでは検出されなかった。 - 対処:
scripts/verify-build.mjsにはabout/と同じ形のchain/分岐が追加され、doctorとdoctor:verboseは 1 回の呼び出しで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
- 経緯: Bitsocial のブラウザ P2P の仕組みについて、ランディングページとドキュメントの文章を書いていたとき
- 想定外だった点:
@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の中にあるため、リポジトリ内にはその存在を示唆するものが何もない。 - 影響: 技術的にはもっともらしいが実際には誤った公開向けの文章を、とても書きやすい。たとえば、2026 年 3 月に WebTransport がブラウザの Baseline に到達したことが Bitsocial のブラウザ P2P を可能にした、という説明である。その主張は開発者が気づくまでに、ランディングページ、比較表、ドキュメント 2 ページに出てしまっていた。公開ページのアーキテクチャに関する誤りは、まさにサイトが対象としている開発者層に見抜かれる。
- 対処: Bitsocial がどのトランスポートを使っているかを、libp2p やブラウザプラットフォームが原理的にサポートしているものから推測してはいけない。現在の拒否リストは
node_modules/@pkcprotocol/pkc-js/dist/browser/helia/dial-transport-filter.jsで確認し、about/src/配下にconnectionGaterの上書きがないことを確かめ、公開向けの主張をする前にブログの「P2P status」パネルで実際のトランスポートのラベルを読むこと。ブラウザからの公開を実際に可能にしたアップストリームの変更は、@libp2p/gossipsub15.0.21 (2026 年 5 月) の gossipsub における単調増加 seqno の修正である。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/配下の各ロケールはドキュメントツリーを鏡写しにしている。それらのミラーに存在しない新しいページも英語フォールバックによってすべてのロケールで描画されるが、その相対マークダウンリンクはもう解決されない。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/**にミラーされていないドキュメントページでは、相対的な.mdリンクではなくルート相対のリンク (/peer-to-peer-protocol/、/apps/5chan/) を使う。Docusaurus が自動的にロケールのプレフィックスを付けてくれる。既存の例はdocs/build-your-own-client.mdである。ドキュメントページを追加したりリンクしたりする変更を引き渡す前には、build:verifyだけでなく完全なyarn docs:buildを実行すること。 - ステータス: 確認済み
update-translations.js は about/ から実行する必要があり、同時実行は黙ってキーを失う
- 日付: 2026-08-02
- 報告者: Claude
- 経緯:
translateスキルを使って、翻訳済みの i18next キー 26 個を 36 ロケールすべてへ適用していたとき - 想定外だった点: 同じスクリプトに罠が 2 つあった。1 つ目は、
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 ...と書かれており、これはリポジトリのルートで実行するコマンドに読める。2 つ目は、1 回の実行が 36 個すべてのロケールファイルに対する read-modify-write になっているため、2 つの実行が同時に走ると互いを上書きし、エラーも出ないままキーが 1 つ消えること。translateスキルは最大 4 つのサブエージェントを同時に起動するよう明示的に指示しており、そのいずれもがこのスクリプトを呼ぶ。 - 影響: リポジトリのルートで実行する形は派手に失敗し、1 パス分の作業をまるごと無駄にする。同時実行の問題は静かに失敗する。任意のロケールからキーが消え、それでも差分はもっともらしく見える。
- 対処:
cd about && node ../scripts/update-translations.js --key <key> --map <abs-path> --writeの形で実行する。翻訳のサブエージェントにロケールファイルを同時に書かせてはいけない。サブエージェントには辞書の JSON ファイルだけを出力させ、親エージェントからキーを 1 つずつ順番に適用する。適用後は、各キーが英語以外の 35 ロケールすべてに存在すること、どの値も英語の原文とバイト単位で一致していないことをプログラムで検証する。 - ステータス: 確認済み