@cat-factory/server 0.215.0 → 0.217.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/publicApi/PublicDecisionController.d.ts.map +1 -1
- package/dist/modules/publicApi/PublicDecisionController.js +41 -322
- package/dist/modules/publicApi/PublicDecisionController.js.map +1 -1
- package/dist/modules/publicApi/decisions/approvalRoutes.d.ts +4 -0
- package/dist/modules/publicApi/decisions/approvalRoutes.d.ts.map +1 -0
- package/dist/modules/publicApi/decisions/approvalRoutes.js +96 -0
- package/dist/modules/publicApi/decisions/approvalRoutes.js.map +1 -0
- package/dist/modules/publicApi/decisions/dialogueRoutes.d.ts +5 -0
- package/dist/modules/publicApi/decisions/dialogueRoutes.d.ts.map +1 -0
- package/dist/modules/publicApi/decisions/dialogueRoutes.js +161 -0
- package/dist/modules/publicApi/decisions/dialogueRoutes.js.map +1 -0
- package/dist/modules/publicApi/decisions/gateRoutes.d.ts +5 -0
- package/dist/modules/publicApi/decisions/gateRoutes.d.ts.map +1 -0
- package/dist/modules/publicApi/decisions/gateRoutes.js +120 -0
- package/dist/modules/publicApi/decisions/gateRoutes.js.map +1 -0
- package/dist/modules/publicApi/decisions/projection.d.ts +62 -0
- package/dist/modules/publicApi/decisions/projection.d.ts.map +1 -0
- package/dist/modules/publicApi/decisions/projection.js +489 -0
- package/dist/modules/publicApi/decisions/projection.js.map +1 -0
- package/dist/modules/publicApi/decisions/requirementsRoutes.d.ts +11 -0
- package/dist/modules/publicApi/decisions/requirementsRoutes.d.ts.map +1 -0
- package/dist/modules/publicApi/decisions/requirementsRoutes.js +91 -0
- package/dist/modules/publicApi/decisions/requirementsRoutes.js.map +1 -0
- package/dist/modules/publicApi/decisions/scope.d.ts +107 -0
- package/dist/modules/publicApi/decisions/scope.d.ts.map +1 -0
- package/dist/modules/publicApi/decisions/scope.js +142 -0
- package/dist/modules/publicApi/decisions/scope.js.map +1 -0
- package/dist/modules/publicApi/publicApiAdmission.d.ts +9 -5
- package/dist/modules/publicApi/publicApiAdmission.d.ts.map +1 -1
- package/dist/modules/publicApi/publicApiAdmission.js +13 -5
- package/dist/modules/publicApi/publicApiAdmission.js.map +1 -1
- package/dist/persistence/rpc-allowlist.d.ts.map +1 -1
- package/dist/persistence/rpc-allowlist.js +5 -0
- package/dist/persistence/rpc-allowlist.js.map +1 -1
- package/dist/runtime/spendAlerts.d.ts +24 -0
- package/dist/runtime/spendAlerts.d.ts.map +1 -0
- package/dist/runtime/spendAlerts.js +173 -0
- package/dist/runtime/spendAlerts.js.map +1 -0
- package/package.json +9 -9
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { ARCHITECTURE_BRAINSTORM_AGENT_KIND, CLARITY_REVIEW_AGENT_KIND, REQUIREMENTS_BRAINSTORM_AGENT_KIND, } from '@cat-factory/agents';
|
|
2
|
+
import { dedicatedParkSurface } from '@cat-factory/orchestration';
|
|
3
|
+
// The run → `PublicDecisionList` projection: what a parked run is currently asking a human, as
|
|
4
|
+
// external resources. One `to*Decision` + one `isLive*` predicate per park kind, and the assembly
|
|
5
|
+
// that decides which reads a given run even needs.
|
|
6
|
+
//
|
|
7
|
+
// Two rules hold across every kind here:
|
|
8
|
+
//
|
|
9
|
+
// 1. **A settled park is not a decision.** A predicate lists the park's own waiting state plus
|
|
10
|
+
// the in-flight states either side of it, so a poller sees progress rather than an empty list
|
|
11
|
+
// that reads as "nothing is happening" — but never a terminal state, which would put a
|
|
12
|
+
// question in front of a caller with nothing left to answer.
|
|
13
|
+
// 2. **Project as data, never as prose.** Every one of these carries model-authored text
|
|
14
|
+
// (a proposal, a finding, an agent's question). It crosses the wire as its own field so a
|
|
15
|
+
// consumer can render it in its own surface; nothing here composes it into markdown.
|
|
16
|
+
/** Project a live requirements review onto the external decision resource. */
|
|
17
|
+
export function toRequirementsDecision(review) {
|
|
18
|
+
return {
|
|
19
|
+
kind: 'requirements-review',
|
|
20
|
+
reviewId: review.id,
|
|
21
|
+
taskId: review.blockId,
|
|
22
|
+
status: review.status,
|
|
23
|
+
iteration: review.iteration ?? 1,
|
|
24
|
+
maxIterations: review.maxIterations ?? 1,
|
|
25
|
+
findings: review.items.map(toFinding),
|
|
26
|
+
incorporatedRequirements: review.incorporatedRequirements,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Project a live clarity (bug-triage) review — the requirements twin over its own document. */
|
|
30
|
+
export function toClarityDecision(review) {
|
|
31
|
+
return {
|
|
32
|
+
kind: 'clarity-review',
|
|
33
|
+
reviewId: review.id,
|
|
34
|
+
taskId: review.blockId,
|
|
35
|
+
status: review.status,
|
|
36
|
+
iteration: review.iteration ?? 1,
|
|
37
|
+
maxIterations: review.maxIterations ?? 1,
|
|
38
|
+
findings: review.items.map(toFinding),
|
|
39
|
+
clarifiedReport: review.clarifiedReport,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** Project a live brainstorm session for one stage. */
|
|
43
|
+
export function toBrainstormDecision(session) {
|
|
44
|
+
return {
|
|
45
|
+
kind: 'brainstorm',
|
|
46
|
+
sessionId: session.id,
|
|
47
|
+
stage: session.stage,
|
|
48
|
+
taskId: session.blockId,
|
|
49
|
+
status: session.status,
|
|
50
|
+
iteration: session.iteration ?? 1,
|
|
51
|
+
maxIterations: session.maxIterations ?? 1,
|
|
52
|
+
options: session.items.map(toFinding),
|
|
53
|
+
convergedDirection: session.convergedDirection,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The shared item projection for all three iterative-review kinds. They persist the SAME item
|
|
58
|
+
* shape (`requirementReviewItemSchema`) on purpose, so one projection is the honest expression of
|
|
59
|
+
* that rather than three copies waiting to drift. The internal `autoAnswerable` classification and
|
|
60
|
+
* the Requirement-Writer recommendation machinery stay off it: both drive in-app affordances.
|
|
61
|
+
*/
|
|
62
|
+
function toFinding(item) {
|
|
63
|
+
return {
|
|
64
|
+
itemId: item.id,
|
|
65
|
+
category: item.category,
|
|
66
|
+
severity: item.severity,
|
|
67
|
+
title: item.title,
|
|
68
|
+
detail: item.detail,
|
|
69
|
+
status: item.status,
|
|
70
|
+
reply: item.reply,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Project a run's fork-decision step state onto the external decision resource. */
|
|
74
|
+
export function toForkDecision(state) {
|
|
75
|
+
return {
|
|
76
|
+
kind: 'fork',
|
|
77
|
+
status: state.status,
|
|
78
|
+
seamSummary: state.seamSummary ?? null,
|
|
79
|
+
forks: state.forks ?? [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Project a run's JUDGE step state onto the external decision resource. The rubric body is
|
|
84
|
+
* deliberately omitted (see `publicJudgeDecisionSchema`) — a caller answers the findings.
|
|
85
|
+
*/
|
|
86
|
+
export function toJudgeDecision(stepKind, state) {
|
|
87
|
+
return {
|
|
88
|
+
kind: 'judge',
|
|
89
|
+
stepKind,
|
|
90
|
+
status: state.status,
|
|
91
|
+
rubricId: state.rubricId ?? null,
|
|
92
|
+
rubricName: state.rubricName ?? null,
|
|
93
|
+
threshold: state.threshold ?? null,
|
|
94
|
+
verdict: state.verdict ?? null,
|
|
95
|
+
bounces: state.bounces ?? 0,
|
|
96
|
+
maxBounces: state.maxBounces ?? 0,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Project a step's APPROVAL GATE. `exceeded` is read off the step's companion state rather than
|
|
101
|
+
* the approval itself, because that is where the engine records it — and it is what tells a caller
|
|
102
|
+
* to answer with `resolve-exceeded` instead of `approve`. Reading it as a plain boolean (rather
|
|
103
|
+
* than only when a companion exists) means an ordinary pipeline gate reports `false`, which is the
|
|
104
|
+
* true statement, not an omission.
|
|
105
|
+
*/
|
|
106
|
+
export function toApprovalDecision(step, stepIndex, approval) {
|
|
107
|
+
return {
|
|
108
|
+
kind: 'approval-gate',
|
|
109
|
+
approvalId: approval.id,
|
|
110
|
+
stepKind: step.agentKind,
|
|
111
|
+
stepIndex,
|
|
112
|
+
status: approval.status,
|
|
113
|
+
proposal: approval.proposal,
|
|
114
|
+
feedback: approval.feedback ?? null,
|
|
115
|
+
exceeded: step.companion?.exceeded === true,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Project a decision an agent raised mid-work. */
|
|
119
|
+
export function toAgentDecision(step, decision) {
|
|
120
|
+
return {
|
|
121
|
+
kind: 'agent-decision',
|
|
122
|
+
decisionId: decision.id,
|
|
123
|
+
stepKind: step.agentKind,
|
|
124
|
+
question: decision.question,
|
|
125
|
+
options: decision.options,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Project a parked PR deep review's curation state.
|
|
130
|
+
*
|
|
131
|
+
* The slices and findings go through their own projections rather than crossing the wire as the
|
|
132
|
+
* engine holds them: the internal shapes are mid-evolution (per-slice resume reports) while the
|
|
133
|
+
* published ones must not move, and the `optional | null` internals collapse to always-present
|
|
134
|
+
* nullables so four generated clients have one shape to check.
|
|
135
|
+
*/
|
|
136
|
+
export function toPrReviewDecision(state) {
|
|
137
|
+
return {
|
|
138
|
+
kind: 'pr-review',
|
|
139
|
+
status: state.status,
|
|
140
|
+
summary: state.summary ?? null,
|
|
141
|
+
prUrl: state.prUrl ?? null,
|
|
142
|
+
slices: (state.slices ?? []).map(toPrReviewSlice),
|
|
143
|
+
findings: (state.findings ?? []).map(toPrReviewFinding),
|
|
144
|
+
selectedFindingIds: state.selectedFindingIds ?? [],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** One reviewed slice, externally. */
|
|
148
|
+
function toPrReviewSlice(slice) {
|
|
149
|
+
return {
|
|
150
|
+
sliceId: slice.id,
|
|
151
|
+
title: slice.title,
|
|
152
|
+
rationale: slice.rationale,
|
|
153
|
+
paths: slice.paths,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* One review finding, externally. The challenge is projected rather than passed through so a
|
|
158
|
+
* caller sees the VERDICT and its justification without the engine's job bookkeeping.
|
|
159
|
+
*/
|
|
160
|
+
function toPrReviewFinding(finding) {
|
|
161
|
+
const challenge = finding.challenge;
|
|
162
|
+
return {
|
|
163
|
+
findingId: finding.id,
|
|
164
|
+
sliceId: finding.sliceId ?? null,
|
|
165
|
+
path: finding.path,
|
|
166
|
+
line: finding.line ?? null,
|
|
167
|
+
side: finding.side ?? null,
|
|
168
|
+
severity: finding.severity,
|
|
169
|
+
category: finding.category,
|
|
170
|
+
title: finding.title,
|
|
171
|
+
detail: finding.detail,
|
|
172
|
+
suggestedFix: finding.suggestedFix ?? null,
|
|
173
|
+
challenge: challenge
|
|
174
|
+
? {
|
|
175
|
+
status: challenge.status,
|
|
176
|
+
question: challenge.question ?? null,
|
|
177
|
+
justification: challenge.justification ?? null,
|
|
178
|
+
}
|
|
179
|
+
: null,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Project a parked human-test gate: what to test against, and how much fix budget is left. */
|
|
183
|
+
export function toHumanTestDecision(state) {
|
|
184
|
+
const env = state.environment;
|
|
185
|
+
return {
|
|
186
|
+
kind: 'human-test',
|
|
187
|
+
phase: state.phase,
|
|
188
|
+
environment: env
|
|
189
|
+
? { url: env.url, status: env.status, expiresAt: env.expiresAt ?? null }
|
|
190
|
+
: null,
|
|
191
|
+
degradedReason: state.degradedReason ?? null,
|
|
192
|
+
attempts: state.attempts,
|
|
193
|
+
maxAttempts: state.maxAttempts,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/** Project a parked visual-confirmation gate: the pairings awaiting a verdict. */
|
|
197
|
+
export function toVisualConfirmDecision(state) {
|
|
198
|
+
return {
|
|
199
|
+
kind: 'visual-confirmation',
|
|
200
|
+
phase: state.phase,
|
|
201
|
+
pairs: (state.pairs ?? []).map((pair) => ({
|
|
202
|
+
view: pair.view,
|
|
203
|
+
actualArtifactId: pair.actualArtifactId ?? null,
|
|
204
|
+
referenceArtifactId: pair.referenceArtifactId ?? null,
|
|
205
|
+
})),
|
|
206
|
+
degradedReason: state.degradedReason ?? null,
|
|
207
|
+
attempts: state.attempts,
|
|
208
|
+
maxAttempts: state.maxAttempts,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Whether a judge state is something the caller can still act on. `awaiting_decision` is the
|
|
213
|
+
* park; `evaluating`/`bouncing` are in flight and worth surfacing so a poller sees progress
|
|
214
|
+
* rather than an empty list that reads as "nothing is happening". A `passed`/`failed`/`skipped`
|
|
215
|
+
* judge is settled and carries no question.
|
|
216
|
+
*/
|
|
217
|
+
function isLiveJudge(state) {
|
|
218
|
+
return (state.status === 'awaiting_decision' ||
|
|
219
|
+
state.status === 'evaluating' ||
|
|
220
|
+
state.status === 'bouncing');
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Whether an iterative review (requirements / clarity / brainstorm — one lifecycle, one
|
|
224
|
+
* predicate) is something the caller can still act on. A settled review (`incorporated`) is
|
|
225
|
+
* history: it is the document downstream agents implement, not a question, so it is dropped from
|
|
226
|
+
* the list rather than presented as answerable. `incorporating`/`reviewing` ARE listed: the driver
|
|
227
|
+
* is mid-cycle and the caller should see that its answers are in flight.
|
|
228
|
+
*/
|
|
229
|
+
function isLiveReview(review) {
|
|
230
|
+
return review.status !== 'incorporated';
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Whether the fork state is something the caller can still act on. `awaiting_choice` is the park;
|
|
234
|
+
* `proposing`/`answering` are in-flight and worth surfacing so a poller sees progress. A `chosen`,
|
|
235
|
+
* `single_path` or `skipped` state is settled and carries no question.
|
|
236
|
+
*/
|
|
237
|
+
function isLiveFork(state) {
|
|
238
|
+
return (state.status === 'awaiting_choice' ||
|
|
239
|
+
state.status === 'proposing' ||
|
|
240
|
+
state.status === 'answering');
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Whether a PR deep review still wants a human. `awaiting_selection` is the park; `reviewing`,
|
|
244
|
+
* `challenging`, `fixing` and `posting` are work in flight a poller should see. `done`/`skipped`
|
|
245
|
+
* are settled.
|
|
246
|
+
*/
|
|
247
|
+
function isLivePrReview(state) {
|
|
248
|
+
return state.status !== 'done' && state.status !== 'skipped';
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Whether a human-test gate still wants a person. `awaiting_human` is the park; `provisioning`,
|
|
252
|
+
* `fixing` and `resolving_conflicts` are work in flight a poller should see; `passed` is settled.
|
|
253
|
+
*
|
|
254
|
+
* An EXHAUSTIVE switch rather than `phase !== 'passed'`, because the interesting direction is the
|
|
255
|
+
* one a negative test gets silently wrong: a phase added later (a `failed`, an `expired`) is
|
|
256
|
+
* terminal more often than not, and `!== 'passed'` would list it as a live question forever with
|
|
257
|
+
* nothing failing. Routed through {@link unclassifiedPhase} so the build breaks until somebody
|
|
258
|
+
* says which side the new phase is on.
|
|
259
|
+
*/
|
|
260
|
+
function isLiveHumanTest(state) {
|
|
261
|
+
switch (state.phase) {
|
|
262
|
+
case 'awaiting_human':
|
|
263
|
+
case 'provisioning':
|
|
264
|
+
case 'fixing':
|
|
265
|
+
case 'resolving_conflicts':
|
|
266
|
+
return true;
|
|
267
|
+
case 'passed':
|
|
268
|
+
return false;
|
|
269
|
+
default:
|
|
270
|
+
return unclassifiedPhase(state.phase);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Whether a visual-confirmation gate still wants a person. `awaiting_human` is the park, `fixing`
|
|
275
|
+
* is in flight, `approved` is settled. Exhaustive for the reason {@link isLiveHumanTest} is, and
|
|
276
|
+
* the pending phase is not hypothetical here: the internal schema's own comment records a
|
|
277
|
+
* `capturing` phase deferred until the re-capture loop is wired.
|
|
278
|
+
*/
|
|
279
|
+
function isLiveVisualConfirm(state) {
|
|
280
|
+
switch (state.phase) {
|
|
281
|
+
case 'awaiting_human':
|
|
282
|
+
case 'fixing':
|
|
283
|
+
return true;
|
|
284
|
+
case 'approved':
|
|
285
|
+
return false;
|
|
286
|
+
default:
|
|
287
|
+
return unclassifiedPhase(state.phase);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* A gate phase this projection has no verdict for. Unreachable by TYPE: reaching it means a
|
|
292
|
+
* member was added to the picklist without being classified above, which is a build failure at the
|
|
293
|
+
* call site rather than a runtime branch.
|
|
294
|
+
*
|
|
295
|
+
* It still answers at runtime, because the type is total against the SCHEMA and only partial
|
|
296
|
+
* against the DATA: a row persisted by a newer build lands here. `false` is the safe answer, as a
|
|
297
|
+
* phase nobody classified is not something to put in front of a caller as an open question.
|
|
298
|
+
*/
|
|
299
|
+
function unclassifiedPhase(_phase) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Project the PRE-DISPATCH INPUT GATE's verdict for an external caller. The issue CODES are the same
|
|
304
|
+
* closed vocabulary the SPA renders, so an integration maps them to its own copy (or hands them to
|
|
305
|
+
* whoever filed the ticket) rather than parsing our prose.
|
|
306
|
+
*/
|
|
307
|
+
export function toInputGateDecision(gate) {
|
|
308
|
+
return {
|
|
309
|
+
kind: 'input-gate',
|
|
310
|
+
status: gate.status,
|
|
311
|
+
mode: gate.mode,
|
|
312
|
+
issues: gate.issues,
|
|
313
|
+
checkedAt: gate.checkedAt,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Whether the gate's verdict is something the caller still has to act on. ONLY `blocked`, which is
|
|
318
|
+
* narrower than the other predicates here on purpose: `off`, `not_applicable` and `passed`
|
|
319
|
+
* are recorded facts about a run that was never held up, and `overridden` is a park somebody
|
|
320
|
+
* already answered. Listing any of them would put a decision in front of a caller with nothing to
|
|
321
|
+
* decide, and `parked` is read off the run's own status rather than from this list, so a settled
|
|
322
|
+
* verdict has nothing to add to it.
|
|
323
|
+
*/
|
|
324
|
+
function isLiveInputGate(gate) {
|
|
325
|
+
return gate.status === 'blocked';
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Build the run's decision list: whatever it is currently asking a human, plus the run status so a
|
|
329
|
+
* caller can distinguish "parked, answer me" from "still working".
|
|
330
|
+
*
|
|
331
|
+
* The run is RE-READ rather than taken from the `ScopedRun` the caller was gated with, because
|
|
332
|
+
* every mutating route builds its response through here AFTER acting: a `proceed` that advanced the
|
|
333
|
+
* run, or an `incorporate` that flipped it out of `blocked`, must not report the pre-action status.
|
|
334
|
+
* A run that vanished between the gate and here (a concurrent delete) falls back to the gated
|
|
335
|
+
* snapshot rather than 500-ing on an action that already succeeded.
|
|
336
|
+
*
|
|
337
|
+
* Everything that rides the run's STEPS is read off the instance already in hand; only the
|
|
338
|
+
* separately-stored iterative reviews cost a round-trip, and those are bounded by what the run's
|
|
339
|
+
* own step chain can produce (see {@link liveDialogueDecisions}).
|
|
340
|
+
*/
|
|
341
|
+
export async function buildDecisionList(c, workspaceId, scoped) {
|
|
342
|
+
const container = c.get('container');
|
|
343
|
+
const execution = (await container.executionRepository.get(workspaceId, scoped.execution.id)) ?? scoped.execution;
|
|
344
|
+
// The dialogue reads and the fork read are INDEPENDENT point lookups in separate stores, so they
|
|
345
|
+
// are issued together: this projection is on the poll path AND rebuilt after every answer, and
|
|
346
|
+
// awaiting them in sequence made its latency the sum of every park kind a run could carry rather
|
|
347
|
+
// than the slowest one. The concatenation order below is still deterministic.
|
|
348
|
+
const [dialogue, fork] = await Promise.all([
|
|
349
|
+
liveDialogueDecisions(c, workspaceId, scoped.blockId, execution),
|
|
350
|
+
liveForkDecisions(c, workspaceId, execution),
|
|
351
|
+
]);
|
|
352
|
+
const decisions = [
|
|
353
|
+
...dialogue,
|
|
354
|
+
...fork,
|
|
355
|
+
...liveStepDecisions(execution, container.agentKindRegistry),
|
|
356
|
+
];
|
|
357
|
+
// The input gate parks BEFORE the first dispatch, so when it is live it is the only thing the
|
|
358
|
+
// run is asking. Listed first for that reason: it is the earliest question, and the steps whose
|
|
359
|
+
// decisions follow have not run.
|
|
360
|
+
if (execution.inputGate && isLiveInputGate(execution.inputGate)) {
|
|
361
|
+
decisions.unshift(toInputGateDecision(execution.inputGate));
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
runId: execution.id,
|
|
365
|
+
taskId: scoped.blockId,
|
|
366
|
+
status: execution.status,
|
|
367
|
+
// `blocked` IS the parked state — the run is waiting on a human and will not move until one
|
|
368
|
+
// of these decisions is answered. Read from the run itself rather than inferred from the
|
|
369
|
+
// decisions, so a run parked on a surface this projection doesn't model (`human-review`,
|
|
370
|
+
// whose answer is a person approving the PR on the VCS host) still reports `parked: true`
|
|
371
|
+
// with an empty list rather than silently claiming all is well.
|
|
372
|
+
parked: execution.status === 'blocked',
|
|
373
|
+
decisions,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* The block-scoped iterative reviews a run can be parked on: requirements, clarity, and a
|
|
378
|
+
* brainstorm session per stage.
|
|
379
|
+
*
|
|
380
|
+
* Each of these lives in its OWN store, so each is a point read. Clarity and the brainstorms are
|
|
381
|
+
* fetched only when the run's step chain actually carries the kind that creates them: a run with
|
|
382
|
+
* no `clarity-review` step cannot be parked on a clarity review, and paying for the read on every
|
|
383
|
+
* poll of every run would make the cost of this endpoint a function of how many park kinds exist
|
|
384
|
+
* rather than of what the run can ask.
|
|
385
|
+
*
|
|
386
|
+
* Requirements is deliberately NOT step-gated. It has been read unconditionally since this surface
|
|
387
|
+
* shipped, which also serves a review run off-path from the block inspector; narrowing it now
|
|
388
|
+
* would take capability away from a live integration, and `/api/v1` does not do that.
|
|
389
|
+
*/
|
|
390
|
+
async function liveDialogueDecisions(c, workspaceId, blockId, execution) {
|
|
391
|
+
const container = c.get('container');
|
|
392
|
+
const kinds = new Set(execution.steps.map((s) => s.agentKind));
|
|
393
|
+
const { requirements, clarity, brainstorm } = container;
|
|
394
|
+
// Each read is against a different store with nothing to say to the others, so they are issued
|
|
395
|
+
// together rather than chained. The RESULT order is fixed by the tuple, not by which store
|
|
396
|
+
// answered first, so a caller's decision list does not reshuffle between two polls of one run.
|
|
397
|
+
const [requirementsReview, clarityReview, brainstormSessions] = await Promise.all([
|
|
398
|
+
requirements ? requirements.service.getForBlock(workspaceId, blockId) : null,
|
|
399
|
+
clarity && kinds.has(CLARITY_REVIEW_AGENT_KIND)
|
|
400
|
+
? clarity.service.getForBlock(workspaceId, blockId)
|
|
401
|
+
: null,
|
|
402
|
+
brainstorm
|
|
403
|
+
? Promise.all(liveBrainstormStages(kinds).map((stage) => brainstorm.services[stage].getForBlock(workspaceId, blockId)))
|
|
404
|
+
: [],
|
|
405
|
+
]);
|
|
406
|
+
const decisions = [];
|
|
407
|
+
if (requirementsReview && isLiveReview(requirementsReview)) {
|
|
408
|
+
decisions.push(toRequirementsDecision(requirementsReview));
|
|
409
|
+
}
|
|
410
|
+
if (clarityReview && isLiveReview(clarityReview)) {
|
|
411
|
+
decisions.push(toClarityDecision(clarityReview));
|
|
412
|
+
}
|
|
413
|
+
for (const session of brainstormSessions) {
|
|
414
|
+
if (session && isLiveReview(session))
|
|
415
|
+
decisions.push(toBrainstormDecision(session));
|
|
416
|
+
}
|
|
417
|
+
return decisions;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* The brainstorm stages this run's step chain can park on. A block may hold one live session per
|
|
421
|
+
* stage at once, so this returns a LIST: a pipeline running both dialogues puts two brainstorm
|
|
422
|
+
* decisions in front of the caller, and collapsing them to one would hide whichever came second.
|
|
423
|
+
*/
|
|
424
|
+
function liveBrainstormStages(kinds) {
|
|
425
|
+
const stages = [];
|
|
426
|
+
if (kinds.has(REQUIREMENTS_BRAINSTORM_AGENT_KIND))
|
|
427
|
+
stages.push('requirements');
|
|
428
|
+
if (kinds.has(ARCHITECTURE_BRAINSTORM_AGENT_KIND))
|
|
429
|
+
stages.push('architecture');
|
|
430
|
+
return stages;
|
|
431
|
+
}
|
|
432
|
+
/** The run's implementation-fork park, which the engine stores behind its own service read. */
|
|
433
|
+
async function liveForkDecisions(c, workspaceId, execution) {
|
|
434
|
+
const fork = await c.get('container').executionService.getForkDecision(workspaceId, execution.id);
|
|
435
|
+
return fork && isLiveFork(fork) ? [toForkDecision(fork)] : [];
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Every park that rides the run's own STEPS — no repository round-trip, since all of this state
|
|
439
|
+
* lives on the instance already in hand (the whole reason none of it has a side table).
|
|
440
|
+
*
|
|
441
|
+
* Scanned over the WHOLE step chain rather than `currentStep` alone: the engine parks a run by
|
|
442
|
+
* leaving the step waiting, and which index that is depends on the park (a companion gate sits on
|
|
443
|
+
* the companion's step, an approval gate on the producer's), so keying off the cursor would report
|
|
444
|
+
* an empty list for a run that is plainly stopped.
|
|
445
|
+
*/
|
|
446
|
+
function liveStepDecisions(execution, registry) {
|
|
447
|
+
const decisions = [];
|
|
448
|
+
execution.steps.forEach((step, index) => {
|
|
449
|
+
const approval = step.approval;
|
|
450
|
+
if (approval?.status === 'pending' && isGenericApprovalPark(execution, step, registry)) {
|
|
451
|
+
decisions.push(toApprovalDecision(step, index, approval));
|
|
452
|
+
}
|
|
453
|
+
if (step.decision && step.decision.chosen == null) {
|
|
454
|
+
decisions.push(toAgentDecision(step, step.decision));
|
|
455
|
+
}
|
|
456
|
+
if (step.judge && isLiveJudge(step.judge)) {
|
|
457
|
+
decisions.push(toJudgeDecision(step.agentKind, step.judge));
|
|
458
|
+
}
|
|
459
|
+
if (step.prReview && isLivePrReview(step.prReview)) {
|
|
460
|
+
decisions.push(toPrReviewDecision(step.prReview));
|
|
461
|
+
}
|
|
462
|
+
if (step.humanTest && isLiveHumanTest(step.humanTest)) {
|
|
463
|
+
decisions.push(toHumanTestDecision(step.humanTest));
|
|
464
|
+
}
|
|
465
|
+
if (step.visualConfirm && isLiveVisualConfirm(step.visualConfirm)) {
|
|
466
|
+
decisions.push(toVisualConfirmDecision(step.visualConfirm));
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
return decisions;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Whether a step's pending approval is an ORDINARY approval gate — the one the approve /
|
|
473
|
+
* request-changes / reject routes answer.
|
|
474
|
+
*
|
|
475
|
+
* `step.approval` is the engine's generic parking mechanism, so a review gate, a brainstorm, a
|
|
476
|
+
* human-verdict gate and a fork choice all carry a pending approval too. Reporting those as
|
|
477
|
+
* `approval-gate` would be the worst kind of wrong here: the caller would be offered verbs the
|
|
478
|
+
* engine refuses (`assertNotIterativeGate`), so a well-behaved integration would sit in a 409 loop
|
|
479
|
+
* against a park it was told it could answer. The classifier is the ENGINE's own, so what this
|
|
480
|
+
* surface offers and what the engine accepts cannot disagree.
|
|
481
|
+
*
|
|
482
|
+
* `companion-cap` is admitted rather than excluded: it IS answered here, by `resolve-exceeded`,
|
|
483
|
+
* and the projection flags it as `exceeded` so a caller reaches for that verb instead of approve.
|
|
484
|
+
*/
|
|
485
|
+
function isGenericApprovalPark(execution, step, registry) {
|
|
486
|
+
const surface = dedicatedParkSurface(execution, step, registry);
|
|
487
|
+
return surface === null || surface === 'companion-cap';
|
|
488
|
+
}
|
|
489
|
+
//# sourceMappingURL=projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.js","sourceRoot":"","sources":["../../../../src/modules/publicApi/decisions/projection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import type { AppEnv } from '../../../http/env.js';
|
|
3
|
+
/**
|
|
4
|
+
* The REQUIREMENTS review loop. Each route is the external twin of a `RequirementReviewController`
|
|
5
|
+
* route, calling the same service method. The item-level routes are addressed by ITEM id (not
|
|
6
|
+
* review id): a headless caller reads the findings from `GET .../decisions`, and making it also
|
|
7
|
+
* thread a review id through would be ceremony over a value it never chose. The live review is
|
|
8
|
+
* resolved from the run's block, exactly as the SPA's block-scoped routes do.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerRequirementsDecisionRoutes(app: Hono<AppEnv>): void;
|
|
11
|
+
//# sourceMappingURL=requirementsRoutes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirementsRoutes.d.ts","sourceRoot":"","sources":["../../../../src/modules/publicApi/decisions/requirementsRoutes.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAIlD;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAqG1E"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { incorporatePublicRunRequirementsContract, proceedPublicRunRequirementsContract, replyPublicRunFindingContract, reReviewPublicRunRequirementsContract, resolvePublicRunRequirementsExceededContract, setPublicRunFindingStatusContract, } from '@cat-factory/contracts';
|
|
2
|
+
import { buildHonoRoute } from '@toad-contracts/hono';
|
|
3
|
+
import { buildDecisionList } from './projection.js';
|
|
4
|
+
import { failureBody, gateRequirementsAction } from './scope.js';
|
|
5
|
+
/**
|
|
6
|
+
* The REQUIREMENTS review loop. Each route is the external twin of a `RequirementReviewController`
|
|
7
|
+
* route, calling the same service method. The item-level routes are addressed by ITEM id (not
|
|
8
|
+
* review id): a headless caller reads the findings from `GET .../decisions`, and making it also
|
|
9
|
+
* thread a review id through would be ceremony over a value it never chose. The live review is
|
|
10
|
+
* resolved from the run's block, exactly as the SPA's block-scoped routes do.
|
|
11
|
+
*/
|
|
12
|
+
export function registerRequirementsDecisionRoutes(app) {
|
|
13
|
+
// Answer one finding.
|
|
14
|
+
buildHonoRoute(app, replyPublicRunFindingContract, async (c) => {
|
|
15
|
+
const { runId, itemId } = c.req.valid('param');
|
|
16
|
+
const gated = await gateRequirementsAction(c, runId);
|
|
17
|
+
if ('fail' in gated) {
|
|
18
|
+
return c.json(failureBody(gated.fail), gated.fail.status);
|
|
19
|
+
}
|
|
20
|
+
const { workspaceId, scoped, requirements, review } = gated;
|
|
21
|
+
await requirements.service.replyToItem(workspaceId, review.id, itemId, c.req.valid('json').reply);
|
|
22
|
+
return c.json(await buildDecisionList(c, workspaceId, scoped), 200);
|
|
23
|
+
});
|
|
24
|
+
// Dismiss a finding as not applicable, or reopen one dismissed by mistake.
|
|
25
|
+
buildHonoRoute(app, setPublicRunFindingStatusContract, async (c) => {
|
|
26
|
+
const { runId, itemId } = c.req.valid('param');
|
|
27
|
+
const gated = await gateRequirementsAction(c, runId);
|
|
28
|
+
if ('fail' in gated) {
|
|
29
|
+
return c.json(failureBody(gated.fail), gated.fail.status);
|
|
30
|
+
}
|
|
31
|
+
const { workspaceId, scoped, requirements, review } = gated;
|
|
32
|
+
await requirements.service.setItemStatus(workspaceId, review.id, itemId, c.req.valid('json').status);
|
|
33
|
+
return c.json(await buildDecisionList(c, workspaceId, scoped), 200);
|
|
34
|
+
});
|
|
35
|
+
// Fold the recorded answers into the standardized document. ASYNCHRONOUS: it records the intent
|
|
36
|
+
// on the parked step and signals the durable driver, which folds + re-reviews in the background —
|
|
37
|
+
// so the returned list shows the review `incorporating`, and the caller learns the outcome from
|
|
38
|
+
// the SSE stream or a follow-up read, exactly as the SPA does.
|
|
39
|
+
buildHonoRoute(app, incorporatePublicRunRequirementsContract, async (c) => {
|
|
40
|
+
const { runId } = c.req.valid('param');
|
|
41
|
+
const gated = await gateRequirementsAction(c, runId);
|
|
42
|
+
if ('fail' in gated) {
|
|
43
|
+
return c.json(failureBody(gated.fail), gated.fail.status);
|
|
44
|
+
}
|
|
45
|
+
const { workspaceId, scoped } = gated;
|
|
46
|
+
await c
|
|
47
|
+
.get('container')
|
|
48
|
+
.executionService.requirementsReview.incorporate(workspaceId, scoped.blockId, c.req.valid('json').feedback);
|
|
49
|
+
return c.json(await buildDecisionList(c, workspaceId, scoped), 200);
|
|
50
|
+
});
|
|
51
|
+
// One more reviewer pass over the incorporated document. On convergence the parked run advances.
|
|
52
|
+
buildHonoRoute(app, reReviewPublicRunRequirementsContract, async (c) => {
|
|
53
|
+
const { runId } = c.req.valid('param');
|
|
54
|
+
const gated = await gateRequirementsAction(c, runId);
|
|
55
|
+
if ('fail' in gated) {
|
|
56
|
+
return c.json(failureBody(gated.fail), gated.fail.status);
|
|
57
|
+
}
|
|
58
|
+
const { workspaceId, scoped } = gated;
|
|
59
|
+
await c
|
|
60
|
+
.get('container')
|
|
61
|
+
.executionService.requirementsReview.reReview(workspaceId, scoped.blockId);
|
|
62
|
+
return c.json(await buildDecisionList(c, workspaceId, scoped), 200);
|
|
63
|
+
});
|
|
64
|
+
// Settle the requirements phase and advance the parked run.
|
|
65
|
+
buildHonoRoute(app, proceedPublicRunRequirementsContract, async (c) => {
|
|
66
|
+
const { runId } = c.req.valid('param');
|
|
67
|
+
const gated = await gateRequirementsAction(c, runId);
|
|
68
|
+
if ('fail' in gated) {
|
|
69
|
+
return c.json(failureBody(gated.fail), gated.fail.status);
|
|
70
|
+
}
|
|
71
|
+
const { workspaceId, scoped } = gated;
|
|
72
|
+
await c
|
|
73
|
+
.get('container')
|
|
74
|
+
.executionService.requirementsReview.proceed(workspaceId, scoped.blockId);
|
|
75
|
+
return c.json(await buildDecisionList(c, workspaceId, scoped), 200);
|
|
76
|
+
});
|
|
77
|
+
// Resolve a review that hit its iteration cap (extra round / proceed / stop and reset).
|
|
78
|
+
buildHonoRoute(app, resolvePublicRunRequirementsExceededContract, async (c) => {
|
|
79
|
+
const { runId } = c.req.valid('param');
|
|
80
|
+
const gated = await gateRequirementsAction(c, runId);
|
|
81
|
+
if ('fail' in gated) {
|
|
82
|
+
return c.json(failureBody(gated.fail), gated.fail.status);
|
|
83
|
+
}
|
|
84
|
+
const { workspaceId, scoped } = gated;
|
|
85
|
+
await c
|
|
86
|
+
.get('container')
|
|
87
|
+
.executionService.requirementsReview.resolveExceeded(workspaceId, scoped.blockId, c.req.valid('json').choice);
|
|
88
|
+
return c.json(await buildDecisionList(c, workspaceId, scoped), 200);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=requirementsRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirementsRoutes.js","sourceRoot":"","sources":["../../../../src/modules/publicApi/decisions/requirementsRoutes.ts"],"names":[],"mappings":"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"}
|