Przejdź do głównej zawartości

Zgłoszenia i delegowanie

Zgłoszenie to jednostka pracy, którą śledzi Control Center. To celowo głupi artefakt: tytuł, treść, status, właściciel i miejsce w drzewie. Nie jest tym, względem czego agenci wykonują pracę — praca agenta żyje w rozmowach, a ustrukturyzowany wynik uruchomienia trafia do dziennika uruchomień.

To najważniejsza rzecz, którą trzeba zrozumieć w kwestii zgłoszeń.

Ustawienie assignedAgentId zapisuje pole i publikuje TicketAssigned zdarzenie domenowe. To zdarzenie 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 i budzi tego agenta.

Wyjątkiem jest zespół: gdy ustawiono assignedTeamId, TeamRoutingService wysyła lidera zespołu z protokołem operacyjnym i składem.

Jeśli chcesz, aby konkretny agent popracował nad zgłoszeniem, poproś go o to w rozmowie — albo wyśle je krok potoku, albo deleguje mu je inny agent. Przypisanie zgłoszenia do agenta i czekanie to jedyna metoda, która nigdy nie przyniesie pracy.

Zgłoszenie może być czysto lokalne albo wsparte zewnętrznym trackerem, a oba te elementy niesie w jednym wierszu.

Kopia lustrzana — dostawca, klucz zewnętrzny, URL, tytuł, opis, priorytet, etykiety, surowy i znormalizowany status, znaczniki czasu — jest cache’em, gdy zgłoszenie jest zdalne. Tam to system zdalny jest źródłem prawdy, a odświeżenie przepisuje kopię lustrzaną w całości.

Nakładka — przypisanie, delegowanie, powiązanie z przestrzenią, element nadrzędny, projekt, powiązane PR-y — należy wyłącznie do Control Center. Tracker nie wie o niej nic, a odświeżenie nigdy jej nie dotyka.

Właśnie ten podział sprawia, że synchronizacja jest w ogóle bezpieczna: pobranie od dostawcy może być niszczące dla kopii lustrzanej, nie gubiąc przy tym metadanych orkiestracji nałożonych na wierzch.

Statusy przebiegają tak: backlog → open → inProgress → inReview → done, gdzie blocked to pętla boczna, a failed / cancelled to pozostałe stany końcowe.

Graf przejść jest egzekwowany tylko na ścieżce agenta i automatyzacji — narzędzia MCP i reconcillery. Niedozwolone przejście jest tam logowane i ignorowane, więc zagubiony agent nie może przeprowadzić zgłoszenia wstecz ze stanu końcowego.

Każda zmiana wywołana przez użytkownika w interfejsie przekazuje force: true i całkowicie omija graf. Człowiek może przenieść zgłoszenie do dowolnego statusu z listy selektora — w tym ponownie otworzyć status końcowy. Selektor nie oferuje failed; agent ustawia go przez fail_ticket. Graf to bariera ochronna dla automatyzacji, a nie reguła mówiąca, jak może toczyć się praca.

TicketWorkflowService włada każdą mutacją przez pojedynczy punkt kontrolny, który wczytuje wiersz, sprawdza, czy należy do obszaru roboczego wywołującego, i zapisuje z oczekiwaną version, dzięki czemu dwie równoległe edycje nie mogą się po cichu nadpisać.

Pełną tabelę statusów, przejścia, listę pól i rodzaje relacji znajdziesz na stronie Cykl życia zgłoszenia.

Każde zgłoszenie ma originKind. Ten enum ma pięć wartości — manual, pipelineStep, agentDelegation, externalSync, recovery — ale dziś zapisywane są tylko dwie: manual (wartość domyślna w createTicket, także dla delegowanych zgłoszeń potomnych) i externalSync (silnik synchronizacji, przy pobraniu od dostawcy). TicketWorkflowService.createTicket nie przyjmuje argumentu pochodzenia, więc pipelineStep, agentDelegation i recovery nigdy nie trafiają do wiersza.

Delegowanie to miejsce, w którym agent tworzy pracę dla innego agenta, i zarazem miejsce, w którym mogłyby wyciekać uprawnienia, dlatego zabezpieczenia żyją po stronie serwera, w punkcie kontrolnym, a nie w instrukcjach promptu.

delegate_task przechodzi przez TicketWorkflowService.delegateGuarded, który oblicza głębokość i korzeń zgłoszenia potomnego na podstawie łańcucha nadrzędnego, a następnie wykonuje wszystkie cztery kontrole DelegationGuards: przeskok, który przekroczyłby pułap głębokości 3, przeskok z powrotem do agenta znajdującego się już w łańcuchu (wykrywanie cykli), pułap autonomii (efektywny poziom delegowanego w przestrzeni nie może przekraczać poziomu delegującego) oraz kopertę budżetową (delegowanie obciąża pozostały budżet twardego zatrzymania delegującego i nie może tworzyć nowego). Produkcyjne okablowanie dostarcza oba porty resolverów. Autonomia i budżet są pomijane, gdy pominięto from_agent_id (budżet nieograniczony / bez polityki również przechodzi). Odmowa jest zgłaszana jako DelegationRefusedException, której komunikat dociera do delegującego agenta dosłownie — głośna odmowa, nigdy ciche działanie bez efektu.

delegate_ticket to starsze, niezabezpieczone rodzeństwo: wywołuje createTicket bezpośrednio i pomija każde zabezpieczenie. Preferuj delegate_task.

Nie myl pułapu głębokości delegowania (3, w łańcuchach delegate_task) z limitem zagnieżdżania subagentów wbudowanego harnessa (2). To różne limity różnych mechanizmów.

Relacje nadrzędne i podzgłoszenia żyją w tickets.parent_ticket_id, którym zarządzają setParent / clearParent. To nie wiersze ticket_links, więc wszystko, co czyta relacje zgłoszenia, musi scalać oba źródła.

ticket_links przechowuje skierowane krawędzie między skądinąd niepowiązanymi zgłoszeniami:

Typ powiązania Znaczenie
blocks Źródło blokuje cel
relatesTo Oba zgłoszenia są powiązane (symetrycznie)
duplicateOf Źródło jest duplikatem celu

Projekt to ugrupowanie zgłoszeń w obrębie obszaru roboczego, dążące do wspólnego celu. Projekty należą wyłącznie do Control Center i nigdy nie synchronizują się z zewnętrznym dostawcą.

Wiersze TicketCollaborator to sposób przypisania do zgłoszenia więcej niż jednego podmiotu, w roli assignee, collaborator lub reviewer. Ludzie i agenci to równorzędne wiersze — principalId plus collaboratorType — bez wartości sentinelowej dla „użytkownika” i bez klucza obcego do którejkolwiek z tych tabel.

Zgłoszenie w Control Center jest nadrzędne. Usunięcie zgłoszenia jest tylko lokalne, więc zgłoszenie oparte na dostawcy, które usuniesz, nie zostaje usunięte w trackerze i może powrócić przy następnej synchronizacji. Współpracownicy i zgłoszenia potomne są usuwane kaskadowo.

Poświadczenia adaptera są rozwiązywane z magazynów poświadczeń serwera (klucz Linear lub token GitHub wklejony w Ustawieniach zostaje podjęty przy następnym żądaniu; środowisko tylko zasiewa te magazyny).

Żaden węzeł potoku nie tworzy, nie kończy ani nie anuluje zgłoszeń — paleta nie ma takiego kroku, a silnik nie wywołuje TicketWorkflowService. Wyzwalacz potoku nadal może zadziałać na TicketAssigned, TicketCompleted, TicketFailed lub TicketCancelled (te cztery to zdarzenia zgłoszeń, które EventPayloadMapper faktycznie mapuje). W zgłoszeniu nie ma kolumny pipelineRunId; sprzężenie z potokami żyje w dzienniku uruchomień agenta.