# 通知設計書 7-ConEmu進捗レポート（OSC 9;4）

## 概要

本ドキュメントは、GhosttyターミナルエミュレータにおけるConEmu互換の進捗レポート機能（OSC 9;4）の設計について記述する。

### 本通知の処理概要

ConEmu進捗レポートは、CLIアプリケーションがOSC 9;4エスケープシーケンスを出力することで、処理の進捗状況をターミナルのプログレスバーとして視覚的に表示する機能である。

**業務上の目的・背景**：長時間実行されるコマンド（コンパイル、ファイルコピー、データ処理等）の進捗を視覚的に確認できるようにする。従来のテキストベースの進捗表示に加えて、GUIのプログレスバーを提供することで、ユーザーは進捗を一目で把握できる。

**通知の送信タイミング**：CLIアプリケーションがOSC 9;4シーケンスを出力した時点で即座にプログレスバーが更新される。アプリケーションは進捗の変化に応じて繰り返しシーケンスを出力できる。

**通知の受信者**：Ghosttyターミナルを使用しているローカルユーザー。プログレスバーはGTKウィンドウ内のオーバーレイとして表示される。

**通知内容の概要**：進捗状態（set/error/indeterminate/pause/remove）と進捗パーセンテージ（0-100%、オプショナル）。

**期待されるアクション**：特別なアクションは不要。ユーザーは処理の進捗を視覚的に確認できる。

## 通知種別

アプリ内通知（GTKプログレスバーオーバーレイ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（エスケープシーケンス受信直後に即時表示） |
| 優先度 | 通常 |
| リトライ | 無し |

### 送信先決定ロジック

プログレスバーは、OSC 9;4シーケンスを受信したサーフェスに対して表示される。

## 通知テンプレート

### プログレスバー状態

| 状態コード | 状態 | 説明 | プログレスバー表示 |
|-----------|------|------|-------------------|
| 0 | remove | プログレスバーを非表示にする | 非表示 |
| 1 | set | 進捗を設定する | 通常色で表示 |
| 2 | error | エラー状態を示す | エラー色（赤）で表示 |
| 3 | indeterminate | 不確定状態（パルス） | パルスアニメーション |
| 4 | pause | 一時停止状態 | 現在の値で静止 |

### エスケープシーケンス形式

| 形式 | 説明 |
|-----|------|
| `\033]9;4;0\007` | プログレスバーを非表示 |
| `\033]9;4;1;50\007` | 進捗を50%に設定 |
| `\033]9;4;2;30\007` | エラー状態で進捗30% |
| `\033]9;4;3\007` | 不確定状態（進捗値なし） |
| `\033]9;4;4;75\007` | 一時停止状態で進捗75% |

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| state | enum (0-4) | 必須 | プログレスバーの状態 |
| progress | u8 (0-100) | オプショナル | 進捗パーセンテージ |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| エスケープシーケンス | OSC 9;4受信 | GTKランタイム | アプリがOSC 9;4を出力 |
| 内部処理 | シェルリセット時 | なし | シェルリセット時に自動的にremove |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| GTK以外のランタイム | この機能はGTK版のみで利用可能 |
| 無効なシーケンス | パースできないシーケンスは無視される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[アプリがOSC 9;4を出力] --> B[OSCパーサーが解析]
    B --> C{パース成功?}
    C -->|失敗| D[無視]
    C -->|成功| E[progressReport関数呼び出し]
    E --> F[surfaceMessageWriter]
    F --> G[Surface.handleMessage]
    G --> H[performAction progress_report]
    H --> I{GTKランタイム?}
    I -->|はい| J[setProgressReport]
    I -->|いいえ| K[処理終了]
    J --> L{状態判定}
    L -->|remove| M[プログレスバー非表示]
    L -->|set| N[進捗値設定 + 通常色]
    L -->|error| O[進捗値設定 + エラー色]
    L -->|indeterminate| P[パルスアニメーション]
    L -->|pause| Q[現在値で静止]
    N --> R[タイムアウトタイマー開始]
    O --> R
    P --> R
    Q --> R
    R --> S[15秒後に自動非表示]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| パースエラー | 不正なOSCシーケンス | 無視してログ出力 |
| 進捗値範囲外 | progress > 100 | 0-100にクランプ |
| タイマー削除失敗 | GLibのタイマー削除エラー | 警告ログ出力して続行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### タイムアウト

| 項目 | 内容 |
|-----|------|
| 自動非表示タイムアウト | 15秒 |
| 説明 | プログレスバーが更新されない場合、15秒後に自動的に非表示になる |

### 配信時間帯

制限なし（24時間いつでも表示可能）

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

- プログレスバーは数値のみを表示するため、機密情報漏洩のリスクは低い
- 悪意のあるアプリケーションがプログレスバーを永続的に表示し続けることを防ぐため、15秒のタイムアウトが設定されている

## 備考

- GTK版のみで利用可能（macOS版では未実装）
- ConEmu互換のエスケープシーケンスを使用
- シェルリセット時（例：プロンプト表示時）に自動的にプログレスバーが非表示になる
- エラー状態では専用のCSSクラス "error" が適用され、赤色で表示される

---

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

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

### 推奨読解順序

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

進捗レポートの状態と値を定義するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | osc.zig | `src/terminal/osc.zig` | ProgressReport構造体（行199-231）を確認 |
| 1-2 | osc.zig | `src/terminal/osc.zig` | ProgressReport.State enum（行200-210）を確認 |

**読解のコツ**: ProgressReport構造体はstate（enum）とprogress（オプショナルu8）の2フィールドを持つ。Stateはremove(0), set(1), error(2), indeterminate(3), pause(4)の5状態。

#### Step 2: OSCパーサーを理解する

OSC 9;4シーケンスのパース処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | osc9.zig | `src/terminal/osc/parsers/osc9.zig` | OSC 9;4パース処理（行144-202）を確認 |

**読解のコツ**: `data[2]`で状態コード（'0'-'4'）を判定し、必要に応じて`data[4..]`から進捗値をパースする。進捗値は0-100にクランプされる。

#### Step 3: ストリームハンドラを理解する

パース結果を処理するストリームハンドラを追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stream_handler.zig | `src/termio/stream_handler.zig` | progress_reportのディスパッチ（行320）を確認 |
| 3-2 | stream_handler.zig | `src/termio/stream_handler.zig` | progressReport関数（行1547-1550）を確認 |
| 3-3 | stream_handler.zig | `src/termio/stream_handler.zig` | シェルリセット時のremove（行958）を確認 |

#### Step 4: Surface処理を理解する

Surfaceでのメッセージ処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | surface.zig | `src/apprt/surface.zig` | progress_reportメッセージ定義（行92）を確認 |
| 4-2 | Surface.zig | `src/Surface.zig` | handleMessage progress_report（行1094-1102）を確認 |

#### Step 5: GTK実装を理解する

GTKでのプログレスバー表示処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | application.zig | `src/apprt/gtk/class/application.zig` | progressReport関数（行2252-2263）を確認 |
| 5-2 | surface.zig | `src/apprt/gtk/class/surface.zig` | setProgressReport関数（行973-1048）を確認 |
| 5-3 | surface.zig | `src/apprt/gtk/class/surface.zig` | progressBarTimer関数（行1051-1057）を確認 |

**読解のコツ**: setProgressReportは状態に応じてプログレスバーの表示を更新し、15秒のタイムアウトタイマーを設定する。タイムアウト時はprogressBarTimer関数が呼ばれ、自動的にremove状態になる。

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

```
CLIアプリがOSC 9;4を出力
    |
    v
Osc9.parse() (src/terminal/osc/parsers/osc9.zig:144-202)
    |   - 状態コード（0-4）を判定
    |   - 進捗値（オプショナル）をパース
    |
    v
StreamHandler.progressReport() (src/termio/stream_handler.zig:1547-1550)
    |
    v
surfaceMessageWriter(.progress_report)
    |
    v
Surface.handleMessage() (src/Surface.zig:1094-1102)
    |
    v
rt_app.performAction(.progress_report)
    |
    v
Application.progressReport() (src/apprt/gtk/class/application.zig:2252-2263)
    |
    v
Surface.setProgressReport() (src/apprt/gtk/class/surface.zig:973-1048)
    |   - タイマー停止
    |   - 状態に応じたプログレスバー更新
    |   - 15秒タイムアウトタイマー開始
    |
    v
gtk.ProgressBar表示更新
```

### データフロー図

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

OSC 9;4;state;progress   --> OSCパーサー                --> ProgressReport構造体
        |                                                      |
        |                                                      v
        |                    StreamHandler.progressReport()
        |                           |
        |                           v
        |                    surfaceMessageWriter
        |                           |
        |                           v
        |                    Surface.handleMessage()
        |                           |
        |                           v
        |                    performAction(.progress_report)
        |                           |
        |                           v
        +--------------------> setProgressReport()        --> GTKプログレスバー表示
                                    |
                                    v
                              タイムアウトタイマー      --> 15秒後に自動非表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| osc.zig | `src/terminal/osc.zig` | ソース | ProgressReport構造体定義 |
| osc9.zig | `src/terminal/osc/parsers/osc9.zig` | ソース | OSC 9;4パーサー |
| stream_handler.zig | `src/termio/stream_handler.zig` | ソース | ストリームハンドラ、progressReport関数 |
| surface.zig | `src/apprt/surface.zig` | ソース | サーフェスメッセージ定義 |
| Surface.zig | `src/Surface.zig` | ソース | サーフェス、メッセージハンドリング |
| action.zig | `src/apprt/action.zig` | ソース | progress_reportアクション定義 |
| application.zig | `src/apprt/gtk/class/application.zig` | ソース | GTKアプリケーション、アクションディスパッチ |
| surface.zig | `src/apprt/gtk/class/surface.zig` | ソース | GTKサーフェス、setProgressReport実装 |
