# バッチ設計書 38-Generate-FeatureStagingHeader.ps1

## 概要

本ドキュメントは、OpenConsoleプロジェクトにおいてフィーチャーフラグのXML定義ファイルからC++ヘッダーファイルを自動生成するスクリプト `Generate-FeatureStagingHeader.ps1` の設計仕様を記載する。

### 本バッチの処理概要

本スクリプトは、XML形式のフィーチャー定義ファイル（features.xml）を読み込み、各フィーチャーの有効/無効状態をブランディング（Dev/Canary/Preview/Release/WindowsInbox）およびGitブランチに基づいて解決し、C++プリプロセッサ定数とconstexpr構造体を含むヘッダーファイルを生成する。

**業務上の目的・背景**：Windows TerminalおよびOpenConsoleプロジェクトでは、フィーチャーフラグを使用して段階的な機能リリース（Feature Staging）を管理している。開発版（Dev）では有効だがリリース版では無効にする機能や、特定のブランチでのみ有効にする機能を制御するために、フィーチャーフラグをC++コードにコンパイル時に埋め込む必要がある。本スクリプトはXML定義からC++ヘッダーを自動生成することで、フィーチャーフラグの管理を効率化し、設定ミスを防止する。

**バッチの実行タイミング**：ビルドプロセスの一部として自動実行される。また、フィーチャー定義の変更時に手動で実行される場合もある。

**主要な処理内容**：
1. XML定義ファイル（features.xml）を読み込み、XSDスキーマで検証する
2. 各フィーチャーのデフォルトステージ（AlwaysEnabled/AlwaysDisabled）を解析する
3. ブランチトークン、ブランディングトークン、リリーストークンに基づいて最終的な有効/無効状態を解決する
4. 現在のGitブランチ名を取得する（BranchOverrideが指定されていない場合）
5. C++プリプロセッサの`#define`文を生成する（TIL_{FEATURE}_ENABLED形式）
6. ODR違反検出用の`__pragma(detect_mismatch)`とconstexpr構造体を生成する
7. 結果をファイルまたは標準出力に出力する

**前後の処理との関連**：ビルドシステム（MSBuild）から呼び出され、生成されたヘッダーファイルがC++コンパイルに使用される。features.xmlの変更が行われた場合、ビルド前に本スクリプトが再実行される必要がある。

**影響範囲**：生成されたヘッダーファイルはプロジェクト全体のC++コンパイルに影響し、フィーチャーフラグの有効/無効がコンパイル時に決定される。

## バッチ種別

コード生成

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | ビルド時（随時） |
| 実行時刻 | - |
| 実行曜日 | - |
| 実行日 | - |
| トリガー | ビルドプロセス / 手動 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| PowerShellが利用可能 | スクリプト実行環境としてPowerShellが必要 |
| features.xmlが存在 | フィーチャー定義XMLファイルが指定パスに存在すること |
| FeatureStagingSchema.xsdが存在 | XMLスキーマファイルがスクリプトと同じディレクトリに存在すること |
| gitが利用可能（オプション） | ブランチ名の自動検出に必要（BranchOverrideを使用する場合は不要） |

### 実行可否判定

`-Path` パラメータで指定されたXMLファイルが存在するか `ValidateScript` で検証される。存在しない場合はスクリプト実行前にエラーとなる。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| Path | string | Yes | なし | features.xmlファイルへのパス |
| Branding | string | No | "Dev" | ブランディング種別（Dev/Canary/Preview/Release/WindowsInbox） |
| BranchOverride | string | No | $Null | Gitブランチ名のオーバーライド（指定しない場合はgitコマンドで自動検出） |
| OutputPath | string | No | なし | 出力先ファイルパス（未指定時は標準出力） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| features.xml | XML | フィーチャー定義ファイル（フィーチャー名、ステージ、ブランチ/ブランディングトークン） |
| FeatureStagingSchema.xsd | XSD | XMLスキーマ検証用ファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| OutputPathで指定されたファイル、または標準出力 | C++ヘッダー（テキスト） | フィーチャーフラグのプリプロセッサ定数と構造体 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | OutputPathパラメータで指定 |
| 出力先 | OutputPathパラメータで指定 |
| 文字コード | UTF-8 |
| 区切り文字 | - |

出力内容の構造:
```
// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT IT
// INPUT FILE: {Path}

#define TIL_{FEATURE_NAME}_ENABLED {0 or 1}
...

#if defined(__cplusplus)

__pragma(detect_mismatch("ODR_violation_TIL_{FEATURE_NAME}_ENABLED_mismatch", "{Stage}"))
struct {FeatureName}
{
    static constexpr bool IsEnabled() { return TIL_{FEATURE_NAME}_ENABLED == 1; }
};
...

#endif
```

## 処理フロー

### 処理シーケンス

```
1. パラメータバインディングと検証
   ├─ Pathの存在チェック（ValidateScript）
   └─ Brandingの値検証（ValidateSet: Dev/Canary/Preview/Release/WindowsInbox）
2. XMLファイルの読み込みとスキーマ検証
   ├─ features.xmlの読み込み
   └─ FeatureStagingSchema.xsdによるXML検証
3. フィーチャーオブジェクトの構築
   ├─ 各featureエントリからFeatureクラスのインスタンスを生成
   ├─ Name, Stage, BranchTokenStages, BrandingTokenStages, DisabledReleaseTokenを設定
   └─ フィーチャーリストをアルファベット順にソート
4. Gitブランチ名の取得
   ├─ BranchOverrideが指定されている場合: そのまま使用
   └─ 未指定の場合: git branch --show-current または git rev-parse --abbrev-ref HEAD
5. フィーチャーステージの最終解決（Resolve-FinalFeatureStage）
   ├─ Release/WindowsInboxかつDisabledReleaseTokenあり → AlwaysDisabled
   ├─ ブランチトークンに最長一致するものがあれば、そのステージを使用
   ├─ ブランディングトークンに一致するものがあれば、そのステージを使用
   └─ いずれにも該当しなければ、デフォルトのステージを使用
6. C++ヘッダーコード生成
   ├─ コメントヘッダー（自動生成の警告、入力ファイル名）
   ├─ #define文の生成（TIL_{FEATURE}_ENABLED 0 or 1）
   ├─ __pragma(detect_mismatch)の生成
   └─ constexpr struct生成（IsEnabled()メソッド付き）
7. 出力
   ├─ OutputPath指定あり: ファイルに書き込み（UTF-8）
   └─ OutputPath未指定: 標準出力に出力
```

### フローチャート

```mermaid
flowchart TD
    A[スクリプト開始] --> B[パラメータ検証]
    B --> C[XMLファイル読み込み・スキーマ検証]
    C --> D[Featureオブジェクト構築・ソート]
    D --> E{BranchOverride指定?}
    E -->|あり| F[BranchOverrideを使用]
    E -->|なし| G[gitコマンドでブランチ名取得]
    F --> H[フィーチャーステージ最終解決]
    G --> H
    H --> I[C++ヘッダーコード生成]
    I --> J{OutputPath指定?}
    J -->|あり| K[ファイル出力]
    J -->|なし| L[標準出力]
    K --> M[スクリプト終了]
    L --> M
```

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作はない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | パラメータ検証エラー | -Pathで指定されたファイルが存在しない | 正しいパスを指定する |
| - | XML検証エラー | features.xmlがスキーマに準拠していない | XMLファイルの内容を修正する |
| - | 不正なステージ値 | XMLに未知のステージ値が含まれている | "Invalid feature stage $stage" 例外がスローされる |
| - | $ErrorActionPreference = "Stop" | スクリプト内の全エラーで即座に停止 | エラーメッセージを確認して原因を修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

### 障害時対応

features.xmlの内容を修正し、スクリプトを再実行する。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし（ファイル出力はアトミックではない） |
| コミットタイミング | - |
| ロールバック条件 | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | フィーチャー数に依存（通常数十件程度） |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | 特に定義なし |

## 排他制御

同一OutputPathに対して複数プロセスが同時に書き込むことは想定されていない。ビルドシステムが排他制御を行う前提。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| Write-Verbose | ブランチ検出失敗時 | "Cannot determine current Git branch; skipping branch validation" |
| 標準出力 | OutputPath未指定時 | 生成されたC++ヘッダーコード |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ビルドエラー | ヘッダー生成失敗時 | ビルドログ |

## 備考

- Enumとして定義されたStage（AlwaysDisabled, AlwaysEnabled）の2状態のみをサポートする
- フィーチャーステージの解決優先順位: Release無効トークン > ブランチトークン（最長一致） > ブランディングトークン > デフォルトステージ
- ODR（One Definition Rule）違反検出のための `__pragma(detect_mismatch)` が生成される。これにより、異なる翻訳単位で異なるフィーチャー設定がリンクされた場合にリンカエラーが発生する
- フィーチャーリストはアルファベット順にソートされ、生成されるヘッダーの順序が安定する
- ブランチ名の取得は `git branch --show-current` を優先し、失敗時は `git rev-parse --abbrev-ref HEAD` にフォールバックする
- ソースファイル: `tools/Generate-FeatureStagingHeader.ps1`
