# 通知設計書 1-OSC 9 デスクトップ通知

## 概要

本ドキュメントは、GhosttyターミナルエミュレータにおけるOSC 9エスケープシーケンスによるiTerm2互換のデスクトップ通知機能の設計について記述する。

### 本通知の処理概要

OSC 9デスクトップ通知は、ターミナル内で実行中のプログラムがOSCエスケープシーケンス（OSC 9;body形式）を送信することで、オペレーティングシステムのネイティブデスクトップ通知を表示する機能である。

**業務上の目的・背景**：長時間実行されるビルドプロセス、バッチジョブ、スクリプトなどが完了した際に、ユーザーに視覚的な通知を提供する。ユーザーがターミナルウィンドウから離れている場合でも、重要なイベントを見逃さないようにすることが目的である。iTerm2との互換性を保つことで、既存のスクリプトやワークフローがそのまま動作する。

**通知の送信タイミング**：ターミナルがOSC 9エスケープシーケンスを受信したタイミングで即座に通知が発生する。プログラムが`printf '\e]9;Build complete!\e\\'`のようなコマンドを出力した際にトリガーされる。

**通知の受信者**：Ghosttyターミナルを使用しているローカルユーザー。通知はターミナルが動作しているOSのデスクトップ通知システムを通じてユーザーに表示される。

**通知内容の概要**：本文（body）のみを含む通知。タイトルは空文字列として設定される。iTerm2互換の仕様により、OSC 9はタイトルを指定する機能を持たない。

**期待されるアクション**：ユーザーは通知を確認し、必要に応じてターミナルウィンドウに戻って処理結果を確認する。通知自体はクリック可能であり、クリックするとターミナルウィンドウがフォーカスされる場合がある（OS依存）。

## 通知種別

デスクトップ通知（OSネイティブ通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（エスケープシーケンス受信時に即時処理） |
| 優先度 | 中 |
| リトライ | 無し |

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

通知は、エスケープシーケンスを受信したターミナルサーフェスが所属するOSのデスクトップ通知システムに送信される。受信者は常にローカルユーザーである。

## 通知テンプレート

### デスクトップ通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | 空文字列 |
| 本文 | OSC 9シーケンスで指定されたbody |
| アイコン | Ghosttyアプリケーションアイコン（OS依存） |

### 本文テンプレート

```
{OSC 9で指定されたbody文字列}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| body | 通知本文 | OSC 9エスケープシーケンスのパラメータ | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| エスケープシーケンス | OSC 9;body形式の受信 | `desktop-notifications`設定がtrue | ターミナルがOSC 9シーケンスを検出した時点で発火 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `desktop-notifications = false` | 設定ファイルでデスクトップ通知が無効化されている場合、通知は表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[OSC 9シーケンス受信] --> B[OSCパーサーで解析]
    B --> C{ConEmu拡張か判定}
    C -->|No| D[show_desktop_notification生成]
    C -->|Yes| E[ConEmu関連コマンド処理]
    D --> F[StreamHandler.showDesktopNotification呼び出し]
    F --> G[Surface.handleMessage]
    G --> H{desktop-notifications設定チェック}
    H -->|有効| I[apprt.performAction実行]
    H -->|無効| J[通知スキップ・ログ出力]
    I --> K[OS通知システムへ送信]
    K --> L[終了]
    J --> L
```

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

### 参照テーブル一覧

該当なし（ファイルシステムやデータベースへのアクセスは行わない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| パース失敗 | 不正なOSC 9シーケンス | パーサーがinvalid状態に遷移し、シーケンスは無視される |
| バッファオーバーフロー | body文字列が長すぎる | 最大255バイトに切り詰めて処理 |
| OS通知システムエラー | OSの通知サービスが利用不可 | エラーログを出力し、処理を継続 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（24時間いつでも送信可能）

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

- 悪意のあるプログラムがユーザーを騙すような通知を表示する可能性があるため、`desktop-notifications`設定で無効化できる
- 通知内容はターミナルに表示される内容と同等の機密性レベルとして扱う
- SSHセッション等、リモートからの通知送信も可能であるため、信頼できないプログラムの実行時は注意が必要

## 備考

- iTerm2互換のOSC 9実装
- ConEmu拡張（OSC 9;1〜OSC 9;12）と共存するが、それらは別の機能として扱われる
- OSC 777（rxvt拡張）はタイトルとbodyの両方を指定可能な代替手段

---

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

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

### 推奨読解順序

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

OSC 9コマンドがどのようなデータ構造で表現されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | osc.zig | `src/terminal/osc.zig` | Command union内のshow_desktop_notification構造体（行94-98）を確認 |
| 1-2 | surface.zig | `src/apprt/surface.zig` | Message.desktop_notification構造体（行54-61）を確認 |

**読解のコツ**: Zigの`union(enum)`型は、タグ付きunionとして動作する。`show_desktop_notification`はtitleとbodyの2つのフィールドを持つ。

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

OSC 9シーケンスのパース処理がどこで行われるかを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | osc9.zig | `src/terminal/osc/parsers/osc9.zig` | parse関数（行7-285）がOSC 9のエントリーポイント |

**主要処理フロー**:
1. **行16-268**: ConEmu拡張（OSC 9;1〜9;12）のチェック
2. **行271-284**: ConEmuでない場合、iTerm2通知として処理
3. **行278-283**: show_desktop_notificationコマンドを生成（title=""、body=受信データ）

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

パースされたコマンドがどのように処理されるかを追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stream_handler.zig | `src/termio/stream_handler.zig` | showDesktopNotification関数（行1427-1443） |

**主要処理フロー**:
- **行1432-1440**: title/bodyをメッセージ構造体にコピー（最大長制限あり）
- **行1442**: surfaceMessageWriterでサーフェスにメッセージ送信

#### Step 4: サーフェス処理を理解する

サーフェスがメッセージを受け取った後の処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Surface.zig | `src/Surface.zig` | handleMessage関数のdesktop_notification分岐（行1060-1068） |

**主要処理フロー**:
- **行1061-1064**: desktop-notifications設定のチェック
- **行1066-1068**: showDesktopNotification呼び出し

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

```
terminal.Parser.end()
    │
    └─ osc/parsers/osc9.parse()
           │
           └─ Command.show_desktop_notification を返す
                  │
                  └─ stream_handler.vt(.show_desktop_notification)
                         │
                         └─ showDesktopNotification()
                                │
                                └─ surfaceMessageWriter(.desktop_notification)
                                       │
                                       └─ Surface.handleMessage()
                                              │
                                              └─ rt_app.performAction(.desktop_notification)
```

### データフロー図

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

OSC 9;body ESC \  ───▶  osc9.parse()              ───▶  Command構造体
                              │
                              ▼
                        StreamHandler.vt()
                              │
                              ▼
                        showDesktopNotification()
                              │
                              ▼
                        Message.desktop_notification  ───▶  OS通知システム
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| osc.zig | `src/terminal/osc.zig` | ソース | OSCコマンドの定義とパーサー状態管理 |
| osc9.zig | `src/terminal/osc/parsers/osc9.zig` | ソース | OSC 9シーケンスのパース処理 |
| stream_handler.zig | `src/termio/stream_handler.zig` | ソース | ターミナルストリームのハンドリング |
| surface.zig | `src/apprt/surface.zig` | ソース | サーフェスメッセージの定義 |
| Surface.zig | `src/Surface.zig` | ソース | サーフェスのメッセージ処理 |
| action.zig | `src/apprt/action.zig` | ソース | アクション定義（DesktopNotification） |
| Config.zig | `src/config/Config.zig` | ソース | desktop-notifications設定 |
