Imported from RI0806123789/DriveRL (
AGENTS.md). Install upstream withnpx skills add RI0806123789/DriveRL. Copyright stays with the author.
AGENTS.md
このリポジトリで作業するコーディングエージェント(Claude Code / Codex / Copilot / Cursor など)が 最初に読むファイルです。
「作業の進め方」は CLAUDE.md にも一字一句同じものを置いてあります。
片方を直したら必ずもう片方も直すこと。
(検証スクリプトの本数が 3 つの文書でずれた実績があります。code_review U-10)
「コードの書き方」も大部分が共通です。アーキテクチャと不変条件の詳しい説明、
および memo/code_review.md との付き合い方は CLAUDE.md にあります。
DriveRL は、OpenStreetMap の実地図上でマルチエージェント強化学習(自作 PPO)の車両を走らせ、 Three.js で 3D 描画・介入できるシミュレーターです。 車両は擬似カメラ画像を CNN で認識した結果だけを見て走ります。
最初に読むもの
| ファイル | 何が書いてあるか |
|---|---|
CLAUDE.md |
アーキテクチャと壊してはいけない約束。コードを触る前に必ず読む |
README.md |
利用者向け。何ができるか・どう動かすか・つまずきやすい点 |
docs/protocol.md |
フロント ↔ バックの唯一の契約(WebSocket メッセージ・座標系) |
backend/app/contracts.py |
バックエンド内部の契約。map / sim / rl / runtime / percep はここ経由でのみやり取りする |
SECURITY.md |
モデルの読み込み・外部通信・ディスク書き込みの方針と「やってはいけないこと」 |
docs/protocol.md / frontend/src/types/protocol.ts / backend/app/contracts.py の 3 つは
セットで直すこと。 片方だけ変えると、型チェックは通るのに実行時に食い違います。
動かす
Python は backend/.venv、Node は frontend/。詳しいコマンドは CLAUDE.md「コマンド」節にあります。
.\run.ps1 -Dev # 開発。Vite も子プロセスとして面倒を見る → localhost:5173
.\run.ps1 # バックエンドのみ(frontend/dist を配信)→ 127.0.0.1:8000
-Dev でリロードするのは Vite だけです。 バックエンドを直したら Ctrl+C で止めて起動し直します
(--reload を使わないのは、学習スレッドが作り直されて学習の途中経過が消えるため)。
バックエンドを起動せずにフロントだけ触るときは npm run dev で開いて URL に ?mock=1 を付けます
(store/mockServer.ts の内蔵フェイクサーバーに繋がる。DEV ビルドのみ)。
確かめる
自動テストのフレームワークは入っていません(pytest も vitest も無い)。確認手段は次の 3 つです。
cd frontend
npm run typecheck # tsc --noEmit
npm run build # typecheck + vite build
npm run verify # 3D の幾何検証(ブラウザ不要。本数の出典は package.json の scripts)
npm run verify がある理由は、3D の向きは間違っていても型チェックもビルドも通るからです。
幾何計算を React から切り離した純粋モジュールへ置き、数値で不変条件を検査しています
(実際に灯火の並びが左右逆になっていたバグをこれが検出しました)。
バックエンドを変えたときは、スクラッチにベンチ/比較スクリプトを書いて 「新旧の結果が一致すること」と「速度」を数値で確かめてください。 このリポジトリで実際に機能している作法で、過去の指摘もこの形で裏を取っています。
性能に関わる変更は必ず金沢プリセットでも測ること。 銀座・梅田・栄は 0.8〜0.9km 四方ですが、 金沢だけ 12.3km 四方で 2 桁違います。 銀座で 2ms の処理が金沢で 1 秒になる差が実際に出ます。
作業の進め方
確認を取ってから行うこと
次の操作は、何をなぜ実行するかを伝えて承認を得てから行ってください。
- ファイル・ディレクトリの削除
git push/ 履歴を書き換える操作(rebase/reset --hard/commit --amend)/ ブランチの削除backend/data/を消すこと(学習済みの重み・認識器・マップキャッシュが入っている。 消すと Overpass からの再取得と学習のやり直しが要る)- 依存ライブラリの追加。 このプロジェクトはライブラリを足さない判断を随所でしています
(PWA は
vite-plugin-pwaも workbox も使わず手書き、グラフも自前の SVG、 アイコンは Node 標準の zlib だけで生成)。足す前に必ず相談すること
利用者から明示的に頼まれた操作には応じてかまいません(その場合も、危険な操作は内容を示して確認する)。
git
- 作業はトピックブランチで行い、
mainへ直接コミットしない。 命名は既存に合わせてfeat/.../fix/...(例:feat/detector-training-tab-and-pwa) - コミットメッセージは
feat:/fix:+ 日本語の要約。本文には **「なぜそうしたか」と「★ 壊れやすい点」**を書く(既存のログが手本) - 利用者が作業完了(機能の実装やバグ修正の完了)を報告したら、 プライバシーの確認(個人情報・鍵・ローカルの絶対パスはプレースホルダーへ)をしたうえで プルリクエストを出す。既存ブランチの再利用でかまわない
- PR・コミットにセッション URL を書かない
同時に走らせるエージェント
作業の複雑さに応じて分けてください。同時に 3 体まで。
コードの書き方
- コメントは最小限。 「何をしているか」を言い直すコメントは書かない。 名前と型で読めることはコメントにしない
- 残してよいのは次の 3 つだけ:
- Python の docstring(1 行。空にすると本体が消えて
SyntaxErrorになる箇所がある) - TypeScript の
/** ... */(1 行。公開 API の説明) - 指令コメント(
# noqa/# -*- coding/// @ts-/// eslint-など)
- Python の docstring(1 行。空にすると本体が消えて
- コメント・ドキュメント・利用者とのやり取りはすべて日本語。 変数名・識別子は英語
- 設計の意図・経緯・実測値はコードではなくこの文書と
README.mdに書く。 以前はコードのコメントに書き込むスタイルで、★を「ここを変えると気づけない形で 壊れる」印として使っていましたが、その規約は廃止しました(2026-09-15)。 いま残っている不変条件はすべてこの文書の側にあります - 失敗を握りつぶすときは必ず初回だけログを残す。 黙らせると「衝突しない世界」「速度超過 0 件」のように成績が良くなる方向に症状が出て、 外から絶対に気づけなくなります
数字を文書に手で書くとき
行数・件数・本数のような手で書いた数字は必ず古くなります。
実際に「検証スクリプトの本数」が package.json(8 本)・CLAUDE.md(7 本)・README.md(4 本)で
三つ巴にずれていた実績があります。書くなら出典(唯一の正)を併記し、
増減させたときに直す場所を明示してください。
壊すと気づけないところ
詳細は CLAUDE.md にあります。 見出しだけ挙げると:
- 観測はカメラ由来、報酬と終了条件は真値由来。 認識を誤れば赤信号に突っ込むが、判定は真値で行う
percep/camera.pyとpercep/groundtruth.pyは同じものを見ていなければならない。 描いた物体にラベルが付かない(逆も)と、認識器から見てタスクが定義できなくなる- エンジンスレッドを止める処理を入れないこと。 1 ステップの予算は 50ms(20Hz)
- 20Hz の
frameは zustand に入れない。 入れると毎秒 20 回ツリーが再レンダリングされる polygonOffsetの重ね順を崩すと Z ファイティングで点滅する- チェックポイントは必ず
weights_only=Trueで読む。フォールバックしない(SECURITY.mdにも明記) - 行動分布の平均は
tanhで -1..1 に収める。 環境はclip(-1, 1)した値しか見ないので、 制約を外すと平均が範囲外へ流れ、アクセルを正にする選択肢が構造的に消えて方策が 「止まる」に固まる(実測 -1.710。立て直しはwarmstart_policy.py) - 方策を立て直すときは価値関数と探索の幅も必ずセットで直す。 「止まる前提」の 価値を残したまま走り出すと、advantage の誤差で2 更新で元へ戻る(実測)
map/loader.pyとpublic/sw.jsのCACHE_VERSIONは、生成物の中身を変えたら上げる- 実用モード(自動運転タクシー)では重みの更新だけが止まる。 物理も推論も配信も動き続ける。 この間は全車を PPO ではなく経路追従(Pure Pursuit)で走らせ、徴用した 1 台は エピソードを閉じない。開発モードでは必ず経路追従を切ること(学習環境が変わる) (閉じると乗降地点で respawn して乗客を置き去りにする)
手元にしかないもの
memo/ は .gitignore されています(.gitignore の /memo)。開発者の手元にしかありません。
memo/code_review.md— 過去のレビュー指摘が番号付き(B/F/X/P/Q/R/W/L/M/C/S/D/A/U)で蓄積されている。コード中のコメントはこの番号を引いて 参照している(例: 「code_review B-15」)memo/memo_1.0.md— 要件定義。コード中の「memo 4章」「memo 5章」という参照の出典で、config.py/contracts.py/main.py/map//rl/buffer.pyなど 11 か所以上から参照されているmemo/system-flow.drawio— システム構成図(6 ページ)
クローンしただけの環境にこれらは存在せず、その参照は追えません。
その場合は README.md「設計上の要点」と CLAUDE.md の不変条件を一次情報としてください。