# 機能設計書 44-ローカル履歴

## 概要

本ドキュメントは、VS Codeのローカル履歴機能に関する機能設計書である。ファイル保存時に自動的にローカルで変更履歴を保存・管理する機能を定義する。

### 本機能の処理概要

ローカル履歴機能は、ファイル保存時に自動的にスナップショットを作成し、ローカルで変更履歴を管理する機能である。Git等のバージョン管理システムとは独立して動作し、過去の状態への復元を可能にする。

**業務上の目的・背景**：コーディング中の「元に戻したい」「過去の状態を確認したい」というニーズに対して、バージョン管理システムに依存せずにローカルで履歴を管理できる機能を提供する。Git管理外のファイルや、コミット前の細かい変更も追跡可能になる。

**機能の利用シーン**：
- 誤って重要なコードを削除・変更してしまった場合の復元
- 過去の実装との差分確認
- 自動保存による頻繁な保存履歴の管理
- Git管理外のファイルの変更追跡

**主要な処理内容**：
1. ファイル保存時の履歴エントリ作成（cloneFile操作）
2. 履歴エントリのメタデータ管理（entries.json）
3. タイムラインビューへの履歴表示
4. 履歴エントリの閲覧・復元・削除
5. 履歴エントリのマージ（設定された時間窓内）
6. 古い履歴エントリの自動削除

**関連システム・外部連携**：
- ファイルシステムサービス（履歴ファイルの保存・読込）
- タイムラインサービス（TimelineProvider連携）
- 設定サービス（履歴の有効/無効、最大エントリ数等）
- ラベルサービス（ファイル名の表示）

**権限による制御**：設定（`workbench.localHistory.enabled`）で機能の有効/無効を切り替え可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | タイムラインビュー | 主画面 | ファイルのローカル変更履歴表示 |

## 機能種別

データ管理 / ファイル操作 / UI連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| workingCopyResource | URI | Yes | 対象ファイルのURI | - |
| source | SaveSource | No | 保存ソース（デフォルト: 'File Saved'） | - |
| sourceDescription | string | No | 保存ソースの説明 | - |
| timestamp | number | No | タイムスタンプ（デフォルト: Date.now()） | - |

### 設定項目

| 設定キー | 型 | デフォルト | 説明 |
|---------|-----|---------|------|
| workbench.localHistory.enabled | boolean | true | ローカル履歴の有効/無効 |
| workbench.localHistory.maxFileEntries | number | 50 | 1ファイルあたりの最大エントリ数 |
| workbench.localHistory.mergeWindow | number | 10 | マージ対象とする時間窓（秒） |

### 入力データソース

- ファイル保存イベント（WorkingCopyHistoryTracker経由）
- タイムラインビューからのリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| IWorkingCopyHistoryEntry | interface | 履歴エントリ |
| id | string | エントリID（ランダム4文字 + 拡張子） |
| location | URI | 履歴ファイルの保存場所 |
| timestamp | number | 作成/更新タイムスタンプ |
| source | SaveSource | 保存ソース |
| workingCopy | object | 元ファイル情報 |

### 出力先

- ファイルシステム（履歴ディレクトリ）
- タイムラインビュー（UIへの表示）
- entries.json（メタデータファイル）

## 処理フロー

### 処理シーケンス

```
1. ファイル保存イベント検知
   └─ WorkingCopyHistoryTracker がファイル保存を検知

2. 履歴エントリ作成判定
   └─ マージウィンドウ内かチェック
   └─ 同一ソースの場合は置換、それ以外は新規作成

3. ファイルクローン
   └─ fileService.cloneFile() で高速コピー
   └─ 履歴ディレクトリに保存

4. メタデータ更新
   └─ entries.json に履歴情報を追加
   └─ flushOnChange 設定に応じて即時保存

5. イベント発火
   └─ onDidAddEntry / onDidReplaceEntry を発火
   └─ タイムラインビューが更新

6. 古いエントリの削除
   └─ maxFileEntries を超えた場合に古いものから削除
```

### フローチャート

```mermaid
flowchart TD
    A[ファイル保存] --> B{ローカル履歴有効?}
    B -->|No| C[終了]
    B -->|Yes| D[最新エントリ取得]
    D --> E{マージウィンドウ内?}
    E -->|Yes| F{同一ソース?}
    F -->|Yes| G[エントリ置換]
    F -->|No| H[新規エントリ作成]
    E -->|No| H
    G --> I[cloneFile実行]
    H --> I
    I --> J[メタデータ更新]
    J --> K{flushOnChange?}
    K -->|Yes| L[entries.json保存]
    K -->|No| M[イベント発火]
    L --> M
    M --> N{maxEntries超過?}
    N -->|Yes| O[古いエントリ削除]
    N -->|No| P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-44-01 | マージウィンドウ | 設定された時間窓（秒）内の同一ソースからの保存は置換 | エントリ追加時 |
| BR-44-02 | 最大エントリ制限 | maxFileEntries設定を超えるエントリは古いものから削除 | getEntries時 |
| BR-44-03 | ハッシュベース格納 | 履歴はファイルURIのハッシュ値をディレクトリ名として格納 | エントリ作成時 |
| BR-44-04 | スキーマ対応 | vscode-local-historyスキーマで履歴ファイルにアクセス | 履歴参照時 |

### 計算ロジック

**履歴ディレクトリパスの計算**：
```typescript
// toHistoryEntriesFolder() より
private toHistoryEntriesFolder(historyHome: URI, workingCopyResource: URI): URI {
    return joinPath(historyHome, hash(workingCopyResource.toString()).toString(16));
}
```

**マージ判定**：
```typescript
// addEntry() より
const configuredReplaceInterval = this.configurationService.getValue<number>('workbench.localHistory.mergeWindow');
if (timestamp - lastEntry.timestamp <= (configuredReplaceInterval * 1000)) {
    entryToReplace = lastEntry;
}
```

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

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

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| 履歴ファイル作成 | ファイルシステム | CREATE | cloneFileで履歴スナップショット作成 |
| メタデータ保存 | entries.json | CREATE/UPDATE | 履歴メタデータの保存 |
| 履歴削除 | ファイルシステム | DELETE | 古いエントリの削除 |

### ファイル構造

```
historyHome/
└─ {hash(resource)}/ (16進数ハッシュ)
   ├─ entries.json (メタデータ)
   ├─ Abc1.ts (履歴エントリ1)
   ├─ Xyz2.ts (履歴エントリ2)
   └─ ...
```

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FILE_NOT_FOUND | システムエラー | 元ファイルが存在しない | エントリ作成をスキップ |
| CLONE_FAILED | システムエラー | ファイルコピーに失敗 | エラーログ出力、処理継続 |
| METADATA_CORRUPT | システムエラー | entries.jsonの解析失敗 | ディスクスキャンでエントリ復元 |

### リトライ仕様

ファイル操作の失敗時はリトライを行わない。失敗はログ出力して処理を継続。

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

トランザクション制御は行わない。各操作は独立して実行され、失敗しても他の操作に影響しない。

## パフォーマンス要件

- cloneFile操作による高速コピー（内容比較なし）
- Limiter(1)による順次書き込み
- 遅延解決（resolveEntriesOnce）によるオンデマンド読込
- MAX_PARALLEL_HISTORY_IO_OPS による並列I/O制限

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

- 履歴ファイルはローカルに保存（リモートには送信されない）
- 機密ファイルの履歴も保存されるため、ローカルディスクのセキュリティに依存
- 履歴ディレクトリのパーミッションはファイルシステムのデフォルトに従う

## 備考

- Git等のバージョン管理システムとは独立して動作
- リモートワークスペースでも動作（リモートのファイルシステムに保存）

---

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

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

### 推奨読解順序

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

ローカル履歴機能で使用される主要なインターフェースと型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | workingCopyHistory.ts | `src/vs/workbench/services/workingCopy/common/workingCopyHistory.ts` | IWorkingCopyHistoryEntry、IWorkingCopyHistoryService を確認 |
| 1-2 | localHistory.ts | `src/vs/workbench/contrib/localHistory/browser/localHistory.ts` | コンテキストキー、アイコン定義 |

**読解のコツ**: IWorkingCopyHistoryServiceがサービスインターフェース、WorkingCopyHistoryModelが個々のファイルの履歴管理を担当。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | workingCopyHistoryService.ts | `src/vs/workbench/services/workingCopy/common/workingCopyHistoryService.ts` | WorkingCopyHistoryModel クラス（57行目〜） |

**主要処理フロー**:
1. **122-155行目**: `addEntry()` で履歴エントリ作成
2. **157-185行目**: `doAddEntry()` でファイルクローンと履歴追加
3. **187-205行目**: `doReplaceEntry()` でエントリ置換
4. **270-282行目**: `getEntries()` で履歴取得（maxEntries考慮）

#### Step 3: タイムライン連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | localHistoryTimeline.ts | `src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts` | LocalHistoryTimeline クラス（28-166行目） |

**主要処理フロー**:
- **28行目**: `LocalHistoryTimeline implements TimelineProvider`
- **69-75行目**: `updateTimelineRegistration()` で設定に応じた登録制御
- **105-148行目**: `provideTimeline()` でタイムラインアイテム生成
- **150-165行目**: `toTimelineItem()` でエントリをTimelineItemに変換

#### Step 4: ファイルシステムプロバイダーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | localHistoryFileSystemProvider.ts | `src/vs/workbench/contrib/localHistory/browser/localHistoryFileSystemProvider.ts` | vscode-local-historyスキーマのプロバイダー |

**主要処理フロー**:
- `SCHEMA = 'vscode-local-history'`
- `fromLocalHistoryFileSystem()` でスキーマからリソースへの変換
- 履歴ファイルへの読み取りアクセス提供

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

```
IWorkingCopyHistoryService
    │
    ├─ WorkingCopyHistoryModel (per file)
    │      ├─ addEntry() [履歴追加]
    │      ├─ removeEntry() [履歴削除]
    │      ├─ getEntries() [履歴取得]
    │      └─ store() [メタデータ保存]
    │
    ├─ WorkingCopyHistoryTracker
    │      └─ ファイル保存イベントの監視
    │
    └─ LocalHistoryTimeline (TimelineProvider)
           ├─ provideTimeline() [タイムライン生成]
           └─ onDidChange [変更イベント]
```

### データフロー図

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

ファイル保存       ───▶ WorkingCopyHistoryTracker  ───▶ addEntry呼び出し
イベント                       │
                              ▼
                    WorkingCopyHistoryModel
                              │
                              ├──▶ cloneFile()         ───▶ 履歴ファイル
                              │                              (historyHome/{hash}/)
                              │
                              └──▶ store()             ───▶ entries.json
                              │
                              ▼
                    イベント発火
                              │
                              ▼
タイムラインビュー ◀─── LocalHistoryTimeline      ◀─── onDidChange
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| workingCopyHistoryService.ts | `src/vs/workbench/services/workingCopy/common/workingCopyHistoryService.ts` | ソース | モデル実装 |
| workingCopyHistory.ts | `src/vs/workbench/services/workingCopy/common/workingCopyHistory.ts` | ソース | インターフェース定義 |
| workingCopyHistoryTracker.ts | `src/vs/workbench/services/workingCopy/common/workingCopyHistoryTracker.ts` | ソース | 保存イベント監視 |
| localHistory.ts | `src/vs/workbench/contrib/localHistory/browser/localHistory.ts` | ソース | 定数・ユーティリティ |
| localHistoryTimeline.ts | `src/vs/workbench/contrib/localHistory/browser/localHistoryTimeline.ts` | ソース | タイムライン連携 |
| localHistoryCommands.ts | `src/vs/workbench/contrib/localHistory/browser/localHistoryCommands.ts` | ソース | コマンド定義 |
| localHistoryFileSystemProvider.ts | `src/vs/workbench/contrib/localHistory/browser/localHistoryFileSystemProvider.ts` | ソース | ファイルシステムプロバイダー |
| localHistory.contribution.ts | `src/vs/workbench/contrib/localHistory/browser/localHistory.contribution.ts` | ソース | 機能登録 |
