@cat-factory/orchestration 0.192.0 → 0.194.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.
Files changed (117) hide show
  1. package/dist/container/dependencies.d.ts +5 -1
  2. package/dist/container/dependencies.d.ts.map +1 -1
  3. package/dist/container/engine-collaborators.d.ts.map +1 -1
  4. package/dist/container/engine-collaborators.js +4 -7
  5. package/dist/container/engine-collaborators.js.map +1 -1
  6. package/dist/container/execution-service.d.ts.map +1 -1
  7. package/dist/container/execution-service.js +3 -0
  8. package/dist/container/execution-service.js.map +1 -1
  9. package/dist/container/inline-model-deps.d.ts +20 -0
  10. package/dist/container/inline-model-deps.d.ts.map +1 -0
  11. package/dist/container/inline-model-deps.js +38 -0
  12. package/dist/container/inline-model-deps.js.map +1 -0
  13. package/dist/container/modules.d.ts.map +1 -1
  14. package/dist/container/modules.js +23 -39
  15. package/dist/container/modules.js.map +1 -1
  16. package/dist/container/review-modules.d.ts.map +1 -1
  17. package/dist/container/review-modules.js +10 -28
  18. package/dist/container/review-modules.js.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/inlineBlockModel.d.ts +51 -0
  24. package/dist/inlineBlockModel.d.ts.map +1 -0
  25. package/dist/inlineBlockModel.js +31 -0
  26. package/dist/inlineBlockModel.js.map +1 -0
  27. package/dist/modules/board/BoardService.d.ts +2 -0
  28. package/dist/modules/board/BoardService.d.ts.map +1 -1
  29. package/dist/modules/board/BoardService.js +4 -0
  30. package/dist/modules/board/BoardService.js.map +1 -1
  31. package/dist/modules/board/publicBoardReads.d.ts +12 -0
  32. package/dist/modules/board/publicBoardReads.d.ts.map +1 -1
  33. package/dist/modules/board/publicBoardReads.js +19 -4
  34. package/dist/modules/board/publicBoardReads.js.map +1 -1
  35. package/dist/modules/bugHunt/BugHuntAssessorService.d.ts +8 -4
  36. package/dist/modules/bugHunt/BugHuntAssessorService.d.ts.map +1 -1
  37. package/dist/modules/bugHunt/BugHuntAssessorService.js +6 -10
  38. package/dist/modules/bugHunt/BugHuntAssessorService.js.map +1 -1
  39. package/dist/modules/docInterview/DocInterviewService.d.ts +8 -4
  40. package/dist/modules/docInterview/DocInterviewService.d.ts.map +1 -1
  41. package/dist/modules/docInterview/DocInterviewService.js +4 -13
  42. package/dist/modules/docInterview/DocInterviewService.js.map +1 -1
  43. package/dist/modules/execution/AgentContextBuilder.d.ts +14 -12
  44. package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -1
  45. package/dist/modules/execution/AgentContextBuilder.js +8 -28
  46. package/dist/modules/execution/AgentContextBuilder.js.map +1 -1
  47. package/dist/modules/execution/AgentDispatchController.d.ts +115 -0
  48. package/dist/modules/execution/AgentDispatchController.d.ts.map +1 -0
  49. package/dist/modules/execution/AgentDispatchController.js +307 -0
  50. package/dist/modules/execution/AgentDispatchController.js.map +1 -0
  51. package/dist/modules/execution/ExecutionService.d.ts +18 -105
  52. package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
  53. package/dist/modules/execution/ExecutionService.js +70 -589
  54. package/dist/modules/execution/ExecutionService.js.map +1 -1
  55. package/dist/modules/execution/ExecutionServiceDependencies.d.ts +19 -3
  56. package/dist/modules/execution/ExecutionServiceDependencies.d.ts.map +1 -1
  57. package/dist/modules/execution/ForkChatService.d.ts +8 -4
  58. package/dist/modules/execution/ForkChatService.d.ts.map +1 -1
  59. package/dist/modules/execution/ForkChatService.js +4 -13
  60. package/dist/modules/execution/ForkChatService.js.map +1 -1
  61. package/dist/modules/execution/IterationCapController.d.ts +57 -0
  62. package/dist/modules/execution/IterationCapController.d.ts.map +1 -0
  63. package/dist/modules/execution/IterationCapController.js +141 -0
  64. package/dist/modules/execution/IterationCapController.js.map +1 -0
  65. package/dist/modules/execution/JudgeService.d.ts +8 -4
  66. package/dist/modules/execution/JudgeService.d.ts.map +1 -1
  67. package/dist/modules/execution/JudgeService.js +4 -13
  68. package/dist/modules/execution/JudgeService.js.map +1 -1
  69. package/dist/modules/execution/RunAdmission.d.ts +1 -1
  70. package/dist/modules/execution/RunAdmission.d.ts.map +1 -1
  71. package/dist/modules/execution/RunAdmission.js +5 -2
  72. package/dist/modules/execution/RunAdmission.js.map +1 -1
  73. package/dist/modules/execution/RunDispatcher.d.ts +31 -195
  74. package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
  75. package/dist/modules/execution/RunDispatcher.js +47 -313
  76. package/dist/modules/execution/RunDispatcher.js.map +1 -1
  77. package/dist/modules/execution/RunDispatcherDependencies.d.ts +142 -0
  78. package/dist/modules/execution/RunDispatcherDependencies.d.ts.map +1 -0
  79. package/dist/modules/execution/RunDispatcherDependencies.js +27 -0
  80. package/dist/modules/execution/RunDispatcherDependencies.js.map +1 -0
  81. package/dist/modules/execution/RunLifecycleController.d.ts +141 -0
  82. package/dist/modules/execution/RunLifecycleController.d.ts.map +1 -0
  83. package/dist/modules/execution/RunLifecycleController.js +489 -0
  84. package/dist/modules/execution/RunLifecycleController.js.map +1 -0
  85. package/dist/modules/execution/TesterQualityReviewService.d.ts +8 -4
  86. package/dist/modules/execution/TesterQualityReviewService.d.ts.map +1 -1
  87. package/dist/modules/execution/TesterQualityReviewService.js +4 -13
  88. package/dist/modules/execution/TesterQualityReviewService.js.map +1 -1
  89. package/dist/modules/execution/dispatchPromptSettings.d.ts +42 -2
  90. package/dist/modules/execution/dispatchPromptSettings.d.ts.map +1 -1
  91. package/dist/modules/execution/dispatchPromptSettings.js +37 -0
  92. package/dist/modules/execution/dispatchPromptSettings.js.map +1 -1
  93. package/dist/modules/execution/run-action-controllers.d.ts +18 -0
  94. package/dist/modules/execution/run-action-controllers.d.ts.map +1 -0
  95. package/dist/modules/execution/run-action-controllers.js +19 -0
  96. package/dist/modules/execution/run-action-controllers.js.map +1 -0
  97. package/dist/modules/execution/run-context-admission.d.ts +1 -1
  98. package/dist/modules/execution/run-context-admission.d.ts.map +1 -1
  99. package/dist/modules/execution/run-context-admission.js +2 -0
  100. package/dist/modules/execution/run-context-admission.js.map +1 -1
  101. package/dist/modules/initiative/InitiativeInterviewService.d.ts +8 -4
  102. package/dist/modules/initiative/InitiativeInterviewService.d.ts.map +1 -1
  103. package/dist/modules/initiative/InitiativeInterviewService.js +4 -13
  104. package/dist/modules/initiative/InitiativeInterviewService.js.map +1 -1
  105. package/dist/modules/kaizen/KaizenService.d.ts +14 -9
  106. package/dist/modules/kaizen/KaizenService.d.ts.map +1 -1
  107. package/dist/modules/kaizen/KaizenService.js +11 -16
  108. package/dist/modules/kaizen/KaizenService.js.map +1 -1
  109. package/dist/modules/modelPresets/ModelPresetService.d.ts +54 -2
  110. package/dist/modules/modelPresets/ModelPresetService.d.ts.map +1 -1
  111. package/dist/modules/modelPresets/ModelPresetService.js +103 -4
  112. package/dist/modules/modelPresets/ModelPresetService.js.map +1 -1
  113. package/dist/modules/review/IterativeReviewService.d.ts +8 -4
  114. package/dist/modules/review/IterativeReviewService.d.ts.map +1 -1
  115. package/dist/modules/review/IterativeReviewService.js +4 -13
  116. package/dist/modules/review/IterativeReviewService.js.map +1 -1
  117. package/package.json +11 -11
@@ -0,0 +1,489 @@
1
+ import { assertFound, ConflictError, DEFAULT_RISK_POLICY, ValidationError, } from '@cat-factory/kernel';
2
+ import { companionFor } from '@cat-factory/agents';
3
+ import { DEFAULT_COMPANION_MAX_ATTEMPTS, pipelineHasVisualStep } from '@cat-factory/contracts';
4
+ import { assertPipelineLaunchable } from '../pipelines/pipelineShape.js';
5
+ import { isTesterKind } from './ci.logic.js';
6
+ import { DEFAULT_FOLLOW_UP_MAX_LOOPS, FOLLOW_UP_PRODUCER_KIND } from './followUp.logic.js';
7
+ import { isRalphKind, resolveRalphConfig, seedRalphState } from './ralph.logic.js';
8
+ import { buildResumedInstance, planResumedSteps, planRestartFromStep } from './retry.logic.js';
9
+ import { claimLiveRunOrConflict, handOffLiveRun } from './runStart.js';
10
+ import { descendantIds } from '../board/board.logic.js';
11
+ /**
12
+ * A run's LIFECYCLE surface: every entry point that launches one (`start`), re-launches one
13
+ * (`retry` / `restartFromStep`), lifts a spend pause (`resumePaused`), or ends one (`cancel` /
14
+ * `stopRun` / `teardownForBlockTree`).
15
+ *
16
+ * They belong together because all three launch paths write the SAME two things in the SAME order:
17
+ * the atomic live-run claim, then the durable/SPA/outbound hand-off (both owned by `runStart.ts`,
18
+ * reached through the one `runStartDeps` getter below). They differ only in the block patch written
19
+ * between the two and in what each tears down first. Keeping that order in one place is what stops
20
+ * a new entry point from claiming without handing off (a run nothing drives) or announcing before
21
+ * the claim commits.
22
+ *
23
+ * `ExecutionService` keeps thin delegates, so no HTTP call site changed. The per-step machine
24
+ * (`advanceInstance` / `stepInstance`) and the human decision surface (`StepDecisionController`)
25
+ * deliberately stay where they are: those act on a run that is already live.
26
+ */
27
+ export class RunLifecycleController {
28
+ deps;
29
+ constructor(deps) {
30
+ this.deps = deps;
31
+ }
32
+ /** Start a pipeline against a block, replacing any prior run on it. */
33
+ async start(workspaceId, blockId, pipelineId, options = {}) {
34
+ const { initiatedBy, activate, origin = 'manual', intakeOrigin, gatesOverride } = options;
35
+ await this.deps.requireWorkspace(workspaceId);
36
+ const block = await this.deps.requireBlock(workspaceId, blockId);
37
+ const pipeline = assertFound(await this.deps.pipelineRepository.get(workspaceId, pipelineId), 'Pipeline', pipelineId);
38
+ // Launch-constraint gate (start-only, NOT part of the shared retry re-validation): reject a
39
+ // manual start of a recurring-only pipeline (or a scheduled fire of a one-off-only one), and
40
+ // a bug-intake pipeline that isn't recurring. Before any side effects.
41
+ assertPipelineLaunchable(pipeline.agentKinds, pipeline.availability, origin, pipeline.enabled);
42
+ // Per-run gate override must be parallel to the pipeline's steps (one boolean per step,
43
+ // original-index-aligned like `pipeline.gates`). A mismatch means a preset's review mapping
44
+ // is out of step with the pipeline it targets — reject up front, before any side effects.
45
+ if (gatesOverride && gatesOverride.length !== pipeline.agentKinds.length) {
46
+ throw new ValidationError(`Gate override has ${gatesOverride.length} entr${gatesOverride.length === 1 ? 'y' : 'ies'} but pipeline '${pipeline.id}' has ${pipeline.agentKinds.length} step(s).`);
47
+ }
48
+ // Shared config/resource preconditions (pipeline shape, frame type, tester infra, binary
49
+ // storage, agent backend, provider/preset satisfiability, budget) — the SAME gate a retry
50
+ // runs, so the two can't drift. See assertRunnable.
51
+ await this.deps.admission.assertRunnable(workspaceId, block, pipeline, initiatedBy);
52
+ // A Ralph-loop step needs a programmatic completion command (its exit condition); refuse to
53
+ // start a misconfigured run rather than dispatch a validation-less coding pass that never
54
+ // gates. The command is a per-task agent-config value (the SPA also requires it at creation).
55
+ if (pipeline.agentKinds.some(isRalphKind) &&
56
+ !resolveRalphConfig(block.agentConfig).validationCommand) {
57
+ throw new ValidationError('A Ralph loop task needs a validation command (its completion criterion) before it can ' +
58
+ 'start. Set one in the task configuration.');
59
+ }
60
+ // START-ONLY gates below: a retry REPLACES the failed run rather than adding a new one, so
61
+ // the concurrency limit doesn't apply to it, and a re-drive of an already-started task isn't
62
+ // re-gated on its dependencies.
63
+ // Enforce the workspace's per-service running-task limit (off by default) — a clear,
64
+ // actionable error before any side effects, so the human knows why the start was refused.
65
+ await this.deps.admission.assertWithinTaskLimit(workspaceId, block);
66
+ // Hard dependency gate: a task cannot start while any block it `dependsOn` is unfinished
67
+ // (not yet `done`/merged). Enforced server-side so it holds for manual starts, recurring
68
+ // fires, auto-start propagation and direct API calls alike — the frontend's runnable
69
+ // check is only a hint. Before any side effects so nothing is torn down on a refusal.
70
+ await this.deps.admission.assertDependenciesMet(workspaceId, block);
71
+ // Mint the activation next: if the credential can't be unlocked, fail before
72
+ // tearing down the block's prior run or creating a new one.
73
+ const executionId = this.deps.idGenerator.next('exec');
74
+ await activate?.(executionId);
75
+ // Read the block's prior run once: a manual re-start of an already-running block REPLACES
76
+ // it (the board offers "start" on a live block), so we pass its id to `insertLive` as the
77
+ // `replaceId` it supersedes atomically. A genuinely-CONCURRENT second start reads the SAME
78
+ // prior (or none), so only one insert wins and the other is rejected 409 — the loser's
79
+ // `replaceId` deletes only what it read, never the winner's fresh row (see insertLive).
80
+ const prior = await this.deps.executionRepository.getByBlock(workspaceId, blockId);
81
+ // Replacing the block's prior run: clear its per-run activation now (it never reaches
82
+ // the terminal cleanup in emitInstance when it's still running), so a replaced run's
83
+ // system-encrypted token copy doesn't linger to its TTL. Keyed by the OLD run id, so
84
+ // the activation just minted for the new run is untouched.
85
+ if (this.deps.subscriptionActivations && prior && prior.id !== executionId) {
86
+ // Best-effort + idempotent, mirroring the terminal cleanup in RunStateMachine.emit: a
87
+ // failure here must never derail the start. In mothership mode this repo is remote and
88
+ // `deleteByExecution` is not yet allow-listed (it throws `unknown_method`), so an
89
+ // unguarded call would otherwise break re-running any block; the TTL sweep reclaims the
90
+ // stale activation row as the backstop.
91
+ try {
92
+ await this.deps.subscriptionActivations.deleteByExecution(prior.id);
93
+ }
94
+ catch {
95
+ // Swallow — see above.
96
+ }
97
+ }
98
+ // NB: do NOT `deleteByBlock` here — `claimLiveRunOrConflict` (below) atomically clears the
99
+ // block's terminal rows AND the `prior` run it replaces, then inserts the new live run, so a
100
+ // concurrent double-start is rejected by the live-run index instead of both wiping each
101
+ // other's row (see insertLive).
102
+ // Build the run only from the ENABLED steps. A step the pipeline marked
103
+ // `enabled[i] === false` is kept in the saved pipeline (so it can be toggled back
104
+ // on later) but skipped here entirely. Gates/thresholds are read by the kind's
105
+ // ORIGINAL index `i`, so they stay aligned to the kind even when earlier steps are
106
+ // skipped; the first SURVIVING step is the one that starts working.
107
+ const steps = pipeline.agentKinds
108
+ .map((kind, i) => ({ kind, i }))
109
+ .filter(({ i }) => pipeline.enabled?.[i] !== false)
110
+ .map(({ kind, i }, position) => {
111
+ const companionDef = companionFor(kind);
112
+ return {
113
+ agentKind: kind,
114
+ state: position === 0 ? 'working' : 'pending',
115
+ progress: 0,
116
+ decision: null,
117
+ // A gated step pauses for human approval once its proposal is ready (see
118
+ // recordStepResult). A per-run override (the initiative-preset seam) wins over the
119
+ // pipeline's own gate for this step; else the pipeline definition at run start. Both
120
+ // read by the step's ORIGINAL index `i`, so they stay aligned to the kind even when
121
+ // earlier steps are disabled.
122
+ requiresApproval: gatesOverride?.[i] ?? pipeline.gates?.[i] ?? false,
123
+ approval: null,
124
+ // A consensus-enabled step runs through the multi-model mechanism (the consensus
125
+ // executor reads this off the context). Copied from the pipeline at run start.
126
+ ...(pipeline.consensus?.[i] ? { consensus: pipeline.consensus[i] } : {}),
127
+ // Estimate gating: when set+enabled the step is skipped at runtime unless the
128
+ // block estimate (written by an earlier task-estimator step) meets the threshold.
129
+ ...(pipeline.gating?.[i] ? { gating: pipeline.gating[i] } : {}),
130
+ // The extensible per-step options bag (the new home for per-step parameters — see
131
+ // stepOptionsSchema). Copied from the pipeline at run start, keyed by the step's
132
+ // ORIGINAL index `i`, so it stays aligned to the kind even when earlier steps are
133
+ // disabled. Today it carries the requirements-review `autoRecommend` toggle.
134
+ ...(pipeline.stepOptions?.[i] ? { stepOptions: pipeline.stepOptions[i] } : {}),
135
+ // A companion step carries its quality bar + rework budget, seeded from the
136
+ // pipeline's per-step threshold (else the companion's default).
137
+ ...(companionDef
138
+ ? {
139
+ companion: {
140
+ threshold: pipeline.thresholds?.[i] ?? companionDef.defaultThreshold,
141
+ maxAttempts: DEFAULT_COMPANION_MAX_ATTEMPTS,
142
+ attempts: 0,
143
+ verdicts: [],
144
+ },
145
+ }
146
+ : {}),
147
+ // The Follow-up companion is on by default for a `coder` step; the pipeline's
148
+ // per-step `followUps[i] === false` toggle disables it. Seeded empty here; the
149
+ // harness streams items in as the Coder surfaces them (see pollAgentJob).
150
+ ...(kind === FOLLOW_UP_PRODUCER_KIND && pipeline.followUps?.[i] !== false
151
+ ? {
152
+ followUps: {
153
+ enabled: true,
154
+ items: [],
155
+ loops: 0,
156
+ maxLoops: DEFAULT_FOLLOW_UP_MAX_LOOPS,
157
+ },
158
+ }
159
+ : {}),
160
+ // The test quality-control companion is on by default for a Tester step; the
161
+ // pipeline's per-step `testerQuality[i].enabled === false` disables it. `maxAttempts`
162
+ // is seeded with the default ceiling here and refreshed from the task's resolved
163
+ // merge preset on the first report (TesterController). Optional estimate gating is
164
+ // carried through so it can be evaluated against the block estimate at gate time.
165
+ ...(isTesterKind(kind) && pipeline.testerQuality?.[i]?.enabled !== false
166
+ ? {
167
+ testerQuality: {
168
+ enabled: true,
169
+ attempts: 0,
170
+ maxAttempts: DEFAULT_RISK_POLICY.maxTesterQualityIterations,
171
+ verdicts: [],
172
+ ...(pipeline.testerQuality?.[i]?.gating
173
+ ? { gating: pipeline.testerQuality[i].gating }
174
+ : {}),
175
+ },
176
+ }
177
+ : {}),
178
+ // A `ralph` step carries its persistent-loop state — the iteration count, the budget,
179
+ // and the programmatic completion command — seeded from the block's per-task agent
180
+ // config. Riding the persisted step is what lets a mid-loop run survive a restart
181
+ // (both durable drivers + sweepers re-drive from it). See ralph.logic.ts.
182
+ ...(isRalphKind(kind)
183
+ ? { ralph: seedRalphState(resolveRalphConfig(block.agentConfig)) }
184
+ : {}),
185
+ };
186
+ });
187
+ if (steps.length === 0) {
188
+ throw new ValidationError('Pipeline has no enabled steps to run.');
189
+ }
190
+ // For a visual (UI-test) pipeline on a frontend frame, resolve its backend bindings ONCE at
191
+ // start and stamp both the resolved bindings and the non-fatal advisories (duplicate env vars,
192
+ // or a partial-live set of bound services) on the run. The bindings are a frozen snapshot so
193
+ // the SPA's run/step detail projects what the run ACTUALLY drove against (truthful after the
194
+ // envs are torn down). Only paid for a visual pipeline — the same condition the tester infra
195
+ // gate keys off — so a plain backend run does no extra env read. Absent → no notes/bindings.
196
+ const frontendRun = pipelineHasVisualStep({ agentKinds: pipeline.agentKinds })
197
+ ? await this.deps.contextBuilder.resolveFrontendRunInfo(workspaceId, block)
198
+ : undefined;
199
+ const instance = {
200
+ id: executionId,
201
+ blockId,
202
+ pipelineId: pipeline.id,
203
+ pipelineName: pipeline.name,
204
+ steps,
205
+ currentStep: 0,
206
+ status: 'running',
207
+ initiatedBy: initiatedBy ?? null,
208
+ // Only a headless start carries an explicit intake origin; `ui` is the read-time
209
+ // default, so an ordinary board/schedule start stores nothing extra.
210
+ ...(intakeOrigin != null ? { intakeOrigin } : {}),
211
+ createdAt: this.deps.clock.now(),
212
+ ...(frontendRun?.notes.length ? { notes: frontendRun.notes } : {}),
213
+ ...(frontendRun?.bindings.length ? { frontendBindings: frontendRun.bindings } : {}),
214
+ };
215
+ await claimLiveRunOrConflict(this.runStartDeps, workspaceId, instance, prior?.id);
216
+ await this.deps.blockRepository.update(workspaceId, blockId, {
217
+ status: 'in_progress',
218
+ progress: 0,
219
+ executionId: instance.id,
220
+ });
221
+ await handOffLiveRun(this.runStartDeps, workspaceId, instance, block);
222
+ return instance;
223
+ }
224
+ /**
225
+ * Retry a failed run: re-drive the same pipeline on the same block, **resuming
226
+ * from the step that actually failed** rather than restarting from step 0. The
227
+ * steps that already completed are preserved (so a `coder` failure in `pl_full`
228
+ * doesn't re-run the human-gated `requirements`/`architect` steps before it);
229
+ * the failed step and everything after it are reset to a clean, re-runnable
230
+ * state. Only a `failed` run can be retried.
231
+ *
232
+ * A fresh instance id is minted because the durable runner addresses one
233
+ * Workflows instance per execution id and the failed one is terminal — the new
234
+ * instance simply starts with `currentStep` pointed at the failed step, so the
235
+ * driver advances forward from there and never re-issues the completed steps'
236
+ * work. Mirrors {@link BootstrapService.retry}; both are reached via the unified
237
+ * `POST /agent-runs/:id/retry` endpoint.
238
+ */
239
+ async retry(workspaceId, executionId,
240
+ /** The retrying user (their personal subscription is used for individual-usage
241
+ * models). Falls back to the original initiator when omitted. */
242
+ initiatedBy,
243
+ /** Mint the per-run personal-credential activation (see {@link start}). */
244
+ activate) {
245
+ await this.deps.requireWorkspace(workspaceId);
246
+ const previous = assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
247
+ if (previous.status !== 'failed') {
248
+ throw new ConflictError(`Only a failed run can be retried (run is '${previous.status}').`, 'run_not_retryable', { status: previous.status });
249
+ }
250
+ const block = await this.deps.requireBlock(workspaceId, previous.blockId);
251
+ // Run the SAME config/resource preconditions start() does (shape, frame type, tester infra,
252
+ // binary storage, agent backend, provider/preset satisfiability, budget), so a retry can't
253
+ // silently proceed on a config a fresh start would refuse — the drift that let a
254
+ // subscription-only preset fail mid-run against the routing default. Validated over the
255
+ // STORED steps (what the retry actually re-drives), not the current pipeline definition, so
256
+ // an out-of-band pipeline edit can't skew the gate and a deleted pipeline needs no special
257
+ // case. Before any side effects.
258
+ await this.deps.admission.assertRunnable(workspaceId, block, this.deps.admission.runnableShapeOf(previous.steps), initiatedBy ?? previous.initiatedBy);
259
+ const { steps, currentStep } = planResumedSteps(previous);
260
+ // Mint the activation before replacing the failed run, so a bad password aborts
261
+ // the retry without losing the retryable terminal run.
262
+ const newId = this.deps.idGenerator.next('exec');
263
+ const replaceId = previous.id;
264
+ await activate?.(newId);
265
+ // Replace the terminal failed run for this block with the resumed one (single run per
266
+ // block, matching the board's by-block projection). This mints a FRESH run id; the
267
+ // atomic `claimLiveRunOrConflict` below replaces `previous` (via `replaceId`) and clears
268
+ // any terminal rows in the SAME transaction, so a concurrent double-retry is serialised by
269
+ // the live-run index (the loser gets a 409) instead of both deleting-then-inserting.
270
+ const instance = buildResumedInstance({
271
+ previous,
272
+ id: newId,
273
+ plan: { steps, currentStep },
274
+ initiatedBy,
275
+ now: this.deps.clock.now(),
276
+ });
277
+ await claimLiveRunOrConflict(this.runStartDeps, workspaceId, instance, replaceId);
278
+ const done = steps.filter((s) => s.state === 'done').length;
279
+ await this.deps.blockRepository.update(workspaceId, previous.blockId, {
280
+ status: 'in_progress',
281
+ progress: steps.length > 0 ? done / steps.length : 0,
282
+ executionId: instance.id,
283
+ });
284
+ await handOffLiveRun(this.runStartDeps, workspaceId, instance, block);
285
+ return instance;
286
+ }
287
+ /**
288
+ * Restart a run from a human-chosen step: re-run from `fromStepIndex` onward,
289
+ * regardless of how far the run had progressed (a `done`, `failed`, `blocked`,
290
+ * `paused` or still-`running` run are all valid sources). Unlike {@link retry}
291
+ * (which resumes at the first FAILURE) this rewinds to an arbitrary step the user
292
+ * picked — so it can re-run steps that already completed.
293
+ *
294
+ * What is preserved vs reset:
295
+ * - Steps BEFORE `fromStepIndex` keep their `output`/approval/timing untouched, so
296
+ * the engine still hands the restarted step its predecessors' work as
297
+ * `priorOutputs` (and their resolved `decisions`) — a useful handoff.
298
+ * - The chosen step and every later one are reset to a clean, re-runnable state,
299
+ * dropping each step's iteration counters (companion attempts, gate/test attempts,
300
+ * eviction recoveries) so the restart starts those loops from zero.
301
+ * - A block's incorporated requirements are NOT touched: they live on the
302
+ * requirement-review record, so a restarted spec-writer/coder still receives the
303
+ * incorporated document (or the base description when none was generated). When the
304
+ * chosen step is the `requirements-review` gate ITSELF, re-running it mints a fresh
305
+ * iteration-1 review (the reviewer's `review()` replaces the prior one), which is
306
+ * exactly the "reset the iterations counter from this step" semantics.
307
+ *
308
+ * Like {@link retry} a fresh instance id is minted (the durable runner addresses one
309
+ * driver per execution id). Any still-live driver/container for the run being
310
+ * replaced is torn down first, so restarting a RUNNING run never orphans a container
311
+ * or a parked Workflows instance.
312
+ */
313
+ async restartFromStep(workspaceId, executionId, fromStepIndex,
314
+ /** The restarting user (their personal subscription is used for individual-usage
315
+ * models). Falls back to the original initiator when omitted. */
316
+ initiatedBy,
317
+ /** Mint the per-run personal-credential activation (see {@link start}). */
318
+ activate) {
319
+ await this.deps.requireWorkspace(workspaceId);
320
+ const previous = assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
321
+ const block = await this.deps.requireBlock(workspaceId, previous.blockId);
322
+ if (!Number.isInteger(fromStepIndex) ||
323
+ fromStepIndex < 0 ||
324
+ fromStepIndex >= previous.steps.length) {
325
+ throw new ValidationError(`Step ${fromStepIndex} is out of range for this run (it has ${previous.steps.length} step(s)).`);
326
+ }
327
+ // Run the SAME config/resource preconditions start()/retry() do, over the STORED steps this
328
+ // restart re-drives (frame type, tester infra, binary storage, agent backend, provider/preset
329
+ // satisfiability, budget). A restart re-dispatches provider-bearing steps just like a retry,
330
+ // so it must be gated identically — otherwise a run whose preset can't run every step (e.g. a
331
+ // subscription-only model an inline reviewer can't drive) strands mid-run instead of being
332
+ // refused up front. Before any teardown/side effects.
333
+ await this.deps.admission.assertRunnable(workspaceId, block, this.deps.admission.runnableShapeOf(previous.steps), initiatedBy ?? previous.initiatedBy);
334
+ // Tear down whatever was driving the run we're about to replace — its per-run
335
+ // container AND its durable driver — before minting the restart. A `done`/`failed`
336
+ // run is already terminal (a no-op teardown), but a still-`running` run would
337
+ // otherwise leak a container and a live Workflows/pg-boss driver.
338
+ await this.deps.runStateMachine.stopRunContainer(workspaceId, previous);
339
+ await this.deps.workRunner.cancelRun(workspaceId, executionId);
340
+ const { steps, currentStep } = planRestartFromStep(previous, fromStepIndex);
341
+ // Mint the activation before replacing the prior run, so a bad password aborts the
342
+ // restart without losing the source run.
343
+ const newId = this.deps.idGenerator.next('exec');
344
+ const replaceId = previous.id;
345
+ await activate?.(newId);
346
+ // Like retry(), this mints a FRESH run id. `claimLiveRunOrConflict` atomically supersedes
347
+ // the torn-down source run (`replaceId`, which here may still be LIVE — running/paused/
348
+ // blocked) and clears terminal rows in one transaction, so a concurrent start that already
349
+ // created a NEW live run for the block loses (409) instead of being silently clobbered.
350
+ const instance = buildResumedInstance({
351
+ previous,
352
+ id: newId,
353
+ plan: { steps, currentStep },
354
+ initiatedBy,
355
+ now: this.deps.clock.now(),
356
+ });
357
+ await claimLiveRunOrConflict(this.runStartDeps, workspaceId, instance, replaceId);
358
+ const done = steps.filter((s) => s.state === 'done').length;
359
+ await this.deps.blockRepository.update(workspaceId, previous.blockId, {
360
+ status: 'in_progress',
361
+ progress: steps.length > 0 ? done / steps.length : 0,
362
+ executionId: instance.id,
363
+ });
364
+ await handOffLiveRun(this.runStartDeps, workspaceId, instance, block);
365
+ return instance;
366
+ }
367
+ /**
368
+ * The bound callbacks the two run-start funnels (`runStart.ts`) need, so they depend on no
369
+ * concrete repository or service. Those funnels own the ORDER between a run's atomic claim and
370
+ * its hand-off and are documented there; every start path calls both, writing the block state
371
+ * that path owns in between.
372
+ */
373
+ get runStartDeps() {
374
+ return {
375
+ insertLive: (ws, instance, options) => this.deps.executionRepository.insertLive(ws, instance, options),
376
+ startRun: (ws, id) => this.deps.workRunner.startRun(ws, id),
377
+ emitInstance: (ws, instance) => this.deps.runStateMachine.emitInstance(ws, instance),
378
+ publishRunStarted: (ws, instance, block) => this.deps.runStateMachine.publishRunStarted(ws, instance, block),
379
+ };
380
+ }
381
+ /**
382
+ * Resume every run paused by the spend safeguard in this workspace. Flips them
383
+ * back to `running` and re-drives the durable runner. If the budget is still
384
+ * exhausted the spend gate will simply pause them again on their next step.
385
+ */
386
+ async resumePaused(workspaceId) {
387
+ await this.deps.requireWorkspace(workspaceId);
388
+ // Lean projection: only the paused runs' ids are needed to re-drive them — no `detail` decode.
389
+ const live = await this.deps.executionRepository.listLive(workspaceId);
390
+ const paused = live.filter((e) => e.status === 'paused');
391
+ for (const p of paused) {
392
+ // Optimistic-concurrency write: only flip + re-drive a run that is STILL paused at
393
+ // write time, so a resume racing the driver (or a concurrent resume) can't clobber a
394
+ // run another writer already advanced. A vanished/contended run is skipped (the next
395
+ // sweep retries) rather than failing the whole batch.
396
+ let flipped = false;
397
+ const resumed = await this.deps.runStateMachine
398
+ .mutateInstance(workspaceId, p.id, (inst) => {
399
+ flipped = inst.status === 'paused';
400
+ if (flipped)
401
+ inst.status = 'running';
402
+ })
403
+ .catch(() => null);
404
+ if (resumed && flipped) {
405
+ // `startRun` re-drives runners that re-create the run from scratch (pg-boss re-enqueues
406
+ // the same id). On Cloudflare the paused run's Workflows instance is still ALIVE parked
407
+ // on a `waitForEvent`, so `startRun`'s `create` no-ops there; `signalResume` delivers the
408
+ // event that wakes it immediately instead of waiting out the periodic budget re-check.
409
+ await this.deps.workRunner.startRun(workspaceId, resumed.id);
410
+ await this.deps.workRunner.signalResume?.(workspaceId, resumed.id);
411
+ await this.deps.runStateMachine.emitInstance(workspaceId, resumed);
412
+ }
413
+ }
414
+ // Clear the workspace-scoped `budget_paused` card now the pause is being lifted (F3). If the
415
+ // budget is still exhausted a resumed run re-pauses and re-raises it on its next step.
416
+ await this.deps.runStateMachine.clearBudgetPaused(workspaceId);
417
+ return this.deps.executionRepository.listByWorkspace(workspaceId);
418
+ }
419
+ /** Cancel the run on a block, returning it to `planned`. */
420
+ async cancel(workspaceId, blockId) {
421
+ await this.deps.requireWorkspace(workspaceId);
422
+ await this.deps.requireBlock(workspaceId, blockId);
423
+ // Tear down the durable run (if any) AND its per-run container before removing
424
+ // the record, so a cancel never leaves a container running until its watchdog.
425
+ const existing = await this.deps.executionRepository.getByBlock(workspaceId, blockId);
426
+ if (existing) {
427
+ await this.deps.runStateMachine.stopRunContainer(workspaceId, existing);
428
+ await this.deps.workRunner.cancelRun(workspaceId, existing.id);
429
+ }
430
+ await this.deps.executionRepository.deleteByBlock(workspaceId, blockId);
431
+ await this.deps.blockRepository.update(workspaceId, blockId, {
432
+ status: 'planned',
433
+ progress: 0,
434
+ executionId: null,
435
+ });
436
+ // The run record is gone and the block is back to planned; the client can't
437
+ // reconstruct that from a per-instance event, so signal a coarse refresh. Name the block
438
+ // so the refresh fans out to every board mounting its shared service.
439
+ await this.deps.events.boardChanged(workspaceId, 'cancel', blockId);
440
+ return this.deps.requireBlock(workspaceId, blockId);
441
+ }
442
+ /**
443
+ * Explicitly stop a *running* run by id (the unified `POST /agent-runs/:id/stop`
444
+ * surface): kill its per-run container, tear down the durable driver, then record
445
+ * a terminal `cancelled` failure so the board shows the run stopped (with retry)
446
+ * rather than spinning forever. Idempotent — a run already terminal is returned
447
+ * as-is. `opts.reason`/`opts.kind` let the orphan sweep reuse this with its own
448
+ * wording instead of the user-facing default.
449
+ */
450
+ async stopRun(workspaceId, executionId, opts = {}) {
451
+ await this.deps.requireWorkspace(workspaceId);
452
+ const instance = assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
453
+ if (instance.status === 'failed' || instance.status === 'done')
454
+ return instance;
455
+ await this.deps.runStateMachine.stopRunContainer(workspaceId, instance);
456
+ await this.deps.workRunner.cancelRun(workspaceId, executionId);
457
+ await this.deps.failRun(workspaceId, executionId, opts.reason ?? 'Stopped by the user.', opts.kind ?? 'cancelled');
458
+ return assertFound(await this.deps.executionRepository.get(workspaceId, executionId), 'Execution', executionId);
459
+ }
460
+ /**
461
+ * Tear down every run under a block subtree — kill each container, terminate each
462
+ * durable driver, and delete the run record — so deleting a service/module never
463
+ * orphans a container or a Workflows instance. Best-effort and silent: the board
464
+ * delete that follows emits the coarse refresh, so no per-run event is needed.
465
+ *
466
+ * Returns the workspace block list it loaded so the immediately-following `removeBlock`
467
+ * can reuse it instead of re-listing the whole board (this teardown deletes only run
468
+ * records, never blocks, so the list is still current) — see {@link PreloadedBlocks}.
469
+ */
470
+ async teardownForBlockTree(workspaceId, rootId) {
471
+ const blocks = await this.deps.blockRepository.listByWorkspace(workspaceId);
472
+ // Resolve every run in one query and index by block id, rather than a per-block
473
+ // getByBlock (N+1) over the whole subtree.
474
+ const runsByBlock = new Map((await this.deps.executionRepository.listByWorkspace(workspaceId)).map((run) => [
475
+ run.blockId,
476
+ run,
477
+ ]));
478
+ for (const blockId of descendantIds(blocks, rootId)) {
479
+ const run = runsByBlock.get(blockId);
480
+ if (!run)
481
+ continue;
482
+ await this.deps.runStateMachine.stopRunContainer(workspaceId, run);
483
+ await this.deps.workRunner.cancelRun(workspaceId, run.id);
484
+ await this.deps.executionRepository.deleteByBlock(workspaceId, blockId);
485
+ }
486
+ return { workspaceId, blocks };
487
+ }
488
+ }
489
+ //# sourceMappingURL=RunLifecycleController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunLifecycleController.js","sourceRoot":"","sources":["../../../src/modules/execution/RunLifecycleController.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import type { Block, ModelProvider, ModelProviderResolver, ModelRef } from '@cat-factory/kernel';
2
2
  import { type ResolveBlockRunContext } from '../../inlineScope.js';
3
+ import { type InlineBlockModelDeps } from '../../inlineBlockModel.js';
3
4
  import type { TestReport } from '@cat-factory/contracts';
4
5
  import { type TesterQualityOutcome } from './testerQuality.logic.js';
5
6
  /**
@@ -26,12 +27,15 @@ export interface TesterQualityReviewDeps {
26
27
  modelProvider?: ModelProvider;
27
28
  /** Default model ref when the block pins none — the agents' routing default. */
28
29
  modelRef?: ModelRef;
29
- /** Resolve a block's selected model id to a ref (the deployment-aware resolver). */
30
- resolveBlockModel?: (modelId: string | undefined) => ModelRef | undefined;
30
+ /** Resolve a block's selected model id to a ref, under the preset's route order. */
31
+ resolveBlockModel?: InlineBlockModelDeps['resolveBlockModel'];
31
32
  /** Keep an ambient-eligible harness ref inline (local mode) instead of degrading it. */
32
33
  runsInline?: (ref: ModelRef) => boolean;
33
- /** Resolve the workspace's per-agent-kind default model id (block pins none). */
34
- resolveWorkspaceModelDefault?: (workspaceId: string, agentKind: string, modelPresetId?: string) => Promise<string | undefined>;
34
+ /**
35
+ * The workspace's per-kind default MODEL and the ROUTE order the preset in force states, from
36
+ * ONE read. Absent ⇒ block pin plus the routing default, on the deployment's default order.
37
+ */
38
+ resolvePresetRouting?: InlineBlockModelDeps['resolvePresetRouting'];
35
39
  /** Resolve the block's run/execution + initiator, folded into the inline model scope. */
36
40
  resolveRunContext?: ResolveBlockRunContext;
37
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TesterQualityReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEhG,OAAO,EAAE,KAAK,sBAAsB,EAAoB,MAAM,sBAAsB,CAAA;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAIxD,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,0BAA0B,CAAA;AAEjC;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CACN,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC3E;AAED,6FAA6F;AAC7F,MAAM,WAAW,uBAAuB;IACtC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,kFAAkF;IAClF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAA;IACzE,wFAAwF;IACxF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAA;IACvC,iFAAiF;IACjF,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,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,sBAAsB,CAAA;CAC3C;AAED;;;;;;GAMG;AACH,qBAAa,0BAA2B,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,uBAAuB,EAAI;YAEhD,QAAQ;IAiBhB,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAyCzE;CACF"}
1
+ {"version":3,"file":"TesterQualityReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEhG,OAAO,EAAE,KAAK,sBAAsB,EAAoB,MAAM,sBAAsB,CAAA;AACpF,OAAO,EAAE,KAAK,oBAAoB,EAA8B,MAAM,2BAA2B,CAAA;AACjG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAIxD,OAAO,EACL,KAAK,oBAAoB,EAG1B,MAAM,0BAA0B,CAAA;AAEjC;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CACN,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC3E;AAED,6FAA6F;AAC7F,MAAM,WAAW,uBAAuB;IACtC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,kFAAkF;IAClF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,oBAAoB,CAAC,mBAAmB,CAAC,CAAA;IAC7D,wFAAwF;IACxF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAA;IACvC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;IACnE,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,sBAAsB,CAAA;CAC3C;AAED;;;;;;GAMG;AACH,qBAAa,0BAA2B,YAAW,qBAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,uBAAuB,EAAI;IAE9D,OAAO,CAAC,QAAQ;IAIV,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;QAAE,OAAO,EAAE,oBAAoB,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAyCzE;CACF"}
@@ -1,5 +1,6 @@
1
- import { inlineModelRef, resolveScopedModelProvider } from '@cat-factory/kernel';
1
+ import { resolveScopedModelProvider } from '@cat-factory/kernel';
2
2
  import { scopeForBlockRun } from '../../inlineScope.js';
3
+ import { resolveInlineBlockModelRef } from '../../inlineBlockModel.js';
3
4
  import { TESTER_QC_AGENT_KIND } from '@cat-factory/contracts';
4
5
  import { generateText } from 'ai';
5
6
  import { catFactoryObservability, TESTER_QC_SYSTEM_PROMPT } from '@cat-factory/agents';
@@ -16,18 +17,8 @@ export class TesterQualityReviewService {
16
17
  constructor(deps) {
17
18
  this.deps = deps;
18
19
  }
19
- async modelFor(workspaceId, block) {
20
- const fallback = this.deps.modelRef;
21
- const runsInline = this.deps.runsInline;
22
- const resolve = (ref) => inlineModelRef(ref, fallback ?? ref, runsInline ? { runsInline } : {});
23
- const fromBlock = this.deps.resolveBlockModel?.(block.modelId);
24
- if (fromBlock)
25
- return resolve(fromBlock);
26
- const defaultId = await this.deps.resolveWorkspaceModelDefault?.(workspaceId, TESTER_QC_AGENT_KIND, block.modelPresetId);
27
- const fromDefault = this.deps.resolveBlockModel?.(defaultId);
28
- if (fromDefault)
29
- return resolve(fromDefault);
30
- return fallback;
20
+ modelFor(workspaceId, block) {
21
+ return resolveInlineBlockModelRef(this.deps, workspaceId, TESTER_QC_AGENT_KIND, block);
31
22
  }
32
23
  async evaluate(workspaceId, block, report) {
33
24
  const scope = await scopeForBlockRun(workspaceId, block, this.deps.resolveRunContext);
@@ -1 +1 @@
1
- {"version":3,"file":"TesterQualityReviewService.js","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TesterQualityReviewService.js","sourceRoot":"","sources":["../../../src/modules/execution/TesterQualityReviewService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAA+B,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACpF,OAAO,EAA6B,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AAEjG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AACtF,OAAO,EAEL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,0BAA0B,CAAA;AAyCjC;;;;;;GAMG;AACH,MAAM,OAAO,0BAA0B;IACR,IAAI;IAAjC,YAA6B,IAA6B;oBAA7B,IAAI;IAA4B,CAAC;IAEtD,QAAQ,CAAC,WAAmB,EAAE,KAAY;QAChD,OAAO,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,KAAK,CAAC,CAAA;IACxF,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,WAAmB,EACnB,KAAY,EACZ,MAAkB;QAElB,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACrF,MAAM,aAAa,GAAG,MAAM,0BAA0B,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACxE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACnD,0FAA0F;QAC1F,IAAI,CAAC,aAAa,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QACvC,IAAI,KAA2C,CAAA;QAC/C,IAAI,CAAC;YACH,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;YACtF,sFAAsF;YACtF,wFAAwF;YACxF,sFAAsF;YACtF,6DAA6D;YAC7D,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,IAAY,CAAA;QAChB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;gBAChC,KAAK;gBACL,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE,wBAAwB,CAAC;oBAC/B,SAAS,EAAE,KAAK,CAAC,KAAK;oBACtB,eAAe,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;oBACxC,MAAM;iBACP,CAAC;gBACF,WAAW,EAAE,GAAG;gBAChB,eAAe,EAAE,IAAI;gBACrB,eAAe,EAAE,uBAAuB,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;aAC3F,CAAC,CAAA;YACF,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,sFAAsF;YACtF,6EAA6E;YAC7E,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO;YACL,OAAO,EAAE,0BAA0B,CAAC,IAAI,CAAC;YACzC,KAAK,EAAE,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK,EAAE;SACtC,CAAA;IACH,CAAC;CACF"}