@cat-factory/orchestration 0.123.4 → 0.123.6
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/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -1
- package/dist/modules/execution/AgentContextBuilder.js +14 -13
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -1
- package/dist/modules/execution/DeployerStepController.d.ts +185 -0
- package/dist/modules/execution/DeployerStepController.d.ts.map +1 -0
- package/dist/modules/execution/DeployerStepController.js +670 -0
- package/dist/modules/execution/DeployerStepController.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +8 -211
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +59 -805
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/FollowUpGateController.d.ts +104 -0
- package/dist/modules/execution/FollowUpGateController.d.ts.map +1 -0
- package/dist/modules/execution/FollowUpGateController.js +317 -0
- package/dist/modules/execution/FollowUpGateController.js.map +1 -0
- package/dist/modules/execution/RunAdmission.d.ts +204 -0
- package/dist/modules/execution/RunAdmission.d.ts.map +1 -0
- package/dist/modules/execution/RunAdmission.js +571 -0
- package/dist/modules/execution/RunAdmission.js.map +1 -0
- package/dist/modules/execution/RunDispatcher.d.ts +24 -196
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +70 -929
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/review-kinds.d.ts +41 -0
- package/dist/modules/execution/review-kinds.d.ts.map +1 -0
- package/dist/modules/execution/review-kinds.js +241 -0
- package/dist/modules/execution/review-kinds.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { ConflictError, NotFoundError } from '@cat-factory/kernel';
|
|
2
|
+
import { followUpsToSendBack, hasPendingFollowUps, renderFollowUpRework, shouldLoopCoder, } from './followUp.logic.js';
|
|
3
|
+
/**
|
|
4
|
+
* The Follow-up companion gate (the future-looking Coder), extracted out of
|
|
5
|
+
* {@link RunDispatcher}: the Coder streams forward-looking items (loose ends / side-tasks /
|
|
6
|
+
* questions) which accrue on its `step.followUps` live (see the dispatcher's poll fold). At
|
|
7
|
+
* the Coder's completion the run parks while any item is undecided, then loops the Coder for
|
|
8
|
+
* the items the human queued / answered (within the loop budget) before the following steps
|
|
9
|
+
* may start. Also owns the human-action API (file / queue / answer / dismiss) the execution
|
|
10
|
+
* controller reaches through the dispatcher's thin pass-throughs. Pure code movement from the
|
|
11
|
+
* dispatcher; no behaviour changes.
|
|
12
|
+
*/
|
|
13
|
+
export class FollowUpGateController {
|
|
14
|
+
executionRepository;
|
|
15
|
+
blockRepository;
|
|
16
|
+
contextBuilder;
|
|
17
|
+
stepGraph;
|
|
18
|
+
runStateMachine;
|
|
19
|
+
workRunner;
|
|
20
|
+
idGenerator;
|
|
21
|
+
clock;
|
|
22
|
+
notificationService;
|
|
23
|
+
ticketTrackerProvider;
|
|
24
|
+
constructor(deps) {
|
|
25
|
+
this.executionRepository = deps.executionRepository;
|
|
26
|
+
this.blockRepository = deps.blockRepository;
|
|
27
|
+
this.contextBuilder = deps.contextBuilder;
|
|
28
|
+
this.stepGraph = deps.stepGraph;
|
|
29
|
+
this.runStateMachine = deps.runStateMachine;
|
|
30
|
+
this.workRunner = deps.workRunner;
|
|
31
|
+
this.idGenerator = deps.idGenerator;
|
|
32
|
+
this.clock = deps.clock;
|
|
33
|
+
this.notificationService = deps.notificationService;
|
|
34
|
+
this.ticketTrackerProvider = deps.ticketTrackerProvider;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Append the items the harness streamed since the last poll onto the Coder step's
|
|
38
|
+
* follow-up state as fresh `pending` items. A no-op when the companion is off or nothing
|
|
39
|
+
* was streamed. Returns whether anything was added (so the poller persists + emits).
|
|
40
|
+
*/
|
|
41
|
+
appendStreamedFollowUps(step, streamed) {
|
|
42
|
+
if (!step.followUps?.enabled || !streamed || streamed.length === 0)
|
|
43
|
+
return false;
|
|
44
|
+
const now = this.clock.now();
|
|
45
|
+
for (const s of streamed) {
|
|
46
|
+
const title = (s.title ?? '').trim();
|
|
47
|
+
if (!title)
|
|
48
|
+
continue;
|
|
49
|
+
step.followUps.items.push({
|
|
50
|
+
id: this.idGenerator.next('fu'),
|
|
51
|
+
kind: s.kind === 'question' ? 'question' : 'follow_up',
|
|
52
|
+
title,
|
|
53
|
+
detail: s.detail ?? '',
|
|
54
|
+
...(s.suggestedAction ? { suggestedAction: s.suggestedAction } : {}),
|
|
55
|
+
status: 'pending',
|
|
56
|
+
createdAt: now,
|
|
57
|
+
updatedAt: now,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The Follow-up companion gate, evaluated when the Coder step completes: park the run on
|
|
64
|
+
* a durable decision while any item is undecided; else loop the Coder for the queued /
|
|
65
|
+
* answered items (within the budget); else fall through (return undefined) so the normal
|
|
66
|
+
* advance/finish logic runs. Returns an {@link AdvanceResult} only when it parks or loops.
|
|
67
|
+
*/
|
|
68
|
+
async evaluateFollowUpGate(workspaceId, instance, step) {
|
|
69
|
+
const state = step.followUps;
|
|
70
|
+
if (!state?.enabled)
|
|
71
|
+
return undefined;
|
|
72
|
+
if (hasPendingFollowUps(state)) {
|
|
73
|
+
await this.raiseFollowUpPending(workspaceId, instance, state);
|
|
74
|
+
return this.runStateMachine.parkStepOnDecision(workspaceId, instance, step);
|
|
75
|
+
}
|
|
76
|
+
if (shouldLoopCoder(state)) {
|
|
77
|
+
this.loopCoderForFollowUps(instance, step);
|
|
78
|
+
await this.runStateMachine.updateBlockProgress(workspaceId, instance, 'in_progress');
|
|
79
|
+
await this.runStateMachine.casPersist(workspaceId, instance);
|
|
80
|
+
await this.runStateMachine.emitInstance(workspaceId, instance);
|
|
81
|
+
return { kind: 'continue' };
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Reset the Coder step and fold the human's queued follow-ups / answered questions into
|
|
87
|
+
* its rework so the next pass extends the prior work. Marks those items `sentToCoder` so
|
|
88
|
+
* a later completion doesn't re-loop them, and counts the loop against the budget. Shared
|
|
89
|
+
* by the at-completion path ({@link evaluateFollowUpGate}) and the parked-resume path.
|
|
90
|
+
*/
|
|
91
|
+
loopCoderForFollowUps(instance, step) {
|
|
92
|
+
const state = step.followUps;
|
|
93
|
+
const sending = followUpsToSendBack(state);
|
|
94
|
+
const feedback = renderFollowUpRework(sending);
|
|
95
|
+
for (const item of sending) {
|
|
96
|
+
item.sentToCoder = true;
|
|
97
|
+
item.updatedAt = this.clock.now();
|
|
98
|
+
}
|
|
99
|
+
state.loops = (state.loops ?? 0) + 1;
|
|
100
|
+
// Reset the step for a fresh dispatch; `step.followUps` is intentionally preserved
|
|
101
|
+
// (resetStepForRerun doesn't touch it) so the surfaced items survive the loop.
|
|
102
|
+
this.stepGraph.resetStepForRerun(step);
|
|
103
|
+
step.rework = { previousProposal: '', feedback };
|
|
104
|
+
this.stepGraph.startStep(step);
|
|
105
|
+
if (instance.status === 'blocked')
|
|
106
|
+
instance.status = 'running';
|
|
107
|
+
}
|
|
108
|
+
/** Raise the "follow-ups need decisions" inbox card when the Coder parks on undecided items. */
|
|
109
|
+
async raiseFollowUpPending(workspaceId, instance, state) {
|
|
110
|
+
if (!this.notificationService)
|
|
111
|
+
return;
|
|
112
|
+
const block = await this.blockRepository.get(workspaceId, instance.blockId);
|
|
113
|
+
if (!block)
|
|
114
|
+
return;
|
|
115
|
+
const pending = state.items.filter((i) => i.status === 'pending').length;
|
|
116
|
+
await this.notificationService.raise(workspaceId, {
|
|
117
|
+
type: 'followup_pending',
|
|
118
|
+
blockId: block.id,
|
|
119
|
+
executionId: instance.id,
|
|
120
|
+
title: `"${block.title}" surfaced ${pending} follow-up${pending === 1 ? '' : 's'} to decide`,
|
|
121
|
+
body: 'The Coder flagged forward-looking follow-ups / questions. Open the task to file ' +
|
|
122
|
+
'each as an issue, send it back to the Coder, answer it, or dismiss it — the ' +
|
|
123
|
+
'pipeline continues once every item is decided.',
|
|
124
|
+
payload: { pipelineName: instance.pipelineName, findingCount: pending },
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The run's "active" follow-up companion step for a read with no item context (the GET /
|
|
129
|
+
* the inbox-card open). A pipeline may carry MORE THAN ONE follow-up-enabled Coder step,
|
|
130
|
+
* so this must not blindly pick the first: prefer the step the run is currently on (a Coder
|
|
131
|
+
* parked on its follow-up gate), else the latest enabled step that has surfaced items, else
|
|
132
|
+
* the first enabled one.
|
|
133
|
+
*/
|
|
134
|
+
activeFollowUpStep(instance) {
|
|
135
|
+
const current = instance.steps[instance.currentStep];
|
|
136
|
+
if (current?.followUps?.enabled)
|
|
137
|
+
return { step: current, index: instance.currentStep };
|
|
138
|
+
for (let i = instance.steps.length - 1; i >= 0; i--) {
|
|
139
|
+
const s = instance.steps[i];
|
|
140
|
+
if (s.followUps?.enabled && s.followUps.items.length > 0)
|
|
141
|
+
return { step: s, index: i };
|
|
142
|
+
}
|
|
143
|
+
const index = instance.steps.findIndex((s) => s.followUps?.enabled);
|
|
144
|
+
return index >= 0 ? { step: instance.steps[index], index } : undefined;
|
|
145
|
+
}
|
|
146
|
+
/** Read a run's live follow-up companion state (the active Coder step's items), or null. */
|
|
147
|
+
async getFollowUps(workspaceId, executionId) {
|
|
148
|
+
const instance = await this.executionRepository.get(workspaceId, executionId);
|
|
149
|
+
if (!instance)
|
|
150
|
+
throw new NotFoundError('Execution', executionId);
|
|
151
|
+
return this.activeFollowUpStep(instance)?.step.followUps ?? null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Locate the run + the Coder step that OWNS the addressed item + the item, throwing 404
|
|
155
|
+
* when absent. Routes by item id (not "the first enabled step") so a pipeline carrying more
|
|
156
|
+
* than one follow-up-enabled Coder step decides each item on the step that surfaced it —
|
|
157
|
+
* otherwise a later Coder's items 404 and its gate can never be cleared.
|
|
158
|
+
*/
|
|
159
|
+
async loadFollowUpItem(workspaceId, executionId, itemId) {
|
|
160
|
+
const instance = await this.executionRepository.get(workspaceId, executionId);
|
|
161
|
+
if (!instance)
|
|
162
|
+
throw new NotFoundError('Execution', executionId);
|
|
163
|
+
const index = instance.steps.findIndex((s) => s.followUps?.enabled && s.followUps.items.some((i) => i.id === itemId));
|
|
164
|
+
if (index < 0)
|
|
165
|
+
throw new NotFoundError('Follow-up item', itemId);
|
|
166
|
+
const step = instance.steps[index];
|
|
167
|
+
const item = step.followUps.items.find((i) => i.id === itemId);
|
|
168
|
+
return { instance, step, index, item };
|
|
169
|
+
}
|
|
170
|
+
/** File a `follow_up` item as a tracker issue (GitHub / Jira), recording the ticket ref. */
|
|
171
|
+
async fileFollowUp(workspaceId, executionId, itemId) {
|
|
172
|
+
// Snapshot read for validation + frame resolution before the non-idempotent ticket
|
|
173
|
+
// creation; the item's ticket refs are then recorded under CAS in applyFollowUpDecision.
|
|
174
|
+
const { instance, item } = await this.loadFollowUpItem(workspaceId, executionId, itemId);
|
|
175
|
+
if (item.kind !== 'follow_up') {
|
|
176
|
+
throw new ConflictError('Only follow-up items can be filed as issues');
|
|
177
|
+
}
|
|
178
|
+
if (!this.ticketTrackerProvider) {
|
|
179
|
+
throw new ConflictError('No issue tracker is configured for this workspace');
|
|
180
|
+
}
|
|
181
|
+
const frameId = (await this.contextBuilder.resolveServiceFrameId(workspaceId, instance.blockId)) ??
|
|
182
|
+
instance.blockId;
|
|
183
|
+
const body = [
|
|
184
|
+
item.detail,
|
|
185
|
+
item.suggestedAction ? `\n\nSuggested approach: ${item.suggestedAction}` : '',
|
|
186
|
+
]
|
|
187
|
+
.join('')
|
|
188
|
+
.trim();
|
|
189
|
+
const ticket = await this.ticketTrackerProvider.createTicket({
|
|
190
|
+
workspaceId,
|
|
191
|
+
frameId,
|
|
192
|
+
title: item.title,
|
|
193
|
+
body: body || item.title,
|
|
194
|
+
});
|
|
195
|
+
if (!ticket) {
|
|
196
|
+
throw new ConflictError('No issue tracker is configured for this workspace');
|
|
197
|
+
}
|
|
198
|
+
return this.applyFollowUpDecision(workspaceId, executionId, itemId, (target) => {
|
|
199
|
+
// Re-validated on the fresh snapshot inside the CAS (the ticket was already created above).
|
|
200
|
+
if (target.kind !== 'follow_up') {
|
|
201
|
+
throw new ConflictError('Only follow-up items can be filed as issues');
|
|
202
|
+
}
|
|
203
|
+
target.status = 'filed';
|
|
204
|
+
target.ticketExternalId = ticket.externalId;
|
|
205
|
+
target.ticketUrl = ticket.url;
|
|
206
|
+
target.updatedAt = this.clock.now();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/** Queue a `follow_up` item to send back to the Coder on its next pass. */
|
|
210
|
+
async queueFollowUp(workspaceId, executionId, itemId) {
|
|
211
|
+
return this.applyFollowUpDecision(workspaceId, executionId, itemId, (item) => {
|
|
212
|
+
if (item.kind !== 'follow_up') {
|
|
213
|
+
throw new ConflictError('Only follow-up items can be sent back to the Coder');
|
|
214
|
+
}
|
|
215
|
+
item.status = 'queued';
|
|
216
|
+
item.sentToCoder = false;
|
|
217
|
+
item.updatedAt = this.clock.now();
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/** Answer a `question` item; the answer is folded into the Coder's next pass. */
|
|
221
|
+
async answerFollowUp(workspaceId, executionId, itemId, answer) {
|
|
222
|
+
return this.applyFollowUpDecision(workspaceId, executionId, itemId, (item) => {
|
|
223
|
+
if (item.kind !== 'question') {
|
|
224
|
+
throw new ConflictError('Only question items can be answered');
|
|
225
|
+
}
|
|
226
|
+
item.status = 'answered';
|
|
227
|
+
item.answer = answer;
|
|
228
|
+
item.sentToCoder = false;
|
|
229
|
+
item.updatedAt = this.clock.now();
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/** Dismiss a follow-up / question item without acting on it. */
|
|
233
|
+
async dismissFollowUp(workspaceId, executionId, itemId) {
|
|
234
|
+
return this.applyFollowUpDecision(workspaceId, executionId, itemId, (item) => {
|
|
235
|
+
item.status = 'dismissed';
|
|
236
|
+
item.updatedAt = this.clock.now();
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Apply a human follow-up item decision and, when the run is PARKED on this step's follow-up
|
|
241
|
+
* gate with every item now decided, drive it forward — loop the Coder for the queued/answered
|
|
242
|
+
* items, hand off to a co-located approval gate, or advance past the gate — all under
|
|
243
|
+
* OPTIMISTIC CONCURRENCY. A follow-up decision can race the driver's running-poll fold (which
|
|
244
|
+
* appends newly-streamed items) or another decision on a sibling item, so it RE-READS +
|
|
245
|
+
* RE-APPLIES on a lost CAS race instead of clobbering — the human-action dual of the driver's
|
|
246
|
+
* abort-and-redrive (race-audit 2.2). The item mutation + the in-memory gate transition run
|
|
247
|
+
* INSIDE the CAS callback (idempotent, re-runnable on reload); the non-idempotent side effects
|
|
248
|
+
* (notifications, `signalDecision`, emit) run once AFTER, on the winning snapshot. `decide`
|
|
249
|
+
* validates + mutates the item, throwing a `ConflictError`/`NotFoundError` that propagates
|
|
250
|
+
* immediately (a domain error is not retried).
|
|
251
|
+
*/
|
|
252
|
+
async applyFollowUpDecision(workspaceId, executionId, itemId, decide) {
|
|
253
|
+
// Captured inside the (re-runnable) callback for the last winning attempt; the
|
|
254
|
+
// non-idempotent side effects below act on them.
|
|
255
|
+
let outcome = 'record';
|
|
256
|
+
let index = -1;
|
|
257
|
+
let loopDecisionId;
|
|
258
|
+
const persisted = await this.runStateMachine.mutateInstance(workspaceId, executionId, (fresh) => {
|
|
259
|
+
outcome = 'record';
|
|
260
|
+
loopDecisionId = undefined;
|
|
261
|
+
index = fresh.steps.findIndex((s) => s.followUps?.enabled && s.followUps.items.some((i) => i.id === itemId));
|
|
262
|
+
if (index < 0)
|
|
263
|
+
throw new NotFoundError('Follow-up item', itemId);
|
|
264
|
+
const step = fresh.steps[index];
|
|
265
|
+
decide(step.followUps.items.find((i) => i.id === itemId));
|
|
266
|
+
const parkedHere = fresh.status === 'blocked' &&
|
|
267
|
+
step.approval?.status === 'pending' &&
|
|
268
|
+
fresh.currentStep === index;
|
|
269
|
+
// Still collecting decisions (or the run isn't parked on this gate): only record it.
|
|
270
|
+
if (!parkedHere || hasPendingFollowUps(step.followUps))
|
|
271
|
+
return;
|
|
272
|
+
// Every item decided and the run is parked here: loop the Coder for the send-back items,
|
|
273
|
+
// hand off to a co-located approval gate, or advance past the gate.
|
|
274
|
+
if (shouldLoopCoder(step.followUps)) {
|
|
275
|
+
loopDecisionId = step.approval.id;
|
|
276
|
+
this.loopCoderForFollowUps(fresh, step);
|
|
277
|
+
outcome = 'loop';
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const isFinalStep = index === fresh.steps.length - 1;
|
|
281
|
+
if (step.requiresApproval && !isFinalStep && step.approval?.status === 'pending') {
|
|
282
|
+
// The follow-up park reused `step.approval`; advancing here would silently SKIP the
|
|
283
|
+
// approval. Refresh the proposal and hand off to the standard approval gate (the
|
|
284
|
+
// follow-up card is cleared + the "waiting for input" card re-raised below), preserving
|
|
285
|
+
// the follow-up-before-approval ordering recordStepResult established across the park.
|
|
286
|
+
step.approval = { ...step.approval, proposal: step.output ?? '' };
|
|
287
|
+
outcome = 'handoff';
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
this.runStateMachine.advanceRunPastGate(fresh, index);
|
|
291
|
+
outcome = 'advance';
|
|
292
|
+
});
|
|
293
|
+
// Non-idempotent side effects on the winning snapshot (the CAS write is the source of truth,
|
|
294
|
+
// so nothing re-persists here). The settled paths first clear the follow-up waiting card.
|
|
295
|
+
if (outcome === 'record') {
|
|
296
|
+
await this.runStateMachine.emitInstance(workspaceId, persisted);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
await this.runStateMachine.clearWaitingNotification(workspaceId, persisted);
|
|
300
|
+
if (outcome === 'loop') {
|
|
301
|
+
await this.runStateMachine.updateBlockProgress(workspaceId, persisted, 'in_progress');
|
|
302
|
+
await this.workRunner.signalDecision(workspaceId, persisted.id, loopDecisionId, 'approved');
|
|
303
|
+
await this.runStateMachine.emitInstance(workspaceId, persisted);
|
|
304
|
+
}
|
|
305
|
+
else if (outcome === 'handoff') {
|
|
306
|
+
await this.runStateMachine.ensureWaitingNotification(workspaceId, persisted);
|
|
307
|
+
await this.runStateMachine.emitInstance(workspaceId, persisted);
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// advance: block writes + `signalDecision('approved')` + emit — the approveStep template.
|
|
311
|
+
await this.runStateMachine.settleAdvancedGate(workspaceId, persisted, index);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return persisted.steps[index].followUps;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=FollowUpGateController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FollowUpGateController.js","sourceRoot":"","sources":["../../../src/modules/execution/FollowUpGateController.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { Block, BlockRepository, ExecutionRepository, ModelRef, PipelineStep, ProviderCapabilities, ResolveBinaryArtifactStore, WorkspaceRepository } from '@cat-factory/kernel';
|
|
2
|
+
import type { AgentKindRegistry } from '@cat-factory/agents';
|
|
3
|
+
import type { EnvironmentProvisioningService } from '@cat-factory/integrations';
|
|
4
|
+
import type { SpendService } from '@cat-factory/spend';
|
|
5
|
+
import { type PipelineShape } from '../pipelines/pipelineShape.js';
|
|
6
|
+
import type { AgentContextBuilder } from './AgentContextBuilder.js';
|
|
7
|
+
import type { WorkspaceSettingsService } from '../settings/WorkspaceSettingsService.js';
|
|
8
|
+
/** Collaborators + optional facade seams the admission preflights read. */
|
|
9
|
+
export interface RunAdmissionDeps {
|
|
10
|
+
workspaceRepository: WorkspaceRepository;
|
|
11
|
+
blockRepository: BlockRepository;
|
|
12
|
+
executionRepository: ExecutionRepository;
|
|
13
|
+
contextBuilder: AgentContextBuilder;
|
|
14
|
+
agentKindRegistry: AgentKindRegistry;
|
|
15
|
+
spend: SpendService;
|
|
16
|
+
/** Optional — see the matching {@link ExecutionServiceDependencies} docs; each guard is a
|
|
17
|
+
* pass-through when its seam is unwired (tests / unconfigured facades). */
|
|
18
|
+
environmentProvisioning?: EnvironmentProvisioningService;
|
|
19
|
+
workspaceSettingsService?: WorkspaceSettingsService;
|
|
20
|
+
resolveBinaryArtifactStore?: ResolveBinaryArtifactStore;
|
|
21
|
+
resolveProviderCapabilities?: (workspaceId: string, initiatedBy?: string | null) => Promise<ProviderCapabilities>;
|
|
22
|
+
inlineHarnessRef?: (ref: ModelRef) => boolean;
|
|
23
|
+
resolveWorkspaceModelDefault?: (workspaceId: string, agentKind: string, modelPresetId?: string) => Promise<string | undefined>;
|
|
24
|
+
assertAgentBackendConfigured?: (workspaceId: string) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The run ADMISSION preflights — every config/resource precondition a run must satisfy
|
|
28
|
+
* before it is allowed to START, RETRY or RESTART, extracted out of `ExecutionService`
|
|
29
|
+
* so the engine's public lifecycle methods stay readable while the guard family grows.
|
|
30
|
+
* All checks are read-only and run BEFORE any side effects, each throwing an actionable
|
|
31
|
+
* {@link ConflictError}. The shared entry point is {@link assertRunnable}; the start-only
|
|
32
|
+
* concurrency/dependency gates ({@link assertWithinTaskLimit}, {@link assertDependenciesMet})
|
|
33
|
+
* are separate because a retry/restart deliberately skips them.
|
|
34
|
+
*/
|
|
35
|
+
export declare class RunAdmission {
|
|
36
|
+
private readonly workspaceRepository;
|
|
37
|
+
private readonly blockRepository;
|
|
38
|
+
private readonly executionRepository;
|
|
39
|
+
private readonly contextBuilder;
|
|
40
|
+
private readonly agentKindRegistry;
|
|
41
|
+
private readonly spend;
|
|
42
|
+
private readonly environmentProvisioning?;
|
|
43
|
+
private readonly workspaceSettingsService?;
|
|
44
|
+
private readonly resolveBinaryArtifactStore?;
|
|
45
|
+
private readonly resolveProviderCapabilities?;
|
|
46
|
+
private readonly inlineHarnessRef?;
|
|
47
|
+
private readonly resolveWorkspaceModelDefault?;
|
|
48
|
+
private readonly assertAgentBackendConfigured?;
|
|
49
|
+
constructor(deps: RunAdmissionDeps);
|
|
50
|
+
/**
|
|
51
|
+
* The config/resource preconditions a run must satisfy to START, RETRY **or** RESTART:
|
|
52
|
+
* everything that depends on the workspace environment + the steps being run, and NOT on
|
|
53
|
+
* whether this is a fresh run or a replacement. All three entry points call this so they
|
|
54
|
+
* can't drift — a guard added to one but silently missing from the other is exactly how a
|
|
55
|
+
* subscription-only preset slipped past retry and failed mid-run against the routing default.
|
|
56
|
+
* All checks are read-only and run BEFORE any side effects, each throwing an actionable
|
|
57
|
+
* {@link ConflictError}.
|
|
58
|
+
*
|
|
59
|
+
* The `shape` is the effective chain that will run, NOT the current pipeline definition: a
|
|
60
|
+
* fresh start passes the pipeline, while a retry/restart passes the STORED steps (via
|
|
61
|
+
* {@link runnableShapeOf}) so the guard validates exactly what re-executes — a pipeline
|
|
62
|
+
* edited out of band since the run started can't falsely refuse (or silently skip a check
|
|
63
|
+
* for) a step that isn't actually being re-driven.
|
|
64
|
+
*
|
|
65
|
+
* The concurrency (task-limit) and dependency gates are deliberately NOT here — they are
|
|
66
|
+
* start-only (a retry replaces the failed run rather than adding a new concurrent one, and a
|
|
67
|
+
* re-drive of an already-started task isn't re-gated on its dependencies).
|
|
68
|
+
*/
|
|
69
|
+
assertRunnable(workspaceId: string, block: Block, shape: PipelineShape, initiatedBy: string | null | undefined): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* The {@link PipelineShape} a retry/restart re-drives: the stored run's steps ARE the enabled,
|
|
72
|
+
* ordered chain that will run again, so {@link assertRunnable} validates exactly what
|
|
73
|
+
* re-executes rather than the current pipeline definition (which may have been edited out of
|
|
74
|
+
* band since the run started). Disabled steps were already filtered out at start, so every
|
|
75
|
+
* stored step is enabled.
|
|
76
|
+
*/
|
|
77
|
+
runnableShapeOf(steps: readonly PipelineStep[]): PipelineShape;
|
|
78
|
+
/**
|
|
79
|
+
* Refuse a task start while any of its dependencies is unfinished. A task may only run
|
|
80
|
+
* once every block it `dependsOn` has reached `done` (its PR merged). No-ops for
|
|
81
|
+
* non-task blocks and for tasks with no dependencies. Throws a {@link ConflictError}
|
|
82
|
+
* (→ 409, shown as a toast) naming the unfinished blockers so the human knows why.
|
|
83
|
+
*/
|
|
84
|
+
assertDependenciesMet(workspaceId: string, block: Block): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Augment a workspace's block list (in place) with any dependency blocks referenced by
|
|
87
|
+
* `depIds` that aren't already present — a `dependsOn` edge can point at a task homed in a
|
|
88
|
+
* DIFFERENT workspace (a shared/mounted service). Resolved via the cross-workspace
|
|
89
|
+
* {@link BlockRepository.findByIds} (one batched query, not a point-read per id), so a
|
|
90
|
+
* shared-service blocker is evaluated by its real status instead of being silently treated
|
|
91
|
+
* as satisfied (missing ⇒ done). Returns the same (now-augmented) array for chaining.
|
|
92
|
+
*/
|
|
93
|
+
augmentWithCrossWorkspaceDeps(blocks: Block[], depIds: string[]): Promise<Block[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Enforce the workspace's per-service running-task limit before a task run starts.
|
|
96
|
+
* No-ops unless the settings module is wired, the block is a task, and a limit mode
|
|
97
|
+
* is active. Counts the tasks under the same service frame that already have a live
|
|
98
|
+
* run (running / blocked / paused) — bucketed by task type when the mode is
|
|
99
|
+
* `per_type`, else shared across all types — and throws a {@link ConflictError} (→ 409,
|
|
100
|
+
* shown as a toast) when the cap is reached. The starting block is excluded from the
|
|
101
|
+
* count (its prior run is about to be replaced).
|
|
102
|
+
*/
|
|
103
|
+
assertWithinTaskLimit(workspaceId: string, block: Block): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Whether a model id will incur metered monetary cost for THIS workspace. Non-metered:
|
|
106
|
+
* a subscription model whose vendor is connected ("subscriptions always win"), or a
|
|
107
|
+
* local-runner model (keyless, on the user's own endpoint). Everything else — including
|
|
108
|
+
* env-default routing (an absent id) and Cloudflare Workers AI — is treated as metered.
|
|
109
|
+
* Shared with {@link RunDispatcher.currentStepIsNonMetered} so the up-front budget gate
|
|
110
|
+
* and the mid-run spend gate can't classify a model differently.
|
|
111
|
+
*/
|
|
112
|
+
modelIdIsMetered(id: string | undefined, caps: ProviderCapabilities): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Guard a run start when the pipeline carries a VISUAL step (`tester-ui` /
|
|
115
|
+
* `visual-confirmation`): such a step exercises a rendered UI, so it only makes sense where
|
|
116
|
+
* there is a UI to drive — a `type: 'frontend'` frame (it owns the app under test) or a frame
|
|
117
|
+
* a `frontend` frame links to (the linked frontend is the UI a change to that service is
|
|
118
|
+
* validated through). On any other frame (a service with no linked frontend, a `library` /
|
|
119
|
+
* `document` repo) a `tester-ui` step would have nothing to drive, so refuse the start with an
|
|
120
|
+
* actionable {@link ConflictError} (`visual_pipeline_no_frontend`). The frontend surfaces the
|
|
121
|
+
* SAME rule (via the shared `frameAllowsVisualPipeline`) so it only offers these pipelines
|
|
122
|
+
* where they can run; this is the server-side guarantee. A non-visual pipeline passes through.
|
|
123
|
+
* The workspace block list is read ONCE (for the frontend→service links), never per-frame.
|
|
124
|
+
*/
|
|
125
|
+
private assertPipelineFrameTypeAllowed;
|
|
126
|
+
/**
|
|
127
|
+
* Guard a Tester pipeline's start on the service frame's declared provisioning being runnable.
|
|
128
|
+
* The Tester needs SOME way to stand its system up: `infraless` (or none declared) runs with no
|
|
129
|
+
* infra; `docker-compose`/`kubernetes`/`custom` are all provisioned by the single Deployer step
|
|
130
|
+
* through a workspace handler, so one must resolve for the service's type. A `frontend` frame is
|
|
131
|
+
* gated instead on having a live service under test. Throws an actionable {@link ConflictError}
|
|
132
|
+
* (`tester_infra_unsupported` for the frontend case, `provision_type_unhandled` for a missing
|
|
133
|
+
* handler); passes through when the provisioning seam is unwired (tests / no environment
|
|
134
|
+
* integration), like the other optional start guards. `initiatedBy` is threaded into
|
|
135
|
+
* `canProvision` so the run initiator's local per-user handler OVERRIDES resolve exactly as they
|
|
136
|
+
* do at provision time (and as the Deployer-config gate does) — else a valid override-only local
|
|
137
|
+
* setup would be falsely refused here while the deployer would actually provision it.
|
|
138
|
+
*/
|
|
139
|
+
private assertTesterInfraConfigured;
|
|
140
|
+
/**
|
|
141
|
+
* Fail fast when a `docker-compose`/`kubernetes`/`custom` service's chain would dead-end at an
|
|
142
|
+
* env-consumer (tester / human-test / playwright) because no enabled `deployer` provisions the
|
|
143
|
+
* environment before it — the exact silent dead-end this initiative fixes (the tester picks
|
|
144
|
+
* ephemeral mode from the provision type but finds no coordinates). The pure ordering check lives
|
|
145
|
+
* in {@link needsDeployerBeforeConsumer}; here we resolve the service's provision type (only when a
|
|
146
|
+
* consumer is present, so consumer-less chains skip the read) and translate a positive verdict
|
|
147
|
+
* into an actionable {@link ConflictError}. Pass-through for infraless/frontend services and for
|
|
148
|
+
* chains with a deployer before the first consumer.
|
|
149
|
+
*/
|
|
150
|
+
private assertDeployerBeforeConsumer;
|
|
151
|
+
/**
|
|
152
|
+
* Guard a pipeline that INCLUDES an enabled `deployer` step on its ephemeral-environment config
|
|
153
|
+
* being FULL + CORRECT on BOTH sides of the "what/where ÷ how" split, so a misconfigured
|
|
154
|
+
* environment fails LOUDLY at start with a fixable pointer instead of mid-run: a `kubernetes` /
|
|
155
|
+
* `custom` service silently failing its async provision, or a `docker-compose` one whose deployer
|
|
156
|
+
* NO-OPS because no handler resolves (the exact silent dead-ends this initiative closes). It
|
|
157
|
+
* checks, in order of the fix a human would make:
|
|
158
|
+
* 1. the SERVICE's provisioning config is complete for its declared type (manifest source /
|
|
159
|
+
* compose path / custom-manifest id) — else `deployer_service_provisioning_incomplete`;
|
|
160
|
+
* 2. a WORKSPACE handler resolves for the type — else `provision_type_unhandled` (the same
|
|
161
|
+
* reason the Tester gate raises; a MISSING/ambiguous handler, not a broken one);
|
|
162
|
+
* 3. (bonus, best-effort) the resolved deployment integration's live connection PROBES green —
|
|
163
|
+
* else `deployer_connection_test_failed`, carrying the provider's failure detail.
|
|
164
|
+
* Each `ConflictError` carries a machine-readable reason + details the SPA deep-links off to the
|
|
165
|
+
* exact fix surface. Pass-through for `infraless`/undeclared services (the deployer stands nothing
|
|
166
|
+
* up) and when the environment seam is unwired (tests / no-env deployments), like the other
|
|
167
|
+
* optional start guards.
|
|
168
|
+
*/
|
|
169
|
+
private assertDeployerConfigured;
|
|
170
|
+
/**
|
|
171
|
+
* Guard a pipeline's start when it carries an agent kind that RELIES on binary-artifact
|
|
172
|
+
* storage (the {@link BINARY_STORAGE_TRAIT}, e.g. the UI Tester, which uploads its
|
|
173
|
+
* screenshots there). Such a run would otherwise dispatch and then fail/degrade with no
|
|
174
|
+
* place to store its artifacts, so refuse it up-front with a clear, actionable
|
|
175
|
+
* `binary_storage_unconfigured` conflict the SPA turns into a "configure storage" prompt.
|
|
176
|
+
* The check is trait-driven so it stays universal: a future artifact-producing kind just
|
|
177
|
+
* carries the trait. Pass-through when no store resolver is wired (tests/conformance with
|
|
178
|
+
* no storage) — matching the other optional start guards.
|
|
179
|
+
*/
|
|
180
|
+
private assertBinaryStorageConfigured;
|
|
181
|
+
/**
|
|
182
|
+
* Guard a pipeline's start on having a usable provider for every step's canonical
|
|
183
|
+
* model. The model a step runs is resolved by the same precedence the dispatch path
|
|
184
|
+
* uses (block pin → workspace per-kind default); each canonical id must have a usable
|
|
185
|
+
* provider given what's configured — a direct API key for its provider, a connected
|
|
186
|
+
* subscription vendor, or the opt-in Cloudflare lib enabled. Env-routing defaults (the
|
|
187
|
+
* last fallback, with no catalog id) are operator-level and not gated, matching the
|
|
188
|
+
* personal-credential gate. A throw aborts the start cleanly before any side effects.
|
|
189
|
+
* Skipped when no capability resolver is wired (tests / unconfigured facades).
|
|
190
|
+
*/
|
|
191
|
+
private assertProvidersConfiguredForPipeline;
|
|
192
|
+
/**
|
|
193
|
+
* Refuse to START / RETRY a run when the workspace has reached its spend budget AND the
|
|
194
|
+
* pipeline has at least one budget-METERED step. A `0` (or exhausted) budget is a
|
|
195
|
+
* deliberate "no paid spend" setting, but it must surface as a clear, up-front error here
|
|
196
|
+
* rather than a silent mid-run pause. Steps that incur no metered cost — a connected
|
|
197
|
+
* subscription model, or a keyless local-runner model — are exempt, so a workspace that
|
|
198
|
+
* runs ONLY local/subscription models starts normally even at a `0` budget. Best-effort:
|
|
199
|
+
* with no capability resolver wired (tests/unconfigured) it is skipped and the mid-run
|
|
200
|
+
* gate still guards. Before any side effects, matching the other start guards.
|
|
201
|
+
*/
|
|
202
|
+
private assertBudgetAllowsPipeline;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=RunAdmission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunAdmission.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/RunAdmission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,eAAe,EACf,mBAAmB,EACnB,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACpB,MAAM,qBAAqB,CAAA;AAiB5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAA;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAgBzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAA;AAEvF,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,eAAe,EAAE,eAAe,CAAA;IAChC,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,cAAc,EAAE,mBAAmB,CAAA;IACnC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB;gFAC4E;IAC5E,uBAAuB,CAAC,EAAE,8BAA8B,CAAA;IACxD,wBAAwB,CAAC,EAAE,wBAAwB,CAAA;IACnD,0BAA0B,CAAC,EAAE,0BAA0B,CAAA;IACvD,2BAA2B,CAAC,EAAE,CAC5B,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,KACxB,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAClC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAA;IAC7C,4BAA4B,CAAC,EAAE,CAC7B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,KACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAChC,4BAA4B,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE;AAED;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAgC;IACzE,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAA0B;IACpE,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAA4B;IACxE,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAGX;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAA4B;IAC9D,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAId;IAChC,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAwC;IAEtF,YAAY,IAAI,EAAE,gBAAgB,EAcjC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACrC,OAAO,CAAC,IAAI,CAAC,CA4Df;IAED;;;;;;OAMG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,aAAa,CAW7D;IAED;;;;;OAKG;IACG,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E;IAED;;;;;;;OAOG;IACG,6BAA6B,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAQvF;IAED;;;;;;;;OAQG;IACG,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CA+D5E;IAED;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAO5E;IAED;;;;;;;;;;;OAWG;YACW,8BAA8B;IAqB5C;;;;;;;;;;;;OAYG;YACW,2BAA2B;IAmDzC;;;;;;;;;OASG;YACW,4BAA4B;IAyB1C;;;;;;;;;;;;;;;;;OAiBG;YACW,wBAAwB;IA8FtC;;;;;;;;;OASG;YACW,6BAA6B;IAgB3C;;;;;;;;;OASG;YACW,oCAAoC;IAqFlD;;;;;;;;;OASG;YACW,0BAA0B;CA+BzC"}
|