İçeriğe geç

Bilet yaşam döngüsü

Durum Depolama dizesi Açıklama
backlog backlog Kaydedildi, henüz etkin kuyruğa triyaj edilmedi
open open Triyaj edildi ve üzerinde çalışılmaya hazır, başlatılmadı
inProgress inProgress Etkin olarak üzerinde çalışılıyor
blocked blocked Başladı ancak harici bir şey tarafından engellendi
inReview inReview İş tamamlandı, inceleme bekliyor
done done Başarıyla tamamlandı (terminal)
failed failed Bir hatayla tamamlandı (terminal)
cancelled cancelled Terk edildi (terminal)

Durum değerleri camelCase olarak (inProgress, inReview) depolanır, asla in_progress biçiminde değil. Depolanmış null bir değer open olarak ayrıştırılır; bilinmeyen bir değer ise zorlanmak yerine hata fırlatır.

tryParseLoose, ajan tarafından sağlanan takma adları kabul eder; büyük/küçük harf ile - / _ / boşluğu yok sayar:

Durum Kabul edilen takma adlar
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

Bu grafik yalnızca ajanları ve otomasyonu bağlar. TicketWorkflowService.transitionStatus, force false olduğunda bunu denetler — MCP araçları ve uzlaştırıcılar. Orada geçersiz bir geçiş günlüğe yazılır ve yok sayılır. Arayüzdeki kullanıcı kaynaklı her durum değişikliği force: true geçirir ve grafiği tümüyle atlar; böylece bir insan bir bileti seçicinin listelediği her duruma (failed dışındaki her durum), terminal bir durumu yeniden açmak dahil taşıyabilir. Ajanlar failed durumunu fail_ticket ile işaretler.

Bir durum her zaman kendisine geçebilir. Terminal durumların dışarı çıkan kenarı yoktur.

Kaynak İzin verilen hedefler
backlog open, cancelled
open inProgress, blocked, cancelled
inProgress blocked, inReview, done, failed, cancelled
blocked inProgress, cancelled
inReview inProgress, done, failed, cancelled
done — (terminal)
failed — (terminal)
cancelled — (terminal)

Linear’ın yerel 0–4 ölçeğinde bir tamsayı olarak depolanır. Bilinmeyen bir değer none olarak ayrıştırılır.

Öncelik Depolanan değer
none 0
urgent 1
high 2
medium 3
low 4

Bilinmeyen veya null bir depolanmış değer local olarak ayrıştırılır.

Sağlayıcı Durum
local Tamamen çalışma alanı veritabanında depolanır; varsayılan
linear Uzakta sahiplenilir, yerelde aynalanır

Eşitleme adaptörleri Linear, GitHub Issues, Jira Cloud ve ClickUp için packages/cc_infra/lib/src/tickets/sync/ altında bulunur. GitHub Issues yalnızca bir eşitleme adaptörü satıcısıdır (vendorId: github) — bir TicketProvider değeri değildir; bu yüzden çekilen bir GitHub issue, originKind: externalSync ve varsayılan provider: local ile depolanır. Satıcı eşlemesi ticket_sync_links üzerinde bulunur.

createTicket manual yazar. Bir satıcı çekmesi externalSync yazar. Devredilen alt biletler manual olarak kalır.

Değer Anlamı
manual createTicket üzerindeki varsayılan (insan, ajan ve devredilen satırlar)
externalSync Bir satıcı çekmesinde TicketSyncEngine tarafından ayarlanır

Agrega, tek bir satırda iki ayrı kaygıyı kapsar. Ayna (sağlayıcı, anahtarlar, başlık, açıklama, öncelik, etiketler, durumlar, zaman damgaları) uzak bir sağlayıcı için bir önbellektir ve bir yenileme tarafından tümüyle yeniden yazılır. Üst katman (atama, devretme, alan, üst öğe, proje, bağlı PR’lar) yalnızca Control Center’a özgüdür ve bir yenileme ona asla dokunmaz.

Alan Tür Açıklama
id String UUID v4
workspaceId String Biletin ait olduğu çalışma alanı
provider TicketProvider Kanonik veriye sahip arka uç (varsayılan local)
externalKey String? Sağlayıcıya özgü anahtar (örn. LIN-123). Yerel createTicket buraya satırın id değerini değil, ayrı bir UUID yazar
url String? Uzak sağlayıcıdaki web URL’si
title String Kısa özet; boş olamaz
description String? Daha uzun Markdown gövdesi
priority TicketPriority Varsayılan none
labels List<String> Serbest biçimli etiketler
status TicketStatus Kanonik normalleştirilmiş durum
rawStatus String? Uzak sağlayıcının yerel durum adı; kayıpsız görüntüleme için saklanır
externalSyncedAt DateTime? Son çoklu satıcı eşitlemesi; ilk eşitlemeye kadar null. Satıcı başına eşleme ticket_sync_links içinde bulunur
parentTicketId String? Devretme / iş kırılımı ağacındaki üst öğe
projectId String? Biletin ait olduğu proje; asla uzak tarafa gönderilmez
assignedAgentId String? Atanan Principal’ın kimliği (yalnızca meta veri — atama hiçbir şey göndermez)
assigneeType PrincipalType assignedAgentId değerinin adlandırdığı Principal türü — user ya da agent (varsayılan agent)
createdByType PrincipalType? Bileti oluşturan Principal türü (user ya da agent); eski/sistem satırları için null
createdById String? Oluşturan Principal’ın kimliği
assignedTeamId String? Atanan ekip (yalnızca meta veri)
delegatedByAgentId String? Bu bileti devreden ajan
delegationDepth int Devretme zincirindeki derinlik; kök 0’dır, azami derinlik sınırına göre denetlenir
delegationRootTicketId String? Devretme zincirinin kökü; kök bilet için null
spaceId String? Biletin doğduğu konuşma ya da devreden ajanın alanı
errorMessage String? status failed olduğunda ayarlanır
linkedPrIds List<String> Bu biletin bağlı olduğu PR düğüm kimlikleri
metadata Map<String, dynamic> Serbest biçimli torba
createdAt DateTime Oluşturulma zamanı
startedAt DateTime? İşin başladığı zaman
blockedAt DateTime? Biletin engellendiği zaman
cancelledAt DateTime? Biletin iptal edildiği zaman
completedAt DateTime? Biletin başarıyla tamamlandığı zaman
finishedAt DateTime? Biletin herhangi bir terminal duruma ulaştığı zaman
updatedAt DateTime Son değişiklik (ayna yenilemesi ya da üst katman değişikliği)
version int İyimser eşzamanlılık sayacı; her değişiklikte artırılır
originKind TicketOriginKind Biletin nasıl oluşturulduğu (varsayılan manual)
collaborators List<TicketCollaborator> Depo tarafından istek üzerine yüklenir

Türetilenler: isTerminal, isRemote (provider != local), isAssignedToUser ve displayKey (externalKey ?? id — bu nedenle yerel biletler satırın id değerini değil, oluşturma anındaki ayrı UUID’yi görüntüler).

Depolanan kenarlar ticket_links içindeki yönlü satırlardır:

Tür Depolama dizesi Anlamı
blocks blocks Kaynak, hedefi engeller
relatesTo relates_to Simetrik ilişki
duplicateOf duplicate_of Kaynak, hedefin kopyasıdır

Arayüzün ve ticket_relation aracının konuştuğu sözlük TicketRelationKind’tır; depolanan bir kenardan ve öznenin hangi uçta yer aldığından türetilir:

Tür Türetildiği kaynak
blockedBy Öznenin hedef olduğu bir blocks satırı
blocking Öznenin kaynak olduğu bir blocks satırı
relatedTo Bir relates_to satırı (simetrik)
duplicateOf Öznenin kaynak olduğu bir duplicate_of satırı
duplicatedBy Öznenin hedef olduğu bir duplicate_of satırı
subIssueOf Özne üzerindeki tickets.parent_ticket_id
parentOf Diğer bilet üzerindeki tickets.parent_ticket_id

Üst ve alt konu bağlantıları ticket_links satırları değildir — tickets.parent_ticket_id üzerinde bulunur.

Bu sekiz sınıf packages/cc_domain/lib/core/domain/events/ticketing_events.dart içinde bulunur. TicketStarted, TicketDelegated, TicketCollaboratorAdded veya ExternalTicketWebhookReceived yoktur.

Olay Tetiklendiği durum
TicketCreated Bilet oluşturulur
TicketAssigned Bilet bir Principal’a ya da ekibe atanır
TicketCompleted İş başarıyla tamamlanır
TicketFailed İş başarısız olur
TicketCancelled Bilet iptal edilir
TicketStatusChanged Herhangi bir durum değişikliği
TicketReassigned Bilet yeniden atanır
TicketDetailsUpdated Başlık, açıklama, öncelik veya etiketler değişir

TicketAssigned bir denetim ve bildirim sinyali ile bir pipeline tetikleyicisidir. Bir ajana atama hiçbir çalıştırma başlatmaz — assignedAgentId değerini izleyen bir bilet göndericisi yoktur. Bir ekibe atama istisnadır: TeamRoutingService ekip liderini gönderir. İşbirlikçi eklemek bir satır yazar ve hiçbir şey yayımlamaz. Bir satıcı webhook’u, bir alan olayı olmadan TicketSyncEngine üzerinden uygulanır.

TicketWorkflowService her değişikliğe sahiptir.

Mekanizma Ayrıntı
Tek darboğaz Tüm değişiklikler _mutate üzerinden yönlenir; bu metot satırı yükler ve uygulamadan önce _assertWorkspace çağırır
Çalışma alanı yalıtımı Yüklenen satırın workspaceId değeri çağıranınkiyle eşleşmediğinde _assertWorkspace bir WorkspaceMismatchException fırlatır
İyimser eşzamanlılık _mutate, az önce okuduğu version değerine ayarlanmış expectedVersion ile yazar ve ConcurrencyConflictException durumunda taze durumu yeniden okuyarak yeniden dener
Özel sahiplenme tryCheckout / releaseCheckout; checkout edilmiş bir bileti talep eden ikinci bir ajan CheckoutConflictException alır
Geçiş koruması canTransitionTo, yalnızca force false olduğunda uygulanır