Kitaran hayat tiket
Status tiket
Bahagian bertajuk “Status tiket”| Status | Rentetan storan | Perihalan |
|---|---|---|
backlog |
backlog |
Direkodkan, belum melalui triage ke dalam baris gilir aktif |
open |
open |
Telah melalui triage dan sedia dikerjakan, belum bermula |
inProgress |
inProgress |
Sedang dikerjakan secara aktif |
blocked |
blocked |
Sudah bermula tetapi terhalang oleh sesuatu yang luaran |
inReview |
inReview |
Kerja selesai, menunggu semakan |
done |
done |
Selesai dengan jayanya (terminal) |
failed |
failed |
Selesai dengan ralat (terminal) |
cancelled |
cancelled |
Ditinggalkan (terminal) |
Nilai status disimpan dalam bentuk camelCase (inProgress, inReview), tidak pernah in_progress. Nilai tersimpan yang null dihuraikan sebagai open; nilai yang tidak dikenali melontar ralat dan tidak dipaksakan.
tryParseLoose menerima alias yang dibekalkan ejen, mengabaikan kepekaan huruf besar/kecil dan aksara - / _ / ruang:
| Status | Alias yang diterima |
|---|---|
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 |
Peralihan status
Bahagian bertajuk “Peralihan status”backlog ──→ open ──→ inProgress ──→ inReview ──→ done │ │ │ │ └──→ failed ┘ └──→ blocked ──→ inProgress
Any non-terminal status ──→ cancelled; inReview ──→ failedGraf ini mengikat ejen dan automasi sahaja. TicketWorkflowService.transitionStatus menyemaknya apabila force ialah false — alat MCP dan penyelaras. Peralihan haram di situ dilog dan diabaikan. Setiap perubahan status yang dipacu pengguna dalam UI menghantar force: true dan melangkau graf itu sepenuhnya, jadi manusia boleh memindahkan tiket ke mana-mana status yang disenaraikan oleh pemilih (setiap status kecuali failed), termasuk membuka semula tiket yang berada dalam keadaan terminal. Ejen menandakan failed dengan fail_ticket.
Status boleh sentiasa beralih kepada dirinya sendiri. Keadaan terminal tiada tepi keluar.
| Daripada | Sasaran yang dibenarkan |
|---|---|
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) |
Keutamaan tiket
Bahagian bertajuk “Keutamaan tiket”Disimpan sebagai integer pada skala asli Linear 0–4. Nilai yang tidak dikenali dihuraikan sebagai none.
| Keutamaan | Disimpan sebagai |
|---|---|
none |
0 |
urgent |
1 |
high |
2 |
medium |
3 |
low |
4 |
Penyedia tiket
Bahagian bertajuk “Penyedia tiket”Nilai tersimpan yang tidak dikenali atau null dihuraikan sebagai local.
| Penyedia | Status |
|---|---|
local |
Disimpan sepenuhnya dalam pangkalan data ruang kerja; lalai |
linear |
Dimiliki jauh, dicerminkan secara tempatan |
Penyesuai penyegerakan terletak di bawah packages/cc_infra/lib/src/tickets/sync/ untuk
Linear, GitHub Issues, Jira Cloud dan ClickUp. GitHub Issues hanyalah vendor
penyesuai penyegerakan (vendorId: github) — ia bukan nilai TicketProvider,
jadi isu GitHub yang ditarik disimpan dengan originKind: externalSync dan
provider: local lalai. Pemetaan vendor terletak pada ticket_sync_links.
Asal usul tiket
Bahagian bertajuk “Asal usul tiket”createTicket menulis manual. Tarikan vendor menulis externalSync. Anak yang
diwakilkan kekal manual.
| Nilai | Maksud |
|---|---|
manual |
Lalai pada createTicket (baris manusia, ejen dan yang diwakilkan) |
externalSync |
Ditetapkan oleh TicketSyncEngine pada tarikan vendor |
Medan tiket
Bahagian bertajuk “Medan tiket”Agregat ini merangkumi dua kebimbangan pada satu baris. Cermin (penyedia, kunci, tajuk, perihalan, keutamaan, label, status, cap masa) ialah cache untuk penyedia jauh dan ditulis semula sepenuhnya oleh penyegaran. Tindanan (penugasan, perwakilan, ruang, induk, projek, PR berpaut) hanya milik Control Center dan penyegaran tidak pernah menyentuhnya.
| Medan | Jenis | Perihalan |
|---|---|---|
id |
String |
UUID v4 |
workspaceId |
String |
Ruang kerja pemilik |
provider |
TicketProvider |
Bahagian belakang yang memiliki data kanonik (lalai local) |
externalKey |
String? |
Kunci asli penyedia (cth. LIN-123). createTicket tempatan menulis UUID berasingan di sini, bukan id baris |
url |
String? |
URL web pada penyedia jauh |
title |
String |
Ringkasan pendek; tidak boleh kosong |
description |
String? |
Badan Markdown yang lebih panjang |
priority |
TicketPriority |
Lalai none |
labels |
List<String> |
Label bentuk bebas |
status |
TicketStatus |
Status ternormal yang kanonik |
rawStatus |
String? |
Nama keadaan asli penyedia jauh, disimpan untuk paparan tanpa kehilangan |
externalSyncedAt |
DateTime? |
Penyegerakan berbilang vendor terakhir; null sehingga yang pertama. Pemetaan setiap vendor terletak dalam ticket_sync_links |
parentTicketId |
String? |
Induk dalam pokok perwakilan / pecahan |
projectId |
String? |
Projek pemilik; tidak pernah ditolak ke jauh |
assignedAgentId |
String? |
Id prinsipal yang ditugaskan (metadata sahaja — menugaskan tidak menghantar apa-apa) |
assigneeType |
PrincipalType |
Jenis prinsipal yang dinamakan oleh assignedAgentId — user atau agent (lalai agent) |
createdByType |
PrincipalType? |
Jenis prinsipal yang mencipta tiket (user atau agent); null untuk baris legasi/sistem |
createdById |
String? |
Id prinsipal pencipta |
assignedTeamId |
String? |
Pasukan yang ditugaskan (metadata sahaja) |
delegatedByAgentId |
String? |
Ejen yang mewakilkan tiket ini |
delegationDepth |
int |
Kedalaman dalam rantaian perwakilan; akar ialah 0, disemak terhadap siling kedalaman maksimum |
delegationRootTicketId |
String? |
Akar rantaian perwakilan; null untuk tiket akar |
spaceId |
String? |
Perbualan tempat tiket ini dipecahkan, atau ruang ejen yang mewakilkan |
errorMessage |
String? |
Ditetapkan apabila status ialah failed |
linkedPrIds |
List<String> |
Id nod PR yang dipautkan pada tiket ini |
metadata |
Map<String, dynamic> |
Beg bentuk bebas |
createdAt |
DateTime |
Masa penciptaan |
startedAt |
DateTime? |
Apabila kerja bermula |
blockedAt |
DateTime? |
Apabila tiket terhalang |
cancelledAt |
DateTime? |
Apabila tiket dibatalkan |
completedAt |
DateTime? |
Apabila tiket selesai dengan jayanya |
finishedAt |
DateTime? |
Apabila tiket mencapai mana-mana keadaan terminal |
updatedAt |
DateTime |
Mutasi terakhir (penyegaran cermin atau perubahan tindanan) |
version |
int |
Pembilang konkurensi optimistik, dinaikkan pada setiap mutasi |
originKind |
TicketOriginKind |
Bagaimana tiket dicipta (lalai manual) |
collaborators |
List<TicketCollaborator> |
Dihidratkan oleh repositori atas permintaan |
Terbitan: isTerminal, isRemote (provider != local), isAssignedToUser dan displayKey (externalKey ?? id — maka tiket tempatan memaparkan UUID berasingan yang dicipta pada masa penciptaan, bukan id baris).
Hubungan tiket
Bahagian bertajuk “Hubungan tiket”Tepi yang disimpan ialah baris berarah dalam ticket_links:
| Jenis | Rentetan storan | Maksud |
|---|---|---|
blocks |
blocks |
Sumber menyekat sasaran |
relatesTo |
relates_to |
Hubungan simetri |
duplicateOf |
duplicate_of |
Sumber ialah pendua kepada sasaran |
Perbendaharaan kata yang digunakan oleh UI dan ticket_relation ialah TicketRelationKind, diterbitkan daripada tepi yang disimpan serta hujung mana subjek itu berada:
| Jenis | Diterbitkan daripada |
|---|---|
blockedBy |
Baris blocks yang subjeknya ialah sasaran |
blocking |
Baris blocks yang subjeknya ialah sumber |
relatedTo |
Baris relates_to (simetri) |
duplicateOf |
Baris duplicate_of yang subjeknya ialah sumber |
duplicatedBy |
Baris duplicate_of yang subjeknya ialah sasaran |
subIssueOf |
tickets.parent_ticket_id pada subjek |
parentOf |
tickets.parent_ticket_id pada tiket yang satu lagi |
Pautan induk dan sub-isu bukan baris ticket_links — ia terletak pada tickets.parent_ticket_id.
Acara domain
Bahagian bertajuk “Acara domain”Lapan kelas ini terletak dalam packages/cc_domain/lib/core/domain/events/ticketing_events.dart. Tiada TicketStarted, TicketDelegated, TicketCollaboratorAdded, atau ExternalTicketWebhookReceived.
| Acara | Dicetuskan apabila |
|---|---|
TicketCreated |
Tiket dicipta |
TicketAssigned |
Tiket ditugaskan kepada prinsipal atau pasukan |
TicketCompleted |
Kerja selesai dengan jayanya |
TicketFailed |
Kerja gagal |
TicketCancelled |
Tiket dibatalkan |
TicketStatusChanged |
Sebarang perubahan status |
TicketReassigned |
Tiket ditugaskan semula |
TicketDetailsUpdated |
Tajuk, perihalan, keutamaan atau label berubah |
TicketAssigned ialah isyarat audit dan pemberitahuan serta pencetus pipeline. Penugasan kepada ejen tidak memulakan sebarang larian — tiada penghantar tiket yang memantau assignedAgentId. Penugasan kepada pasukan ialah pengecualian: TeamRoutingService menghantar ketua pasukan. Menambah kolaborator menulis satu baris dan tidak menerbitkan apa-apa. Webhook vendor digunakan melalui TicketSyncEngine tanpa acara domain.
Titik kawalan mutasi
Bahagian bertajuk “Titik kawalan mutasi”TicketWorkflowService memiliki setiap mutasi.
| Mekanisme | Butiran |
|---|---|
| Titik kawalan tunggal | Semua mutasi dihalakan melalui _mutate, yang memuatkan baris itu dan memanggil _assertWorkspace sebelum menerapkannya |
| Pengasingan ruang kerja | _assertWorkspace melontar WorkspaceMismatchException apabila workspaceId baris yang dimuatkan tidak sepadan dengan pemanggil |
| Konkurensi optimistik | _mutate menulis dengan expectedVersion ditetapkan kepada version yang baru dibacanya dan mencuba semula pada ConcurrencyConflictException dengan membaca semula keadaan terkini |
| Tuntutan eksklusif | tryCheckout / releaseCheckout; ejen kedua yang menuntut tiket yang sudah di-checkout mendapat CheckoutConflictException |
| Pengawal peralihan | canTransitionTo, digunakan hanya apabila force ialah false |