Lewati ke konten

Peristiwa domain

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 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

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

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 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 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

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 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 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 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 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 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

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.

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.