Pipeline-stegtyper
Ett pipelinesteg har två oberoende axlar:
- Typ (
StepKind) – hur motorn schemalägger steget i förhållande till dess triggers. - Kroppsnyckel (
BuiltInBodyKeys) – vilken registrerad kropp som utför stegets arbete.
Stegtyper
Avsnitt med rubriken “Stegtyper”Definierade i packages/cc_domain/lib/features/pipelines/domain/entities/step_kind.dart.
| Typ | Schemaläggningssemantik |
|---|---|
trigger |
Obligatorisk ingångspunkt – exakt en per mall, alltid den första noden. Utför inget arbete själv; det som startar körningen (manuellt / händelse / schema) spåras separat som rader av typen PipelineTrigger. Dess kropp är den verkanslösa pipeline.trigger. |
listen |
Utlöses när alla källsteg (i StepTrigger.sourceStepIds) har slutförts. |
join |
Utlöses när alla steg i waitForStepIds når ett terminalt tillstånd. |
router |
Villkorlig förgrening – kroppen returnerar StepResult.route(key), vilket bara utlöser den nedströms kant vars routeKey matchar; ovalda grenar markeras som överhoppade. |
forEach |
Schemaläggs som listen (utlöses när alla sourceStepIds har slutförts). Det är den registrerade kroppen flow.forEach som itererar; motorn skapar inte ett understeg per objekt. |
terminal |
Markör för schemaläggaren utan kropp. Pipelinekörningen slutförs när ett terminalsteg är klart. |
Stegkroppar
Avsnitt med rubriken “Stegkroppar”Registrerade kroppar (closures) som nycklas av konstanterna i BuiltInBodyKeys (packages/cc_domain/lib/features/pipelines/domain/templates/builtin_template_seeds.dart). Det finns 25 stycken, alla listade nedan. Konfigurationen läses från stegets PipelineNodeConfig (se nedan) om inget annat anges; ”tillståndsnycklar” läses från pipelinens tillstånd / triggerns nyttolast vid körning.
Ett steg vars bodyKey inte är registrerad ger en varning vid inläsning av mallen och körs sedan aldrig – det får inte körningen att misslyckas. Stegen trigger och terminal omfattas inte av den varningen: triggern kör fortfarande den verkanslösa kroppen pipeline.trigger; ett terminal-steg har ingen kropp.
pipeline.trigger
Avsnitt med rubriken “pipeline.trigger”Verkanslös kropp till den obligatoriska noden trigger – slutförs direkt så att motorn kan sprida ut arbetet till nedströms lyssnare. Ingen konfiguration.
pipeline.bashScript
Avsnitt med rubriken “pipeline.bashScript”Shellsteg utan agent (bash -c). Platshållare av typen {{key}} i skriptet ersätts från tillstånd och triggerns nyttolast med shell-escapeade värden.
| Konfigurationsfält | Beskrivning |
|---|---|
script |
Shellkommando att köra (obligatoriskt) |
outputKey |
Tillståndsnyckel som tar emot trimmad stdout vid exit 0 |
Körs med cwd <cc_root>/pipelines/<pipelineRunId>/ (delas av alla bash-steg i en körning) och GITHUB_TOKEN i miljön. Skriver även <stepId>_runDir till tillståndet. En exit-kod som inte är noll får steget att misslyckas med slutet av stderr som felmeddelande.
conversation.promptAgent
Avsnitt med rubriken “conversation.promptAgent”Generisk nod för prompt och utskick: renderar prompten, skickar ut agenten i ett samtal och pausar tills körningen är klar. Agentens nyttolast från submit_output samlas in i tillståndet under outputKey.
| Konfigurationsfält | Beskrivning |
|---|---|
agentId |
Arbetsytebunden agent-UUID att skicka ut (obligatoriskt) |
prompt |
Instruktionstext; stöder {{key}}-ersättning (obligatoriskt) |
outputKey |
Tillståndsnyckel för den insamlade utdatan |
outputSchema |
JSON-schema som utdatan måste uppfylla |
label |
Mänsklig etikett som visas på duken |
extras.spaceId |
Befintligt samtal att arbeta i (standard: ett dolt) |
extras.conversationTitle |
Namngiven ström i den ytan (valfritt) |
extras.mode |
Läses på den nod som öppnar rummet (messaging.createSpace), inte här. Standard review. |
pipeline.condition
Avsnitt med rubriken “pipeline.condition”Kropp för routern – läser config.extras, utvärderar ett villkor och returnerar StepResult.route(key). Villkor är inte JavaScript-uttryck; tre sätt att skriva dem stöds, i prioritetsordning:
- Predikatträd (
extras.predicate) – ett booleskt träd som dirigerar"true"/"false". Varje nod är en map med etttype:{"type": "fileExists", "paths": [...], "baseKey": "repo_local_path", "negate": false, "recursive": false}– sant när någon av de angivna sökvägarna finns på disken;negatevänder på det;recursivesöker även i underkataloger (och hoppar över.git,node_modules,build,.dart_tool). Relativa sökvägar löses motstate[baseKey](standardrepo_local_path), annars mot arbetsytans katalog för körningen.{"type": "comparison", "left": "{{score}}", "op": "gt", "right": 80}– operatorerequals,notEquals,contains,exists,notExists,gt,lt; läser pipelinens tillstånd, inte filsystemet.{"type": "and" | "or", "of": [<predicate>, ...]}– booleska grupper.{"type": "not", "of": <predicate>}– negation.
- Switch (
extras.switchKey) –{"switchKey": "pr_class", "cases": [...], "default": "standard"}; dirigerar till det första fall som tillståndsvärdet innehåller utan hänsyn till skiftläge, annarsdefault. - Jämförelse (äldre toppnivå:
extras.left/extras.op/extras.right) – likvärdig med predikatetcomparison, finns kvar för mallar som skrevs innan trädet.
Kanter ut från noden bär en routeKey som måste matcha den returnerade nyckeln.
prReview.comment
Avsnitt med rubriken “prReview.comment”Publicerar de sammanställda fynden som en PR-granskningskommentar via GitHub-PR-klienten.
| Tillståndsnyckel | Beskrivning |
|---|---|
repo_full_name |
owner/repo (obligatoriskt) |
pr_number |
PR-nummer – int eller numerisk sträng (obligatoriskt) |
consolidated_findings |
Kommentarens brödtext (obligatoriskt) |
Returnerar StepResult.terminal med comment_review_id och commented_at i tillståndet.
messaging.postSpace
Avsnitt med rubriken “messaging.postSpace”Publicerar ett meddelande till en meddelandeyta via MessagingPort.
| Tillståndsnyckel | Beskrivning |
|---|---|
space_id |
Målyta (obligatoriskt) |
content |
Meddelandets brödtext, läses ordagrant från tillståndet (obligatoriskt) |
Skriver posted_space_id och posted_at till tillståndet.
team.dispatch
Avsnitt med rubriken “team.dispatch”Skickar ut ett helt team i stället för en enskild agent och pausar sedan tills medlemmarnas körningar är klara.
| Konfigurationsfält | Beskrivning |
|---|---|
teamId |
Arbetsytebundet team att skicka ut (obligatoriskt; ömsesidigt uteslutande mot agentId) |
prompt |
Måltext; stöder {{key}}-ersättning (obligatoriskt) |
dispatchMode |
allParallel (standard – en uppgift per medlem) eller manager (skicka bara ledaren, som samordnar) |
outputKey |
Tillståndsnyckel för medlemmarnas insamlade utdata |
outputSchema, label, extras.spaceId |
Som för conversation.promptAgent |
human.gate
Avsnitt med rubriken “human.gate”Godkännandegrind. Skickar ut godkännaragenten i ett samtal (review-läget) med grindens prompt och ett utdatakontrakt {decision, reason} och pausar sedan tills godkännaren skickar in via submit_output.
| Konfigurationsfält | Beskrivning |
|---|---|
agentId |
Godkännaragenten (obligatoriskt) |
prompt |
Grindens prompt (valfritt; en standard används när det saknas) |
outputKey |
Tillståndsnyckel för den insamlade nyttolasten {decision, reason} |
outputSchema |
Standard är ett godkännandeschema (decision: approved / rejected, reason) |
label, extras.spaceId |
Som för conversation.promptAgent |
Grinden avgörs bara genom submit_output. BuiltInBodyKeys.humanGate, biblioteket över nodtyper och prompttexten i en av de inbyggda mallarna namnger alla MCP-verktygen approve_step och reject_step; inget av verktygen finns i något paket eller register.
repos.cleanup
Avsnitt med rubriken “repos.cleanup”Tar bort föråldrade avskilda worktrees; väljer sitt läge utifrån triggerns nyttolast. Respekterar körningens flagga dryRun.
| Tillståndsnyckel | Beskrivning |
|---|---|
ticket_id |
Frigör ärendets worktrees |
repo_full_name + pr_number |
Frigör den tillfälliga PR-redigerarens worktree |
space_id |
Riv ner det samtalets worktrees och mapp |
| (inget av ovanstående) | Svep arbetsytan: försvunna kataloger, döda ytor, föräldralösa samtalsmappar |
outputKey (valfritt) tar emot en sammanfattande sträng.
flow.forEach
Avsnitt med rubriken “flow.forEach”Map / fan-out över en samling i tillståndet: renderar prompten en gång per objekt och skickar sedan ut agenten en gång med dessa prompter sammanfogade (--- som avgränsare) och pausar tills den körningen är klar. En tom samling slutförs direkt med en tom lista. Det är inte ett parallellt utskick per objekt.
| Konfigurationsfält | Beskrivning |
|---|---|
agentId |
Agent att skicka ut per objekt (obligatoriskt) |
prompt |
Prompt per objekt; stöder {{key}}-ersättning (obligatoriskt) |
extras.iterableKey |
Tillståndsnyckel som innehåller samlingen (obligatoriskt) |
extras.itemKey |
Nyckeln som det aktuella objektet binds till i prompten (standard item) |
outputKey |
Tillståndsnyckel för den insamlade utdatan (ett utskick, inte en lista) |
flow.callPipeline
Avsnitt med rubriken “flow.callPipeline”Kör en annan pipelinemall som ett nästlat delsteg (underpipelines körs som en barnkörning med parentPipelineRunId satt). Steget pausar tills barnet når ett terminalt tillstånd; därefter slås barnets sluttillstånd ihop under outputKey.
| Konfigurationsfält | Beskrivning |
|---|---|
extras.templateId |
Barnmall att köra (obligatoriskt; en pipeline kan inte anropa sig själv) |
inputKeys |
Tillståndsnycklar som kopieras in i barnets triggernyttolast |
outputKey |
Tillståndsnyckel för barnets sammanslagna sluttillstånd |
code.index
Avsnitt med rubriken “code.index”Bakgrundsindexering med tree-sitter: går igenom ett repo, extraherar symboler/kanter i worker-isolates och matar in dem i arbetsytans kodgraf. Strömmar förlopp till stegets körningsrad; stöder dry-run. Tree-sitter och dess grammatiker är nödvändiga native-bibliotek – en saknad dylib betyder att servern aldrig startade, och en grammatik som inte kan lösas upp mitt i körningen får steget att misslyckas i stället för att hoppas över.
| Tillståndsnyckel | Beskrivning |
|---|---|
repo_id |
Repo att indexera (obligatoriskt) |
repo_local_path |
Lokal sökväg till utcheckningen (obligatoriskt) |
meeting.diarize
Avsnitt med rubriken “meeting.diarize”Offline-talarseparation. Läser mötets bevarade ljud, klustrar det till talare (Person 1, Person 2, …), märker om transkriptets segment och skriver om tillståndet transcript; avger även diarization_spans till det parallella steget meeting.updateTranscript. Skickar transkriptet oförändrat vidare när inget ljud bevarades eller modellerna inte är installerade.
| Tillståndsnyckel | Beskrivning |
|---|---|
meeting_id |
Möte att separera talare i (obligatoriskt) |
meeting.saveNotes, meeting.addActionItems, meeting.addDecisions
Avsnitt med rubriken “meeting.saveNotes, meeting.addActionItems, meeting.addDecisions”Deterministiska kroppar som sparar mötessammanfattningen. Var och en läser meeting_id och agentstegets strukturerade nyttolast meeting_outcome ({summary, enhancedNotes, actionItems[], decisions[]}) från tillståndet och skriver sin del till sin egen tabell – anteckningar, åtgärdspunkter eller beslut. Rader som sparats tidigare raderas aldrig vid en degraderad körning.
Övriga inbyggda kroppar
Avsnitt med rubriken “Övriga inbyggda kroppar”| Kroppsnyckel | Beskrivning |
|---|---|
meeting.identifySpeakers |
Taligenkänning över möten: matchar separerade talare mot sparade röstprofiler och tillämpar säkra matchningar automatiskt. Verkar inte utan profiler/embeddingar. |
meeting.updateTranscript |
Tillämpar etiketterna Person N från diarization_spans och slår ihop fragment per fönster till turer per talare och sparar sedan det rensade transkriptet. Verkar inte när talarseparationen inte gav något. |
meeting.assemblePlayback |
Sätter ihop mötets mixade uppspelningsspår från bevarade WAV-filer per kanal. Verkar inte när inget ljud bevarades. |
orchestration.markPhase |
I slutet av arbets-DAG:en skriver den felmarkörer för underärenden utan utdata och växlar orkestreringen till synthesizing. |
orchestration.persistDeliverable |
Skriver syntesutdatan till föräldraärendet, slutför det, publicerar leveransen och markerar orkestreringen som completed. |
orchestration.awaitApproval |
Grind för delgodkännande: slutförs direkt när stegets nodnyckel finns i orkestreringens godkända mängd, annars pausar den tills ett senare godkännande återupptar den. Detta är den enda kroppen som sätter extras.awaitApproval, vilket befriar den från timeoutern på 24 timmar för pausade steg. |
messaging.createSpace |
Öppnar samtalet som resten av mallen arbetar i, publicerat under stegets outputKey (inbyggda använder pipeline_space_id). En tom lista repoIds checkar inte ut något; extras['allRepos'] checkar ut alla arbetsytans repos. extras['createConversation'] (av som standard) öppnar dessutom en namngiven ström. Ett agentsteg GÅR MED i ett rum och öppnar aldrig ett, så en fan-out utan den här noden misslyckas vid utskicket – och kopplar du in den en gång delar hela fan-outen på en utcheckning i stället för att skaffa en var. |
prReview.finalize |
Det sista steget i PR-granskningsmallen: sorterar de ackumulerade granskningsnoderna i konsensusgrupper och beräknar utlåtandet för PR:en. |
skills.analyze |
Kör leverantörskedjeskanningen av en arbetsytas installerade skills och registrerar varje utlåtande. |
Stegresultat
Avsnitt med rubriken “Stegresultat”En stegkropp returnerar en StepResult (packages/cc_domain/lib/features/pipelines/domain/entities/step_result.dart). Alla fabriker tar emot en valfri mutatedState-map som slås ihop med pipelinens tillstånd, utom failed.
| Fabrik | Signatur | Beskrivning |
|---|---|---|
ok |
StepResult.ok({mutatedState}) |
Normalt slutförande; nedströms lyssnare utvärderas |
route |
StepResult.route(nextRouterKey, {mutatedState}) |
Routerns slutförande; väljer den nedströms gren vars routeKey matchar |
suspendUntilEvent |
StepResult.suspendUntilEvent(eventType, {mutatedState}) |
Pausar tills en specifik domänhändelsetyp utlöses |
suspendUntilTasksComplete |
StepResult.suspendUntilTasksComplete(taskIds, {mutatedState}) |
Pausar tills alla angivna uppgifter når ett terminalt tillstånd |
terminal |
StepResult.terminal({mutatedState}) |
Pipelinekörningen är klar – inga fler steg |
failed |
StepResult.failed(errorMessage) |
Steget misslyckades med ett felmeddelande |
StepRetryPolicy
Avsnitt med rubriken “StepRetryPolicy”Återförsöksbeteende för en nodkropp som misslyckas (PipelineNodeConfig.retryPolicy; null stänger av återförsök).
| Fält | Typ | Beskrivning |
|---|---|---|
maxAttempts |
int |
Totalt antal försök inklusive det första (3 = 1 försök + 2 återförsök); måste vara ≥ 1 |
backoff |
String |
linear eller exponential (standard) |
initialDelayMs |
int |
Fördröjning före första återförsöket, i millisekunder; senare fördröjningar växer enligt backoff |
PipelineNodeConfig
Avsnitt med rubriken “PipelineNodeConfig”Konfiguration per nod som bärs inuti stegdefinitionen (packages/cc_domain/lib/features/pipelines/domain/entities/pipeline_node_config.dart). Både inbyggda och anpassade noder delar den här formen; varje kropp läser bara de fält den bryr sig om.
| Fält | Typ | Beskrivning |
|---|---|---|
prompt |
String? |
Promptmall med {{key}}-ersättning |
script |
String? |
Bash-skriptets kropp med {{key}}-ersättning |
agentId |
String? |
Arbetsytebunden agent-UUID att skicka ut |
inputKeys |
List<String> |
Tillståndsnycklar som noden konsumerar som indata |
repoIds |
List<String> |
Repos som noden messaging.createSpace checkar ut (<repoId> eller <repoId>@<branch>). Tom = inga; extras['allRepos'] = alla arbetsytans repos. Ignoreras på agentsteg. |
outputKey |
String? |
Tillståndsnyckel som nodens utdata skrivs under |
label |
String? |
Mänsklig etikett som visas på duken (standard: stegets id) |
outputSchema |
Map<String, dynamic>? |
JSON-schema (delmängd) som utdatavärdet måste uppfylla |
reducer |
String? |
Sammanfogningsstrategi när parallella grenar skriver till samma outputKey: append, mergeLists, mergeMaps, sum eller override (standard) |
retryPolicy |
StepRetryPolicy? |
Återförsökspolicy vid kroppsfel; null = ett enda försök |
continueOnFail |
bool |
När sant får ett terminalt fel inte körningen att misslyckas; felet sparas undan under state['_stepErrors'][stepId] |
timeoutMs |
int? |
Timeout i klocktid för nodkroppen i millisekunder; null = ingen timeout |
teamId |
String? |
Team att skicka ut (team.dispatch-noder); ömsesidigt uteslutande mot agentId |
dispatchMode |
String? |
Teamets körningsläge: allParallel eller manager |
extras |
Map<String, dynamic> |
Fri kroppsspecifik konfiguration (t.ex. iterableKey, templateId, villkorsträd) |
Härledda accessorer: spaceId (extras['spaceId'] – befintligt samtal att arbeta i), createsConversation (extras['createConversation']), conversationTitle (extras['conversationTitle']), modeName (extras['mode'] – chat / review / plan, läses på den ytöppnande noden) och runWhen (extras['runWhen'] – hoppa över noden när villkoret inte är uppfyllt).