コンテンツにスキップ

ドメインイベント

DomainEventBus はインプロセスのブロードキャスト型パブリッシュ/サブスクライブバスです。パブリッシャーは publish(event) を呼び出し、サブスクライバーは型付きの on<T>() ストリームを消費します。すべてのイベントは DomainEvent を実装し、occurredAt を保持します。

バスは cc_server の内部で動作します。 すべてのパブリッシャーと、稼働中のすべてのサブスクライバーはそこに存在します。このバスを目にするクライアントはありません。サーバーが厳選されたサブセットを notifications/* JSON-RPC フレームとして転送し、サブスクライバーごとにワークスペースのメンバーシップでフィルタリングします。

項目 数
具象イベントクラス 54
ソースファイル(packages/cc_domain/lib/core/domain/events/) 14(および domain_event_bus.dart)
直接発行されない抽象基底 1(TaskLifecycleEvent、sealed 階層)

以下のカタログにあるすべてのイベントは、この 1 つのディレクトリに存在します。ほかで宣言されているドメインイベントはありません。

ワークスペース、エージェント、リポジトリのイベント

「ワークスペース、エージェント、リポジトリのイベント」というセクション
イベント ペイロード 発行されるタイミング
WorkspaceCreated workspaceId ワークスペースが作成されたとき
AgentRunCompleted agentId, runId?, workspaceId?, conversationId? エージェントが実行を終了したとき(成功または失敗)
AgentAwaitingInput workspaceId, kind, summary, spaceId?, conversationId?, agentId?, agentName? エージェントが人間の対応待ちを開始したとき。承認、ask_user の質問、または認証情報で停止した実行(kind は approval、question、credential のいずれか)
RepoAdded repoId, path, workspaceId リポジトリが登録されたとき。バックグラウンドのコードインデックス作成をトリガーします
SkillUpdated workspaceId, slug, origin, computedHash, scanVerdict? スキルがインストールまたは更新されたとき。サプライチェーンスキャンの判定を伴います

最初のブロックは PR 自身のライフサイクルです。2 番目は 自作 PR のウォッチです。あなたが開いた PR に関するシグナルで、それぞれが forUserId を保持するため、ポーリングはブロードキャストするのではなく、関係する本人にそれらを届けることができます。

イベント ペイロード 発行されるタイミング
PullRequestPublished prId, workspaceId, repoOwner, repoName エージェントが PR を開いたとき
PullRequestStatusChanged status, workspaceId, prId?, repoFullName?, prNumber? PR がマージ/クローズ/オープン/再オープン/承認されたとき
PrMerged prId, workspaceId, agentId PR がマージされたとき。分析/通知のために保持されている、マージ専用の限定的なシグナルです
PrReviewRequested workspaceId, repoOwner, repoName, prNumber, prTitle GitHub がサーバーユーザーにレビューを依頼したとき(通知ポーリング、review_requested)
PrMentioned workspaceId, repoOwner, repoName, prNumber, prTitle サーバーユーザーが PR でメンションされたとき(通知ポーリング、mention)
ExternalPrMerged workspaceId, repoOwner, repoName, prNumber, prTitle, mergedByLogin? GitHub の通知ポーリングによって検出された、外部で追跡されている(エージェント以外の)PR がマージされたとき。prMerged 通知カテゴリにマッピングされます
ExternalPrDetected repoOwner, repoName, prNumber, prTitle, author, workspaceId? ポーリングで見つかったエージェント以外の PR。パイプライン専用で(external_pr_welcome を駆動します)、通知は発生させません
PrHeadChanged repoOwner, repoName, prNumber, prTitle, previousHeadSha, headSha, workspaceId PR の head SHA が移動したとき。作成者がプッシュしました
ReviewBecameStale workspaceId, spaceId, repoOwner, repoName, prNumber, prTitle, reviewedHeadSha, headSha 完了した AI レビューが、レビュー対象だった PR を説明しなくなったとき。置き換えられたコミットに対するレビューが存在する場合にのみ発行されるため、プッシュごとの ping ではなくシグナルであり続けます

6 つすべてが workspaceId、repoOwner、repoName、prNumber、prTitle と、省略可能な forUserId を保持します。

イベント 追加のペイロード 発行されるタイミング
PrMergeReadinessChanged ready, reason あなたが作成した PR がマージ可能になった、またはマージ可能でなくなったとき
PrReviewDecisionChanged decision, reviewersRemaining, approverLogin? レビュアーが承認した、変更を要求した、または承認が却下されたとき
PrChecksStatusChanged failing, failingCheckName?, failingCheckUrl? CI が失敗した、または復旧したとき
PrCommentMentioned commentId, authorLogin, bodyPreview, isReviewComment, threadId?, path?, line? PR のコメントまたはレビューコメントであなたがメンションされたとき
PrThreadReplied commentId, authorLogin, bodyPreview, threadId?, path?, line? あなたが参加しているレビュースレッドで誰かが返信したとき
PrThreadResolved threadId, commentId?, path?, line? あなたが参加しているレビュースレッドが解決されたとき
イベント ペイロード 発行されるタイミング
MessageReceived spaceId, messageId, senderName, contentPreview, isAgentMessage, workspaceId?, mentions, requestedByUserId?, senderUserId? 新しいメッセージが届いたとき
SpaceCreated spaceId, workspaceId スペースが作成されたとき
SpaceDeleted spaceId, workspaceId スペースが削除されたとき
SpaceProvisioningChanged workspaceId, spaceId, status, step? スペースのワークスペースがプロビジョニングに入り、ステップ(リポジトリのクローン、PR のチェックアウト、エージェントのセットアップ)に到達し、または ready/failed に切り替わったとき。チャットブリッジがタスクカードでそれをナレーションします
イベント ペイロード 発行されるタイミング
TicketCreated ticketId, workspaceId チケットが作成されたとき
TicketAssigned ticketId, ticketTitle, ticketBody?, ticketUrl?, assignedAgentId?, assigneeType, assignedTeamId?, workspaceId チケットがプリンシパルまたはチームに割り当てられたとき
TicketCompleted ticketId 作業が完了したとき(終端)
TicketFailed ticketId, errorMessage エージェントが失敗したとき(終端)
TicketCancelled ticketId チケットがキャンセルされたとき(終端)
TicketStatusChanged ticketId, workspaceId, from, to ステータスが変更されたとき
TicketReassigned ticketId, workspaceId, fromAgentId?, toAgentId? チケットが再割り当てされたとき
TicketDetailsUpdated ticketId, workspaceId タイトル、説明、または優先度が変更されたとき

統合されたタスクライフサイクルのストリームです。ディスパッチされた 1 回のエージェント実行を、実行ログの id でキー付けします。すべてのイベントが taskId、タスクごとに単調増加する seq、workspaceId?、agentId?、および phase を保持します。以下の行は追加フィールドのみを挙げています。

イベント ペイロード 発行されるタイミング
TaskDispatched — タスクが実行のためにバックエンドに渡されたとき
TaskRunning — タスクが出力を生成し始めたとき
TaskWaitingLocalDirectory lockedPath, holderTaskId? タスクが待機したとき。別のタスクが必要なオンディスクのパスロックを所有しています
TaskProgress note? 実行途中の進捗チェックポイント
TaskMessage messageType, content ストリーミングされたメッセージ(text/thinking/tool_use/tool_result/error)。progress フェーズで報告されます
TaskCompleted summary? タスクが正常に終了したとき
TaskFailed errorMessage タスクがエラーで終了したとき
TaskCancelled — タスクが完了前にキャンセルされたとき

TaskPhase enum には queued メンバーもありますが、queued イベントを発行するものはありません。TaskQueued クラスは存在しません。タスクで最初に観測できるフレームは TaskDispatched です。

イベント ペイロード 発行されるタイミング
PipelineRunCompleted workspaceId, pipelineRunId, templateId 実行が終了したとき
PipelineRunCancelled workspaceId, pipelineRunId, templateId 実行がキャンセルされたとき(ユーザーまたはシステムによる)。意図的な停止であり、エラーではありません
PipelineRunFailed workspaceId, pipelineRunId, templateId, errorMessage 実行が失敗したとき

発行されるのは終端の遷移だけです。PipelineRunStarted はなく、ステップ単位のイベントもありません。ステップの進捗は、バスを介してではなく、実行自身の行と、そのステップがディスパッチしたエージェントのタスクライフサイクルストリームを通じてクライアントに届きます。

イベント ペイロード 発行されるタイミング
ActivityLogged id, actorType, actorId?, action, entityType, entityId?, details?, workspaceId?, runId? 監査証跡のエントリが作成されたとき
BudgetThresholdCrossed scopeType, scopeId, spentCents, budgetCents, isHardStop 支出がしきい値を超えたとき

アイデンティティとメンバーシップのイベント

「アイデンティティとメンバーシップのイベント」というセクション
イベント ペイロード 発行されるタイミング
WorkspaceMemberAdded workspaceId, userId, role ユーザーがワークスペースに参加したとき(招待の引き換えまたは管理者による追加)
WorkspaceMemberRemoved workspaceId, userId メンバーが削除されたとき。そのワークスペースにスコープされたそのユーザーのライブセッションは、ただちにアクセスを再確認する必要があります
WorkspaceMemberRoleChanged workspaceId, userId, role メンバーのロールが変更されたとき

バス上にあるアイデンティティの表面はメンバーシップだけです。ユーザーの作成とデバイスの失効は発生しますが、ドメインイベントとしては発行されません。失効はバスを経由するのではなく、ライブセッションに対して直接適用されます。

イベント ペイロード 発行されるタイミング
CalendarAuthExpired workspaceId, accountEmail 接続済みアカウントの OAuth リフレッシュトークンが恒久的に無効になったとき(切断エピソードごとに 1 回発行されます)
MeetingStartingSoon workspaceId, eventId, title, startTime, meetingUrl? カレンダーの予定が、設定されたリードウィンドウ内で開始しようとしているとき
MeetingRecordingStopped workspaceId, meetingId, title, userNotes, transcript, summaryInstructions? ミーティングの録画が終了し、組み込みの meeting_summary パイプラインをトリガーしたとき
イベント ペイロード 発行されるタイミング
RigClosedEvent workspaceId, rigId, reason リグがクローズ理由とともに消滅したとき。コンシューマーが作用するのは backendFailure のみで、それ以外の理由は要求されたものか、RigReaped を伴うものです
RigControlChanged workspaceId, rigId, controller? 人間がリグの排他的な制御を取得した、または返却したとき(解放時は controller が null。イベントは誰が手放したかを記録しません)
RigReaped workspaceId, rigId, reason, agentId? システムがマシンを回収したとき。アイドル、TTL、またはメモリ圧迫による追い出し(idleTimeout として報告されます)で、駆動していたエージェントを伴います

リグのオープンはイベントではありません。ブートが完了してリグの行が ready に切り替わるだけで、何も発行されません。したがってサブスクライブできる RigOpened は存在しません。

外から見るとイベント駆動に見えるのに、そうではないサブシステムがいくつかあります。ここに挙げるのは、フックを探しに行く前に知っておく価値のある設計判断として、それらが存在しないからです。

サブドメイン 代わりに状態がどう動くか
メモリ record_memory_fact などが書き込んで返し、recall が読み取ります。ファクトや競合で発行されるものはありません
オーケストレーション 提案、その承認、生成されたパイプライン実行は、行と RPC 呼び出しです
プランドキュメント submit_plan がリビジョンを書き込み、承認がオーケストレーションを実体化します。どちらもアナウンスされません
アーティファクト publish_artifact / revise_artifact がリビジョンを直接書き込みます
承認 エスカレーションは承認ワークフローサービスの内部で処理されます
チケット同期 ベンダーコーディネーターが上記のチケットイベントをサブスクライブします。受信 Webhook は直接適用されます
カレンダー更新 同期が予定を upsert し、クライアントが再読み取りします。更新のブロードキャストはありません
ワークツリーのマージ worktree_merge_log に記録され、そこから読み取られます

以下のサブスクライバーはすべて runCcServer の内部(またはそれが構築するサービス)で構築されます。クライアント側のサブスクライバーはありません。

サブスクライバー 消費するイベント
WorkspaceSeeder WorkspaceCreated
スターター評価スイートのシード(インライン) WorkspaceCreated
チャットスペースのプロビジョニング(インライン) SpaceCreated
PipelineTriggerDispatcher すべての DomainEvent。有効な各トリガーが自身のタイプでフィルタリングします
SubPipelineResumeListener PipelineRunCompleted, PipelineRunFailed
PipelineCostRollupListener AgentRunCompleted
BudgetEvaluationListener AgentRunCompleted
MeetingSummaryReconciler PipelineRunCompleted, PipelineRunFailed, PipelineRunCancelled(meeting_summary の実行のみ)
PipelineStepResumeListener AgentRunCompleted
AgentRunTaskCompleter AgentRunCompleted
GoalSupervisor AgentRunCompleted
CheckerDispatchListener AgentRunCompleted
TeamRoutingService AgentRunCompleted, TicketAssigned
OrchestrationRunListener PipelineRunCancelled, PipelineRunFailed
MultiVendorTicketSyncCoordinator TicketCreated, TicketAssigned, TicketReassigned, TicketStatusChanged, TicketDetailsUpdated
WorktreeGcListener TicketCompleted, TicketCancelled, SpaceDeleted, PrMerged, PullRequestStatusChanged
ChatBridgeService MessageReceived, SpaceProvisioningChanged
ActivityLogPersister ActivityLogged
RigEventListener RigControlChanged, RigReaped, RigClosedEvent。駆動しているエージェントのステアリングレーンに平易な言葉の通知を注入します
StaleReviewWatcher PrHeadChanged。置き換えられたコミットに対する完了済みレビューが存在する場合にのみ ReviewBecameStale を発行します
GitHubPrConversationBridge AgentRunCompleted。外向きの PR 会話の返信
NotificationFeedRecorder 以下の 22 個の通知クラスのイベント
RemoteEventForwarder その 22 個に加えて TicketReassigned とすべての TaskLifecycleEvent。3 つのメンバーシップイベントは、ワークスペースごとのメンバーシップキャッシュを無効化するだけで、フレームとして転送されません
LocalRpcServer / RemoteRelayHost WorkspaceMemberRemoved。そのユーザーがアタッチしたワークスペース購読を削除します。ソケットは開いたままです

TicketAssigned は監査と通知のシグナルであり、パイプライントリガーでもあります。エージェントへの割り当ては所有権を記録するだけで、実行は開始しません。チケットディスパッチャーは存在しません。チームへの割り当て(assignedTeamId が設定されている場合)は例外で、TeamRoutingService がチームリーダーをディスパッチします。

TicketRemoteSyncHandler は宣言されていますが、本番コードでは決して構築されないため、今日は何もサブスクライブしていません。クライアント側の NotificationEventMapper は自身のテスト内でのみ構築されます。これはクライアント/サーバー分割以前のインプロセス経路の名残です。ライブのトーストは以下のワイヤフレームから届きます。

サーバーでは、NotificationFeedRecorder と RemoteEventForwarder がこれらのイベントを notifications/* ワイヤフレーム(notification_wire.dart)に変換します。クライアントでは、RpcNotificationMapper → mapNotificationFrame がフレームを AppNotification に変換します。

通知カテゴリはちょうど 17 個あります。いくつかのイベントは複数のワイヤメソッドにマッピングされます。フレームがエッジ(失敗か復旧か)を運び、カテゴリが問い(「CI は何をしているか」)を運ぶからです。

カテゴリ ソースイベント ワイヤメソッド
newMessage MessageReceived notifications/message_received(あなたへのメンション)
agentRunCompleted MessageReceived notifications/message_received(is_agent_message、あなたへのメンションなし)
agentAwaitingInput AgentAwaitingInput notifications/agent_awaiting_input
ticketAssigned TicketAssigned notifications/ticket_assigned
ticketStatusChanged TicketStatusChanged notifications/ticket_status_changed
pullRequestPublished PullRequestPublished notifications/pr_published
prMerged PrMerged notifications/pr_merged
prMerged ExternalPrMerged notifications/external_pr_merged
prMentioned PrMentioned notifications/pr_mentioned
prMentioned PrCommentMentioned notifications/pr_comment_mentioned
reviewRequested PrReviewRequested notifications/pr_review_requested
reviewStale ReviewBecameStale notifications/review_stale
prMergeReadiness PrMergeReadinessChanged notifications/pr_ready_to_merge / pr_merge_blocked
prReviewDecision PrReviewDecisionChanged notifications/pr_approved / pr_changes_requested / pr_review_dismissed
prChecksStatus PrChecksStatusChanged notifications/pr_checks_failed / pr_checks_recovered
prThreadActivity PrThreadReplied notifications/pr_thread_replied
prThreadActivity PrThreadResolved notifications/pr_thread_resolved
meetingStartsSoon MeetingStartingSoon notifications/meeting_starting_soon
calendarAuthExpired CalendarAuthExpired notifications/calendar_auth_expired
rigStatusChanged RigControlChanged notifications/rig_control_changed
rigStatusChanged RigReaped notifications/rig_reaped
rigStatusChanged RigClosedEvent notifications/rig_closed

リグのテイクオーバーのフレームは、ハンドルを握った本人には返送されません。解放はフィルタリングされず(イベントは誰が手放したかを記録しません)、backendFailure によるクローズだけが rig_closed フレームを生成します。それ以外の理由は、要求されたものであるか、回収のフレームですでにカバーされています。

AgentAwaitingInput は AgentAwaitingInputPublisher が発行します。このパブリッシャーは承認と認証情報ブロックのレジストリを監視して新しいエントリを検出し、ask_user の各質問については AgentQuestionService から通知を受けます。1 回の待機が 1 つのイベントです。待機が終わったときには何も発行されません。

5 つの自作 PR カテゴリは forUserId を保持するため、ワークスペースの全員ではなく作成者に届きます。

RemoteEventForwarder はさらに、TicketReassigned を notifications/ticket_reassigned として、すべての TaskLifecycleEvent を notifications/task_<phase> として転送します。どちらも通知カテゴリにはマッピングされません。これらは通知センターではなく、ライブ UI を駆動します。メンバーシップイベントはフレームとして転送されません。それらはフォワーダーのキャッシュを無効化し、セッションホストは削除されたメンバーのワークスペース購読を破棄します。