Domeingebeurtenissen
Gebeurtenissenbus
Sectie getiteld “Gebeurtenissenbus”De DomainEventBus is een broadcast-publish/subscribe-bus die binnen één proces draait. Uitgevers roepen publish(event) aan; abonnees consumeren een getypeerde on<T>()-stream. Elke gebeurtenis implementeert DomainEvent en draagt occurredAt.
De bus draait in cc_server. Elke uitgever en elke actieve abonnee leeft daar. Geen enkele client ziet deze bus — de server stuurt een zorgvuldig samengestelde subset door als notifications/* JSON-RPC-frames, per abonnee gefilterd op werkruimtelidmaatschap.
| Onderdeel | Aantal |
|---|---|
| Concrete gebeurtenisklassen | 54 |
Bronbestanden (packages/cc_domain/lib/core/domain/events/) |
14 (plus domain_event_bus.dart) |
| Abstracte bases die nooit rechtstreeks worden gepubliceerd | 1 (TaskLifecycleEvent, een sealed hiërarchie) |
Elke gebeurtenis in de catalogus hieronder woont in die ene map; er zijn nergens anders domeingebeurtenissen gedeclareerd.
Gebeurtenissen rond werkruimtes, agenten en repo’s
Sectie getiteld “Gebeurtenissen rond werkruimtes, agenten en repo’s”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
WorkspaceCreated |
workspaceId |
Werkruimte wordt aangemaakt |
AgentRunCompleted |
agentId, runId?, workspaceId?, conversationId? |
Agent rondt een run af (geslaagd of mislukt) |
AgentAwaitingInput |
workspaceId, kind, summary, spaceId?, conversationId?, agentId?, agentName? |
Een agent begint op een mens te wachten: een goedkeuring, een ask_user-vraag of een run die stilstaat op inloggegevens (kind is approval, question of credential) |
RepoAdded |
repoId, path, workspaceId |
Een repo wordt geregistreerd; start code-indexering op de achtergrond |
SkillUpdated |
workspaceId, slug, origin, computedHash, scanVerdict? |
Een skill wordt geïnstalleerd of bijgewerkt, met het oordeel van de toeleveringsketenscan erbij |
PR- en reviewgebeurtenissen
Sectie getiteld “PR- en reviewgebeurtenissen”Het eerste blok is de eigen levenscyclus van de PR. Het tweede is de bewaking van eigen PR’s: signalen over een PR die jij hebt geopend, elk met forUserId, zodat de poll ze naar de persoon in kwestie kan sturen in plaats van ze breed uit te zenden.
| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
PullRequestPublished |
prId, workspaceId, repoOwner, repoName |
Agent opent een PR |
PullRequestStatusChanged |
status, workspaceId, prId?, repoFullName?, prNumber? |
PR wordt samengevoegd/gesloten/geopend/heropend/goedgekeurd |
PrMerged |
prId, workspaceId, agentId |
PR wordt samengevoegd — een smal signaal dat alleen merges betreft, bewaard voor analytics/meldingen |
PrReviewRequested |
workspaceId, repoOwner, repoName, prNumber, prTitle |
GitHub vraagt om een review van de servergebruiker (meldingenpoll, review_requested) |
PrMentioned |
workspaceId, repoOwner, repoName, prNumber, prTitle |
De servergebruiker wordt vermeld bij een PR (meldingenpoll, mention) |
ExternalPrMerged |
workspaceId, repoOwner, repoName, prNumber, prTitle, mergedByLogin? |
Een extern gevolgde (niet-agent-)PR wordt samengevoegd, gedetecteerd door de GitHub-meldingenpoll; komt overeen met de meldingscategorie prMerged |
ExternalPrDetected |
repoOwner, repoName, prNumber, prTitle, author, workspaceId? |
Niet-agent-PR gevonden via polling — alleen voor pipelines (stuurt external_pr_welcome aan), levert geen melding op |
PrHeadChanged |
repoOwner, repoName, prNumber, prTitle, previousHeadSha, headSha, workspaceId |
De head-SHA van de PR is verschoven — de auteur heeft gepusht |
ReviewBecameStale |
workspaceId, spaceId, repoOwner, repoName, prNumber, prTitle, reviewedHeadSha, headSha |
Een afgeronde AI-review beschrijft de PR die hij heeft gereviewd niet meer. Gaat alleen af wanneer er een review bestaat voor de vervangen commit, zodat het een signaal blijft in plaats van een ping bij elke push |
De bewaking van eigen PR’s
Sectie getiteld “De bewaking van eigen PR’s”Alle zes dragen workspaceId, repoOwner, repoName, prNumber, prTitle en een optionele forUserId mee.
| Gebeurtenis | Aanvullende payload | Wordt gepubliceerd wanneer |
|---|---|---|
PrMergeReadinessChanged |
ready, reason |
Een PR van jou werd samenvoegbaar, of is dat niet meer |
PrReviewDecisionChanged |
decision, reviewersRemaining, approverLogin? |
Een reviewer keurde goed, vroeg wijzigingen of zag een goedkeuring ingetrokken worden |
PrChecksStatusChanged |
failing, failingCheckName?, failingCheckUrl? |
CI werd rood, of herstelde |
PrCommentMentioned |
commentId, authorLogin, bodyPreview, isReviewComment, threadId?, path?, line? |
Iemand vermeldde je in een PR-opmerking of reviewopmerking |
PrThreadReplied |
commentId, authorLogin, bodyPreview, threadId?, path?, line? |
Iemand antwoordde in een reviewthread waarin je zit |
PrThreadResolved |
threadId, commentId?, path?, line? |
Iemand markeerde een reviewthread waarin je zit als opgelost |
Berichtengebeurtenissen
Sectie getiteld “Berichtengebeurtenissen”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
MessageReceived |
spaceId, messageId, senderName, contentPreview, isAgentMessage, workspaceId?, mentions, requestedByUserId?, senderUserId? |
Er komt een nieuw bericht binnen |
SpaceCreated |
spaceId, workspaceId |
Ruimte wordt aangemaakt |
SpaceDeleted |
spaceId, workspaceId |
Ruimte wordt verwijderd |
SpaceProvisioningChanged |
workspaceId, spaceId, status, step? |
De werkruimte die bij de ruimte hoort gaat provisioneren, bereikt een stap (een repo klonen, een PR uitchecken, een agent opzetten) of klapt om naar gereed/mislukt — de chatbrug vertelt dat op zijn taakkaart |
Ticketgebeurtenissen
Sectie getiteld “Ticketgebeurtenissen”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
TicketCreated |
ticketId, workspaceId |
Ticket wordt aangemaakt |
TicketAssigned |
ticketId, ticketTitle, ticketBody?, ticketUrl?, assignedAgentId?, assigneeType, assignedTeamId?, workspaceId |
Ticket toegewezen aan een principaal of team |
TicketCompleted |
ticketId |
Het werk is klaar (eindtoestand) |
TicketFailed |
ticketId, errorMessage |
Agent mislukt (eindtoestand) |
TicketCancelled |
ticketId |
Ticket geannuleerd (eindtoestand) |
TicketStatusChanged |
ticketId, workspaceId, from, to |
Elke statuswijziging |
TicketReassigned |
ticketId, workspaceId, fromAgentId?, toAgentId? |
Ticket opnieuw toegewezen |
TicketDetailsUpdated |
ticketId, workspaceId |
Titel, beschrijving of prioriteit verandert |
Gebeurtenissen in de taaklevenscyclus
Sectie getiteld “Gebeurtenissen in de taaklevenscyclus”De uniforme stream van de taaklevenscyclus — één gedispatchte agentrun, gesleuteld op het id van zijn runlog. Elke gebeurtenis draagt taskId, een monotone seq per taak, workspaceId?, agentId? en een phase; de rijen hieronder vermelden alleen de extra velden.
| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
TaskDispatched |
— | Taak wordt aan een backend overgedragen voor uitvoering |
TaskRunning |
— | Taak begon uitvoer te produceren |
TaskWaitingLocalDirectory |
lockedPath, holderTaskId? |
Taak wordt geparkeerd — een andere taak bezit het padslot op schijf dat hij nodig heeft |
TaskProgress |
note? |
Voortgangscontrolepunt halverwege de run |
TaskMessage |
messageType, content |
Gestreamd bericht (text/thinking/tool_use/tool_result/error); gerapporteerd onder de fase progress |
TaskCompleted |
summary? |
Taak is geslaagd |
TaskFailed |
errorMessage |
Taak is met een fout afgerond |
TaskCancelled |
— | Taak geannuleerd voordat hij klaar was |
De enum TaskPhase heeft ook een lid queued, maar niets publiceert een queued-gebeurtenis — er is geen klasse TaskQueued. Het eerste waarneembare frame van een taak is TaskDispatched.
Pipelinegebeurtenissen
Sectie getiteld “Pipelinegebeurtenissen”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
PipelineRunCompleted |
workspaceId, pipelineRunId, templateId |
Run is klaar |
PipelineRunCancelled |
workspaceId, pipelineRunId, templateId |
Run geannuleerd (door de gebruiker of het systeem) — een bewuste stop, geen fout |
PipelineRunFailed |
workspaceId, pipelineRunId, templateId, errorMessage |
Run mislukt |
Alleen eindovergangen worden gepubliceerd. Er is geen PipelineRunStarted en geen gebeurtenis per stap: de voortgang van een stap bereikt clients via de eigen rijen van de run en de stream van de taaklevenscyclus van de agent die hij heeft gedispatcht, niet via de bus.
Observability-gebeurtenissen
Sectie getiteld “Observability-gebeurtenissen”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
ActivityLogged |
id, actorType, actorId?, action, entityType, entityId?, details?, workspaceId?, runId? |
Er wordt een regel in het auditspoor aangemaakt |
BudgetThresholdCrossed |
scopeType, scopeId, spentCents, budgetCents, isHardStop |
Uitgaven overschrijden de drempel |
Gebeurtenissen rond identiteit en lidmaatschap
Sectie getiteld “Gebeurtenissen rond identiteit en lidmaatschap”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
WorkspaceMemberAdded |
workspaceId, userId, role |
Een gebruiker komt bij een werkruimte (uitnodiging inwisselen of toevoegen door een beheerder) |
WorkspaceMemberRemoved |
workspaceId, userId |
Een lid wordt verwijderd — actieve sessies van die gebruiker binnen de werkruimte moeten de toegang onmiddellijk opnieuw controleren |
WorkspaceMemberRoleChanged |
workspaceId, userId, role |
De rol van een lid verandert |
Lidmaatschap is het hele identiteitsoppervlak op de bus. Het aanmaken van gebruikers en het intrekken van apparaten gebeuren wel, maar ze worden niet als domeingebeurtenissen gepubliceerd — intrekking wordt rechtstreeks tegen actieve sessies afgedwongen in plaats van via de bus te lopen.
Agenda- en vergadergebeurtenissen
Sectie getiteld “Agenda- en vergadergebeurtenissen”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
CalendarAuthExpired |
workspaceId, accountEmail |
De OAuth-refresh token van een gekoppeld account is permanent ongeldig (één keer gepubliceerd per verbreking) |
MeetingStartingSoon |
workspaceId, eventId, title, startTime, meetingUrl? |
Een agenda-afspraak begint binnen het geconfigureerde voorloopvenster |
MeetingRecordingStopped |
workspaceId, meetingId, title, userNotes, transcript, summaryInstructions? |
Een vergaderopname is klaar en start de ingebouwde pipeline meeting_summary |
Riggebeurtenissen
Sectie getiteld “Riggebeurtenissen”| Gebeurtenis | Payload | Wordt gepubliceerd wanneer |
|---|---|---|
RigClosedEvent |
workspaceId, rigId, reason |
Een rig is verdwenen, met zijn sluitingsreden; consumenten reageren alleen op backendFailure — elke andere reden is aangevraagd of gaat gepaard met een RigReaped |
RigControlChanged |
workspaceId, rigId, controller? |
Een mens nam de exclusieve controle over een rig over of gaf die terug (controller is null bij vrijgave — de gebeurtenis legt niet vast wie heeft losgelaten) |
RigReaped |
workspaceId, rigId, reason, agentId? |
Het systeem heeft een machine teruggeëist: idle, TTL of geheugendrukevictie (gerapporteerd als idleTimeout), met de aansturende agent |
Een rig die opent is geen gebeurtenis. De boot rondt af en de rij van de rig klapt om naar gereed; er wordt niets gepubliceerd, dus er is geen RigOpened om je op te abonneren.
Subdomeinen zonder enige gebeurtenis
Sectie getiteld “Subdomeinen zonder enige gebeurtenis”Verschillende subsystemen die van buitenaf gebeurtenisgestuurd lijken, zijn dat niet. Ze staan hier omdat hun afwezigheid een ontwerpbeslissing is die je wilt kennen voordat je op zoek gaat naar een hook:
| Subdomein | Hoe de status wél verandert |
|---|---|
| Geheugen | record_memory_fact en vrienden schrijven en geven terug; recall leest. Niets publiceert bij een feit of conflict |
| Orkestratie | Het voorstel, de goedkeuring ervan en de gegenereerde pipelinerun zijn rijen en RPC-aanroepen |
| Plandocumenten | submit_plan schrijft een revisie; goedkeuring materialiseert een orkestratie. Geen van beide wordt aangekondigd |
| Artefacten | publish_artifact / revise_artifact schrijven revisies rechtstreeks |
| Goedkeuringen | Escalatie wordt binnen de goedkeuringsworkflowservice afgehandeld |
| Ticketsynchronisatie | De leverancierscoördinator abonneert zich op de ticketgebeurtenissen hierboven; inkomende webhooks worden rechtstreeks toegepast |
| Agendaverversing | Een sync upsert afspraken en de client leest opnieuw; er is geen verversingsbroadcast |
| Worktreemerges | Vastgelegd in worktree_merge_log en daarvandaan gelezen |
Abonnees
Sectie getiteld “Abonnees”Elke abonnee hieronder wordt geconstrueerd in runCcServer (of in een service die het opbouwt). Er is geen abonnee aan de clientkant.
| Abonnee | Gebeurtenissen die hij consumeert |
|---|---|
WorkspaceSeeder |
WorkspaceCreated |
| Seeden van starter-evalsuites (inline) | WorkspaceCreated |
| Provisioneren van chatruimtes (inline) | SpaceCreated |
PipelineTriggerDispatcher |
Elke DomainEvent; elke ingeschakelde trigger filtert op zijn eigen type |
SubPipelineResumeListener |
PipelineRunCompleted, PipelineRunFailed |
PipelineCostRollupListener |
AgentRunCompleted |
BudgetEvaluationListener |
AgentRunCompleted |
MeetingSummaryReconciler |
PipelineRunCompleted, PipelineRunFailed, PipelineRunCancelled (alleen runs van 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 — injecteert een bericht in gewone taal op de stuurbaan van de aansturende agent |
StaleReviewWatcher |
PrHeadChanged — publiceert ReviewBecameStale alleen wanneer er een afgeronde review bestaat voor de vervangen commit |
GitHubPrConversationBridge |
AgentRunCompleted — uitgaande antwoorden in PR-gesprekken |
NotificationFeedRecorder |
De tweeëntwintig gebeurtenissen van de meldingsklasse hieronder |
RemoteEventForwarder |
Die tweeëntwintig plus TicketReassigned en elke TaskLifecycleEvent. De drie lidmaatschapsgebeurtenissen maken alleen de lidmaatschapscache per werkruimte ongeldig; ze worden niet als frames doorgestuurd |
LocalRpcServer / RemoteRelayHost |
WorkspaceMemberRemoved — laat de gekoppelde werkruimte-abonnementen van die gebruiker vallen; de socket blijft open |
TicketAssigned is een audit- en meldingssignaal en een pipelinetrigger. Toewijzing aan een agent legt eigenaarschap vast en start geen run — er is geen ticketdispatcher. Toewijzing aan een team (assignedTeamId ingesteld) is de uitzondering: TeamRoutingService dispatcht de teamleider.
TicketRemoteSyncHandler is gedeclareerd maar wordt nooit geconstrueerd in productiecode, dus hij abonneert zich vandaag op niets. De client-side NotificationEventMapper wordt alleen in zijn eigen test geconstrueerd — het is het overblijfsel van het in-process-pad van vóór de client/server-splitsing. Live toasts komen uit de wire frames hieronder.
Meldingstoewijzing
Sectie getiteld “Meldingstoewijzing”Op de server zetten NotificationFeedRecorder en RemoteEventForwarder deze gebeurtenissen om in notifications/* wire frames (notification_wire.dart). Op de client zet RpcNotificationMapper → mapNotificationFrame een frame om in een AppNotification.
Er zijn precies zeventien meldingscategorieën. Verschillende gebeurtenissen komen overeen met meer dan één wire-methode, omdat het frame de overgang draagt (mislukt versus hersteld) terwijl de categorie de vraag draagt (“wat doet CI?”).
| Categorie | Brongebeurtenis | Wire-methode |
|---|---|---|
newMessage |
MessageReceived |
notifications/message_received (vermeldt jou) |
agentRunCompleted |
MessageReceived |
notifications/message_received (is_agent_message, zonder vermelding van jou) |
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 |
Het frame voor rig-overname wordt niet terugbezorgd aan wie het stuur overnam, een
vrijgave wordt niet gefilterd (de gebeurtenis legt niet vast wie heeft losgelaten), en alleen een
sluiting met backendFailure levert een rig_closed-frame op — de andere redenen zijn
aangevraagd of al gedekt door het reap-frame.
AgentAwaitingInput wordt gepubliceerd door AgentAwaitingInputPublisher, die
de registers voor goedkeuringen en geblokkeerde inloggegevens in de gaten houdt
voor nieuwe items en door AgentQuestionService op de hoogte wordt gebracht van
elke ask_user-vraag. Eén wachtmoment is één gebeurtenis; er wordt niets
gepubliceerd wanneer het wachten eindigt.
De vijf categorieën voor eigen PR’s dragen forUserId mee, zodat ze de auteur bereiken in plaats van iedereen in de werkruimte.
RemoteEventForwarder stuurt daarnaast TicketReassigned door als notifications/ticket_reassigned en elke TaskLifecycleEvent als notifications/task_<phase>. Geen van beide komt overeen met een meldingscategorie — ze sturen live UI aan, niet het meldingencentrum. Lidmaatschapsgebeurtenissen worden niet als frames doorgestuurd: ze maken de cache van de forwarder ongeldig, en de sessiehosts laten de werkruimte-abonnementen van het verwijderde lid vallen.