コンテンツにスキップ

チケットと委任

チケットは、Control Center が追跡する作業の単位です。意図的に_単純な_成果物であり、タイトル、本文、ステータス、担当者、そしてツリー内の位置を持ちます。エージェントが実際に処理する対象ではありません — エージェントの作業は会話の中にあり、実行の構造化出力は実行ログに残ります。

割り当ては所有権を記録するだけで、何もディスパッチしません

「割り当ては所有権を記録するだけで、何もディスパッチしません」というセクション

これは、チケットについて何よりも正しく理解しておくべき点です。

assignedAgentId を設定すると、1 つのフィールドが書き込まれ、TicketAssigned ドメインイベントが発行されます。このイベントは監査と 通知のシグナルであり、パイプラインのトリガーでもあります。エージェントへの 割り当ては実行を開始しません。 assignedAgentId を監視してそのエージェントを 起こすチケットディスパッチャーは存在しません。

例外はチームです。assignedTeamId が設定されている場合、TeamRoutingService がオペレーティングプロトコルと名簿を渡してチームリーダーをディスパッチします。

特定のエージェントにチケットへ取り組んでほしい場合は、会話の中で依頼するか、 パイプラインのステップでディスパッチするか、別のエージェントがそのエージェントに 委任します。チケットをエージェントに割り当てて待つことだけは、決して作業を 生み出しません。

チケットは完全にローカルなものでも、外部トラッカーに裏付けられたものでもよく、 どちらも 1 つの行にまとめて持ちます。

ミラー — プロバイダー、外部キー、URL、タイトル、説明、優先度、ラベル、生の ステータスと正規化されたステータス、タイムスタンプ — は、チケットがリモートの 場合のキャッシュです。そこではリモートが正であり、リフレッシュはミラーを丸ごと 書き換えます。

オーバーレイ — 割り当て、委任、スペースのリンク、親、プロジェクト、リンク された PR — は Control Center だけのものです。トラッカーはそれを一切知らず、 リフレッシュがそれに触れることもありません。

この分離があるからこそ、そもそも同期が安全になります。ベンダーからのプルは ミラーを破壊し得ますが、その上に重ねられたオーケストレーションのメタデータが 失われることは決してありません。

ライフサイクルグラフが縛るのはエージェントであり、あなたではありません

「ライフサイクルグラフが縛るのはエージェントであり、あなたではありません」というセクション

ステータスは backlog → open → inProgress → inReview → done と進み、blocked は横にそれるループ、failed と cancelled はもう一方の終端状態です。

遷移グラフが強制されるのはエージェントと自動化の経路だけです — MCP ツール とリコンサイラーです。そこでの不正な遷移はログに記録されて無視されるため、 混乱したエージェントがチケットを終端状態から逆走させることはできません。

UI でのユーザー操作による変更は、すべて force: true を渡してグラフを完全に 迂回します。人間は、ピッカーに並ぶ任意のステータスへチケットを移動できます — 終端状態を再び開くことも含みます。ピッカーが failed を提示することはなく、 エージェントは fail_ticket を通じて設定します。グラフは自動化のための ガードレールであり、作業の進め方に関するルールではありません。

TicketWorkflowService は、すべての変更を単一のチョークポイント経由で所有 します。このチョークポイントは行を読み込み、呼び出し元のワークスペースに 属することを検証し、期待する version を付けて書き込むため、2 つの並行編集が 互いを黙って上書きすることはありません。

ステータスの一覧、遷移、フィールド、リレーションの種類については、 チケットのライフサイクルを参照してください。

すべてのチケットは originKind を持ちます。この列挙型には 5 つの値 — manual、 pipelineStep、agentDelegation、externalSync、recovery — がありますが、 現在書き込まれるのは 2 つだけです。manual(createTicket の既定値で、委任 された子チケットも含みます)と externalSync(ベンダーからのプル時に同期 エンジンが設定します)です。TicketWorkflowService.createTicket は origin 引数を 取らないため、pipelineStep、agentDelegation、recovery が行に書き込まれる ことはありません。

委任は、あるエージェントが別のエージェントのために作業を作る場面であり、権限が 漏れうる場所でもあるため、ガードはプロンプトの指示ではなく、サーバー側の チョークポイントに置かれています。

delegate_task は TicketWorkflowService.delegateGuarded を通ります。これは親の 連鎖から子の深さとルートを計算し、続いて 4 つの DelegationGuards チェックを すべて実行します。深さの上限 3 を超えるホップ、すでに連鎖にいるエージェント へ戻るホップ(循環検出)、自律性の上限(スペース内での委任先の実効 レベルが委任元を超えてはなりません)、そして予算のエンベロープ(委任は 委任元の残りのハードストップ予算から引かれ、新たに生み出すことはできません) です。プロダクションの配線は両方のリゾルバーポートを供給します。from_agent_id を省略した場合、自律性と予算はスキップされます(無制限の予算、またはポリシー なしの予算も通過します)。拒否は DelegationRefusedException としてスローされ、 そのメッセージは委任元のエージェントにそのまま届きます — 声高な拒否であり、 決して無言の no-op ではありません。

delegate_ticket は古いほうのガードなしの兄弟です。createTicket を直接 呼び出し、すべてのガードをスキップします。delegate_task を優先してください。

委任の深さの上限(delegate_task の連鎖で 3)と、内蔵ハーネスのサブエージェント のネスト上限(2)を混同しないでください。これらは異なるメカニズムに対する、 異なる制限です。

親子とサブイシューの関係は tickets.parent_ticket_id にあり、setParent / clearParent が所有します。これらは ticket_links の行ではありません。 そのため、チケットのリレーションを読むものはどちらも両方のソースをマージする 必要があります。

ticket_links は、それ以外に関係のないチケット同士の方向性のあるエッジを 保持します。

リンク種別 意味
blocks ソースがターゲットをブロックする
relatesTo 2 つのチケットは関連している(対称)
duplicateOf ソースはターゲットの重複である

プロジェクトは、共通の目標に向けたチケットのワークスペース単位のまとまり です。プロジェクトは Control Center だけのものであり、外部プロバイダーに 同期されることはありません。

TicketCollaborator の行は、複数のプリンシパルを 1 つのチケットに紐づける仕組み であり、ロールは assignee、collaborator、reviewer のいずれかです。人間と エージェントは対等な行です — principalId と collaboratorType を持ち、 「ユーザー」を表すセンチネル値も、どちらのテーブルへの外部キーもありません。

Control Center のチケットが主体です。チケットの削除はローカルのみなので、 削除したベンダー連携のチケットはトラッカー上では削除されず、次の同期で再び 現れることがあります。コラボレーターと子チケットはカスケードします。

アダプターの資格情報は、サーバーの資格情報ストアから解決されます(設定で 貼り付けた Linear キーや GitHub トークンは次のリクエストで拾われます。環境は それらのストアをシードするだけです)。

チケットを作成、完了、キャンセルするパイプラインのノードはありません — パレットにそのようなステップはなく、エンジンが TicketWorkflowService を 呼び出すこともありません。それでもパイプラインのトリガーは TicketAssigned、 TicketCompleted、TicketFailed、TicketCancelled で発火できます (EventPayloadMapper が実際にマップするチケットイベントはこの 4 つです)。 チケットに pipelineRunId 列はなく、パイプラインとの結合はエージェントの 実行ログにあります。