Vòng đời phiếu
Trạng thái phiếu
Phần tiêu đề “Trạng thái phiếu”| Trạng thái | Chuỗi lưu trữ | Mô tả |
|---|---|---|
backlog |
backlog |
Đã ghi nhận, chưa được phân loại vào hàng đợi đang chạy |
open |
open |
Đã phân loại và sẵn sàng để làm, chưa bắt đầu |
inProgress |
inProgress |
Đang được xử lý |
blocked |
blocked |
Đã bắt đầu nhưng bị chặn bởi một thứ gì đó bên ngoài |
inReview |
inReview |
Đã xong việc, đang chờ đánh giá |
done |
done |
Hoàn tất thành công (trạng thái kết thúc) |
failed |
failed |
Kết thúc với lỗi (trạng thái kết thúc) |
cancelled |
cancelled |
Bị bỏ dở (trạng thái kết thúc) |
Các giá trị trạng thái được lưu ở dạng camelCase (inProgress, inReview), không bao giờ là in_progress. Một giá trị lưu là null được phân tích thành open; một giá trị không xác định sẽ ném lỗi thay vì ép kiểu.
tryParseLoose chấp nhận các bí danh do agent cung cấp, bỏ qua chữ hoa chữ thường và - / _ / dấu cách:
| Trạng thái | Bí danh được chấp nhận |
|---|---|
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 |
Chuyển trạng thái
Phần tiêu đề “Chuyển trạng thái”backlog ──→ open ──→ inProgress ──→ inReview ──→ done │ │ │ │ └──→ failed ┘ └──→ blocked ──→ inProgress
Any non-terminal status ──→ cancelled; inReview ──→ failedĐồ thị này chỉ ràng buộc agent và tự động hóa. TicketWorkflowService.transitionStatus kiểm tra nó khi force là false — tức các công cụ MCP và các bộ đối soát. Một chuyển trạng thái không hợp lệ ở đó sẽ bị ghi log và bỏ qua. Mọi thay đổi trạng thái do người dùng thực hiện trong giao diện đều truyền force: true và bỏ qua hoàn toàn đồ thị, nên con người có thể chuyển một phiếu sang bất kỳ trạng thái nào mà hộp chọn liệt kê (mọi trạng thái trừ failed), kể cả mở lại một trạng thái kết thúc. Agent đánh dấu failed bằng fail_ticket.
Một trạng thái luôn có thể chuyển sang chính nó. Các trạng thái kết thúc không có cạnh đi ra.
| Từ | Đích được phép |
|---|---|
backlog |
open, cancelled |
open |
inProgress, blocked, cancelled |
inProgress |
blocked, inReview, done, failed, cancelled |
blocked |
inProgress, cancelled |
inReview |
inProgress, done, failed, cancelled |
done |
— (trạng thái kết thúc) |
failed |
— (trạng thái kết thúc) |
cancelled |
— (trạng thái kết thúc) |
Độ ưu tiên của phiếu
Phần tiêu đề “Độ ưu tiên của phiếu”Được lưu dưới dạng số nguyên theo thang 0–4 gốc của Linear. Một giá trị không xác định được phân tích thành none.
| Độ ưu tiên | Lưu dưới dạng |
|---|---|
none |
0 |
urgent |
1 |
high |
2 |
medium |
3 |
low |
4 |
Nhà cung cấp phiếu
Phần tiêu đề “Nhà cung cấp phiếu”Một giá trị lưu không xác định hoặc null được phân tích thành local.
| Nhà cung cấp | Trạng thái |
|---|---|
local |
Được lưu hoàn toàn trong cơ sở dữ liệu không gian làm việc; mặc định |
linear |
Do hệ thống từ xa sở hữu, được sao gương cục bộ |
Các adapter đồng bộ nằm trong packages/cc_infra/lib/src/tickets/sync/ cho Linear,
GitHub Issues, Jira Cloud và ClickUp. GitHub Issues chỉ là một vendor của adapter
đồng bộ (vendorId: github) — nó không phải là một giá trị TicketProvider, nên
một issue GitHub được kéo về sẽ được lưu với originKind: externalSync và
provider: local mặc định. Ánh xạ vendor nằm trên ticket_sync_links.
Nguồn gốc phiếu
Phần tiêu đề “Nguồn gốc phiếu”createTicket ghi manual. Một lần kéo từ vendor ghi externalSync. Các phiếu
con được ủy thác vẫn giữ manual.
| Giá trị | Ý nghĩa |
|---|---|
manual |
Mặc định trên createTicket (hàng do con người, agent và ủy thác tạo) |
externalSync |
Được TicketSyncEngine đặt khi kéo từ vendor |
Các trường của phiếu
Phần tiêu đề “Các trường của phiếu”Thực thể tổng hợp trải hai mối quan tâm trên cùng một hàng. Bản gương (nhà cung cấp, khóa, tiêu đề, mô tả, mức ưu tiên, nhãn, trạng thái, dấu thời gian) là bộ đệm cho một nhà cung cấp từ xa và bị một lần làm mới ghi lại toàn bộ. Lớp phủ (phân công, ủy thác, space, phiếu cha, dự án, các PR được liên kết) chỉ thuộc về Control Center và một lần làm mới không bao giờ chạm tới nó.
| Trường | Kiểu | Mô tả |
|---|---|---|
id |
String |
UUID v4 |
workspaceId |
String |
Không gian làm việc sở hữu |
provider |
TicketProvider |
Backend sở hữu dữ liệu chuẩn tắc (mặc định local) |
externalKey |
String? |
Khóa gốc của nhà cung cấp (ví dụ LIN-123). createTicket cục bộ ghi một UUID riêng vào đây, chứ không phải id của hàng |
url |
String? |
URL web trên nhà cung cấp từ xa |
title |
String |
Tóm tắt ngắn; không được để trống |
description |
String? |
Nội dung Markdown dài hơn |
priority |
TicketPriority |
Mặc định none |
labels |
List<String> |
Nhãn tự do |
status |
TicketStatus |
Trạng thái chuẩn hóa chuẩn tắc |
rawStatus |
String? |
Tên trạng thái gốc của nhà cung cấp từ xa, được giữ để hiển thị không mất mát |
externalSyncedAt |
DateTime? |
Lần đồng bộ đa vendor gần nhất; null cho đến lần đầu tiên. Ánh xạ theo từng vendor nằm trong ticket_sync_links |
parentTicketId |
String? |
Phiếu cha trong cây ủy thác / chia nhỏ |
projectId |
String? |
Dự án sở hữu; không bao giờ được đẩy lên hệ thống từ xa |
assignedAgentId |
String? |
Id của chủ thể được gán (chỉ là siêu dữ liệu — gán không điều phối gì cả) |
assigneeType |
PrincipalType |
Loại chủ thể mà assignedAgentId chỉ tới — user hoặc agent (mặc định agent) |
createdByType |
PrincipalType? |
Loại chủ thể đã tạo phiếu (user hoặc agent); null với các hàng cũ/hệ thống |
createdById |
String? |
Id của chủ thể đã tạo |
assignedTeamId |
String? |
Đội được gán (chỉ là siêu dữ liệu) |
delegatedByAgentId |
String? |
Agent đã ủy thác phiếu này |
delegationDepth |
int |
Độ sâu trong chuỗi ủy thác; gốc là 0, được kiểm tra với giới hạn độ sâu tối đa |
delegationRootTicketId |
String? |
Gốc của chuỗi ủy thác; null với một phiếu gốc |
spaceId |
String? |
Cuộc hội thoại mà phiếu được tách ra từ đó, hoặc space của agent ủy thác |
errorMessage |
String? |
Được đặt khi status là failed |
linkedPrIds |
List<String> |
Id nút PR mà phiếu này được liên kết tới |
metadata |
Map<String, dynamic> |
Túi dữ liệu tự do |
createdAt |
DateTime |
Thời điểm tạo |
startedAt |
DateTime? |
Khi công việc bắt đầu |
blockedAt |
DateTime? |
Khi phiếu bị chặn |
cancelledAt |
DateTime? |
Khi phiếu bị hủy |
completedAt |
DateTime? |
Khi phiếu hoàn tất thành công |
finishedAt |
DateTime? |
Khi phiếu đạt tới bất kỳ trạng thái kết thúc nào |
updatedAt |
DateTime |
Lần thay đổi gần nhất (làm mới bản gương hoặc thay đổi lớp phủ) |
version |
int |
Bộ đếm đồng thời lạc quan, tăng lên sau mỗi thay đổi |
originKind |
TicketOriginKind |
Cách phiếu được tạo (mặc định manual) |
collaborators |
List<TicketCollaborator> |
Được repository nạp theo yêu cầu |
Suy ra: isTerminal, isRemote (provider != local), isAssignedToUser và displayKey (externalKey ?? id — do đó phiếu cục bộ hiển thị UUID riêng được tạo lúc tạo phiếu, chứ không phải id của hàng).
Quan hệ phiếu
Phần tiêu đề “Quan hệ phiếu”Các cạnh được lưu là những hàng có hướng trong ticket_links:
| Loại | Chuỗi lưu trữ | Ý nghĩa |
|---|---|---|
blocks |
blocks |
Phiếu nguồn chặn phiếu đích |
relatesTo |
relates_to |
Quan hệ đối xứng |
duplicateOf |
duplicate_of |
Phiếu nguồn là bản trùng của phiếu đích |
Từ vựng mà giao diện và ticket_relation dùng là TicketRelationKind, được suy ra từ một cạnh đã lưu cộng với việc chủ thể nằm ở đầu nào của cạnh đó:
| Loại | Suy ra từ |
|---|---|
blockedBy |
Một hàng blocks trong đó chủ thể là phiếu đích |
blocking |
Một hàng blocks trong đó chủ thể là phiếu nguồn |
relatedTo |
Một hàng relates_to (đối xứng) |
duplicateOf |
Một hàng duplicate_of trong đó chủ thể là phiếu nguồn |
duplicatedBy |
Một hàng duplicate_of trong đó chủ thể là phiếu đích |
subIssueOf |
tickets.parent_ticket_id trên chủ thể |
parentOf |
tickets.parent_ticket_id trên phiếu kia |
Các liên kết cha và vấn đề con không phải là hàng ticket_links — chúng nằm trên tickets.parent_ticket_id.
Sự kiện miền
Phần tiêu đề “Sự kiện miền”Tám lớp này nằm trong packages/cc_domain/lib/core/domain/events/ticketing_events.dart. Không có TicketStarted, TicketDelegated, TicketCollaboratorAdded hay ExternalTicketWebhookReceived.
| Sự kiện | Kích hoạt khi |
|---|---|
TicketCreated |
Phiếu được tạo |
TicketAssigned |
Phiếu được gán cho một chủ thể hoặc một đội |
TicketCompleted |
Công việc kết thúc thành công |
TicketFailed |
Công việc thất bại |
TicketCancelled |
Phiếu bị hủy |
TicketStatusChanged |
Mọi thay đổi trạng thái |
TicketReassigned |
Phiếu được gán lại |
TicketDetailsUpdated |
Tiêu đề, mô tả, mức ưu tiên hoặc nhãn thay đổi |
TicketAssigned là một tín hiệu kiểm toán và thông báo, đồng thời là một trình kích hoạt quy trình. Gán cho một agent không khởi động lần chạy nào — không có bộ điều phối phiếu nào theo dõi assignedAgentId. Gán cho một đội là ngoại lệ: TeamRoutingService điều phối trưởng đội. Thêm một cộng tác viên chỉ ghi một hàng và không phát ra gì. Một webhook từ vendor được áp dụng qua TicketSyncEngine mà không có sự kiện miền nào.
Điểm nghẽn thay đổi
Phần tiêu đề “Điểm nghẽn thay đổi”TicketWorkflowService sở hữu mọi thay đổi.
| Cơ chế | Chi tiết |
|---|---|
| Điểm nghẽn duy nhất | Mọi thay đổi đều đi qua _mutate, hàm này nạp hàng và gọi _assertWorkspace trước khi áp dụng |
| Cô lập không gian làm việc | _assertWorkspace ném WorkspaceMismatchException khi workspaceId của hàng được nạp không khớp với workspaceId của bên gọi |
| Đồng thời lạc quan | _mutate ghi với expectedVersion được đặt bằng version mà nó vừa đọc và thử lại khi gặp ConcurrencyConflictException bằng cách đọc lại trạng thái mới |
| Giành quyền độc quyền | tryCheckout / releaseCheckout; agent thứ hai giành một phiếu đã được checkout sẽ nhận CheckoutConflictException |
| Chốt chuyển trạng thái | canTransitionTo, chỉ được áp dụng khi force là false |