跳至內容

工單與委派

工單是 Control Center 追蹤工作所用的單位。它刻意做得很_簡單_:一個標題、一段正文、一個狀態、一位負責人,以及它在樹中的位置。它不是代理實際執行的對象——代理的工作存在於對話之中,而一次執行的結構化輸出則記錄在執行記錄上。

指派只記錄歸屬,不會派發任何東西

標題為「指派只記錄歸屬,不會派發任何東西」的章節

這是關於工單最需要弄清楚的一點。

設定 assignedAgentId 會寫入一個欄位,並發佈一個 TicketAssigned 領域事件。該事件既是稽核與通知訊號,也是管線觸發器。把工單指派給代理不會啟動任何執行。 沒有任何工單派發器會監看 assignedAgentId 並喚醒該代理。

例外是團隊:當設定了 assignedTeamId 時,TeamRoutingService 會帶著運作協定與名冊派發團隊領導人。

若你想讓某個特定的代理處理某張工單,你要在對話中請它去做,或由某個管線步驟派發它,再或者由另一個代理把工作委派給它。把工單指派給某個代理然後坐等,是唯一永遠不會產生任何工作的做法。

一張工單可以純粹存在於本機,也可以由外部追蹤器支撐,而同一列記錄會同時承載這兩部分。

鏡像——供應商、外部索引鍵、URL、標題、描述、優先級、標籤、原始狀態與正規化狀態、時間戳——在工單來自遠端時充當快取。此時遠端才是事實來源,而一次重新整理會整體改寫鏡像。

覆蓋層——指派、委派、空間連結、父項、項目、已連結的 PR——只屬於 Control Center。追蹤器對它一無所知,重新整理也永遠不會觸及它。

正是這種劃分,才讓同步這件事本身變得安全:供應商拉取即使對鏡像造成破壞,也永遠不會遺失疊加其上的編排中繼資料。

生命週期圖約束的是代理,而不是你

標題為「生命週期圖約束的是代理,而不是你」的章節

狀態按 backlog → open → inProgress → inReview → done 流轉,其中 blocked 是一條側支迴圈,failed / cancelled 則是另外兩個終端狀態。

轉換圖只在代理與自動化路徑上強制執行——也就是 MCP 工具與對帳器。在該路徑上,不合法的轉換會被記錄下來並忽略,因此即使代理迷糊了,也無法把工單從終端狀態倒著走回去。

使用者在介面上驅動的每一項變更,都會傳入 force: true,完全繞過這張圖。人類可以把工單移到選擇器所列的任何狀態——包括重新開啟已是終端狀態的工單。選擇器不提供 failed;該狀態由代理透過 fail_ticket 設定。這張圖是給自動化用的防護欄,而不是關於工作允許如何推進的規定。

TicketWorkflowService 透過單一關卡掌管所有變更:它載入該列、斷言它屬於呼叫者的工作區,並以預期的 version 寫入,因此兩筆並行編輯無法靜默地互相覆寫。

完整的狀態表、轉換、欄位清單與關聯種類,請參閱工單生命週期。

每張工單都有一個 originKind。這個列舉有五個值——manual、 pipelineStep、agentDelegation、externalSync、recovery——但現時只會寫入其中兩個:manual(createTicket 的預設值,被委派的子工單也包括在內)與 externalSync(同步引擎在供應商拉取時寫入)。 TicketWorkflowService.createTicket 不接受出處參數,因此 pipelineStep、agentDelegation 與 recovery 永遠不會落到任何一列上。

委派是代理為另一個代理建立工作的地方,也是權限可能外洩之處,因此這些防護設於伺服器端的關卡,而不是寫在提示指令中。

delegate_task 會經由 TicketWorkflowService.delegateGuarded 路由,後者會從父鏈計算子工單的深度與根,然後執行全部四項 DelegationGuards 檢查:一次會超出深度上限 3 的跳躍、一次跳回鏈中已有代理的跳躍(循環偵測)、一個自主權上限(受委派者在該空間的有效層級不得高於委派者),以及一個預算額度(委派會向委派者剩餘的硬性停止預算請款,且不能額外增發)。正式環境的接線會同時提供兩個解析器連接埠。當省略 from_agent_id 時,自主權與預算檢查會略過(不設上限/沒有政策預算時亦會通過)。拒絕會以 DelegationRefusedException 拋出,其訊息會原樣送達發出委派的代理——是一次明確張揚的拒絕,而不是靜默無聲的空操作。

delegate_ticket 是較舊、不受防護的同類工具:它直接呼叫 createTicket,跳過每一道防護。請優先使用 delegate_task。

請勿把委派深度上限(在 delegate_task 鏈上為 3)與內建執行框架的子代理巢狀上限(2)混為一談。它們是針對不同機制的不同限制。

父項與子問題的關聯存放於 tickets.parent_ticket_id,由 setParent / clearParent 掌管。它們不是 ticket_links 的列,因此任何讀取工單關聯的東西,都必須合併這兩個來源。

ticket_links 存放彼此本不相關的工單之間的有向邊:

連結類型 含義
blocks 來源封鎖目標
relatesTo 兩張工單彼此相關(對稱)
duplicateOf 來源是目標的重複項

項目是以工作區為範圍、朝著共同目標為工單分組。項目只屬於 Control Center,永遠不會同步到外部供應商。

TicketCollaborator 的列,就是把多個主體掛到同一張工單上的方式,角色為 assignee、collaborator 或 reviewer。人類與代理是地位對等的列——一個 principalId 加一個 collaboratorType——既沒有代表「使用者」的哨兵值,也沒有指向這兩張表中任何一張的外鍵。

Control Center 的工單才是主記錄。刪除工單只在本機生效,因此你刪除一張由供應商支撐的工單時,追蹤器上並不會刪除它,它可能在下一次同步時重新出現。協作者與子工單會串聯。

配接器憑證會從伺服器的憑證儲存區解析(在設定中貼上的 Linear 金鑰或 GitHub 權杖,會在下一次請求時被取用;環境變數只是為這些儲存區提供初始值)。

沒有任何管線節點會建立、完成或取消工單——面板中沒有這類步驟,引擎也不會呼叫 TicketWorkflowService。管線觸發器仍然可以因 TicketAssigned、TicketCompleted、 TicketFailed 或 TicketCancelled 而觸發(EventPayloadMapper 實際對應的工單事件正是這四個)。工單上沒有 pipelineRunId 欄位;管線的耦合關係存在於代理的執行記錄上。