# 通知設計書 2-OSC 777 デスクトップ通知

## 概要

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

### 本通知の処理概要

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

**業務上の目的・背景**：長時間実行されるビルドプロセス、バッチジョブ、スクリプトなどが完了した際に、タイトル付きの視覚的な通知を提供する。OSC 9より表現力が高く、ユーザーは通知の内容をタイトルで素早く識別できる。rxvt-unicodeとの互換性を保つことで、既存のスクリプトやワークフローがそのまま動作する。

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

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

**通知内容の概要**：タイトル（title）と本文（body）の両方を含む通知。`notify`サブコマンドを使用して明示的にデスクトップ通知であることを指定する。

**期待されるアクション**：ユーザーは通知のタイトルを確認して重要度を判断し、必要に応じてターミナルウィンドウに戻って処理結果を確認する。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

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

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

### 本文テンプレート

```
タイトル: {title}
本文: {body}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| title | 通知タイトル | OSC 777エスケープシーケンスの第2パラメータ | Yes |
| body | 通知本文 | OSC 777エスケープシーケンスの第3パラメータ | Yes |

## 送信トリガー・条件

### トリガー一覧

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

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `desktop-notifications = false` | 設定ファイルでデスクトップ通知が無効化されている場合、通知は表示されない |
| サブコマンドが"notify"以外 | notify以外のrxvt拡張は無視される |
| titleが欠落 | セミコロンで区切られたtitleが存在しない場合、パースエラーとなる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[OSC 777シーケンス受信] --> B[OSCパーサーで解析]
    B --> C{サブコマンド確認}
    C -->|notify| D[title/body抽出]
    C -->|その他| E[警告ログ出力・無視]
    D --> F{titleが存在するか}
    F -->|Yes| G[show_desktop_notification生成]
    F -->|No| H[パースエラー・invalid状態]
    G --> I[StreamHandler.showDesktopNotification呼び出し]
    I --> J[Surface.handleMessage]
    J --> K{desktop-notifications設定チェック}
    K -->|有効| L[apprt.performAction実行]
    K -->|無効| M[通知スキップ・ログ出力]
    L --> N[OS通知システムへ送信]
    N --> O[終了]
    M --> O
    E --> O
    H --> O
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 不明なrxvt拡張 | サブコマンドが"notify"以外 | 警告ログ出力、パーサーをinvalid状態に遷移 |
| titleの欠落 | セミコロン区切りのtitleがない | 警告ログ出力、パーサーをinvalid状態に遷移 |
| バッファオーバーフロー | title/body文字列が長すぎる | 最大長（title:63バイト、body:255バイト）に切り詰めて処理 |
| OS通知システムエラー | OSの通知サービスが利用不可 | エラーログを出力し、処理を継続 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

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

## 備考

- rxvt-unicode互換のOSC 777実装
- `notify`サブコマンドのみをサポート、その他のrxvt拡張は警告ログを出力して無視
- OSC 9（iTerm2互換）と比較して、タイトルを指定可能な点が優位

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 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）を確認 |

**読解のコツ**: OSC 777はOSC 9と同じshow_desktop_notification構造体を使用する。違いはtitleフィールドに値が設定される点。

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

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

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

**主要処理フロー**:
1. **行20-23**: 最初のセミコロンを検索し、サブコマンド（ext）を抽出
2. **行25-29**: サブコマンドが"notify"でなければ警告ログを出力
3. **行30-34**: 2つ目のセミコロンを検索し、titleを抽出。欠落時は警告
4. **行35-37**: セミコロン位置にNULを書き込み、titleとbodyを分離
5. **行38-44**: show_desktop_notificationコマンドを生成

#### 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） |

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

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

### データフロー図

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

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

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| osc.zig | `src/terminal/osc.zig` | ソース | OSCコマンドの定義とパーサー状態管理 |
| rxvt_extension.zig | `src/terminal/osc/parsers/rxvt_extension.zig` | ソース | OSC 777シーケンスのパース処理 |
| 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設定 |
