# 機能設計書 52-Watchモード

## 概要

本ドキュメントは、Bunテストランナーにおけるウォッチモード（Watch Mode）機能の設計仕様を記述する。

### 本機能の処理概要

ウォッチモード機能は、ファイルシステムの変更を監視し、テストファイルや依存ファイルが変更された際に自動的にテストを再実行する。開発中のテスト駆動開発（TDD）ワークフローを効率化し、コード変更時の即座のフィードバックを提供する。

**業務上の目的・背景**：開発者がコードを変更するたびに手動でテストコマンドを実行する手間を省き、開発サイクルを高速化する。コード変更の影響を即座に確認できることで、バグの早期発見と修正を促進する。

**機能の利用シーン**：テスト駆動開発（TDD）、リファクタリング作業中の回帰テスト確認、バグ修正時のテスト検証、継続的な開発作業中のテスト実行。

**主要な処理内容**：
1. `--watch`オプションの解析とウォッチモードの有効化
2. ファイルシステムウォッチャーの初期化（kqueue/inotify/FSEvents）
3. テストファイルおよび依存ファイルの監視登録
4. ファイル変更イベントの検出
5. 変更検出時のテストプロセス再起動

**関連システム・外部連携**：OSのファイルシステム監視API（macOS: FSEvents/kqueue、Linux: inotify、Windows: ReadDirectoryChangesW）。

**権限による制御**：特になし。全ユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | test | 主画面 | `--watch`オプションによるファイル監視とテスト自動再実行 |

## 機能種別

ファイル監視 / プロセス制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --watch | フラグ | No | ウォッチモードを有効化 | - |
| --no-clear-screen | フラグ | No | 再実行時に画面クリアしない | - |

### 入力データソース

- テストファイル群
- テストが依存するソースファイル群
- 設定ファイル（bunfig.toml等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 変更検出ログ | string | 変更されたファイルパス |
| テスト結果 | TestResult | 各テストの成功/失敗結果 |

### 出力先

- 標準出力（テスト結果、変更検出ログ）
- 標準エラー出力（エラーメッセージ）

## 処理フロー

### 処理シーケンス

```
1. テストコマンド実行時に--watchオプション解析
   └─ Arguments.zigでオプションをパース
2. WatchReloaderの初期化
   └─ enableHotModuleReloading関数でウォッチャー起動
3. ファイルウォッチャーの開始
   └─ OS固有のファイル監視APIを使用
4. テストファイルと依存ファイルを監視リストに追加
   └─ addFile関数でハッシュとパスを登録
5. イベントループでファイル変更を待機
   └─ runEventLoopForWatch関数
6. ファイル変更イベント検出
   └─ onFileUpdate関数で処理
7. プロセス再起動
   └─ bun.reloadProcess関数でテストを再実行
```

### フローチャート

```mermaid
flowchart TD
    A[テスト開始] --> B{--watch指定?}
    B -->|No| C[通常テスト実行]
    B -->|Yes| D[WatchReloader初期化]
    D --> E[ファイルウォッチャー開始]
    E --> F[テストファイル監視登録]
    F --> G[依存ファイル監視登録]
    G --> H[テスト実行]
    H --> I[イベントループ待機]
    I --> J{ファイル変更?}
    J -->|No| I
    J -->|Yes| K[変更ファイル検出]
    K --> L{画面クリア?}
    L -->|Yes| M[画面クリア]
    L -->|No| N[プロセス再起動]
    M --> N
    N --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-1 | 即座再起動 | reload_immediately=trueでファイル変更時に即座にプロセス再起動 | WatchReloader使用時 |
| BR-52-2 | 画面クリア | デフォルトで再実行時に画面をクリア | BUN_CONFIG_NO_CLEAR_TERMINAL_ON_RELOAD未設定時 |
| BR-52-3 | 重複検出防止 | 同一ファイルの連続変更は1回の再実行にまとめる | 常時 |
| BR-52-4 | vim保存対応 | macOSでのvimアトミック保存に対応（rename後のdir変更を待つ） | macOS環境 |

### 計算ロジック

```
ファイルハッシュ = Watcher.getHash(file_path)
変更検出 = event.op.write or event.op.delete or event.op.rename
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | WatcherInitError | ファイルウォッチャー初期化失敗 | パニック終了 |
| - | WatcherCrash | ウォッチャークラッシュ | エラーログ出力、デバッグ時はパニック |

### リトライ仕様

ファイルウォッチャーの初期化失敗時はリトライせずパニック終了する。

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

該当なし（データベース操作なし）。

## パフォーマンス要件

- ファイル変更検出から再実行開始まで：100ms以内
- 監視対象ファイル数：実質無制限（OS制限に依存）

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

- 監視対象ディレクトリ外のファイル変更は検出しない
- シンボリックリンクの追跡は制限される場合がある

## 備考

- HotReloaderはホットモジュールリプレイス（HMR）用、WatchReloaderはプロセス再起動用
- reload_immediately=trueの場合、イベントループを使わず即座にプロセス再起動

---

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

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

### 推奨読解順序

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

まず、ファイルウォッチャーの基本構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | hot_reloader.zig | `src/bun.js/hot_reloader.zig` | ImportWatcher union、HotReloader/WatchReloader定義 |

**読解のコツ**: `NewHotReloader`関数が`reload_immediately`パラメータで振る舞いを変える点に注目。

**主要処理フロー**:
- **1-4行目**: ImportWatcher union定義。none/hot/watchの3状態
- **64-65行目**: HotReloader/WatchReloaderの定義。reload_immediatelyの違い
- **69-71行目**: NewHotReloader関数。ジェネリックなリローダー生成

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

テストコマンドからウォッチモードがどのように呼び出されるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | test_command.zig | `src/cli/test_command.zig` | --watchオプション処理、イベントループ |

**主要処理フロー**:
- **1535-1539行目**: hot_reloadの状態に応じてHotReloaderまたはWatchReloaderを有効化
- **1779-1781行目**: vm.hot_reload == .watchの場合、runEventLoopForWatchを実行

#### Step 3: ウォッチャー初期化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | hot_reloader.zig | `src/bun.js/hot_reloader.zig` | enableHotModuleReloading関数 |

**主要処理フロー**:
- **238-297行目**: enableHotModuleReloading関数。ウォッチャーの初期化とリゾルバへの登録
- **81-98行目**: init関数。Watcher.initの呼び出しと開始

#### Step 4: ファイル変更検出処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | hot_reloader.zig | `src/bun.js/hot_reloader.zig` | onFileUpdate関数、Task構造体 |

**主要処理フロー**:
- **331-400行目**: onFileUpdate関数。ファイル変更イベントの処理
- **159-236行目**: Task構造体。変更タスクの管理とエンキュー
- **208-216行目**: reload_immediatelyの場合、即座にbun.reloadProcessを呼び出し

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

```
test_command.zig (テストコマンド実行)
    │
    ├─ Arguments.zig (--watch オプション解析)
    │
    └─ hot_reloader.zig
           ├─ WatchReloader.enableHotModuleReloading
           │      └─ Watcher.init
           │             └─ OS固有ファイル監視API
           │
           ├─ runEventLoopForWatch (イベントループ)
           │
           └─ onFileUpdate
                  ├─ Task.append (変更ファイル追加)
                  └─ Task.enqueue
                         └─ bun.reloadProcess (プロセス再起動)
```

### データフロー図

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

ファイル変更イベント ──▶ Watcher.onFileUpdate ──────▶ 変更ログ出力
(write/delete/rename)          │
                               ▼
                        Task.append
                               │
                               ▼
                        Task.enqueue
                               │
                               ▼
                        bun.reloadProcess ───────▶ テスト再実行
                               │
                               └──▶ 画面クリア（設定時）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| hot_reloader.zig | `src/bun.js/hot_reloader.zig` | ソース | ウォッチモードの中核実装 |
| test_command.zig | `src/cli/test_command.zig` | ソース | テストコマンドからの呼び出し |
| VirtualMachine.zig | `src/bun.js/VirtualMachine.zig` | ソース | VMの状態管理、hot_reloadフィールド |
| watcher.zig | `src/watcher.zig` | ソース | OS固有ファイル監視の抽象化 |
| Arguments.zig | `src/cli/Arguments.zig` | ソース | CLI引数パース |
