Przejdź do głównej zawartości

Cykl życia zgłoszenia

Status Zapisany ciąg Opis
backlog backlog Zarejestrowane, jeszcze nieprzeniesione do aktywnej kolejki
open open Rozpatrzone i gotowe do pracy, jeszcze nie rozpoczęte
inProgress inProgress Praca trwa
blocked blocked Rozpoczęte, ale zablokowane przez coś zewnętrznego
inReview inReview Praca wykonana, oczekuje na recenzję
done done Zakończone pomyślnie (stan końcowy)
failed failed Zakończone błędem (stan końcowy)
cancelled cancelled Porzucone (stan końcowy)

Wartości statusu są zapisywane w camelCase (inProgress, inReview), nigdy jako in_progress. Zapisana wartość null jest parsowana jako open; nieznana wartość zgłasza wyjątek, a nie jest rzutowana.

tryParseLoose przyjmuje aliasy podane przez agenta, ignorując wielkość liter oraz znaki - / _ / spację:

Status Akceptowane aliasy
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

Ten graf wiąże wyłącznie agentów i automatyzację. TicketWorkflowService.transitionStatus sprawdza go, gdy force ma wartość false — czyli w narzędziach MCP i reconcilerach. Niedozwolone przejście jest tam logowane i ignorowane. Każda zmiana statusu wywołana przez użytkownika w interfejsie przekazuje force: true i całkowicie omija graf, więc człowiek może przenieść zgłoszenie do dowolnego statusu z listy selektora (każdego poza failed), w tym ponownie otworzyć stan końcowy. Agenci oznaczają failed za pomocą fail_ticket.

Status może zawsze przejść sam w siebie. Stany końcowe nie mają krawędzi wychodzących.

Ze stanu Dozwolone stany docelowe
backlog open, cancelled
open inProgress, blocked, cancelled
inProgress blocked, inReview, done, failed, cancelled
blocked inProgress, cancelled
inReview inProgress, done, failed, cancelled
done — (stan końcowy)
failed — (stan końcowy)
cancelled — (stan końcowy)

Przechowywany jako liczba całkowita w natywnej skali 0–4 Linear. Nieznana wartość jest parsowana jako none.

Priorytet Zapisywany jako
none 0
urgent 1
high 2
medium 3
low 4

Nieznana zapisana wartość lub wartość null jest parsowana jako local.

Dostawca Status
local Przechowywane w całości w bazie obszaru roboczego; wartość domyślna
linear Należące do systemu zdalnego, odzwierciedlane lokalnie

Adaptery synchronizacji znajdują się w packages/cc_infra/lib/src/tickets/sync/ dla Linear, GitHub Issues, Jira Cloud i ClickUp. GitHub Issues jest wyłącznie dostawcą adaptera synchronizacji (vendorId: github) — nie jest wartością TicketProvider, więc pobrane zgłoszenie z GitHub jest zapisywane z originKind: externalSync i domyślnym provider: local. Mapowanie dostawcy znajduje się w ticket_sync_links.

createTicket zapisuje manual. Pobranie od dostawcy zapisuje externalSync. Delegowane zgłoszenia potomne pozostają manual.

Wartość Znaczenie
manual Wartość domyślna w createTicket (wiersze człowieka, agenta i delegowane)
externalSync Ustawiana przez TicketSyncEngine przy pobraniu od dostawcy

Agregat obejmuje dwa zagadnienia w jednym wierszu. Kopia lustrzana (dostawca, klucze, tytuł, opis, priorytet, etykiety, statusy, znaczniki czasu) jest pamięcią podręczną dla zdalnego dostawcy i jest w całości przepisywana przez odświeżenie. Nakładka (przypisanie, delegowanie, przestrzeń, element nadrzędny, projekt, powiązane PR-y) należy wyłącznie do Control Center i odświeżenie nigdy jej nie dotyka.

Pole Typ Opis
id String UUID v4
workspaceId String Obszar roboczy będący właścicielem
provider TicketProvider Backend będący właścicielem danych kanonicznych (domyślnie local)
externalKey String? Klucz natywny dla dostawcy (np. LIN-123). Lokalny createTicket zapisuje tutaj osobny UUID, a nie id wiersza
url String? URL internetowy u zdalnego dostawcy
title String Krótkie podsumowanie; nie może być puste
description String? Dłuższa treść w formacie Markdown
priority TicketPriority Domyślnie none
labels List<String> Etykiety o dowolnej treści
status TicketStatus Znormalizowany status kanoniczny
rawStatus String? Natywna nazwa stanu u zdalnego dostawcy, zachowana na potrzeby bezstratnego wyświetlania
externalSyncedAt DateTime? Ostatnia synchronizacja wielu dostawców; null aż do pierwszej. Mapowanie poszczególnych dostawców znajduje się w ticket_sync_links
parentTicketId String? Element nadrzędny w drzewie delegowania / podziału
projectId String? Projekt będący właścicielem; nigdy nie jest wysyłany do systemu zdalnego
assignedAgentId String? Identyfikator przypisanego podmiotu (tylko metadane — przypisanie nic nie wysyła)
assigneeType PrincipalType Rodzaj podmiotu, który wskazuje assignedAgentId — user lub agent (domyślnie agent)
createdByType PrincipalType? Rodzaj podmiotu, który utworzył zgłoszenie (user lub agent); null dla wierszy zastanych/systemowych
createdById String? Identyfikator podmiotu tworzącego
assignedTeamId String? Przypisany zespół (tylko metadane)
delegatedByAgentId String? Agent, który delegował to zgłoszenie
delegationDepth int Głębokość w łańcuchu delegowania; korzeń to 0, sprawdzana względem pułapu maksymalnej głębokości
delegationRootTicketId String? Korzeń łańcucha delegowania; null dla zgłoszenia korzenia
spaceId String? Rozmowa, z której wyodrębniono zgłoszenie, albo przestrzeń delegującego agenta
errorMessage String? Ustawiany, gdy status ma wartość failed
linkedPrIds List<String> Identyfikatory węzłów PR, z którymi powiązano to zgłoszenie
metadata Map<String, dynamic> Dowolny zbiór wartości
createdAt DateTime Czas utworzenia
startedAt DateTime? Czas rozpoczęcia pracy
blockedAt DateTime? Czas zablokowania zgłoszenia
cancelledAt DateTime? Czas anulowania zgłoszenia
completedAt DateTime? Czas pomyślnego zakończenia zgłoszenia
finishedAt DateTime? Czas osiągnięcia dowolnego stanu końcowego przez zgłoszenie
updatedAt DateTime Ostatnia mutacja (odświeżenie kopii lustrzanej lub zmiana nakładki)
version int Licznik współbieżności optymistycznej, zwiększany przy każdej mutacji
originKind TicketOriginKind Sposób utworzenia zgłoszenia (domyślnie manual)
collaborators List<TicketCollaborator> Uzupełniani przez repozytorium na żądanie

Wartości pochodne: isTerminal, isRemote (provider != local), isAssignedToUser oraz displayKey (externalKey ?? id — zgłoszenia lokalne wyświetlają więc osobny UUID z czasu utworzenia, a nie id wiersza).

Zapisane krawędzie to skierowane wiersze w ticket_links:

Typ Zapisany ciąg Znaczenie
blocks blocks Źródło blokuje cel
relatesTo relates_to Relacja symetryczna
duplicateOf duplicate_of Źródło jest duplikatem celu

Słownictwo, którym posługują się interfejs i ticket_relation, to TicketRelationKind, wyprowadzane z zapisanej krawędzi oraz z tego, na którym końcu znajduje się podmiot:

Rodzaj Wyprowadzany z
blockedBy Wiersz blocks, w którym podmiot jest celem
blocking Wiersz blocks, w którym podmiot jest źródłem
relatedTo Wiersz relates_to (symetrycznie)
duplicateOf Wiersz duplicate_of, w którym podmiot jest źródłem
duplicatedBy Wiersz duplicate_of, w którym podmiot jest celem
subIssueOf tickets.parent_ticket_id w podmiocie
parentOf tickets.parent_ticket_id w drugim zgłoszeniu

Powiązania nadrzędne i podzgłoszenia nie są wierszami ticket_links — żyją w tickets.parent_ticket_id.

Te osiem klas znajduje się w packages/cc_domain/lib/core/domain/events/ticketing_events.dart. Nie istnieje TicketStarted, TicketDelegated, TicketCollaboratorAdded ani ExternalTicketWebhookReceived.

Zdarzenie Wyzwalane, gdy
TicketCreated Zgłoszenie zostaje utworzone
TicketAssigned Zgłoszenie zostaje przypisane do podmiotu lub zespołu
TicketCompleted Praca kończy się pomyślnie
TicketFailed Praca kończy się niepowodzeniem
TicketCancelled Zgłoszenie zostaje anulowane
TicketStatusChanged Dowolna zmiana statusu
TicketReassigned Zgłoszenie zostaje przypisane ponownie
TicketDetailsUpdated Zmienia się tytuł, opis, priorytet lub etykiety

TicketAssigned jest sygnałem audytowym i powiadomieniem oraz wyzwalaczem potoku. Przypisanie do agenta nie rozpoczyna żadnego uruchomienia — nie istnieje dyspozytor zgłoszeń, który obserwuje assignedAgentId. Wyjątkiem jest przypisanie do zespołu: TeamRoutingService wysyła lidera zespołu. Dodanie współpracownika zapisuje wiersz i niczego nie publikuje. Webhook dostawcy jest stosowany przez TicketSyncEngine bez zdarzenia domenowego.

TicketWorkflowService włada każdą mutacją.

Mechanizm Szczegóły
Pojedynczy punkt kontrolny Wszystkie mutacje przechodzą przez _mutate, który wczytuje wiersz i wywołuje _assertWorkspace przed zastosowaniem zmian
Izolacja obszarów roboczych _assertWorkspace zgłasza WorkspaceMismatchException, gdy workspaceId wczytanego wiersza nie zgadza się z obszarem wywołującego
Współbieżność optymistyczna _mutate zapisuje z expectedVersion ustawionym na version, którą właśnie odczytał, a przy ConcurrencyConflictException ponawia próbę po odczytaniu świeżego stanu
Wyłączność przejęcia tryCheckout / releaseCheckout; drugi agent próbujący przejąć już przejęte zgłoszenie otrzymuje CheckoutConflictException
Strażnik przejść canTransitionTo, stosowany tylko wtedy, gdy force ma wartość false