Pipeline-stapsoorten
Een pipelinestap heeft twee onafhankelijke assen:
- Kind (
StepKind) — hoe de engine de stap plant ten opzichte van zijn triggers. - Body-sleutel (
BuiltInBodyKeys) — welke geregistreerde body-closure het werk van de stap uitvoert.
Stapsoorten
Sectie getiteld “Stapsoorten”Gedefinieerd in packages/cc_domain/lib/features/pipelines/domain/entities/step_kind.dart.
| Kind | Planningssemantiek |
|---|---|
trigger |
Verplicht ingangspunt — precies één per sjabloon, altijd de eerste node. Doet zelf geen werk; wat de run start (handmatig / gebeurtenis / schema) wordt apart bijgehouden als PipelineTrigger-rijen. De body is de no-op pipeline.trigger. |
listen |
Gaat af wanneer alle bronstappen (in StepTrigger.sourceStepIds) klaar zijn. |
join |
Gaat af wanneer alle stappen in waitForStepIds een eindtoestand bereiken. |
router |
Voorwaardelijke vertakking — de body geeft StepResult.route(key) terug, waardoor alleen de stroomafwaartse rand afgaat waarvan de routeKey overeenkomt; niet-geselecteerde takken worden als overgeslagen gemarkeerd. |
forEach |
Wordt net als listen gepland (gaat af wanneer alle sourceStepIds klaar zijn). De geregistreerde body flow.forEach is wat itereert; de engine maakt niet per item een kindstap aan. |
terminal |
Sentinel voor de scheduler zonder body. De pipelinerun is voltooid wanneer een terminale stap klaar is. |
Bodies van stappen
Sectie getiteld “Bodies van stappen”Geregistreerde body-closures, gesleuteld op de constanten in BuiltInBodyKeys (packages/cc_domain/lib/features/pipelines/domain/templates/builtin_template_seeds.dart). Er zijn er 25, allemaal hieronder vermeld. De configuratie wordt gelezen uit de PipelineNodeConfig van de stap (zie hieronder), tenzij anders vermeld; “statussleutels” worden op uitvoeringstijd gelezen uit de pipelinestatus of de triggerpayload.
Een stap waarvan de bodyKey niet is geregistreerd, geeft een waarschuwing bij het laden van het sjabloon en wordt daarna nooit uitgevoerd — de run mislukt er niet door. trigger- en terminal-stappen vallen niet onder die waarschuwing: de trigger voert nog steeds de no-op-body pipeline.trigger uit; een terminal-stap heeft geen body.
pipeline.trigger
Sectie getiteld “pipeline.trigger”No-op-body van de verplichte trigger-node — voltooit onmiddellijk, zodat de engine naar stroomafwaartse luisteraars uitwaaiert. Geen configuratie.
pipeline.bashScript
Sectie getiteld “pipeline.bashScript”Agentloze shellstap (bash -c). {{key}}-placeholders in het script worden vervangen door shell-geëscapete waarden uit de status en de triggerpayload.
| Configuratieveld | Beschrijving |
|---|---|
script |
Uit te voeren shellopdracht (verplicht) |
outputKey |
Statussleutel die bij exitcode 0 de getrimde stdout ontvangt |
Draait met cwd <cc_root>/pipelines/<pipelineRunId>/ (gedeeld door alle bash-stappen in een run) en GITHUB_TOKEN in de omgeving. Schrijft ook <stepId>_runDir naar de status. Een exitcode anders dan nul laat de stap mislukken met de staart van stderr.
conversation.promptAgent
Sectie getiteld “conversation.promptAgent”Algemene prompt-en-dispatch-node: rendert de prompt, dispatcht de agent naar een gesprek en blijft onderbroken tot de run klaar is. De submit_output-payload van de agent wordt onder outputKey in de status opgehaald.
| Configuratieveld | Beschrijving |
|---|---|
agentId |
Werkruimtegebonden agent-UUID om te dispatchen (verplicht) |
prompt |
Instructietekst; ondersteunt {{key}}-substitutie (verplicht) |
outputKey |
Statussleutel voor de opgehaalde uitvoer |
outputSchema |
JSON Schema waaraan de uitvoer moet voldoen |
label |
Menselijk label dat op het canvas wordt getoond |
extras.spaceId |
Bestaand gesprek om in te werken (standaard: een verborgen gesprek) |
extras.conversationTitle |
Benoemde stroom binnen die ruimte (optioneel) |
extras.mode |
Wordt gelezen op de node die de ruimte opent (messaging.createSpace), niet hier. Standaard review. |
pipeline.condition
Sectie getiteld “pipeline.condition”Routerbody — leest config.extras, evalueert een voorwaarde en geeft StepResult.route(key) terug. Voorwaarden zijn geen JavaScript-expressies; er worden drie schrijfvormen ondersteund, in volgorde van prioriteit:
- Predicaatboom (
extras.predicate) — een booleaanse boom die routeert naar"true"/"false". Elke node is een map met eentype:{"type": "fileExists", "paths": [...], "baseKey": "repo_local_path", "negate": false, "recursive": false}— waar als een van de opgegeven paden op schijf bestaat;negatekeert dat om;recursivedoorzoekt ook submappen (met overslaan van.git,node_modules,build,.dart_tool). Relatieve paden worden opgelost tegenstate[baseKey](standaardrepo_local_path), anders tegen de werkmap van de run.{"type": "comparison", "left": "{{score}}", "op": "gt", "right": 80}— operatorenequals,notEquals,contains,exists,notExists,gt,lt; leest de pipelinestatus, niet het bestandssysteem.{"type": "and" | "or", "of": [<predicate>, ...]}— booleaanse groepen.{"type": "not", "of": <predicate>}— negatie.
- Schakelaar (
extras.switchKey) —{"switchKey": "pr_class", "cases": [...], "default": "standard"}; routeert naar het eerste geval dat de statuswaarde zonder onderscheid van hoofdletters en kleine letters bevat, anders naardefault. - Vergelijking (verouderde velden op het hoogste niveau
extras.left/extras.op/extras.right) — gelijkwaardig aan eencomparison-predicaat, behouden voor sjablonen die zijn gemaakt vóór de boom.
Randen die uit de node vertrekken, dragen een routeKey die moet overeenkomen met de teruggegeven sleutel.
prReview.comment
Sectie getiteld “prReview.comment”Plaatst de gebundelde bevindingen als PR-reviewcommentaar via de GitHub-PR-client.
| Statussleutel | Beschrijving |
|---|---|
repo_full_name |
owner/repo (verplicht) |
pr_number |
PR-nummer — int of numerieke tekenreeks (verplicht) |
consolidated_findings |
Commentaartekst (verplicht) |
Geeft StepResult.terminal terug met comment_review_id en commented_at in de status.
messaging.postSpace
Sectie getiteld “messaging.postSpace”Plaatst een bericht in een berichtenruimte via MessagingPort.
| Statussleutel | Beschrijving |
|---|---|
space_id |
Doelruimte (verplicht) |
content |
Berichttekst, letterlijk uit de status gelezen (verplicht) |
Schrijft posted_space_id en posted_at naar de status.
team.dispatch
Sectie getiteld “team.dispatch”Dispatcht een heel team in plaats van één agent en blijft daarna onderbroken tot de runs van de leden klaar zijn.
| Configuratieveld | Beschrijving |
|---|---|
teamId |
Werkruimtegebonden team om te dispatchen (verplicht; wederzijds uitsluitend met agentId) |
prompt |
Doeltekst; ondersteunt {{key}}-substitutie (verplicht) |
dispatchMode |
allParallel (standaard — één taak per lid) of manager (dispatch alleen de leider om te coördineren) |
outputKey |
Statussleutel voor de opgehaalde uitvoer van de leden |
outputSchema, label, extras.spaceId |
Zoals bij conversation.promptAgent |
human.gate
Sectie getiteld “human.gate”Goedkeuringspoort. Dispatcht de goedkeurder-agent met de poortprompt naar een gesprek (reviewmodus) en met een uitvoercontract {decision, reason}, en blijft daarna onderbroken tot de goedkeurder indient via submit_output.
| Configuratieveld | Beschrijving |
|---|---|
agentId |
De goedkeurder-agent (verplicht) |
prompt |
Poortprompt (optioneel; bij afwezigheid wordt een standaard gebruikt) |
outputKey |
Statussleutel voor de opgehaalde payload {decision, reason} |
outputSchema |
Standaard een goedkeuringsschema (decision: approved / rejected, reason) |
label, extras.spaceId |
Zoals bij conversation.promptAgent |
De poort wordt uitsluitend via submit_output opgelost. BuiltInBodyKeys.humanGate, de nodetype-bibliotheek en de prompttekst van één ingebouwd sjabloon noemen allemaal de MCP-tools approve_step en reject_step; geen van beide tools bestaat in welk pakket of register dan ook.
repos.cleanup
Sectie getiteld “repos.cleanup”Verwijdert verouderde geïsoleerde worktrees; kiest zijn modus op basis van de triggerpayload. Respecteert de dryRun-markering van de run.
| Statussleutel | Beschrijving |
|---|---|
ticket_id |
Geeft de worktrees van dat ticket vrij |
repo_full_name + pr_number |
Geeft de tijdelijke PR-editor-worktree vrij |
space_id |
Breekt de worktrees en de map van dat gesprek af |
| (geen van bovenstaande) | Veegt de werkruimte schoon: verdwenen mappen, dode ruimtes, verweesde gespreksmappen |
outputKey (optioneel) ontvangt een samenvattende tekenreeks.
flow.forEach
Sectie getiteld “flow.forEach”Map / fan-out over een statusverzameling: rendert de prompt één keer per item en dispatcht de agent daarna één keer met die prompts aan elkaar (gescheiden door ---), en blijft onderbroken tot die run klaar is. Een lege verzameling voltooit direct met een lege lijst. Het is geen aparte parallelle dispatch per item.
| Configuratieveld | Beschrijving |
|---|---|
agentId |
Agent om per item te dispatchen (verplicht) |
prompt |
Prompt per item; ondersteunt {{key}}-substitutie (verplicht) |
extras.iterableKey |
Statussleutel met de verzameling (verplicht) |
extras.itemKey |
Sleutel waaraan het huidige item in de prompt is gebonden (standaard item) |
outputKey |
Statussleutel voor de opgehaalde uitvoer (één dispatch, geen lijst) |
flow.callPipeline
Sectie getiteld “flow.callPipeline”Voert een ander pipelinesjabloon uit als geneste substap (de subpipeline draait als kindrun met parentPipelineRunId ingesteld). De stap blijft onderbroken tot het kind een eindtoestand bereikt; daarna wordt de eindstatus van het kind onder outputKey samengevoegd.
| Configuratieveld | Beschrijving |
|---|---|
extras.templateId |
Uit te voeren kindsjabloon (verplicht; een pipeline kan zichzelf niet aanroepen) |
inputKeys |
Statussleutels die naar de triggerpayload van het kind worden gekopieerd |
outputKey |
Statussleutel voor de samengevoegde eindstatus van het kind |
code.index
Sectie getiteld “code.index”Achtergrondindexering met tree-sitter: loopt een repo door, extraheert symbolen en randen in worker-isolates en neemt ze op in de codegraaf van de werkruimte. Streamt de voortgang naar de rij van de stap-run; ondersteunt dry-run. Tree-sitter en zijn grammatica’s zijn vereiste natives — een ontbrekende dylib betekent dat de server nooit is opgestart, en een grammatica die tijdens de run niet kan worden gevonden laat de stap mislukken in plaats van hem over te slaan.
| Statussleutel | Beschrijving |
|---|---|
repo_id |
Te indexeren repo (verplicht) |
repo_local_path |
Lokaal pad van de checkout (verplicht) |
meeting.diarize
Sectie getiteld “meeting.diarize”Offline sprekersscheiding. Leest de bewaarde audio van de vergadering, clustert die in sprekers (Person 1, Person 2, …), voorziet de transcriptsegmenten opnieuw van labels en herschrijft de status transcript; levert ook diarization_spans op voor de parallelle stap meeting.updateTranscript. Geeft het transcript ongewijzigd door wanneer er geen audio is bewaard of de modellen niet zijn geïnstalleerd.
| Statussleutel | Beschrijving |
|---|---|
meeting_id |
Te diarizeren vergadering (verplicht) |
meeting.saveNotes, meeting.addActionItems, meeting.addDecisions
Sectie getiteld “meeting.saveNotes, meeting.addActionItems, meeting.addDecisions”Deterministische bodies om de vergaderingsamenvatting vast te leggen. Elk leest meeting_id en de gestructureerde payload meeting_outcome van de agentstap ({summary, enhancedNotes, actionItems[], decisions[]}) uit de status en schrijft zijn eigen deel naar zijn eigen tabel — notities, actiepunten of beslissingen. Eerder opgeslagen rijen worden bij een gedegradeerde run nooit gewist.
Andere ingebouwde bodies
Sectie getiteld “Andere ingebouwde bodies”| Body-sleutel | Beschrijving |
|---|---|
meeting.identifySpeakers |
Sprekersherkenning over vergaderingen heen: matcht gediariseerde sprekers tegen opgeslagen stemprofielen en past zekere overeenkomsten automatisch toe. No-op zonder profielen of embeddings. |
meeting.updateTranscript |
Past de labels Person N uit diarization_spans toe, voegt fragmenten per venster samen tot beurten per spreker en legt daarna het opgeschoonde transcript vast. No-op wanneer de sprekersscheiding niets heeft opgeleverd. |
meeting.assemblePlayback |
Stelt het gemengde afspeelspoor van de vergadering samen uit de bewaarde WAV’s per kanaal. No-op wanneer er geen audio is bewaard. |
orchestration.markPhase |
Schrijft aan het einde van de werk-DAG mislukkings-sentinels voor subtickets zonder uitvoer en zet de orkestratie om naar synthesizing. |
orchestration.persistDeliverable |
Schrijft de uitvoer van de synthese naar het bovenliggende ticket, rondt dat af, plaatst het eindresultaat en markeert de orkestratie als completed. |
orchestration.awaitApproval |
Poort voor gedeeltelijke goedkeuring: voltooit onmiddellijk wanneer de nodesleutel van de stap in de goedgekeurde verzameling van de orkestratie zit, en blijft anders onderbroken tot een latere goedkeuring hem hervat. Dit is de enige body die extras.awaitApproval instelt, wat hem uitzondert van de time-out van 24 uur voor onderbroken stappen. |
messaging.createSpace |
Opent het gesprek waarin de rest van het sjabloon werkt, gepubliceerd onder de outputKey van de stap (ingebouwde sjablonen gebruiken pipeline_space_id). Een lege lijst repoIds checkt niets uit; extras['allRepos'] checkt elke repo van de werkruimte uit. extras['createConversation'] (standaard uit) opent ook een benoemde stroom. Een agentstap VOEGT ZICH BIJ een ruimte en opent er nooit een, dus een fan-out zonder deze node mislukt bij het dispatchen — en hem één keer aansluiten betekent dat de hele fan-out één checkout deelt in plaats van dat er voor elk een wordt ingericht. |
prReview.finalize |
De laatste stap van het PR-reviewsjabloon: sorteert de verzamelde reviewnodes in consensusgroepen en berekent het oordeel per PR. |
skills.analyze |
Draait de toeleveringsketenscan voor skills over de geïnstalleerde skills van een werkruimte en legt elk oordeel vast. |
Stapresultaten
Sectie getiteld “Stapresultaten”Een stapbody geeft een StepResult terug (packages/cc_domain/lib/features/pipelines/domain/entities/step_result.dart). Alle factories accepteren een optionele map mutatedState die in de pipelinestatus wordt samengevoegd, behalve failed.
| Factory | Signatuur | Beschrijving |
|---|---|---|
ok |
StepResult.ok({mutatedState}) |
Normale voltooiing; stroomafwaartse luisteraars worden geëvalueerd |
route |
StepResult.route(nextRouterKey, {mutatedState}) |
Voltooiing van de router; selecteert de stroomafwaartse tak waarvan de routeKey overeenkomt |
suspendUntilEvent |
StepResult.suspendUntilEvent(eventType, {mutatedState}) |
Pauzeert tot een specifiek type domeingebeurtenis optreedt |
suspendUntilTasksComplete |
StepResult.suspendUntilTasksComplete(taskIds, {mutatedState}) |
Pauzeert tot alle vermelde taken een eindtoestand bereiken |
terminal |
StepResult.terminal({mutatedState}) |
De pipelinerun is klaar — geen verdere stappen |
failed |
StepResult.failed(errorMessage) |
De stap is mislukt met een foutmelding |
StepRetryPolicy
Sectie getiteld “StepRetryPolicy”Herkansingsgedrag voor een mislukkende nodebody (PipelineNodeConfig.retryPolicy; null schakelt herkansingen uit).
| Veld | Type | Beschrijving |
|---|---|---|
maxAttempts |
int |
Totaal aantal pogingen inclusief de eerste (3 = 1 poging + 2 herkansingen); moet ≥ 1 zijn |
backoff |
String |
linear of exponential (standaard) |
initialDelayMs |
int |
Vertraging vóór de eerste herkansing, in milliseconden; latere vertragingen groeien volgens backoff |
PipelineNodeConfig
Sectie getiteld “PipelineNodeConfig”Configuratie per node, meegevoerd in de stapdefinitie (packages/cc_domain/lib/features/pipelines/domain/entities/pipeline_node_config.dart). Ingebouwde en aangepaste nodes delen deze vorm; elke body leest alleen de velden die hij nodig heeft.
| Veld | Type | Beschrijving |
|---|---|---|
prompt |
String? |
Prompttemplate met {{key}}-substitutie |
script |
String? |
Body van het bash-script met {{key}}-substitutie |
agentId |
String? |
Werkruimtegebonden agent-UUID om te dispatchen |
inputKeys |
List<String> |
Statussleutels die deze node als invoer gebruikt |
repoIds |
List<String> |
Repo’s die de node messaging.createSpace uitcheckt (<repoId> of <repoId>@<branch>). Leeg = geen enkele; extras['allRepos'] = elke repo van de werkruimte. Genegeerd op agentstappen. |
outputKey |
String? |
Statussleutel waaronder de uitvoer van deze node wordt geschreven |
label |
String? |
Menselijk label dat op het canvas wordt getoond (standaard de stap-ID) |
outputSchema |
Map<String, dynamic>? |
JSON Schema (deelverzameling) waaraan de uitvoerwaarde moet voldoen |
reducer |
String? |
Samenvoegstrategie wanneer parallelle takken naar dezelfde outputKey schrijven: append, mergeLists, mergeMaps, sum of override (standaard) |
retryPolicy |
StepRetryPolicy? |
Herkansingsbeleid bij een mislukte body; null = één poging |
continueOnFail |
bool |
Wanneer waar, laat een terminale mislukking de run niet mislukken; de fout wordt opgeborgen onder state['_stepErrors'][stepId] |
timeoutMs |
int? |
Time-out op wandkloktijd voor de nodebody, in milliseconden; null = geen time-out |
teamId |
String? |
Team om te dispatchen (team.dispatch-nodes); wederzijds uitsluitend met agentId |
dispatchMode |
String? |
Uitvoeringsmodus van het team: allParallel of manager |
extras |
Map<String, dynamic> |
Vrije body-specifieke configuratie (bijvoorbeeld iterableKey, templateId, voorwaardebomen) |
Afgeleide accessors: spaceId (extras['spaceId'] — bestaand gesprek om in te werken), createsConversation (extras['createConversation']), conversationTitle (extras['conversationTitle']), modeName (extras['mode'] — chat / review / plan, gelezen op de ruimteopenende node) en runWhen (extras['runWhen'] — sla de node over wanneer niet voldaan).