
# ワークフローのフォーク

Queuetyを使うと、実行中のワークフローを完全に独立したコピーにフォークできます。フォークされたワークフローは、元のワークフローと同じステップ、同じ状態で開始しますが、その後は互いに独立して進行します。一方への変更は、もう一方に影響しません。

## ワークフローのフォーク

### PHP API

ワークフローIDを指定して`Queuety::fork_workflow()`を呼び出します。新しいワークフローIDが返されます。

```php
use Queuety\Queuety;

$forked_id = Queuety::fork_workflow( $workflow_id );
```

### CLI

```bash
wp queuety workflow fork <id>
```

| オプション | 説明 |
|---|---|
| `<id>` | 分岐元のワークフローID（必須） |

```bash
wp queuety workflow fork 42
# Success: Workflow #42 forked. New workflow ID: 43.
```

## 仕組み

ワークフローをフォークすると、次の処理が行われます。

1. 元のワークフローの行がロックされ、読み取られる
2. 同じ状態、ステップ定義、現在のステップを持つ新しいワークフロー行が挿入される
3. 新しいワークフローの名前は`{original_name}_fork_{timestamp}`になる
4. フォークしたワークフローの現在のステップがキューに追加される
5. 元のワークフローとフォークしたワークフローの両方に`workflow_forked`ログイベントが記録される
6. 元のワークフローは通常どおり処理を続ける

フォークしたワークフローは完全に独立しています。独自のワークフローID、状態のコピー、ジョブキュー項目を持ちます。フォークした時点以降は、各ワークフローは自由に異なる経路を進めます。

## 活用例

### ステップハンドラーのA/Bテスト

今後のステップに対する2つの異なる実装をテストするには、ワークフローをフォークします。

```php
// Original workflow will use the existing CallLLMHandler (GPT-4).
// Fork it to test with a different handler.
$forked_id = Queuety::fork_workflow( $workflow_id );

// Modify the forked workflow's state to use a different model.
// (Update the state via a custom step or direct DB update.)
```

### 仮説分析

判断点でワークフローをフォークし、異なるブランチを試します。

```php
// Workflow is at step 3, about to process data.
// Fork it so we can try two different processing strategies.
$fork_a = Queuety::fork_workflow( $workflow_id );
$fork_b = Queuety::fork_workflow( $workflow_id );
```

各フォークは同じ入力状態から進みますが、異なる経路をたどるように変更できます。

### 並行実験

ワークフローで複数の方法を並行して試したい場合は、それぞれの方法ごとにフォークし、すべてのフォークが完了した後で結果を比較します。

## フォークの追跡

各ワークフローのログイベントには、もう一方への参照が含まれます。

- 元のワークフローでは、`context.forked_workflow_id`が新しいワークフローを指します
- フォークでは、`context.forked_from_workflow_id`が元のワークフローを指します

ログを検索して、あるワークフローから作成されたすべてのフォークを見つけます。

```php
$logs = Queuety::logger()->for_workflow( $workflow_id );

foreach ( $logs as $entry ) {
    if ( 'workflow_forked' === $entry['event'] ) {
        $context = json_decode( $entry['context'] ?? '{}', true );
        // $context['forked_workflow_id'] is the new workflow
    }
}
```

## 制限事項

- フォークしたワークフローは、元のワークフローのイベントログ履歴を引き継ぎません。空のイベントログで開始します。
- ワークフロー実行の関連付けは複製されません。元のワークフローで実行中のワークフロー実行があっても、フォークにはコピーされません。
- フォークは現在の状態のスナップショットです。元のワークフローで進行中のジョブは複製されません。
