Peristiwa domain
Bus peristiwa
Bagian berjudul “Bus peristiwa”DomainEventBus adalah bus publish/subscribe siaran dalam proses. Penerbit memanggil publish(event); pelanggan mengonsumsi aliran on<T>() yang bertipe. Setiap peristiwa mengimplementasikan DomainEvent dan membawa occurredAt.
Bus ini berjalan di dalam cc_server. Setiap penerbit dan setiap pelanggan yang aktif berada di sana. Tidak ada klien yang melihat bus ini — server meneruskan subset terkurasi sebagai frame JSON-RPC notifications/*, yang difilter per pelanggan berdasarkan keanggotaan ruang kerja.
| Ukuran | Jumlah |
|---|---|
| Kelas peristiwa konkret | 54 |
Berkas sumber (packages/cc_domain/lib/core/domain/events/) |
14 (ditambah domain_event_bus.dart) |
| Basis abstrak yang tidak pernah diterbitkan secara langsung | 1 (TaskLifecycleEvent, hierarki sealed) |
Setiap peristiwa dalam katalog di bawah ini berada di satu direktori tersebut; tidak ada peristiwa domain yang dideklarasikan di tempat lain.
Peristiwa ruang kerja, agen, dan repo
Bagian berjudul “Peristiwa ruang kerja, agen, dan repo”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
WorkspaceCreated |
workspaceId |
Ruang kerja dibuat |
AgentRunCompleted |
agentId, runId?, workspaceId?, conversationId? |
Agen menyelesaikan sebuah run (berhasil atau gagal) |
AgentAwaitingInput |
workspaceId, kind, summary, spaceId?, conversationId?, agentId?, agentName? |
Agen mulai menunggu manusia: persetujuan, pertanyaan ask_user, atau run yang tertahan oleh kredensial (kind bernilai approval, question, atau credential) |
RepoAdded |
repoId, path, workspaceId |
Repo didaftarkan; memicu pengindeksan kode di latar belakang |
SkillUpdated |
workspaceId, slug, origin, computedHash, scanVerdict? |
Sebuah skill dipasang atau diperbarui, membawa putusan pemindaian rantai pasoknya |
Peristiwa PR dan tinjauan
Bagian berjudul “Peristiwa PR dan tinjauan”Blok pertama adalah siklus hidup PR itu sendiri. Blok kedua adalah pemantauan PR yang Anda tulis: sinyal tentang PR yang Anda buka, masing-masing membawa forUserId sehingga polling dapat mengarahkannya kepada orang yang bersangkutan alih-alih menyiarkannya ke semua orang.
| Peristiwa | Payload | Dipicu saat |
|---|---|---|
PullRequestPublished |
prId, workspaceId, repoOwner, repoName |
Agen membuka PR |
PullRequestStatusChanged |
status, workspaceId, prId?, repoFullName?, prNumber? |
PR digabungkan/ditutup/dibuka/dibuka kembali/disetujui |
PrMerged |
prId, workspaceId, agentId |
PR digabungkan — sinyal khusus penggabungan yang sempit, disimpan untuk analitik/notifikasi |
PrReviewRequested |
workspaceId, repoOwner, repoName, prNumber, prTitle |
GitHub meminta tinjauan dari pengguna server (polling notifikasi, review_requested) |
PrMentioned |
workspaceId, repoOwner, repoName, prNumber, prTitle |
Pengguna server disebut di sebuah PR (polling notifikasi, mention) |
ExternalPrMerged |
workspaceId, repoOwner, repoName, prNumber, prTitle, mergedByLogin? |
PR yang dilacak secara eksternal (bukan agen) digabungkan, terdeteksi oleh polling notifikasi GitHub; dipetakan ke kategori notifikasi prMerged |
ExternalPrDetected |
repoOwner, repoName, prNumber, prTitle, author, workspaceId? |
PR non-agen ditemukan melalui polling — hanya untuk pipeline (menggerakkan external_pr_welcome), tidak memunculkan notifikasi |
PrHeadChanged |
repoOwner, repoName, prNumber, prTitle, previousHeadSha, headSha, workspaceId |
SHA head PR berpindah — penulisnya melakukan push |
ReviewBecameStale |
workspaceId, spaceId, repoOwner, repoName, prNumber, prTitle, reviewedHeadSha, headSha |
Tinjauan AI yang sudah selesai tidak lagi menggambarkan PR yang ditinjaunya. Hanya dipicu saat sudah ada tinjauan untuk commit yang digantikan, sehingga tetap menjadi sinyal, bukan ping untuk setiap push |
Pemantauan PR yang Anda tulis
Bagian berjudul “Pemantauan PR yang Anda tulis”Keenamnya membawa workspaceId, repoOwner, repoName, prNumber, prTitle dan forUserId opsional.
| Peristiwa | Payload tambahan | Dipicu saat |
|---|---|---|
PrMergeReadinessChanged |
ready, reason |
PR yang Anda tulis menjadi dapat digabungkan, atau tidak lagi |
PrReviewDecisionChanged |
decision, reviewersRemaining, approverLogin? |
Peninjau menyetujui, meminta perubahan, atau persetujuannya dibatalkan |
PrChecksStatusChanged |
failing, failingCheckName?, failingCheckUrl? |
CI menjadi merah, atau pulih |
PrCommentMentioned |
commentId, authorLogin, bodyPreview, isReviewComment, threadId?, path?, line? |
Seseorang menyebut Anda di komentar PR atau komentar tinjauan |
PrThreadReplied |
commentId, authorLogin, bodyPreview, threadId?, path?, line? |
Seseorang membalas di thread tinjauan tempat Anda berada |
PrThreadResolved |
threadId, commentId?, path?, line? |
Seseorang menyelesaikan thread tinjauan tempat Anda berada |
Peristiwa pesan
Bagian berjudul “Peristiwa pesan”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
MessageReceived |
spaceId, messageId, senderName, contentPreview, isAgentMessage, workspaceId?, mentions, requestedByUserId?, senderUserId? |
Pesan baru tiba |
SpaceCreated |
spaceId, workspaceId |
Space dibuat |
SpaceDeleted |
spaceId, workspaceId |
Space dihapus |
SpaceProvisioningChanged |
workspaceId, spaceId, status, step? |
Ruang kerja milik space memasuki penyediaan, mencapai sebuah langkah (mengkloning repo, melakukan checkout PR, menyiapkan agen), atau berubah menjadi siap/gagal — jembatan chat menceritakannya di kartu tugasnya |
Peristiwa tiket
Bagian berjudul “Peristiwa tiket”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
TicketCreated |
ticketId, workspaceId |
Tiket dibuat |
TicketAssigned |
ticketId, ticketTitle, ticketBody?, ticketUrl?, assignedAgentId?, assigneeType, assignedTeamId?, workspaceId |
Tiket ditugaskan ke principal atau tim |
TicketCompleted |
ticketId |
Pekerjaan selesai (terminal) |
TicketFailed |
ticketId, errorMessage |
Agen gagal (terminal) |
TicketCancelled |
ticketId |
Tiket dibatalkan (terminal) |
TicketStatusChanged |
ticketId, workspaceId, from, to |
Setiap perubahan status |
TicketReassigned |
ticketId, workspaceId, fromAgentId?, toAgentId? |
Tiket ditugaskan ulang |
TicketDetailsUpdated |
ticketId, workspaceId |
Judul, deskripsi, atau prioritas berubah |
Peristiwa siklus hidup tugas
Bagian berjudul “Peristiwa siklus hidup tugas”Aliran siklus hidup tugas yang terpadu — satu run agen yang dikirim, dikunci oleh id log run-nya. Setiap peristiwa membawa taskId, seq per tugas yang monoton, workspaceId?, agentId? dan sebuah phase; baris-baris di bawah ini hanya mencantumkan kolom tambahannya.
| Peristiwa | Payload | Dipicu saat |
|---|---|---|
TaskDispatched |
— | Tugas diserahkan ke backend untuk dieksekusi |
TaskRunning |
— | Tugas mulai menghasilkan output |
TaskWaitingLocalDirectory |
lockedPath, holderTaskId? |
Tugas diparkir — tugas lain memegang kunci jalur di disk yang dibutuhkannya |
TaskProgress |
note? |
Pos pemeriksaan kemajuan di tengah run |
TaskMessage |
messageType, content |
Pesan yang dialirkan (text/thinking/tool_use/tool_result/error); dilaporkan dalam fase progress |
TaskCompleted |
summary? |
Tugas selesai dengan sukses |
TaskFailed |
errorMessage |
Tugas selesai dengan kesalahan |
TaskCancelled |
— | Tugas dibatalkan sebelum selesai |
Enum TaskPhase juga memiliki anggota queued, tetapi tidak ada yang menerbitkan peristiwa queued — tidak ada kelas TaskQueued. Frame pertama yang dapat diamati dari sebuah tugas adalah TaskDispatched.
Peristiwa pipeline
Bagian berjudul “Peristiwa pipeline”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
PipelineRunCompleted |
workspaceId, pipelineRunId, templateId |
Run selesai |
PipelineRunCancelled |
workspaceId, pipelineRunId, templateId |
Run dibatalkan (oleh pengguna atau sistem) — penghentian yang disengaja, bukan kesalahan |
PipelineRunFailed |
workspaceId, pipelineRunId, templateId, errorMessage |
Run gagal |
Hanya transisi terminal yang diterbitkan. Tidak ada PipelineRunStarted dan tidak ada peristiwa per langkah: kemajuan sebuah langkah sampai ke klien melalui baris milik run itu sendiri dan aliran siklus hidup tugas dari agen apa pun yang dikirimnya, bukan melalui bus.
Peristiwa observabilitas
Bagian berjudul “Peristiwa observabilitas”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
ActivityLogged |
id, actorType, actorId?, action, entityType, entityId?, details?, workspaceId?, runId? |
Entri jejak audit dibuat |
BudgetThresholdCrossed |
scopeType, scopeId, spentCents, budgetCents, isHardStop |
Pengeluaran melampaui ambang batas |
Peristiwa identitas dan keanggotaan
Bagian berjudul “Peristiwa identitas dan keanggotaan”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
WorkspaceMemberAdded |
workspaceId, userId, role |
Seorang pengguna bergabung ke ruang kerja (penukaran undangan atau penambahan oleh admin) |
WorkspaceMemberRemoved |
workspaceId, userId |
Seorang anggota dihapus — sesi aktif pengguna tersebut yang tercakup ke ruang kerja harus segera memeriksa ulang aksesnya |
WorkspaceMemberRoleChanged |
workspaceId, userId, role |
Peran seorang anggota berubah |
Keanggotaan adalah seluruh permukaan identitas di bus ini. Pembuatan pengguna dan pencabutan perangkat memang terjadi, tetapi keduanya tidak diterbitkan sebagai peristiwa domain — pencabutan ditegakkan langsung terhadap sesi aktif alih-alih dialirkan melalui bus.
Peristiwa kalender dan rapat
Bagian berjudul “Peristiwa kalender dan rapat”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
CalendarAuthExpired |
workspaceId, accountEmail |
Token refresh OAuth akun yang terhubung menjadi tidak valid secara permanen (diterbitkan sekali per episode pemutusan) |
MeetingStartingSoon |
workspaceId, eventId, title, startTime, meetingUrl? |
Peristiwa kalender akan dimulai dalam jendela persiapan yang dikonfigurasi |
MeetingRecordingStopped |
workspaceId, meetingId, title, userNotes, transcript, summaryInstructions? |
Perekaman rapat selesai dan memicu pipeline bawaan meeting_summary |
Peristiwa rig
Bagian berjudul “Peristiwa rig”| Peristiwa | Payload | Dipicu saat |
|---|---|---|
RigClosedEvent |
workspaceId, rigId, reason |
Sebuah rig hilang, beserta alasan penutupannya; konsumen hanya bertindak atas backendFailure — semua alasan lainnya diminta atau disertai RigReaped |
RigControlChanged |
workspaceId, rigId, controller? |
Seorang manusia mengambil kendali eksklusif atas sebuah rig atau mengembalikannya (controller null saat dilepas — peristiwa ini tidak mencatat siapa yang melepasnya) |
RigReaped |
workspaceId, rigId, reason, agentId? |
Sistem mengambil kembali sebuah mesin: pengusiran karena idle, TTL, atau tekanan memori (dilaporkan sebagai idleTimeout), beserta agen yang menggerakkannya |
Sebuah rig yang dibuka bukanlah peristiwa. Proses boot selesai dan baris rig berubah menjadi siap; tidak ada yang diterbitkan, jadi tidak ada RigOpened untuk dilanggani.
Subdomain yang tidak memiliki peristiwa sama sekali
Bagian berjudul “Subdomain yang tidak memiliki peristiwa sama sekali”Beberapa subsistem yang dari luar tampak digerakkan oleh peristiwa ternyata bukan. Semuanya dicantumkan di sini karena ketiadaan peristiwanya adalah keputusan desain yang perlu diketahui sebelum Anda mencari-cari hook:
| Subdomain | Bagaimana status berpindah sebagai gantinya |
|---|---|
| Memori | record_memory_fact dan kawan-kawan menulis lalu kembali; recall membaca. Tidak ada yang menerbitkan apa pun saat ada fakta atau konflik |
| Orkestrasi | Proposal, persetujuannya, dan run pipeline yang dihasilkan adalah baris dan panggilan RPC |
| Dokumen rencana | submit_plan menulis revisi; persetujuan mewujudkan sebuah orkestrasi. Keduanya tidak diumumkan |
| Artefak | publish_artifact / revise_artifact menulis revisi secara langsung |
| Persetujuan | Eskalasi ditangani di dalam layanan alur kerja persetujuan |
| Sinkronisasi tiket | Koordinator vendor berlangganan peristiwa tiket di atas; webhook masuk diterapkan secara langsung |
| Penyegaran kalender | Sinkronisasi melakukan upsert peristiwa dan klien membacanya ulang; tidak ada siaran penyegaran |
| Penggabungan worktree | Dicatat di worktree_merge_log dan dibaca dari sana |
Pelanggan
Bagian berjudul “Pelanggan”Setiap pelanggan di bawah ini dikonstruksi di dalam runCcServer (atau layanan yang dibangunnya). Tidak ada pelanggan di sisi klien.
| Pelanggan | Peristiwa yang dikonsumsinya |
|---|---|
WorkspaceSeeder |
WorkspaceCreated |
| Penyemaian suite eval pemula (inline) | WorkspaceCreated |
| Penyediaan space chat (inline) | SpaceCreated |
PipelineTriggerDispatcher |
Setiap DomainEvent; setiap pemicu yang aktif memfilter untuk tipenya sendiri |
SubPipelineResumeListener |
PipelineRunCompleted, PipelineRunFailed |
PipelineCostRollupListener |
AgentRunCompleted |
BudgetEvaluationListener |
AgentRunCompleted |
MeetingSummaryReconciler |
PipelineRunCompleted, PipelineRunFailed, PipelineRunCancelled (hanya run 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 — menyuntikkan pemberitahuan berbahasa sederhana ke jalur pengarahan agen yang menggerakkannya |
StaleReviewWatcher |
PrHeadChanged — menerbitkan ReviewBecameStale hanya saat sudah ada tinjauan selesai untuk commit yang digantikan |
GitHubPrConversationBridge |
AgentRunCompleted — balasan percakapan PR ke luar |
NotificationFeedRecorder |
Dua puluh dua peristiwa kelas notifikasi di bawah ini |
RemoteEventForwarder |
Kedua puluh dua peristiwa itu ditambah TicketReassigned dan setiap TaskLifecycleEvent. Ketiga peristiwa keanggotaan hanya membatalkan cache keanggotaan per ruang kerjanya; ketiganya tidak diteruskan sebagai frame |
LocalRpcServer / RemoteRelayHost |
WorkspaceMemberRemoved — menjatuhkan langganan ruang kerja pengguna tersebut yang terpasang; soketnya tetap terbuka |
TicketAssigned adalah sinyal audit dan notifikasi sekaligus pemicu pipeline. Penugasan kepada agen mencatat kepemilikan dan tidak memulai run apa pun — tidak ada dispatcher tiket. Penugasan kepada tim (assignedTeamId diisi) adalah pengecualiannya: TeamRoutingService mengirim pemimpin tim.
TicketRemoteSyncHandler dideklarasikan tetapi tidak pernah dikonstruksi di kode produksi, jadi saat ini ia tidak berlangganan apa pun. NotificationEventMapper di sisi klien hanya dikonstruksi di pengujiannya sendiri — ia adalah sisa dari jalur dalam proses sebelum pemisahan klien/server. Toast langsung berasal dari frame yang dijelaskan di bawah ini.
Pemetaan notifikasi
Bagian berjudul “Pemetaan notifikasi”Di server, NotificationFeedRecorder dan RemoteEventForwarder mengubah peristiwa-peristiwa ini menjadi frame wire notifications/* (notification_wire.dart). Di klien, RpcNotificationMapper → mapNotificationFrame mengubah sebuah frame menjadi AppNotification.
Tepat ada tujuh belas kategori notifikasi. Beberapa peristiwa dipetakan ke lebih dari satu metode wire, karena frame membawa transisinya (gagal versus pulih) sementara kategori membawa pertanyaannya (“apa yang sedang dilakukan CI?”).
| Kategori | Peristiwa sumber | Metode wire |
|---|---|---|
newMessage |
MessageReceived |
notifications/message_received (menyebut Anda) |
agentRunCompleted |
MessageReceived |
notifications/message_received (is_agent_message, tidak menyebut Anda) |
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 |
Frame pengambilalihan rig tidak dikirim kembali kepada siapa pun yang mengambil alih, pelepasan tidak difilter (peristiwa ini tidak mencatat siapa yang melepasnya), dan hanya penutupan backendFailure yang menghasilkan frame rig_closed — alasan lainnya diminta atau sudah tercakup oleh frame reap.
AgentAwaitingInput diterbitkan oleh AgentAwaitingInputPublisher, yang memantau registri persetujuan dan registri blokir kredensial untuk entri baru, serta diberi tahu tentang setiap pertanyaan ask_user oleh AgentQuestionService. Satu penantian adalah satu peristiwa; tidak ada yang diterbitkan saat penantian berakhir.
Kelima kategori PR yang Anda tulis membawa forUserId, sehingga sampai ke penulisnya alih-alih ke semua orang di ruang kerja.
RemoteEventForwarder juga meneruskan TicketReassigned sebagai notifications/ticket_reassigned dan setiap TaskLifecycleEvent sebagai notifications/task_<phase>. Keduanya tidak dipetakan ke kategori notifikasi — keduanya menggerakkan UI langsung, bukan pusat notifikasi. Peristiwa keanggotaan tidak diteruskan sebagai frame: peristiwa itu membatalkan cache forwarder, dan host sesi menjatuhkan langganan ruang kerja anggota yang dihapus.