Přeskočit na obsah

Pipelines a automatizace

Pipeline tvoří deterministickou polovinu Control Center. Agent rozhoduje, co řekne; pipeline rozhoduje, co se stane dál, pokaždé stejně. Pipeline je DAG kroků, které umí odeslat agenty, spustit skripty, větvit se podle podmínky, rozvětvit se nad kolekcí a předávat si data — uložená, obnovitelná a s vyčíslenými náklady.

Jsou tu ze tří důvodů: zřetězit opakovaný vícekrokový postup, sladit několik agentů za sebou nebo paralelně a reagovat na něco, co se stalo, i když u toho nikdo není.

Šablona (PipelineDefinition) je deklarativní DAG: kroky, deklarované vstupy a konfigurace. Leží ve vlastní databázi pracovního prostoru. Běh (PipelineRun) je jedno provedení té šablony. Nese proměnlivý společný stav, součty nákladů a tokenů a stav každého kroku.

Jedna šablona má mnoho běhů. Běhy přežijí restart: engine rozjeté běhy znovu načte a naváže tam, kde se zastavily.

Dvě pojistky nechají spadnout celý běh, místo aby krok obnovily. Obnovení by bylo horší než zastavení:

  • Krok, který je suspended déle než suspendedStepTimeout (výchozí 24 hodin), čeká na tickety, které se nikdy nedostanou do koncového stavu, a proto spadne, aby se běh uvolnil. Výjimkou je extras['awaitApproval'] == true. To je brána částečného schválení orchestration.awaitApproval. human.gate výjimku nemá.
  • Krok s extras: {'idempotent': false}, který běžel, když se server zastavil, už mohl uplatnit vedlejší účinek (squash merge, úklid worktree). Druhé spuštění by ho mohlo uplatnit znovu, takže ho engine nechá spadnout a opakování nechá na tobě.

Druh plánuje, tělo pracuje

Sekce “Druh plánuje, tělo pracuje”

Krok má dvě na sobě nezávislé části. Právě to drží engine malý.

Druh (StepKind) říká enginu, kdy se krok vůči svým předchůdcům stane spustitelným. To je jediné, co plánovač potřebuje vědět. Druhů je šest: trigger, listen, join, router, forEach a terminal. Tělo (bodyKey) je práce, kterou krok udělá, jakmile je naplánovaný. Těla jsou uzávěry registrované podle klíče při startu serveru, takže mnoho kroků různých druhů sdílí jedno tělo: několik kroků listen spouští totéž conversation.promptAgent.

Sémantika plánování žije v šesti druzích, takže katalog chování roste, aniž by někdo sahal na plánovač. Úplný katalog druhů, těl a jejich konfigurace je na stránce Typy kroků pipeline.

Než šablonu napíšeš ručně, z registru plynou dvě věci:

  • Krok, jehož bodyKey není registrovaný, při načtení šablony varuje a pak se nikdy nespustí. Za běhu nic hlasitě neselže. Kroky trigger a terminal tohle varování nemají: krok trigger pořád spustí prázdné tělo pipeline.trigger, aby se navazující posluchači rozběhli; krok terminal tělo nemá a je zarážka plánovače.
  • Klíče v mapě extras uzlu platí jen při přesné shodě, jinak se tiše ignorují. Jen extras['spaceId'] vloží práci kroku agenta do existující konverzace. extras['mode'] (chat / plan / review) se čte na uzlu, který prostor otevírá (messaging.createSpace, výchozí review). Pozdější krok agenta nemůže konverzaci, do které vstoupil, znovu nastavit oprávnění. Jakékoli jiné hláskování obou klíčů se ignoruje.

Kroky se navzájem nevolají. Čtou ze společného stavu na běhu a zapisují do něj: krok si podle klíče přečte vstupy, provede se a výstup zapíše zpět pod vlastní outputKey. StateReducer sloučí souběžné zápisy, když paralelní větve míří na stejný klíč, a TemplateRenderer z téhož stavu dosazuje zástupné symboly {{...}} v promptech a skriptech.

Proto se pipeline dá zpětně prohlédnout. Společný stav je celý příběh běhu.

Řádky PipelineTrigger říkají, kdy se šablona spustí sama. Druhy jsou čtyři:

Spouštěč Běh se spustí, když
Doménová událost Vyletí odpovídající doménová událost, třeba PullRequestPublished nebo TicketAssigned
Plán Nastane výraz cronu nebo intervalu
Ručně Spustíš ho sám. Zapnutý ruční spouštěč je to, co šablonu zařadí do výběru pro spuštění
Webhook Externí systém pošle POST na /webhooks/<token> na HTTP portu serveru

Spouštěče událostí jsou uzavřená množina: dispečer zná 16 typů událostí a nabízí je ve výběru (EventPayloadMapper.knownEventTypes). Nic jiného pipeline nespustí. Čtrnáct z těch 16 má mapování payloadu. Dva — TicketCreated a TicketStatusChanged — nemají žádné, takže spouštěč na kterémkoli z nich zůstane zapnutý a nikdy nevyletí. Úplný seznam je na stránce Doménové události.

Token webhooku je zároveň tajemství HMAC: hlavička požadavku X-Hub-Signature-256: sha256=<hex> se ověřuje proti HMAC-SHA256(body, token), neověřená doručení se odmítnou a nejdou zopakovat a duplicity zahazuje dedupe_key. Řádky spouštěčů jsou jedinečné na (pracovní prostor, typ události, šablona), takže šablona může mít nejvýš jeden spouštěč webhooku a jeden spouštěč na každý typ doménové události.

Vestavěné šablony zakládají ruční a událostní spouštěče zapnuté. Plánované spouštěče se zakládají vypnuté, takže opakovaný průchod si vždy zapínáš sám.

Šablony, které se dodávají vypnuté

Sekce “Šablony, které se dodávají vypnuté”

Do každého pracovního prostoru se založí třináct šablon pipeline a osm z nich se dodává vypnutých: external_pr_welcome, cross_review, ticket_to_pr, pr_triage, pre_merge_gate, release_notes, dep_audit a pr_digest.

Tohle lidi překvapí. Jejich spouštěče se zakládají zapnuté, ale PipelineEngine.start vypnutou šablonu odmítne a vrátí null, takže spouštěč vystřelí do prázdna a žádný běh se neobjeví. Přepínač je šablona, ne spouštěč. Zapni ji v Nastavení → Pracovní prostor → Šablony pipeline, než budeš čekat, že některá z těch osmi něco udělá.

Když se pracovní prostor zakládá znovu, zůstane, co jsi zvolil: nastavení isEnabled i existující řádky spouštěčů přežijí. Jediná záměrná výjimka: denní plán pr_merged_cleanup se zapne natvrdo i tehdy, když byl předtím vypnutý, protože je to úklid. Bez něj se hromadí řádky worktree, oddíly grafu kódu a kopie copy-on-write. To nikdy nemělo být volba uživatele.

Ještě jedna asymetrie: vestavěná pr_review už na GitHub záměrně nic neposílá. Zveřejnění revize je samostatný krok, který musíš pustit ty, a pipeline, která by psala přímo, by revizi zveřejnila dvakrát. cross_review, ticket_to_pr a pr_triage komentář na GitHub pořád posílají rovnou, když běží.

PipelineEngine založí záznam běhu, naplánuje počáteční uzel, který odpovídá typu události běhu, a pak projde DAG. Jak se kroky dokončují, vyhodnocuje navazující spouštěče, vybírá větve router, čeká na join, uplatňuje politiky opakování a pokračování při chybě a po každém kroku ukládá stav, náklady a chyby. Hrany, které vycházejí z jiného startu, se pro tento běh ignorují, takže spuštění podle plánu nečeká na podmínku, která platí jen pro ruční start.

Tickety, odeslání, GitHub ani zprávy nezná. Rozšiřuje se jedině přes PipelineBodyRegistry. Těla zaregistrovaná tam drží AgentDispatchPort, MessagingPort a jim podobné porty. Proto nová schopnost pipeline nikdy neznamená zásah do plánovače.

Krok, který selže, zapíše chybovou zprávu a přejde do failed. Když krok deklaruje continueOnFail, navazující kroky pokračují a chyba se odloží do stavu běhu. Jinak spadne celý běh. Krok s StepRetryPolicy se nejdřív zopakuje, s lineární nebo exponenciální prodlevou, a teprve potom nastane jedno z toho.