# 機能設計書 21-タスク開始

## 概要

本ドキュメントは、Giselleシステムにおける「タスク開始」機能の設計仕様を定義する。この機能は、事前に作成されたタスクの実行を開始するためのコア機能である。

### 本機能の処理概要

**業務上の目的・背景**：ワークフローの実行において、タスクの作成と開始を分離することで、実行前の検証やバッチ処理、外部システムからの実行制御など、柔軟な実行管理が可能となる。この分離により、タスクの作成後に条件を満たした時点で実行を開始する、といった高度な制御フローを実現できる。

**機能の利用シーン**：
- ワークフローエディタのRunボタン押下時に、事前に作成されたタスクを開始する場合
- GitHub Webhookイベントを受信し、対応するタスクの実行を開始する場合
- API経由でタスクの実行開始をトリガーする場合
- バッチ処理で複数のタスクを順次実行する場合

**主要な処理内容**：
1. 指定されたタスクIDに基づいてタスクデータを取得する
2. タスクのステータスが「created」であることを検証する
3. タスクのステータスを「inProgress」に更新する
4. 実行プロセスタイプに応じて、自己実行または外部プロセス委譲を行う
5. タスク実行完了後に生成結果のコールバックを呼び出す

**関連システム・外部連携**：
- Storage: タスクデータの永続化と取得
- Generation Engine: 各ノードの生成処理実行
- GitHub App: Webhookイベントからのタスク開始トリガー

**権限による制御**：
- ワークスペースへのアクセス権限を持つユーザーのみがタスクを開始可能
- API経由の場合は、適切なAPIキーによる認証が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ワークフローエディタ画面 | 主画面 | Runボタン押下によるタスク開始 |
| 18 | プレイグラウンド画面 | 主画面 | アプリ実行テストでのタスク開始 |

## 機能種別

CRUD操作（Update） / 非同期処理実行

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| taskId | TaskId（文字列） | Yes | 開始対象のタスクID | `tsk_`で始まる有効なID形式 |
| generationOriginType | string（enum） | Yes | 生成元タイプ | "studio" / "github-app" / "api" / "stage" |
| onGenerationComplete | function | No | 生成完了時のコールバック | - |
| onGenerationError | function | No | 生成エラー時のコールバック | - |

### 入力データソース

- Storage: `tasks/{taskId}.json` からタスクデータを取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| - | void | 戻り値なし（非同期実行のため） |

### 出力先

- Storage: タスクステータスの更新（`tasks/{taskId}.json`）
- コールバック: 生成完了/エラー時のコールバック関数

## 処理フロー

### 処理シーケンス

```
1. タスク取得
   └─ getTask関数でストレージからタスクデータを取得

2. ステータス検証
   └─ タスクのstatusが"created"でない場合はエラーをスロー

3. ステータス更新
   └─ patchTask関数でstatusを"inProgress"に更新

4. 実行プロセス分岐
   ├─ type="self"の場合: waitUntilでrunTaskを非同期実行
   └─ type="external"の場合: 外部プロセスに処理を委譲
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[タスク取得]
    B --> C{status == created?}
    C -->|No| D[エラー: Task is not in created state]
    C -->|Yes| E[ステータスをinProgressに更新]
    E --> F{runTaskProcess.type}
    F -->|self| G[waitUntilでrunTask実行]
    F -->|external| H[外部プロセスに委譲]
    G --> I[終了]
    H --> I
    D --> J[例外スロー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | ステータス検証 | タスクは"created"状態からのみ開始可能 | タスク開始時 |
| BR-21-02 | ステータス遷移 | 開始時にステータスを"inProgress"に変更 | ステータス検証成功時 |
| BR-21-03 | 実行プロセス選択 | コンテキスト設定に基づき自己実行または外部委譲 | ステータス更新後 |

### 計算ロジック

特になし（状態遷移のみ）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| タスク取得 | Storage (tasks/{taskId}.json) | SELECT | タスクデータの読み取り |
| ステータス更新 | Storage (tasks/{taskId}.json) | UPDATE | statusフィールドの更新 |

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

#### Storage: tasks/{taskId}.json

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | status | "inProgress" | パッチ操作による更新 |
| UPDATE | updatedAt | 現在時刻（ミリ秒） | 暗黙的に更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TASK_NOT_FOUND | NotFoundError | 指定されたタスクIDが存在しない | 有効なタスクIDを指定する |
| INVALID_STATE | StateError | タスクのstatusが"created"でない | 新規作成されたタスクを指定する |
| STORAGE_ERROR | StorageError | ストレージアクセスに失敗 | システム管理者に連絡 |

### リトライ仕様

- ストレージエラーの場合: 自動リトライなし（呼び出し側で制御）
- 外部プロセスエラーの場合: 外部プロセス側でリトライを制御

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

- タスクステータス更新は単一のJSON書き込み操作
- 複数タスクの同時実行開始は、各タスクが独立してステータス管理される
- runTask内での生成処理はパッチキューによるバッチ更新で一貫性を保持

## パフォーマンス要件

- タスク開始処理: 100ms以内
- ステータス更新: 50ms以内
- タスク実行全体: ノード数とAIモデルのレスポンス時間に依存

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

- タスクIDは推測困難なランダムID（`tsk_`プレフィックス + ランダム文字列）
- ワークスペースへのアクセス権限チェックは呼び出し側で実施
- 外部プロセス委譲時は、認証情報を安全に受け渡し

## 備考

- `waitUntil`関数は、Vercel等のサーバーレス環境でレスポンス後も処理を継続するためのユーティリティ
- `runTaskProcess.type`が"external"の場合は、QStash等の外部キューサービスへの委譲を想定

---

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

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

### 推奨読解順序

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

タスクの状態遷移と入力パラメータの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | task.ts | `packages/protocol/src/task/task.ts` | Task型の定義、statusの取りうる値、Sequence/Step構造 |
| 1-2 | task-id.ts | `packages/protocol/src/task/task-id.ts` | TaskIdの生成規則と型定義 |

**読解のコツ**: Zodスキーマによる型定義パターンに慣れる。`z.object({...})`で定義され、`z.infer<typeof X>`で型が導出される。

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

タスク開始関数の全体構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | start-task.ts | `packages/giselle/src/tasks/start-task.ts` | startTask関数のシグネチャと処理フロー |

**主要処理フロー**:
1. **10-16行目**: StartTaskInputsスキーマ定義（taskId, generationOriginType）
2. **18-28行目**: startTask関数のシグネチャ（コンテキストとコールバックを含む）
3. **29行目**: getTaskでタスクデータ取得
4. **31-33行目**: ステータスが"created"でない場合のエラーハンドリング
5. **35-39行目**: patchTaskでステータスを"inProgress"に更新
6. **41-64行目**: runTaskProcess.typeに応じた実行プロセス分岐

#### Step 3: タスク取得処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | get-task.ts | `packages/giselle/src/tasks/get-task.ts` | ストレージからのタスク取得ロジック |
| 3-2 | path.ts | `packages/giselle/src/path.ts` | タスクのストレージパス生成規則 |

**主要処理フロー**:
- **6-14行目**: storage.getJsonでJSONファイルからタスクデータを取得

#### Step 4: パッチ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | patch-task.ts | `packages/giselle/src/tasks/patch-task.ts` | タスクのパッチ更新処理 |
| 4-2 | patch-creators.ts | `packages/giselle/src/tasks/object/patch-creators.ts` | パッチオブジェクトの生成ヘルパー |

#### Step 5: タスク実行処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | run-task.ts | `packages/giselle/src/tasks/run-task.ts` | タスクの実際の実行ロジック |
| 5-2 | task-execution-utils.ts | `packages/giselle/src/tasks/shared/task-execution-utils.ts` | シーケンス/ステップの実行ユーティリティ |

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

```
startTask (start-task.ts)
    │
    ├─ getTask (get-task.ts)
    │      └─ storage.getJson
    │
    ├─ patchTask (patch-task.ts)
    │      └─ storage.setJson
    │
    └─ runTask (run-task.ts) ※selfの場合
           │
           ├─ createPatchQueue
           │
           └─ executeTask (task-execution-utils.ts)
                  │
                  ├─ executeSequence
                  │      └─ startGeneration
                  │             └─ executeStep
                  │
                  └─ applyPatches
```

### データフロー図

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

taskId ─────────────▶ getTask ─────────────────────────▶ Task (status: created)
                           │
                           ▼
generationOriginType ──▶ startTask
                           │
                           ├─▶ patchTask ─────────────▶ Task (status: inProgress)
                           │
                           └─▶ runTask (async)
                                   │
                                   └─▶ executeStep ──▶ Generation結果
                                           │
                                           └─▶ onGenerationComplete callback
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| start-task.ts | `packages/giselle/src/tasks/start-task.ts` | ソース | タスク開始のエントリーポイント |
| get-task.ts | `packages/giselle/src/tasks/get-task.ts` | ソース | タスク取得処理 |
| run-task.ts | `packages/giselle/src/tasks/run-task.ts` | ソース | タスク実行処理 |
| patch-task.ts | `packages/giselle/src/tasks/patch-task.ts` | ソース | タスクパッチ更新 |
| task-execution-utils.ts | `packages/giselle/src/tasks/shared/task-execution-utils.ts` | ソース | 実行ユーティリティ |
| task.ts | `packages/protocol/src/task/task.ts` | ソース | Task型定義 |
| path.ts | `packages/giselle/src/path.ts` | ソース | ストレージパス生成 |
| index.ts | `packages/giselle/src/tasks/index.ts` | ソース | モジュールエクスポート |
