# 画面設計書 108-シナリオ一覧画面

## 概要

Captain AIアシスタントが会話中に特定の状況で実行するシナリオを管理するための一覧画面設計書です。シナリオはAIの振る舞いを制御するルールベースの指示であり、作成、編集、削除、一括操作機能を提供します。

### 本画面の処理概要

**業務上の目的・背景**：Captain AIアシスタントは会話の文脈に応じて適切なアクションを実行する必要があります。シナリオは特定の条件や状況に対するAIの対応方法を定義するもので、例えば「購入希望の顧客にはセールスチームへ引き継ぐ」といったルールを設定できます。これにより、AIの応答を業務フローに合わせてカスタマイズできます。

**画面へのアクセス方法**：Captain機能のサイドナビゲーションから「Scenarios」を選択してアクセスします。URLパスは `/app/accounts/:accountId/captain/:assistantId/scenarios` です。

**主要な操作・処理内容**：
1. シナリオ一覧の表示（検索対応）
2. 新規シナリオの作成
3. 既存シナリオの編集
4. シナリオの削除（単体・一括）
5. サンプルシナリオの追加（サジェスト機能）
6. 一括選択と一括削除

**画面遷移**：
- 遷移元：Captainアシスタント一覧画面、サイドナビゲーション
- 遷移先：作成/編集ダイアログ（モーダル）

**権限による表示制御**：administrator および agent ロールがアクセス可能です。CAPTAIN_V2フィーチャーフラグが有効で、CloudまたはEnterpriseインストールタイプの場合のみ利用可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 87 | シナリオ管理 | 主機能 | シナリオの一覧表示、CRUD操作 |

## 画面種別

一覧 / 登録（ダイアログ） / 編集（インライン）

## URL/ルーティング

| パス | ルート名 |
|------|----------|
| `/app/accounts/:accountId/captain/:assistantId/scenarios` | `captain_assistants_scenarios_index` |

## 入出力項目

### 検索入力

| 項目名 | 物理名 | 型 | 必須 | バリデーション | 備考 |
|--------|--------|-----|------|---------------|------|
| 検索クエリ | searchQuery | string | No | - | picoSearchで即時フィルタ |

### シナリオ作成/編集フォーム

| 項目名 | 物理名 | 型 | 必須 | バリデーション | 備考 |
|--------|--------|-----|------|---------------|------|
| タイトル | title | string | Yes | 必須 | シナリオ名 |
| 説明 | description | string | Yes | 必須 | シナリオの説明 |
| 指示 | instruction | string | Yes | 必須 | AIへの指示内容（Markdown対応） |
| ツール | tools | array | No | - | 使用するツールのリスト（自動抽出） |

### 出力項目（一覧）

| 項目名 | 物理名 | 型 | 備考 |
|--------|--------|-----|------|
| シナリオID | id | number | 内部識別子 |
| タイトル | title | string | シナリオ名 |
| 説明 | description | string | シナリオの説明 |
| 指示 | instruction | string | AIへの指示内容 |
| ツール | tools | array | 参照ツールリスト |

## 表示項目

### ヘッダー領域

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| タイトル | "Scenarios" | セクションヘッダー |
| 説明 | テキスト | 機能説明 |

### サジェストシナリオ領域

| 項目名 | 表示形式 | 条件 | 備考 |
|--------|----------|------|------|
| サジェストシナリオ | SuggestedScenarios | show_scenarios_suggestions=true | UISettingsで制御 |
| サンプルシナリオ | カード | サジェスト表示時 | "Prospective Buyer"など |
| 追加ボタン | ボタン | サンプルごと | 個別追加 |
| 全て追加ボタン | ボタン | サジェスト表示時 | 一括追加 |

### 検索・フィルタ領域

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| 一括選択バー | BulkSelectBar | 常時表示 |
| 新規追加ダイアログ | AddNewScenariosDialog | バー内に配置 |
| 検索入力フィールド | テキスト入力 | データ存在時のみ表示 |

### シナリオカード

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| タイトル | テキスト（太字） | シナリオ名 |
| 説明 | テキスト | シナリオの説明 |
| 指示 | Markdown表示 | ツールリンク含む |
| ツール | バッジリスト | @ツール名形式 |
| 選択チェックボックス | チェックボックス | ホバー時または選択モード時表示 |
| 編集/削除ボタン | ボタン | カード内アクション |

## イベント仕様

### 1-シナリオ作成

1. AddNewScenariosDialogの「Add」ボタンをクリック
2. ダイアログでtitle, description, instructionを入力
3. Submit時に `addScenario(scenario)` が呼び出される
4. `captainScenarios/create` アクションが dispatch される
5. `getToolsFromInstruction()` で指示からツールを自動抽出
6. API成功時：成功メッセージ表示、一覧更新
7. API失敗時：エラーメッセージ表示

### 2-シナリオ編集

1. シナリオカードの編集ボタンをクリック
2. インライン編集モードが開く
3. 編集後、保存時に `updateScenario(scenario)` が呼び出される
4. `captainScenarios/update` アクションが dispatch される

### 3-シナリオ削除（単体）

1. シナリオカードの削除ボタンをクリック
2. `deleteScenario(id)` が呼び出される
3. `captainScenarios/delete` アクションが dispatch される
4. API成功時：成功メッセージ表示、一覧から削除

### 4-一括削除

1. シナリオカードのチェックボックスで複数選択
2. BulkSelectBarの削除ボタンをクリック
3. `bulkDeleteScenarios()` が呼び出される
4. Promise.allで全削除を並列実行
5. 選択状態をクリアして一覧更新

### 5-サンプルシナリオ追加

1. SuggestedScenariosの「Add」ボタンをクリック
2. 個別追加：`addScenario(item)` が呼び出される
3. 全て追加：`addAllExampleScenarios()` が呼び出される
4. サンプルデータを使用してシナリオ作成

### 6-サジェスト非表示

1. SuggestedScenariosの閉じるボタンをクリック
2. `closeSuggestedRules()` が呼び出される
3. UISettingsの `show_scenarios_suggestions` を false に更新

### 7-検索

1. 検索フィールドに入力
2. `picoSearch()` で即時フィルタリング（title, description, instruction対象）
3. `filteredScenarios` computed で結果反映

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| シナリオ一覧取得 | captain_scenarios | SELECT | アシスタントのシナリオ取得 |
| シナリオ作成 | captain_scenarios | INSERT | 新規シナリオ作成 |
| シナリオ編集 | captain_scenarios | UPDATE | シナリオ情報更新 |
| シナリオ削除 | captain_scenarios | DELETE | シナリオ削除 |
| ツール一覧取得 | captain_tools | SELECT | 利用可能ツール取得 |

### テーブル別更新項目詳細

#### captain_scenarios

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | - | `assistant_id = :assistantId` | 一覧取得条件 |
| INSERT | title, description, instruction, tools | フォーム入力値 | 新規作成 |
| UPDATE | title, description, instruction, tools | フォーム入力値 | 編集 |
| DELETE | - | `id = :scenarioId` | 指定ID削除 |

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 |
|------|---------------|---------------|
| 成功 | CAPTAIN.ASSISTANTS.SCENARIOS.API.ADD.SUCCESS | シナリオ追加成功 |
| エラー | CAPTAIN.ASSISTANTS.SCENARIOS.API.ADD.ERROR | シナリオ追加失敗 |
| 成功 | CAPTAIN.ASSISTANTS.SCENARIOS.API.UPDATE.SUCCESS | シナリオ更新成功 |
| エラー | CAPTAIN.ASSISTANTS.SCENARIOS.API.UPDATE.ERROR | シナリオ更新失敗 |
| 成功 | CAPTAIN.ASSISTANTS.SCENARIOS.API.DELETE.SUCCESS | シナリオ削除成功 |
| エラー | CAPTAIN.ASSISTANTS.SCENARIOS.API.DELETE.ERROR | シナリオ削除失敗 |

## 例外処理

| 例外条件 | 処理内容 | 表示 |
|----------|----------|------|
| データ取得中 | isFetchingフラグでローディング表示 | PageLayoutのローディング |
| シナリオ0件 | 空メッセージ表示 | "No scenarios available" |
| 検索結果0件 | 空メッセージ表示 | "No scenarios match your search" |
| API通信エラー | アラート表示 | エラーメッセージ |

## 備考

- CAPTAIN_V2フィーチャーフラグが必要（V2専用機能）
- 検索はpicoSearchでクライアントサイドフィルタリング（サーバー通信なし）
- 指示内のツールリンクは `(tool://tool_name)` 形式で記述
- `getToolsFromInstruction()` で指示からツール参照を自動抽出
- サンプルシナリオはハードコードされた例（scenariosExample）
- UISettingsでサジェスト表示を制御（ユーザー単位）
- 一括削除はPromise.allで並列実行（TODO: バルク削除エンドポイント実装予定）

---

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

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

### 推奨読解順序

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

まず、シナリオデータの構造とストアの状態管理を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | scenarios.js (store) | `app/javascript/dashboard/store/captain/scenarios.js` | ストア定義、カスタムのupdate/deleteアクションを確認 |
| 1-2 | scenarios.js (api) | `app/javascript/dashboard/api/captain/scenarios.js` | APIクライアント、assistantIdパラメータを確認 |

**読解のコツ**: APIはアシスタントIDベースのネストされたリソース構造（`assistants/:id/scenarios`）です。

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

処理の起点となるVueコンポーネントを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue (scenarios) | `app/javascript/dashboard/routes/dashboard/captain/assistants/scenarios/Index.vue` | メインコンポーネントの構造を確認 |

**主要処理フロー**:
1. **25行目**: `assistantId` をルートパラメータから取得
2. **43-53行目**: `scenariosExample` でサンプルシナリオ定義
3. **55-59行目**: `filteredScenarios` でpicoSearch使用
4. **98-102行目**: `getToolsFromInstruction()` でツール抽出
5. **104-119行目**: `updateScenario()` で更新処理
6. **151-165行目**: `addScenario()` で作成処理
7. **184-189行目**: `onMounted` でデータ取得

#### Step 3: 検索機能を理解する

クライアントサイドフィルタリングの実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Index.vue (scenarios) | `app/javascript/dashboard/routes/dashboard/captain/assistants/scenarios/Index.vue` | picoSearchの使用方法を確認（55-59行目） |

**読解のコツ**: `picoSearch` は `@scmmishra/pico-search` パッケージで、クライアントサイドの高速全文検索を提供します。

#### Step 4: API通信層を理解する

バックエンドとの通信処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | scenarios.js (api) | `app/javascript/dashboard/api/captain/scenarios.js` | ネストされたリソースのCRUD操作を確認 |

**主要処理フロー**:
- **5行目**: `captain/assistants` ベースエンドポイント
- **9-11行目**: `get` メソッドで `/:assistantId/scenarios` にアクセス
- **19-22行目**: `create` メソッドで `scenario` ラッパー使用

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

```
Index.vue (scenarios)
    |
    +-- PageLayout.vue
    |       |
    |       +-- SettingsHeader (タイトル、説明)
    |
    +-- SuggestedScenarios.vue (条件付き表示)
    |       |
    |       +-- scenariosExample (サンプルデータ)
    |       +-- @add -> addScenario() または addAllExampleScenarios()
    |       +-- @close -> closeSuggestedRules()
    |
    +-- BulkSelectBar.vue
    |       |
    |       +-- #default-actions
    |       |       |
    |       |       +-- AddNewScenariosDialog
    |       |
    |       +-- @bulk-delete -> bulkDeleteScenarios()
    |
    +-- Input.vue (検索)
    |       |
    |       +-- v-model -> searchQuery
    |       +-- filteredScenarios (picoSearch)
    |
    +-- ScenariosCard.vue (複数)
            |
            +-- @select -> handleRuleSelect()
            +-- @delete -> deleteScenario()
            +-- @update -> updateScenario()
            +-- @hover -> handleRuleHover()
```

### データフロー図

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

URLアクセス ──────────▶ onMounted
                              │
                              ├── captainScenarios/get
                              │       │
                              │       ▼
                              │   GET /api/v1/.../captain/assistants/:id/scenarios
                              │
                              └── captainTools/getTools (ツール一覧)
                                      │
                                      ▼
                              Vuex State更新
                                      │
                                      ▼
                              ScenariosCard描画 ────────▶ シナリオ一覧

検索入力 ────────────▶ searchQuery
                              │
                              ▼
                        picoSearch(scenarios, query, ['title', 'description', 'instruction'])
                              │
                              ▼
                        filteredScenarios ────────▶ フィルタ済み一覧

シナリオ作成 ────────▶ addScenario()
                              │
                              ├── getToolsFromInstruction()
                              │
                              ▼
                        captainScenarios/create
                              │
                              ▼
                        POST /api/v1/.../captain/assistants/:id/scenarios
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/captain/assistants/scenarios/Index.vue` | ソース | メイン画面コンポーネント |
| captain.routes.js | `app/javascript/dashboard/routes/dashboard/captain/captain.routes.js` | 設定 | ルーティング定義 |
| scenarios.js (store) | `app/javascript/dashboard/store/captain/scenarios.js` | ソース | Vuexストアモジュール |
| scenarios.js (api) | `app/javascript/dashboard/api/captain/scenarios.js` | ソース | APIクライアント |
| ScenariosCard.vue | `app/javascript/dashboard/components-next/captain/assistant/ScenariosCard.vue` | ソース | シナリオカード |
| SuggestedScenarios.vue | `app/javascript/dashboard/components-next/captain/assistant/SuggestedRules.vue` | ソース | サジェスト表示 |
| AddNewScenariosDialog.vue | `app/javascript/dashboard/components-next/captain/assistant/AddNewScenariosDialog.vue` | ソース | 作成ダイアログ |
| BulkSelectBar.vue | `app/javascript/dashboard/components-next/captain/assistant/BulkSelectBar.vue` | ソース | 一括選択バー |
| SettingsHeader.vue | `app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.vue` | ソース | ヘッダーコンポーネント |
| useUISettings.js | `app/javascript/dashboard/composables/useUISettings.js` | ソース | UISettings composable |
