# 機能設計書 24-セッションアーカイブ

## 概要

本ドキュメントは、OpenCodeにおけるセッションアーカイブ機能の設計を定義する。セッションアーカイブは、セッションを非表示にして整理する機能であり、完全な削除ではなくソフトデリートに相当する。

### 本機能の処理概要

セッションアーカイブ機能は、セッションにアーカイブタイムスタンプを設定することで、一覧表示から除外する機能である。アーカイブされたセッションは削除されず、アーカイブ解除により再び表示可能となる。

**業務上の目的・背景**：長期間使用しているとセッション数が増加し、一覧が煩雑になる。完了したタスクや参照頻度の低いセッションをアーカイブすることで、アクティブなセッションに集中できるようにする。データの完全削除を避けたいケースにも対応。

**機能の利用シーン**：ユーザーが「このセッションはもう使わないが、後で参照する可能性がある」という場合に利用される。サイドバーのセッション一覧を整理する際に使用。

**主要な処理内容**：
1. セッションのtime_archivedカラムにタイムスタンプを設定（アーカイブ）
2. セッションのtime_archivedカラムをnull（undefined）に設定（アーカイブ解除）
3. セッション更新イベントの発行
4. 一覧取得時のフィルタリング

**関連システム・外部連携**：特に外部システムとの連携はない。

**権限による制御**：特別な権限制御はない。セッション所有者（同一プロジェクト内）であればアーカイブ操作が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | レイアウト | 主画面 | セッションのアーカイブ処理 |

## 機能種別

データ更新処理（UPDATE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sessionID | string | Yes | アーカイブ対象セッションのID | session_で始まるIdentifier形式 |
| time | number | No | アーカイブタイムスタンプ | UNIXタイムスタンプ（ミリ秒）。省略時はアーカイブ解除 |

### 入力データソース

- UIからの操作（サイドバーのコンテキストメニュー等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | セッションID |
| time.archived | number? | アーカイブ日時（アーカイブ解除時はundefined） |
| その他 | Session.Info | 完全なセッション情報 |

### 出力先

- SQLiteデータベース（SessionTable.time_archived）
- Busイベント（session.updated）

## 処理フロー

### 処理シーケンス

```
1. 入力パラメータの検証
   └─ zodスキーマによる型チェック

2. セッションの更新
   └─ time_archivedカラムを更新（time指定時は値を設定、未指定時はundefined/null）

3. 更新結果の取得
   └─ RETURNING句で更新後のレコードを取得

4. イベント発行
   └─ session.updatedイベントを発行

5. 更新後のセッション情報を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[入力パラメータ検証]
    B --> C{time指定あり?}
    C -->|Yes| D[time_archived = time]
    C -->|No| E[time_archived = undefined]
    D --> F[DB UPDATE実行]
    E --> F
    F --> G{レコード存在?}
    G -->|No| H[NotFoundError]
    G -->|Yes| I[fromRow変換]
    I --> J[session.updatedイベント発行]
    J --> K[Session.Info返却]
    K --> L[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-24-01 | アーカイブ設定 | time パラメータに値を設定することでアーカイブ状態にする | time パラメータ指定時 |
| BR-24-02 | アーカイブ解除 | time パラメータを省略（undefined）することでアーカイブを解除 | time パラメータ未指定時 |
| BR-24-03 | 一覧フィルタリング | listGlobalでarchived=falseの場合、time_archivedがnullのセッションのみ返す | 一覧取得時（デフォルト） |
| BR-24-04 | アーカイブ済み表示 | listGlobalでarchived=trueの場合、全セッションを返す | 一覧取得時（オプション） |

### 計算ロジック

アーカイブ状態の判定:
```typescript
// セッションがアーカイブされているか
const isArchived = session.time.archived !== undefined
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アーカイブ/解除 | session | UPDATE | time_archivedカラムの更新 |
| 一覧取得 | session | SELECT | time_archivedによるフィルタリング |

### テーブル別操作詳細

#### SessionTable

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | time_archived | input.time（またはnull） | アーカイブ日時 |
| SELECT | time_archived | IS NULL（archived=false時）| 一覧フィルタ条件 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | NotFoundError | 指定されたセッションが存在しない | "Session not found: {sessionID}"エラーをスロー |

### リトライ仕様

リトライ機構は実装されていない。

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

Database.use()によるトランザクション管理。UPDATE成功後にイベントが発行される（Database.effect）。

## パフォーマンス要件

- アーカイブ操作は10ms以内に完了すること
- 一覧取得時のフィルタリングはインデックスを活用

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

- 同一プロジェクト内のセッションのみ操作可能
- アーカイブはソフトデリートであり、データは保持される

## 備考

- アーカイブされたセッションは共有機能から除外されない
- 子セッションを個別にアーカイブ可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | session.sql.ts | `packages/opencode/src/session/session.sql.ts` | SessionTable.time_archived定義（32行目） |
| 1-2 | index.ts | `packages/opencode/src/session/index.ts` | Session.Info.time.archived定義（142行目） |

**読解のコツ**: time_archivedはnull許容のinteger型で、UNIXタイムスタンプ（ミリ秒）を格納する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/opencode/src/session/index.ts` | Session.setArchived関数（390-409行目） |

**主要処理フロー**:
1. **390-394行目**: 入力スキーマ定義（sessionID必須、timeオプション）
2. **396-407行目**: DB更新とイベント発行
3. **399行目**: time_archived = input.time（undefinedの場合はnull相当）

#### Step 3: 一覧フィルタリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/opencode/src/session/index.ts` | Session.listGlobal関数（567-634行目） |

**主要処理フロー**:
- **593-595行目**: archived=falseの場合、isNull(SessionTable.time_archived)条件を追加

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

```
Session.setArchived (public API)
    │
    ├─ zod検証
    │      └─ sessionID, time
    │
    └─ Database.use()
           │
           ├─ db.update(SessionTable)
           │      ├─ set({ time_archived: input.time })
           │      ├─ where(eq(SessionTable.id, input.sessionID))
           │      └─ returning()
           │
           ├─ NotFoundError チェック
           │
           ├─ fromRow() 変換
           │
           └─ Database.effect()
                  └─ Bus.publish(Event.Updated)

Session.listGlobal (一覧取得)
    │
    └─ 条件構築
           │
           └─ archived=false → isNull(SessionTable.time_archived)
```

### データフロー図

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

sessionID ──────┐                                    ┌─> Session.Info
time ───────────┼──▶ Session.setArchived() ─────────┼─> DB (session)
                │           │                        └─> Bus Event
                │           ├─ DB UPDATE
                │           └─ イベント発行
                │
                │
[一覧取得]
                │
archived ───────┼──▶ Session.listGlobal() ──────────▶ Session.Info[]
                │           │
                │           └─ フィルタ条件
                │                  └─ time_archived IS NULL
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/opencode/src/session/index.ts` | ソース | setArchived関数、listGlobal関数の実装 |
| session.sql.ts | `packages/opencode/src/session/session.sql.ts` | ソース | time_archivedカラム定義 |
