Gå til innholdet

Livssyklus for saker

Status Lagringsstreng Beskrivelse
backlog backlog Fanget opp, ennå ikke prioritert inn i den aktive køen
open open Prioritert og klar til å arbeides med, ikke startet
inProgress inProgress Arbeides aktivt med
blocked blocked Startet, men blokkert av noe eksternt
inReview inReview Arbeidet er ferdig, venter på gjennomgang
done done Fullført med suksess (sluttilstand)
failed failed Fullført med feil (sluttilstand)
cancelled cancelled Avbrutt (sluttilstand)

Statusverdier lagres i camelCase (inProgress, inReview), aldri in_progress. En lagret nullverdi tolkes som open; en ukjent verdi kaster feil i stedet for å tvinges.

tryParseLoose godtar aliaser som agenter oppgir, og ser bort fra store og små bokstaver og - / _ / mellomrom:

Status Godtatte aliaser
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

Denne grafen binder bare agenter og automatisering. TicketWorkflowService.transitionStatus kontrollerer den når force er usann — MCP-verktøyene og avstemmerne. En ulovlig overgang der logges og ignoreres. Enhver brukerstyrt statusendring i brukergrensesnittet sender force: true og omgår grafen helt, så et menneske kan flytte en sak til hvilken som helst status velgeren lister opp (alle statuser unntatt failed), inkludert å gjenåpne en sluttilstand. Agenter markerer failed med fail_ticket.

En status kan alltid gå over til seg selv. Sluttilstander har ingen utgående kanter.

Fra Tillatte mål
backlog open, cancelled
open inProgress, blocked, cancelled
inProgress blocked, inReview, done, failed, cancelled
blocked inProgress, cancelled
inReview inProgress, done, failed, cancelled
done — (sluttilstand)
failed — (sluttilstand)
cancelled — (sluttilstand)

Lagres som et heltall på Linears opprinnelige 0–4-skala. En ukjent verdi tolkes som none.

Prioritet Lagret som
none 0
urgent 1
high 2
medium 3
low 4

En ukjent verdi eller en lagret nullverdi tolkes som local.

Leverandør Status
local Lagres helt i arbeidsområdets database; standardvalget
linear Eies eksternt, speiles lokalt

Synkroniseringsadaptere ligger under packages/cc_infra/lib/src/tickets/sync/ for Linear, GitHub Issues, Jira Cloud og ClickUp. GitHub Issues er bare en synkroniseringsadapter-leverandør (vendorId: github) — det er ikke en TicketProvider-verdi, så en hentet GitHub-sak lagres med originKind: externalSync og standardverdien provider: local. Tilordningen av leverandører ligger på ticket_sync_links.

createTicket skriver manual. En leverandørhenting skriver externalSync. Delegerte barnesaker forblir manual.

Verdi Betydning
manual Standard i createTicket (rader fra mennesker, agenter og delegeringer)
externalSync Settes av TicketSyncEngine ved en leverandørhenting

Aggregatet dekker to forhold på én rad. Speilet (leverandør, nøkler, tittel, beskrivelse, prioritet, etiketter, statuser, tidsstempler) er en hurtigbuffer for en ekstern leverandør og skrives i sin helhet på nytt ved en oppdatering. Overlegget (tildeling, delegering, område, overordnet, prosjekt, koblede PR-er) finnes bare i Control Center, og en oppdatering rører det aldri.

Felt Type Beskrivelse
id String UUID v4
workspaceId String Arbeidsområdet den tilhører
provider TicketProvider Backend som eier de kanoniske dataene (standard local)
externalKey String? Leverandørens egen nøkkel (f.eks. LIN-123). Lokal createTicket skriver en egen UUID her, ikke radens id
url String? Nettadresse hos den eksterne leverandøren
title String Kort sammendrag; kan ikke være tomt
description String? Lengre markdown-tekst
priority TicketPriority Standard none
labels List<String> Frie etiketter
status TicketStatus Kanonisk normalisert status
rawStatus String? Den eksterne leverandørens opprinnelige tilstandsnavn, beholdt for tapsfri visning
externalSyncedAt DateTime? Siste synkronisering på tvers av leverandører; null til den første. Tilordningen per leverandør ligger i ticket_sync_links
parentTicketId String? Overordnet i treet for delegering og nedbrytning
projectId String? Prosjektet den tilhører; sendes aldri til en ekstern leverandør
assignedAgentId String? Id-en til den tildelte principalen (bare metadata — en tildeling sender ikke ut noe)
assigneeType PrincipalType Hva slags principal assignedAgentId navngir — user eller agent (standard agent)
createdByType PrincipalType? Typen principal som opprettet saken (user eller agent); null for eldre rader og systemrader
createdById String? Id-en til principalen som opprettet saken
assignedTeamId String? Tildelt team (bare metadata)
delegatedByAgentId String? Agenten som delegerte denne saken
delegationDepth int Dybde i delegeringskjeden; roten er 0, kontrolleres mot grensen for maksimal dybde
delegationRootTicketId String? Roten i delegeringskjeden; null for en rotsak
spaceId String? Samtalen saken ble skilt ut fra, eller området til agenten som delegerte
errorMessage String? Settes når status er failed
linkedPrIds List<String> Node-id-er for PR-ene denne saken er koblet til
metadata Map<String, dynamic> Fri beholder
createdAt DateTime Opprettelsestidspunkt
startedAt DateTime? Når arbeidet startet
blockedAt DateTime? Når saken ble blokkert
cancelledAt DateTime? Når saken ble avbrutt
completedAt DateTime? Når saken ble fullført med suksess
finishedAt DateTime? Når saken nådde en sluttilstand
updatedAt DateTime Siste endring (speiloppdatering eller overleggsendring)
version int Teller for optimistisk samtidighet, økes ved hver endring
originKind TicketOriginKind Hvordan saken ble opprettet (standard manual)
collaborators List<TicketCollaborator> Fylles ut av repositoriet ved behov

Avledet: isTerminal, isRemote (provider != local), isAssignedToUser og displayKey (externalKey ?? id — lokale saker viser derfor den separate UUID-en fra opprettelsen, ikke radens id).

Lagrede kanter er retningsbestemte rader i ticket_links:

Type Lagringsstreng Betydning
blocks blocks Kilden blokkerer målet
relatesTo relates_to Symmetrisk relasjon
duplicateOf duplicate_of Kilden er en duplikat av målet

Vokabularet som brukergrensesnittet og ticket_relation bruker, er TicketRelationKind, avledet fra en lagret kant pluss hvilket endepunkt subjektet sitter på:

Type Avledet fra
blockedBy En blocks-rad der subjektet er målet
blocking En blocks-rad der subjektet er kilden
relatedTo En relates_to-rad (symmetrisk)
duplicateOf En duplicate_of-rad der subjektet er kilden
duplicatedBy En duplicate_of-rad der subjektet er målet
subIssueOf tickets.parent_ticket_id på subjektet
parentOf tickets.parent_ticket_id på den andre saken

Koblinger for overordnet og undersak er ikke ticket_links-rader — de ligger på tickets.parent_ticket_id.

Disse åtte klassene ligger i packages/cc_domain/lib/core/domain/events/ticketing_events.dart. Det finnes ingen TicketStarted, TicketDelegated, TicketCollaboratorAdded eller ExternalTicketWebhookReceived.

Hendelse Utløses når
TicketCreated En sak opprettes
TicketAssigned En sak tildeles en principal eller et team
TicketCompleted Arbeidet fullføres med suksess
TicketFailed Arbeidet mislykkes
TicketCancelled En sak avbrytes
TicketStatusChanged Enhver statusendring
TicketReassigned En sak tildeles på nytt
TicketDetailsUpdated Tittel, beskrivelse, prioritet eller etiketter endres

TicketAssigned er et revisjons- og varslingssignal og en pipeline-utløser. Tildeling til en agent starter ingen kjøring — det finnes ingen utsender for saker som overvåker assignedAgentId. Tildeling til et team er unntaket: TeamRoutingService sender ut teamlederen. Å legge til en samarbeidspartner skriver en rad og publiserer ingenting. En leverandørwebhook brukes gjennom TicketSyncEngine uten en domenehendelse.

TicketWorkflowService eier enhver endring.

Mekanisme Detaljer
Ett enkelt knutepunkt Alle endringer går gjennom _mutate, som laster raden og kaller _assertWorkspace før den brukes
Arbeidsområdeisolasjon _assertWorkspace kaster WorkspaceMismatchException når den lastede radens workspaceId ikke samsvarer med den kallendes
Optimistisk samtidighet _mutate skriver med expectedVersion satt til version-en den nettopp leste, og prøver på nytt ved ConcurrencyConflictException ved å lese fersk tilstand på nytt
Eksklusivt krav tryCheckout / releaseCheckout; en andre agent som gjør krav på en utsjekket sak, får en CheckoutConflictException
Overgangsvakt canTransitionTo, brukes bare når force er usann