# 機能設計書 32-ノード生成履歴

## 概要

本ドキュメントは、Giselleワークフローエンジンにおける「ノード生成履歴」機能の設計を記述する。本機能は、特定のノードに関連する過去の生成結果（Generation）の履歴を取得するAPIを提供する。

### 本機能の処理概要

本機能は、指定されたノードIDに紐づく生成履歴をストレージから取得し、時系列順（新しい順）でソートした最新10件の生成結果を返却する。

**業務上の目的・背景**：ワークフローの各ノードがどのような出力を生成してきたかを確認することで、デバッグや結果の比較、処理の傾向分析が可能となる。特にテキスト生成ノードや画像生成ノードの出力履歴を振り返る際に活用される。

**機能の利用シーン**：
- ワークフローエディタでノードの過去の生成結果を確認する場合
- 同じノードの異なる実行結果を比較する場合
- 生成品質の経時変化を確認する場合

**主要な処理内容**：
1. ノードID（NodeId）と生成オリジン（GenerationOrigin）を受け取る
2. ノードに紐づく生成インデックス一覧を取得
3. 作成日時の降順でソートし、最新10件に絞り込む
4. 各生成IDから生成データを並列取得
5. 取得できた生成結果のリストを返却

**関連システム・外部連携**：GiselleStorageを介したファイルストレージとの連携

**権限による制御**：ワークスペースへのアクセス権限を持つユーザーのみが生成履歴を取得可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ワークフローエディタ画面 | 主画面 | ノードの生成履歴表示 |

## 機能種別

データ取得（SELECT操作）/ 一覧取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| context | GiselleContext | Yes | Giselle実行コンテキスト（ストレージ参照を含む） | - |
| origin | GenerationOrigin | Yes | 生成オリジン（studio/stage/github-app/api） | - |
| nodeId | NodeId | Yes | 対象ノードのID | `nd-`プレフィックス付きID形式 |

### 入力データソース

- ストレージ（GiselleStorage）からノード生成インデックスおよび生成データを取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (配列) | Generation[] | 生成結果の配列（最大10件、作成日時の昇順） |

各Generation要素の構造は機能No.31「生成取得」を参照。

### 出力先

呼び出し元への戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. ノードIDから生成インデックスパスを計算
   └─ `generations/byNode/{nodeId}.json`

2. ノード生成インデックス一覧を取得
   └─ NodeGenerationIndex[]を取得

3. 存在チェック
   └─ インデックスが存在しない場合は空配列を返却

4. ソート・絞り込み
   └─ createdAtの降順でソート、先頭10件を取得

5. 順序を逆転
   └─ 古い順（昇順）に並べ替え

6. 各生成データを並列取得
   └─ Promise.allで並列処理、エラー時はnull

7. 有効な生成結果のみをフィルタリングして返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[nodeIdから生成インデックスパス計算]
    B --> C[ストレージからインデックス取得]
    C --> D{インデックス存在?}
    D -->|No| E[空配列を返却]
    D -->|Yes| F[createdAt降順でソート]
    F --> G[先頭10件に絞り込み]
    G --> H[順序を逆転（昇順）]
    H --> I[各generationIdから並列取得]
    I --> J[nullをフィルタリング]
    J --> K[Generation配列を返却]
    E --> L[終了]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-001 | 取得件数上限 | 最大10件の生成履歴を取得 | 常時 |
| BR-32-002 | ソート順序 | 最終的に作成日時の昇順（古い順）で返却 | 常時 |
| BR-32-003 | エラー許容 | 個別の生成データ取得失敗時はスキップ | 常時 |

### 計算ロジック

- limit定数: 10（ハードコード）
- ソート: createdAt（Unixタイムスタンプ）の降順 → slice(0, 10) → reverse()

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インデックス取得 | ストレージ（ファイル） | SELECT | generations/byNode/{nodeId}.jsonの読み込み |
| 生成データ取得 | ストレージ（ファイル） | SELECT | generations/{id}/generation.jsonの読み込み（複数） |

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

#### ストレージ（generations/byNode/{nodeId}.json）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | NodeGenerationIndex[] | nodeIdでパス指定 | 配列形式 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | インデックス不在 | ノードの生成インデックスが存在しない | 空配列を返却 |
| - | 生成データ取得失敗 | 個別の生成データ取得でエラー | nullとして処理、最終結果からフィルタリング |

### リトライ仕様

該当なし（個別エラーは許容し、取得可能なデータのみ返却）

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

該当なし（読み取り専用操作）

## パフォーマンス要件

- レスポンス時間：500ms以内（最大10件の並列取得込み）
- 同時アクセス：ストレージドライバの制限に依存

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

- GiselleContextを通じてアクセス制御
- ワークスペース境界を超えたアクセスは不可

## 備考

- limit定数（10件）はハードコードされており、現状変更不可
- 生成データの取得失敗は静かに無視される（.catch(() => null)）

---

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

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

### 推奨読解順序

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

まず、NodeGenerationIndexの型定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/protocol/src/generation/index.ts` | NodeGenerationIndex型（180-191行目）を理解 |
| 1-2 | context.ts | `packages/protocol/src/generation/context.ts` | GenerationOrigin型を理解 |

**読解のコツ**: NodeGenerationIndexはGenerationの軽量インデックス。idとnodeId、各種タイムスタンプを持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | get-node-generations.ts | `packages/giselle/src/generations/get-node-generations.ts` | 公開API関数の全体フロー |

**主要処理フロー**:
1. **5行目**: limit定数を10に設定
2. **7-11行目**: 引数の型定義（context, origin, nodeId）
3. **12-15行目**: getNodeGenerationIndexes呼び出し
4. **16-18行目**: インデックス不在時は空配列返却
5. **19-21行目**: createdAt降順ソート、先頭10件取得
6. **22行目**: reverse()で昇順に変換
7. **23-28行目**: Promise.allで並列取得、エラー時はnull
8. **30行目**: nullをフィルタリング

#### Step 3: ユーティリティ層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | utils.ts | `packages/giselle/src/generations/utils.ts` | getNodeGenerationIndexes関数（415-426行目） |

**主要処理フロー**:
- **411行目**: nodeGenerationIndexPath関数でストレージパス生成
- **419行目**: ストレージ存在チェック
- **420-421行目**: 存在しない場合はundefinedを返却
- **422-425行目**: NodeGenerationIndex配列として取得

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

```
getNodeGenerations (get-node-generations.ts)
    │
    ├─ getNodeGenerationIndexes (utils.ts)
    │      │
    │      ├─ nodeGenerationIndexPath() - インデックスパス生成
    │      │
    │      └─ storage.getJson()
    │             │
    │             └─ NodeGenerationIndex.array().parse()
    │
    └─ getGeneration (utils.ts) × N件
           │
           └─ storage.getJson()
                  │
                  └─ Generation.parse()
```

### データフロー図

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

nodeId ───▶ nodeGenerationIndexPath() ───▶ インデックスパス
                         │
                         ▼
              storage.getJson() ───▶ NodeGenerationIndex[]
                         │
                         ▼
               sort(createdAt desc) ───▶ ソート済み配列
                         │
                         ▼
                  slice(0, 10) ───▶ 最新10件
                         │
                         ▼
                    reverse() ───▶ 昇順配列
                         │
                         ▼
              Promise.all(getGeneration) ───▶ Generation[]
                         │
                         ▼
                filter(!!generation) ───▶ Generation[]返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| get-node-generations.ts | `packages/giselle/src/generations/get-node-generations.ts` | ソース | 公開API関数 |
| utils.ts | `packages/giselle/src/generations/utils.ts` | ソース | getNodeGenerationIndexes、getGeneration実装 |
| index.ts | `packages/protocol/src/generation/index.ts` | ソース | NodeGenerationIndex、Generation型定義 |
| context.ts | `packages/protocol/src/generation/context.ts` | ソース | GenerationOrigin型定義 |
