


層に分かれたデスクトップアプリに機能を足し、全部のビルドでテストする
コア・デスクトップのホスト・WebのUIに分かれたデスクトップアプリをAIに直させる時に使う。決まりはコアに置き、ツールが触れるコマンドとフォルダを絞り、オプション機能を実際の依存関係で切り分け、対応する全部のビルドでテストしてから完了にする。
このAIルールを使うには
## コア・デスクトップのホスト・UIが、それぞれ何を受け持つか決める
コードを変更する前に、出荷対象のプラットフォーム、対応クライアント、プロセス構成、信頼境界を定義する。
- ビジネスルール、永続化、実行処理、ドメインの挙動は、権威あるコアに置く。
- デスクトップホストは、ライフサイクル、ネイティブ機能、安全な橋渡し、パッケージングを担当する。
- Web向けUIは、表示、ナビゲーション、オーケストレーションを担当する。レンダラーにコアのルールを重複実装しない。
- UIからコアへの呼び出しは、その場しのぎの直接アクセスではなく、認証済みの単一通信抽象層を通す。
- 実験的なクライアントは、通信方式、暗号化、リリース状態を明示した独立の互換性対象として扱う。
- 各層、各層が所有する状態、公開インターフェース、禁止される責務を記したアーキテクチャマップを維持する。
## コマンドを危なさで分け、ツールが触れるフォルダを絞る
設定を一元管理し、動作を実行するすべてのツールに、判断不能時は拒否する単一方針を適用する。
- 環境値は型付き設定モジュールから読み取る。機能コードからプロセス環境変数やビルド時環境変数へ直接アクセスしてはならない。
- 自律性は、ワークスペース制限、信頼済みルート、インストール権限と組み合わせた明示的な段階としてモデル化する。
- コマンドを読取、書込、ネットワーク、インストール、破壊操作に分類する。認識できないコマンドは書込操作として扱う。
- 有効な段階に従って、各分類を許可、確認、ブロックのいずれかに解決する。システム領域と認証情報の領域は常にブロックする。
- ユーザー操作のルートとアプリケーション内部の状態を分離する。ツールは操作ルート内だけで動作でき、内部状態へ直接書き込んではならない。
- 対話的な変更操作では承認ゲートを既定で有効にし、応答のない要求には有効期限を設け、期限切れ時は操作を拒否する。
- アプリケーション側のパス検証と、OSまたはコンテナのサンドボックスを組み合わせる。サンドボックスは多層防御であり、方針検査の代わりではない。
## コアの中を、ドメインごとのモジュールに分ける
各ドメインに専用モジュールを割り当て、所有範囲を明確にし、ファイルを小さく組み合わせ可能に保つ。
### 標準モジュール構成を使う
- モジュールのファサードはエクスポートに専念させ、ビジネスロジックを置かない。
- その責務が存在する場合は、直列化可能なドメイン型、永続化、操作、コントローラースキーマ、エージェントツール、イベント購読処理、テストを別々のファイルに置く。
- ドメインが所有するツールはそのドメインに置き、共有ツール基盤は本当に横断的な挙動だけに使う。
- 通信モジュールは認証、ディスパッチ、ログ、可観測性、プロトコルに関する処理だけに限定する。
スキーマとハンドラーの組を持つレジストリを通じてコントローラーを公開する。新しい挙動ではドメインコントローラーを追加し、1か所の合成地点に登録する。通信コード全体へコマンド名の分岐を増やしてはならない。
## 実行時のオン・オフと、コンパイル時の機能を分けて扱う
独立した2つの軸としてモデル化する。
- サービスセットは、実行するバックグラウンドサービスと通信方式を選択する。
- ドメインセットは、実行時に利用できるドメイン群を選択する。
- コンパイル時機能は、製品バリエーションに応じてコードと依存関係をビルド対象から外す。
実行時フィルタリングでは、無効なドメインのコントローラー、ツール、ストア、購読処理を稼働中の機能面から除外しなければならない。コンパイル時ゲートは既定ビルドを変えずに、この挙動と組み合わせて機能しなければならない。スキーマ、ディスパッチ、ツール、起動サービスの間にずれが生じないよう、登録地点を権威ある正本に保つ。
## 実際の依存関係を見て、オプション機能の外し方を選ぶ
常時有効な挙動を保てる最小のゲートを選ぶ。
1. 外部参照がすべて登録地点にある場合は、末端ゲートを使う。無効化された機能面は、失敗するスタブとして登録するのではなく、存在させない。
2. 常にコンパイルされる呼び出し元が呼び出し可能なシンボルを必要とする場合だけ、挙動スタブを備えたファサードを使う。
3. 依存関係を持たない共有型は常時コンパイルされるモジュールへ切り出し、スタブ化するのは挙動だけにする。有効ビルドと無効ビルドの間で型定義を重複させてはならない。
4. 一部のユーティリティが常時有効なドメインに使われる場合は、ディレクトリを分割する。フォルダ名ではなく、実際の依存辺をゲートする。
5. オプションドメインの下にあっても、動作を支える必須ヘルパーは維持する。必要な実装を、成功したように見えるスタブへ置き換えてはならない。
機能がコンパイル対象外でもコマンドが表示される場合は、誤解を招く未知コマンドエラーではなく、無効ビルドであることを明示するエラーを返す。無効なコンポーネント名がコンパイル後も残るデータでは、存在しない識別子を許容して解決できるようにし、その契約をテストする。
コンパイルが成功したという事実だけで、機能ゲートが依存関係を取り除いたと主張してはならない。無効構成で依存ツリーを逆引きし、取り除いたとする依存関係を1件ずつ実証する。
## オプション機能を入れたビルドと外したビルドを両方テストする
テストをアーキテクチャの一部として扱い、挙動、統合、パッケージングを網羅する。
- 焦点を絞った単体テストを対象コードの近くに置き、実装詳細より観察可能な挙動を優先する。
- 決定的な統合テストには共有モックサービスを使う。単体テストスイートでは、実ネットワークアクセスと時間依存のsleepを禁止する。
- 実装前に、正常系、失敗、認可ゲート、回復を含むE2Eシナリオを定義する。
- オプション機能は両方向でテストする。有効時の登録と、無効時に存在しないことを実証する。
- 無効ビルドのテストスイートを明示的に実行する。コンパイルだけの簡易レーンではテストコードがコンパイルされないため、ゲート対象のテストが引き続き有効だとは証明できない。
- 変更行のカバレッジしきい値を強制し、共有設定または基礎契約を変更した場合は全テストスイートへ切り替える。
- ビルドシステムが許す場合は、高コストなプラットフォーム成果物を1回だけビルドし、その成果物からテストを分岐して実行する。
## 秘密情報や個人データを残さない診断ログを足す
新規または変更された処理フローには、開始、終了、分岐、外部呼び出し、再試行、タイムアウト、状態遷移、エラーの各地点で診断を用意する。
- 安定して検索しやすいドメイン接頭辞と、リクエストIDやメソッド名などの相関項目を使う。
- 通常ログは簡潔に保ち、debugとtraceレベルには対象を絞った調査に十分な情報を持たせる。
- 秘密情報、生の認証情報、個人データの全文、ユーザーが作成したコンテンツ、エンティティ識別子、ファイル名、生のエラーメッセージを分析サービスへ絶対に記録しない。
- 分析イベントは、同意状態を考慮する単一の機能APIを通し、内容を含まない安定したイベント名を使う。
- 変更によって新しい実行経路が生まれる場合、診断が欠けていれば実装未完了として扱う。
## UIの文字を全部翻訳し、自動生成の文書は手で直さない
ローカルな近道ではなく、一元化された状態、通信、ローカライズを使う。
- 分散したブラウザストレージではなく、指定されたアプリケーション状態層を優先する。
- コアへのすべての呼び出しには共有コアクライアントを使い、並行する通信方式の挙動を一致させる。
- ネイティブ専用APIは、対応する実行環境検出器とエラー境界を通じて保護する。
- 表示されるすべての文字列をローカライズに通し、対応するすべてのロケールへ実際の翻訳を追加し、補間プレースホルダーを完全に維持する。
- 完了前に、ローカライズの構文、英語混入、カバレッジを検査する。
- 自動生成されるドキュメントブロックを手作業で編集してはならない。ソースマーカーを更新して再生成し、古い生成物は差分検査で失敗させる。
- 埋め込みの外部ビューへスクリプト注入を追加しない。新しい挙動は、ネイティブハンドラー、プロトコルツール、制御されたIPCフックを通じて実装する。
## 機能をコアからUIまで順に作り、層ごとにテストしてから進む
固定された縦方向の手順に従う。
1. 既存のドメイン契約、命名規則、セキュリティ方針、E2Eシナリオから挙動を仕様化する。
2. 権威あるドメインロジックを単体テストとともに実装する。
3. コントローラーまたはRPC境界を統合テストで実証する。
4. ルールをコアに保ちながら、共有クライアントを通じてUIに挙動を提供する。
5. UI単体テストとプラットフォームE2Eの網羅を追加する。
6. 機能を追加、廃止、名前変更した場合は、ユーザー向け機能メタデータとアーキテクチャ文書を更新する。
現在の層が未テストのまま次の層へ進んではならない。モジュールは小さく単一目的に保ち、ドキュメントはそれが管理する挙動とともに更新する。
## 必須のチェックを飛ばさず、結果を見てから完了と言う
専用ブランチで変更し、リポジトリが指定する統合ブランチを対象にし、本番リリースを宣言済みのリリース元に結び付ける。
- リポジトリのルートから、正本のパッケージマネージャー、固定版ツールチェーン、フォーマッター、リンター、型チェッカー、テストランナーを使う。
- 別々にビルドされるネイティブコンポーネント間で、同等のビルドプロファイル設定を同期する。
- 失敗を隠すために必須フックや検査を絶対に迂回しない。フックがファイルを生成した場合は、その結果を確認して含めた上で、フックを再実行する。
- 変更が原因の失敗は修正する。既存の無関係な阻害要因は、安全策を黙って弱めるのではなく文書化する。
- 最終差分を見直し、実装、テスト、スキーマ、自動生成成果物、ローカライズ、ドキュメントの整合性を確認する。
- 変更したすべての層と対応するビルド構成に関係する検査の直接結果がないまま、完了を宣言してはならない。
