Ticketlevenscyclus
Ticketstatussen
Sectie getiteld “Ticketstatussen”| Status | Opslagwaarde | Beschrijving |
|---|---|---|
backlog |
backlog |
Vastgelegd, nog niet getriëerd naar de actieve wachtrij |
open |
open |
Getriëerd en klaar om aan te werken, nog niet begonnen |
inProgress |
inProgress |
Wordt actief aan gewerkt |
blocked |
blocked |
Begonnen, maar geblokkeerd door iets externs |
inReview |
inReview |
Werk gedaan, wacht op review |
done |
done |
Succesvol afgerond (eindtoestand) |
failed |
failed |
Afgerond met een fout (eindtoestand) |
cancelled |
cancelled |
Opgegeven (eindtoestand) |
Statuswaarden worden opgeslagen in camelCase (inProgress, inReview), nooit als in_progress. Een opgeslagen null-waarde wordt geparseerd als open; een onbekende waarde gooit een fout in plaats van te converteren.
tryParseLoose accepteert aliassen die agents meegeven, waarbij hoofdlettergebruik en - / _ / spatie worden genegeerd:
| Status | Geaccepteerde aliassen |
|---|---|
open |
todo, ready, pending, new |
inProgress |
doing, started, active, wip |
blocked |
stuck |
inReview |
review, reviewing |
done |
closed, complete, completed, finished |
failed |
error, errored |
cancelled |
canceled, abandoned, dropped |
Statustransities
Sectie getiteld “Statustransities”backlog ──→ open ──→ inProgress ──→ inReview ──→ done │ │ │ │ └──→ failed ┘ └──→ blocked ──→ inProgress
Any non-terminal status ──→ cancelled; inReview ──→ failedDeze graaf bindt alleen agents en automatisering. TicketWorkflowService.transitionStatus controleert hem wanneer force false is — de MCP-tools en de reconcilers. Een ongeldige transitie wordt daar gelogd en genegeerd. Elke statuswijziging die de gebruiker in de UI doorvoert, geeft force: true mee en omzeilt de graaf volledig, dus een mens mag een ticket naar elke status verplaatsen die de keuzelijst toont (elke status behalve failed), inclusief het heropenen van een eindtoestand. Agents stellen failed in met fail_ticket.
Een status mag altijd naar zichzelf overgaan. Eindtoestanden hebben geen uitgaande randen.
| Van | Toegestane doelstatussen |
|---|---|
backlog |
open, cancelled |
open |
inProgress, blocked, cancelled |
inProgress |
blocked, inReview, done, failed, cancelled |
blocked |
inProgress, cancelled |
inReview |
inProgress, done, failed, cancelled |
done |
— (eindtoestand) |
failed |
— (eindtoestand) |
cancelled |
— (eindtoestand) |
Ticketprioriteiten
Sectie getiteld “Ticketprioriteiten”Opgeslagen als een geheel getal op Linears eigen schaal van 0–4. Een onbekende waarde wordt geparseerd naar none.
| Prioriteit | Opgeslagen als |
|---|---|
none |
0 |
urgent |
1 |
high |
2 |
medium |
3 |
low |
4 |
Ticketproviders
Sectie getiteld “Ticketproviders”Een onbekende of null opgeslagen waarde wordt geparseerd naar local.
| Provider | Status |
|---|---|
local |
Volledig opgeslagen in de werkruimtedatabase; de standaard |
linear |
Extern beheerd, lokaal gespiegeld |
Synchronisatie-adapters staan onder packages/cc_infra/lib/src/tickets/sync/ voor
Linear, GitHub Issues, Jira Cloud en ClickUp. GitHub Issues is alleen een
leverancier van een synchronisatie-adapter (vendorId: github) — het is geen
TicketProvider-waarde, dus een opgehaald GitHub-issue wordt opgeslagen met
originKind: externalSync en standaard provider: local. De leverancierskoppeling
staat op ticket_sync_links.
Ticketherkomst
Sectie getiteld “Ticketherkomst”createTicket schrijft manual. Een pull bij de leverancier schrijft
externalSync. Gedelegeerde kinderen blijven manual.
| Waarde | Betekenis |
|---|---|
manual |
Standaard bij createTicket (menselijke, agent- en gedelegeerde rijen) |
externalSync |
Ingesteld door TicketSyncEngine bij een pull bij de leverancier |
Ticketvelden
Sectie getiteld “Ticketvelden”Het aggregaat bestrijkt twee zaken op één rij. De spiegel (provider, sleutels, titel, beschrijving, prioriteit, labels, statussen, tijdstempels) is een cache voor een externe provider en wordt bij een verversing in zijn geheel herschreven. De overlay (toewijzing, delegatie, ruimte, ouder, project, gekoppelde PR’s) bestaat alleen in Control Center en een verversing raakt die nooit aan.
| Veld | Type | Beschrijving |
|---|---|---|
id |
String |
UUID v4 |
workspaceId |
String |
Werkruimte waartoe het ticket behoort |
provider |
TicketProvider |
Backend die de canonieke data bezit (standaard local) |
externalKey |
String? |
Provider-eigen sleutel (bijv. LIN-123). De lokale createTicket schrijft hier een afzonderlijke UUID, niet de rij-id |
url |
String? |
Web-URL bij de externe provider |
title |
String |
Korte samenvatting; mag niet leeg zijn |
description |
String? |
Langere Markdown-body |
priority |
TicketPriority |
Standaard none |
labels |
List<String> |
Vrije labels |
status |
TicketStatus |
Canonieke, genormaliseerde status |
rawStatus |
String? |
De eigen statusnaam van de externe provider, bewaard voor verliesvrije weergave |
externalSyncedAt |
DateTime? |
Laatste synchronisatie over alle leveranciers; null tot de eerste. De koppeling per leverancier staat in ticket_sync_links |
parentTicketId |
String? |
Ouder in de delegatie-/opsplitsingsboom |
projectId |
String? |
Project waartoe het hoort; wordt nooit naar een externe provider gepusht |
assignedAgentId |
String? |
Id van de toegewezen principal (alleen metadata — toewijzen dispatcht niets) |
assigneeType |
PrincipalType |
Soort principal dat assignedAgentId aanwijst — user of agent (standaard agent) |
createdByType |
PrincipalType? |
Soort principal dat het ticket heeft gemaakt (user of agent); null voor verouderde/systeemrijen |
createdById |
String? |
Id van de aanmakende principal |
assignedTeamId |
String? |
Toegewezen team (alleen metadata) |
delegatedByAgentId |
String? |
Agent die dit ticket heeft gedelegeerd |
delegationDepth |
int |
Diepte in de delegatieketen; de wortel is 0, gecontroleerd tegen het maximum-diepteplafond |
delegationRootTicketId |
String? |
Wortel van de delegatieketen; null voor een wortelticket |
spaceId |
String? |
Gesprek waaruit het ticket is voortgekomen, of de ruimte van de delegerende agent |
errorMessage |
String? |
Ingesteld wanneer status gelijk is aan failed |
linkedPrIds |
List<String> |
Node-id’s van PR’s waaraan dit ticket is gekoppeld |
metadata |
Map<String, dynamic> |
Ongestructureerde gegevensverzameling |
createdAt |
DateTime |
Tijdstip van aanmaken |
startedAt |
DateTime? |
Wanneer het werk begon |
blockedAt |
DateTime? |
Wanneer het ticket werd geblokkeerd |
cancelledAt |
DateTime? |
Wanneer het ticket werd geannuleerd |
completedAt |
DateTime? |
Wanneer het ticket succesvol werd afgerond |
finishedAt |
DateTime? |
Wanneer het ticket een eindtoestand bereikte |
updatedAt |
DateTime |
Laatste mutatie (spiegelverversing of overlaywijziging) |
version |
int |
Teller voor optimistische gelijktijdigheid, bij elke mutatie verhoogd |
originKind |
TicketOriginKind |
Hoe het ticket is ontstaan (standaard manual) |
collaborators |
List<TicketCollaborator> |
Op aanvraag gevuld door de repository |
Afgeleid: isTerminal, isRemote (provider != local), isAssignedToUser en displayKey (externalKey ?? id — lokale tickets tonen daarom de afzonderlijke UUID van het aanmaakmoment, niet de rij-id).
Ticketrelaties
Sectie getiteld “Ticketrelaties”Opgeslagen randen zijn gerichte rijen in ticket_links:
| Type | Opslagwaarde | Betekenis |
|---|---|---|
blocks |
blocks |
De bron blokkeert het doel |
relatesTo |
relates_to |
Symmetrische relatie |
duplicateOf |
duplicate_of |
De bron is een duplicaat van het doel |
Het vocabulaire dat de UI en ticket_relation gebruiken is TicketRelationKind, afgeleid van een opgeslagen rand plus het eindpunt waaraan het subject hangt:
| Soort | Afgeleid van |
|---|---|
blockedBy |
Een blocks-rij waarin het subject het doel is |
blocking |
Een blocks-rij waarin het subject de bron is |
relatedTo |
Een relates_to-rij (symmetrisch) |
duplicateOf |
Een duplicate_of-rij waarin het subject de bron is |
duplicatedBy |
Een duplicate_of-rij waarin het subject het doel is |
subIssueOf |
tickets.parent_ticket_id op het subject |
parentOf |
tickets.parent_ticket_id op het andere ticket |
Ouder- en subissue-koppelingen zijn geen rijen in ticket_links — ze leven op tickets.parent_ticket_id.
Domeingebeurtenissen
Sectie getiteld “Domeingebeurtenissen”Deze acht klassen staan in packages/cc_domain/lib/core/domain/events/ticketing_events.dart. Er is geen TicketStarted, TicketDelegated, TicketCollaboratorAdded of ExternalTicketWebhookReceived.
| Gebeurtenis | Wordt gepubliceerd wanneer |
|---|---|
TicketCreated |
Er wordt een ticket gemaakt |
TicketAssigned |
Een ticket wordt toegewezen aan een principal of team |
TicketCompleted |
Het werk wordt succesvol afgerond |
TicketFailed |
Het werk mislukt |
TicketCancelled |
Een ticket wordt geannuleerd |
TicketStatusChanged |
Elke statuswijziging |
TicketReassigned |
Een ticket wordt opnieuw toegewezen |
TicketDetailsUpdated |
Titel, beschrijving, prioriteit of labels veranderen |
TicketAssigned is een audit- en meldingssignaal en een pipelinetrigger. Toewijzing aan een agent start geen run — er is geen ticketdispatcher die op assignedAgentId let. Toewijzing aan een team is de uitzondering: TeamRoutingService dispatcht de teamleider. Een medewerker toevoegen schrijft een rij en publiceert niets. Een webhook van een leverancier wordt via TicketSyncEngine toegepast zonder domeingebeurtenis.
Centraal controlepunt voor mutaties
Sectie getiteld “Centraal controlepunt voor mutaties”TicketWorkflowService bezit elke mutatie.
| Mechanisme | Details |
|---|---|
| Eén centraal controlepunt | Alle mutaties lopen via _mutate, dat de rij laadt en _assertWorkspace aanroept voordat er iets wordt toegepast |
| Werkruimte-isolatie | _assertWorkspace gooit WorkspaceMismatchException wanneer de workspaceId van de geladen rij niet overeenkomt met die van de aanroeper |
| Optimistische gelijktijdigheid | _mutate schrijft met expectedVersion ingesteld op de version die het zojuist heeft gelezen en probeert het opnieuw bij een ConcurrencyConflictException door de nieuwste status opnieuw te lezen |
| Exclusieve claim | tryCheckout / releaseCheckout; een tweede agent die een uitgecheckt ticket claimt, krijgt een CheckoutConflictException |
| Transitiebeveiliging | canTransitionTo, alleen toegepast wanneer force false is |