@cat-factory/orchestration 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/container.d.ts +460 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +657 -0
- package/dist/container.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/board/BoardService.d.ts +125 -0
- package/dist/modules/board/BoardService.d.ts.map +1 -0
- package/dist/modules/board/BoardService.js +496 -0
- package/dist/modules/board/BoardService.js.map +1 -0
- package/dist/modules/board/board.logic.d.ts +17 -0
- package/dist/modules/board/board.logic.d.ts.map +1 -0
- package/dist/modules/board/board.logic.js +51 -0
- package/dist/modules/board/board.logic.js.map +1 -0
- package/dist/modules/boardScan/BoardScanService.d.ts +35 -0
- package/dist/modules/boardScan/BoardScanService.d.ts.map +1 -0
- package/dist/modules/boardScan/BoardScanService.js +91 -0
- package/dist/modules/boardScan/BoardScanService.js.map +1 -0
- package/dist/modules/boardScan/board-scan.logic.d.ts +10 -0
- package/dist/modules/boardScan/board-scan.logic.d.ts.map +1 -0
- package/dist/modules/boardScan/board-scan.logic.js +26 -0
- package/dist/modules/boardScan/board-scan.logic.js.map +1 -0
- package/dist/modules/bootstrap/BootstrapService.d.ts +114 -0
- package/dist/modules/bootstrap/BootstrapService.d.ts.map +1 -0
- package/dist/modules/bootstrap/BootstrapService.js +516 -0
- package/dist/modules/bootstrap/BootstrapService.js.map +1 -0
- package/dist/modules/clarity/ClarityReviewService.d.ts +48 -0
- package/dist/modules/clarity/ClarityReviewService.d.ts.map +1 -0
- package/dist/modules/clarity/ClarityReviewService.js +63 -0
- package/dist/modules/clarity/ClarityReviewService.js.map +1 -0
- package/dist/modules/clarity/clarity.logic.d.ts +36 -0
- package/dist/modules/clarity/clarity.logic.d.ts.map +1 -0
- package/dist/modules/clarity/clarity.logic.js +98 -0
- package/dist/modules/clarity/clarity.logic.js.map +1 -0
- package/dist/modules/estimation/estimate.logic.d.ts +11 -0
- package/dist/modules/estimation/estimate.logic.d.ts.map +1 -0
- package/dist/modules/estimation/estimate.logic.js +37 -0
- package/dist/modules/estimation/estimate.logic.js.map +1 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts +114 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -0
- package/dist/modules/execution/AgentContextBuilder.js +316 -0
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -0
- package/dist/modules/execution/CompanionController.d.ts +60 -0
- package/dist/modules/execution/CompanionController.d.ts.map +1 -0
- package/dist/modules/execution/CompanionController.js +216 -0
- package/dist/modules/execution/CompanionController.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +874 -0
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -0
- package/dist/modules/execution/ExecutionService.js +2921 -0
- package/dist/modules/execution/ExecutionService.js.map +1 -0
- package/dist/modules/execution/MergeResolver.d.ts +34 -0
- package/dist/modules/execution/MergeResolver.d.ts.map +1 -0
- package/dist/modules/execution/MergeResolver.js +81 -0
- package/dist/modules/execution/MergeResolver.js.map +1 -0
- package/dist/modules/execution/ReviewGateController.d.ts +163 -0
- package/dist/modules/execution/ReviewGateController.d.ts.map +1 -0
- package/dist/modules/execution/ReviewGateController.js +251 -0
- package/dist/modules/execution/ReviewGateController.js.map +1 -0
- package/dist/modules/execution/TesterController.d.ts +61 -0
- package/dist/modules/execution/TesterController.d.ts.map +1 -0
- package/dist/modules/execution/TesterController.js +215 -0
- package/dist/modules/execution/TesterController.js.map +1 -0
- package/dist/modules/execution/advance.d.ts +84 -0
- package/dist/modules/execution/advance.d.ts.map +1 -0
- package/dist/modules/execution/advance.js +2 -0
- package/dist/modules/execution/advance.js.map +1 -0
- package/dist/modules/execution/artifact-review.logic.d.ts +25 -0
- package/dist/modules/execution/artifact-review.logic.d.ts.map +1 -0
- package/dist/modules/execution/artifact-review.logic.js +39 -0
- package/dist/modules/execution/artifact-review.logic.js.map +1 -0
- package/dist/modules/execution/ci.logic.d.ts +101 -0
- package/dist/modules/execution/ci.logic.d.ts.map +1 -0
- package/dist/modules/execution/ci.logic.js +117 -0
- package/dist/modules/execution/ci.logic.js.map +1 -0
- package/dist/modules/execution/drive.d.ts +47 -0
- package/dist/modules/execution/drive.d.ts.map +1 -0
- package/dist/modules/execution/drive.js +112 -0
- package/dist/modules/execution/drive.js.map +1 -0
- package/dist/modules/execution/gates.d.ts +97 -0
- package/dist/modules/execution/gates.d.ts.map +1 -0
- package/dist/modules/execution/gates.js +2 -0
- package/dist/modules/execution/gates.js.map +1 -0
- package/dist/modules/execution/individualVendors.logic.d.ts +22 -0
- package/dist/modules/execution/individualVendors.logic.d.ts.map +1 -0
- package/dist/modules/execution/individualVendors.logic.js +33 -0
- package/dist/modules/execution/individualVendors.logic.js.map +1 -0
- package/dist/modules/execution/job.logic.d.ts +52 -0
- package/dist/modules/execution/job.logic.d.ts.map +1 -0
- package/dist/modules/execution/job.logic.js +56 -0
- package/dist/modules/execution/job.logic.js.map +1 -0
- package/dist/modules/execution/release.logic.d.ts +43 -0
- package/dist/modules/execution/release.logic.d.ts.map +1 -0
- package/dist/modules/execution/release.logic.js +49 -0
- package/dist/modules/execution/release.logic.js.map +1 -0
- package/dist/modules/execution/retry.logic.d.ts +40 -0
- package/dist/modules/execution/retry.logic.d.ts.map +1 -0
- package/dist/modules/execution/retry.logic.js +83 -0
- package/dist/modules/execution/retry.logic.js.map +1 -0
- package/dist/modules/execution/stepGating.logic.d.ts +15 -0
- package/dist/modules/execution/stepGating.logic.d.ts.map +1 -0
- package/dist/modules/execution/stepGating.logic.js +29 -0
- package/dist/modules/execution/stepGating.logic.js.map +1 -0
- package/dist/modules/execution/stepResolvers.d.ts +41 -0
- package/dist/modules/execution/stepResolvers.d.ts.map +1 -0
- package/dist/modules/execution/stepResolvers.js +2 -0
- package/dist/modules/execution/stepResolvers.js.map +1 -0
- package/dist/modules/execution/tester-infra.logic.d.ts +42 -0
- package/dist/modules/execution/tester-infra.logic.d.ts.map +1 -0
- package/dist/modules/execution/tester-infra.logic.js +46 -0
- package/dist/modules/execution/tester-infra.logic.js.map +1 -0
- package/dist/modules/merge/MergePresetService.d.ts +32 -0
- package/dist/modules/merge/MergePresetService.d.ts.map +1 -0
- package/dist/modules/merge/MergePresetService.js +109 -0
- package/dist/modules/merge/MergePresetService.js.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.d.ts +22 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.d.ts.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.js +28 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.js.map +1 -0
- package/dist/modules/notifications/NotificationService.d.ts +74 -0
- package/dist/modules/notifications/NotificationService.d.ts.map +1 -0
- package/dist/modules/notifications/NotificationService.js +131 -0
- package/dist/modules/notifications/NotificationService.js.map +1 -0
- package/dist/modules/observability/LlmObservabilityService.d.ts +121 -0
- package/dist/modules/observability/LlmObservabilityService.d.ts.map +1 -0
- package/dist/modules/observability/LlmObservabilityService.js +140 -0
- package/dist/modules/observability/LlmObservabilityService.js.map +1 -0
- package/dist/modules/observability/observability.logic.d.ts +57 -0
- package/dist/modules/observability/observability.logic.d.ts.map +1 -0
- package/dist/modules/observability/observability.logic.js +186 -0
- package/dist/modules/observability/observability.logic.js.map +1 -0
- package/dist/modules/pipelines/PipelineService.d.ts +54 -0
- package/dist/modules/pipelines/PipelineService.d.ts.map +1 -0
- package/dist/modules/pipelines/PipelineService.js +226 -0
- package/dist/modules/pipelines/PipelineService.js.map +1 -0
- package/dist/modules/pipelines/pipelineShape.d.ts +53 -0
- package/dist/modules/pipelines/pipelineShape.d.ts.map +1 -0
- package/dist/modules/pipelines/pipelineShape.js +74 -0
- package/dist/modules/pipelines/pipelineShape.js.map +1 -0
- package/dist/modules/recurring/RecurringPipelineService.d.ts +76 -0
- package/dist/modules/recurring/RecurringPipelineService.d.ts.map +1 -0
- package/dist/modules/recurring/RecurringPipelineService.js +295 -0
- package/dist/modules/recurring/RecurringPipelineService.js.map +1 -0
- package/dist/modules/recurring/TrackerSettingsService.d.ts +16 -0
- package/dist/modules/recurring/TrackerSettingsService.d.ts.map +1 -0
- package/dist/modules/recurring/TrackerSettingsService.js +30 -0
- package/dist/modules/recurring/TrackerSettingsService.js.map +1 -0
- package/dist/modules/recurring/schedule.logic.d.ts +14 -0
- package/dist/modules/recurring/schedule.logic.d.ts.map +1 -0
- package/dist/modules/recurring/schedule.logic.js +85 -0
- package/dist/modules/recurring/schedule.logic.js.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.d.ts +38 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.d.ts.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.js +96 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts +48 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.js +83 -0
- package/dist/modules/requirements/RequirementReviewService.js.map +1 -0
- package/dist/modules/requirements/requirements.logic.d.ts +93 -0
- package/dist/modules/requirements/requirements.logic.d.ts.map +1 -0
- package/dist/modules/requirements/requirements.logic.js +203 -0
- package/dist/modules/requirements/requirements.logic.js.map +1 -0
- package/dist/modules/review/IterativeReviewService.d.ts +175 -0
- package/dist/modules/review/IterativeReviewService.d.ts.map +1 -0
- package/dist/modules/review/IterativeReviewService.js +327 -0
- package/dist/modules/review/IterativeReviewService.js.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.d.ts +20 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.d.ts.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.js +26 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.js.map +1 -0
- package/dist/modules/services/ServiceMountService.d.ts +48 -0
- package/dist/modules/services/ServiceMountService.d.ts.map +1 -0
- package/dist/modules/services/ServiceMountService.js +90 -0
- package/dist/modules/services/ServiceMountService.js.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsService.d.ts +22 -0
- package/dist/modules/settings/WorkspaceSettingsService.d.ts.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsService.js +50 -0
- package/dist/modules/settings/WorkspaceSettingsService.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,874 @@
|
|
|
1
|
+
import type { AgentFailureKind, Block, BlueprintService, CiStatusProvider, ExecutionInstance, MergePresetRepository, PullRequestMerger, PullRequestMergeabilityProvider, ReleaseHealthProvider, IncidentEnrichmentProvider, StepReviewComment, SubscriptionActivationRepository, TicketTrackerProvider } from '@cat-factory/kernel';
|
|
2
|
+
import { type HasPersonalSubscription } from './individualVendors.logic.js';
|
|
3
|
+
import { type ProviderCapabilities, type SubscriptionVendor } from '@cat-factory/kernel';
|
|
4
|
+
import type { NotificationService } from '../notifications/NotificationService.js';
|
|
5
|
+
import type { WorkspaceSettingsService } from '../settings/WorkspaceSettingsService.js';
|
|
6
|
+
import type { RequirementReviewService } from '../requirements/RequirementReviewService.js';
|
|
7
|
+
import type { ClarityReviewService } from '../clarity/ClarityReviewService.js';
|
|
8
|
+
import type { IterationCapChoice, RequirementReview, ClarityReview, ResolveRequirementsExceededChoice } from '@cat-factory/kernel';
|
|
9
|
+
import type { LlmObservabilityService } from '../observability/LlmObservabilityService.js';
|
|
10
|
+
import type { AccountRepository, BlockRepository, ExecutionRepository, PipelineRepository, WorkspaceRepository } from '@cat-factory/kernel';
|
|
11
|
+
import type { Clock, IdGenerator } from '@cat-factory/kernel';
|
|
12
|
+
import type { AgentExecutor } from '@cat-factory/kernel';
|
|
13
|
+
import type { WorkRunner } from '@cat-factory/kernel';
|
|
14
|
+
import type { ExecutionEventPublisher } from '@cat-factory/kernel';
|
|
15
|
+
import type { DocumentRepository } from '@cat-factory/kernel';
|
|
16
|
+
import type { TaskRepository } from '@cat-factory/kernel';
|
|
17
|
+
import type { RequirementReviewRepository } from '@cat-factory/kernel';
|
|
18
|
+
import type { ClarityReviewRepository } from '@cat-factory/kernel';
|
|
19
|
+
import type { EnvironmentProvisioningService } from '@cat-factory/integrations';
|
|
20
|
+
import type { BoardService } from '../board/BoardService.js';
|
|
21
|
+
import type { SpendService } from '@cat-factory/spend';
|
|
22
|
+
import type { AdvanceOptions, AdvanceResult } from './advance.js';
|
|
23
|
+
export interface ExecutionServiceDependencies {
|
|
24
|
+
workspaceRepository: WorkspaceRepository;
|
|
25
|
+
blockRepository: BlockRepository;
|
|
26
|
+
pipelineRepository: PipelineRepository;
|
|
27
|
+
executionRepository: ExecutionRepository;
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the owning account of a workspace so a service that pins no cloud
|
|
30
|
+
* provider falls back to the account's `defaultCloudProvider` at dispatch.
|
|
31
|
+
*/
|
|
32
|
+
accountRepository: AccountRepository;
|
|
33
|
+
idGenerator: IdGenerator;
|
|
34
|
+
clock: Clock;
|
|
35
|
+
agentExecutor: AgentExecutor;
|
|
36
|
+
workRunner: WorkRunner;
|
|
37
|
+
executionEventPublisher: ExecutionEventPublisher;
|
|
38
|
+
boardService: BoardService;
|
|
39
|
+
spendService: SpendService;
|
|
40
|
+
/**
|
|
41
|
+
* Optional: when the document-source integration is configured, documents
|
|
42
|
+
* linked to a block are resolved here and fed to the agent as extra context.
|
|
43
|
+
*/
|
|
44
|
+
documentRepository?: DocumentRepository;
|
|
45
|
+
/**
|
|
46
|
+
* Optional: when the task-source integration is configured, tracker issues
|
|
47
|
+
* linked to a block are resolved here and fed to the agent as extra context.
|
|
48
|
+
*/
|
|
49
|
+
taskRepository?: TaskRepository;
|
|
50
|
+
/**
|
|
51
|
+
* Optional: when the requirements-review feature is configured, a block's
|
|
52
|
+
* reworked ("incorporated") requirements are read here. When present they REPLACE
|
|
53
|
+
* the block's description + linked docs/tasks as the agent context (for every
|
|
54
|
+
* step) and become the per-task input the spec-writer aggregates. Absent
|
|
55
|
+
* → the engine uses the original description + docs/tasks unchanged.
|
|
56
|
+
*/
|
|
57
|
+
requirementReviewRepository?: RequirementReviewRepository;
|
|
58
|
+
/**
|
|
59
|
+
* Optional: the requirements-review feature's service, present when the reviewer is
|
|
60
|
+
* wired. Drives the special `requirements-review` gate step (run reviewer inline, the
|
|
61
|
+
* iterative answer → incorporate → re-review loop). Absent → the gate step passes
|
|
62
|
+
* through so pipelines run unchanged without the feature.
|
|
63
|
+
*/
|
|
64
|
+
requirementReviewService?: RequirementReviewService;
|
|
65
|
+
/**
|
|
66
|
+
* Optional: persistence for the clarity-review (bug-report triage) feature. Read here
|
|
67
|
+
* to substitute a converged clarified report as the downstream agent context (the
|
|
68
|
+
* mirror of `requirementReviewRepository`). Absent → no substitution.
|
|
69
|
+
*/
|
|
70
|
+
clarityReviewRepository?: ClarityReviewRepository;
|
|
71
|
+
/**
|
|
72
|
+
* Optional: the clarity-review feature's service, present when the reviewer is wired.
|
|
73
|
+
* Drives the special `clarity-review` gate step (inline reviewer + the iterative
|
|
74
|
+
* answer → incorporate → re-review loop). Absent → the gate step passes through.
|
|
75
|
+
*/
|
|
76
|
+
clarityReviewService?: ClarityReviewService;
|
|
77
|
+
/**
|
|
78
|
+
* Optional: when the individual-usage subscription store is configured, a finished
|
|
79
|
+
* run's per-run credential activation is deleted here the moment it reaches a terminal
|
|
80
|
+
* state, bounding standing exposure to the run's own lifetime (the TTL sweep is the
|
|
81
|
+
* backstop). Absent → activations are reclaimed by the TTL sweep alone.
|
|
82
|
+
*/
|
|
83
|
+
subscriptionActivationRepository?: SubscriptionActivationRepository;
|
|
84
|
+
/**
|
|
85
|
+
* Optional: resolve a workspace's per-agent-kind default model id (the same resolver
|
|
86
|
+
* the container executor uses for dispatch). The personal-credential gate consults it
|
|
87
|
+
* so a run whose block has NO pinned model but whose workspace default resolves to an
|
|
88
|
+
* individual-usage vendor is still gated up-front — matching what dispatch will resolve,
|
|
89
|
+
* instead of starting and then failing on a missing activation. Absent → the gate sees
|
|
90
|
+
* only the block's pinned model (env-routing defaults are operator-level and not gated).
|
|
91
|
+
*/
|
|
92
|
+
resolveWorkspaceModelDefault?: (workspaceId: string, agentKind: string) => Promise<string | undefined>;
|
|
93
|
+
/**
|
|
94
|
+
* Optional: resolve the provider capabilities (configured direct keys +
|
|
95
|
+
* subscription vendors + whether Cloudflare AI is enabled) for a workspace and the
|
|
96
|
+
* run initiator. The start guard uses it to block a pipeline whose steps' canonical
|
|
97
|
+
* models have no usable provider. Absent → the guard is skipped (tests / unconfigured
|
|
98
|
+
* facades), exactly like the existing optional engine deps.
|
|
99
|
+
*/
|
|
100
|
+
resolveProviderCapabilities?: (workspaceId: string, initiatedBy?: string | null) => Promise<ProviderCapabilities>;
|
|
101
|
+
/**
|
|
102
|
+
* Optional: when the environment integration is configured, a `deployer` step
|
|
103
|
+
* provisions an ephemeral environment deterministically through this service
|
|
104
|
+
* (no LLM), and downstream steps discover the resulting env via it.
|
|
105
|
+
*/
|
|
106
|
+
environmentProvisioning?: EnvironmentProvisioningService;
|
|
107
|
+
/**
|
|
108
|
+
* Optional: when the board-scan module is configured, a `blueprints` step's
|
|
109
|
+
* decomposition tree is reconciled onto the board through this (BoardScanService).
|
|
110
|
+
* Absent → a blueprint step still runs and commits its in-repo files, but the
|
|
111
|
+
* board isn't auto-updated from it.
|
|
112
|
+
*/
|
|
113
|
+
blueprintReconciler?: BlueprintReconciler;
|
|
114
|
+
/**
|
|
115
|
+
* Optional: raises human-actionable notifications (a PR needs a merge decision,
|
|
116
|
+
* a no-merger pipeline finished, CI fixing gave up). Absent → those events still
|
|
117
|
+
* transition the block but no notification surfaces (tests).
|
|
118
|
+
*/
|
|
119
|
+
notificationService?: NotificationService;
|
|
120
|
+
/**
|
|
121
|
+
* Optional: resolves a workspace's runtime settings so {@link ExecutionService.start}
|
|
122
|
+
* can enforce the per-service running-task limit. Absent → the limit is never enforced
|
|
123
|
+
* (tests / unconfigured facades start runs unbounded).
|
|
124
|
+
*/
|
|
125
|
+
workspaceSettingsService?: WorkspaceSettingsService;
|
|
126
|
+
/**
|
|
127
|
+
* Optional: reads a block's CI check runs so the `ci` step can gate the PR on
|
|
128
|
+
* green CI. Absent → the `ci` step is a pass-through (nothing to gate), so the
|
|
129
|
+
* engine works unchanged when GitHub CI isn't wired.
|
|
130
|
+
*/
|
|
131
|
+
ciStatusProvider?: CiStatusProvider;
|
|
132
|
+
/**
|
|
133
|
+
* Optional: reads a block's PR mergeability so the `conflicts` step can gate the
|
|
134
|
+
* PR on being mergeable. Absent → the `conflicts` step is a pass-through (nothing
|
|
135
|
+
* to gate), so the engine works unchanged when GitHub isn't wired.
|
|
136
|
+
*/
|
|
137
|
+
mergeabilityProvider?: PullRequestMergeabilityProvider;
|
|
138
|
+
/**
|
|
139
|
+
* Optional: reads a deployed release's Datadog monitors/SLOs so the
|
|
140
|
+
* `post-release-health` step can gate on the release looking healthy after deploy.
|
|
141
|
+
* Absent → the step is a pass-through (nothing to watch), so the engine works
|
|
142
|
+
* unchanged when Datadog isn't wired.
|
|
143
|
+
*/
|
|
144
|
+
releaseHealthProvider?: ReleaseHealthProvider;
|
|
145
|
+
/**
|
|
146
|
+
* Optional: annotates an incident PagerDuty / incident.io already opened from the
|
|
147
|
+
* same monitors/SLOs with the on-call agent's investigation. Best-effort enrichment,
|
|
148
|
+
* NOT alerting (those systems already paged). Absent → no enrichment.
|
|
149
|
+
*/
|
|
150
|
+
incidentEnrichment?: IncidentEnrichmentProvider;
|
|
151
|
+
/**
|
|
152
|
+
* Optional: performs the real GitHub merge when a task should become `done`.
|
|
153
|
+
* Absent → `done` is a board-only flip (tests); when wired, `done` provably
|
|
154
|
+
* means the PR was merged on the remote.
|
|
155
|
+
*/
|
|
156
|
+
pullRequestMerger?: PullRequestMerger;
|
|
157
|
+
/**
|
|
158
|
+
* Optional: resolves a task's merge threshold preset (auto-merge ceilings + the
|
|
159
|
+
* CI-fixer attempt budget). Absent → the built-in {@link DEFAULT_MERGE_PRESET}.
|
|
160
|
+
*/
|
|
161
|
+
mergePresetRepository?: MergePresetRepository;
|
|
162
|
+
/**
|
|
163
|
+
* Optional: files a GitHub issue / Jira ticket for the `tracker` step (the
|
|
164
|
+
* tech-debt recurring pipeline). Absent → the `tracker` step passes through
|
|
165
|
+
* without filing anything, so the engine works unchanged when no tracker is wired.
|
|
166
|
+
*/
|
|
167
|
+
ticketTrackerProvider?: TicketTrackerProvider;
|
|
168
|
+
/**
|
|
169
|
+
* Optional: the LLM observability sink. When wired, each emit rolls the per-run
|
|
170
|
+
* model-call aggregates onto the matching pipeline steps (`step.metrics`) so the
|
|
171
|
+
* board shows tokens / output-limit headroom / transport-vs-execution latency
|
|
172
|
+
* live. Absent (tests / unconfigured) → steps carry no `metrics`.
|
|
173
|
+
*/
|
|
174
|
+
llmObservability?: LlmObservabilityService;
|
|
175
|
+
/**
|
|
176
|
+
* Optional: whether the runtime can run the Tester's LOCAL docker-compose infra via
|
|
177
|
+
* Docker-in-Docker. Defaults to `true` (Cloudflare, Node, tests). The local facade
|
|
178
|
+
* sets it `false` for runtimes without nesting (Apple `container`), which makes
|
|
179
|
+
* {@link ExecutionService.assertTesterInfraConfigured} refuse a local-infra Tester run
|
|
180
|
+
* (steering it to the ephemeral environment or a no-infra service) instead of
|
|
181
|
+
* dispatching a job that can't stand its dependencies up.
|
|
182
|
+
*/
|
|
183
|
+
localTestInfraSupported?: boolean;
|
|
184
|
+
}
|
|
185
|
+
/** Reconciles a Blueprinter step's tree onto the board in place (BoardScanService). */
|
|
186
|
+
export interface BlueprintReconciler {
|
|
187
|
+
reconcileBlueprint(workspaceId: string, frameId: string | null, service: BlueprintService): Promise<unknown>;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The execution engine. It orchestrates a pipeline of agent-performed steps and
|
|
191
|
+
* is fully deterministic: `advanceInstance` moves one run forward by exactly one
|
|
192
|
+
* step, delegating the actual work — and the choice of whether to pause for a
|
|
193
|
+
* human decision — to the injected {@link AgentExecutor}. The durable workflow
|
|
194
|
+
* driver calls it in a loop. All LLM behaviour lives behind that port, so the
|
|
195
|
+
* engine here can be tested with a
|
|
196
|
+
* deterministic fake and no timing/delays.
|
|
197
|
+
*/
|
|
198
|
+
export declare class ExecutionService {
|
|
199
|
+
private readonly workspaceRepository;
|
|
200
|
+
private readonly blockRepository;
|
|
201
|
+
private readonly pipelineRepository;
|
|
202
|
+
private readonly executionRepository;
|
|
203
|
+
private readonly accountRepository;
|
|
204
|
+
private readonly idGenerator;
|
|
205
|
+
private readonly clock;
|
|
206
|
+
private readonly agentExecutor;
|
|
207
|
+
private readonly workRunner;
|
|
208
|
+
private readonly events;
|
|
209
|
+
private readonly board;
|
|
210
|
+
private readonly spend;
|
|
211
|
+
private readonly requirementReviewService?;
|
|
212
|
+
private readonly clarityReviewService?;
|
|
213
|
+
private readonly environmentProvisioning?;
|
|
214
|
+
/** Assembles the per-step agent context (requirements, docs, env, service frame, fragments). */
|
|
215
|
+
private readonly contextBuilder;
|
|
216
|
+
/** Resolves a `merger` step's assessment into an auto-merge or a `merge_review` notification. */
|
|
217
|
+
private readonly mergeResolver;
|
|
218
|
+
/** Drives a companion (reviewer/spec/architect) step: grade → pass / loop producer / park. */
|
|
219
|
+
private readonly companionController;
|
|
220
|
+
/** Drives the Tester gate's fix loop: report → greenlight / dispatch fixer / fail. */
|
|
221
|
+
private readonly testerController;
|
|
222
|
+
/** Drives both iterative review gates (requirements + clarity); kind-parameterised. */
|
|
223
|
+
private readonly reviewGate;
|
|
224
|
+
/** The requirements subject for {@link reviewGate}. */
|
|
225
|
+
private readonly requirementsKind;
|
|
226
|
+
/** The clarity (bug-report triage) subject for {@link reviewGate}. */
|
|
227
|
+
private readonly clarityKind;
|
|
228
|
+
private readonly blueprintReconciler?;
|
|
229
|
+
private readonly notificationService?;
|
|
230
|
+
private readonly workspaceSettingsService?;
|
|
231
|
+
private readonly llmObservability?;
|
|
232
|
+
private readonly ciStatusProvider?;
|
|
233
|
+
private readonly mergeabilityProvider?;
|
|
234
|
+
private readonly releaseHealthProvider?;
|
|
235
|
+
private readonly incidentEnrichment?;
|
|
236
|
+
private readonly prMerger?;
|
|
237
|
+
private readonly mergePresetRepository?;
|
|
238
|
+
private readonly ticketTrackerProvider?;
|
|
239
|
+
private readonly subscriptionActivations?;
|
|
240
|
+
private readonly resolveProviderCapabilities?;
|
|
241
|
+
private readonly resolveWorkspaceModelDefault?;
|
|
242
|
+
/** Whether the runtime can run the Tester's local DinD infra (false = limited mode). */
|
|
243
|
+
private readonly localTestInfraSupported;
|
|
244
|
+
/** Lazily-built polling-gate registry, keyed by `agentKind`. See {@link gateFor}. */
|
|
245
|
+
private gateRegistryCache?;
|
|
246
|
+
/**
|
|
247
|
+
* Lazily-built post-completion resolver registry, keyed by `agentKind`. See
|
|
248
|
+
* {@link stepResolverFor} and {@link StepCompletionResolver}.
|
|
249
|
+
*/
|
|
250
|
+
private stepResolverCache?;
|
|
251
|
+
constructor({ workspaceRepository, blockRepository, pipelineRepository, executionRepository, accountRepository, idGenerator, clock, agentExecutor, workRunner, executionEventPublisher, boardService, spendService, documentRepository, taskRepository, requirementReviewRepository, requirementReviewService, clarityReviewRepository, clarityReviewService, environmentProvisioning, blueprintReconciler, notificationService, workspaceSettingsService, llmObservability, ciStatusProvider, mergeabilityProvider, releaseHealthProvider, incidentEnrichment, pullRequestMerger, mergePresetRepository, ticketTrackerProvider, subscriptionActivationRepository, resolveWorkspaceModelDefault, resolveProviderCapabilities, localTestInfraSupported, }: ExecutionServiceDependencies);
|
|
252
|
+
private requireWorkspace;
|
|
253
|
+
private requireBlock;
|
|
254
|
+
/**
|
|
255
|
+
* The individual-usage subscription vendors a run STARTED against `blockId` with
|
|
256
|
+
* `pipelineId` will lease a personal credential for — so the controller can gate the
|
|
257
|
+
* run on the initiator's personal subscription(s) up-front. Mirrors the dispatch-time
|
|
258
|
+
* model precedence (block pin → workspace per-kind default) across every step, AND the
|
|
259
|
+
* per-user dispatch decision: `hasPersonalSubscription(vendor)` reports whether the
|
|
260
|
+
* initiator has their own subscription for a vendor, so a dual-mode model (GLM) only
|
|
261
|
+
* gates a subscriber (a non-subscriber runs it on the Cloudflare base, ungated).
|
|
262
|
+
* Defaults to "no personal subscription" for system/unauthenticated callers.
|
|
263
|
+
*/
|
|
264
|
+
individualVendorsForBlock(workspaceId: string, blockId: string, pipelineId: string, hasPersonalSubscription?: HasPersonalSubscription): Promise<SubscriptionVendor[]>;
|
|
265
|
+
/** The individual-usage vendors a failed run's resumed steps use (for the retry gate). */
|
|
266
|
+
individualVendorsForRun(workspaceId: string, executionId: string, hasPersonalSubscription?: HasPersonalSubscription): Promise<SubscriptionVendor[]>;
|
|
267
|
+
/**
|
|
268
|
+
* The set of individual-usage vendors the given steps resolve to, used to gate a run
|
|
269
|
+
* on the initiator's personal subscription(s) up-front. Delegates to the pure
|
|
270
|
+
* {@link resolveIndividualVendors}, which mirrors the dispatch-time precedence: a
|
|
271
|
+
* resolvable block pin decides the set alone (NONE for a non-subscription model), and
|
|
272
|
+
* only an unpinned run falls to the workspace per-kind defaults.
|
|
273
|
+
*/
|
|
274
|
+
private resolveIndividualVendors;
|
|
275
|
+
/**
|
|
276
|
+
* Guard a Tester pipeline's start: local-mode testing must have its infra
|
|
277
|
+
* configured on the service frame — either a docker-compose path to stand the
|
|
278
|
+
* dependencies up, or the explicit "no infra dependencies" flag. Ephemeral-mode
|
|
279
|
+
* testing uses the provisioned environment, so it needs neither. Throws a
|
|
280
|
+
* {@link ConflictError} (surfaced as an actionable message) when neither is set.
|
|
281
|
+
*/
|
|
282
|
+
private assertTesterInfraConfigured;
|
|
283
|
+
/**
|
|
284
|
+
* Guard a pipeline's start on having a usable provider for every step's canonical
|
|
285
|
+
* model. The model a step runs is resolved by the same precedence the dispatch path
|
|
286
|
+
* uses (block pin → workspace per-kind default); each canonical id must have a usable
|
|
287
|
+
* provider given what's configured — a direct API key for its provider, a connected
|
|
288
|
+
* subscription vendor, or the opt-in Cloudflare lib enabled. Env-routing defaults (the
|
|
289
|
+
* last fallback, with no catalog id) are operator-level and not gated, matching the
|
|
290
|
+
* personal-credential gate. A throw aborts the start cleanly before any side effects.
|
|
291
|
+
* Skipped when no capability resolver is wired (tests / unconfigured facades).
|
|
292
|
+
*/
|
|
293
|
+
private assertProvidersConfiguredForPipeline;
|
|
294
|
+
/** Start a pipeline against a block, replacing any prior run on it. */
|
|
295
|
+
start(workspaceId: string, blockId: string, pipelineId: string,
|
|
296
|
+
/**
|
|
297
|
+
* Internal user id of the initiator. Recorded on the run so an individual-usage
|
|
298
|
+
* model (Claude) uses this user's OWN personal subscription. Absent for
|
|
299
|
+
* system-initiated runs (recurring schedules) and auth-disabled dev.
|
|
300
|
+
*/
|
|
301
|
+
initiatedBy?: string | null,
|
|
302
|
+
/**
|
|
303
|
+
* Mint the per-run personal-credential activation for an individual-usage model.
|
|
304
|
+
* Invoked with the new run's id BEFORE it is persisted/dispatched, so the async
|
|
305
|
+
* steps can lease it; a throw (wrong/missing password) aborts the start cleanly
|
|
306
|
+
* with nothing persisted. The server layer supplies this (the personal store lives
|
|
307
|
+
* outside the domain Core); absent for non-individual runs.
|
|
308
|
+
*/
|
|
309
|
+
activate?: (executionId: string) => Promise<void>): Promise<ExecutionInstance>;
|
|
310
|
+
/**
|
|
311
|
+
* Enforce the workspace's per-service running-task limit before a task run starts.
|
|
312
|
+
* No-ops unless the settings module is wired, the block is a task, and a limit mode
|
|
313
|
+
* is active. Counts the tasks under the same service frame that already have a live
|
|
314
|
+
* run (running / blocked / paused) — bucketed by task type when the mode is
|
|
315
|
+
* `per_type`, else shared across all types — and throws a {@link ConflictError} (→ 409,
|
|
316
|
+
* shown as a toast) when the cap is reached. The starting block is excluded from the
|
|
317
|
+
* count (its prior run is about to be replaced).
|
|
318
|
+
*/
|
|
319
|
+
private assertWithinTaskLimit;
|
|
320
|
+
/**
|
|
321
|
+
* Advance a single run by exactly one step and report what happened. This is
|
|
322
|
+
* the durable driver's entry point: it reloads the run from storage (so it is
|
|
323
|
+
* safe under replay/retry), no-ops unless the run is actively running, and
|
|
324
|
+
* otherwise performs one agent step via the shared {@link stepInstance} logic.
|
|
325
|
+
*/
|
|
326
|
+
advanceInstance(workspaceId: string, executionId: string, options?: AdvanceOptions): Promise<AdvanceResult>;
|
|
327
|
+
/** Advance a single running instance by one step, persisting the result. */
|
|
328
|
+
private stepInstance;
|
|
329
|
+
/**
|
|
330
|
+
* Preview the model a step will run (`provider:model`) ahead of the work, so the
|
|
331
|
+
* board can show it during the inline query / container cold-boot rather than only
|
|
332
|
+
* once the result or job handle lands. Best-effort: the executor may not implement
|
|
333
|
+
* a preview, and a resolution failure (e.g. an unwired container kind that fails at
|
|
334
|
+
* dispatch anyway) must never break the run — both yield undefined.
|
|
335
|
+
*/
|
|
336
|
+
private previewStepModel;
|
|
337
|
+
/**
|
|
338
|
+
* Whether the current step will run on a flat-rate subscription (quota) model, so
|
|
339
|
+
* the spend gate can let it proceed even when the monetary budget is exhausted.
|
|
340
|
+
* Resolved through the executor (the authority on the "subscriptions always win"
|
|
341
|
+
* routing) off a full step context. Best-effort and side-effect-free: an executor
|
|
342
|
+
* without the capability, a missing block, or any resolution error all report false
|
|
343
|
+
* (the step is treated as budget-metered, the prior behaviour). Only consulted on
|
|
344
|
+
* the over-budget path, so the extra context build never touches the happy path.
|
|
345
|
+
*/
|
|
346
|
+
private currentStepIsQuotaBased;
|
|
347
|
+
/**
|
|
348
|
+
* Poll the asynchronous job a parked step dispatched. Returns `awaiting_job`
|
|
349
|
+
* while it runs (the driver keeps polling), records the result and advances on
|
|
350
|
+
* success, or reports `job_failed` so the driver can fail the run. Reading run
|
|
351
|
+
* state from storage on every call keeps it safe under Workflows replay/retry:
|
|
352
|
+
* once a job's result is recorded the step's `jobId` is cleared, so a re-poll
|
|
353
|
+
* simply lets the driver advance the now-current step.
|
|
354
|
+
*/
|
|
355
|
+
pollAgentJob(workspaceId: string, executionId: string): Promise<AdvanceResult>;
|
|
356
|
+
/**
|
|
357
|
+
* Re-run a polling gate step's precheck from the durable driver's `awaiting_gate`
|
|
358
|
+
* loop: which gate (ci / conflicts) is resolved from the current step's `agentKind`,
|
|
359
|
+
* and it returns the same outcomes as the initial evaluation (precheck passes →
|
|
360
|
+
* advance, still computing → keep polling, fails → dispatch a helper or give up).
|
|
361
|
+
* Safe under replay: reads run state fresh each call. A no-op unless the current
|
|
362
|
+
* step is a gate actively in its `checking` phase.
|
|
363
|
+
*/
|
|
364
|
+
pollGate(workspaceId: string, executionId: string): Promise<AdvanceResult>;
|
|
365
|
+
/**
|
|
366
|
+
* Decide what happens when the durable driver's GATE poll budget (ciMaxPolls ×
|
|
367
|
+
* ciPollInterval) is spent while a gate is still `pending` — called by both runtime
|
|
368
|
+
* drivers (Cloudflare ExecutionWorkflow / Node `driveExecution`) instead of failing
|
|
369
|
+
* the run directly, so the per-gate policy lives in one place. Most gates `fail`
|
|
370
|
+
* (CI never went green / the PR never became mergeable). A time-windowed watch gate
|
|
371
|
+
* (post-release-health, `pollExhaustion: 'pass'`) instead PASSES: the watch window
|
|
372
|
+
* simply outlasted the poll budget with no regression observed, which is healthy — not
|
|
373
|
+
* a timeout. Returns the result the driver should act on (it never re-fails for a fail
|
|
374
|
+
* gate; it returns a `job_failed` the driver funnels through its single `failRun`).
|
|
375
|
+
*/
|
|
376
|
+
resolveGatePollExhaustion(workspaceId: string, executionId: string): Promise<AdvanceResult>;
|
|
377
|
+
/**
|
|
378
|
+
* Transition a step into `working`, stamping its start time the first time it
|
|
379
|
+
* actually begins. Set-once so a Workflows replay (which re-runs `advance`)
|
|
380
|
+
* preserves the original start rather than resetting it on every replay. An
|
|
381
|
+
* explicit re-run clears `startedAt` first (see {@link requestStepChanges}) so
|
|
382
|
+
* the fresh attempt is timed from scratch.
|
|
383
|
+
*/
|
|
384
|
+
private startStep;
|
|
385
|
+
/**
|
|
386
|
+
* Transition a step into `done`, stamping its finish time once. Set-once so the
|
|
387
|
+
* approval-gate flow (which re-asserts `done` after a human approves, long after
|
|
388
|
+
* the agent actually finished) keeps the agent's true completion time, and so a
|
|
389
|
+
* replay doesn't move it. With {@link startStep}'s `startedAt` this yields the
|
|
390
|
+
* step's execution duration. A step finished directly out of a parked approval
|
|
391
|
+
* stopped *working* when it parked, so its duration is billed to the pause instant
|
|
392
|
+
* ({@link pauseStepForInput}), not the (later) moment the human decided.
|
|
393
|
+
*/
|
|
394
|
+
private finishStep;
|
|
395
|
+
/**
|
|
396
|
+
* Finish a gated step that was skipped (its estimate gate was not satisfied) and either
|
|
397
|
+
* complete the run or advance to the next step — the deterministic finish/advance tail
|
|
398
|
+
* of {@link recordStepResult}, minus all the agent-result handling (no LLM ran, so there
|
|
399
|
+
* is no usage / decision / PR / artifact / approval / resolver to process). The step is
|
|
400
|
+
* marked `skipped` with empty output so the UI renders "skipped (gated)".
|
|
401
|
+
*/
|
|
402
|
+
private skipGatedStep;
|
|
403
|
+
/**
|
|
404
|
+
* Park a step on a human decision and freeze its duration clock. Records when the
|
|
405
|
+
* step stopped working (`pausedAt`) so elapsed time no longer accrues while it waits
|
|
406
|
+
* for input — the symmetric counterpart of the terminal freeze on `finishedAt`.
|
|
407
|
+
* Set-once (a Workflows replay re-parking keeps the original instant); cleared when
|
|
408
|
+
* the step resumes ({@link startStep}) or finishes ({@link finishStep}).
|
|
409
|
+
*/
|
|
410
|
+
private pauseStepForInput;
|
|
411
|
+
/**
|
|
412
|
+
* Record a completed agent step's result and report what the driver should do
|
|
413
|
+
* next: meter token usage, park on a raised decision, or persist the output
|
|
414
|
+
* (and any opened PR) and either finish the run or advance to the next step.
|
|
415
|
+
* Shared by the inline path and the async-job poll path.
|
|
416
|
+
*/
|
|
417
|
+
private recordStepResult;
|
|
418
|
+
/**
|
|
419
|
+
* Reset a step so the durable driver re-runs it from scratch: clear its live
|
|
420
|
+
* container job handle (so it dispatches FRESH work rather than re-attaching to a
|
|
421
|
+
* finished or evicted job), its timings, approval gate, live subtasks and last
|
|
422
|
+
* output, and drop it back to `pending`. Preserves the step's identity
|
|
423
|
+
* (`agentKind` / `requiresApproval`) and any companion budget/verdict history.
|
|
424
|
+
*/
|
|
425
|
+
private resetStepForRerun;
|
|
426
|
+
/**
|
|
427
|
+
* Loop a producer step back for rework and re-run every step from it up to and
|
|
428
|
+
* including the companion at `companionIndex`: each one is reset (crucially clearing
|
|
429
|
+
* stale container job handles so an intermediate container step re-dispatches fresh
|
|
430
|
+
* work instead of re-attaching to its evicted job), the producer is handed the
|
|
431
|
+
* `rework` feedback + started, and the instance cursor is moved back to the producer.
|
|
432
|
+
* Shared by the automatic companion loop and the human "request changes" path.
|
|
433
|
+
*/
|
|
434
|
+
private rerunProducerThrough;
|
|
435
|
+
/**
|
|
436
|
+
* The index of the nearest preceding step a companion grades (one of its target
|
|
437
|
+
* producer kinds), or -1 when none precedes it. The single producer-search used by the
|
|
438
|
+
* automatic companion loop, the human "request changes" redirect, and the iteration-cap
|
|
439
|
+
* extra-round resolution.
|
|
440
|
+
*/
|
|
441
|
+
private companionProducerIndex;
|
|
442
|
+
/**
|
|
443
|
+
* Loop a companion's producer back for one more automatic rework cycle: charge one
|
|
444
|
+
* attempt against the budget, then re-run the producer (and any intermediate steps) up
|
|
445
|
+
* to and including the companion so it re-grades. Shared by the automatic
|
|
446
|
+
* below-threshold loop ({@link evaluateCompanion}) and the human-granted extra round
|
|
447
|
+
* ({@link resolveCompanionExceeded}), so both consume the budget identically.
|
|
448
|
+
*/
|
|
449
|
+
private loopCompanionProducer;
|
|
450
|
+
/**
|
|
451
|
+
* Deterministically provision an ephemeral environment for a deployer step.
|
|
452
|
+
* Produces a human-readable summary as the step output and reports no token
|
|
453
|
+
* usage (it incurs no LLM cost). Errors are swallowed into the output unless
|
|
454
|
+
* the durable driver wants them surfaced for its per-step retry.
|
|
455
|
+
*/
|
|
456
|
+
private runDeployer;
|
|
457
|
+
/**
|
|
458
|
+
* File a tracking issue/ticket for a `tracker` step from the preceding `analysis`
|
|
459
|
+
* output. Non-LLM and best-effort: when no provider is wired or none is configured
|
|
460
|
+
* for the workspace it simply notes the skip; a filing error is folded into the
|
|
461
|
+
* step output rather than failing the run (the implementation still proceeds).
|
|
462
|
+
*/
|
|
463
|
+
private runTracker;
|
|
464
|
+
/**
|
|
465
|
+
* The polling-gate registry, keyed by `agentKind`. A gate runs a programmatic
|
|
466
|
+
* precheck against a provider and only escalates to a helper container agent on a
|
|
467
|
+
* negative verdict. Built lazily (the closures capture `this`, so the providers /
|
|
468
|
+
* merge preset / notification helpers resolve at call time). Returns undefined for a
|
|
469
|
+
* non-gate kind. See {@link GateDefinition} and {@link evaluateGate}.
|
|
470
|
+
*/
|
|
471
|
+
private gateFor;
|
|
472
|
+
/**
|
|
473
|
+
* The post-completion resolver for an agent kind, or undefined when the kind has none.
|
|
474
|
+
* A resolver runs DETERMINISTIC backend follow-up once the step's agent finishes — e.g.
|
|
475
|
+
* the merger performs the real GitHub merge — independent of the step's position in the
|
|
476
|
+
* pipeline. Built lazily (closures capture `this`). See {@link StepCompletionResolver}.
|
|
477
|
+
*/
|
|
478
|
+
private stepResolverFor;
|
|
479
|
+
private buildStepResolverRegistry;
|
|
480
|
+
private buildGateRegistry;
|
|
481
|
+
/**
|
|
482
|
+
* Evaluate a polling gate step once and decide (shared by the initial advance and the
|
|
483
|
+
* durable `awaiting_gate` re-poll):
|
|
484
|
+
* - no provider wired → pass-through (advance; nothing to gate);
|
|
485
|
+
* - precheck passes → advance to the next step (the helper agent is NEVER spun up);
|
|
486
|
+
* - still computing → `awaiting_gate` (the driver sleeps then calls {@link pollGate});
|
|
487
|
+
* - fails, budget left → dispatch the helper container agent (`awaiting_job`);
|
|
488
|
+
* - fails, budget spent → the gate's exhaustion handler, then fail the run.
|
|
489
|
+
*/
|
|
490
|
+
private evaluateGate;
|
|
491
|
+
/**
|
|
492
|
+
* Dispatch a gate's helper container agent on a failed precheck: build the agent
|
|
493
|
+
* context with the kind overridden to the helper (it clones the PR head branch and
|
|
494
|
+
* pushes — no new PR), park on the job, and flip the gate to `working`. Idempotent
|
|
495
|
+
* under replay via the step's `jobId` (re-attach handled in {@link evaluateGate}).
|
|
496
|
+
*/
|
|
497
|
+
private dispatchGateHelper;
|
|
498
|
+
/**
|
|
499
|
+
* Raise a `decision_required` notification when a run parks on an iteration-cap gate
|
|
500
|
+
* after spending its automatic budget — a quality companion at its rework cap or an
|
|
501
|
+
* iterative reviewer (requirements / clarity) at its iteration cap. Without it the
|
|
502
|
+
* three-choice decision is reachable only by drilling into the parked step, so the run
|
|
503
|
+
* looks silently stuck. Best-effort: a missing notification service (tests) or block is
|
|
504
|
+
* a no-op.
|
|
505
|
+
*/
|
|
506
|
+
private raiseDecisionRequired;
|
|
507
|
+
/**
|
|
508
|
+
* Ensure an open notification exists for a run that has just parked waiting for a human
|
|
509
|
+
* (an agent-raised decision, an approval gate, or an iterative review gate). Without
|
|
510
|
+
* the old decision timeout the run waits indefinitely, so the inbox card — which the
|
|
511
|
+
* periodic sweep escalates yellow → red — is the only signal a human is needed.
|
|
512
|
+
*
|
|
513
|
+
* Non-clobbering: if ANY open notification is already on the block (a more specific
|
|
514
|
+
* `merge_review`, iteration-cap `decision_required`, etc.), it is left untouched and we
|
|
515
|
+
* raise nothing — so the richer message wins. Best-effort: no notification service
|
|
516
|
+
* (tests) or a missing block is a no-op.
|
|
517
|
+
*/
|
|
518
|
+
private ensureWaitingNotification;
|
|
519
|
+
/**
|
|
520
|
+
* Clear the auto-raised "waiting for a human decision" card once a run advances past
|
|
521
|
+
* the decision it was parked on (so the escalation sweep can't flip a settled decision
|
|
522
|
+
* red). Scoped to the `decision_required` type, so the human-actionable cards a stopped
|
|
523
|
+
* run leaves behind are untouched. Best-effort: no notification service (tests) is a no-op.
|
|
524
|
+
*/
|
|
525
|
+
private clearWaitingNotification;
|
|
526
|
+
/** Raise a `ci_failed` notification when the CI gate exhausts its fixer budget. */
|
|
527
|
+
private raiseCiFailed;
|
|
528
|
+
/** Provision inputs (`{{input.*}}`) derived from the block under deployment. */
|
|
529
|
+
private deployInputs;
|
|
530
|
+
/**
|
|
531
|
+
* Typed git/PR/repo context for the deployer, derived from the block's PR ref. A
|
|
532
|
+
* PR-environment provider (e.g. an in-house adapter) needs the branch/repo to target
|
|
533
|
+
* the right environment; the same values are also flattened into `{{input.*}}` for
|
|
534
|
+
* the manifest path. `owner`/`repo` are parsed from the PR url when present.
|
|
535
|
+
*/
|
|
536
|
+
private deployContext;
|
|
537
|
+
/**
|
|
538
|
+
* Invoke the agent for an already-built context. Failures are swallowed into the
|
|
539
|
+
* step output so a run never wedges — unless `rethrowAgentErrors` is set (the
|
|
540
|
+
* durable path), in which case the error propagates so the driver's per-step
|
|
541
|
+
* retry can take over.
|
|
542
|
+
*/
|
|
543
|
+
private runAgent;
|
|
544
|
+
/**
|
|
545
|
+
* Strictly parse a Blueprinter step's tree and reconcile it onto the board. The
|
|
546
|
+
* blueprint maps the whole repository, so it is reconciled onto the run block's
|
|
547
|
+
* **service frame** (walked up from the block), not the task the run targeted.
|
|
548
|
+
* Best-effort and reconciler-gated: a parse/reconcile failure is logged-by-throw
|
|
549
|
+
* upstream only when the reconciler is wired; with no reconciler it is a no-op so
|
|
550
|
+
* the blueprint's in-repo files still land.
|
|
551
|
+
*/
|
|
552
|
+
private ingestBlueprint;
|
|
553
|
+
/**
|
|
554
|
+
* Strictly validate a spec-writer step's unified specification. The canonical record
|
|
555
|
+
* is the in-repo `spec/` files the harness already committed; this is the trust
|
|
556
|
+
* boundary (a malformed payload is dropped, never trusted) plus a client refresh
|
|
557
|
+
* nudge. A persisted board projection is a deliberate later phase.
|
|
558
|
+
*/
|
|
559
|
+
private ingestSpec;
|
|
560
|
+
/**
|
|
561
|
+
* Park a step on the durable decision-wait the approval gate uses, so a human (or the
|
|
562
|
+
* dedicated review window) can drive an iterative loop and resume the run. Shared by the
|
|
563
|
+
* requirements gate and the companion iteration-cap gate: both reuse the SAME parking
|
|
564
|
+
* mechanism rather than each rolling its own. `proposal` seeds the gate's stored text
|
|
565
|
+
* (the companion's latest feedback; empty for the requirements window, which renders its
|
|
566
|
+
* own structured surface via the universal result-view registry).
|
|
567
|
+
*/
|
|
568
|
+
private parkStepOnDecision;
|
|
569
|
+
/**
|
|
570
|
+
* Two gates park on a `step.approval` but are NOT generic prose approvals — they are
|
|
571
|
+
* iterative gates driven by their own dedicated surface, never the generic
|
|
572
|
+
* approve/request-changes/reject resolvers (which would advance the run bypassing the
|
|
573
|
+
* loop). Guard those resolvers so a stray approve can't short-circuit either gate:
|
|
574
|
+
* - the requirements-review gate (driven by re-review / proceed / resolve-exceeded);
|
|
575
|
+
* - a companion gate that hit its rework cap (`companion.exceeded`), driven by
|
|
576
|
+
* {@link resolveCompanionExceeded}'s one-more-round / proceed / stop-reset choices.
|
|
577
|
+
*/
|
|
578
|
+
private assertNotIterativeGate;
|
|
579
|
+
/**
|
|
580
|
+
* The requirements subject for {@link reviewGate}: closures over the requirements reviewer
|
|
581
|
+
* service. The service-not-configured guard preserves the exact 409 the inline reviewer
|
|
582
|
+
* raised before this extraction.
|
|
583
|
+
*/
|
|
584
|
+
private buildRequirementsKind;
|
|
585
|
+
/**
|
|
586
|
+
* The clarity (bug-report triage) subject for {@link reviewGate}: threads any upstream
|
|
587
|
+
* `bug-investigator` output into the reviewer/incorporation context, otherwise identical to
|
|
588
|
+
* the requirements kind.
|
|
589
|
+
*/
|
|
590
|
+
private buildClarityKind;
|
|
591
|
+
/**
|
|
592
|
+
* Run a fresh reviewer pass over a block's collected requirements, snapshotting the
|
|
593
|
+
* task's merge-preset knobs (iteration budget + tolerated severity) onto the review.
|
|
594
|
+
* Shared by the pipeline gate and the off-path inspector "Run review" surface, so both
|
|
595
|
+
* honour the task's preset identically.
|
|
596
|
+
*/
|
|
597
|
+
reviewRequirements(workspaceId: string, blockId: string): Promise<RequirementReview>;
|
|
598
|
+
/**
|
|
599
|
+
* Incorporate the human's settled answers ASYNCHRONOUSLY. Validates that every finding is
|
|
600
|
+
* answered/dismissed, flags the review `incorporating`, records the intent on the parked
|
|
601
|
+
* gate step, and signals the durable driver to wake — which folds the answers and
|
|
602
|
+
* re-reviews in the background. Off-path (no parked run) the fold + re-review run inline.
|
|
603
|
+
*/
|
|
604
|
+
incorporateRequirements(workspaceId: string, blockId: string, feedback?: string): Promise<RequirementReview>;
|
|
605
|
+
/**
|
|
606
|
+
* Re-review the incorporated document (one more reviewer pass). On convergence
|
|
607
|
+
* (`incorporated`) the parked run advances; otherwise the window shows the next cycle
|
|
608
|
+
* (`ready`) or the iteration-cap choices (`exceeded`).
|
|
609
|
+
*/
|
|
610
|
+
reReviewRequirements(workspaceId: string, blockId: string): Promise<RequirementReview>;
|
|
611
|
+
/**
|
|
612
|
+
* Proceed: settle the requirements (the last incorporated doc, if any, becomes what
|
|
613
|
+
* downstream agents consume) and advance the parked run.
|
|
614
|
+
*/
|
|
615
|
+
proceedRequirements(workspaceId: string, blockId: string): Promise<RequirementReview>;
|
|
616
|
+
/**
|
|
617
|
+
* Route an iteration-cap resolution to its gate-specific handlers. `stop-reset` is
|
|
618
|
+
* uniform across gates: cancel the run and return the block to phase zero (editable),
|
|
619
|
+
* keeping whatever reference artifact each gate persists (the requirements doc on its
|
|
620
|
+
* own table; a companion's producer output on its branch). Shared by the requirements
|
|
621
|
+
* gate ({@link resolveRequirementsExceeded}) and the companion gate
|
|
622
|
+
* ({@link resolveCompanionExceeded}) so the three-way choice lives in one place.
|
|
623
|
+
*/
|
|
624
|
+
private dispatchIterationCap;
|
|
625
|
+
/**
|
|
626
|
+
* Resolve a requirements review that hit its iteration cap: grant one more round,
|
|
627
|
+
* proceed with the last incorporated doc, or stop the task and reset it to phase zero.
|
|
628
|
+
*/
|
|
629
|
+
resolveRequirementsExceeded(workspaceId: string, blockId: string, choice: ResolveRequirementsExceededChoice): Promise<RequirementReview>;
|
|
630
|
+
/**
|
|
631
|
+
* Resolve a companion step parked at its automatic-rework cap (`companion.exceeded`):
|
|
632
|
+
* grant one more round, proceed accepting the producer's current output, or stop the
|
|
633
|
+
* task and reset it to phase zero. The companion mirror of
|
|
634
|
+
* {@link resolveRequirementsExceeded}, sharing the iteration-cap dispatch + the
|
|
635
|
+
* gate-resume plumbing. Idempotent — an already-resolved gate returns the instance
|
|
636
|
+
* unchanged. Scoped by execution + approval id (the execution controller surface),
|
|
637
|
+
* since a companion gate is not block-addressed like the requirements window.
|
|
638
|
+
*/
|
|
639
|
+
resolveCompanionExceeded(workspaceId: string, executionId: string, approvalId: string, choice: IterationCapChoice): Promise<ExecutionInstance>;
|
|
640
|
+
/**
|
|
641
|
+
* Finish a gate step the human just resolved (its `approval` already marked `approved`),
|
|
642
|
+
* then either finish the run (final step) or advance to the next step, persist, and wake
|
|
643
|
+
* the parked durable driver. The single advance/finalize/signal path shared by every
|
|
644
|
+
* gate-resume site — the generic approval ({@link approveStep}), the review gates (via
|
|
645
|
+
* {@link ReviewGateController}) and the companion iteration-cap proceed
|
|
646
|
+
* ({@link resolveCompanionExceeded}) — so the logic lives in exactly one place.
|
|
647
|
+
*/
|
|
648
|
+
private advancePastResolvedGate;
|
|
649
|
+
/** The latest `bug-investigator` step output on a run (the triage subject), or undefined. */
|
|
650
|
+
private investigationFor;
|
|
651
|
+
/** Resolve a block's investigator output via its current execution (off the gate path). */
|
|
652
|
+
private investigationForBlock;
|
|
653
|
+
/**
|
|
654
|
+
* Run a fresh clarity reviewer pass over a block's bug report, snapshotting the task's
|
|
655
|
+
* merge-preset knobs (iteration budget + tolerated severity) and threading in any
|
|
656
|
+
* `bug-investigator` output as the triage subject. Shared by the gate + the off-path
|
|
657
|
+
* inspector "Run review" surface.
|
|
658
|
+
*/
|
|
659
|
+
reviewClarity(workspaceId: string, blockId: string): Promise<ClarityReview>;
|
|
660
|
+
/** Incorporate the human's settled answers ASYNCHRONOUSLY (the clarity mirror of {@link incorporateRequirements}). */
|
|
661
|
+
incorporateClarity(workspaceId: string, blockId: string, feedback?: string): Promise<ClarityReview>;
|
|
662
|
+
/** Re-review the clarified report (one more pass). On convergence the parked run advances. */
|
|
663
|
+
reReviewClarity(workspaceId: string, blockId: string): Promise<ClarityReview>;
|
|
664
|
+
/** Proceed: settle the clarity review and advance the parked run. */
|
|
665
|
+
proceedClarity(workspaceId: string, blockId: string): Promise<ClarityReview>;
|
|
666
|
+
/** Resolve a clarity review that hit its iteration cap (extra-round / proceed / stop-reset). */
|
|
667
|
+
resolveClarityExceeded(workspaceId: string, blockId: string, choice: ResolveRequirementsExceededChoice): Promise<ClarityReview>;
|
|
668
|
+
/**
|
|
669
|
+
* Push the run's latest state to subscribed clients, alongside its rolled-up
|
|
670
|
+
* block so the board updates without a refetch. Best-effort: the publisher
|
|
671
|
+
* swallows its own errors, and the persisted run remains the source of truth.
|
|
672
|
+
*/
|
|
673
|
+
private emitInstance;
|
|
674
|
+
/**
|
|
675
|
+
* Roll the run's recorded LLM calls into per-step `metrics` for the board, in
|
|
676
|
+
* place on the emitted instance. The proxy keys calls by execution + agentKind
|
|
677
|
+
* (not step index), so the aggregate is per-agent-kind within the run; steps
|
|
678
|
+
* sharing a kind get the same rollup. Best-effort and a no-op when the sink is
|
|
679
|
+
* not wired, so it never blocks an emit.
|
|
680
|
+
*/
|
|
681
|
+
private attachStepMetrics;
|
|
682
|
+
/** Set the block's in-progress/blocked status and step-completion progress. */
|
|
683
|
+
private updateBlockProgress;
|
|
684
|
+
/**
|
|
685
|
+
* Advance the block's step PROGRESS without touching its status — used when a step
|
|
686
|
+
* resolver already owns the block's terminal status (the merger set `done`/`pr_ready`)
|
|
687
|
+
* and a trailing step still follows, so the bar moves on without downgrading that status.
|
|
688
|
+
*/
|
|
689
|
+
private refreshBlockProgress;
|
|
690
|
+
/**
|
|
691
|
+
* A pipeline finished. A frame becomes `done` (a mapping-only run leaves it
|
|
692
|
+
* `ready`). A *task* never auto-`done`s from a confidence score any more — that
|
|
693
|
+
* looked merged when the PR was still open with red CI. Instead:
|
|
694
|
+
* - if the pipeline has a `merger` step, it already owned the merge/notify
|
|
695
|
+
* decision (see {@link resolveMergerStep}); we only backstop a missing one;
|
|
696
|
+
* - otherwise the work is complete but unmerged: leave the PR open (`pr_ready`)
|
|
697
|
+
* and raise a `pipeline_complete` notification for a human to confirm + merge.
|
|
698
|
+
* `done` now strictly means the PR was merged (see {@link finalizeMerge}).
|
|
699
|
+
*/
|
|
700
|
+
private finalizeBlock;
|
|
701
|
+
/**
|
|
702
|
+
* Merge a block's PR for real, then mark it `done`. The remote merge happens
|
|
703
|
+
* FIRST (via the {@link PullRequestMerger} port) and only on its success does the
|
|
704
|
+
* block flip to `done` — so `done` provably means "merged", not a board-only
|
|
705
|
+
* status. When no merger is wired (tests) this degrades to the old board-only
|
|
706
|
+
* flip. Throws if the remote merge fails so callers can fall back to a manual
|
|
707
|
+
* merge / review notification.
|
|
708
|
+
*/
|
|
709
|
+
private finalizeMerge;
|
|
710
|
+
/**
|
|
711
|
+
* Resolve the merge threshold preset that governs a task: its explicitly-picked
|
|
712
|
+
* preset, else the workspace default, else the built-in {@link DEFAULT_MERGE_PRESET}.
|
|
713
|
+
* Returns just the thresholds the engine compares against (+ the CI attempt budget).
|
|
714
|
+
*/
|
|
715
|
+
private resolveMergePreset;
|
|
716
|
+
/**
|
|
717
|
+
* Resolve a finished `on-call` investigation (the post-release-health gate's helper):
|
|
718
|
+
* parse its assessment, raise a `release_regression` notification for a human, enrich
|
|
719
|
+
* any incident PagerDuty/incident.io already opened, then finish the gate step so the
|
|
720
|
+
* run completes (the human acts on the notification out-of-band — the engine never
|
|
721
|
+
* auto-reverts). Best-effort on the side-effects; the step always finishes.
|
|
722
|
+
*/
|
|
723
|
+
private resolveOnCallStep;
|
|
724
|
+
/** Raise a `release_regression` notification carrying the on-call assessment + signals. */
|
|
725
|
+
private raiseReleaseRegression;
|
|
726
|
+
/**
|
|
727
|
+
* Best-effort: annotate an incident PagerDuty / incident.io already opened (from the
|
|
728
|
+
* same monitors/SLOs) with the on-call investigation. NOT alerting — those systems
|
|
729
|
+
* already paged. A no-op when no provider is wired or no matching incident exists.
|
|
730
|
+
*/
|
|
731
|
+
private enrichIncident;
|
|
732
|
+
/** Raise a `pipeline_complete` notification for a no-merger run awaiting confirmation. */
|
|
733
|
+
private raisePipelineComplete;
|
|
734
|
+
/**
|
|
735
|
+
* Implementing a task assigned to a module materialises that module: create it
|
|
736
|
+
* in the service if missing, then move the task inside it.
|
|
737
|
+
*/
|
|
738
|
+
private applyModuleAssignment;
|
|
739
|
+
/** Resolve a pending decision; the run's next step lets the agent finish it. */
|
|
740
|
+
resolveDecision(workspaceId: string, executionId: string, decisionId: string, choice: string): Promise<ExecutionInstance>;
|
|
741
|
+
/**
|
|
742
|
+
* Approve a step's gated proposal: the run advances to the next step, carrying
|
|
743
|
+
* the (optionally human-edited) proposal forward as context. Mirrors
|
|
744
|
+
* {@link resolveDecision}'s durable-wake but *advances* the pipeline instead of
|
|
745
|
+
* re-running the step (the step is already done). Idempotent — re-approving an
|
|
746
|
+
* already-approved gate is a no-op.
|
|
747
|
+
*/
|
|
748
|
+
approveStep(workspaceId: string, executionId: string, approvalId: string, opts?: {
|
|
749
|
+
proposal?: string;
|
|
750
|
+
}): Promise<ExecutionInstance>;
|
|
751
|
+
/**
|
|
752
|
+
* Request changes on a step's gated proposal: the same step re-runs with the
|
|
753
|
+
* human's freeform feedback and/or per-block comments (and its prior proposal)
|
|
754
|
+
* folded into the agent's context (see {@link AgentContextBuilder}). The run is left
|
|
755
|
+
* `running` on the same step; on the re-run's completion the gate is raised
|
|
756
|
+
* afresh. At least one of `feedback`/`comments` is expected (the controller
|
|
757
|
+
* validates this), but an empty review is harmless — the agent simply re-runs.
|
|
758
|
+
*/
|
|
759
|
+
requestStepChanges(workspaceId: string, executionId: string, approvalId: string, review: {
|
|
760
|
+
feedback?: string;
|
|
761
|
+
comments?: StepReviewComment[];
|
|
762
|
+
}): Promise<ExecutionInstance>;
|
|
763
|
+
/**
|
|
764
|
+
* Reject a step's gated proposal: the run stops entirely. The gate is marked
|
|
765
|
+
* `rejected` and the run is failed with a dedicated `rejected` failure kind, so
|
|
766
|
+
* the board surfaces it via the shared failure banner (block → `blocked`) with a
|
|
767
|
+
* Retry affordance. The parked durable run is woken so it observes the now-terminal
|
|
768
|
+
* status and stops (the workflow's advance loop no-ops on a non-running run).
|
|
769
|
+
* Idempotent — rejecting an already-terminal gate is a no-op.
|
|
770
|
+
*/
|
|
771
|
+
rejectStep(workspaceId: string, executionId: string, approvalId: string, reason?: string): Promise<ExecutionInstance>;
|
|
772
|
+
/** Merge an open PR: a block moves from `pr_ready` to `done`. */
|
|
773
|
+
mergePr(workspaceId: string, blockId: string): Promise<Block>;
|
|
774
|
+
/**
|
|
775
|
+
* Record a terminal agent failure: persist a structured {@link AgentFailure},
|
|
776
|
+
* flip the run to `failed`, and mark the block `blocked` (needs attention) — NOT
|
|
777
|
+
* `pr_ready`, which looked like success and hid the failure. The board then
|
|
778
|
+
* renders the same failure banner + retry as a failed bootstrap. Called by the
|
|
779
|
+
* durable driver once a step has exhausted its retries (or a job/decision
|
|
780
|
+
* faulted); `kind` classifies the cause so the right hint is shown.
|
|
781
|
+
*/
|
|
782
|
+
failRun(workspaceId: string, executionId: string, message: string, kind?: AgentFailureKind, detail?: string | null): Promise<void>;
|
|
783
|
+
/**
|
|
784
|
+
* Retry a failed run: re-drive the same pipeline on the same block, **resuming
|
|
785
|
+
* from the step that actually failed** rather than restarting from step 0. The
|
|
786
|
+
* steps that already completed are preserved (so a `coder` failure in `pl_full`
|
|
787
|
+
* doesn't re-run the human-gated `requirements`/`architect` steps before it);
|
|
788
|
+
* the failed step and everything after it are reset to a clean, re-runnable
|
|
789
|
+
* state. Only a `failed` run can be retried.
|
|
790
|
+
*
|
|
791
|
+
* A fresh instance id is minted because the durable runner addresses one
|
|
792
|
+
* Workflows instance per execution id and the failed one is terminal — the new
|
|
793
|
+
* instance simply starts with `currentStep` pointed at the failed step, so the
|
|
794
|
+
* driver advances forward from there and never re-issues the completed steps'
|
|
795
|
+
* work. Mirrors {@link BootstrapService.retry}; both are reached via the unified
|
|
796
|
+
* `POST /agent-runs/:id/retry` endpoint.
|
|
797
|
+
*/
|
|
798
|
+
retry(workspaceId: string, executionId: string,
|
|
799
|
+
/** The retrying user (their personal subscription is used for individual-usage
|
|
800
|
+
* models). Falls back to the original initiator when omitted. */
|
|
801
|
+
initiatedBy?: string | null,
|
|
802
|
+
/** Mint the per-run personal-credential activation (see {@link start}). */
|
|
803
|
+
activate?: (executionId: string) => Promise<void>): Promise<ExecutionInstance>;
|
|
804
|
+
/**
|
|
805
|
+
* Restart a run from a human-chosen step: re-run from `fromStepIndex` onward,
|
|
806
|
+
* regardless of how far the run had progressed (a `done`, `failed`, `blocked`,
|
|
807
|
+
* `paused` or still-`running` run are all valid sources). Unlike {@link retry}
|
|
808
|
+
* (which resumes at the first FAILURE) this rewinds to an arbitrary step the user
|
|
809
|
+
* picked — so it can re-run steps that already completed.
|
|
810
|
+
*
|
|
811
|
+
* What is preserved vs reset:
|
|
812
|
+
* - Steps BEFORE `fromStepIndex` keep their `output`/approval/timing untouched, so
|
|
813
|
+
* the engine still hands the restarted step its predecessors' work as
|
|
814
|
+
* `priorOutputs` (and their resolved `decisions`) — a useful handoff.
|
|
815
|
+
* - The chosen step and every later one are reset to a clean, re-runnable state,
|
|
816
|
+
* dropping each step's iteration counters (companion attempts, gate/test attempts,
|
|
817
|
+
* eviction recoveries) so the restart starts those loops from zero.
|
|
818
|
+
* - A block's incorporated requirements are NOT touched: they live on the
|
|
819
|
+
* requirement-review record, so a restarted spec-writer/coder still receives the
|
|
820
|
+
* incorporated document (or the base description when none was generated). When the
|
|
821
|
+
* chosen step is the `requirements-review` gate ITSELF, re-running it mints a fresh
|
|
822
|
+
* iteration-1 review (the reviewer's `review()` replaces the prior one), which is
|
|
823
|
+
* exactly the "reset the iterations counter from this step" semantics.
|
|
824
|
+
*
|
|
825
|
+
* Like {@link retry} a fresh instance id is minted (the durable runner addresses one
|
|
826
|
+
* driver per execution id). Any still-live driver/container for the run being
|
|
827
|
+
* replaced is torn down first, so restarting a RUNNING run never orphans a container
|
|
828
|
+
* or a parked Workflows instance.
|
|
829
|
+
*/
|
|
830
|
+
restartFromStep(workspaceId: string, executionId: string, fromStepIndex: number,
|
|
831
|
+
/** The restarting user (their personal subscription is used for individual-usage
|
|
832
|
+
* models). Falls back to the original initiator when omitted. */
|
|
833
|
+
initiatedBy?: string | null,
|
|
834
|
+
/** Mint the per-run personal-credential activation (see {@link start}). */
|
|
835
|
+
activate?: (executionId: string) => Promise<void>): Promise<ExecutionInstance>;
|
|
836
|
+
/**
|
|
837
|
+
* Resume every run paused by the spend safeguard in this workspace. Flips them
|
|
838
|
+
* back to `running` and re-drives the durable runner. If the budget is still
|
|
839
|
+
* exhausted the spend gate will simply pause them again on their next step.
|
|
840
|
+
*/
|
|
841
|
+
resumePaused(workspaceId: string): Promise<ExecutionInstance[]>;
|
|
842
|
+
/** Cancel the run on a block, returning it to `planned`. */
|
|
843
|
+
cancel(workspaceId: string, blockId: string): Promise<Block>;
|
|
844
|
+
/**
|
|
845
|
+
* Explicitly stop a *running* run by id (the unified `POST /agent-runs/:id/stop`
|
|
846
|
+
* surface): kill its per-run container, tear down the durable driver, then record
|
|
847
|
+
* a terminal `cancelled` failure so the board shows the run stopped (with retry)
|
|
848
|
+
* rather than spinning forever. Idempotent — a run already terminal is returned
|
|
849
|
+
* as-is. `opts.reason`/`opts.kind` let the orphan sweep reuse this with its own
|
|
850
|
+
* wording instead of the user-facing default.
|
|
851
|
+
*/
|
|
852
|
+
stopRun(workspaceId: string, executionId: string, opts?: {
|
|
853
|
+
reason?: string;
|
|
854
|
+
kind?: AgentFailureKind;
|
|
855
|
+
}): Promise<ExecutionInstance>;
|
|
856
|
+
/**
|
|
857
|
+
* Tear down every run under a block subtree — kill each container, terminate each
|
|
858
|
+
* durable driver, and delete the run record — so deleting a service/module never
|
|
859
|
+
* orphans a container or a Workflows instance. Best-effort and silent: the board
|
|
860
|
+
* delete that follows emits the coarse refresh, so no per-run event is needed.
|
|
861
|
+
*/
|
|
862
|
+
teardownForBlockTree(workspaceId: string, rootId: string): Promise<void>;
|
|
863
|
+
/**
|
|
864
|
+
* Best-effort: reclaim the per-run container backing an execution. The container is
|
|
865
|
+
* addressed by the run (execution) id, so a backend that shares one across the run
|
|
866
|
+
* (Cloudflare, local Docker) tears the whole thing down. A per-job backend (a
|
|
867
|
+
* self-hosted pool) has no run container, so it cancels the run's IN-FLIGHT step job
|
|
868
|
+
* instead — hence we pass the current step's job id alongside the run id. A no-op for
|
|
869
|
+
* inline executors (no `stopJob`) and for an already-gone container/job; never
|
|
870
|
+
* throws, so it can't derail the teardown that calls it.
|
|
871
|
+
*/
|
|
872
|
+
private stopRunContainer;
|
|
873
|
+
}
|
|
874
|
+
//# sourceMappingURL=ExecutionService.d.ts.map
|