# 帳票設計書 11-validate-config

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータの `+validate-config` コマンドによって出力される設定検証レポートの設計仕様を定義する。このレポートはCLIコマンドの実行結果として標準出力に出力され、設定ファイルの妥当性検証結果を提供する。

### 本帳票の処理概要

`+validate-config` コマンドは、Ghosttyの設定ファイル（デフォルト設定ファイルまたは指定された設定ファイル）を読み込み、パース処理を行い、検出されたエラーや警告をユーザーに報告する。

**業務上の目的・背景**：Ghosttyの設定ファイルは多数の設定項目を持ち、フォーマットエラーや無効な値の指定が発生しやすい。ユーザーがGhosttyを起動する前に設定ファイルの妥当性を検証することで、起動時のエラーを未然に防ぎ、設定のトラブルシューティングを効率化する。また、設定ファイルの変更後に即座に検証できることで、ユーザーエクスペリエンスが向上する。

**帳票の利用シーン**：
- 新しい設定ファイルを作成した後の検証
- 既存の設定ファイルを編集した後の確認
- Ghostty起動時にエラーが発生した場合の原因調査
- 設定ファイルのリファクタリング後の検証
- CI/CD環境での設定ファイルの自動検証

**主要な出力内容**：
1. 設定ファイルのパースエラー（構文エラー、無効なフィールド名など）
2. 設定値の検証エラー（範囲外の値、無効な列挙値など）
3. エラーの発生箇所（ファイルパスと行番号）
4. 検証対象のキー名とエラーメッセージ

**帳票の出力タイミング**：ユーザーがCLIで `ghostty +validate-config` または `ghostty +validate-config --config-file=<path>` を実行した際に即座に出力される。

**帳票の利用者**：Ghosttyのエンドユーザー、システム管理者、開発者

## 帳票種別

CLI診断レポート（テキスト形式のエラー/警告メッセージ一覧）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI-11 | ターミナル | N/A（CLI） | `ghostty +validate-config [--config-file=<path>]` |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | 標準出力（stdout）へのテキスト出力 |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A（標準出力） |
| 出力方法 | コンソール出力 |
| 文字コード | UTF-8 |

### 終了コード

| 終了コード | 意味 |
|-----------|------|
| 0 | 設定ファイルに問題なし |
| 1 | 設定ファイルにエラーあり |

## 帳票レイアウト

### レイアウト概要

設定検証レポートは、検出されたエラーや警告を1行ずつ出力するシンプルな形式である。各エラーメッセージには発生箇所とエラー内容が含まれる。

```
┌─────────────────────────────────────────────────────────────┐
│  [ファイルパス]:[行番号]:[キー名]: [エラーメッセージ]          │
│  [ファイルパス]:[行番号]:[キー名]: [エラーメッセージ]          │
│  ...                                                        │
└─────────────────────────────────────────────────────────────┘
```

### 出力フォーマット詳細

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ファイルパス | エラーが発生した設定ファイルのパス | Diagnostic.location.file.path | 文字列 |
| 2 | 行番号 | エラーが発生した行番号 | Diagnostic.location.file.line | 整数 |
| 3 | キー名 | 問題のある設定キー | Diagnostic.key | 文字列 |
| 4 | エラーメッセージ | エラーの詳細説明 | Diagnostic.message | 文字列 |

### 出力例

```
/home/user/.config/ghostty/config:15:font-size: invalid value "abc", valid values are: 1-999
/home/user/.config/ghostty/config:23:unknown-key: unknown field
```

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 設定ファイルパス | `--config-file` オプションで指定された場合はそのパス、指定されない場合はデフォルトの設定ファイルパス | No |

### コマンドラインオプション

| オプション | 説明 | デフォルト |
|-----------|------|-----------|
| `--config-file` | 検証対象の設定ファイルパスを指定 | デフォルト設定ファイルパス |
| `-h`, `--help` | ヘルプメッセージを表示 | - |

### 改ページ条件

N/A（CLIテキスト出力のため改ページなし）

## データベース参照仕様

N/A（データベースを使用しない）

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 診断件数 | `_diagnostics.items().len` | N/A | 検出されたエラー/警告の総数 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[オプション解析]
    B --> C{--config-file指定?}
    C -->|Yes| D[指定ファイルを読込]
    C -->|No| E[デフォルト設定をロード]
    D --> F[ファイルをパース]
    E --> F
    F --> G[再帰的にconfig-fileをロード]
    G --> H[設定をfinalize]
    H --> I{診断情報あり?}
    I -->|Yes| J[診断情報を出力]
    I -->|No| K[正常終了 code=0]
    J --> L[エラー終了 code=1]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 無効なフィールド | 存在しない設定キーが指定された | `unknown field` | 設定キー名を確認し修正 |
| 値が必要 | 値が必要なフィールドに値がない | `value required` | 設定値を追加 |
| 無効な値 | フィールドの型に合わない値 | `invalid value "<value>"` | 正しい形式の値に修正 |
| ファイル読込エラー | 設定ファイルが存在しないか読み取れない | ファイルエラーメッセージ | ファイルパスと権限を確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 設定ファイル1-10個、各100-1000行程度 |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | 1（CLIコマンド） |

## セキュリティ考慮事項

- 設定ファイルパスとして任意のファイルパスを指定できるが、ファイルの内容は設定ファイルとしてパースされるのみで、外部に送信されることはない
- パスワードやトークンなどの機密情報を含む設定値は出力されない（設定キー名のみ出力）

## 備考

- `--config-file` オプションで指定されたファイルパスは相対パスでも絶対パスでも指定可能
- 設定ファイル内で `config-file` ディレクティブによって参照される追加の設定ファイルも再帰的に検証される
- 検証は設定のパース段階とfinalize段階の両方で行われる

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

設定検証の結果を保持するDiagnostic構造体とDiagnosticList構造体を理解することが最初の重要なステップである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | diagnostics.zig | `src/cli/diagnostics.zig` | Diagnostic構造体（13-45行目）: location, key, messageフィールドの役割を理解する |
| 1-2 | diagnostics.zig | `src/cli/diagnostics.zig` | Location共用体（49-85行目）: エラー発生箇所の種類（none, cli, file）を理解する |
| 1-3 | diagnostics.zig | `src/cli/diagnostics.zig` | DiagnosticList構造体（94-197行目）: 診断情報の格納と管理方法を理解する |

**読解のコツ**: ZigではUnion（共用体）がタグ付きで使われることが多い。Locationの `union(enum)` パターンは、エラー発生箇所を3種類に分類している。

#### Step 2: エントリーポイントを理解する

`+validate-config` コマンドのエントリーポイントと処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | validate_config.zig | `src/cli/validate_config.zig` | Options構造体（7-21行目）: コマンドラインオプションの定義 |
| 2-2 | validate_config.zig | `src/cli/validate_config.zig` | run関数（32-48行目）: コマンド実行のエントリーポイント |
| 2-3 | validate_config.zig | `src/cli/validate_config.zig` | runInner関数（50-78行目）: 実際の検証処理ロジック |

**主要処理フロー**:
1. **32-48行目**: run関数でオプションをパースし、標準出力ライターを準備
2. **55-56行目**: デフォルト設定を初期化
3. **59-66行目**: 指定ファイルまたはデフォルト設定をロード
4. **68行目**: 設定をfinalize
5. **70-75行目**: 診断情報があれば出力して終了コード1を返す

#### Step 3: 設定ロード処理を理解する

Configの設定ロード処理と診断情報の収集方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Config.zig | `src/config/Config.zig` | _diagnosticsフィールド（3761行目）: 診断リストの格納場所 |
| 3-2 | Config.zig | `src/config/Config.zig` | load関数（3792-3807行目）: デフォルト設定ロードの流れ |
| 3-3 | Config.zig | `src/config/Config.zig` | loadFile関数（3846-3862行目）: 個別ファイルのロード処理 |
| 3-4 | Config.zig | `src/config/Config.zig` | finalize関数（4444行目以降）: 設定の最終検証処理 |

**主要処理フロー**:
- **3792-3807行目**: load関数がデフォルトファイル、CLIArgs、再帰ファイルを順にロード
- **3846-3862行目**: loadFile関数がファイルを開いてパーサーに渡す
- **4444行目以降**: finalize関数で設定の整合性を最終検証

#### Step 4: CLI引数パース処理を理解する

CLIオプションのパース処理と診断情報の生成方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | args.zig | `src/cli/args.zig` | parse関数（55-181行目）: CLIおよび設定ファイルのパース処理 |
| 4-2 | args.zig | `src/cli/args.zig` | parseIntoField関数（302-469行目）: フィールドごとのパース処理 |
| 4-3 | args.zig | `src/cli/args.zig` | LineIterator（1393-1510行目）: 設定ファイルの行読み込み処理 |

**主要処理フロー**:
- **112-123行目**: `--` で始まらない引数をエラーとして診断リストに追加
- **136-179行目**: パースエラー発生時に診断情報を生成
- **1498-1509行目**: LineIteratorがファイルパスと行番号を診断情報として提供

### プログラム呼び出し階層図

```
ghostty +validate-config
    │
    ├─ ghostty.zig: Action.run()
    │      │
    │      └─ validate_config.zig: run()
    │              │
    │              ├─ args.zig: argsIterator() / parse()
    │              │
    │              ├─ Config.zig: default()
    │              │
    │              ├─ Config.zig: loadFile() または load()
    │              │      │
    │              │      └─ args.zig: parse() → LineIterator
    │              │              │
    │              │              └─ diagnostics.zig: DiagnosticList.append()
    │              │
    │              ├─ Config.zig: loadRecursiveFiles()
    │              │
    │              ├─ Config.zig: finalize()
    │              │
    │              └─ diagnostics.zig: Diagnostic.format()
    │                      │
    │                      └─ stdout: 診断メッセージ出力
```

### データフロー図

```
[入力]                      [処理]                           [出力]

設定ファイル ───────▶ Config.loadFile() ───────▶ _diagnostics
    │                       │
    ▼                       ▼
args.parse() ◀──── LineIterator.next()
    │
    ▼
parseIntoField()
    │
    ├─(エラー発生)─▶ DiagnosticList.append()
    │
    ▼
Config.finalize()
    │
    ├─(エラー発生)─▶ DiagnosticList.append()
    │
    ▼
_diagnostics.items() ───▶ Diagnostic.format() ───▶ stdout（テキスト出力）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| validate_config.zig | `src/cli/validate_config.zig` | ソース | +validate-configコマンドのエントリーポイント |
| diagnostics.zig | `src/cli/diagnostics.zig` | ソース | Diagnostic/DiagnosticList構造体の定義 |
| args.zig | `src/cli/args.zig` | ソース | CLI引数および設定ファイルのパーサー |
| ghostty.zig | `src/cli/ghostty.zig` | ソース | CLIアクションのディスパッチャー |
| Config.zig | `src/config/Config.zig` | ソース | 設定管理と検証のメインロジック |
| cli.zig | `src/cli.zig` | ソース | CLI関連モジュールのエクスポート |
