ドメインイベント
イベントバス
「イベントバス」というセクション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 とレビューのイベント
「PR とレビューのイベント」というセクション最初のブロックは 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 ではなくシグナルであり続けます |
自作 PR のウォッチ
「自作 PR のウォッチ」というセクション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 を駆動します。メンバーシップイベントはフレームとして転送されません。それらはフォワーダーのキャッシュを無効化し、セッションホストは削除されたメンバーのワークスペース購読を破棄します。