ここに書くのはこのプロジェクトでしか言えないことだけである。全プロジェクトに通る決めごとは共通のルールにあり、同じ文を両方に書かない。
1〜4 節は、実際に踏んだ落とし穴である。次のセッションが同じ順路を辿らないようにするのが目的で、一般論を並べる場所ではない。5・6 節は、このプロジェクトだけで行う運用手順である。
root の AGENTS.md はこの資料から生成した Markdown を 1 行で取り込んでいる。セッションを開くと本文が読み込まれる。
全体を示す設計書は notes/10_plan/p260829-01-設計.html である。README から「設計」としてリンクしている。
大きな変更は別の計画書 (notes/10_plan/pyymmdd-nn-件名.html)を立てて実装する。実装が済んだら、設計書を最新に更新する。個別の計画書は残し、設計書からリンクで参照する。
| 箇所 | 何を見るか |
|---|---|
| テーブルの役割 / スキーマ | テーブルと列。sqlite_master から取り出して貼る(推測で書かない) |
| API | 追加・変更した口 |
| コマンド表 | CLI のコマンドとオプション |
| 個別の計画書の一覧 | notes/10_plan/ の全件が表に並んでいるか。片付いたものも消さない |
スキーマは手で写さない。版を重ねるたびに写していたため、設計書が 6 か所ずれていた。cursors と archives が丸ごと無く、messages に足した 2 列と msg_kind の 2 値、索引 3 本も落ちていた。
テスト用の置き場を新しく作って版を当て、sqlite_master から取り出せばずれようがない。
計画書は設計書の表から辿れるようにする。README には代表だけを載せる。
README の資料一覧は色相を本数で割って振っている(刻み=280 ÷ (本数 − 1))。1 本足すと hsl() の指定が 28 か所すべて変わるため、計画書を足すたびに全部を振り直すことになる。
CLI は node 版 (src/client/chat.mjs)と Rust 版 (src/cli-rs/)の 2 本ある。既定の aichat を受けるのは Rust 版。かつて C# 版 (src/cli-cs/)も対比実装として持っていたが、i260918-01 で削除した。
| 守ること | 中身 |
|---|---|
| 定義は 1 か所 | 出どころは src/client/options.mjs。tools/20_build/export-options.mjs が JSON に書き出し、Rust 版が埋め込む。手で写さない |
| 実体の名前で呼ぶ | 突き合わせのテストは aichat-rs.exe を名指しする。aichat.exe は既定の別名なので、そこを見ると別の実装を試すことになる |
| 形を変えたら版を上げる | JSON の形を変えたら schema を上げる。Rust 版の EXPECTED_SCHEMA、テストの期待値も合わせる |
| 食い違いはテストが落とす | tests/cli-rs.test.mjs(16 件) ・ tools/40_test/compare-cli.mjs(54 通り) |
保守する本数だけ、食い違いは必ず出る。かつて C# 版があったときに、同じ秒に立った待受けの並び順が食い違った (C# 版はミリ秒まで持ち、node 版は秒に丸めていた)。say の本文なしの終了コードも片方だけ違っていた。Rust 版では桁の詰め方が 2 種類あることに気づくまで 8 件ずれていた。
どれも突き合わせのテストがあって初めて見つかった。目で読んで気づける差ではない。
走っている待受けが aichat.exe を掴んでいる。待受けは 12 時間張りっぱなしになるので、その間ずっと掴まれたままである。
掴んでいるのは自分の待受けだけではない。他プロジェクトの分も混ざる。止めれば相手は原因不明の exit 255 で落ちる (課題の i260901-07)。
tools/20_build/place-exe.mjs が始めに片付ける。ふつうは消し、掴まれているときだけ tmp/aichat-old-<日時>.exe へ退避する。
--- 古い exe を片付ける ---
退避済み 1 本のうち 1 本を消しました (残り 0 本は待受けが掴んでいます)
待受けが掴んでいるので退避しました: .\tmp\aichat-old-20260903-215152.exe
走っている待受けは落ちません。退避先を使い続けます
Windows では、走っている exe は削除できないが名前は変えられる。走っているプロセスは名前を変えたあとの実体を使い続けるため、退避しても落ちない。空いた名前に新しいものを置ける。
退避したものは次のビルドで消せるだけ消す。残っていても構わない。
この前提は tests/exe-swap.test.mjs が実物の exe を走らせて 1 段ずつ確かめている。理屈だけで信じない。
それぞれ自分の名前へビルドし、既定はあとから写す。ビルドが既定を直接書かない形にしておく。
| 順 | すること | 出力 |
|---|---|---|
| 1 | node tools/20_build/build-aichat-rs.mjs |
aichat-rs.exe |
| 2 | node tools/20_build/install-aichat.mjs |
aichat.exe(Rust 版の写し) |
ビルドが既定 (aichat.exe)へ直接書かないようにする。かつて C# 版のビルドが aichat.exe を出力していたため、C# 版を作っただけで既定が入れ替わった。
ビルドは「できました」と出るので気づけない。気づいたのは、その後で走らせたテストが落ちたからだった。
2 は明示して行う。ビルドのたびに既定が入れ替わると、試しに作っただけのものが他プロジェクトの待受けにまで届く。
親を止めても子は道連れにならない。archive の残骸を片付けたとき、sh.exe を 2 本止めて「片付いた」と報告したが、子の bun が 2 本生きていた(確保量 147 MB と 137 MB)。
| 起動パス | 段 |
|---|---|
run_in_background の待受け |
bash.exe 3 段 → aichat.exe |
aichat-bun |
sh.exe → bun.exe(bun が無ければ node.exe) |
psh 経由 |
sh.exe → bun.exe → powershell.exe |
実メモリだけを見ると軽く見える。残っていた bun は実メモリ 1.2 MB で、確保量は 140 MB 前後だった。確保量まで見ないと、残っていることの重さが分からない。
数え直す式が親しか見ていないと、0 件と読む。実際にそれで「片付いた」と誤って報告した。プロセス名ではなくコマンド行で探し、親子の両方を見る。
探す式に、探したい語をそのまま書かない。書くと、その式を走らせているプロセス自身が条件に当たる。'aich' + 'at' のように割って繋ぐ。1 度これで 0 件を 5 件と読み違えた。
適用条件: このプロジェクトのセッションで作業しているとき。
3 時間ごとに CronCreate で定期実行し、aichat waiters で自分の待受け本数を確認して、0 本なら張り直す。既存の待受けの出力に新着があれば全文を読み、必要な対応 (課題への追加・返信等)を行う。共通ルール「ai-chat-lite (AI 間チャット)の利用」の本体 (張り方・報告不要の原則等)はそのまま従う。
この節は共通ルールを 1 点だけ上書きする。共通ルール「ai-chat-lite (AI 間チャット)の利用」は、待受けの開始・再接続や cron の定期処理が行えたときに「✅月/日 時:分 事象名」の形で日時を添えるとし、新着なしの張り直しの報告は要らないとする。この定期実行に限っては、それに加えて毎回、受信メッセージの概要を書く(新着が無ければ「新着なし」と書く)。理由: 3 時間おきの定期実行という形自体が、あとから「いつ何が来ていたか」を追う記録の役目も兼ねるため。
cron の式は 13 */3 * * *(3 時間ごと、毎正時の 13 分)。cron はセッションの中だけで生きる(共通ルール「cron はセッションの中だけで生きる」)。セッションを開き直したときは、待受けと同様に指示を待たず張り直す。
適用条件: 環境変数を足す・消す・渡し方を変えるとき (読む側のコードも、渡す側の XML・テスト・道具も含む)。
環境変数の一覧は 環境変数の使い方 に 1 か所だけ持ち、その作業の中で直す。後回しにしない。直すのは 1 章の 2 つの表と 2 章の表で、3 つを揃える。消した変数は 3 章 (やめた変数)へ移し、表から黙って消さない。
理由: 環境変数はプロセスの一覧に出ず、渡し損ねても既定値で静かに動く。読むコードだけが残り、誰も渡していない口 (2026-10-15 時点で 2 つ)にも気づけない。
探し方は資料の 5 章に置き、ここには写さない。