@cat-factory/orchestration 0.129.2 → 0.129.4
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/RunDispatcher.d.ts +7 -2
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +56 -432
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/dispatcher-registries.d.ts +85 -0
- package/dist/modules/execution/dispatcher-registries.d.ts.map +1 -0
- package/dist/modules/execution/dispatcher-registries.js +451 -0
- package/dist/modules/execution/dispatcher-registries.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts +7 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts.map +1 -1
- package/dist/modules/requirements/RequirementReviewService.js +48 -39
- package/dist/modules/requirements/RequirementReviewService.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import { INITIATIVE_ANALYST_AGENT_KIND, INITIATIVE_COMMITTER_AGENT_KIND, INITIATIVE_PLANNER_AGENT_KIND, } from '@cat-factory/kernel';
|
|
2
|
+
import { FORK_PROPOSER_KIND, PR_REVIEWER_KIND, hasTrait, isCompanionKind, isContainerBackedCompanion, INTERVIEW_GATE_TRAIT, TASK_ESTIMATOR_AGENT_KIND, } from '@cat-factory/agents';
|
|
3
|
+
import { DEPLOYER_AGENT_KIND, isDeployStep } from '@cat-factory/integrations';
|
|
4
|
+
import { BUG_INTAKE_AGENT_KIND } from '../pipelines/pipelineShape.js';
|
|
5
|
+
import { coerceTaskEstimate, summarizeEstimate } from '../estimation/estimate.logic.js';
|
|
6
|
+
import { renderInvestigationDigest } from './bugInvestigation.logic.js';
|
|
7
|
+
import { renderReproDigest } from './reproTest.logic.js';
|
|
8
|
+
import { ARCHITECTURE_BRAINSTORM_AGENT_KIND, BLUEPRINTS_AGENT_KIND, BUG_INVESTIGATOR_AGENT_KIND, CLARITY_REVIEW_AGENT_KIND, HUMAN_TEST_AGENT_KIND, isTesterKind, MERGER_AGENT_KIND, REPRO_TEST_AGENT_KIND, REQUIREMENTS_BRAINSTORM_AGENT_KIND, REQUIREMENTS_REVIEW_AGENT_KIND, SPEC_WRITER_AGENT_KIND, TRACKER_AGENT_KIND, VISUAL_CONFIRM_AGENT_KIND, } from './ci.logic.js';
|
|
9
|
+
import { PrReviewController, PR_REVIEW_STEP_KIND } from './PrReviewController.js';
|
|
10
|
+
import { forkPhasePending, resolveForkTriState } from './forkDecision.logic.js';
|
|
11
|
+
import { isRalphKind } from './ralph.logic.js';
|
|
12
|
+
import { FALLTHROUGH_STEP_HANDLER_ORDER, } from './step-handler-registry.js';
|
|
13
|
+
/**
|
|
14
|
+
* The inline review/brainstorm gate kinds, all driven through the {@link ReviewGateController}
|
|
15
|
+
* by the dispatcher's `review-gate` StepHandler. Kept in sync with the handler's `switch`.
|
|
16
|
+
*/
|
|
17
|
+
const REVIEW_GATE_AGENT_KINDS = new Set([
|
|
18
|
+
REQUIREMENTS_REVIEW_AGENT_KIND,
|
|
19
|
+
CLARITY_REVIEW_AGENT_KIND,
|
|
20
|
+
REQUIREMENTS_BRAINSTORM_AGENT_KIND,
|
|
21
|
+
ARCHITECTURE_BRAINSTORM_AGENT_KIND,
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* Build the order-sorted per-step-kind handler list (built-ins constructed inline, closing over
|
|
25
|
+
* the injected {@link DispatcherRegistryDeps}). Engine-internal: there is no public
|
|
26
|
+
* `registerStepHandler` seam. Phase 0 registers only the generic fallthrough; later phases
|
|
27
|
+
* prepend more-specific handlers with lower `order`.
|
|
28
|
+
*/
|
|
29
|
+
export function buildStepHandlerRegistry(d) {
|
|
30
|
+
const handlers = [
|
|
31
|
+
// A `deployer` step provisions an ephemeral environment deterministically via the
|
|
32
|
+
// provider — no LLM, no token usage — when the integration is wired. Unwired, its
|
|
33
|
+
// `canHandle` is false so the step falls through to the generic agent path.
|
|
34
|
+
{
|
|
35
|
+
kind: DEPLOYER_AGENT_KIND,
|
|
36
|
+
order: 100,
|
|
37
|
+
canHandle: ({ step }) => !!d.environmentProvisioning && isDeployStep(step.agentKind),
|
|
38
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => d.deployer.runDeployerStep(workspaceId, instance, step, block, isFinalStep),
|
|
39
|
+
},
|
|
40
|
+
// A `tracker` step files a GitHub issue / Jira ticket from the preceding `analysis`
|
|
41
|
+
// output (the tech-debt pipeline) — no LLM of its own. It is a pass-through when no
|
|
42
|
+
// tracker provider is wired or none is configured for the workspace (handled inside
|
|
43
|
+
// {@link runTracker}, which still records a result), so it always claims the step.
|
|
44
|
+
{
|
|
45
|
+
kind: TRACKER_AGENT_KIND,
|
|
46
|
+
order: 110,
|
|
47
|
+
canHandle: ({ step }) => step.agentKind === TRACKER_AGENT_KIND,
|
|
48
|
+
handle: async ({ workspaceId, instance, step, block, isFinalStep }) => {
|
|
49
|
+
const result = await d.runTracker(workspaceId, instance, block);
|
|
50
|
+
return d.recordStepResult(workspaceId, instance, step, isFinalStep, result);
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
// A `bug-intake` step (the recurring bug-triage pipeline) pulls ONE matching open issue from
|
|
54
|
+
// the schedule's tracker board, claims it, and seeds the reused block from it — no LLM of its
|
|
55
|
+
// own, the inbound dual of `tracker`. On no match (or no task source wired) it completes the
|
|
56
|
+
// run successfully, skipping every remaining step. Handled entirely inside
|
|
57
|
+
// {@link runBugIntake}, so it always claims the step.
|
|
58
|
+
{
|
|
59
|
+
kind: BUG_INTAKE_AGENT_KIND,
|
|
60
|
+
order: 111,
|
|
61
|
+
canHandle: ({ step }) => step.agentKind === BUG_INTAKE_AGENT_KIND,
|
|
62
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => d.runBugIntake(workspaceId, instance, step, block, isFinalStep),
|
|
63
|
+
},
|
|
64
|
+
// The interactive-INTERVIEWER gates (`initiative-interviewer`, `doc-interviewer`, …): an
|
|
65
|
+
// inline LLM gate that PARKS the run on a decision-wait while the human answers the
|
|
66
|
+
// interviewer's questions through a dedicated window, then synthesizes a brief and advances
|
|
67
|
+
// (see {@link InterviewGateController}). Routed by the `interview-gate` TRAIT — the same
|
|
68
|
+
// marker the re-park + approval guards key off — and dispatched to the controller registered
|
|
69
|
+
// for the step's `agentKind`, so a new interviewer just carries the trait + wires its
|
|
70
|
+
// controller (no new branch here). Pass-through when the interviewer isn't wired (no model /
|
|
71
|
+
// no store) so pipelines + conformance run unchanged; a wired-but-unmatched trait kind is a
|
|
72
|
+
// pipeline authoring error, but we still advance rather than wedge the run.
|
|
73
|
+
{
|
|
74
|
+
kind: 'interview-gate',
|
|
75
|
+
order: 113,
|
|
76
|
+
canHandle: ({ step }) => hasTrait(step.agentKind, INTERVIEW_GATE_TRAIT, d.agentKindRegistry),
|
|
77
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => {
|
|
78
|
+
const controller = d.interviewControllers.get(step.agentKind);
|
|
79
|
+
return controller
|
|
80
|
+
? controller.evaluate(workspaceId, instance, step, block, isFinalStep)
|
|
81
|
+
: d.recordStepResult(workspaceId, instance, step, isFinalStep, { output: '' });
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
// The `initiative-committer` step persists an APPROVED initiative plan: it runs
|
|
85
|
+
// strictly after the planner's human gate, flips the entity to `executing`, and
|
|
86
|
+
// mirrors the tracker into the repo (`docs/initiatives/<slug>/`) when GitHub is
|
|
87
|
+
// wired — no LLM of its own (the `tracker`-style deterministic one-shot).
|
|
88
|
+
{
|
|
89
|
+
kind: INITIATIVE_COMMITTER_AGENT_KIND,
|
|
90
|
+
order: 115,
|
|
91
|
+
canHandle: ({ step }) => step.agentKind === INITIATIVE_COMMITTER_AGENT_KIND,
|
|
92
|
+
handle: async ({ workspaceId, instance, step, block, isFinalStep }) => {
|
|
93
|
+
const outcome = await d.runInitiativeCommitter(workspaceId, block);
|
|
94
|
+
if (outcome.kind === 'failed') {
|
|
95
|
+
return { kind: 'job_failed', error: outcome.error, failureKind: 'agent' };
|
|
96
|
+
}
|
|
97
|
+
return d.recordStepResult(workspaceId, instance, step, isFinalStep, outcome.result);
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
// The `requirements-review` / `clarity-review` / `requirements-brainstorm` /
|
|
101
|
+
// `architecture-brainstorm` steps are inline reviewers that park for their dedicated
|
|
102
|
+
// window and drive the iterative answer → incorporate → re-review loop — NOT
|
|
103
|
+
// container/prose agents. All four run through the {@link ReviewGateController},
|
|
104
|
+
// parameterised by their {@link ReviewKind} (the per-case `switch` binds each kind's
|
|
105
|
+
// review type so `evaluate`'s generic infers). Pass-through when the service isn't wired.
|
|
106
|
+
{
|
|
107
|
+
kind: 'review-gate',
|
|
108
|
+
order: 120,
|
|
109
|
+
canHandle: ({ step }) => REVIEW_GATE_AGENT_KINDS.has(step.agentKind),
|
|
110
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => {
|
|
111
|
+
switch (step.agentKind) {
|
|
112
|
+
case REQUIREMENTS_REVIEW_AGENT_KIND:
|
|
113
|
+
return d.reviewGate.evaluate(d.requirementsKind, workspaceId, instance, step, block, isFinalStep);
|
|
114
|
+
case CLARITY_REVIEW_AGENT_KIND:
|
|
115
|
+
return d.reviewGate.evaluate(d.clarityKind, workspaceId, instance, step, block, isFinalStep);
|
|
116
|
+
case REQUIREMENTS_BRAINSTORM_AGENT_KIND:
|
|
117
|
+
return d.reviewGate.evaluate(d.requirementsBrainstormKind, workspaceId, instance, step, block, isFinalStep);
|
|
118
|
+
case ARCHITECTURE_BRAINSTORM_AGENT_KIND:
|
|
119
|
+
return d.reviewGate.evaluate(d.architectureBrainstormKind, workspaceId, instance, step, block, isFinalStep);
|
|
120
|
+
// `canHandle` admits only the kinds in REVIEW_GATE_AGENT_KINDS, so every member
|
|
121
|
+
// must have an explicit case above. Throw loudly if the two ever drift (a new
|
|
122
|
+
// review kind added to the Set without a case here) rather than silently routing
|
|
123
|
+
// it to the wrong reviewer.
|
|
124
|
+
default:
|
|
125
|
+
throw new Error(`Unhandled review-gate agentKind "${step.agentKind}"`);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
// A `human-test` gate spins up an ephemeral environment and PARKS for a human to
|
|
130
|
+
// validate the change in a live URL — NOT a container/prose agent and NOT a
|
|
131
|
+
// programmatic polling gate (the human is the verdict). Degrades to a manual (no-env)
|
|
132
|
+
// mode when no ephemeral-environment provider is wired. See {@link HumanTestController}.
|
|
133
|
+
{
|
|
134
|
+
kind: HUMAN_TEST_AGENT_KIND,
|
|
135
|
+
order: 130,
|
|
136
|
+
canHandle: ({ step }) => step.agentKind === HUMAN_TEST_AGENT_KIND,
|
|
137
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => d.humanTestController.evaluate(workspaceId, instance, step, block, isFinalStep),
|
|
138
|
+
},
|
|
139
|
+
// A `visual-confirmation` gate gathers the UI tester's screenshots + uploaded reference
|
|
140
|
+
// designs and PARKS for a human to review actual-vs-reference, then on demand dispatches
|
|
141
|
+
// the Tester's `fixer`. Passes through when no binary-artifact store is wired.
|
|
142
|
+
// See {@link VisualConfirmationController}.
|
|
143
|
+
{
|
|
144
|
+
kind: VISUAL_CONFIRM_AGENT_KIND,
|
|
145
|
+
order: 140,
|
|
146
|
+
canHandle: ({ step }) => step.agentKind === VISUAL_CONFIRM_AGENT_KIND,
|
|
147
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => d.visualConfirmationController.evaluate(workspaceId, instance, step, block, isFinalStep),
|
|
148
|
+
},
|
|
149
|
+
// A polling gate step (`ci` / `conflicts` / `post-release-health` / `human-review`) runs
|
|
150
|
+
// a programmatic precheck and only escalates to a helper container agent on a negative
|
|
151
|
+
// verdict — no LLM of its own. Pass-through when the gate's provider is not wired. One
|
|
152
|
+
// generic machine drives every gate; see {@link evaluateGate}. `canHandle` is the gate
|
|
153
|
+
// registry lookup, so this claims exactly the registered gate kinds.
|
|
154
|
+
{
|
|
155
|
+
kind: 'polling-gate',
|
|
156
|
+
order: 150,
|
|
157
|
+
canHandle: ({ step }) => d.gateFor(step.agentKind) !== undefined,
|
|
158
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep }) => d.evaluateGate(workspaceId, instance, step, block, isFinalStep, d.gateFor(step.agentKind)),
|
|
159
|
+
},
|
|
160
|
+
// An INLINE companion (architect-companion / spec-companion) grades the nearest
|
|
161
|
+
// preceding producer right here and loops it back for automatic rework below the
|
|
162
|
+
// threshold before any human gate. CONTAINER-backed companions (reviewer / doc-reviewer)
|
|
163
|
+
// do NOT match — they fall through to the generic async container dispatch and have their
|
|
164
|
+
// verdict resolved by the completion interceptor instead. See {@link CompanionController}.
|
|
165
|
+
{
|
|
166
|
+
kind: 'inline-companion',
|
|
167
|
+
order: 160,
|
|
168
|
+
canHandle: ({ step }) => isCompanionKind(step.agentKind) && !isContainerBackedCompanion(step.agentKind),
|
|
169
|
+
handle: ({ workspaceId, instance, step, block, isFinalStep, options }) => d.companionController.evaluate(workspaceId, instance, step, block, isFinalStep, options),
|
|
170
|
+
},
|
|
171
|
+
// The optional implementation-fork decision phase on a Coder step (Phase A): when the
|
|
172
|
+
// per-task tri-state + the risk-policy gate call for it, dispatch the read-only
|
|
173
|
+
// `fork-proposer` explore job as a helper off THIS coder step. Claims the step only
|
|
174
|
+
// while the phase is pending (tri-state not `off`, not yet resolved); once resolved
|
|
175
|
+
// (`chosen` / `single_path` / `skipped`) it falls through so the Coder dispatches
|
|
176
|
+
// normally (Phase B). A parked `awaiting_choice` step is short-circuited by the
|
|
177
|
+
// run-lifecycle re-entry guard before this handler runs. See {@link handleForkDecisionPhase}.
|
|
178
|
+
{
|
|
179
|
+
kind: 'fork-decision',
|
|
180
|
+
order: 170,
|
|
181
|
+
canHandle: ({ step, block }) => forkPhasePending(step, resolveForkTriState(block.agentConfig)),
|
|
182
|
+
handle: (ctx) => d.handleForkDecisionPhase(ctx),
|
|
183
|
+
},
|
|
184
|
+
// The PR deep-review RESOLUTION phase (PR 3): after the human resolved a parked review with
|
|
185
|
+
// `fix` / `post`, `PrReviewController.resolve` re-armed this `pr-reviewer` step and woke the
|
|
186
|
+
// driver. Claim it by the re-armed status so it re-dispatches as the Fixer (`fixing`) or
|
|
187
|
+
// posts the selected findings as inline PR comments (`posting`) — never the generic
|
|
188
|
+
// pr-reviewer clone the fallthrough would run. A `reviewing`/`awaiting_selection`/resolved
|
|
189
|
+
// step falls through (this handler doesn't claim it). See {@link handlePrReviewResolution}.
|
|
190
|
+
{
|
|
191
|
+
kind: 'pr-review-resolution',
|
|
192
|
+
order: 175,
|
|
193
|
+
canHandle: ({ step }) => step.agentKind === PR_REVIEW_STEP_KIND &&
|
|
194
|
+
(step.prReview?.status === 'fixing' || step.prReview?.status === 'posting'),
|
|
195
|
+
handle: (ctx) => d.handlePrReviewResolution(ctx),
|
|
196
|
+
},
|
|
197
|
+
// The generic container/inline-agent step — claims every step no more-specific handler
|
|
198
|
+
// did. Highest order so it always runs last. See {@link handleAgentStep}.
|
|
199
|
+
{
|
|
200
|
+
kind: 'agent',
|
|
201
|
+
order: FALLTHROUGH_STEP_HANDLER_ORDER,
|
|
202
|
+
canHandle: () => true,
|
|
203
|
+
handle: (ctx) => d.handleAgentStep(ctx),
|
|
204
|
+
},
|
|
205
|
+
];
|
|
206
|
+
return handlers.sort((a, b) => a.order - b.order);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Build the order-sorted completion-path interceptors (companion / tester verdict
|
|
210
|
+
* short-circuits), mirroring {@link buildStepHandlerRegistry}.
|
|
211
|
+
*/
|
|
212
|
+
export function buildStepCompletionInterceptors(d) {
|
|
213
|
+
const interceptors = [
|
|
214
|
+
// A container-backed companion (reviewer / doc-reviewer) just finished reviewing the
|
|
215
|
+
// real repository on the producer's PR branch and returned its verdict as
|
|
216
|
+
// `result.custom`. Hand it to the companion loop, which parses the verdict and applies
|
|
217
|
+
// the SAME threshold / rework / human-gate handling an inline companion gets. Routed
|
|
218
|
+
// here (not the normal step completion) so the verdict drives the loop instead of being
|
|
219
|
+
// recorded as plain output. Falls through (returns null) when the block can't be loaded.
|
|
220
|
+
{
|
|
221
|
+
kind: 'companion-verdict',
|
|
222
|
+
order: 100,
|
|
223
|
+
canIntercept: ({ step }) => isCompanionKind(step.agentKind) && isContainerBackedCompanion(step.agentKind),
|
|
224
|
+
intercept: async ({ workspaceId, instance, step, isFinalStep, result }) => {
|
|
225
|
+
const companionBlock = await d.blockRepository.get(workspaceId, instance.blockId);
|
|
226
|
+
if (!companionBlock)
|
|
227
|
+
return null;
|
|
228
|
+
return d.companionController.resolveContainerVerdict(workspaceId, instance, step, companionBlock, isFinalStep, result);
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
// The `fork-proposer` explore job (Phase A of the fork decision) just finished on a
|
|
232
|
+
// coder step. Its structured `result.custom` is the proposal; record it onto the step's
|
|
233
|
+
// `forkDecision` and either park for the human to choose (≥2 usable forks) or auto-advance
|
|
234
|
+
// a single path — never the normal output/PR/follow-up/approval completion (none applies
|
|
235
|
+
// to the proposer). Keyed on the coder step carrying `forkDecision.status === 'proposing'`.
|
|
236
|
+
{
|
|
237
|
+
kind: 'fork-proposal',
|
|
238
|
+
order: 105,
|
|
239
|
+
canIntercept: ({ step }) => step.agentKind === 'coder' && step.forkDecision?.status === 'proposing',
|
|
240
|
+
intercept: ({ workspaceId, instance, step, result }) => {
|
|
241
|
+
const proposal = d.agentKindRegistry
|
|
242
|
+
.structuredOutput(FORK_PROPOSER_KIND)
|
|
243
|
+
?.safeParse(result.custom);
|
|
244
|
+
return d.forkDecisionController.recordProposal(workspaceId, instance, step, proposal, step.model);
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
// The read-only `pr-reviewer` deep-review job just finished on a review task's step. Its
|
|
248
|
+
// structured `result.custom` is the sliced, prioritized findings; record them onto the
|
|
249
|
+
// step's `prReview` and PARK for the human to select which findings matter (≥1 finding),
|
|
250
|
+
// rather than the normal completion. A clean PR (no findings) returns null and falls
|
|
251
|
+
// through to the normal finish. Keyed on the `pr-reviewer` step kind.
|
|
252
|
+
{
|
|
253
|
+
kind: 'pr-review',
|
|
254
|
+
order: 106,
|
|
255
|
+
canIntercept: ({ step }) => step.agentKind === PR_REVIEW_STEP_KIND,
|
|
256
|
+
intercept: async ({ workspaceId, instance, step, result }) => {
|
|
257
|
+
const output = d.agentKindRegistry
|
|
258
|
+
.structuredOutput(PR_REVIEWER_KIND)
|
|
259
|
+
?.safeParse(result.custom);
|
|
260
|
+
const block = await d.blockRepository.get(workspaceId, instance.blockId);
|
|
261
|
+
return d.prReviewController.recordFindings(workspaceId, instance, step, output, result.model ?? step.model, block);
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
// A `tester` step returned a structured report. On a withheld greenlight we do NOT
|
|
265
|
+
// finish the step: loop the `fixer` (within the attempt budget) and re-test, mirroring
|
|
266
|
+
// the CI gate. A greenlight (or no provider) returns null and falls through to the
|
|
267
|
+
// normal finish/advance below. Records the report on the step either way.
|
|
268
|
+
{
|
|
269
|
+
kind: 'tester-verdict',
|
|
270
|
+
order: 110,
|
|
271
|
+
canIntercept: ({ step, result }) => isTesterKind(step.agentKind) && result.testReport !== undefined,
|
|
272
|
+
intercept: ({ workspaceId, instance, step, result }) => d.testerController.resolveTesterResult(workspaceId, instance, step, result),
|
|
273
|
+
},
|
|
274
|
+
// A `ralph` iteration finished and the harness attached its programmatic validation
|
|
275
|
+
// verdict. Hand it to the ralph loop: a passing command finishes + advances (returns
|
|
276
|
+
// null → normal completion), a failing one re-dispatches a fresh iteration within the
|
|
277
|
+
// budget or gives up for a human — never the normal single-shot completion. Keyed on the
|
|
278
|
+
// `ralph` kind carrying a `ralphVerdict`; a ralph run that errored before validation (no
|
|
279
|
+
// verdict) falls through to the normal failure path.
|
|
280
|
+
{
|
|
281
|
+
kind: 'ralph-verdict',
|
|
282
|
+
order: 115,
|
|
283
|
+
canIntercept: ({ step, result }) => isRalphKind(step.agentKind) && result.ralphVerdict !== undefined,
|
|
284
|
+
intercept: ({ workspaceId, instance, step, result }) => d.ralphController.resolveRalphResult(workspaceId, instance, step, result),
|
|
285
|
+
},
|
|
286
|
+
];
|
|
287
|
+
return interceptors.sort((a, b) => a.order - b.order);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Build the post-completion / terminal step-resolver registry, keyed by `agentKind`. The
|
|
291
|
+
* built-in `merger` resolver (which owns terminal status) plus the post-completion result
|
|
292
|
+
* reshapers are constructed inline; deployment-registered resolvers are merged last (last
|
|
293
|
+
* registration wins).
|
|
294
|
+
*/
|
|
295
|
+
export function buildStepResolverRegistry(d) {
|
|
296
|
+
const resolvers = [
|
|
297
|
+
// The `merger` agent OWNS the merge decision, but the merge itself is mechanical
|
|
298
|
+
// and uses backend-held GitHub credentials the sandboxed agent never sees — so the
|
|
299
|
+
// engine performs it deterministically from the agent's assessment here, the moment
|
|
300
|
+
// the merger step finishes (NOT only when it is the pipeline's last step, which is
|
|
301
|
+
// why a trailing `post-release-health` step no longer disables auto-merge).
|
|
302
|
+
{
|
|
303
|
+
kind: MERGER_AGENT_KIND,
|
|
304
|
+
applies: (result) => result.mergeAssessment !== undefined,
|
|
305
|
+
resolve: async ({ workspaceId, instance, step, result }) => {
|
|
306
|
+
// The real merge runs the engine GitHub client under the run initiator's
|
|
307
|
+
// ambient context, so a per-user PAT (when set) authors the merge.
|
|
308
|
+
const decision = await d.runInitiatorScope(instance.initiatedBy, () => d.mergeResolver.resolveMergerStep(workspaceId, instance, result.mergeAssessment));
|
|
309
|
+
// Record the structured verdict on the step so the SPA's dedicated merger result
|
|
310
|
+
// view renders the assessment + explains the auto-merge / awaiting-review decision,
|
|
311
|
+
// instead of showing the agent's raw JSON.
|
|
312
|
+
if (decision) {
|
|
313
|
+
step.custom = decision;
|
|
314
|
+
// Drop the raw JSON only when we captured a structured assessment (the view
|
|
315
|
+
// renders it from `step.custom`). When the merger produced NO parseable
|
|
316
|
+
// assessment, keep the raw reply so an operator can still diagnose what it sent.
|
|
317
|
+
if (decision.assessment)
|
|
318
|
+
step.output = '';
|
|
319
|
+
}
|
|
320
|
+
return { ownsTerminalStatus: true };
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
// POST-COMPLETION resolvers — run at the early slot (after output is recorded, before
|
|
324
|
+
// the follow-up/approval gates), reshaping the agent's structured result into domain
|
|
325
|
+
// state. Lifted verbatim from the old inline `recordStepResult` branches.
|
|
326
|
+
//
|
|
327
|
+
// A Blueprinter step produced a fresh service decomposition. Validate it with the
|
|
328
|
+
// authoritative schema (a bad payload must never touch the board), then reconcile it
|
|
329
|
+
// in place onto the run's service frame.
|
|
330
|
+
{
|
|
331
|
+
kind: BLUEPRINTS_AGENT_KIND,
|
|
332
|
+
phase: 'post-completion',
|
|
333
|
+
resolve: async ({ workspaceId, instance, result }) => {
|
|
334
|
+
if (result.blueprintService !== undefined) {
|
|
335
|
+
await d.ingestBlueprint(workspaceId, instance.blockId, result.blueprintService);
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
// An initiative-analyst step produced a prose codebase analysis. Fold it onto the
|
|
340
|
+
// block's `initiatives` entity (`analysisSummary`) so the planner's prompt is grounded
|
|
341
|
+
// in it. Best-effort: an empty analysis or an unwired store simply leaves the summary
|
|
342
|
+
// unchanged (the planner still runs); never fail the run on a missing analysis.
|
|
343
|
+
{
|
|
344
|
+
kind: INITIATIVE_ANALYST_AGENT_KIND,
|
|
345
|
+
phase: 'post-completion',
|
|
346
|
+
resolve: async ({ workspaceId, instance, result }) => {
|
|
347
|
+
const summary = result.output?.trim();
|
|
348
|
+
if (!d.initiativeService || !summary)
|
|
349
|
+
return;
|
|
350
|
+
await d.initiativeService.recordAnalysis(workspaceId, instance.blockId, summary);
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
// An initiative-planner step produced a plan draft. Ingest it into the block's
|
|
354
|
+
// `initiatives` entity (strict-parse at the trust boundary; replay-idempotent —
|
|
355
|
+
// the same draft re-applies to identical content). The run then parks at the
|
|
356
|
+
// planner's human gate; the committer step later mirrors the APPROVED plan into
|
|
357
|
+
// the repo. A malformed draft fails the step loudly — completing the run without
|
|
358
|
+
// an ingested plan would strand the initiative in `planning` with a green run.
|
|
359
|
+
{
|
|
360
|
+
kind: INITIATIVE_PLANNER_AGENT_KIND,
|
|
361
|
+
phase: 'post-completion',
|
|
362
|
+
resolve: async ({ workspaceId, instance, result }) => {
|
|
363
|
+
if (!d.initiativeService)
|
|
364
|
+
return;
|
|
365
|
+
if (result.initiativePlan === undefined) {
|
|
366
|
+
throw new Error('The initiative planner returned no usable plan (malformed or empty JSON)');
|
|
367
|
+
}
|
|
368
|
+
const ingested = await d.initiativeService.ingestPlan(workspaceId, instance.blockId, result.initiativePlan);
|
|
369
|
+
if (!ingested) {
|
|
370
|
+
throw new Error('No initiative entity found for this block — cannot ingest the plan');
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
// A spec-writer step produced the service's unified specification (`spec.json`) and
|
|
375
|
+
// committed it to the implementation branch — strict-validate it then nudge clients —
|
|
376
|
+
// and reports its BUSINESS-vs-TECHNICAL determination. "No business specs" (a purely
|
|
377
|
+
// technical task) is a valid outcome the spec-companion's convergence later combines
|
|
378
|
+
// with its `technicalCorroborated` verdict; recorded even when false so a re-run
|
|
379
|
+
// reflects the latest.
|
|
380
|
+
{
|
|
381
|
+
kind: SPEC_WRITER_AGENT_KIND,
|
|
382
|
+
phase: 'post-completion',
|
|
383
|
+
resolve: async ({ workspaceId, step, result }) => {
|
|
384
|
+
if (result.spec !== undefined)
|
|
385
|
+
await d.ingestSpec(workspaceId, result.spec);
|
|
386
|
+
step.noBusinessSpecs = result.noBusinessSpecs === true;
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
// A `task-estimator` step emits a JSON triage (complexity/risk/impact). Parse it
|
|
390
|
+
// tolerantly, persist it on the block (used to gate consensus steps + surfaced in the
|
|
391
|
+
// UI), and replace the raw JSON output with a readable summary. An unparseable estimate
|
|
392
|
+
// leaves the block untouched and keeps the raw output (no run failure). Works the same
|
|
393
|
+
// whether the single-actor estimator or the consensus ranked-scoring variant produced
|
|
394
|
+
// the JSON. Running at the post-completion slot keeps the summary in `step.output`
|
|
395
|
+
// before the approval gate reads it as the proposal.
|
|
396
|
+
// A `bug-investigator` step returns its STRUCTURED triage as `result.custom` (kept on
|
|
397
|
+
// `step.custom` for the generic-structured view + the clarity gate's structured read).
|
|
398
|
+
// Render a prose digest into `step.output` at the post-completion slot so downstream
|
|
399
|
+
// steps (estimator / repro-test / coder) read the investigation via `priorOutputs`
|
|
400
|
+
// (which carries only `step.output`), and the clarity gate's investigation-prose context
|
|
401
|
+
// sees it too. An unparseable result leaves the agent's raw reply on `step.output`.
|
|
402
|
+
{
|
|
403
|
+
kind: BUG_INVESTIGATOR_AGENT_KIND,
|
|
404
|
+
phase: 'post-completion',
|
|
405
|
+
applies: (result) => result.custom !== undefined,
|
|
406
|
+
resolve: async ({ result }) => {
|
|
407
|
+
const digest = renderInvestigationDigest(result.custom);
|
|
408
|
+
if (digest)
|
|
409
|
+
return { output: digest };
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
// A `repro-test` step returns its STRUCTURED outcome as `result.custom` (kept on
|
|
413
|
+
// `step.custom` for the generic-structured view). Render a short prose digest into
|
|
414
|
+
// `step.output` at the post-completion slot so the coder reads the reproduction result
|
|
415
|
+
// (reproduced / conceded + why) via `priorOutputs` (which carries only `step.output`).
|
|
416
|
+
// Conceding never fails the run — the container tolerates a no-op (`noChangesTolerated`),
|
|
417
|
+
// so this only reshapes the output. An unparseable result leaves the raw reply on
|
|
418
|
+
// `step.output`.
|
|
419
|
+
{
|
|
420
|
+
kind: REPRO_TEST_AGENT_KIND,
|
|
421
|
+
phase: 'post-completion',
|
|
422
|
+
applies: (result) => result.custom !== undefined,
|
|
423
|
+
resolve: async ({ result }) => {
|
|
424
|
+
const digest = renderReproDigest(result.custom);
|
|
425
|
+
if (digest)
|
|
426
|
+
return { output: digest };
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
kind: TASK_ESTIMATOR_AGENT_KIND,
|
|
431
|
+
phase: 'post-completion',
|
|
432
|
+
resolve: async ({ workspaceId, instance, step, result }) => {
|
|
433
|
+
const estimate = coerceTaskEstimate(step.output ?? '', result.model ?? step.model ?? null, d.clock.now());
|
|
434
|
+
if (estimate) {
|
|
435
|
+
await d.blockRepository.update(workspaceId, instance.blockId, { estimate });
|
|
436
|
+
return { output: summarizeEstimate(estimate) };
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
];
|
|
441
|
+
const map = new Map(resolvers.map((r) => [r.kind, r]));
|
|
442
|
+
// Merge deployment-registered resolvers, mirroring the gate registry below. A
|
|
443
|
+
// registered resolver of the same kind replaces the built-in (last registration wins).
|
|
444
|
+
// The registry is the app-owned instance injected through `CoreDependencies`, not a
|
|
445
|
+
// module global.
|
|
446
|
+
const ctx = { runInitiatorScope: d.runInitiatorScope };
|
|
447
|
+
for (const { kind, factory } of d.stepResolverRegistry.factories())
|
|
448
|
+
map.set(kind, factory(ctx));
|
|
449
|
+
return map;
|
|
450
|
+
}
|
|
451
|
+
//# sourceMappingURL=dispatcher-registries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher-registries.js","sourceRoot":"","sources":["../../../src/modules/execution/dispatcher-registries.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,6BAA6B,EAC7B,+BAA+B,EAC/B,6BAA6B,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,eAAe,EACf,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAE7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACvF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,kCAAkC,EAClC,8BAA8B,EAC9B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,eAAe,CAAA;AAOtB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AACjF,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAI/E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,EACL,8BAA8B,GAI/B,MAAM,4BAA4B,CAAA;AAInC;;;GAGG;AACH,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC;IAC3D,8BAA8B;IAC9B,yBAAyB;IACzB,kCAAkC;IAClC,kCAAkC;CACnC,CAAC,CAAA;AAyEF;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,CAAyB;IAChE,MAAM,QAAQ,GAAkB;QAC9B,kFAAkF;QAClF,kFAAkF;QAClF,4EAA4E;QAC5E;YACE,IAAI,EAAE,mBAAmB;YACzB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB,IAAI,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;YACpF,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAC9D,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC;SAC9E;QACD,oFAAoF;QACpF,oFAAoF;QACpF,oFAAoF;QACpF,mFAAmF;QACnF;YACE,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,kBAAkB;YAC9D,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;gBACpE,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;gBAC/D,OAAO,CAAC,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;YAC7E,CAAC;SACF;QACD,6FAA6F;QAC7F,8FAA8F;QAC9F,6FAA6F;QAC7F,2EAA2E;QAC3E,sDAAsD;QACtD;YACE,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,qBAAqB;YACjE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAC9D,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC;SAClE;QACD,yFAAyF;QACzF,oFAAoF;QACpF,4FAA4F;QAC5F,yFAAyF;QACzF,6FAA6F;QAC7F,sFAAsF;QACtF,6FAA6F;QAC7F,4FAA4F;QAC5F,4EAA4E;QAC5E;YACE,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,EAAE,CAAC,CAAC,iBAAiB,CAAC;YAC5F,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;gBAC9D,MAAM,UAAU,GAAG,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;gBAC7D,OAAO,UAAU;oBACf,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC;oBACtE,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;YAClF,CAAC;SACF;QACD,gFAAgF;QAChF,gFAAgF;QAChF,gFAAgF;QAChF,0EAA0E;QAC1E;YACE,IAAI,EAAE,+BAA+B;YACrC,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,+BAA+B;YAC3E,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;gBACpE,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,sBAAsB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;gBAClE,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC9B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAA;gBAC3E,CAAC;gBACD,OAAO,CAAC,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;YACrF,CAAC;SACF;QACD,6EAA6E;QAC7E,qFAAqF;QACrF,6EAA6E;QAC7E,iFAAiF;QACjF,qFAAqF;QACrF,0FAA0F;QAC1F;YACE,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACpE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;gBAC9D,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;oBACvB,KAAK,8BAA8B;wBACjC,OAAO,CAAC,CAAC,UAAU,CAAC,QAAQ,CAC1B,CAAC,CAAC,gBAAgB,EAClB,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,WAAW,CACZ,CAAA;oBACH,KAAK,yBAAyB;wBAC5B,OAAO,CAAC,CAAC,UAAU,CAAC,QAAQ,CAC1B,CAAC,CAAC,WAAW,EACb,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,WAAW,CACZ,CAAA;oBACH,KAAK,kCAAkC;wBACrC,OAAO,CAAC,CAAC,UAAU,CAAC,QAAQ,CAC1B,CAAC,CAAC,0BAA0B,EAC5B,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,WAAW,CACZ,CAAA;oBACH,KAAK,kCAAkC;wBACrC,OAAO,CAAC,CAAC,UAAU,CAAC,QAAQ,CAC1B,CAAC,CAAC,0BAA0B,EAC5B,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,WAAW,CACZ,CAAA;oBACH,gFAAgF;oBAChF,8EAA8E;oBAC9E,iFAAiF;oBACjF,4BAA4B;oBAC5B;wBACE,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;gBAC1E,CAAC;YACH,CAAC;SACF;QACD,iFAAiF;QACjF,4EAA4E;QAC5E,sFAAsF;QACtF,yFAAyF;QACzF;YACE,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,qBAAqB;YACjE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAC9D,CAAC,CAAC,mBAAmB,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC;SAClF;QACD,wFAAwF;QACxF,yFAAyF;QACzF,+EAA+E;QAC/E,4CAA4C;QAC5C;YACE,IAAI,EAAE,yBAAyB;YAC/B,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,yBAAyB;YACrE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAC9D,CAAC,CAAC,4BAA4B,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC;SAC3F;QACD,yFAAyF;QACzF,uFAAuF;QACvF,uFAAuF;QACvF,uFAAuF;QACvF,qEAAqE;QACrE;YACE,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,SAAS;YAChE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,CAC9D,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAE,CAAC;SAC9F;QACD,gFAAgF;QAChF,iFAAiF;QACjF,yFAAyF;QACzF,0FAA0F;QAC1F,2FAA2F;QAC3F;YACE,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACtB,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC;YAChF,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,CACvE,CAAC,CAAC,mBAAmB,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC;SAC3F;QACD,sFAAsF;QACtF,gFAAgF;QAChF,oFAAoF;QACpF,oFAAoF;QACpF,kFAAkF;QAClF,gFAAgF;QAChF,8FAA8F;QAC9F;YACE,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAC7B,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAChE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,uBAAuB,CAAC,GAAG,CAAC;SAChD;QACD,4FAA4F;QAC5F,6FAA6F;QAC7F,yFAAyF;QACzF,oFAAoF;QACpF,2FAA2F;QAC3F,4FAA4F;QAC5F;YACE,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACtB,IAAI,CAAC,SAAS,KAAK,mBAAmB;gBACtC,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC;YAC7E,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC;SACjD;QACD,uFAAuF;QACvF,0EAA0E;QAC1E;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,8BAA8B;YACrC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI;YACrB,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC;SACxC;KACF,CAAA;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAC7C,CAAyB;IAEzB,MAAM,YAAY,GAAgC;QAChD,qFAAqF;QACrF,0EAA0E;QAC1E,uFAAuF;QACvF,qFAAqF;QACrF,wFAAwF;QACxF,yFAAyF;QACzF;YACE,IAAI,EAAE,mBAAmB;YACzB,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACzB,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC;YAC/E,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE;gBACxE,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;gBACjF,IAAI,CAAC,cAAc;oBAAE,OAAO,IAAI,CAAA;gBAChC,OAAO,CAAC,CAAC,mBAAmB,CAAC,uBAAuB,CAClD,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,WAAW,EACX,MAAM,CACP,CAAA;YACH,CAAC;SACF;QACD,oFAAoF;QACpF,wFAAwF;QACxF,2FAA2F;QAC3F,yFAAyF;QACzF,4FAA4F;QAC5F;YACE,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACzB,IAAI,CAAC,SAAS,KAAK,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,MAAM,KAAK,WAAW;YACzE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;gBACrD,MAAM,QAAQ,GAAG,CAAC,CAAC,iBAAiB;qBACjC,gBAAgB,CAAC,kBAAkB,CAAC;oBACrC,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAA6B,CAAA;gBACxD,OAAO,CAAC,CAAC,sBAAsB,CAAC,cAAc,CAC5C,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,IAAI,CAAC,KAAK,CACX,CAAA;YACH,CAAC;SACF;QACD,yFAAyF;QACzF,uFAAuF;QACvF,yFAAyF;QACzF,qFAAqF;QACrF,sEAAsE;QACtE;YACE,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,mBAAmB;YAClE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC3D,MAAM,MAAM,GAAG,CAAC,CAAC,iBAAiB;qBAC/B,gBAAgB,CAAC,gBAAgB,CAAC;oBACnC,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAoC,CAAA;gBAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;gBACxE,OAAO,CAAC,CAAC,kBAAkB,CAAC,cAAc,CACxC,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAC1B,KAAK,CACN,CAAA;YACH,CAAC;SACF;QACD,mFAAmF;QACnF,uFAAuF;QACvF,mFAAmF;QACnF,0EAA0E;QAC1E;YACE,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACjC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS;YACjE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACrD,CAAC,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC;SAC9E;QACD,oFAAoF;QACpF,qFAAqF;QACrF,sFAAsF;QACtF,yFAAyF;QACzF,yFAAyF;QACzF,qDAAqD;QACrD;YACE,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACjC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS;YAClE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACrD,CAAC,CAAC,eAAe,CAAC,kBAAkB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC;SAC5E;KACF,CAAA;IACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,CAAyB;IAEzB,MAAM,SAAS,GAA6B;QAC1C,iFAAiF;QACjF,mFAAmF;QACnF,oFAAoF;QACpF,mFAAmF;QACnF,4EAA4E;QAC5E;YACE,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,KAAK,SAAS;YACzD,OAAO,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;gBACzD,yEAAyE;gBACzE,mEAAmE;gBACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE,CACpE,CAAC,CAAC,aAAa,CAAC,iBAAiB,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,eAAe,CAAC,CACjF,CAAA;gBACD,iFAAiF;gBACjF,oFAAoF;gBACpF,2CAA2C;gBAC3C,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAA;oBACtB,4EAA4E;oBAC5E,wEAAwE;oBACxE,iFAAiF;oBACjF,IAAI,QAAQ,CAAC,UAAU;wBAAE,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;gBAC3C,CAAC;gBACD,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAA;YACrC,CAAC;SACF;QACD,sFAAsF;QACtF,qFAAqF;QACrF,0EAA0E;QAC1E,EAAE;QACF,kFAAkF;QAClF,qFAAqF;QACrF,yCAAyC;QACzC;YACE,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;gBACnD,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;oBAC1C,MAAM,CAAC,CAAC,eAAe,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAA;gBACjF,CAAC;YACH,CAAC;SACF;QACD,kFAAkF;QAClF,uFAAuF;QACvF,sFAAsF;QACtF,gFAAgF;QAChF;YACE,IAAI,EAAE,6BAA6B;YACnC,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;gBACnD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAA;gBACrC,IAAI,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,OAAO;oBAAE,OAAM;gBAC5C,MAAM,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAClF,CAAC;SACF;QACD,+EAA+E;QAC/E,gFAAgF;QAChF,6EAA6E;QAC7E,gFAAgF;QAChF,iFAAiF;QACjF,+EAA+E;QAC/E;YACE,IAAI,EAAE,6BAA6B;YACnC,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;gBACnD,IAAI,CAAC,CAAC,CAAC,iBAAiB;oBAAE,OAAM;gBAChC,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;oBACxC,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAA;gBACH,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,iBAAiB,CAAC,UAAU,CACnD,WAAW,EACX,QAAQ,CAAC,OAAO,EAChB,MAAM,CAAC,cAAc,CACtB,CAAA;gBACD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;gBACvF,CAAC;YACH,CAAC;SACF;QACD,oFAAoF;QACpF,sFAAsF;QACtF,qFAAqF;QACrF,qFAAqF;QACrF,iFAAiF;QACjF,uBAAuB;QACvB;YACE,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;oBAAE,MAAM,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;gBAC3E,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,KAAK,IAAI,CAAA;YACxD,CAAC;SACF;QACD,iFAAiF;QACjF,sFAAsF;QACtF,wFAAwF;QACxF,uFAAuF;QACvF,sFAAsF;QACtF,mFAAmF;QACnF,qDAAqD;QACrD,sFAAsF;QACtF,uFAAuF;QACvF,qFAAqF;QACrF,mFAAmF;QACnF,yFAAyF;QACzF,oFAAoF;QACpF;YACE,IAAI,EAAE,2BAA2B;YACjC,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;YAChD,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC5B,MAAM,MAAM,GAAG,yBAAyB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;gBACvD,IAAI,MAAM;oBAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;YACvC,CAAC;SACF;QACD,iFAAiF;QACjF,mFAAmF;QACnF,uFAAuF;QACvF,uFAAuF;QACvF,0FAA0F;QAC1F,kFAAkF;QAClF,iBAAiB;QACjB;YACE,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS;YAChD,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;gBAC5B,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;gBAC/C,IAAI,MAAM;oBAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;YACvC,CAAC;SACF;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,KAAK,EAAE,iBAAiB;YACxB,OAAO,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;gBACzD,MAAM,QAAQ,GAAG,kBAAkB,CACjC,IAAI,CAAC,MAAM,IAAI,EAAE,EACjB,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,EAClC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CACd,CAAA;gBACD,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;oBAC3E,OAAO,EAAE,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAA;gBAChD,CAAC;YACH,CAAC;SACF;KACF,CAAA;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACtD,8EAA8E;IAC9E,uFAAuF;IACvF,oFAAoF;IACpF,iBAAiB;IACjB,MAAM,GAAG,GAAoB,EAAE,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,EAAE,CAAA;IACvE,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE;QAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/F,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -123,6 +123,13 @@ export declare class RequirementReviewService extends IterativeReviewService<Req
|
|
|
123
123
|
}): Promise<{
|
|
124
124
|
produced: number;
|
|
125
125
|
}>;
|
|
126
|
+
/**
|
|
127
|
+
* Apply one Writer suggestion to its live placeholder against a fresh read, mutating `review` in
|
|
128
|
+
* place. Extracted from the chunk-application loop so that loop stays within the max-depth ceiling
|
|
129
|
+
* (the auto-accept/answered branch nested three levels below the loop). Returns whether the target
|
|
130
|
+
* produced a recommendation and whether it became a `ready` card the human must review.
|
|
131
|
+
*/
|
|
132
|
+
private applyRecommendationToTarget;
|
|
126
133
|
/**
|
|
127
134
|
* Drop every `pending` placeholder on a review and reopen its source finding (the same cleanup
|
|
128
135
|
* the per-finding failure path does, applied to the whole batch). Used when the Writer can't run
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequirementReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/requirements/RequirementReviewService.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"RequirementReviewService.d.ts","sourceRoot":"","sources":["../../../src/modules/requirements/RequirementReviewService.ts"],"names":[],"mappings":"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"}
|
|
@@ -237,46 +237,12 @@ export class RequirementReviewService extends IterativeReviewService {
|
|
|
237
237
|
// Re-read fresh before applying: the human may have acted during the Writer call.
|
|
238
238
|
const review = assertFound(await this.repository.get(workspaceId, reviewId), this.entityName, reviewId);
|
|
239
239
|
const now = this.deps.clock.now();
|
|
240
|
-
for (const
|
|
241
|
-
const
|
|
242
|
-
if (
|
|
243
|
-
continue;
|
|
244
|
-
const suggestion = finding ? suggestions.get(finding.id) : undefined;
|
|
245
|
-
if (suggestion) {
|
|
246
|
-
const standard = suggestion.fromStandard
|
|
247
|
-
? fragmentById.get(suggestion.fromStandard)
|
|
248
|
-
: undefined;
|
|
249
|
-
rec.recommendedText = suggestion.recommendation;
|
|
250
|
-
rec.groundedInFragment = standard ? { id: standard.id, title: standard.title } : null;
|
|
251
|
-
rec.updatedAt = now;
|
|
252
|
-
if (rec.auto) {
|
|
253
|
-
// Auto-recommendation: accept it immediately as the finding's default answer, so
|
|
254
|
-
// the human sees it pre-filled (editable / dismissable) rather than a card to act
|
|
255
|
-
// on. Mirrors `acceptRecommendation`, matching the finding against the fresh read.
|
|
256
|
-
rec.status = 'accepted';
|
|
257
|
-
const item = findSourceItem(review.items, ph.sourceFinding);
|
|
258
|
-
if (item) {
|
|
259
|
-
item.reply = suggestion.recommendation;
|
|
260
|
-
item.status = 'answered';
|
|
261
|
-
item.updatedAt = now;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
rec.status = 'ready';
|
|
266
|
-
readyForReview += 1;
|
|
267
|
-
}
|
|
240
|
+
for (const target of targets) {
|
|
241
|
+
const outcome = this.applyRecommendationToTarget(target, review, suggestions, fragmentById, now);
|
|
242
|
+
if (outcome.produced)
|
|
268
243
|
produced += 1;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
// The Writer failed for (or no longer matches) this finding: drop the dead placeholder
|
|
272
|
-
// and reopen its finding so the human can answer it by hand.
|
|
273
|
-
review.recommendations = review.recommendations.filter((r) => r.id !== ph.id);
|
|
274
|
-
const item = findSourceItem(review.items, ph.sourceFinding);
|
|
275
|
-
if (item && item.status === 'recommend_requested') {
|
|
276
|
-
item.status = 'open';
|
|
277
|
-
item.updatedAt = now;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
244
|
+
if (outcome.readyForReview)
|
|
245
|
+
readyForReview += 1;
|
|
280
246
|
}
|
|
281
247
|
review.updatedAt = now;
|
|
282
248
|
await this.repository.upsert(workspaceId, review);
|
|
@@ -287,6 +253,49 @@ export class RequirementReviewService extends IterativeReviewService {
|
|
|
287
253
|
await this.notifyRecommendationsReady(workspaceId, block, readyForReview);
|
|
288
254
|
return { produced };
|
|
289
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Apply one Writer suggestion to its live placeholder against a fresh read, mutating `review` in
|
|
258
|
+
* place. Extracted from the chunk-application loop so that loop stays within the max-depth ceiling
|
|
259
|
+
* (the auto-accept/answered branch nested three levels below the loop). Returns whether the target
|
|
260
|
+
* produced a recommendation and whether it became a `ready` card the human must review.
|
|
261
|
+
*/
|
|
262
|
+
applyRecommendationToTarget(target, review, suggestions, fragmentById, now) {
|
|
263
|
+
const { ph, finding } = target;
|
|
264
|
+
const rec = review.recommendations.find((r) => r.id === ph.id);
|
|
265
|
+
if (!rec || rec.status !== 'pending')
|
|
266
|
+
return { produced: false, readyForReview: false };
|
|
267
|
+
const suggestion = finding ? suggestions.get(finding.id) : undefined;
|
|
268
|
+
if (!suggestion) {
|
|
269
|
+
// The Writer failed for (or no longer matches) this finding: drop the dead placeholder
|
|
270
|
+
// and reopen its finding so the human can answer it by hand.
|
|
271
|
+
review.recommendations = review.recommendations.filter((r) => r.id !== ph.id);
|
|
272
|
+
const item = findSourceItem(review.items, ph.sourceFinding);
|
|
273
|
+
if (item && item.status === 'recommend_requested') {
|
|
274
|
+
item.status = 'open';
|
|
275
|
+
item.updatedAt = now;
|
|
276
|
+
}
|
|
277
|
+
return { produced: false, readyForReview: false };
|
|
278
|
+
}
|
|
279
|
+
const standard = suggestion.fromStandard ? fragmentById.get(suggestion.fromStandard) : undefined;
|
|
280
|
+
rec.recommendedText = suggestion.recommendation;
|
|
281
|
+
rec.groundedInFragment = standard ? { id: standard.id, title: standard.title } : null;
|
|
282
|
+
rec.updatedAt = now;
|
|
283
|
+
if (!rec.auto) {
|
|
284
|
+
rec.status = 'ready';
|
|
285
|
+
return { produced: true, readyForReview: true };
|
|
286
|
+
}
|
|
287
|
+
// Auto-recommendation: accept it immediately as the finding's default answer, so the human
|
|
288
|
+
// sees it pre-filled (editable / dismissable) rather than a card to act on. Mirrors
|
|
289
|
+
// `acceptRecommendation`, matching the finding against the fresh read.
|
|
290
|
+
rec.status = 'accepted';
|
|
291
|
+
const item = findSourceItem(review.items, ph.sourceFinding);
|
|
292
|
+
if (item) {
|
|
293
|
+
item.reply = suggestion.recommendation;
|
|
294
|
+
item.status = 'answered';
|
|
295
|
+
item.updatedAt = now;
|
|
296
|
+
}
|
|
297
|
+
return { produced: true, readyForReview: false };
|
|
298
|
+
}
|
|
290
299
|
/**
|
|
291
300
|
* Drop every `pending` placeholder on a review and reopen its source finding (the same cleanup
|
|
292
301
|
* the per-finding failure path does, applied to the whole batch). Used when the Writer can't run
|