Skip to content

PipelineExecutionService

Target

This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.

Bounded context BC-23 Source & Pipelines
Platform / plane DevOps / GitOps / Execution
Deployment granularity module of host · host DeliveryHost
Status target · ConnectSoft.Factory.Delivery.Pipelines
Built from connectsoft-microservice · libraries: connectsoft-extensions-saas-abstractions, connectsoft-extensions-messaging-model, connectsoft-extensions-persistence-model-nhibernate
Decisions ADR-0014
Traceability FR-07 FUX-05 FUX-06 NFR-08 NFR-12 XL-04 XL-10

Purpose and responsibilities

PipelineExecutionService keeps two mirrors with provenance. A change proposal is what the propose-change-set tool produced: a change-set artifact pushed as a branch, a pull request opened, reviews, and a merge — each state mirrored from verified webhook deliveries (BC-17) or connector reads, never written by the Factory directly. A pipeline run is the system of record's run with its stages and typed results: build, unit and integration tests, coverage, static analysis, security scan, SBOM, packages, container images and attestations, each a receipt with an artifact reference. Every Factory-authored commit carries trailers naming the run, the change-set hash and the agent release, so a human reading the repository sees exactly which run wrote what.

It absorbs BuildResultService; repository, branch, commit and pull-request "services" of the June-2026 catalog are external canonical rows.

Context and boundaries

flowchart LR
    S["PipelineExecutionService"]
    ToolAdapterService["ToolAdapterService"] -->|grpc| S
    StudioBff["StudioBff"] -->|sync-http| S
    S -->|grpc| ConnectorRegistryService["ConnectorRegistryService"]
    S -->|grpc| ArtifactService["ArtifactService"]
    S -. "ChangeProposalOpened" .-> E_ChangeProposalOpened(("event"))
    S -. "ChangeProposalStateChanged" .-> E_ChangeProposalStateChanged(("event"))
    S -. "ChangeProposalMerged" .-> E_ChangeProposalMerged(("event"))
    S -. "PipelineRunStarted" .-> E_PipelineRunStarted(("event"))
    S -. "PipelineRunCompleted" .-> E_PipelineRunCompleted(("event"))
Hold "Alt" / "Option" to enable pan & zoom

Merging is a human or branch-policy decision in the system of record; the Factory never auto-merges to a protected branch without an approval of class shared-write recorded here. A missed webhook is reconciled by polling, never assumed; merge lead time per proposal is the §51 agent-success signal for code changes.

Domain model

ChangeProposal — A change set the Factory proposed (through the propose-change-set tool, shared-write class) and its life in the system of record: repository, branch, commits, pull request, reviews and merge — with provenance to the run, attempt, agent release and change-set artifact. (catalog entry)

Field Type Required Description
proposalId guid yes
tenantId string yes
projectId string yes
runId guid yes
attemptId guid yes
agentReleaseId string yes
changeSetRef string yes Artifact reference (change-set-v1)
system enum:SystemOfRecord yes
repository string yes
branch string yes
pullRequestRef string no
commits list:string yes
state enum:ProposalState yes
reviewers json no
mergedCommit string no
updatedAt datetime yes

Invariants:

  • The system of record is the truth of branches, commits and pull requests; the proposal mirrors it from verified deliveries and connector reads, never the other way round.
  • Every commit the Factory authors carries the run id and change-set hash in its trailer; a proposal without provenance is not Factory-authored.
  • A merge is a human or policy decision in the system of record; the Factory never auto-merges to a protected branch without an approval of class shared-write recorded here.
stateDiagram-v2
    Proposed --> BranchCreated : BranchPushed
    BranchCreated --> PullRequestOpen : PullRequestOpened
    PullRequestOpen --> ChangesRequested : ReviewRequestedChanges
    ChangesRequested --> PullRequestOpen : NewCommits
    PullRequestOpen --> Approved : ReviewApproved
    Approved --> Merged : Merged
    PullRequestOpen --> Abandoned : Closed
Hold "Alt" / "Option" to enable pan & zoom

Events: ChangeProposalOpened, ChangeProposalStateChanged, ChangeProposalMerged · Tables: ChangeProposals, ProposalCommits · Repository: ChangeProposalRepository

PipelineRun — A mirrored pipeline run with its stages and typed results (build, tests, coverage, static analysis, security scan, SBOM, packages, images, attestations) and the proposal or release that triggered it. (catalog entry)

Field Type Required Description
pipelineRunId guid yes
tenantId string yes
projectId string yes
system enum:SystemOfRecord yes
externalRunRef string yes
definitionRef string yes Pipeline definition in the repository (generated by the Factory from the pipeline blueprint).
proposalId guid no
commit string yes
state enum:PipelineRunState yes
stages json yes
startedAt datetime yes
completedAt datetime no

Invariants:

  • Results are receipts with artifact references; logs and reports live in the artifact store, not here.
  • A run's state comes from verified deliveries (webhooks) or a connector read; a missing final delivery is reconciled by polling, never assumed.

Events: PipelineRunStarted, PipelineRunCompleted · Tables: PipelineRuns, PipelineResults · Repository: PipelineRunRepository

erDiagram
    ChangeProposal {
        guid proposalId PK
        string tenantId
        string projectId
        guid runId
        guid attemptId
        string agentReleaseId
        string changeSetRef
        enum_SystemOfRecord system
        string repository
        string branch
        string pullRequestRef
        list_string commits
        enum_ProposalState state
        json reviewers
        string mergedCommit
        datetime updatedAt
    }
    PipelineRun {
        guid pipelineRunId PK
        string tenantId
        string projectId
        enum_SystemOfRecord system
        string externalRunRef
        string definitionRef
        guid proposalId
        string commit
        enum_PipelineRunState state
        json stages
        datetime startedAt
        datetime completedAt
    }
    PipelineResult {
        enum_ResultKind kind

        bool passed

        json summary

        string artifactRef

    }
    PipelineRun ||--o{ PipelineResult : contains
Hold "Alt" / "Option" to enable pan & zoom

Entities and value objects

PipelineResult (entity, in PipelineRun) — One typed result of a run.

Field Type Required Description
kind enum:ResultKind yes
passed bool yes
summary json yes counts, percentages, severities
artifactRef string no

Data model and storage

Store Role Engine / profile Tables
Delivery store primary azure-sql / nhibernate-sqlserver ChangeProposals, ProposalCommits, PipelineRuns, PipelineResults
Table Owner Columns Indexes
dbo.ChangeProposals ChangeProposal 15 2
dbo.ProposalCommits ChangeProposal 5 0
dbo.PipelineRuns PipelineRun 12 2
dbo.PipelineResults PipelineResult 6 0

Full DDL: appendix.

APIs

Method Path Operation Scope Side effects Idempotency Gateway Summary
GET /factory/delivery/proposals ListChangeProposals factory.delivery.read read natural GW-03 Change proposals by project, run, repository and state with pull-request references.
GET /factory/delivery/proposals/{proposalId} GetChangeProposal factory.delivery.read read natural GW-03 One proposal with commits, reviews, pipeline runs and provenance.
POST /factory/delivery/proposals OpenChangeProposal factory.delivery.propose shared-write key-header GW-03 Push a change set as a branch and open a pull request in the system of record (shared-write class; called by the propose-change-set tool with its receipt).
GET /factory/delivery/pipeline-runs ListPipelineRuns factory.delivery.read read natural GW-03 Pipeline runs by project, commit, proposal and state.
GET /factory/delivery/pipeline-runs/{pipelineRunId} GetPipelineRun factory.delivery.read read natural GW-03 Stages and typed results with artifact references.
POST /factory/delivery/pipeline-runs/{pipelineRunId}/reconcile ReconcilePipelineRun factory.delivery.operate shared-write natural GW-03 Re-read the run from the system of record when a delivery was missed (Operator).
gRPC service Method Streaming Visibility Side effects Summary
Pipelines RecordProposal none internal shared-write Record a proposal opened by the propose-change-set tool with its receipt.

Messages

Event Topic Scope / v Aggregate Consumers Summary
ChangeProposalOpened pipelines.proposals.v1.change-proposal-opened integration / 1 ChangeProposal RunControlService, StudioBff, AuditService, DashboardService A Factory change set is a branch and pull request in the system of record.
ChangeProposalStateChanged pipelines.proposals.v1.change-proposal-state-changed integration / 1 ChangeProposal RunControlService, StudioBff, DashboardService Review or pull-request state changed.
ChangeProposalMerged pipelines.proposals.v1.change-proposal-merged integration / 1 ChangeProposal GenerationRecipeService, RunControlService, ReleaseService, RepositoryIntelligenceService, StudioBff, AuditService, FeedbackService The proposal was merged; the merged commit is known.
PipelineRunStarted pipelines.runs.v1.pipeline-run-started integration / 1 PipelineRun StudioBff, DashboardService A pipeline run started in the system of record.
PipelineRunCompleted pipelines.runs.v1.pipeline-run-completed integration / 1 PipelineRun TemplateRegistryService, ReleaseService, RunControlService, StudioBff, DashboardService, AuditService, QualityScoreService A pipeline run completed with typed results.

ChangeProposalOpened payload:

Field Type Required Description
proposalId guid yes
tenantId string yes
projectId string yes
runId guid yes
repository string yes
pullRequestRef string no

ChangeProposalStateChanged payload:

Field Type Required Description
proposalId guid yes
tenantId string yes
runId guid yes
fromState enum:ProposalState yes
toState enum:ProposalState yes

ChangeProposalMerged payload:

Field Type Required Description
proposalId guid yes
tenantId string yes
projectId string yes
runId guid yes
mergedCommit string yes

PipelineRunStarted payload:

Field Type Required Description
pipelineRunId guid yes
tenantId string yes
projectId string yes
commit string yes
proposalId guid no

PipelineRunCompleted payload:

Field Type Required Description
pipelineRunId guid yes
tenantId string yes
projectId string yes
commit string yes
state enum:PipelineRunState yes
results json yes
Command Handled by Result events Summary
OpenChangeProposal ChangeProposal ChangeProposalOpened
ReconcilePipelineRun PipelineRun PipelineRunCompleted
Event Producer Handler Purpose
DeliveryReceived ConnectorRegistryService ApplyDelivery Verified webhooks from Azure DevOps and GitHub: push, pull request, review, pipeline run events.
ArtifactValidated ArtifactService LinkValidation Local validator results of a change set before it is proposed.

Workers and jobs

Worker Trigger Output events Retry Idempotency key Summary
DeliveryApplier event ChangeProposalStateChanged, ChangeProposalMerged, PipelineRunStarted, PipelineRunCompleted exponential deliveryId Maps verified inbound deliveries (push, pull request, review, pipeline run) to proposal and run state; unknown references are looked up through the connector.
RunReconciler schedule */10 * * * * PipelineRunCompleted, ChangeProposalStateChanged fixed pipelineRunId + window Polls runs still Running past their expected duration and proposals without a terminal state through the connector (read class).

Actors and grains

None modelled

No grains are modelled for this item yet.

Sagas and long-running flows

None modelled

No sagas are modelled for this item yet.

sequenceDiagram
    participant A as Agent attempt (runtime)
    participant T as ToolAdapterService (propose-change-set)
    participant P as PipelineExecutionService
    participant SOR as Azure DevOps / GitHub (via connector)
    participant W as WebhookGatewayService → ConnectorRegistryService
    A->>T: propose-change-set (change-set artifact)
    T->>SOR: push branch, open pull request (shared-write, receipt)
    T->>P: RecordProposal (receipt)
    P-)A: ChangeProposalOpened
    SOR-)W: webhook: pipeline run started / completed, review, merge
    W-)P: DeliveryReceived (verified)
    P->>P: mirror state, attach typed results
    P-)A: PipelineRunCompleted / ChangeProposalMerged
Hold "Alt" / "Option" to enable pan & zoom
stateDiagram-v2
    [*] --> Proposed
    Proposed --> BranchCreated: BranchPushed
    BranchCreated --> PullRequestOpen: PullRequestOpened
    PullRequestOpen --> ChangesRequested: ReviewRequestedChanges
    ChangesRequested --> PullRequestOpen: NewCommits
    PullRequestOpen --> Approved: ReviewApproved
    Approved --> Merged: Merged
    PullRequestOpen --> Abandoned: Closed
Hold "Alt" / "Option" to enable pan & zoom

Options and configuration

Section Key Type Default Reloadable Secret Summary
Delivery:Pipelines CommitTrailerKeys string[] [Factory-Run, Factory-ChangeSet, Factory-Agent] no no Git trailers every Factory-authored commit carries.
Delivery:Pipelines ReconcileAfterMinutes int 60 yes no Age after which a non-terminal run is polled.

Metrics and observability

Metric Instrument Unit Dimensions Summary
connectsoft.factory.delivery.proposals updown {proposal} tenant, state Proposals by state.
connectsoft.factory.delivery.pipeline_runs counter {run} tenant, state Pipeline runs by outcome.
connectsoft.factory.delivery.pipeline_duration histogram s tenant Pipeline run duration.
connectsoft.factory.delivery.merge_lead_time histogram s tenant Time from proposal to merge (the §51 agent-success signal for code changes).

Security

Authentication client-credentials
Scopes factory.delivery.read (Read proposals and runs.); factory.delivery.propose (Open proposals (the propose-change-set tool under its receipt).); factory.delivery.operate (Reconcile (Operator).)
Roles Requester, Reviewer, Operator, PlatformAdmin, Observer
Tenant isolation row-filter
Data classification internal
Max side-effect class shared-write
Secrets —

Dependencies

Outbound

Target Kind Purpose Failure mode Required
ConnectorRegistryService grpc Azure DevOps and GitHub connectors (shared-write) and inbound deliveries. degrade yes
ArtifactService grpc Change sets, logs and reports. fail-fast yes

Inbound

Target Kind Purpose Failure mode Required
ToolAdapterService grpc RecordProposal from the propose-change-set tool. — yes
StudioBff sync-http Proposal and pipeline views. — yes

Failure and recovery

Scenario Detection Recovery Data impact RTO (min)
Webhook delivery missed run non-terminal past threshold RunReconciler polls the system of record delayed state 70
Push refused by branch policy connector error proposal stays Proposed with the reason; the agent attempt records a failed shared-write none 0

NFR targets

Target Class value (pilot-batch) Override
latency_p95_ms 0 —
availability_pct 99.5 —
throughput_rps 10 —
rpo_minutes 15 —
rto_minutes 240 —
cost_class medium —

Deployment

Granularity module of host · host DeliveryHost
Topologies saas-default, hybrid, on-prem, hybrid-compute
Runtime —; replicas —–—
Ports —

Current implementation

ConnectSoft.AzurePipelines defines the pipelines every template repository runs; the Azure DevOps and GitHub MCP tool descriptors exist in the tools catalog. No proposal or run mirror, no typed results, no commit trailers.

Later capabilities

Pipeline definitions generated from the pipeline blueprint and validated against the registry; test-impact selection fed by repository intelligence; flaky-test tracking as a typed result.

Decisions and traceability

Family Ids
FR FR-07
FUX FUX-05, FUX-06
NFR NFR-08, NFR-12
XL XL-04, XL-10