# 通知設計書 10-Auto-accepting edits

## 概要

本ドキュメントは、OpenCodeアプリケーションにおける「Auto-accepting edits（編集自動承認）」トースト通知の設計を記述します。セッションの編集権限自動承認モードが有効化された際に、ユーザーに対してアプリ内トースト通知を表示する機能です。

### 本通知の処理概要

**業務上の目的・背景**：OpenCodeはAIエージェントがファイル編集を行う際に、セキュリティ上の理由から権限確認を求めます。しかし、頻繁な確認は作業効率を低下させるため、信頼できるセッションでは編集権限を自動承認するモードを提供しています。このモードの有効化/無効化をユーザーに明確にフィードバックする必要があります。

**通知の送信タイミング**：ユーザーがpermissions.autoacceptコマンドを実行し、自動承認モードをオフからオンに切り替えた時に即座に送信されます。コマンドパレットまたはキーバインド（Cmd/Ctrl+Shift+A）で発火します。

**通知の受信者**：自動承認を有効化したユーザー本人。設定による制御はなく、常に表示されます。

**通知内容の概要**：通知タイトル「Auto-accepting edits」と、「Edit and write permissions will be automatically approved」という説明が表示されます。

**期待されるアクション**：ユーザーは以降の編集権限リクエストが自動的に承認されることを認識します。作業完了後やセキュリティ上の懸念がある場合は、同じコマンドで無効化できます。

## 通知種別

アプリ内トースト通知（一時的）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ユーザーアクション直後） |
| 優先度 | 低 |
| リトライ | なし |

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

1. ユーザーがpermissions.autoacceptコマンドを実行
2. permission.isAutoAccepting()で現在の状態を確認
3. permission.toggleAutoAccept()でトグル実行
4. トグル後の状態がオン→showToast()で有効化通知を表示
5. トグル後の状態がオフ→showToast()で無効化通知を表示

## 通知テンプレート

### アプリ内トースト通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | `toast.permissions.autoaccept.on.title`（"Auto-accepting edits"） |
| 説明 | `toast.permissions.autoaccept.on.description`（"Edit and write permissions will be automatically approved"） |
| 永続性 | なし（自動消去） |
| アクション | なし |

### 本文テンプレート

```
タイトル: Auto-accepting edits
説明: Edit and write permissions will be automatically approved
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルは使用されません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 固定テキスト | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ユーザーアクション | permissions.autoacceptコマンド | オフ→オンの場合 | 自動承認有効化時 |
| ユーザーアクション | キーバインド（Cmd/Ctrl+Shift+A） | オフ→オンの場合 | 自動承認有効化時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 既に有効な場合 | オン→オフは「Stopped auto-accepting edits」通知が代わりに表示 |
| セッション未選択 | params.idがない場合はコマンドがdisabled |
| 権限設定なし | permission.permissionsEnabled()がfalseの場合はコマンドがdisabled |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[permissions.autoacceptコマンド実行] --> B{params.id存在?}
    B -->|No| C[コマンド無効]
    B -->|Yes| D{権限設定有効?}
    D -->|No| C
    D -->|Yes| E[toggleAutoAccept実行]
    E --> F{isAutoAccepting?}
    F -->|Yes| G[showToast - on]
    F -->|No| H[showToast - off]
    G --> I[トースト表示]
    H --> I
    C --> J[終了]
    I --> J
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| permission.autoAcceptEdits | 自動承認状態の確認 | persisted store |
| config.permission | 権限設定の確認 | GlobalSync経由 |

### テーブル別参照項目詳細

#### permission store

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| autoAcceptEdits[key] | セッション別自動承認状態 | acceptKey(sessionID, directory) |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| permission.autoAcceptEdits | UPDATE | 自動承認状態の更新 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|------------|
| セッション未選択 | params.idがundefined | コマンドがdisabledで発火しない |
| 権限設定なし | permission.permissionsEnabled()がfalse | コマンドがdisabledで発火しない |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（24時間配信可能）

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

- 固定テキストのためセキュリティリスクは低い
- 自動承認有効化はセキュリティ上のリスクを伴うため、明確な通知が重要
- 自動承認はセッション単位で管理され、他のセッションには影響しない
- 状態はpersistedストアに保存され、ブラウザ再起動後も維持される

## 備考

- 「Stopped auto-accepting edits」通知と対になる通知
- 自動承認はedit権限のみに適用される（shouldAutoAccept関数で判定）
- キーバインドはCmd/Ctrl+Shift+A
- 権限設定（config.permission）がallowの場合はコマンド自体が表示されない
- 自動承認有効時、permission.askedイベントに対して自動的にrespondOnce()が呼ばれる

---

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

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

### 推奨読解順序

#### Step 1: コマンド定義を理解する

permissions.autoacceptコマンドの定義を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | use-session-commands.tsx | `packages/app/src/pages/session/use-session-commands.tsx` | permissions.autoacceptコマンド（264-287行目）を理解 |

**読解のコツ**: toggleAutoAccept実行後にisAutoAccepting()でトグル後の状態を確認し、適切な通知を表示していることに注目。

**主要処理フロー**:
1. **272行目**: disabled判定（params.idなし or permissionsEnabled()がfalse）
2. **276行目**: permission.toggleAutoAccept()でトグル
3. **277-284行目**: isAutoAccepting()に基づいて適切な通知を表示

#### Step 2: Permission Contextの実装を理解する

自動承認の状態管理ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | permission.tsx | `packages/app/src/context/permission.tsx` | toggleAutoAccept関数（180-187行目）を理解 |
| 2-2 | permission.tsx | `packages/app/src/context/permission.tsx` | isAutoAccepting関数（113-116行目）を確認 |
| 2-3 | permission.tsx | `packages/app/src/context/permission.tsx` | enable/disable関数（137-171行目）を確認 |

**主要処理フロー**:
- **113-116行目**: isAutoAccepting()でセッション/ディレクトリ別の状態を取得
- **137-160行目**: enable()でautoAcceptEditsをtrueに設定し、既存の権限リクエストを自動承認
- **162-171行目**: disable()でautoAcceptEditsをfalseに設定

#### Step 3: 自動承認イベントリスナーを理解する

permission.askedイベントの自動処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | permission.tsx | `packages/app/src/context/permission.tsx` | イベントリスナー（125-135行目）を確認 |

**主要処理フロー**:
- **125-135行目**: permission.askedイベントを監視し、isAutoAccepting()がtrue かつ shouldAutoAccept()がtrueの場合、respondOnce()で自動承認

#### Step 4: i18nキーを理解する

通知テキストの定義を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | en.ts | `packages/app/src/i18n/en.ts` | toast.permissions.autoaccept.on.*（405-406行目）を確認 |

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

```
permissions.autoacceptコマンド (use-session-commands.tsx:264)
    │
    ├─ disabled判定 (272行目)
    │      ├─ !params.id → disabled
    │      └─ !permission.permissionsEnabled() → disabled
    │
    ├─ permission.toggleAutoAccept (276行目)
    │      │
    │      ├─ isAutoAccepting() ? disable() : enable()
    │      │      │
    │      │      ├─ enable() (permission.tsx:137)
    │      │      │      ├─ setStore({ autoAcceptEdits[key]: true })
    │      │      │      └─ 既存権限リクエストを自動承認
    │      │      │
    │      │      └─ disable() (permission.tsx:162)
    │      │             └─ setStore({ delete autoAcceptEdits[key] })
    │      │
    │      └─ 状態変更完了
    │
    └─ showToast (277-284行目)
           │
           └─ isAutoAccepting() ? on通知 : off通知
                  │
                  ├─ title: "Auto-accepting edits"
                  └─ description: "Edit and write permissions..."
```

### データフロー図

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

ユーザーアクション          use-session-commands
Cmd+Shift+A     ────▶    toggleAutoAccept()  ───────────────▶ トースト通知
                              │
                              ▼
                         permission.tsx
                              │
                         ┌────┴────┐
                         │         │
                      enable()  disable()
                         │         │
                         ▼         ▼
                    setStore()  setStore()
                         │         │
                         └────┬────┘
                              ▼
                         isAutoAccepting()
                              │
                         showToast({
                           title: "Auto-accepting edits",
                           description: "Edit and write..."
                         })

[イベント自動処理]

permission.asked ────▶ isAutoAccepting? ────▶ respondOnce()
イベント                  │                    （自動承認）
                         ▼
                    shouldAutoAccept?
                    (edit権限のみ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| use-session-commands.tsx | `packages/app/src/pages/session/use-session-commands.tsx` | ソース | コマンド定義・トースト表示 |
| permission.tsx | `packages/app/src/context/permission.tsx` | ソース | 自動承認状態管理 |
| prompt-input.tsx | `packages/app/src/components/prompt-input.tsx` | ソース | 自動承認UI表示 |
| toast.tsx | `packages/ui/src/components/toast.tsx` | ソース | showToast関数 |
| en.ts | `packages/app/src/i18n/en.ts` | 設定 | 翻訳キー定義 |
