コンテンツにスキップ

パイプラインステップ

パイプラインのステップには、互いに独立した 2 つの軸があります:

  • 種別(StepKind)— エンジンがトリガーに対してそのステップをどのようにスケジュールするか。
  • ボディキー(BuiltInBodyKeys)— 登録されたどのボディクロージャがステップの作業を実行するか。

packages/cc_domain/lib/features/pipelines/domain/entities/step_kind.dart で定義されています。

種別 スケジューリングのセマンティクス
trigger 必須のエントリーポイント — テンプレートごとにちょうど 1 つで、常に最初のノードです。それ自体は何の作業も行いません。実行を開始するもの(手動/イベント/スケジュール)は PipelineTrigger の行として別途追跡されます。そのボディは何もしない pipeline.trigger です。
listen すべてのソースステップ(StepTrigger.sourceStepIds 内)が完了したときに発火します。
join waitForStepIds 内のすべてのステップが終端状態に達したときに発火します。
router 条件分岐 — ボディは StepResult.route(key) を返し、routeKey が一致する下流のエッジだけを発火させます。選択されなかったブランチはスキップ済みとしてマークされます。
forEach listen と同じようにスケジュールされます(すべての sourceStepIds が完了したときに発火)。反復するのは登録された flow.forEach ボディであり、エンジンが項目ごとに子ステップを生成するわけではありません。
terminal ボディを持たないスケジューラーのセンチネルです。終端ステップが完了するとパイプライン実行が完了します。

BuiltInBodyKeys(packages/cc_domain/lib/features/pipelines/domain/templates/builtin_template_seeds.dart)の定数をキーとして登録されたボディクロージャです。25 個あり、すべて下記に挙げます。特に断りのない限り、設定はステップの PipelineNodeConfig(下記参照)から読み取られます。「ステートキー」は実行時にパイプラインステート/トリガーペイロードから読み取られます。

bodyKey が登録されていないステップは、テンプレートの読み込み時に警告を出し、その後は決して実行されません — 実行を失敗させることはありません。trigger と terminal のステップはこの警告の対象外です。trigger は何もしない pipeline.trigger ボディを実行し、terminal ステップはボディを持ちません。

必須の trigger ノードの何もしないボディです — 即座に完了し、エンジンが下流のリスナーへファンアウトできるようにします。設定はありません。

エージェントを使わないシェルステップ(bash -c)です。スクリプト内の {{key}} プレースホルダーは、ステート + トリガーペイロードからシェルエスケープ済みの値で置換されます。

設定フィールド 説明
script 実行するシェルコマンド(必須)
outputKey 終了コード 0 のときにトリム済みの stdout を受け取るステートキー

cwd を <cc_root>/pipelines/<pipelineRunId>/(実行内のすべての bash ステップで共有)とし、環境変数に GITHUB_TOKEN を設定して実行されます。また、<stepId>_runDir をステートに書き込みます。ゼロ以外の終了コードは、stderr の末尾とともにステップを失敗させます。

汎用のプロンプト&ディスパッチノードです。プロンプトをレンダリングし、エージェントを会話へディスパッチし、その実行が完了するまでサスペンドします。エージェントの submit_output ペイロードは outputKey の下でステートに回収されます。

設定フィールド 説明
agentId ディスパッチするワークスペーススコープのエージェント UUID(必須)
prompt 指示テキスト。{{key}} の置換に対応(必須)
outputKey 回収された出力のステートキー
outputSchema 出力が満たす必要のある JSON Schema
label キャンバスに表示される人間向けラベル
extras.spaceId 作業対象とする既存の会話(デフォルト: 非表示の会話)
extras.conversationTitle そのスペース内の名前付きストリーム(任意)
extras.mode ここではなく、ルームを開くノード(messaging.createSpace)で読み取られます。デフォルトは review。

ルーターボディです — config.extras を読み取り、条件を評価して StepResult.route(key) を返します。条件は JavaScript 式ではありません。3 つの記述形式を優先順にサポートしています:

  • 述語ツリー(extras.predicate)— "true" / "false" にルーティングするブールツリーです。各ノードは type を持つマップです:
    • {"type": "fileExists", "paths": [...], "baseKey": "repo_local_path", "negate": false, "recursive": false} — リストされたパスのいずれかがディスク上に存在するときに true になります。negate はそれを反転させます。recursive はサブディレクトリも検索します(.git、node_modules、build、.dart_tool をスキップ)。相対パスは state[baseKey](デフォルトは repo_local_path)を基準に解決され、そうでなければ実行ごとのワークスペースディレクトリを基準にします。
    • {"type": "comparison", "left": "{{score}}", "op": "gt", "right": 80} — 演算子は equals、notEquals、contains、exists、notExists、gt、lt です。ファイルシステムではなくパイプラインステートを読み取ります。
    • {"type": "and" | "or", "of": [<predicate>, ...]} — ブールグループです。
    • {"type": "not", "of": <predicate>} — 否定です。
  • スイッチ(extras.switchKey)— {"switchKey": "pr_class", "cases": [...], "default": "standard"}。ステートの値が大文字小文字を区別せずに含む最初の case へルーティングし、どれにも含まれなければ default へルーティングします。
  • 比較(レガシーのトップレベル extras.left / extras.op / extras.right)— comparison 述語と同等で、ツリー以前に作成されたテンプレートのために残されています。

ノードから出るエッジは、返されたキーと一致しなければならない routeKey を持ちます。

統合された指摘を、GitHub PR クライアントを介して PR レビューコメントとして投稿します。

ステートキー 説明
repo_full_name owner/repo(必須)
pr_number PR 番号 — int または数値文字列(必須)
consolidated_findings コメント本文(必須)

ステートに comment_review_id と commented_at を伴う StepResult.terminal を返します。

MessagingPort を介してメッセージングスペースにメッセージを投稿します。

ステートキー 説明
space_id 対象のスペース(必須)
content メッセージ本文。ステートからそのまま読み取られます(必須)

posted_space_id と posted_at をステートに書き込みます。

単一のエージェントではなくチーム全体をディスパッチし、メンバーの実行が完了するまでサスペンドします。

設定フィールド 説明
teamId ディスパッチするワークスペーススコープのチーム(必須。agentId とは排他的)
prompt ゴールのテキスト。{{key}} の置換に対応(必須)
dispatchMode allParallel(デフォルト — メンバーごとに 1 タスク)または manager(調整役のリーダーだけをディスパッチ)
outputKey 回収されたメンバー出力のステートキー
outputSchema, label, extras.spaceId conversation.promptAgent と同様

承認ゲートです。承認者エージェントを、ゲートプロンプトと {decision, reason} の出力契約を伴って会話(review モード)へディスパッチし、承認者が submit_output を介して送信するまでサスペンドします。

設定フィールド 説明
agentId 承認者エージェント(必須)
prompt ゲートプロンプト(任意。省略時はデフォルトが使われます)
outputKey 回収された {decision, reason} ペイロードのステートキー
outputSchema デフォルトは承認スキーマ(decision: approved / rejected、reason)
label, extras.spaceId conversation.promptAgent と同様

ゲートは submit_output を介してのみ解決されます。BuiltInBodyKeys.humanGate、ノードタイプライブラリ、およびある組み込みテンプレートのプロンプトテキストは、いずれも approve_step と reject_step という MCP ツールを指していますが、どちらのツールもどのパッケージやレジストリにも存在しません。

古くなった分離ワークツリーを削除します。モードはトリガーペイロードから選びます。実行の dryRun フラグを尊重します。

ステートキー 説明
ticket_id そのチケットのワークツリーを解放します
repo_full_name + pr_number 一時的な PR エディターのワークツリーを解放します
space_id その会話のワークツリーとフォルダを破棄します
(上記のいずれでもない) ワークスペースをスイープします: 消えたディレクトリ、死んだスペース、孤立した会話フォルダ

outputKey(任意)は要約文字列を受け取ります。

ステートのコレクションに対するマップ/ファンアウトです。項目ごとにプロンプトを 1 回レンダリングし、それらのプロンプトを連結した(--- 区切り)うえでエージェントを1 回ディスパッチし、その実行が完了するまでサスペンドします。空のコレクションは、空のリストとともに即座に完了します。項目ごとに 1 回ずつ並列ディスパッチするわけではありません。

設定フィールド 説明
agentId 項目ごとにディスパッチするエージェント(必須)
prompt 項目ごとのプロンプト。{{key}} の置換に対応(必須)
extras.iterableKey コレクションを保持するステートキー(必須)
extras.itemKey プロンプト内で現在の項目がバインドされるキー(デフォルトは item)
outputKey 回収された出力のステートキー(1 回のディスパッチで、リストではありません)

別のパイプラインテンプレートをネストされたサブステップとして実行します(サブパイプラインは parentPipelineRunId が設定された子実行として実行されます)。ステップは子が終端状態に達するまでサスペンドし、その後、子の最終ステートが outputKey の下にマージされます。

設定フィールド 説明
extras.templateId 実行する子テンプレート(必須。パイプラインは自身を呼び出せません)
inputKeys 子のトリガーペイロードへコピーされるステートキー
outputKey 子のマージされた最終ステートのステートキー

バックグラウンドの tree-sitter インデックス作成です。リポジトリを走査し、ワーカーアイソレートでシンボル/エッジを抽出して、ワークスペースのコードグラフに取り込みます。進捗はステップ実行の行へストリーミングされます。ドライランに対応します。tree-sitter とその文法は必須のネイティブであり、dylib が欠けていればサーバーは起動すらしていません。実行中に解決に失敗する文法は、スキップされるのではなくステップを失敗させます。

ステートキー 説明
repo_id インデックスを作成するリポジトリ(必須)
repo_local_path チェックアウトのローカルパス(必須)

オフラインの話者分離です。ミーティングで保持されている音声を読み込み、話者(Person 1、Person 2、…)へクラスタリングし、文字起こしのセグメントにラベルを付け直し、transcript ステートを書き換えます。並行する meeting.updateTranscript ステップ向けに diarization_spans も出力します。音声が保持されていない場合やモデルがインストールされていない場合は、文字起こしをそのまま通します。

ステートキー 説明
meeting_id 話者分離するミーティング(必須)

meeting.saveNotes, meeting.addActionItems, meeting.addDecisions

「meeting.saveNotes, meeting.addActionItems, meeting.addDecisions」というセクション

決定論的なミーティング要約の永続化ボディです。それぞれが、ステートから meeting_id とエージェントステップの構造化された meeting_outcome ペイロード({summary, enhancedNotes, actionItems[], decisions[]})を読み取り、自身の担当部分(ノート、アクションアイテム、または決定事項)を自身のテーブルに書き込みます。以前に保存された行が、劣化した実行で消去されることはありません。

ボディキー 説明
meeting.identifySpeakers ミーティングをまたぐ話者認識です。話者分離された話者を保存済みの音声プロファイルと照合し、確度の高い一致を自動適用します。プロファイル/埋め込みがない場合は何もしません。
meeting.updateTranscript diarization_spans から Person N ラベルを適用し、ウィンドウごとの断片を話者ごとの発話へマージして、クリーンアップされた文字起こしを永続化します。話者分離が何も生成しなかった場合は何もしません。
meeting.assemblePlayback 保持されているチャンネルごとの WAV から、ミーティングのミックス再生トラックを組み立てます。音声が保持されていない場合は何もしません。
orchestration.markPhase 作業 DAG の最後に、出力のないサブチケットの失敗センチネルを書き込み、オーケストレーションを synthesizing に切り替えます。
orchestration.persistDeliverable 統合の出力を親チケットに書き込み、それを完了させ、成果物を投稿して、オーケストレーションを completed としてマークします。
orchestration.awaitApproval 部分承認ゲートです。ステップのノードキーがオーケストレーションの承認済みセットに含まれていれば即座に完了し、そうでなければ後続の承認が再開するまでサスペンドします。extras.awaitApproval を設定する唯一のボディであり、これにより 24 時間のサスペンドステップタイムアウトから免除されます。
messaging.createSpace テンプレートの残りの部分が作業する会話を開き、ステップの outputKey の下に公開します(組み込みでは pipeline_space_id を使用)。repoIds リストが空であれば何もチェックアウトしません。extras['allRepos'] はワークスペースのすべてのリポジトリをチェックアウトします。extras['createConversation'](デフォルトではオフ)は名前付きストリームも開きます。エージェントステップはルームに参加するだけで、ルームを開くことはないため、このノードのないファンアウトはディスパッチ時に失敗します。そしてこれを一度配線しておけば、ファンアウト全体が 1 つのチェックアウトを共有し、それぞれに 1 つずつ用意する必要がなくなります。
prReview.finalize PR レビューテンプレートの最後のステップです。蓄積されたレビューノードをコンセンサスバケットに振り分け、PR ごとの判定を算出します。
skills.analyze ワークスペースにインストールされたスキルに対してスキルのサプライチェーンスキャンを行い、各判定を記録します。

ステップボディは StepResult(packages/cc_domain/lib/features/pipelines/domain/entities/step_result.dart)を返します。すべてのファクトリは、パイプラインステートにマージされる任意の mutatedState マップを受け取りますが、failed は例外です。

ファクトリ シグネチャ 説明
ok StepResult.ok({mutatedState}) 通常の完了。下流のリスナーが評価されます
route StepResult.route(nextRouterKey, {mutatedState}) ルーターの完了。routeKey が一致する下流のブランチを選択します
suspendUntilEvent StepResult.suspendUntilEvent(eventType, {mutatedState}) 特定のドメインイベント種別が発火するまで一時停止します
suspendUntilTasksComplete StepResult.suspendUntilTasksComplete(taskIds, {mutatedState}) リストされたすべてのタスクが終端状態に達するまで一時停止します
terminal StepResult.terminal({mutatedState}) パイプライン実行が終了しました — これ以上のステップはありません
failed StepResult.failed(errorMessage) ステップがエラーメッセージとともに失敗しました

失敗するノードボディの再試行動作です(PipelineNodeConfig.retryPolicy。null は再試行を無効にします)。

フィールド 型 説明
maxAttempts int 最初の試行を含む総試行回数(3 = 1 回の試行 + 2 回の再試行)。≥ 1 でなければなりません
backoff String linear または exponential(デフォルト)
initialDelayMs int 最初の再試行前の遅延(ミリ秒)。以降の遅延は backoff に従って増加します

ステップ定義の内部に保持されるノードごとの設定です(packages/cc_domain/lib/features/pipelines/domain/entities/pipeline_node_config.dart)。組み込みノードとカスタムノードはどちらもこの形を共有し、各ボディは自身が関心のあるフィールドだけを読み取ります。

フィールド 型 説明
prompt String? {{key}} 置換対応のプロンプトテンプレート
script String? {{key}} 置換対応の Bash スクリプトボディ
agentId String? ディスパッチするワークスペーススコープのエージェント UUID
inputKeys List<String> このノードが入力として消費するステートキー
repoIds List<String> messaging.createSpace ノードがチェックアウトするリポジトリ(<repoId> または <repoId>@<branch>)。空 = なし。extras['allRepos'] = ワークスペースのすべてのリポジトリ。エージェントステップでは無視されます。
outputKey String? このノードの出力が書き込まれるステートキー
label String? キャンバスに表示される人間向けラベル(デフォルトはステップ ID)
outputSchema Map<String, dynamic>? 出力値が満たす必要のある JSON Schema(サブセット)
reducer String? 並列ブランチが同じ outputKey に書き込むときのマージ戦略: append、mergeLists、mergeMaps、sum、または override(デフォルト)
retryPolicy StepRetryPolicy? ボディ失敗時の再試行ポリシー。null = 1 回だけ試行
continueOnFail bool true のとき、終端の失敗は実行を失敗させません。エラーは state['_stepErrors'][stepId] の下に退避されます
timeoutMs int? ノードボディの実時間タイムアウト(ミリ秒)。null = タイムアウトなし
teamId String? ディスパッチするチーム(team.dispatch ノード)。agentId とは排他的
dispatchMode String? チームの実行モード: allParallel または manager
extras Map<String, dynamic> 自由形式のボディ固有の設定(例: iterableKey、templateId、条件ツリー)

派生アクセサー: spaceId(extras['spaceId'] — 作業対象とする既存の会話)、createsConversation(extras['createConversation'])、conversationTitle(extras['conversationTitle'])、modeName(extras['mode'] — chat / review / plan。スペースを開くノードで読み取られます)、runWhen(extras['runWhen'] — 満たされない場合はノードをスキップします)。