@cat-factory/orchestration 0.38.1 → 0.39.1

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.
@@ -0,0 +1,479 @@
1
+ import type { AgentExecutor, AgentRunContext, AgentRunResult, Block, BlockRepository, BrainstormSession, ClarityReview, Clock, ExecutionEventPublisher, ExecutionInstance, ExecutionRepository, FollowUpsStepState, GateDefinition, IdGenerator, IssueWritebackProvider, PipelineStep, ProviderCapabilities, ProvisionContext, RequirementConcernLevel, RequirementReview, ResolveRunRepoContext, RunInitiatorScope, TicketTrackerProvider, WorkRunner } from '@cat-factory/kernel';
2
+ import type { EnvironmentProvisioningService } from '@cat-factory/integrations';
3
+ import { AgentContextBuilder } from './AgentContextBuilder.js';
4
+ import { CompanionController } from './CompanionController.js';
5
+ import { HumanTestController } from './HumanTestController.js';
6
+ import { MergeResolver } from './MergeResolver.js';
7
+ import { ReviewGateController, type ReviewKind } from './ReviewGateController.js';
8
+ import { RunStateMachine } from './RunStateMachine.js';
9
+ import { StepGraph } from './StepGraph.js';
10
+ import { TesterController } from './TesterController.js';
11
+ import { VisualConfirmationController } from './VisualConfirmationController.js';
12
+ import { type StepHandlerContext } from './step-handler-registry.js';
13
+ import type { AdvanceOptions, AdvanceResult } from './advance.js';
14
+ import type { NotificationService } from '../notifications/NotificationService.js';
15
+ import type { SpendService } from '@cat-factory/spend';
16
+ import type { BlueprintReconciler } from './ExecutionService.js';
17
+ /**
18
+ * The task's fully-resolved merge-threshold preset (block pin → workspace default →
19
+ * built-in). The dispatcher only reads the gate-relevant fields; the full shape is kept so
20
+ * a gate's `attemptBudget(preset)` sees every knob. Mirrors {@link ExecutionService.resolveMergePreset}.
21
+ */
22
+ type ResolvedMergePreset = {
23
+ maxComplexity: number;
24
+ maxRisk: number;
25
+ maxImpact: number;
26
+ ciMaxAttempts: number;
27
+ maxRequirementIterations: number;
28
+ maxRequirementConcernAllowed: RequirementConcernLevel;
29
+ releaseWatchWindowMinutes: number;
30
+ releaseMaxAttempts: number;
31
+ humanReviewGraceMinutes: number;
32
+ };
33
+ /** Collaborators + leaf dependencies the {@link RunDispatcher} needs. */
34
+ export interface RunDispatcherDeps {
35
+ blockRepository: BlockRepository;
36
+ executionRepository: ExecutionRepository;
37
+ agentExecutor: AgentExecutor;
38
+ workRunner: WorkRunner;
39
+ events: ExecutionEventPublisher;
40
+ idGenerator: IdGenerator;
41
+ clock: Clock;
42
+ spend: SpendService;
43
+ stepGraph: StepGraph;
44
+ runStateMachine: RunStateMachine;
45
+ contextBuilder: AgentContextBuilder;
46
+ mergeResolver: MergeResolver;
47
+ companionController: CompanionController;
48
+ testerController: TesterController;
49
+ humanTestController: HumanTestController;
50
+ visualConfirmationController: VisualConfirmationController;
51
+ reviewGate: ReviewGateController;
52
+ requirementsKind: ReviewKind<RequirementReview>;
53
+ clarityKind: ReviewKind<ClarityReview>;
54
+ requirementsBrainstormKind: ReviewKind<BrainstormSession>;
55
+ architectureBrainstormKind: ReviewKind<BrainstormSession>;
56
+ runInitiatorScope: RunInitiatorScope;
57
+ environmentProvisioning?: EnvironmentProvisioningService;
58
+ ticketTrackerProvider?: TicketTrackerProvider;
59
+ issueWriteback?: IssueWritebackProvider;
60
+ notificationService?: NotificationService;
61
+ blueprintReconciler?: BlueprintReconciler;
62
+ resolveRunRepoContext?: ResolveRunRepoContext;
63
+ resolveProviderCapabilities?: (workspaceId: string, initiatedBy?: string | null) => Promise<ProviderCapabilities>;
64
+ /** Resolve a task's merge preset (stays on the engine, shared with the merge subgraph). */
65
+ resolveMergePreset: (workspaceId: string, block: Block) => Promise<ResolvedMergePreset>;
66
+ /** Whether a resolved model id incurs metered monetary cost (the start gate's predicate). */
67
+ modelIdIsMetered: (id: string | undefined, caps: ProviderCapabilities) => boolean;
68
+ }
69
+ /**
70
+ * The per-step dispatch + completion spine of the execution engine. It owns the four
71
+ * registries (step handlers, completion interceptors, post-completion / terminal resolvers,
72
+ * polling gates), the completion hub (`recordStepResult` / `handleAgentStep`), the gate
73
+ * machinery (`evaluateGate` / `dispatchGateHelper` / `pollGate` / `resolveGatePollExhaustion`),
74
+ * the deterministic `deployer` / `tracker` steps, the registered pre/post-op cluster, the
75
+ * structured-artifact ingest helpers, and the follow-up companion gate + its human-action API.
76
+ *
77
+ * Extracted out of `ExecutionService` so the handlers depend on a cohesive surface rather than
78
+ * a fat per-callback bag. It composes the existing collaborators ({@link RunStateMachine} /
79
+ * {@link StepGraph} / the five gate controllers / {@link MergeResolver}); the merge/auto-start
80
+ * subgraph deliberately STAYS on the engine, reached only through the injected
81
+ * `resolveMergePreset` callback + the {@link MergeResolver} (which itself closes over the
82
+ * engine's `finalizeMerge`). `ExecutionService.stepInstance` / `pollAgentJob` / `pollGate`
83
+ * delegate here; no behaviour changes in the move.
84
+ */
85
+ export declare class RunDispatcher {
86
+ private readonly blockRepository;
87
+ private readonly executionRepository;
88
+ private readonly agentExecutor;
89
+ private readonly workRunner;
90
+ private readonly events;
91
+ private readonly idGenerator;
92
+ private readonly clock;
93
+ private readonly spend;
94
+ private readonly stepGraph;
95
+ private readonly runStateMachine;
96
+ private readonly contextBuilder;
97
+ private readonly mergeResolver;
98
+ private readonly companionController;
99
+ private readonly testerController;
100
+ private readonly humanTestController;
101
+ private readonly visualConfirmationController;
102
+ private readonly reviewGate;
103
+ private readonly requirementsKind;
104
+ private readonly clarityKind;
105
+ private readonly requirementsBrainstormKind;
106
+ private readonly architectureBrainstormKind;
107
+ private readonly runInitiatorScope;
108
+ private readonly environmentProvisioning?;
109
+ private readonly ticketTrackerProvider?;
110
+ private readonly issueWriteback?;
111
+ private readonly notificationService?;
112
+ private readonly blueprintReconciler?;
113
+ private readonly resolveRunRepoContext?;
114
+ private readonly resolveProviderCapabilities?;
115
+ private readonly resolveMergePreset;
116
+ private readonly modelIdIsMetered;
117
+ /** Lazily-built polling-gate registry, keyed by `agentKind`. See {@link gateFor}. */
118
+ private gateRegistryCache?;
119
+ /** Lazily-built post-completion resolver registry, keyed by `agentKind`. */
120
+ private stepResolverCache?;
121
+ /** Lazily-built, order-sorted per-step-kind handler list. See {@link dispatchStepHandler}. */
122
+ private stepHandlerCache?;
123
+ /** Lazily-built, order-sorted completion-path interceptor list. */
124
+ private stepCompletionInterceptorCache?;
125
+ constructor(deps: RunDispatcherDeps);
126
+ /**
127
+ * The generic container/inline-agent step — the lowest-priority StepHandler, claiming
128
+ * every step no more-specific handler did (coder, architect, spec-writer, merger,
129
+ * task-estimator, the container-backed companions, …). Builds the agent context, runs the
130
+ * kind's pre-ops, then either dispatches an async container job and parks (the durable
131
+ * driver polls between sleeps) or runs the inline LLM call and records the result. This is
132
+ * what the dispatch chain falls through to; all the deterministic / gate / inline-review
133
+ * kinds are claimed earlier by their own handlers (see {@link buildStepHandlerRegistry}).
134
+ */
135
+ private handleAgentStep;
136
+ /**
137
+ * Preview the model a step will run (`provider:model`) ahead of the work, so the
138
+ * board can show it during the inline query / container cold-boot rather than only
139
+ * once the result or job handle lands. Best-effort: the executor may not implement
140
+ * a preview, and a resolution failure (e.g. an unwired container kind that fails at
141
+ * dispatch anyway) must never break the run — both yield undefined.
142
+ */
143
+ previewStepModel(context: AgentRunContext): Promise<string | undefined>;
144
+ /**
145
+ * Whether the current step incurs NO metered monetary LLM cost, so the spend gate can
146
+ * let it proceed even when the budget is exhausted. Two non-metered cases:
147
+ * - a flat-rate SUBSCRIPTION (quota) model — Claude Code / Codex on a pooled token;
148
+ * resolved through the executor (the authority on "subscriptions always win").
149
+ * - a LOCAL-runner model (Ollama / LM Studio / …) — keyless, runs on the user's own
150
+ * endpoint, so it costs the deployment nothing; detected off the resolved model id.
151
+ * This is what makes a `0` budget mean "no PAID spend" without bricking a workspace that
152
+ * deliberately runs only local models or subscriptions (see the spend-budget docs).
153
+ *
154
+ * Once the executor resolves the step's concrete model id, the metered/non-metered
155
+ * decision is delegated to the SAME {@link modelIdIsMetered} predicate the up-front
156
+ * {@link assertBudgetAllowsPipeline} gate uses, so the two gates can't classify a model
157
+ * differently (a divergence would let a run pass the start gate then immediately pause,
158
+ * or vice versa). The executor's `isQuotaBased` is still consulted first as the
159
+ * authoritative subscription-routing signal; the shared predicate covers local-runner +
160
+ * subscription-by-capability + Cloudflare classification identically to the start gate.
161
+ * Falls back to a bare local-id check when no capability resolver is wired.
162
+ *
163
+ * Best-effort and side-effect-free: an executor without the capability, a missing block,
164
+ * or any resolution error all report false (treated as budget-metered, the prior
165
+ * behaviour). Only consulted on the over-budget path, so it never touches the happy path.
166
+ */
167
+ currentStepIsNonMetered(workspaceId: string, instance: ExecutionInstance, step: ExecutionInstance['steps'][number]): Promise<boolean>;
168
+ /**
169
+ * Poll the asynchronous job a parked step dispatched. Returns `awaiting_job`
170
+ * while it runs (the driver keeps polling), records the result and advances on
171
+ * success, or reports `job_failed` so the driver can fail the run. Reading run
172
+ * state from storage on every call keeps it safe under Workflows replay/retry:
173
+ * once a job's result is recorded the step's `jobId` is cleared, so a re-poll
174
+ * simply lets the driver advance the now-current step.
175
+ */
176
+ pollAgentJob(workspaceId: string, executionId: string): Promise<AdvanceResult>;
177
+ /**
178
+ * Re-run a polling gate step's precheck from the durable driver's `awaiting_gate`
179
+ * loop: which gate (ci / conflicts) is resolved from the current step's `agentKind`,
180
+ * and it returns the same outcomes as the initial evaluation (precheck passes →
181
+ * advance, still computing → keep polling, fails → dispatch a helper or give up).
182
+ * Safe under replay: reads run state fresh each call. A no-op unless the current
183
+ * step is a gate actively in its `checking` phase.
184
+ */
185
+ pollGate(workspaceId: string, executionId: string): Promise<AdvanceResult>;
186
+ /**
187
+ * Decide what happens when the durable driver's GATE poll budget (ciMaxPolls ×
188
+ * ciPollInterval) is spent while a gate is still `pending` — called by both runtime
189
+ * drivers (Cloudflare ExecutionWorkflow / Node `driveExecution`) instead of failing
190
+ * the run directly, so the per-gate policy lives in one place. Most gates `fail`
191
+ * (CI never went green / the PR never became mergeable). A time-windowed watch gate
192
+ * (post-release-health, `pollExhaustion: 'pass'`) instead PASSES: the watch window
193
+ * simply outlasted the poll budget with no regression observed, which is healthy — not
194
+ * a timeout. Returns the result the driver should act on (it never re-fails for a fail
195
+ * gate; it returns a `job_failed` the driver funnels through its single `failRun`).
196
+ */
197
+ resolveGatePollExhaustion(workspaceId: string, executionId: string): Promise<AdvanceResult>;
198
+ /**
199
+ * Stamp `step.environment` from the block's live ephemeral environment so a run's
200
+ * details show its spinning-up / running / shut-down / errored state + the exact
201
+ * error. Best-effort: a no-op when the env integration isn't wired, and never
202
+ * throws (a projection failure must not break the run). Returns whether it changed,
203
+ * so the poll path can fold it into its single emit. The `human-test` gate keeps
204
+ * its own `humanTest.environment`, so this is for the other env-consuming steps
205
+ * (tester/coder/deployer).
206
+ */
207
+ private attachEnvironmentProjection;
208
+ /**
209
+ * Finish a gated step that was skipped (its estimate gate was not satisfied) and either
210
+ * complete the run or advance to the next step — the deterministic finish/advance tail
211
+ * of {@link recordStepResult}, minus all the agent-result handling (no LLM ran, so there
212
+ * is no usage / decision / PR / artifact / approval / resolver to process). The step is
213
+ * marked `skipped` with empty output so the UI renders "skipped (gated)".
214
+ */
215
+ skipGatedStep(workspaceId: string, instance: ExecutionInstance, step: PipelineStep, isFinalStep: boolean): Promise<AdvanceResult>;
216
+ /**
217
+ * Record a completed agent step's result and report what the driver should do
218
+ * next: meter token usage, park on a raised decision, or persist the output
219
+ * (and any opened PR) and either finish the run or advance to the next step.
220
+ * Shared by the inline path and the async-job poll path.
221
+ */
222
+ private recordStepResult;
223
+ /**
224
+ * Deterministically provision an ephemeral environment for a deployer step.
225
+ * Produces a human-readable summary as the step output and reports no token
226
+ * usage (it incurs no LLM cost). Errors are swallowed into the output unless
227
+ * the durable driver wants them surfaced for its per-step retry.
228
+ */
229
+ private runDeployer;
230
+ /**
231
+ * File a tracking issue/ticket for a `tracker` step from the preceding `analysis`
232
+ * output. Non-LLM and best-effort: when no provider is wired or none is configured
233
+ * for the workspace it simply notes the skip; a filing error is folded into the
234
+ * step output rather than failing the run (the implementation still proceeds).
235
+ */
236
+ private runTracker;
237
+ /**
238
+ * The polling-gate registry, keyed by `agentKind`. A gate runs a programmatic
239
+ * precheck against a provider and only escalates to a helper container agent on a
240
+ * negative verdict. Built lazily (the closures capture `this`, so the providers /
241
+ * merge preset / notification helpers resolve at call time) and cached per instance.
242
+ * The registry merges deployment-registered gates ({@link registeredGateFactories}),
243
+ * which are a STARTUP import side effect — a gate registered after this cache is first
244
+ * built is invisible to this instance, so register at startup, before serving. Returns
245
+ * undefined for a non-gate kind. See {@link GateDefinition} and {@link evaluateGate}.
246
+ */
247
+ gateFor(agentKind: string): GateDefinition | undefined;
248
+ /**
249
+ * Resolve the concrete branch a registered kind's pre/post-op reads or writes, from
250
+ * its declared clone target — mirroring the container executor's mapping so a backend
251
+ * op and the container agent operate on the SAME branch:
252
+ * - `base` → the repo default branch (the ONLY way a committing op targets `main`).
253
+ * - `pr` → the block's PR branch (the coder's branch); when no PR is open, the
254
+ * per-block work branch (created from base if missing) — NOT base, so a
255
+ * committing post-op can't silently land on the default branch.
256
+ * - `work` (default) → the per-block work branch, ENSURED to exist exactly as
257
+ * {@link ContainerAgentExecutor}'s `ensureWorkBranch` does. The old code
258
+ * returned base here whenever no PR was open yet, diverging from the
259
+ * container agent (which clones `cat-factory/<blockId>`) and letting a
260
+ * post-op commit onto the default branch.
261
+ * The work-branch name (`cat-factory/<blockId>`) is the same convention
262
+ * {@link ContainerAgentExecutor} uses.
263
+ */
264
+ private resolveRepoOpBranch;
265
+ /**
266
+ * Ensure the per-block work branch `cat-factory/<blockId>` exists — creating it from the
267
+ * repo default branch's head when absent — and return it. The checkout-free analogue of
268
+ * {@link ContainerAgentExecutor}'s `ensureWorkBranch`, so a backend pre/post-op writes
269
+ * the SAME branch the container agent does instead of the default branch. Falls back to
270
+ * the base branch only when the repo has no default-branch head to fork from (an empty
271
+ * repo), so the caller always gets a real branch.
272
+ */
273
+ private ensureWorkBranch;
274
+ /**
275
+ * Run a registered kind's PRE-op hooks before its agent step dispatches: deterministic
276
+ * backend work (read a baseline artifact into the prompt, etc.) over a checkout-free
277
+ * {@link RepoFiles}. No-op for built-in / unregistered kinds, when the kind declares no
278
+ * pre-ops, or when GitHub isn't wired (no `resolveRunRepoContext`) — so the engine runs
279
+ * unchanged without the feature. A throwing op propagates to fail the step.
280
+ */
281
+ private runRegisteredPreOps;
282
+ /**
283
+ * Resolve a block's run-repo context for its pre/post-op hooks. Returns null only when
284
+ * the resolver is UNWIRED (tests / GitHub not connected) so a deployment without the
285
+ * feature simply skips the hooks. When the resolver IS wired, its result — including a
286
+ * THROW from `resolveRepoTarget` for a block that isn't under a linked service — is
287
+ * propagated as-is: a registered kind with repo hooks run on a misconfigured block fails
288
+ * the run loudly rather than silently committing nothing (or guessing a repo), the same
289
+ * way a container custom kind fails at dispatch.
290
+ */
291
+ private resolveRunRepo;
292
+ /**
293
+ * Run a registered kind's POST-op hooks after its agent step's result is recorded:
294
+ * deterministic backend work that consumes the agent's structured output (coerce its
295
+ * JSON, render artifact files, commit them via {@link RepoFiles}) — the
296
+ * blueprint/spec rendering that used to live in the harness. Same gating + symmetry as
297
+ * {@link runRegisteredPreOps}; the agent's {@link AgentRunResult} is threaded through.
298
+ */
299
+ private runRegisteredPostOps;
300
+ /**
301
+ * The BUILT-IN (non-registry) post-ops for a migrated built-in kind, keyed by agent
302
+ * kind — the deterministic render + commit lifted out of the executor-harness. Kept
303
+ * OUT of the agent-kind registry on purpose: registering the built-ins would leak them
304
+ * into `customAgentKinds` / the SPA palette. Empty for every other kind.
305
+ */
306
+ private builtInPostOps;
307
+ /**
308
+ * The built-in (NON-registry) post-ops keyed by kind. A small map rather than an
309
+ * `if`-chain so each migrated built-in is one entry as the strangler converts more
310
+ * kinds; deliberately NOT the agent-kind registry (that would leak the built-ins into
311
+ * `customAgentKinds` / the SPA palette).
312
+ */
313
+ private static readonly BUILT_IN_POST_OPS;
314
+ /**
315
+ * The branch a built-in kind's post-op reads/commits, resolved to MATCH the kind's
316
+ * container dispatch (so the post-op commits onto exactly the branch the explore agent
317
+ * cloned).
318
+ * - blueprints clones the PR branch when one is open, else the repo's default branch —
319
+ * so the initial bootstrap map lands directly on the default branch, mirroring
320
+ * {@link ContainerAgentExecutor}'s `pr`-clone resolution (`prBranch ?? baseBranch`).
321
+ * Deliberately NOT {@link resolveRepoOpBranch}, whose `pr` case ensures a work branch
322
+ * for the no-PR case — correct for a committing CUSTOM kind, wrong for the blueprint.
323
+ * - spec-writer commits onto the per-block WORK branch (`cat-factory/<blockId>`), created
324
+ * from base when absent. It is a WRITER (not read-only), so its container dispatch
325
+ * always ensures + clones that work branch ({@link ContainerAgentExecutor}'s
326
+ * `workBranchReady ? workBranch : …` resolves to the work branch). We mirror that
327
+ * DETERMINISTICALLY here — NOT via {@link resolveRepoOpBranch}'s `work` case, whose
328
+ * PR-preferring branch would commit onto a divergent PR branch (read one tree, write
329
+ * another) if a PR were ever open on a branch other than `cat-factory/<blockId>`.
330
+ */
331
+ private builtInRepoOpBranch;
332
+ /**
333
+ * The post-completion resolver for an agent kind, or undefined when the kind has none.
334
+ * A resolver runs DETERMINISTIC backend follow-up once the step's agent finishes — e.g.
335
+ * the merger performs the real GitHub merge — independent of the step's position in the
336
+ * pipeline. Built lazily (closures capture `this`) and cached per instance; the registry
337
+ * merges deployment-registered resolvers ({@link registeredStepResolverFactories}), a
338
+ * startup import side effect (see {@link gateFor} for the same caching caveat). See
339
+ * {@link StepCompletionResolver}.
340
+ */
341
+ /**
342
+ * Dispatch a step (whose preamble already ran in {@link stepInstance}) to the first
343
+ * registered {@link StepHandler} whose `canHandle` claims it, ordered by `order`. The
344
+ * fallthrough handler claims everything, so this always resolves to a handler.
345
+ */
346
+ dispatchStepHandler(ctx: StepHandlerContext): Promise<AdvanceResult>;
347
+ /**
348
+ * Build the order-sorted per-step-kind handler list, mirroring
349
+ * {@link buildStepResolverRegistry} (built-ins constructed inline, closing over `this`).
350
+ * Engine-internal: there is no public `registerStepHandler` seam. Phase 0 registers only
351
+ * the generic fallthrough; later phases prepend more-specific handlers with lower `order`.
352
+ */
353
+ private buildStepHandlerRegistry;
354
+ /**
355
+ * Run the first completion-path interceptor that claims this finished step, returning its
356
+ * short-circuit {@link AdvanceResult} (the companion verdict loop / tester re-test) or
357
+ * `null` to let `recordStepResult`'s normal finish/advance spine run. Engine-internal,
358
+ * mirroring {@link dispatchStepHandler}.
359
+ */
360
+ private dispatchStepCompletionInterceptor;
361
+ /**
362
+ * Build the order-sorted completion-path interceptors (companion / tester verdict
363
+ * short-circuits), mirroring {@link buildStepHandlerRegistry} — built-ins constructed
364
+ * inline closing over `this`, no public registration seam.
365
+ */
366
+ private buildStepCompletionInterceptors;
367
+ private stepResolverFor;
368
+ private buildStepResolverRegistry;
369
+ /** The shared engine seams handed to a deployment-registered step resolver's factory. */
370
+ private makeResolverContext;
371
+ private buildGateRegistry;
372
+ /** The shared engine seams handed to a deployment-registered gate's factory. */
373
+ private makeGateContext;
374
+ /**
375
+ * Evaluate a polling gate step once and decide (shared by the initial advance and the
376
+ * durable `awaiting_gate` re-poll):
377
+ * - no provider wired → pass-through (advance; nothing to gate);
378
+ * - precheck passes → advance to the next step (the helper agent is NEVER spun up);
379
+ * - still computing → `awaiting_gate` (the driver sleeps then calls {@link pollGate});
380
+ * - fails, budget left → dispatch the helper container agent (`awaiting_job`);
381
+ * - fails, budget spent → the gate's exhaustion handler, then fail the run.
382
+ */
383
+ private evaluateGate;
384
+ /**
385
+ * Dispatch a gate's helper container agent on a failed precheck: build the agent
386
+ * context with the kind overridden to the helper (it clones the PR head branch and
387
+ * pushes — no new PR), park on the job, and flip the gate to `working`. Idempotent
388
+ * under replay via the step's `jobId` (re-attach handled in {@link evaluateGate}).
389
+ */
390
+ private dispatchGateHelper;
391
+ /**
392
+ * Append the items the harness streamed since the last poll onto the Coder step's
393
+ * follow-up state as fresh `pending` items. A no-op when the companion is off or nothing
394
+ * was streamed. Returns whether anything was added (so the poller persists + emits).
395
+ */
396
+ private appendStreamedFollowUps;
397
+ /**
398
+ * The Follow-up companion gate, evaluated when the Coder step completes: park the run on
399
+ * a durable decision while any item is undecided; else loop the Coder for the queued /
400
+ * answered items (within the budget); else fall through (return undefined) so the normal
401
+ * advance/finish logic runs. Returns an {@link AdvanceResult} only when it parks or loops.
402
+ */
403
+ private evaluateFollowUpGate;
404
+ /**
405
+ * Reset the Coder step and fold the human's queued follow-ups / answered questions into
406
+ * its rework so the next pass extends the prior work. Marks those items `sentToCoder` so
407
+ * a later completion doesn't re-loop them, and counts the loop against the budget. Shared
408
+ * by the at-completion path ({@link evaluateFollowUpGate}) and the parked-resume path.
409
+ */
410
+ private loopCoderForFollowUps;
411
+ /** Raise the "follow-ups need decisions" inbox card when the Coder parks on undecided items. */
412
+ private raiseFollowUpPending;
413
+ /**
414
+ * The run's "active" follow-up companion step for a read with no item context (the GET /
415
+ * the inbox-card open). A pipeline may carry MORE THAN ONE follow-up-enabled Coder step,
416
+ * so this must not blindly pick the first: prefer the step the run is currently on (a Coder
417
+ * parked on its follow-up gate), else the latest enabled step that has surfaced items, else
418
+ * the first enabled one.
419
+ */
420
+ private activeFollowUpStep;
421
+ /** Read a run's live follow-up companion state (the active Coder step's items), or null. */
422
+ getFollowUps(workspaceId: string, executionId: string): Promise<FollowUpsStepState | null>;
423
+ /**
424
+ * Locate the run + the Coder step that OWNS the addressed item + the item, throwing 404
425
+ * when absent. Routes by item id (not "the first enabled step") so a pipeline carrying more
426
+ * than one follow-up-enabled Coder step decides each item on the step that surfaced it —
427
+ * otherwise a later Coder's items 404 and its gate can never be cleared.
428
+ */
429
+ private loadFollowUpItem;
430
+ /** File a `follow_up` item as a tracker issue (GitHub / Jira), recording the ticket ref. */
431
+ fileFollowUp(workspaceId: string, executionId: string, itemId: string): Promise<FollowUpsStepState>;
432
+ /** Queue a `follow_up` item to send back to the Coder on its next pass. */
433
+ queueFollowUp(workspaceId: string, executionId: string, itemId: string): Promise<FollowUpsStepState>;
434
+ /** Answer a `question` item; the answer is folded into the Coder's next pass. */
435
+ answerFollowUp(workspaceId: string, executionId: string, itemId: string, answer: string): Promise<FollowUpsStepState>;
436
+ /** Dismiss a follow-up / question item without acting on it. */
437
+ dismissFollowUp(workspaceId: string, executionId: string, itemId: string): Promise<FollowUpsStepState>;
438
+ /**
439
+ * Persist an item decision and, when the run is PARKED on this step's follow-up gate and
440
+ * every item is now decided, drive it forward: loop the Coder for the queued / answered
441
+ * items (within the budget), else advance past the gate. When the run is not parked (the
442
+ * Coder is still running, or it already moved on) this only persists + emits the change.
443
+ */
444
+ private driveFollowUpsAfterDecision;
445
+ /** Provision inputs (`{{input.*}}`) derived from the block under deployment. */
446
+ deployInputs(block: Block): Record<string, string>;
447
+ /**
448
+ * Typed git/PR/repo context for the deployer, derived from the block's PR ref. A
449
+ * PR-environment provider (e.g. an in-house adapter) needs the branch/repo to target
450
+ * the right environment; the same values are also flattened into `{{input.*}}` for
451
+ * the manifest path. `owner`/`repo` are parsed from the PR url when present.
452
+ */
453
+ deployContext(block: Block): ProvisionContext;
454
+ /**
455
+ * Invoke the agent for an already-built context. Failures are swallowed into the
456
+ * step output so a run never wedges — unless `rethrowAgentErrors` is set (the
457
+ * durable path), in which case the error propagates so the driver's per-step
458
+ * retry can take over.
459
+ */
460
+ runAgent(context: AgentRunContext, options?: AdvanceOptions): Promise<AgentRunResult>;
461
+ /**
462
+ * Strictly parse a Blueprinter step's tree and reconcile it onto the board. The
463
+ * blueprint maps the whole repository, so it is reconciled onto the run block's
464
+ * **service frame** (walked up from the block), not the task the run targeted.
465
+ * Best-effort and reconciler-gated: a parse/reconcile failure is logged-by-throw
466
+ * upstream only when the reconciler is wired; with no reconciler it is a no-op so
467
+ * the blueprint's in-repo files still land.
468
+ */
469
+ private ingestBlueprint;
470
+ /**
471
+ * Strictly validate a spec-writer step's unified specification. The canonical record
472
+ * is the in-repo `spec/` files the harness already committed; this is the trust
473
+ * boundary (a malformed payload is dropped, never trusted) plus a client refresh
474
+ * nudge. A persisted board projection is a deliberate later phase.
475
+ */
476
+ private ingestSpec;
477
+ }
478
+ export {};
479
+ //# sourceMappingURL=RunDispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunDispatcher.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/RunDispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAEb,eAAe,EACf,cAAc,EAEd,KAAK,EACL,eAAe,EAEf,iBAAiB,EACjB,aAAa,EACb,KAAK,EACL,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EAEnB,kBAAkB,EAElB,cAAc,EAEd,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAGhB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EAErB,iBAAiB,EAIjB,qBAAqB,EACrB,UAAU,EACX,MAAM,qBAAqB,CAAA;AA4B5B,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAA;AAgC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAA;AAChF,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAA;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAA;AAClF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAEhE;;;;GAIG;AACH,KAAK,mBAAmB,GAAG;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,wBAAwB,EAAE,MAAM,CAAA;IAChC,4BAA4B,EAAE,uBAAuB,CAAA;IACrD,yBAAyB,EAAE,MAAM,CAAA;IACjC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,uBAAuB,EAAE,MAAM,CAAA;CAChC,CAAA;AAqCD,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,eAAe,CAAA;IAChC,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,aAAa,EAAE,aAAa,CAAA;IAC5B,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,uBAAuB,CAAA;IAC/B,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;IACnB,SAAS,EAAE,SAAS,CAAA;IACpB,eAAe,EAAE,eAAe,CAAA;IAChC,cAAc,EAAE,mBAAmB,CAAA;IACnC,aAAa,EAAE,aAAa,CAAA;IAC5B,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,4BAA4B,EAAE,4BAA4B,CAAA;IAC1D,UAAU,EAAE,oBAAoB,CAAA;IAChC,gBAAgB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAC/C,WAAW,EAAE,UAAU,CAAC,aAAa,CAAC,CAAA;IACtC,0BAA0B,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACzD,0BAA0B,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACzD,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,uBAAuB,CAAC,EAAE,8BAA8B,CAAA;IACxD,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,cAAc,CAAC,EAAE,sBAAsB,CAAA;IACvC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,2BAA2B,CAAC,EAAE,CAC5B,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,KACxB,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAClC,2FAA2F;IAC3F,kBAAkB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACvF,6FAA6F;IAC7F,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,oBAAoB,KAAK,OAAO,CAAA;CAClF;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAA8B;IAC3E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;IAChE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA+B;IAC1E,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA+B;IAC1E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAgC;IACzE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAuB;IAC9D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAwB;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAuB;IAC9D,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAGX;IAClC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAGF;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAiE;IAElG,qFAAqF;IACrF,OAAO,CAAC,iBAAiB,CAAC,CAA6B;IACvD,4EAA4E;IAC5E,OAAO,CAAC,iBAAiB,CAAC,CAAqC;IAC/D,8FAA8F;IAC9F,OAAO,CAAC,gBAAgB,CAAC,CAAe;IACxC,mEAAmE;IACnE,OAAO,CAAC,8BAA8B,CAAC,CAA6B;IAEpE,YAAY,IAAI,EAAE,iBAAiB,EAgClC;IAED;;;;;;;;OAQG;YACW,eAAe;IAwF7B;;;;;;OAMG;IACG,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO5E;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,uBAAuB,CAC3B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GACvC,OAAO,CAAC,OAAO,CAAC,CA8BlB;IAED;;;;;;;OAOG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAqPnF;IAED;;;;;;;OAOG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAsB/E;IAED;;;;;;;;;;OAUG;IACG,yBAAyB,CAC7B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA8CxB;IAED;;;;;;;;OAQG;YACW,2BAA2B;IAsCzC;;;;;;OAMG;IACG,aAAa,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,aAAa,CAAC,CAsBxB;IACD;;;;;OAKG;YACW,gBAAgB;IAwO9B;;;;;OAKG;YACW,WAAW;IA6BzB;;;;;OAKG;YACW,UAAU;IAkCxB;;;;;;;;;OASG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAGrD;IAED;;;;;;;;;;;;;;;OAeG;YACW,mBAAmB;IAuBjC;;;;;;;OAOG;YACW,gBAAgB;IAY9B;;;;;;OAMG;YACW,mBAAmB;IAkBjC;;;;;;;;OAQG;YACW,cAAc;IAQ5B;;;;;;OAMG;YACW,oBAAoB;IAuClC;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAItB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAGxC;IAED;;;;;;;;;;;;;;;;OAgBG;YACW,mBAAmB;IAWjC;;;;;;;;OAQG;IACH;;;;OAIG;IACH,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAOnE;IAED;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;IAmKhC;;;;;OAKG;YACW,iCAAiC;IAe/C;;;;OAIG;IACH,OAAO,CAAC,+BAA+B;IA0CvC,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,yBAAyB;IAgFjC,yFAAyF;IACzF,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,iBAAiB;IAazB,gFAAgF;IAChF,OAAO,CAAC,eAAe;IAevB;;;;;;;;OAQG;YACW,YAAY;IAqH1B;;;;;OAKG;YACW,kBAAkB;IA4DhC;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAuB/B;;;;;OAKG;YACW,oBAAoB;IAqBlC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAiB7B,gGAAgG;YAClF,oBAAoB;IAsBlC;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAa1B,4FAA4F;IACtF,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAI/F;IAED;;;;;OAKG;YACW,gBAAgB;IAqB9B,4FAA4F;IACtF,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAoC7B;IAED,2EAA2E;IACrE,aAAa,CACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAc7B;IAED,iFAAiF;IAC3E,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAe7B;IAED,gEAAgE;IAC1D,eAAe,CACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,kBAAkB,CAAC,CAU7B;IAED;;;;;OAKG;YACW,2BAA2B;IA+CzC,gFAAgF;IAChF,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQjD;IAED;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAe5C;IAED;;;;;OAKG;IACG,QAAQ,CACZ,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,cAAc,CAAC,CAYzB;IAED;;;;;;;OAOG;YACW,eAAe;IAsB7B;;;;;OAKG;YACW,UAAU;CAWzB"}