@cat-factory/orchestration 0.326.0 → 0.328.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/modules/execution/AgentContextBuilder.d.ts +3 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -1
- package/dist/modules/execution/AgentContextBuilder.js +4 -1
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -1
- package/dist/modules/execution/AgentDispatchController.d.ts +23 -1
- package/dist/modules/execution/AgentDispatchController.d.ts.map +1 -1
- package/dist/modules/execution/AgentDispatchController.js +32 -0
- package/dist/modules/execution/AgentDispatchController.js.map +1 -1
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +1 -1
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/PollCompletionController.d.ts +1 -4
- package/dist/modules/execution/PollCompletionController.d.ts.map +1 -1
- package/dist/modules/execution/PollCompletionController.js +6 -19
- package/dist/modules/execution/PollCompletionController.js.map +1 -1
- package/dist/modules/execution/PrReviewChallengeQueue.d.ts +89 -0
- package/dist/modules/execution/PrReviewChallengeQueue.d.ts.map +1 -0
- package/dist/modules/execution/PrReviewChallengeQueue.js +273 -0
- package/dist/modules/execution/PrReviewChallengeQueue.js.map +1 -0
- package/dist/modules/execution/PrReviewController.d.ts +15 -26
- package/dist/modules/execution/PrReviewController.d.ts.map +1 -1
- package/dist/modules/execution/PrReviewController.js +44 -52
- package/dist/modules/execution/PrReviewController.js.map +1 -1
- package/dist/modules/execution/PrReviewResolutionController.d.ts +9 -14
- package/dist/modules/execution/PrReviewResolutionController.d.ts.map +1 -1
- package/dist/modules/execution/PrReviewResolutionController.js +15 -42
- package/dist/modules/execution/PrReviewResolutionController.js.map +1 -1
- package/dist/modules/execution/ReviewGateController.d.ts +11 -1
- package/dist/modules/execution/ReviewGateController.d.ts.map +1 -1
- package/dist/modules/execution/ReviewGateController.js +29 -3
- package/dist/modules/execution/ReviewGateController.js.map +1 -1
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +14 -2
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/advance.d.ts +13 -0
- package/dist/modules/execution/advance.d.ts.map +1 -1
- package/dist/modules/execution/advance.js.map +1 -1
- package/dist/modules/execution/builder-review-effort.d.ts +24 -0
- package/dist/modules/execution/builder-review-effort.d.ts.map +1 -0
- package/dist/modules/execution/builder-review-effort.js +37 -0
- package/dist/modules/execution/builder-review-effort.js.map +1 -0
- package/dist/modules/execution/dispatcher-registries.d.ts.map +1 -1
- package/dist/modules/execution/dispatcher-registries.js +2 -20
- package/dist/modules/execution/dispatcher-registries.js.map +1 -1
- package/dist/modules/execution/drive.d.ts.map +1 -1
- package/dist/modules/execution/drive.js +16 -9
- package/dist/modules/execution/drive.js.map +1 -1
- package/dist/modules/execution/gate-window-controllers.d.ts +5 -0
- package/dist/modules/execution/gate-window-controllers.d.ts.map +1 -1
- package/dist/modules/execution/gate-window-facades.d.ts +4 -2
- package/dist/modules/execution/gate-window-facades.d.ts.map +1 -1
- package/dist/modules/execution/gate-window-facades.js +5 -4
- package/dist/modules/execution/gate-window-facades.js.map +1 -1
- package/dist/modules/execution/policy-types.d.ts +7 -0
- package/dist/modules/execution/policy-types.d.ts.map +1 -1
- package/dist/modules/execution/policy-types.js.map +1 -1
- package/dist/modules/execution/prReview.logic.js +2 -2
- package/dist/modules/execution/prReview.logic.js.map +1 -1
- package/dist/modules/execution/run-context-admission.d.ts +8 -1
- package/dist/modules/execution/run-context-admission.d.ts.map +1 -1
- package/dist/modules/execution/run-context-admission.js +8 -1
- package/dist/modules/execution/run-context-admission.js.map +1 -1
- package/dist/modules/execution/step-fold.logic.d.ts +10 -0
- package/dist/modules/execution/step-fold.logic.d.ts.map +1 -1
- package/dist/modules/execution/step-fold.logic.js +16 -0
- package/dist/modules/execution/step-fold.logic.js.map +1 -1
- package/dist/modules/merge/AccountRiskPolicyService.d.ts.map +1 -1
- package/dist/modules/merge/AccountRiskPolicyService.js +1 -0
- package/dist/modules/merge/AccountRiskPolicyService.js.map +1 -1
- package/dist/modules/merge/RiskPolicyService.d.ts.map +1 -1
- package/dist/modules/merge/RiskPolicyService.js +1 -0
- package/dist/modules/merge/RiskPolicyService.js.map +1 -1
- package/dist/modules/requirements/RequirementReviewService.d.ts +2 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts.map +1 -1
- package/dist/modules/requirements/RequirementReviewService.js +3 -0
- package/dist/modules/requirements/RequirementReviewService.js.map +1 -1
- package/dist/modules/requirements/requirements.logic.d.ts +7 -1
- package/dist/modules/requirements/requirements.logic.d.ts.map +1 -1
- package/dist/modules/requirements/requirements.logic.js +18 -2
- package/dist/modules/requirements/requirements.logic.js.map +1 -1
- package/dist/modules/review/IterativeReviewService.d.ts +7 -1
- package/dist/modules/review/IterativeReviewService.d.ts.map +1 -1
- package/dist/modules/review/IterativeReviewService.js +19 -6
- package/dist/modules/review/IterativeReviewService.js.map +1 -1
- package/dist/modules/review/follow-up-bar.logic.d.ts +32 -0
- package/dist/modules/review/follow-up-bar.logic.d.ts.map +1 -0
- package/dist/modules/review/follow-up-bar.logic.js +62 -0
- package/dist/modules/review/follow-up-bar.logic.js.map +1 -0
- package/package.json +11 -11
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { failureKindFromHarnessCause } from '@cat-factory/kernel';
|
|
2
2
|
import { containerShutdownFailure, delegatedTerminalFailure, MAX_BRANCH_CONTENTION_RECOVERIES, MAX_DELEGATED_RETRIES, } from './job.logic.js';
|
|
3
|
-
import { PR_REVIEWER_KIND } from '@cat-factory/agents';
|
|
4
3
|
import { HUMAN_TEST_AGENT_KIND, isTesterKind, VISUAL_CONFIRM_AGENT_KIND } from './ci.logic.js';
|
|
5
4
|
import { BUG_FISHING_STEP_KIND } from './BugFishingController.js';
|
|
6
5
|
import { applyValidationReport, coerceValidationReport, validationFailureDetail, } from './validation.logic.js';
|
|
@@ -22,7 +21,6 @@ export class PollCompletionController {
|
|
|
22
21
|
testerController;
|
|
23
22
|
humanTestController;
|
|
24
23
|
visualConfirmationController;
|
|
25
|
-
prReviewController;
|
|
26
24
|
bugFishingController;
|
|
27
25
|
recordBackendDiagnostics;
|
|
28
26
|
recoverContainerEviction;
|
|
@@ -35,7 +33,6 @@ export class PollCompletionController {
|
|
|
35
33
|
this.testerController = deps.testerController;
|
|
36
34
|
this.humanTestController = deps.humanTestController;
|
|
37
35
|
this.visualConfirmationController = deps.visualConfirmationController;
|
|
38
|
-
this.prReviewController = deps.prReviewController;
|
|
39
36
|
this.bugFishingController = deps.bugFishingController;
|
|
40
37
|
this.recordBackendDiagnostics = deps.recordBackendDiagnostics;
|
|
41
38
|
this.recoverContainerEviction = deps.recoverContainerEviction;
|
|
@@ -93,7 +90,7 @@ export class PollCompletionController {
|
|
|
93
90
|
}
|
|
94
91
|
/**
|
|
95
92
|
* Resolve a `failed` agent poll: record backend diagnostics, attempt transient container-eviction
|
|
96
|
-
* recovery, settle a
|
|
93
|
+
* recovery, settle a failed bug-fishing angle, else mark
|
|
97
94
|
* the container errored and report `job_failed` with the harness's classified cause.
|
|
98
95
|
*/
|
|
99
96
|
async handleFailedPoll(workspaceId, instance, step, update) {
|
|
@@ -145,22 +142,12 @@ export class PollCompletionController {
|
|
|
145
142
|
const redispatched = await this.recoverDelegatedFailure(workspaceId, instance, step, update);
|
|
146
143
|
if (redispatched)
|
|
147
144
|
return redispatched;
|
|
148
|
-
// A read-only Challenge Investigator (dispatched off a parked `pr-reviewer` step when the
|
|
149
|
-
// human challenged ONE finding) failed for real: settle the challenge as `failed` and RE-PARK
|
|
150
|
-
// the review — a non-critical second opinion crashing must not fail the human's in-flight
|
|
151
|
-
// curation. Mirrors the human-test / visual-confirmation helper-failure branches above.
|
|
152
|
-
if (step.agentKind === PR_REVIEWER_KIND && step.prReview?.status === 'challenging') {
|
|
153
|
-
const settled = await this.prReviewController.recordChallengeFailure(workspaceId, instance, step, update.error);
|
|
154
|
-
if (settled)
|
|
155
|
-
return settled;
|
|
156
|
-
}
|
|
157
145
|
// A BUG-FISHING pass failed for real: settle THAT ANGLE as failed, carrying the reason, and
|
|
158
146
|
// carry on with the next one. The angles share nothing but the checkout, so one crashing must
|
|
159
147
|
// not cost the expedition the passes that already landed nor the ones still to come — and the
|
|
160
148
|
// failure is named on the phase, because a phase that silently reported nothing is
|
|
161
|
-
// indistinguishable from a phase that honestly found nothing.
|
|
162
|
-
//
|
|
163
|
-
// of a larger read-only investigation, not a verdict on the run.
|
|
149
|
+
// indistinguishable from a phase that honestly found nothing. It is a failure of ONE
|
|
150
|
+
// non-critical part of a larger read-only investigation, not a verdict on the run.
|
|
164
151
|
if (step.agentKind === BUG_FISHING_STEP_KIND && step.bugFishing?.status === 'fishing') {
|
|
165
152
|
const block = await this.blockRepository.get(workspaceId, instance.blockId);
|
|
166
153
|
const settled = await this.bugFishingController.recordPhaseFailure(workspaceId, instance, step, update.error, block);
|
|
@@ -183,9 +170,9 @@ export class PollCompletionController {
|
|
|
183
170
|
// A harness that exited cleanly mid-job was stopped by something a fresh container meets
|
|
184
171
|
// again, so this fails the run outright rather than spending an eviction budget on it. It is
|
|
185
172
|
// asked HERE, below every branch that settles a job WITHOUT failing the run, because those
|
|
186
|
-
// branches are about whose job died rather than about how: a killed
|
|
187
|
-
// still a non-critical
|
|
188
|
-
// would trade one wrong recovery for a worse one. It cannot be reached by the eviction
|
|
173
|
+
// branches are about whose job died rather than about how: a killed bug-fishing angle is
|
|
174
|
+
// still a non-critical part of a larger investigation, and failing the whole expedition over
|
|
175
|
+
// it would trade one wrong recovery for a worse one. It cannot be reached by the eviction
|
|
189
176
|
// recovery above either way (`harnessShutdown` is never set beside `evicted`), so nothing
|
|
190
177
|
// above it spends a retry on this failure.
|
|
191
178
|
const shutdown = containerShutdownFailure(update);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PollCompletionController.js","sourceRoot":"","sources":["../../../src/modules/execution/PollCompletionController.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAEL,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"PollCompletionController.js","sourceRoot":"","sources":["../../../src/modules/execution/PollCompletionController.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAEL,wBAAwB,EACxB,wBAAwB,EACxB,gCAAgC,EAChC,qBAAqB,GACtB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAA;AAM9F,OAAO,EAA6B,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AAC5F,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAmC3E;;;;;;GAMG;AACH,MAAM,OAAO,wBAAwB;IAClB,eAAe,CAAiB;IAChC,KAAK,CAAO;IACZ,KAAK,CAAc;IACnB,eAAe,CAAiB;IAChC,gBAAgB,CAAkB;IAClC,mBAAmB,CAAqB;IACxC,4BAA4B,CAA8B;IAC1D,oBAAoB,CAAsB;IAC1C,wBAAwB,CAA0D;IAClF,wBAAwB,CAA0D;IAClF,mBAAmB,CAAqD;IAEzF,YAAY,IAAkC;QAC5C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAA;QAC3C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACvB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACvB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAA;QAC3C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAA;QAC7C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAA;QACnD,IAAI,CAAC,4BAA4B,GAAG,IAAI,CAAC,4BAA4B,CAAA;QACrE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAA;QACrD,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,CAAA;QAC7D,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,CAAA;QAC7D,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAA;IACrD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,4BAA4B,CAChC,WAAmB,EACnB,QAA2B,EAC3B,IAAkB,EAClB,MAAqB;QAErB,2EAA2E;QAC3E,6EAA6E;QAC7E,6EAA6E;QAC7E,0EAA0E;QAC1E,IAAI,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,QAAQ,EAAE,CAAC;YAClE,qFAAqF;YACrF,oFAAoF;YACpF,iCAAiC;YACjC,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CACtC,IAAI,EACJ,MAAM,CAAC,KAAK,KAAK,MAAM;gBACrB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE;gBACzD,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,EACpD,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CACjB,CAAA;YACD,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;YACtB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAA;YACzB,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;YAC3B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;YAC3E,IAAI,CAAC,KAAK;gBAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;YACnC,8EAA8E;YAC9E,6EAA6E;YAC7E,4BAA4B;YAC5B,MAAM,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;YAClE,OAAO,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QACjF,CAAC;QAED,qFAAqF;QACrF,oFAAoF;QACpF,mFAAmF;QACnF,uFAAuF;QACvF,6CAA6C;QAC7C,IACE,IAAI,CAAC,SAAS,KAAK,qBAAqB;YACxC,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,qBAAqB,CAAC,EACvF,CAAC;YACD,OAAO,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC5E,KAAK,EAAE,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;aACrD,CAAC,CAAA;QACJ,CAAC;QAED,0FAA0F;QAC1F,kFAAkF;QAClF,IAAI,IAAI,CAAC,SAAS,KAAK,yBAAyB,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC3F,OAAO,IAAI,CAAC,4BAA4B,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACrF,KAAK,EAAE,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;aACrD,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,gBAAgB,CACpB,WAAmB,EACnB,QAA2B,EAC3B,IAAkB,EAClB,MAAoD;QAEpD,wFAAwF;QACxF,qFAAqF;QACrF,oFAAoF;QACpF,0FAA0F;QAC1F,wFAAwF;QACxF,4FAA4F;QAC5F,6DAA6D;QAC7D,IAAI,CAAC,wBAAwB,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACvD,2FAA2F;QAC3F,gGAAgG;QAChG,gGAAgG;QAChG,2FAA2F;QAC3F,2FAA2F;QAC3F,+FAA+F;QAC/F,8EAA8E;QAC9E,MAAM,gBAAgB,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAA;QACnF,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAA;QACxD,4FAA4F;QAC5F,4FAA4F;QAC5F,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACpE,sFAAsF;QACtF,yFAAyF;QACzF,sFAAsF;QACtF,2FAA2F;QAC3F,6EAA6E;QAC7E,4FAA4F;QAC5F,4FAA4F;QAC5F,cAAc;QACd,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC1F,IAAI,SAAS;YAAE,OAAO,SAAS,CAAA;QAC/B,2FAA2F;QAC3F,8FAA8F;QAC9F,2FAA2F;QAC3F,uFAAuF;QACvF,wDAAwD;QACxD,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAC/D,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,MAAM,CACP,CAAA;QACD,IAAI,sBAAsB;YAAE,OAAO,sBAAsB,CAAA;QACzD,uFAAuF;QACvF,8FAA8F;QAC9F,8FAA8F;QAC9F,2FAA2F;QAC3F,0FAA0F;QAC1F,yBAAyB;QACzB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAC5F,IAAI,YAAY;YAAE,OAAO,YAAY,CAAA;QACrC,4FAA4F;QAC5F,8FAA8F;QAC9F,8FAA8F;QAC9F,mFAAmF;QACnF,qFAAqF;QACrF,mFAAmF;QACnF,IAAI,IAAI,CAAC,SAAS,KAAK,qBAAqB,IAAI,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YACtF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;YAC3E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,kBAAkB,CAChE,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,MAAM,CAAC,KAAK,EACZ,KAAK,CACN,CAAA;YACD,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAA;QAC7B,CAAC;QACD,+FAA+F;QAC/F,yFAAyF;QACzF,yFAAyF;QACzF,0FAA0F;QAC1F,wFAAwF;QACxF,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAA;QAC1D,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC1D,KAAK,EAAE,iBAAiB,CAAC,KAAK;gBAC9B,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChE,CAAC,CAAA;YACF,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,iBAAiB,EAAE,CAAA;QACrD,CAAC;QACD,yFAAyF;QACzF,6FAA6F;QAC7F,2FAA2F;QAC3F,yFAAyF;QACzF,6FAA6F;QAC7F,0FAA0F;QAC1F,0FAA0F;QAC1F,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAA;QACjD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC1D,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChE,CAAC,CAAA;YACF,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,CAAA;QAC5C,CAAC;QACD,sFAAsF;QACtF,sFAAsF;QACtF,uFAAuF;QACvF,0FAA0F;QAC1F,yFAAyF;QACzF,gFAAgF;QAChF,oFAAoF;QACpF,4FAA4F;QAC5F,6FAA6F;QAC7F,8FAA8F;QAC9F,6FAA6F;QAC7F,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC1D,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChE,CAAC,CAAA;QACF,OAAO;YACL,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,wFAAwF;YACxF,2FAA2F;YAC3F,6FAA6F;YAC7F,0FAA0F;YAC1F,uFAAuF;YACvF,WAAW,EACT,2BAA2B,CAAC,MAAM,CAAC,YAAY,CAAC;gBAChD,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3D,MAAM,EAAE,gBAAgB,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK;YACzD,wFAAwF;YACxF,iFAAiF;YACjF,wFAAwF;YACxF,4DAA4D;YAC5D,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChE,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;OAaG;IACK,KAAK,CAAC,uBAAuB,CACnC,WAAmB,EACnB,QAA2B,EAC3B,IAAkB,EAClB,MAAoD;QAEpD,IAAI,MAAM,CAAC,YAAY,KAAK,kBAAkB;YAAE,OAAO,IAAI,CAAA;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,0BAA0B,IAAI,CAAC,CAAA;QACvD,IAAI,UAAU,IAAI,gCAAgC;YAAE,OAAO,IAAI,CAAA;QAC/D,IAAI,CAAC,0BAA0B,GAAG,UAAU,GAAG,CAAC,CAAA;QAChD,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAA;QACzB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,8FAA8F;QAC9F,0FAA0F;QAC1F,IAAI,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;QACvC,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAChE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;IAC7B,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACK,KAAK,CAAC,uBAAuB,CACnC,WAAmB,EACnB,QAA2B,EAC3B,IAAkB,EAClB,MAAoD;QAEpD,IAAI,MAAM,CAAC,SAAS,EAAE,WAAW,KAAK,WAAW;YAAE,OAAO,IAAI,CAAA;QAC9D,6FAA6F;QAC7F,6FAA6F;QAC7F,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAA;QAC1C,IAAI,OAAO,IAAI,qBAAqB;YAAE,OAAO,IAAI,CAAA;QACjD,IAAI,CAAC,gBAAgB,GAAG,OAAO,GAAG,CAAC,CAAA;QACnC,gBAAgB,CAAC,IAAI,EAAE;YACrB,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,MAAM,CAAC,KAAK;YACrB,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAA;QACF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAA;QACzB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAChE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;IAC7B,CAAC;IAED;;;;;OAKG;IACK,sBAAsB,CAAC,IAAkB,EAAE,GAAY;QAC7D,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAA;QAC1C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QACxB,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACnC,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { AgentJobHandle, AgentJobUpdate, AgentRunContext, AgentRunResult, Clock, ExecutionInstance, Logger, PipelineStep } from '@cat-factory/kernel';
|
|
2
|
+
import { type AgentKindRegistry } from '@cat-factory/agents';
|
|
3
|
+
import type { SpendService } from '@cat-factory/spend';
|
|
4
|
+
import type { AdvanceResult } from './advance.js';
|
|
5
|
+
import type { RunStateMachine } from './RunStateMachine.js';
|
|
6
|
+
import type { StepHandlerContext } from './step-handler-registry.js';
|
|
7
|
+
/** What the challenge queue needs from the dispatcher. */
|
|
8
|
+
export interface PrReviewChallengeQueueDeps {
|
|
9
|
+
runStateMachine: RunStateMachine;
|
|
10
|
+
agentKindRegistry: AgentKindRegistry;
|
|
11
|
+
spend: SpendService;
|
|
12
|
+
clock: Clock;
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
/** @see AgentDispatchController.startSideJob */
|
|
15
|
+
startSideJob: (ctx: StepHandlerContext, dispatchKind: string, dispatchEpoch: number, augmentContext: (context: AgentRunContext) => void) => Promise<{
|
|
16
|
+
job: AgentJobHandle;
|
|
17
|
+
} | {
|
|
18
|
+
result: AgentRunResult;
|
|
19
|
+
}>;
|
|
20
|
+
/** @see AgentDispatchController.pollSideJob */
|
|
21
|
+
pollSideJob: (handle: AgentJobHandle) => Promise<AgentJobUpdate | null>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The PR-review CHALLENGE QUEUE: every finding a human challenged gets its own read-only Challenge
|
|
25
|
+
* Investigator, at most {@link MAX_CONCURRENT_CHALLENGE_INVESTIGATIONS} at once, the rest starting in
|
|
26
|
+
* the order they were asked for as earlier ones settle.
|
|
27
|
+
*
|
|
28
|
+
* The investigators are HELPER jobs beside the `pr-reviewer` step, never the step's own job: one
|
|
29
|
+
* step can hold one job, and three running side by side is the point. So each queue entry
|
|
30
|
+
* (`step.challengeJobs`) carries what the step-level fields carry for the step's job, the claimed
|
|
31
|
+
* epoch and the attribution its poll re-supplies.
|
|
32
|
+
*
|
|
33
|
+
* While the queue is non-empty the review is `challenging` and the run parks on
|
|
34
|
+
* `awaiting_investigations`: the driver polls {@link poll} between sleeps. Every settled verdict
|
|
35
|
+
* answers `continue`, which sends the driver back through the step handler ({@link drive}) to fill
|
|
36
|
+
* the freed slot. That is also what keeps a long queue inside the poll budget: each settle starts a
|
|
37
|
+
* fresh park, so the budget bounds one wait for one verdict, never the whole queue.
|
|
38
|
+
*
|
|
39
|
+
* Replay safety rests on claim-before-effect: an entry's epoch is claimed and PERSISTED before its
|
|
40
|
+
* executor call, and the harness job id is derived from the epoch, so a replay that finds an epoch
|
|
41
|
+
* with no job id re-addresses the same job rather than starting another.
|
|
42
|
+
*/
|
|
43
|
+
export declare class PrReviewChallengeQueue {
|
|
44
|
+
private readonly deps;
|
|
45
|
+
private readonly log;
|
|
46
|
+
constructor(deps: PrReviewChallengeQueueDeps);
|
|
47
|
+
/**
|
|
48
|
+
* The step handler's body while the review is `challenging`: re-address any claim a replay
|
|
49
|
+
* interrupted, start queued challenges into the free slots, and park on the running ones. With
|
|
50
|
+
* nothing left in the queue the review returns to `awaiting_selection` and parks for the human.
|
|
51
|
+
*/
|
|
52
|
+
drive(ctx: StepHandlerContext): Promise<AdvanceResult>;
|
|
53
|
+
/**
|
|
54
|
+
* One poll of the running investigators. A settled one has its verdict applied (or its failure
|
|
55
|
+
* recorded) and answers `continue` so the handler can fill the slot; a queue with a free slot
|
|
56
|
+
* (a challenge added while the others ran) answers `continue` for the same reason. Otherwise the
|
|
57
|
+
* park holds.
|
|
58
|
+
*/
|
|
59
|
+
poll(workspaceId: string, instance: ExecutionInstance, step: PipelineStep): Promise<AdvanceResult>;
|
|
60
|
+
/** Claim an epoch for a queued entry and mark its finding `investigating`, persisted first. */
|
|
61
|
+
private claim;
|
|
62
|
+
/**
|
|
63
|
+
* Start (or, on a replay, re-address) a claimed entry's investigator. An inline executor answers
|
|
64
|
+
* with the verdict straight away. A dispatch that throws settles THAT challenge as `failed` with
|
|
65
|
+
* the reason: one finding's second opinion failing to start must not fail the review it sits in.
|
|
66
|
+
*/
|
|
67
|
+
private start;
|
|
68
|
+
/** Apply a finished investigator's verdict, meter its usage, and drop its entry. */
|
|
69
|
+
private settleResult;
|
|
70
|
+
/** Record a failed investigation on its finding (left exactly as it was) and drop its entry. */
|
|
71
|
+
private settleFailure;
|
|
72
|
+
/**
|
|
73
|
+
* The queue drained: hand the review back to the human.
|
|
74
|
+
*
|
|
75
|
+
* The status flip is written under CAS BEFORE the park. A human may add a challenge while the
|
|
76
|
+
* review is `challenging`, and `parkStepOnDecision` writes blind, so without the CAS a challenge
|
|
77
|
+
* landing between this advance's read and the park was overwritten: the request answered
|
|
78
|
+
* `queued` and the finding then stayed `queued` with no queue entry behind it. With it, the lost
|
|
79
|
+
* race throws `RunContendedError` and the driver re-drives on the state that holds the new entry,
|
|
80
|
+
* and a challenge arriving after the flip is refused until the park lands.
|
|
81
|
+
*/
|
|
82
|
+
private finish;
|
|
83
|
+
/**
|
|
84
|
+
* Keep the run's `updated_at` moving while investigators work quietly, throttled. Without it the
|
|
85
|
+
* stale-run sweeper reads a run that wrote nothing for a while as orphaned.
|
|
86
|
+
*/
|
|
87
|
+
private heartbeat;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=PrReviewChallengeQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrReviewChallengeQueue.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/PrReviewChallengeQueue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,KAAK,EAEL,iBAAiB,EACjB,MAAM,EACN,YAAY,EACb,MAAM,qBAAqB,CAAA;AAO5B,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAQjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAKpE,0DAA0D;AAC1D,MAAM,WAAW,0BAA0B;IACzC,eAAe,EAAE,eAAe,CAAA;IAChC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gDAAgD;IAChD,YAAY,EAAE,CACZ,GAAG,EAAE,kBAAkB,EACvB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,KAC/C,OAAO,CAAC;QAAE,GAAG,EAAE,cAAc,CAAA;KAAE,GAAG;QAAE,MAAM,EAAE,cAAc,CAAA;KAAE,CAAC,CAAA;IAClE,+CAA+C;IAC/C,WAAW,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;CACxE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,sBAAsB;IAGrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAE5B,YAA6B,IAAI,EAAE,0BAA0B,EAE5D;IAED;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAW3D;IAED;;;;;OAKG;IACG,IAAI,CACR,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,aAAa,CAAC,CAmCxB;IAED,+FAA+F;YACjF,KAAK;IAmBnB;;;;OAIG;YACW,KAAK;IA+DnB,oFAAoF;YACtE,YAAY;IAoB1B,gGAAgG;IAChG,OAAO,CAAC,aAAa;IAKrB;;;;;;;;;OASG;YACW,MAAM;IAUpB;;;OAGG;YACW,SAAS;CAYxB"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { ConflictError, describeError, getErrorMessage, noopLogger } from '@cat-factory/kernel';
|
|
2
|
+
import { MAX_CONCURRENT_CHALLENGE_INVESTIGATIONS, } from '@cat-factory/contracts';
|
|
3
|
+
import { CHALLENGE_INVESTIGATOR_KIND, runsDelegated, } from '@cat-factory/agents';
|
|
4
|
+
import { meterJobUsage } from './job-facts.js';
|
|
5
|
+
import { MAX_EVICTION_RECOVERIES, MAX_TRANSIENT_EVICTION_RECOVERIES } from './job.logic.js';
|
|
6
|
+
import { applyChallengeVerdict, failChallenge, renderChallengeInvestigatorFeedback, } from './prReview.logic.js';
|
|
7
|
+
import { claimDispatchEpoch } from './step-fold.logic.js';
|
|
8
|
+
/** How often a quiet queue refreshes the step's activity stamp, so the stale-run sweeper sees it. */
|
|
9
|
+
const ACTIVITY_HEARTBEAT_MS = 60_000;
|
|
10
|
+
/**
|
|
11
|
+
* The PR-review CHALLENGE QUEUE: every finding a human challenged gets its own read-only Challenge
|
|
12
|
+
* Investigator, at most {@link MAX_CONCURRENT_CHALLENGE_INVESTIGATIONS} at once, the rest starting in
|
|
13
|
+
* the order they were asked for as earlier ones settle.
|
|
14
|
+
*
|
|
15
|
+
* The investigators are HELPER jobs beside the `pr-reviewer` step, never the step's own job: one
|
|
16
|
+
* step can hold one job, and three running side by side is the point. So each queue entry
|
|
17
|
+
* (`step.challengeJobs`) carries what the step-level fields carry for the step's job, the claimed
|
|
18
|
+
* epoch and the attribution its poll re-supplies.
|
|
19
|
+
*
|
|
20
|
+
* While the queue is non-empty the review is `challenging` and the run parks on
|
|
21
|
+
* `awaiting_investigations`: the driver polls {@link poll} between sleeps. Every settled verdict
|
|
22
|
+
* answers `continue`, which sends the driver back through the step handler ({@link drive}) to fill
|
|
23
|
+
* the freed slot. That is also what keeps a long queue inside the poll budget: each settle starts a
|
|
24
|
+
* fresh park, so the budget bounds one wait for one verdict, never the whole queue.
|
|
25
|
+
*
|
|
26
|
+
* Replay safety rests on claim-before-effect: an entry's epoch is claimed and PERSISTED before its
|
|
27
|
+
* executor call, and the harness job id is derived from the epoch, so a replay that finds an epoch
|
|
28
|
+
* with no job id re-addresses the same job rather than starting another.
|
|
29
|
+
*/
|
|
30
|
+
export class PrReviewChallengeQueue {
|
|
31
|
+
deps;
|
|
32
|
+
log;
|
|
33
|
+
constructor(deps) {
|
|
34
|
+
this.deps = deps;
|
|
35
|
+
this.log = deps.logger ?? noopLogger;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The step handler's body while the review is `challenging`: re-address any claim a replay
|
|
39
|
+
* interrupted, start queued challenges into the free slots, and park on the running ones. With
|
|
40
|
+
* nothing left in the queue the review returns to `awaiting_selection` and parks for the human.
|
|
41
|
+
*/
|
|
42
|
+
async drive(ctx) {
|
|
43
|
+
const { workspaceId, instance, step } = ctx;
|
|
44
|
+
for (const job of claimedUnstarted(step))
|
|
45
|
+
await this.start(ctx, job);
|
|
46
|
+
for (;;) {
|
|
47
|
+
const next = queued(step)[0];
|
|
48
|
+
if (!next || running(step).length >= MAX_CONCURRENT_CHALLENGE_INVESTIGATIONS)
|
|
49
|
+
break;
|
|
50
|
+
await this.claim(workspaceId, instance, step, next);
|
|
51
|
+
await this.start(ctx, next);
|
|
52
|
+
}
|
|
53
|
+
if (!step.challengeJobs?.length)
|
|
54
|
+
return this.finish(workspaceId, instance, step);
|
|
55
|
+
return { kind: 'awaiting_investigations', stepIndex: instance.currentStep };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* One poll of the running investigators. A settled one has its verdict applied (or its failure
|
|
59
|
+
* recorded) and answers `continue` so the handler can fill the slot; a queue with a free slot
|
|
60
|
+
* (a challenge added while the others ran) answers `continue` for the same reason. Otherwise the
|
|
61
|
+
* park holds.
|
|
62
|
+
*/
|
|
63
|
+
async poll(workspaceId, instance, step) {
|
|
64
|
+
let settled = false;
|
|
65
|
+
// The jobs are independent, so their status reads run together; only the settling below has
|
|
66
|
+
// to be sequential, since each one rewrites `step.prReview`.
|
|
67
|
+
const started = running(step).filter((job) => job.jobId);
|
|
68
|
+
const updates = await Promise.all(started.map((job) => this.deps.pollSideJob(handleFor(job, workspaceId, instance))));
|
|
69
|
+
for (const [i, job] of started.entries()) {
|
|
70
|
+
const update = updates[i];
|
|
71
|
+
if (!update || update.state === 'running')
|
|
72
|
+
continue;
|
|
73
|
+
if (update.state === 'failed') {
|
|
74
|
+
// A failed job has spent its tokens all the same, as on the step-level failed poll.
|
|
75
|
+
await meterJobUsage(this.deps.spend, workspaceId, instance, step, {
|
|
76
|
+
...update,
|
|
77
|
+
...(job.model ? { model: job.model } : {}),
|
|
78
|
+
});
|
|
79
|
+
if (!requeueEvicted(step, job, update.evicted)) {
|
|
80
|
+
this.settleFailure(step, job, update.error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
await this.settleResult(workspaceId, instance, step, job, update.result);
|
|
85
|
+
}
|
|
86
|
+
settled = true;
|
|
87
|
+
}
|
|
88
|
+
if (settled) {
|
|
89
|
+
await this.deps.runStateMachine.persistAndEmit(workspaceId, instance);
|
|
90
|
+
return { kind: 'continue' };
|
|
91
|
+
}
|
|
92
|
+
if (queued(step).length && running(step).length < MAX_CONCURRENT_CHALLENGE_INVESTIGATIONS) {
|
|
93
|
+
return { kind: 'continue' };
|
|
94
|
+
}
|
|
95
|
+
if (!step.challengeJobs?.length)
|
|
96
|
+
return { kind: 'continue' };
|
|
97
|
+
await this.heartbeat(workspaceId, instance, step);
|
|
98
|
+
return { kind: 'awaiting_investigations', stepIndex: instance.currentStep };
|
|
99
|
+
}
|
|
100
|
+
/** Claim an epoch for a queued entry and mark its finding `investigating`, persisted first. */
|
|
101
|
+
async claim(workspaceId, instance, step, job) {
|
|
102
|
+
job.epoch = claimDispatchEpoch(instance, step, CHALLENGE_INVESTIGATOR_KIND);
|
|
103
|
+
const review = step.prReview;
|
|
104
|
+
step.prReview = {
|
|
105
|
+
...review,
|
|
106
|
+
findings: (review.findings ?? []).map((f) => f.id === job.findingId && f.challenge
|
|
107
|
+
? { ...f, challenge: { ...f.challenge, status: 'investigating' } }
|
|
108
|
+
: f),
|
|
109
|
+
};
|
|
110
|
+
await this.deps.runStateMachine.persistAndEmit(workspaceId, instance);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Start (or, on a replay, re-address) a claimed entry's investigator. An inline executor answers
|
|
114
|
+
* with the verdict straight away. A dispatch that throws settles THAT challenge as `failed` with
|
|
115
|
+
* the reason: one finding's second opinion failing to start must not fail the review it sits in.
|
|
116
|
+
*/
|
|
117
|
+
async start(ctx, job) {
|
|
118
|
+
const { workspaceId, instance, step } = ctx;
|
|
119
|
+
const review = step.prReview;
|
|
120
|
+
const finding = review.findings?.find((f) => f.id === job.findingId);
|
|
121
|
+
if (!finding) {
|
|
122
|
+
// Nothing can remove a finding while the review is `challenging`; dropping the entry rather
|
|
123
|
+
// than dispatching a brief-less investigator keeps a stale queue from wedging the step.
|
|
124
|
+
removeJob(step, job);
|
|
125
|
+
await this.deps.runStateMachine.persistAndEmit(workspaceId, instance);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
// A delegated executor is observed through a claim on the STEP (one per step), which a side
|
|
130
|
+
// job beside the step's own cannot hold, so a deployment that registers the investigator as
|
|
131
|
+
// delegated gets this challenge settled as failed with the reason, rather than the kind
|
|
132
|
+
// quietly running in the platform's own harness instead.
|
|
133
|
+
if (runsDelegated(CHALLENGE_INVESTIGATOR_KIND, this.deps.agentKindRegistry)) {
|
|
134
|
+
throw new ConflictError(`The \`${CHALLENGE_INVESTIGATOR_KIND}\` kind is registered on a delegated executor, ` +
|
|
135
|
+
'which challenge investigations do not support: they run beside the review step, and ' +
|
|
136
|
+
'a delegated dispatch is tracked on the step itself.');
|
|
137
|
+
}
|
|
138
|
+
const started = await this.deps.startSideJob(ctx, CHALLENGE_INVESTIGATOR_KIND, job.epoch ?? 0, (context) => {
|
|
139
|
+
context.priorOutputs = [
|
|
140
|
+
...context.priorOutputs,
|
|
141
|
+
{
|
|
142
|
+
agentKind: CHALLENGE_INVESTIGATOR_KIND,
|
|
143
|
+
output: renderChallengeInvestigatorFeedback(finding, job.question ?? null, review.summary),
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
});
|
|
147
|
+
if ('job' in started) {
|
|
148
|
+
job.jobId = started.job.jobId;
|
|
149
|
+
if (started.job.model)
|
|
150
|
+
job.model = started.job.model;
|
|
151
|
+
if (started.job.subscriptionTokenId) {
|
|
152
|
+
job.subscriptionTokenId = started.job.subscriptionTokenId;
|
|
153
|
+
}
|
|
154
|
+
if (started.job.initiatedByUserId)
|
|
155
|
+
job.initiatedByUserId = started.job.initiatedByUserId;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
await this.settleResult(workspaceId, instance, step, job, started.result);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.log.warn('challenge investigator dispatch failed', {
|
|
163
|
+
workspaceId,
|
|
164
|
+
executionId: instance.id,
|
|
165
|
+
findingId: job.findingId,
|
|
166
|
+
...describeError(error),
|
|
167
|
+
});
|
|
168
|
+
this.settleFailure(step, job, getErrorMessage(error));
|
|
169
|
+
}
|
|
170
|
+
await this.deps.runStateMachine.persistAndEmit(workspaceId, instance);
|
|
171
|
+
}
|
|
172
|
+
/** Apply a finished investigator's verdict, meter its usage, and drop its entry. */
|
|
173
|
+
async settleResult(workspaceId, instance, step, job, result) {
|
|
174
|
+
await meterJobUsage(this.deps.spend, workspaceId, instance, step, result);
|
|
175
|
+
const output = this.deps.agentKindRegistry
|
|
176
|
+
.structuredOutput(CHALLENGE_INVESTIGATOR_KIND)
|
|
177
|
+
?.safeParse(result.custom);
|
|
178
|
+
step.prReview = applyChallengeVerdict(step.prReview, job.findingId, job.question ?? null, output);
|
|
179
|
+
removeJob(step, job);
|
|
180
|
+
}
|
|
181
|
+
/** Record a failed investigation on its finding (left exactly as it was) and drop its entry. */
|
|
182
|
+
settleFailure(step, job, reason) {
|
|
183
|
+
step.prReview = failChallenge(step.prReview, job.findingId, job.question ?? null, reason);
|
|
184
|
+
removeJob(step, job);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The queue drained: hand the review back to the human.
|
|
188
|
+
*
|
|
189
|
+
* The status flip is written under CAS BEFORE the park. A human may add a challenge while the
|
|
190
|
+
* review is `challenging`, and `parkStepOnDecision` writes blind, so without the CAS a challenge
|
|
191
|
+
* landing between this advance's read and the park was overwritten: the request answered
|
|
192
|
+
* `queued` and the finding then stayed `queued` with no queue entry behind it. With it, the lost
|
|
193
|
+
* race throws `RunContendedError` and the driver re-drives on the state that holds the new entry,
|
|
194
|
+
* and a challenge arriving after the flip is refused until the park lands.
|
|
195
|
+
*/
|
|
196
|
+
async finish(workspaceId, instance, step) {
|
|
197
|
+
step.prReview = { ...step.prReview, status: 'awaiting_selection', resolution: null };
|
|
198
|
+
await this.deps.runStateMachine.casPersist(workspaceId, instance);
|
|
199
|
+
return this.deps.runStateMachine.parkStepOnDecision(workspaceId, instance, step);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Keep the run's `updated_at` moving while investigators work quietly, throttled. Without it the
|
|
203
|
+
* stale-run sweeper reads a run that wrote nothing for a while as orphaned.
|
|
204
|
+
*/
|
|
205
|
+
async heartbeat(workspaceId, instance, step) {
|
|
206
|
+
const now = this.deps.clock.now();
|
|
207
|
+
if (step.lastActivityAt != null && now - step.lastActivityAt < ACTIVITY_HEARTBEAT_MS) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
step.lastActivityAt = now;
|
|
211
|
+
await this.deps.runStateMachine.persistAndEmit(workspaceId, instance);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** Entries with a claimed epoch: running, or claimed and about to be (re-)started. */
|
|
215
|
+
function running(step) {
|
|
216
|
+
return (step.challengeJobs ?? []).filter((j) => j.epoch !== undefined);
|
|
217
|
+
}
|
|
218
|
+
/** Claimed entries a replay interrupted before the executor accepted them. */
|
|
219
|
+
function claimedUnstarted(step) {
|
|
220
|
+
return running(step).filter((j) => !j.jobId);
|
|
221
|
+
}
|
|
222
|
+
/** Entries still waiting for a slot, in the order they were asked for. */
|
|
223
|
+
function queued(step) {
|
|
224
|
+
return (step.challengeJobs ?? []).filter((j) => j.epoch === undefined);
|
|
225
|
+
}
|
|
226
|
+
function removeJob(step, job) {
|
|
227
|
+
step.challengeJobs = (step.challengeJobs ?? []).filter((j) => j !== job);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Put an investigator whose container was EVICTED back at the head of the queue, within the same
|
|
231
|
+
* budgets a step's own job gets (`MAX_EVICTION_RECOVERIES` for a crash, the larger
|
|
232
|
+
* `MAX_TRANSIENT_EVICTION_RECOVERIES` for infra churn). An eviction says nothing about the
|
|
233
|
+
* finding, so settling it as `failed` would hand the human a broken second opinion for a container
|
|
234
|
+
* blip. The re-queued entry claims a FRESH epoch when it restarts, because the evicted job's id may
|
|
235
|
+
* still be held by a pooled runner. Returns false once the budget is spent (or for a non-eviction
|
|
236
|
+
* failure), leaving the caller to settle the challenge as failed.
|
|
237
|
+
*/
|
|
238
|
+
function requeueEvicted(step, job, evicted) {
|
|
239
|
+
if (!evicted)
|
|
240
|
+
return false;
|
|
241
|
+
const budget = evicted === 'transient' ? MAX_TRANSIENT_EVICTION_RECOVERIES : MAX_EVICTION_RECOVERIES;
|
|
242
|
+
const recoveries = job.evictionRecoveries ?? 0;
|
|
243
|
+
if (recoveries >= budget)
|
|
244
|
+
return false;
|
|
245
|
+
const requeued = {
|
|
246
|
+
findingId: job.findingId,
|
|
247
|
+
question: job.question ?? null,
|
|
248
|
+
evictionRecoveries: recoveries + 1,
|
|
249
|
+
};
|
|
250
|
+
step.challengeJobs = [requeued, ...(step.challengeJobs ?? []).filter((j) => j !== job)];
|
|
251
|
+
const review = step.prReview;
|
|
252
|
+
step.prReview = {
|
|
253
|
+
...review,
|
|
254
|
+
findings: (review.findings ?? []).map((f) => f.id === job.findingId && f.challenge
|
|
255
|
+
? { ...f, challenge: { ...f.challenge, status: 'queued' } }
|
|
256
|
+
: f),
|
|
257
|
+
};
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
/** The poll handle of a running entry: the step-level `pollHandleFor`, for a side job. */
|
|
261
|
+
function handleFor(job, workspaceId, instance) {
|
|
262
|
+
return {
|
|
263
|
+
jobId: job.jobId,
|
|
264
|
+
runId: instance.id,
|
|
265
|
+
workspaceId,
|
|
266
|
+
blockId: instance.blockId,
|
|
267
|
+
agentKind: CHALLENGE_INVESTIGATOR_KIND,
|
|
268
|
+
...(job.model ? { model: job.model } : {}),
|
|
269
|
+
...(job.subscriptionTokenId ? { subscriptionTokenId: job.subscriptionTokenId } : {}),
|
|
270
|
+
...(job.initiatedByUserId ? { initiatedByUserId: job.initiatedByUserId } : {}),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=PrReviewChallengeQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrReviewChallengeQueue.js","sourceRoot":"","sources":["../../../src/modules/execution/PrReviewChallengeQueue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Block, ChallengePrReviewFindingInput, Clock, ExecutionInstance, ExecutionRepository, IdGenerator, PipelineStep, PrReviewAgentOutput,
|
|
1
|
+
import type { Block, ChallengePrReviewFindingInput, Clock, ExecutionInstance, ExecutionRepository, IdGenerator, PipelineStep, PrReviewAgentOutput, PrReviewStepState, ResolvePrReviewInput, WorkRunner } from '@cat-factory/kernel';
|
|
2
2
|
import type { NotificationService } from '../notifications/NotificationService.js';
|
|
3
3
|
import type { AdvanceResult } from './advance.js';
|
|
4
4
|
import type { RunStateMachine } from './RunStateMachine.js';
|
|
@@ -112,38 +112,27 @@ export declare class PrReviewController {
|
|
|
112
112
|
*/
|
|
113
113
|
dismissFinding(workspaceId: string, executionId: string, findingId: string): Promise<PrReviewStepState>;
|
|
114
114
|
/**
|
|
115
|
-
* Challenge a
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
115
|
+
* Challenge a finding: QUEUE it for a read-only Challenge Investigator (`queued` until a slot is
|
|
116
|
+
* free; see {@link PrReviewChallengeQueue}). An empty `question` uses the generic "dig deeper +
|
|
117
|
+
* validate" prompt.
|
|
118
|
+
*
|
|
119
|
+
* Accepted while the review is parked AND while other challenges are still running, which is what
|
|
120
|
+
* lets a human challenge several findings in a row. Only the first one re-arms the step and wakes
|
|
121
|
+
* the parked driver (the `fix`/`post` re-arm); later ones join the queue the running driver is
|
|
122
|
+
* already polling. Refused for an unknown finding, a retracted one, and one whose challenge is
|
|
123
|
+
* already in flight.
|
|
121
124
|
*/
|
|
122
125
|
challengeFinding(workspaceId: string, executionId: string, findingId: string, input: ChallengePrReviewFindingInput): Promise<PrReviewStepState>;
|
|
123
126
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* `revised*` field + records the justification (`amended`); `retracted` records the justification
|
|
128
|
-
* and auto-deselects the finding. Idempotent: a replay after the marker cleared (status no longer
|
|
129
|
-
* `challenging`) returns `null`, letting the normal `pr-review` interceptor re-park.
|
|
130
|
-
*/
|
|
131
|
-
recordChallengeResult(workspaceId: string, instance: ExecutionInstance, step: PipelineStep, output: PrReviewChallengeOutput | undefined): Promise<AdvanceResult | null>;
|
|
132
|
-
/**
|
|
133
|
-
* Settle a CHALLENGE whose read-only investigator job FAILED (a genuine crash / non-transient
|
|
134
|
-
* error, after any container-eviction retry budget is spent), RE-PARKING the review instead of
|
|
135
|
-
* failing the whole run. Run from the driver's failed-job path (the analogue of the human-test /
|
|
136
|
-
* visual-confirmation `onHelperComplete` failure branch): mark the challenged finding `failed`
|
|
137
|
-
* (carrying the reason), leave its body untouched, and re-park at `awaiting_selection` so the
|
|
138
|
-
* human can re-challenge or act on it — a non-critical second opinion crashing on ONE finding
|
|
139
|
-
* must never nuke the human's in-flight curation. Idempotent: a step no longer `challenging`
|
|
140
|
-
* (verdict already applied) returns null and falls through to the normal spine.
|
|
127
|
+
* The run's `pr-reviewer` step a challenge can be added to: the parked review (`parked: true`,
|
|
128
|
+
* the human is curating) or one whose challenge queue is already running. Throws
|
|
129
|
+
* {@link ConflictError} otherwise (still reviewing, resolved, or mid fix/post).
|
|
141
130
|
*/
|
|
142
|
-
|
|
131
|
+
private findChallengeableReview;
|
|
143
132
|
/**
|
|
144
133
|
* The run's parked `pr-reviewer` step (the human is curating findings) — the single lookup the
|
|
145
134
|
* `resolve` / `dismiss` / `challenge` actions share. Throws {@link ConflictError} when the run is
|
|
146
|
-
* no longer awaiting a selection (already resolved, or
|
|
135
|
+
* no longer awaiting a selection (already resolved, or challenges are still running).
|
|
147
136
|
*/
|
|
148
137
|
private findParkedReview;
|
|
149
138
|
/** The active PR-review state for a run's GET, or null when no `pr-reviewer` step carries one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrReviewController.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/PrReviewController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,KAAK,EACL,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,
|
|
1
|
+
{"version":3,"file":"PrReviewController.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/PrReviewController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,KAAK,EACL,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACX,MAAM,qBAAqB,CAAA;AAI5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAA;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,gBAAmB,CAAA;AAEnD,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,UAAU,EAAE,UAAU,CAAA;IACtB,2EAA2E;IAC3E,YAAY,EAAE,eAAe,CAAA;IAC7B,0DAA0D;IAC1D,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,kFAAkF;IAClF,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,sBAAsB,EAAI;IAE7D;;;;;;;;;;OAUG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,GAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAyF/B;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+CjF;IAED;;;;;;;;;;;;;OAaG;IACG,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAyE5B;IAED;;;;;OAKG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,CAAC,CAa5B;IAED;;;;;;;;;;OAUG;IACG,gBAAgB,CACpB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,iBAAiB,CAAC,CA+C5B;IAED;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAexB,kGAAkG;IAC5F,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAI3F;IAED;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAU1B,2EAA2E;YAC7D,kBAAkB;CAmBjC"}
|