# アーキテクチャポリシー

アーキテクチャに関する独立した判定を一つの正本で行う。

## 原則

| 原則 | 基準 |
|------|------|
| 適用条件を確認 | 元要件、変更契約、実在する影響経路に基づいて適用する |
| 事実を根拠にする | コード、契約、証跡で確認できる条件だけを判定する |
| 責務境界を守る | 判定対象の所有者と観測可能な影響を分けて確認する |
| 最小範囲に限定する | 今回の要求と因果関係のある範囲だけを判定する |
| 判定根拠を統一する | 元要件、変更契約、実在する影響経路から導けない例示を判断基準に追加しない |

## アーキテクチャ 判定基準

### データ量と資源の境界

対象操作の要求、入力の上限、取得から消費までの実在経路に基づいて判定する。全件の処理が必要なことと、全件を同時に保持する必要があることを分ける。

| 基準 | 判定 |
|------|------|
| 一部の結果を返す操作で、必要性なく上限のない入力を全件取得・実体化してから制限する | REJECT |
| 逐次消費できる全件処理で、契約上の必要性なく全件を蓄積してから消費先へ渡す | REJECT |
| 全件出力や正確な集計に必要な走査を、資源対策として途中で打ち切り結果を欠落させる | REJECT |
| 要求に必要な全件を走査しつつ、保持量と未消費の処理量を制御する | OK |
| 実効的な入力上限がある、または全体保持が必要な契約・アルゴリズムに根拠がある | OK。確認した保持量と適用条件で判断する |

### 複数失敗を集約する境界

| 基準 | 判定 |
|------|------|
| status、分類、表示理由、abort 理由を別々の結果から作る | REJECT |
| 分類した結果を選ぶ前に汎用エラーへ置き換える | REJECT |
| 並列処理や batch ごとの優先順位を、共通の分類処理に埋め込む | REJECT |
| 分類、基準となる結果の選択、出力を別々の処理が担当する | OK |
| 対象の処理に定められた規則で結果を一度選び、すべての判断と表現をそこから作る | OK |

### 構造・設計

| 判定 | 基準 |
|------|------|
| REJECT | インフラ層の関数がパブリック API からエクスポートされている |
| REJECT | 内部実装の関数が外部から直接呼び出し可能になっている |
| OK | 外部消費者がドメインレベルの抽象のみを通じて対話する |

### 共有層と責務境界

| 判定 | 基準 |
|------|------|
| REJECT | `shared` や汎用ユーティリティが特定 feature の所有データ・型へ依存する |
| REJECT | 共有モジュールが feature 固有の整形・解析とインフラ I/O を同時に所有する |
| REJECT | 同じ変更で別々に変わる責務を一つのモジュールへ集約する |
| OK | 共有モジュールがドメイン非依存の契約を扱い、単一の責務と変更理由を持つ |

### 例外の外部表現への変換

| 基準 | 判定 |
|------|------|
| endpoint / handler ごとに同じ例外から同じプロトコル表現への変換を実装している | REJECT |
| プロトコル表現への変換が application/domain 層に入っている | REJECT |
| 特定 API 固有の例外変換を全 API 共通の global handler に置いている | REJECT |
| adapter 境界の例外変換レイヤで、外部表現への変換を一元化している | OK |

### 境界での解決

| 基準 | 判定 |
|------|------|
| 入口で `ExecutionContext` や `ResolvedOptions` のような解決済みオブジェクトを作る | OK |
| オーケストレーション層が解決済みの値だけを扱う | OK |
| 下位層が global/project/env を再読込して同じ値を再解決する | REJECT |
| 表示用と実行用で別々の解決関数を持つ | REJECT |
| 未解決の options を深い層まで運び、先で `??` 解決する | REJECT |

### Tell, Don't Ask

| パターン | 判定 |
|---------|------|
| 上位層が `resolvedProvider` のような値を渡す | OK |
| 下位層が `options` を覗いて自前で解決する | REJECT |
| 実行オブジェクトが `setup(config)` 後は `run()` だけ公開する | OK |
| 実行中に `getGlobalConfig()` を呼んで分岐する | REJECT |

### 腐敗防止層

| パターン | 判定 |
|---------|------|
| YAML/env/CLI 差分を resolver/adapter に閉じ込める | OK |
| ドメイン層が env 名や設定キー文字列を直接扱う | REJECT |
| 外部形式から内部形式への変換が1箇所に集約されている | OK |
| 同じ正規化ロジックが複数箇所にコピーされている | REJECT |

### 候補解決と値合成の分離

| 基準 | 判定 |
|------|------|
| 候補探索が first-match なのに、値合成の deep merge と混同して複数候補を暗黙に合成する | REJECT |
| 近いスコープの候補が遠いスコープの候補より後に探索される | REJECT |
| 参照文字列を「区切り文字を含むか」だけで分類し、特殊参照と明示パスを混同する | REJECT |
| 候補探索、参照種別の分類、値合成の責務が別関数として読める | OK |

### Raw入力の正規化

| 基準 | 判定 |
|------|------|
| parse 直後の unknown 値に配列メソッドやプロパティアクセスを直接行う | REJECT |
| 「存在する」だけでファイル種別やディレクトリ要件を満たしたと扱う | REJECT |
| unknown を境界で内部型へ正規化し、契約外shapeを無視・正規化・明示エラーのいずれかに固定する | OK |
| ファイルとディレクトリの要件を実体種別まで確認する | OK |

### フェーズ分離

| 基準 | 判定 |
|------|------|
| 入口で raw input を `Resolved*` 型へ変換してから本処理に渡す | OK |
| ループ本体が解決済みデータに対する実行だけを担う | OK |
| ループ内で毎回 config/env/option を解釈する | REJECT |
| 反復ごとに「入力取得→解釈→実行→出力」を1関数に詰め込む | REJECT |
| 最適化で逐次処理が必要でも、解釈フェーズを専用メソッドに隔離している | OK |

### コード品質の検出手法

| 判定 | 基準 |
|------|------|
| REJECT | コードの動作をそのまま自然言語で言い換えている |
| REJECT | 関数名・変数名から明らかなことを繰り返している |
| REJECT | JSDocが関数名の言い換えだけで情報を追加していない |
| OK | なぜその実装を選んだかの設計判断を説明している |
| OK | 一見不自然に見える挙動の理由を説明している |
| OK | 定数・マジックナンバーの算出根拠や内訳を説明している |
| 最良 | コメントなしでコード自体が意図を語っている |

## アンチパターン検出

| パターン | 判定 |
|---------|------|
| God Class/Component | REJECT。1つのクラスが多くの責務を持つ |
| Feature Envy | REJECT。他モジュールのデータを頻繁に参照する |
| Shotgun Surgery | REJECT。1つの変更が複数ファイルに波及する構造 |
| 過度な汎用化 | REJECT。今使わないバリアントや拡張ポイントを追加する |
| 隠れた依存 | REJECT。子コンポーネントなどが暗黙的にAPIを呼ぶ |
| 非イディオマティック | REJECT。言語・FWの作法を無視した独自実装 |

## 仕様制約の検出

| パターン | 判定 |
|---------|------|
| 仕様に存在しないフィールドの使用 | REJECT |
| 仕様上無効な値の設定 | REJECT |
| 文書化された制約への違反 | REJECT |
