Ga naar inhoud

Domeingebeurtenissen

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

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

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

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.

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.

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.

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

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

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.

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.