# 機能設計書 63-コマンド完了通知

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおける長時間実行コマンドの完了通知機能の設計を記述する。

### 本機能の処理概要

コマンド完了通知機能は、シェル統合と連携して長時間実行されるコマンドが完了した際にユーザーに通知を行う機能である。ベル音やデスクトップ通知などの方法で、ユーザーが別の作業を行っている間にコマンドが完了したことを知らせる。

**業務上の目的・背景**：開発作業において、ビルドコマンドやテスト実行などの長時間かかる処理は頻繁に発生する。これらの処理中、ユーザーは別のウィンドウで作業を行ったり、休憩を取ったりすることがある。コマンド完了通知機能により、ユーザーは処理完了を即座に認識でき、次のタスクにスムーズに移行できる。これにより待ち時間を有効活用でき、作業効率が向上する。

**機能の利用シーン**：
- 長時間かかるビルドやコンパイル処理の完了を待つ場合
- バッチ処理やデータ処理のジョブ完了を監視する場合
- バックグラウンドで実行中のコマンドが終了したことを知りたい場合
- ターミナルウィンドウにフォーカスがない状態でコマンド完了を検知したい場合

**主要な処理内容**：
1. OSC 133シーケンスによるコマンド開始の検出とタイマー開始
2. コマンド終了の検出とタイマー停止
3. 実行時間の計算と閾値との比較
4. 通知条件の判定（フォーカス状態、設定値）
5. 通知アクションの実行（ベル音、デスクトップ通知）

**関連システム・外部連携**：
- シェル統合: OSC 133シーケンスによるコマンド開始/終了マーキング
- デスクトップ通知システム: libnotify（Linux）、ネイティブ通知（macOS）

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主機能 | コマンド実行時の通知トリガー |

## 機能種別

通知処理 / イベント検出

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| exit_code | ?u8 | No | コマンドの終了コード（nullの場合は不明） | 0-255 |
| duration | Duration | Yes | コマンド実行時間（ナノ秒精度） | 正の整数 |

### 入力データソース

- OSC 133 Aシーケンス: コマンド開始マーカー
- OSC 133 Dシーケンス: コマンド終了マーカー
- 設定ファイル: notify-on-command-finish、notify-on-command-finish-action、notify-on-command-finish-after

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 通知タイトル | string | "Command Finished"/"Command Succeeded"/"Command Failed" |
| 通知本文 | string | 実行時間と終了コードを含む説明文 |
| ベル音 | audio | ターミナルベル音 |

### 出力先

- デスクトップ通知システム
- ターミナルベル

## 処理フロー

### 処理シーケンス

```
1. コマンド開始検出（OSC 133 A）
   └─ Surface.handleMessage(.start_command)
   └─ command_timer = std.time.Instant.now()

2. コマンド終了検出（OSC 133 D）
   └─ Surface.handleMessage(.stop_command)
   └─ 終了時刻取得と実行時間計算
   └─ command_timer = null

3. 通知条件判定
   └─ notify-on-command-finish設定確認
       └─ .never: 通知しない
       └─ .unfocused: フォーカスがない場合のみ
       └─ .always: 常に通知
   └─ 実行時間が閾値以上か確認

4. 通知アクション実行
   └─ notify-on-command-finish-action設定確認
       └─ .bell: ベル音を鳴らす
       └─ .notify: デスクトップ通知を送信

5. デスクトップ通知（設定時）
   └─ 通知タイトル生成（終了コードに基づく）
   └─ 通知本文生成（実行時間と終了コード）
   └─ sendDesktopNotification呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド開始検出] --> B[タイマー開始]
    B --> C[コマンド実行中...]
    C --> D[コマンド終了検出]
    D --> E[実行時間計算]
    E --> F{実行時間 >= 閾値?}
    F -->|No| G[通知なし]
    F -->|Yes| H{notify-on-command-finish設定?}
    H -->|never| G
    H -->|unfocused| I{フォーカスあり?}
    H -->|always| J[通知実行]
    I -->|Yes| G
    I -->|No| J
    J --> K{bell設定?}
    K -->|Yes| L[ベル音鳴らす]
    K -->|No| M{notify設定?}
    L --> M
    M -->|Yes| N[デスクトップ通知送信]
    M -->|No| O[終了]
    N --> O
    G --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-63-01 | 通知条件 | notify-on-command-finish設定に基づいて通知有無を決定 | always/unfocused/never |
| BR-63-02 | 時間閾値 | 実行時間がnotify-on-command-finish-after以上の場合のみ通知 | デフォルト5秒 |
| BR-63-03 | 次回通知オーバーライド | GTKコンテキストメニューから単発で通知を有効化可能 | GTK版のみ |
| BR-63-04 | 通知内容 | 終了コード0=成功、それ以外=失敗、null=完了として表示 | 常時 |

### 計算ロジック

実行時間は`std.time.Instant.since()`を使用してナノ秒精度で計算される。

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

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | タイマー未開始 | start_commandなしでstop_commandが発生 | 通知をスキップ |
| - | 通知送信失敗 | デスクトップ通知システムへの送信失敗 | ログ出力、処理継続 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- タイマー処理はナノ秒精度を維持すること
- 通知送信は非同期で行い、ターミナル操作をブロックしないこと

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

- コマンド内容自体は通知に含まれない（終了コードと実行時間のみ）
- デスクトップ通知はシステムの通知権限に依存

## 備考

- シェル統合が有効でない場合、OSC 133シーケンスが出力されないため本機能は動作しない
- GTK版ではコンテキストメニューから「Notify on Next Command Finish」を選択可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | action.zig | `src/apprt/action.zig` | CommandFinished構造体（938-946行目） |
| 1-2 | Config.zig | `src/config/Config.zig` | 通知関連設定（1216-1267行目） |

**読解のコツ**: `Duration`型はナノ秒単位の時間を表現し、設定ファイルでは"5s"のような人間可読な形式で指定できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Surface.zig | `src/Surface.zig` | command_timerフィールド（163行目） |
| 2-2 | Surface.zig | `src/Surface.zig` | handleMessage処理（1109-1128行目） |

**主要処理フロー**:
1. **163行目**: `command_timer: ?std.time.Instant`フィールド定義
2. **1109-1110行目**: `.start_command`でタイマー開始
3. **1113-1116行目**: `.stop_command`で終了時刻取得、実行時間計算
4. **1121-1127行目**: `command_finished`アクション発行

#### Step 3: 通知処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | application.zig | `src/apprt/gtk/class/application.zig` | commandFinishedアクション（756行目、2626-2631行目） |
| 3-2 | surface.zig | `src/apprt/gtk/class/surface.zig` | commandFinished実装（1070-1129行目） |

**主要処理フロー**:
- **1075-1085行目**: 次回通知オーバーライドの確認
- **1091-1094行目**: notify-on-command-finish設定チェック
- **1096行目**: 実行時間閾値チェック
- **1100行目**: ベル音処理
- **1102-1126行目**: デスクトップ通知生成・送信

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

```
OSC 133 A (コマンド開始)
    │
    └─ Terminal.handleOSC133
           │
           └─ Surface.handleMessage(.start_command)
                  │
                  └─ command_timer = std.time.Instant.now()

OSC 133 D (コマンド終了)
    │
    └─ Terminal.handleOSC133
           │
           └─ Surface.handleMessage(.stop_command)
                  │
                  ├─ 実行時間計算
                  │
                  └─ rt_app.performAction(.command_finished)
                         │
                         └─ GTK: surface.commandFinished
                                │
                                ├─ setBellRinging (bell設定時)
                                │
                                └─ sendDesktopNotification (notify設定時)
```

### データフロー図

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

OSC 133 A ───────────▶ command_timer = now()
                                │
                                ▼
OSC 133 D ───────────▶ duration = now() - command_timer
                                │
                                ▼
exit_code ───────────▶ CommandFinished構造体
                                │
                                ▼
設定値 ─────────────▶ 通知条件判定 ───────▶ ベル音
(notify-on-*)                │               デスクトップ通知
                                │                   │
                                ▼                   ▼
                        フォーカス確認 ───▶ 通知タイトル/本文生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Surface.zig | `src/Surface.zig` | ソース | command_timer管理とアクション発行 |
| action.zig | `src/apprt/action.zig` | ソース | CommandFinished構造体定義 |
| Config.zig | `src/config/Config.zig` | ソース | notify-on-command-finish設定 |
| surface.zig | `src/apprt/gtk/class/surface.zig` | ソース | GTK通知実装 |
| application.zig | `src/apprt/gtk/class/application.zig` | ソース | GTKアクションディスパッチ |
| Ghostty.App.swift | `macos/Sources/Ghostty/Ghostty.App.swift` | ソース | macOS通知実装 |
