Přeskočit na obsah

Typy kroků pipeline

Krok pipeline má dvě na sobě nezávislé osy:

  • Druh (StepKind) — jak engine krok vůči jeho spouštěčům naplánuje.
  • Klíč těla (BuiltInBodyKeys) — který registrovaný uzávěr těla práci kroku provede.

Definováno v packages/cc_domain/lib/features/pipelines/domain/entities/step_kind.dart.

Druh Sémantika plánování
trigger Povinný vstupní bod — v šabloně právě jeden, vždy první uzel. Sám nic neudělá; co běh spustilo (ručně / událost / plán), se eviduje zvlášť jako řádky PipelineTrigger. Jeho tělo je prázdné pipeline.trigger.
listen Spustí se, když se dokončí všechny zdrojové kroky (v StepTrigger.sourceStepIds).
join Spustí se, když všechny kroky v waitForStepIds dojdou do koncového stavu.
router Podmíněné větvení — tělo vrátí StepResult.route(key), což vystřelí jen navazující hranu, jejíž routeKey sedí; nevybrané větve se označí jako přeskočené.
forEach Plánuje se jako listen (spustí se, když se dokončí všechna sourceStepIds). Iteruje registrované tělo flow.forEach; engine nezaloží jeden podřízený krok na položku.
terminal Zarážka plánovače bez těla. Běh pipeline se dokončí, když skončí krok terminal.

Registrované uzávěry těl podle konstant v BuiltInBodyKeys (packages/cc_domain/lib/features/pipelines/domain/templates/builtin_template_seeds.dart). Je jich 25 a všechny jsou níže. Konfigurace se čte z PipelineNodeConfig kroku (viz níže), pokud není uvedeno jinak; „stavové klíče“ se při provedení čtou ze stavu pipeline a z payloadu spouštěče.

Krok, jehož bodyKey není registrovaný, při načtení šablony varuje a pak se nikdy nespustí — běh tím neselže. Kroky trigger a terminal tohle varování nemají: trigger pořád spustí prázdné tělo pipeline.trigger; krok terminal tělo nemá.

Prázdné tělo povinného uzlu trigger — dokončí se hned, aby se engine rozvětvil k navazujícím posluchačům. Bez konfigurace.

Shellový krok bez agenta (bash -c). Zástupné symboly {{key}} ve skriptu se dosadí ze stavu a z payloadu spouštěče, s hodnotami escapovanými pro shell.

Pole konfigurace Popis
script Shellový příkaz ke spuštění (povinné)
outputKey Stavový klíč, který při exitu 0 dostane ořezaný stdout

Běží s cwd <cc_root>/pipelines/<pipelineRunId>/ (sdílí ho všechny bash kroky v běhu) a s GITHUB_TOKEN v prostředí. Do stavu taky zapíše <stepId>_runDir. Nenulový exit krok shodí a přiloží konec stderr.

conversation.promptAgent

Sekce “conversation.promptAgent”

Obecný uzel pro prompt a odeslání: vykreslí prompt, odešle agenta do konverzace a pozastaví se, dokud běh neskončí. Payload z submit_output agenta se zapíše do stavu pod outputKey.

Pole konfigurace Popis
agentId UUID agenta v rozsahu pracovního prostoru k odeslání (povinné)
prompt Text instrukce; umí dosazení {{key}} (povinné)
outputKey Stavový klíč pro sebraný výstup
outputSchema JSON Schema, kterou musí výstup splnit
label Lidský popisek na plátně
extras.spaceId Existující konverzace, ve které se pracuje (výchozí: skrytá)
extras.conversationTitle Pojmenovaný proud uvnitř toho prostoru (volitelné)
extras.mode Čte se na uzlu, který prostor otevírá (messaging.createSpace), ne tady. Výchozí review.

Tělo routeru — přečte config.extras, vyhodnotí podmínku a vrátí StepResult.route(key). Podmínky nejsou výrazy JavaScriptu; podporované jsou tři tvary zápisu, v tomhle pořadí priority:

  • Strom predikátů (extras.predicate) — booleovský strom, který vede na "true" / "false". Každý uzel je mapa s type:
    • {"type": "fileExists", "paths": [...], "baseKey": "repo_local_path", "negate": false, "recursive": false} — platí, když na disku existuje kterákoli uvedená cesta; negate to obrátí; recursive hledá i v podadresářích (přeskočí .git, node_modules, build, .dart_tool). Relativní cesty se vyhodnotí vůči state[baseKey] (výchozí repo_local_path), jinak vůči adresáři pracovního prostoru daného běhu.
    • {"type": "comparison", "left": "{{score}}", "op": "gt", "right": 80} — operátory equals, notEquals, contains, exists, notExists, gt, lt; čte stav pipeline, ne souborový systém.
    • {"type": "and" | "or", "of": [<predicate>, ...]} — booleovské skupiny.
    • {"type": "not", "of": <predicate>} — negace.
  • Přepínač (extras.switchKey) — {"switchKey": "pr_class", "cases": [...], "default": "standard"}; vede na první případ, jehož řetězec hodnota stavu obsahuje bez ohledu na velikost písmen, jinak na default.
  • Porovnání (starší zápis nahoře v extras.left / extras.op / extras.right) — odpovídá predikátu comparison a zůstává kvůli šablonám napsaným před stromem.

Hrany vycházející z uzlu nesou routeKey, který se musí shodovat s vráceným klíčem.

Pošle sloučená zjištění jako komentář k revizi PR přes klienta GitHub PR.

Stavový klíč Popis
repo_full_name owner/repo (povinné)
pr_number Číslo PR — int, nebo číselný řetězec (povinné)
consolidated_findings Tělo komentáře (povinné)

Vrátí StepResult.terminal a do stavu zapíše comment_review_id a commented_at.

Pošle zprávu do prostoru pro zprávy přes MessagingPort.

Stavový klíč Popis
space_id Cílový prostor (povinné)
content Tělo zprávy, ze stavu se čte doslovně (povinné)

Do stavu zapíše posted_space_id a posted_at.

Odešle celý tým místo jednoho agenta a pozastaví se, dokud běhy členů neskončí.

Pole konfigurace Popis
teamId Tým v rozsahu pracovního prostoru k odeslání (povinné; s agentId se vzájemně vylučuje)
prompt Text cíle; umí dosazení {{key}} (povinné)
dispatchMode allParallel (výchozí — jeden úkol na člena) nebo manager (odešle jen vedoucího, aby koordinoval)
outputKey Stavový klíč pro sebrané výstupy členů
outputSchema, label, extras.spaceId Stejně jako u conversation.promptAgent

Schvalovací brána. Odešle schvalujícího agenta do konverzace (režim review) s promptem brány a výstupním kontraktem {decision, reason} a pozastaví se, dokud schvalovatel neodešle výsledek přes submit_output.

Pole konfigurace Popis
agentId Schvalující agent (povinné)
prompt Prompt brány (volitelné; když chybí, použije se výchozí)
outputKey Stavový klíč pro sebraný payload {decision, reason}
outputSchema Výchozí je schvalovací schéma (decision: approved / rejected, reason)
label, extras.spaceId Stejně jako u conversation.promptAgent

Brána se vyřeší jen přes submit_output. BuiltInBodyKeys.humanGate, knihovna typů uzlů i text promptu jedné vestavěné šablony jmenují nástroje MCP approve_step a reject_step; ani jeden nástroj neexistuje v žádném balíčku ani registru.

Odstraní zastaralé izolované worktree; režim si vybere z payloadu spouštěče. Respektuje příznak dryRun běhu.

Stavový klíč Popis
ticket_id Uvolní worktree toho ticketu
repo_full_name + pr_number Uvolní dočasný worktree editoru PR
space_id Zruší worktree a složku té konverzace
(nic z výše uvedeného) Projde pracovní prostor: zmizelé adresáře, mrtvé prostory, osiřelé složky konverzací

outputKey (volitelné) dostane souhrnný řetězec.

Mapování / fan-out nad kolekcí ve stavu: prompt vykreslí jednou pro každou položku, pak agenta odešle jednou s těmi prompty zřetězenými (oddělovače ---) a pozastaví se, dokud ten běh neskončí. Prázdná kolekce hned skončí prázdným seznamem. Není to jedno paralelní odeslání na položku.

Pole konfigurace Popis
agentId Agent k odeslání na každou položku (povinné)
prompt Prompt na položku; umí dosazení {{key}} (povinné)
extras.iterableKey Stavový klíč, který drží kolekci (povinné)
extras.itemKey Klíč, na který se v promptu naváže aktuální položka (výchozí item)
outputKey Stavový klíč pro sebraný výstup (jedno odeslání, ne seznam)

Spustí jinou šablonu pipeline jako vnořený podkrok (podpipeline běží jako podřízený běh s nastaveným parentPipelineRunId). Krok se pozastaví, dokud podřízený běh nedojde do koncového stavu, a pak se jeho konečný stav sloučí pod outputKey.

Pole konfigurace Popis
extras.templateId Podřízená šablona ke spuštění (povinné; pipeline nemůže volat sama sebe)
inputKeys Stavové klíče zkopírované do payloadu spouštěče podřízeného běhu
outputKey Stavový klíč pro sloučený konečný stav podřízeného běhu

Indexování tree-sitter na pozadí: projde repozitář, v izolátech workerů vytáhne symboly a hrany a vloží je do grafu kódu pracovního prostoru. Průběh streamuje do řádku běhu kroku; umí dry-run. Tree-sitter a jeho gramatiky jsou povinné nativy — chybějící dylib znamená, že se server nikdy nespustil, a gramatika, která se v půlce běhu nepodaří načíst, krok shodí, místo aby ho přeskočila.

Stavový klíč Popis
repo_id Repozitář k indexování (povinné)
repo_local_path Lokální cesta checkoutu (povinné)

Offline diarizace řečníků. Přečte ponechané audio schůzky, seskupí ho do řečníků (Person 1, Person 2, …), přeznačí segmenty přepisu a přepíše stav transcript; pro paralelní krok meeting.updateTranscript taky vyprodukuje diarization_spans. Když se audio neponechalo nebo nejsou nainstalované modely, přepis propustí beze změny.

Stavový klíč Popis
meeting_id Schůzka k diarizaci (povinné)

meeting.saveNotes, meeting.addActionItems, meeting.addDecisions

Sekce “meeting.saveNotes, meeting.addActionItems, meeting.addDecisions”

Deterministická těla pro uložení shrnutí schůzky. Každé si ze stavu přečte meeting_id a strukturovaný payload meeting_outcome z kroku agenta ({summary, enhancedNotes, actionItems[], decisions[]}) a svou část zapíše do vlastní tabulky — poznámky, akční položky, nebo rozhodnutí. Dříve uložené řádky se při zhoršeném běhu nikdy nemažou.

Další vestavěná těla

Sekce “Další vestavěná těla”
Klíč těla Popis
meeting.identifySpeakers Rozpoznání řečníků napříč schůzkami: diarizované řečníky porovná s uloženými hlasovými profily a jisté shody uplatní samo. Bez profilů a embeddingů nic neudělá.
meeting.updateTranscript Aplikuje popisky Person N z diarization_spans a sloučí fragmenty po oknech do replik podle řečníka, pak uloží vyčištěný přepis. Když diarizace nic nevyprodukovala, nic neudělá.
meeting.assemblePlayback Složí smíšenou stopu přehrávání schůzky z ponechaných WAV po kanálech. Když se audio neponechalo, nic neudělá.
orchestration.markPhase Na konci pracovního DAGu zapíše zarážky selhání pro podtickety bez výstupu a přepne orchestaci na synthesizing.
orchestration.persistDeliverable Zapíše výstup syntézy na nadřazený ticket, dokončí ho, zveřejní výstup a označí orchestaci jako completed.
orchestration.awaitApproval Brána částečného schválení: dokončí se hned, když je klíč uzlu kroku ve schválené množině orchetrace, jinak se pozastaví, dokud ho pozdější schválení neobnoví. Je to jediné tělo, které nastavuje extras.awaitApproval, a tím se vyjímá z 24hodinového timeoutu pozastaveného kroku.
messaging.createSpace Otevře konverzaci, ve které pracuje zbytek šablony, a zveřejní ji pod outputKey kroku (vestavěné používají pipeline_space_id). Prázdný seznam repoIds nic necheckoutuje; extras['allRepos'] checkoutne každý repozitář pracovního prostoru. extras['createConversation'] (ve výchozím stavu vypnuté) navíc otevře pojmenovaný proud. Krok agenta do místnosti VSTOUPÍ a nikdy ji neotevře, takže fan-out bez tohoto uzlu spadne při odeslání — a když ho zapojíš jednou, celý fan-out sdílí jeden checkout, místo aby se připravoval jeden pro každý.
prReview.finalize Poslední krok šablony revize PR: nashromážděné uzly revize roztřídí do košů podle konsenzu a spočítá verdikt na PR.
skills.analyze Spustí kontrolu dodavatelského řetězce skillů nad nainstalovanými skilly pracovního prostoru a zaznamená každý verdikt.

Tělo kroku vrací StepResult (packages/cc_domain/lib/features/pipelines/domain/entities/step_result.dart). Všechny továrny berou volitelnou mapu mutatedState, která se sloučí do stavu pipeline, kromě failed.

Továrna Signatura Popis
ok StepResult.ok({mutatedState}) Běžné dokončení; vyhodnotí se navazující posluchači
route StepResult.route(nextRouterKey, {mutatedState}) Dokončení routeru; vybere navazující větev, jejíž routeKey sedí
suspendUntilEvent StepResult.suspendUntilEvent(eventType, {mutatedState}) Pozastavení, dokud nevyletí konkrétní typ doménové události
suspendUntilTasksComplete StepResult.suspendUntilTasksComplete(taskIds, {mutatedState}) Pozastavení, dokud všechny uvedené úlohy nedojdou do koncového stavu
terminal StepResult.terminal({mutatedState}) Běh pipeline je hotový — žádné další kroky
failed StepResult.failed(errorMessage) Krok selhal s chybovou zprávou

Chování opakování pro selhávající tělo uzlu (PipelineNodeConfig.retryPolicy; null opakování vypne).

Pole Typ Popis
maxAttempts int Celkový počet pokusů včetně prvního (3 = 1 pokus + 2 opakování); musí být ≥ 1
backoff String linear nebo exponential (výchozí)
initialDelayMs int Prodleva před prvním opakováním v milisekundách; další prodlevy rostou podle backoff

Konfigurace jednoho uzlu nesená uvnitř definice kroku (packages/cc_domain/lib/features/pipelines/domain/entities/pipeline_node_config.dart). Vestavěné i vlastní uzly sdílejí tenhle tvar; každé tělo čte jen pole, která potřebuje.

Pole Typ Popis
prompt String? Šablona promptu s dosazením {{key}}
script String? Tělo bash skriptu s dosazením {{key}}
agentId String? UUID agenta v rozsahu pracovního prostoru k odeslání
inputKeys List<String> Stavové klíče, které tenhle uzel bere jako vstup
repoIds List<String> Repozitáře, které checkoutne uzel messaging.createSpace (<repoId> nebo <repoId>@<branch>). Prázdné = žádný; extras['allRepos'] = každý repozitář pracovního prostoru. Na krocích agenta se ignoruje.
outputKey String? Stavový klíč, pod který se zapíše výstup tohohle uzlu
label String? Lidský popisek na plátně (výchozí je ID kroku)
outputSchema Map<String, dynamic>? JSON Schema (podmnožina), kterou musí výstupní hodnota splnit
reducer String? Strategie sloučení, když paralelní větve zapisují stejný outputKey: append, mergeLists, mergeMaps, sum, nebo override (výchozí)
retryPolicy StepRetryPolicy? Politika opakování při selhání těla; null = jeden pokus
continueOnFail bool Když je true, koncové selhání běh neshodí; chyba se odloží pod state['_stepErrors'][stepId]
timeoutMs int? Časový limit těla uzlu v milisekundách reálného času; null = bez limitu
teamId String? Tým k odeslání (uzly team.dispatch); s agentId se vzájemně vylučuje
dispatchMode String? Režim běhu týmu: allParallel nebo manager
extras Map<String, dynamic> Volná konfigurace specifická pro tělo (např. iterableKey, templateId, stromy podmínek)

Odvozené přístupy: spaceId (extras['spaceId'] — existující konverzace, ve které se pracuje), createsConversation (extras['createConversation']), conversationTitle (extras['conversationTitle']), modeName (extras['mode'] — chat / review / plan, čte se na uzlu, který prostor otevírá) a runWhen (extras['runWhen'] — přeskočí uzel, když podmínka neplatí).