責務
各ファイルが持つものと、含むべきでないもの。
| ファイル | 持つ | 持つべきでない |
|---|---|---|
domain.ts | 型とエラー。 | SDK 呼び出しや IO。 |
files.ts | ファイル検出と適応。 | RAG 検索やテキスト生成。 |
rag.ts | チャンク化とプロンプト。 | モデルライフサイクル。 |
qvac.ts | QVAC SDK 連携。 | UI やフォルダ走査。 |
store.ts | ローカル JSON 永続化。 | モデル呼び出し。 |
locallens.ts | プロダクトワークフロー。 | HTTP の詳細や DOM コード。 |
cli.ts | ターミナルインターフェース。 | RAG の内部。 |
server.ts | HTTP インターフェース。 | ビジネスロジック。 |
ui/ | ブラウザの操作。 | QVAC 呼び出し。 |
ここで意味があるのは 2 列です。「持つ」列は、その領域で機能を作るときに 触る場所です。「持つべきでない」列は、そこに入れないものです。変更が 右の列に手を出し始めたら、その変更は別のファイルに居場所を求めている サインです。
ルールの理由
domain.ts は SDK 呼び出しや IO を持つべきでない
ドメイン型は他のすべてのファイルから import されます。ここから QVAC や ファイルシステムに手を伸ばすと、依存方向が逆転し、グラフ全体が循環します。 このファイルは純粋に保ってください。
files.ts は RAG 検索やテキスト生成を持つべきでない
ファイルアダプタは LocalDocument[] を生成するだけです。チャンク化と
embedding はそのあと、rag.ts と qvac.ts で行われます。ファイル検出中に
embedding したくなる場面が来ても(たとえば重複排除のため)、抵抗して
ください。別ステップとして追加しましょう。
rag.ts はモデルライフサイクルを持つべきでない
rag.ts は ragChunk を呼びますが、モデルは読み込みません。それは QVAC
ゲートウェイの仕事です。モデルを変更しても qvac.ts だけが変わります。
rag.ts はそのまま動き続けます。
qvac.ts は UI やフォルダ走査を持つべきでない
ゲートウェイは「QVAC は何をするか?」の単一情報源です。フォルダを読みも しなければ、メッセージをレンダリングもせず、HTTP も知りません。5 つの 呼び出しの表面が頭に収まるのはこのためです。
store.ts はモデル呼び出しを持つべきでない
JSON ストアはどの brain が存在するかとそれがどのチャンクを持つかを
扱います。embedding も、検索も、生成も行いません。brain を削除すると
store.ts はエントリを除去します。QVAC 側の処理はワークフロークラスが
担当します。
locallens.ts は HTTP や DOM コードを持つべきでない
LocalLensApp はワークフロークラスです。CLI が呼び、サーバーが呼び、
UI は間接的に呼びます。どの呼び出し元も、自分の都合をこのクラスに
漏らすべきではありません。ここに request.headers が出てきたら、何かが
おかしいです。
cli.ts は RAG 内部を持つべきでない
CLI は LocalLensApp の上に乗る薄いエントリポイントの 1 つです。argv と
console.log を扱います。チャンクサイズ、embedding、プロンプトは扱いません。
RAG 挙動を変えるフラグなら、CLI ハンドラではなくワークフロー層に置きます。
server.ts はビジネスロジックを持つべきでない
CLI と同じ形。薄く保ちます。サーバーはルートマッチ、JSON パース、エラー
マッピングです。ルートハンドラ内に分岐ロジックを書いている自分に気づいた
瞬間、それは LocalLensApp の中身です。
ui/ は QVAC 呼び出しを持つべきでない
ブラウザは QVAC と直接話せませんが、ルールとしては依然重要です。UI は サーバーの JSON API とだけ会話します。チャンクサイズの定数、モデル名、 ワークスペース ID を二重に持つことはしません。
2 つのエントリポイント、1 つのコア
CLI とサーバーはどちらも薄いことに注目してください。両方とも同じコア
(LocalLensApp)に乗り、異なる表面を提供します。これがワークフロー層に
機能を足すと両方に恩恵が及ぶ理由です。サーバーのルートが新機能を得る
のと同じタイミングで CLI もそれを得ます。