Ga naar inhoud

Ticketlevenscyclus

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
backlog ──→ open ──→ inProgress ──→ inReview ──→ done
│ │ │
│ └──→ failed ┘
└──→ blocked ──→ inProgress
Any non-terminal status ──→ cancelled; inReview ──→ failed

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

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

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.

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

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

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.

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.

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