@cat-factory/orchestration 0.6.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/LICENSE +21 -0
- package/dist/container.d.ts +460 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +657 -0
- package/dist/container.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/board/BoardService.d.ts +125 -0
- package/dist/modules/board/BoardService.d.ts.map +1 -0
- package/dist/modules/board/BoardService.js +496 -0
- package/dist/modules/board/BoardService.js.map +1 -0
- package/dist/modules/board/board.logic.d.ts +17 -0
- package/dist/modules/board/board.logic.d.ts.map +1 -0
- package/dist/modules/board/board.logic.js +51 -0
- package/dist/modules/board/board.logic.js.map +1 -0
- package/dist/modules/boardScan/BoardScanService.d.ts +35 -0
- package/dist/modules/boardScan/BoardScanService.d.ts.map +1 -0
- package/dist/modules/boardScan/BoardScanService.js +91 -0
- package/dist/modules/boardScan/BoardScanService.js.map +1 -0
- package/dist/modules/boardScan/board-scan.logic.d.ts +10 -0
- package/dist/modules/boardScan/board-scan.logic.d.ts.map +1 -0
- package/dist/modules/boardScan/board-scan.logic.js +26 -0
- package/dist/modules/boardScan/board-scan.logic.js.map +1 -0
- package/dist/modules/bootstrap/BootstrapService.d.ts +114 -0
- package/dist/modules/bootstrap/BootstrapService.d.ts.map +1 -0
- package/dist/modules/bootstrap/BootstrapService.js +516 -0
- package/dist/modules/bootstrap/BootstrapService.js.map +1 -0
- package/dist/modules/clarity/ClarityReviewService.d.ts +48 -0
- package/dist/modules/clarity/ClarityReviewService.d.ts.map +1 -0
- package/dist/modules/clarity/ClarityReviewService.js +63 -0
- package/dist/modules/clarity/ClarityReviewService.js.map +1 -0
- package/dist/modules/clarity/clarity.logic.d.ts +36 -0
- package/dist/modules/clarity/clarity.logic.d.ts.map +1 -0
- package/dist/modules/clarity/clarity.logic.js +98 -0
- package/dist/modules/clarity/clarity.logic.js.map +1 -0
- package/dist/modules/estimation/estimate.logic.d.ts +11 -0
- package/dist/modules/estimation/estimate.logic.d.ts.map +1 -0
- package/dist/modules/estimation/estimate.logic.js +37 -0
- package/dist/modules/estimation/estimate.logic.js.map +1 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts +114 -0
- package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -0
- package/dist/modules/execution/AgentContextBuilder.js +316 -0
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -0
- package/dist/modules/execution/CompanionController.d.ts +60 -0
- package/dist/modules/execution/CompanionController.d.ts.map +1 -0
- package/dist/modules/execution/CompanionController.js +216 -0
- package/dist/modules/execution/CompanionController.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +874 -0
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -0
- package/dist/modules/execution/ExecutionService.js +2921 -0
- package/dist/modules/execution/ExecutionService.js.map +1 -0
- package/dist/modules/execution/MergeResolver.d.ts +34 -0
- package/dist/modules/execution/MergeResolver.d.ts.map +1 -0
- package/dist/modules/execution/MergeResolver.js +81 -0
- package/dist/modules/execution/MergeResolver.js.map +1 -0
- package/dist/modules/execution/ReviewGateController.d.ts +163 -0
- package/dist/modules/execution/ReviewGateController.d.ts.map +1 -0
- package/dist/modules/execution/ReviewGateController.js +251 -0
- package/dist/modules/execution/ReviewGateController.js.map +1 -0
- package/dist/modules/execution/TesterController.d.ts +61 -0
- package/dist/modules/execution/TesterController.d.ts.map +1 -0
- package/dist/modules/execution/TesterController.js +215 -0
- package/dist/modules/execution/TesterController.js.map +1 -0
- package/dist/modules/execution/advance.d.ts +84 -0
- package/dist/modules/execution/advance.d.ts.map +1 -0
- package/dist/modules/execution/advance.js +2 -0
- package/dist/modules/execution/advance.js.map +1 -0
- package/dist/modules/execution/artifact-review.logic.d.ts +25 -0
- package/dist/modules/execution/artifact-review.logic.d.ts.map +1 -0
- package/dist/modules/execution/artifact-review.logic.js +39 -0
- package/dist/modules/execution/artifact-review.logic.js.map +1 -0
- package/dist/modules/execution/ci.logic.d.ts +101 -0
- package/dist/modules/execution/ci.logic.d.ts.map +1 -0
- package/dist/modules/execution/ci.logic.js +117 -0
- package/dist/modules/execution/ci.logic.js.map +1 -0
- package/dist/modules/execution/drive.d.ts +47 -0
- package/dist/modules/execution/drive.d.ts.map +1 -0
- package/dist/modules/execution/drive.js +112 -0
- package/dist/modules/execution/drive.js.map +1 -0
- package/dist/modules/execution/gates.d.ts +97 -0
- package/dist/modules/execution/gates.d.ts.map +1 -0
- package/dist/modules/execution/gates.js +2 -0
- package/dist/modules/execution/gates.js.map +1 -0
- package/dist/modules/execution/individualVendors.logic.d.ts +22 -0
- package/dist/modules/execution/individualVendors.logic.d.ts.map +1 -0
- package/dist/modules/execution/individualVendors.logic.js +33 -0
- package/dist/modules/execution/individualVendors.logic.js.map +1 -0
- package/dist/modules/execution/job.logic.d.ts +52 -0
- package/dist/modules/execution/job.logic.d.ts.map +1 -0
- package/dist/modules/execution/job.logic.js +56 -0
- package/dist/modules/execution/job.logic.js.map +1 -0
- package/dist/modules/execution/release.logic.d.ts +43 -0
- package/dist/modules/execution/release.logic.d.ts.map +1 -0
- package/dist/modules/execution/release.logic.js +49 -0
- package/dist/modules/execution/release.logic.js.map +1 -0
- package/dist/modules/execution/retry.logic.d.ts +40 -0
- package/dist/modules/execution/retry.logic.d.ts.map +1 -0
- package/dist/modules/execution/retry.logic.js +83 -0
- package/dist/modules/execution/retry.logic.js.map +1 -0
- package/dist/modules/execution/stepGating.logic.d.ts +15 -0
- package/dist/modules/execution/stepGating.logic.d.ts.map +1 -0
- package/dist/modules/execution/stepGating.logic.js +29 -0
- package/dist/modules/execution/stepGating.logic.js.map +1 -0
- package/dist/modules/execution/stepResolvers.d.ts +41 -0
- package/dist/modules/execution/stepResolvers.d.ts.map +1 -0
- package/dist/modules/execution/stepResolvers.js +2 -0
- package/dist/modules/execution/stepResolvers.js.map +1 -0
- package/dist/modules/execution/tester-infra.logic.d.ts +42 -0
- package/dist/modules/execution/tester-infra.logic.d.ts.map +1 -0
- package/dist/modules/execution/tester-infra.logic.js +46 -0
- package/dist/modules/execution/tester-infra.logic.js.map +1 -0
- package/dist/modules/merge/MergePresetService.d.ts +32 -0
- package/dist/modules/merge/MergePresetService.d.ts.map +1 -0
- package/dist/modules/merge/MergePresetService.js +109 -0
- package/dist/modules/merge/MergePresetService.js.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.d.ts +22 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.d.ts.map +1 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.js +28 -0
- package/dist/modules/modelDefaults/ModelDefaultsService.js.map +1 -0
- package/dist/modules/notifications/NotificationService.d.ts +74 -0
- package/dist/modules/notifications/NotificationService.d.ts.map +1 -0
- package/dist/modules/notifications/NotificationService.js +131 -0
- package/dist/modules/notifications/NotificationService.js.map +1 -0
- package/dist/modules/observability/LlmObservabilityService.d.ts +121 -0
- package/dist/modules/observability/LlmObservabilityService.d.ts.map +1 -0
- package/dist/modules/observability/LlmObservabilityService.js +140 -0
- package/dist/modules/observability/LlmObservabilityService.js.map +1 -0
- package/dist/modules/observability/observability.logic.d.ts +57 -0
- package/dist/modules/observability/observability.logic.d.ts.map +1 -0
- package/dist/modules/observability/observability.logic.js +186 -0
- package/dist/modules/observability/observability.logic.js.map +1 -0
- package/dist/modules/pipelines/PipelineService.d.ts +54 -0
- package/dist/modules/pipelines/PipelineService.d.ts.map +1 -0
- package/dist/modules/pipelines/PipelineService.js +226 -0
- package/dist/modules/pipelines/PipelineService.js.map +1 -0
- package/dist/modules/pipelines/pipelineShape.d.ts +53 -0
- package/dist/modules/pipelines/pipelineShape.d.ts.map +1 -0
- package/dist/modules/pipelines/pipelineShape.js +74 -0
- package/dist/modules/pipelines/pipelineShape.js.map +1 -0
- package/dist/modules/recurring/RecurringPipelineService.d.ts +76 -0
- package/dist/modules/recurring/RecurringPipelineService.d.ts.map +1 -0
- package/dist/modules/recurring/RecurringPipelineService.js +295 -0
- package/dist/modules/recurring/RecurringPipelineService.js.map +1 -0
- package/dist/modules/recurring/TrackerSettingsService.d.ts +16 -0
- package/dist/modules/recurring/TrackerSettingsService.d.ts.map +1 -0
- package/dist/modules/recurring/TrackerSettingsService.js +30 -0
- package/dist/modules/recurring/TrackerSettingsService.js.map +1 -0
- package/dist/modules/recurring/schedule.logic.d.ts +14 -0
- package/dist/modules/recurring/schedule.logic.d.ts.map +1 -0
- package/dist/modules/recurring/schedule.logic.js +85 -0
- package/dist/modules/recurring/schedule.logic.js.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.d.ts +38 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.d.ts.map +1 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.js +96 -0
- package/dist/modules/releaseHealth/ReleaseHealthService.js.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts +48 -0
- package/dist/modules/requirements/RequirementReviewService.d.ts.map +1 -0
- package/dist/modules/requirements/RequirementReviewService.js +83 -0
- package/dist/modules/requirements/RequirementReviewService.js.map +1 -0
- package/dist/modules/requirements/requirements.logic.d.ts +93 -0
- package/dist/modules/requirements/requirements.logic.d.ts.map +1 -0
- package/dist/modules/requirements/requirements.logic.js +203 -0
- package/dist/modules/requirements/requirements.logic.js.map +1 -0
- package/dist/modules/review/IterativeReviewService.d.ts +175 -0
- package/dist/modules/review/IterativeReviewService.d.ts.map +1 -0
- package/dist/modules/review/IterativeReviewService.js +327 -0
- package/dist/modules/review/IterativeReviewService.js.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.d.ts +20 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.d.ts.map +1 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.js +26 -0
- package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsService.js.map +1 -0
- package/dist/modules/services/ServiceMountService.d.ts +48 -0
- package/dist/modules/services/ServiceMountService.d.ts.map +1 -0
- package/dist/modules/services/ServiceMountService.js +90 -0
- package/dist/modules/services/ServiceMountService.js.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsService.d.ts +22 -0
- package/dist/modules/settings/WorkspaceSettingsService.d.ts.map +1 -0
- package/dist/modules/settings/WorkspaceSettingsService.js +50 -0
- package/dist/modules/settings/WorkspaceSettingsService.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { AgentFailureKind } from '@cat-factory/kernel';
|
|
2
|
+
export type AdvanceResult =
|
|
3
|
+
/** The step completed; the run is still running and has more steps. */
|
|
4
|
+
{
|
|
5
|
+
kind: 'continue';
|
|
6
|
+
}
|
|
7
|
+
/** The step raised a decision; the run is parked until it is resolved. */
|
|
8
|
+
| {
|
|
9
|
+
kind: 'awaiting_decision';
|
|
10
|
+
decisionId: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The step dispatched an asynchronous agent job (a container run). The run is
|
|
14
|
+
* parked: the durable driver polls {@link ExecutionService.pollAgentJob} between
|
|
15
|
+
* sleeps until the job finishes, then records its result and continues.
|
|
16
|
+
*/
|
|
17
|
+
| {
|
|
18
|
+
kind: 'awaiting_job';
|
|
19
|
+
jobId: string;
|
|
20
|
+
stepIndex: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A polling **gate** step (`ci` / `conflicts`) is gating the PR on its precheck.
|
|
24
|
+
* The run is parked: the durable driver sleeps, then polls
|
|
25
|
+
* {@link ExecutionService.pollGate} to re-run the precheck (which gate is resolved
|
|
26
|
+
* from the current step's `agentKind`). Polling stops the moment `pollGate` returns
|
|
27
|
+
* anything else — a passing precheck yields `continue`, a dispatched helper agent
|
|
28
|
+
* (ci-fixer / conflict-resolver) yields `awaiting_job`, exhaustion fails the run.
|
|
29
|
+
*/
|
|
30
|
+
| {
|
|
31
|
+
kind: 'awaiting_gate';
|
|
32
|
+
stepIndex: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A step finished in a terminal failure; the driver records it via the single
|
|
36
|
+
* `failRun` funnel and stops. `error` is the human-readable message. An inline
|
|
37
|
+
* gate that already knows the precise classification sets `failureKind` (e.g. an
|
|
38
|
+
* unparseable companion verdict → `'companion_rejected'`, a Tester gate that
|
|
39
|
+
* exhausted its fixer budget → `'agent'`) and may attach extended `detail` (e.g.
|
|
40
|
+
* the companion's raw reply); the driver records those instead of the generic
|
|
41
|
+
* `'job_failed'` container-failure framing. Defaults: `failureKind` →
|
|
42
|
+
* `'job_failed'`, `detail` → none. Inline gates MUST NOT call `failRun`
|
|
43
|
+
* themselves — returning this is the single path so the driver can't double-write
|
|
44
|
+
* and clobber the rich record.
|
|
45
|
+
*/
|
|
46
|
+
| {
|
|
47
|
+
kind: 'job_failed';
|
|
48
|
+
error: string;
|
|
49
|
+
failureKind?: AgentFailureKind;
|
|
50
|
+
detail?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A polled async job's container was evicted/crashed and the single automatic
|
|
54
|
+
* recovery (a fresh-container re-dispatch of the same step) has been spent, so the
|
|
55
|
+
* eviction is treated as deterministic. The driver fails the run as `evicted`.
|
|
56
|
+
* (A first eviction is recovered silently inside {@link ExecutionService.pollAgentJob}
|
|
57
|
+
* by re-dispatching and returning `continue`, so it never reaches the driver.)
|
|
58
|
+
*/
|
|
59
|
+
| {
|
|
60
|
+
kind: 'job_evicted';
|
|
61
|
+
error: string;
|
|
62
|
+
}
|
|
63
|
+
/** The final step completed; the run is finished. */
|
|
64
|
+
| {
|
|
65
|
+
kind: 'done';
|
|
66
|
+
}
|
|
67
|
+
/** The spend budget is exhausted; the run is paused until it frees up. */
|
|
68
|
+
| {
|
|
69
|
+
kind: 'paused';
|
|
70
|
+
}
|
|
71
|
+
/** Nothing to do — the run is absent or not running (replay/idempotent). */
|
|
72
|
+
| {
|
|
73
|
+
kind: 'noop';
|
|
74
|
+
};
|
|
75
|
+
/** Options controlling how a single advance behaves. */
|
|
76
|
+
export interface AdvanceOptions {
|
|
77
|
+
/**
|
|
78
|
+
* When true, an agent failure is rethrown instead of being swallowed into the
|
|
79
|
+
* step output. The durable driver sets this so a failed `step.do` retries; tests
|
|
80
|
+
* leave it false to preserve the "never wedge" behaviour.
|
|
81
|
+
*/
|
|
82
|
+
rethrowAgentErrors?: boolean;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=advance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advance.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/advance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAK3D,MAAM,MAAM,aAAa;AACvB,uEAAuE;AACrE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE;AACtB,0EAA0E;GACxE;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AACnD;;;;GAIG;GACD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC5D;;;;;;;GAOG;GACD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC9C;;;;;;;;;;;GAWG;GACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;AACxF;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACxC,qDAAqD;GACnD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;AAClB,0EAA0E;GACxE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE;AACpB,4EAA4E;GAC1E;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpB,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advance.js","sourceRoot":"","sources":["../../../src/modules/execution/advance.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AgentRunResult } from '@cat-factory/kernel';
|
|
2
|
+
/**
|
|
3
|
+
* The text a companion (and the SPA reader, and downstream steps via `priorOutputs`)
|
|
4
|
+
* should review for a finished producer step, or `undefined` when the step's own
|
|
5
|
+
* `output` already IS the work product.
|
|
6
|
+
*
|
|
7
|
+
* A producer that emits a STRUCTURED ARTIFACT (the spec doc, the blueprint tree, …)
|
|
8
|
+
* runs as a container agent: it commits the artifact to the repo and returns its raw
|
|
9
|
+
* Pi transcript summary as `result.output`. That summary is a useless thing to grade
|
|
10
|
+
* — it was what made the spec-companion declare every pass "unreviewable" and loop the
|
|
11
|
+
* producer to its rework cap on every spec task. So whenever a known artifact is
|
|
12
|
+
* present, the reviewable output is a deterministic rendering of the ARTIFACT itself.
|
|
13
|
+
*
|
|
14
|
+
* This is the universal seam: it is keyed off WHICH artifact the result carries, not
|
|
15
|
+
* off a specific `agentKind`, so every artifact-producing agent with a companion —
|
|
16
|
+
* today's spec-writer, and any future one — is covered by rendering its artifact here
|
|
17
|
+
* rather than by another per-agent special case. A producer whose work product is
|
|
18
|
+
* already prose (architect, researcher, the coder's PR summary) carries no artifact
|
|
19
|
+
* field and falls through to `undefined`, keeping its own `output`.
|
|
20
|
+
*
|
|
21
|
+
* Falls back to `undefined` when the artifact is present but won't parse (the in-repo
|
|
22
|
+
* files are committed regardless, so the raw summary is kept rather than nothing).
|
|
23
|
+
*/
|
|
24
|
+
export declare function reviewableArtifactOutput(result: AgentRunResult): string | undefined;
|
|
25
|
+
//# sourceMappingURL=artifact-review.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-review.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/artifact-review.logic.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAcnF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { renderBlueprintForReview, renderSpecForReview, safeParseBlueprintService, safeParseSpecDoc, } from '@cat-factory/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* The text a companion (and the SPA reader, and downstream steps via `priorOutputs`)
|
|
4
|
+
* should review for a finished producer step, or `undefined` when the step's own
|
|
5
|
+
* `output` already IS the work product.
|
|
6
|
+
*
|
|
7
|
+
* A producer that emits a STRUCTURED ARTIFACT (the spec doc, the blueprint tree, …)
|
|
8
|
+
* runs as a container agent: it commits the artifact to the repo and returns its raw
|
|
9
|
+
* Pi transcript summary as `result.output`. That summary is a useless thing to grade
|
|
10
|
+
* — it was what made the spec-companion declare every pass "unreviewable" and loop the
|
|
11
|
+
* producer to its rework cap on every spec task. So whenever a known artifact is
|
|
12
|
+
* present, the reviewable output is a deterministic rendering of the ARTIFACT itself.
|
|
13
|
+
*
|
|
14
|
+
* This is the universal seam: it is keyed off WHICH artifact the result carries, not
|
|
15
|
+
* off a specific `agentKind`, so every artifact-producing agent with a companion —
|
|
16
|
+
* today's spec-writer, and any future one — is covered by rendering its artifact here
|
|
17
|
+
* rather than by another per-agent special case. A producer whose work product is
|
|
18
|
+
* already prose (architect, researcher, the coder's PR summary) carries no artifact
|
|
19
|
+
* field and falls through to `undefined`, keeping its own `output`.
|
|
20
|
+
*
|
|
21
|
+
* Falls back to `undefined` when the artifact is present but won't parse (the in-repo
|
|
22
|
+
* files are committed regardless, so the raw summary is kept rather than nothing).
|
|
23
|
+
*/
|
|
24
|
+
export function reviewableArtifactOutput(result) {
|
|
25
|
+
if (result.spec !== undefined) {
|
|
26
|
+
const doc = safeParseSpecDoc(result.spec);
|
|
27
|
+
return doc ? renderSpecForReview(doc) : undefined;
|
|
28
|
+
}
|
|
29
|
+
if (result.blueprintService !== undefined) {
|
|
30
|
+
const service = safeParseBlueprintService(result.blueprintService);
|
|
31
|
+
return service ? renderBlueprintForReview(service) : undefined;
|
|
32
|
+
}
|
|
33
|
+
// `testReport` / `mergeAssessment` carry their own dedicated structured surfaces
|
|
34
|
+
// (the tester result view; the merger is the final step) and no prose companion
|
|
35
|
+
// grades them today. If one ever gains a companion, render it here — the seam, not
|
|
36
|
+
// the call sites, is where a new artifact type is taught to be reviewable.
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=artifact-review.logic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-review.logic.js","sourceRoot":"","sources":["../../../src/modules/execution/artifact-review.logic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,wBAAwB,CAAA;AAG/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAsB;IAC7D,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACzC,OAAO,GAAG,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnD,CAAC;IACD,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;QAClE,OAAO,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAChE,CAAC;IACD,iFAAiF;IACjF,gFAAgF;IAChF,mFAAmF;IACnF,2EAA2E;IAC3E,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { CiCheck } from '@cat-factory/kernel';
|
|
2
|
+
/** The agent kind of the special CI-gate step (polls checks, loops the ci-fixer). */
|
|
3
|
+
export declare const CI_AGENT_KIND = "ci";
|
|
4
|
+
/**
|
|
5
|
+
* The agent kind of the special requirements-review gate step. It is NOT a container /
|
|
6
|
+
* prose agent: the engine runs the inline reviewer (via the requirements module), parks
|
|
7
|
+
* the run for the dedicated review window, and drives the iterative answer → incorporate →
|
|
8
|
+
* re-review loop until it converges (or the human resolves a hit iteration cap). Passes
|
|
9
|
+
* through when the requirements module / reviewer model is not wired.
|
|
10
|
+
*/
|
|
11
|
+
export declare const REQUIREMENTS_REVIEW_AGENT_KIND = "requirements-review";
|
|
12
|
+
/**
|
|
13
|
+
* The agent kind of the special clarity-review gate step. Like the requirements reviewer
|
|
14
|
+
* it is an INLINE engine step (not a container/prose agent): the engine runs the inline
|
|
15
|
+
* clarity reviewer (via the clarity module), parks the run for the dedicated review
|
|
16
|
+
* window, and drives the iterative answer → incorporate → re-review loop until it
|
|
17
|
+
* converges. It triages a BUG REPORT for fixability rather than reviewing requirements
|
|
18
|
+
* completeness. Passes through when the clarity module / reviewer model is not wired.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CLARITY_REVIEW_AGENT_KIND = "clarity-review";
|
|
21
|
+
/**
|
|
22
|
+
* The agent kind of the read-only `bug-investigator` container agent. It clones the repo,
|
|
23
|
+
* reads the codebase from the raw bug report, and returns a prose report: an enriched bug
|
|
24
|
+
* report plus an OPTIONAL working hypothesis (omitted unless reasonably confident). It
|
|
25
|
+
* makes no commits and opens no PR — it runs the shared read-only `/explore` harness path
|
|
26
|
+
* (like `architect`/`analysis`). Its prose output feeds the downstream clarity reviewer
|
|
27
|
+
* (as the triage subject) and the coder (via `priorOutputs`, as a non-binding lead).
|
|
28
|
+
*/
|
|
29
|
+
export declare const BUG_INVESTIGATOR_AGENT_KIND = "bug-investigator";
|
|
30
|
+
/**
|
|
31
|
+
* The agent kind of the container agent that writes the service's unified, in-repo
|
|
32
|
+
* specification (`spec.json`). It runs BEFORE the coder and aggregates the collected
|
|
33
|
+
* requirements of every task under the service frame — including their acceptance
|
|
34
|
+
* scenarios — onto the implementation branch.
|
|
35
|
+
*/
|
|
36
|
+
export declare const SPEC_WRITER_AGENT_KIND = "spec-writer";
|
|
37
|
+
/** The agent kind of the container agent that fixes failing CI on the PR branch. */
|
|
38
|
+
export declare const CI_FIXER_AGENT_KIND = "ci-fixer";
|
|
39
|
+
/** The agent kind of the container agent that scores a PR for the merge decision. */
|
|
40
|
+
export declare const MERGER_AGENT_KIND = "merger";
|
|
41
|
+
/**
|
|
42
|
+
* The agent kind of the special `tester` gate step: a container agent that runs the
|
|
43
|
+
* project's tests (local docker-compose infra or an ephemeral env) and returns a
|
|
44
|
+
* structured report. On a withheld greenlight the engine loops the `fixer` agent
|
|
45
|
+
* with the report and re-tests — mirroring the CI gate / ci-fixer loop.
|
|
46
|
+
*/
|
|
47
|
+
export declare const TESTER_AGENT_KIND = "tester";
|
|
48
|
+
/**
|
|
49
|
+
* The agent kind of the container agent that applies fixes from a Tester's report to
|
|
50
|
+
* the PR head branch and pushes them back (no new PR), looping with the Tester.
|
|
51
|
+
*/
|
|
52
|
+
export declare const FIXER_AGENT_KIND = "fixer";
|
|
53
|
+
/**
|
|
54
|
+
* The agent kind of the special pre-merge gate step: it checks whether the PR can
|
|
55
|
+
* be merged and, on a conflict, loops the conflict-resolver — mirroring the CI gate.
|
|
56
|
+
*/
|
|
57
|
+
export declare const CONFLICTS_AGENT_KIND = "conflicts";
|
|
58
|
+
/**
|
|
59
|
+
* The agent kind of the container agent that resolves merge conflicts: it merges
|
|
60
|
+
* the base into the PR branch, fixes the conflicts and pushes back onto the branch.
|
|
61
|
+
*/
|
|
62
|
+
export declare const CONFLICT_RESOLVER_AGENT_KIND = "conflict-resolver";
|
|
63
|
+
/**
|
|
64
|
+
* The agent kind of the read-only code-analysis agent that opens the tech-debt
|
|
65
|
+
* recurring pipeline: it inspects the repo and emits a prioritized markdown report
|
|
66
|
+
* (no commits). Reuses the generic container run path — no special engine handling.
|
|
67
|
+
*/
|
|
68
|
+
export declare const ANALYSIS_AGENT_KIND = "analysis";
|
|
69
|
+
/**
|
|
70
|
+
* The agent kind of the special `tracker` step: a non-LLM step that files a GitHub
|
|
71
|
+
* issue / Jira ticket from the preceding `analysis` output before implementation,
|
|
72
|
+
* mirroring the special handling of the `ci` gate. Passes through when no tracker
|
|
73
|
+
* is configured for the workspace.
|
|
74
|
+
*/
|
|
75
|
+
export declare const TRACKER_AGENT_KIND = "tracker";
|
|
76
|
+
/**
|
|
77
|
+
* The aggregate CI verdict for a PR head commit, derived from its check runs:
|
|
78
|
+
* - `none` — no checks reported (nothing to gate; treated as green).
|
|
79
|
+
* - `pending` — at least one check is still queued/in-progress and none failed.
|
|
80
|
+
* - `success` — every completed check succeeded (or was neutral/skipped) and none pending.
|
|
81
|
+
* - `failure` — at least one check concluded in a non-success terminal state.
|
|
82
|
+
*/
|
|
83
|
+
export type CiVerdict = 'none' | 'pending' | 'success' | 'failure';
|
|
84
|
+
/**
|
|
85
|
+
* Reduce a set of check runs to a single verdict. A failure dominates (one red
|
|
86
|
+
* check fails the gate); otherwise a still-running check keeps it pending; with
|
|
87
|
+
* everything completed-and-passing it is green; with no checks at all it is
|
|
88
|
+
* `none` (the engine treats `none` as green so a repo with no CI configured isn't
|
|
89
|
+
* blocked forever).
|
|
90
|
+
*/
|
|
91
|
+
export declare function aggregateCi(checks: CiCheck[]): CiVerdict;
|
|
92
|
+
/** Whether a verdict means the gate may advance (green or nothing to gate). */
|
|
93
|
+
export declare function isCiGreen(verdict: CiVerdict): boolean;
|
|
94
|
+
/** The completed-and-non-passing checks behind a `failure` verdict. */
|
|
95
|
+
export declare function listFailingChecks(checks: CiCheck[]): {
|
|
96
|
+
name: string;
|
|
97
|
+
conclusion: string | null;
|
|
98
|
+
}[];
|
|
99
|
+
/** A short, human-readable summary of the failing checks, for the step output / notification. */
|
|
100
|
+
export declare function describeFailingChecks(checks: CiCheck[]): string;
|
|
101
|
+
//# sourceMappingURL=ci.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/ci.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,qFAAqF;AACrF,eAAO,MAAM,aAAa,OAAO,CAAA;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,wBAAwB,CAAA;AAEnE;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,mBAAmB,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,qBAAqB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,gBAAgB,CAAA;AAEnD,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,aAAa,CAAA;AAE7C,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,WAAW,CAAA;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,WAAW,CAAA;AAEzC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAA;AAE/C;;;GAGG;AACH,eAAO,MAAM,4BAA4B,sBAAsB,CAAA;AAE/D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,aAAa,CAAA;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,YAAY,CAAA;AAE3C;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAKlE;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,CAYxD;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAErD;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,CAI/C;AAED,iGAAiG;AACjG,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAK/D"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** The agent kind of the special CI-gate step (polls checks, loops the ci-fixer). */
|
|
2
|
+
export const CI_AGENT_KIND = 'ci';
|
|
3
|
+
/**
|
|
4
|
+
* The agent kind of the special requirements-review gate step. It is NOT a container /
|
|
5
|
+
* prose agent: the engine runs the inline reviewer (via the requirements module), parks
|
|
6
|
+
* the run for the dedicated review window, and drives the iterative answer → incorporate →
|
|
7
|
+
* re-review loop until it converges (or the human resolves a hit iteration cap). Passes
|
|
8
|
+
* through when the requirements module / reviewer model is not wired.
|
|
9
|
+
*/
|
|
10
|
+
export const REQUIREMENTS_REVIEW_AGENT_KIND = 'requirements-review';
|
|
11
|
+
/**
|
|
12
|
+
* The agent kind of the special clarity-review gate step. Like the requirements reviewer
|
|
13
|
+
* it is an INLINE engine step (not a container/prose agent): the engine runs the inline
|
|
14
|
+
* clarity reviewer (via the clarity module), parks the run for the dedicated review
|
|
15
|
+
* window, and drives the iterative answer → incorporate → re-review loop until it
|
|
16
|
+
* converges. It triages a BUG REPORT for fixability rather than reviewing requirements
|
|
17
|
+
* completeness. Passes through when the clarity module / reviewer model is not wired.
|
|
18
|
+
*/
|
|
19
|
+
export const CLARITY_REVIEW_AGENT_KIND = 'clarity-review';
|
|
20
|
+
/**
|
|
21
|
+
* The agent kind of the read-only `bug-investigator` container agent. It clones the repo,
|
|
22
|
+
* reads the codebase from the raw bug report, and returns a prose report: an enriched bug
|
|
23
|
+
* report plus an OPTIONAL working hypothesis (omitted unless reasonably confident). It
|
|
24
|
+
* makes no commits and opens no PR — it runs the shared read-only `/explore` harness path
|
|
25
|
+
* (like `architect`/`analysis`). Its prose output feeds the downstream clarity reviewer
|
|
26
|
+
* (as the triage subject) and the coder (via `priorOutputs`, as a non-binding lead).
|
|
27
|
+
*/
|
|
28
|
+
export const BUG_INVESTIGATOR_AGENT_KIND = 'bug-investigator';
|
|
29
|
+
/**
|
|
30
|
+
* The agent kind of the container agent that writes the service's unified, in-repo
|
|
31
|
+
* specification (`spec.json`). It runs BEFORE the coder and aggregates the collected
|
|
32
|
+
* requirements of every task under the service frame — including their acceptance
|
|
33
|
+
* scenarios — onto the implementation branch.
|
|
34
|
+
*/
|
|
35
|
+
export const SPEC_WRITER_AGENT_KIND = 'spec-writer';
|
|
36
|
+
/** The agent kind of the container agent that fixes failing CI on the PR branch. */
|
|
37
|
+
export const CI_FIXER_AGENT_KIND = 'ci-fixer';
|
|
38
|
+
/** The agent kind of the container agent that scores a PR for the merge decision. */
|
|
39
|
+
export const MERGER_AGENT_KIND = 'merger';
|
|
40
|
+
/**
|
|
41
|
+
* The agent kind of the special `tester` gate step: a container agent that runs the
|
|
42
|
+
* project's tests (local docker-compose infra or an ephemeral env) and returns a
|
|
43
|
+
* structured report. On a withheld greenlight the engine loops the `fixer` agent
|
|
44
|
+
* with the report and re-tests — mirroring the CI gate / ci-fixer loop.
|
|
45
|
+
*/
|
|
46
|
+
export const TESTER_AGENT_KIND = 'tester';
|
|
47
|
+
/**
|
|
48
|
+
* The agent kind of the container agent that applies fixes from a Tester's report to
|
|
49
|
+
* the PR head branch and pushes them back (no new PR), looping with the Tester.
|
|
50
|
+
*/
|
|
51
|
+
export const FIXER_AGENT_KIND = 'fixer';
|
|
52
|
+
/**
|
|
53
|
+
* The agent kind of the special pre-merge gate step: it checks whether the PR can
|
|
54
|
+
* be merged and, on a conflict, loops the conflict-resolver — mirroring the CI gate.
|
|
55
|
+
*/
|
|
56
|
+
export const CONFLICTS_AGENT_KIND = 'conflicts';
|
|
57
|
+
/**
|
|
58
|
+
* The agent kind of the container agent that resolves merge conflicts: it merges
|
|
59
|
+
* the base into the PR branch, fixes the conflicts and pushes back onto the branch.
|
|
60
|
+
*/
|
|
61
|
+
export const CONFLICT_RESOLVER_AGENT_KIND = 'conflict-resolver';
|
|
62
|
+
/**
|
|
63
|
+
* The agent kind of the read-only code-analysis agent that opens the tech-debt
|
|
64
|
+
* recurring pipeline: it inspects the repo and emits a prioritized markdown report
|
|
65
|
+
* (no commits). Reuses the generic container run path — no special engine handling.
|
|
66
|
+
*/
|
|
67
|
+
export const ANALYSIS_AGENT_KIND = 'analysis';
|
|
68
|
+
/**
|
|
69
|
+
* The agent kind of the special `tracker` step: a non-LLM step that files a GitHub
|
|
70
|
+
* issue / Jira ticket from the preceding `analysis` output before implementation,
|
|
71
|
+
* mirroring the special handling of the `ci` gate. Passes through when no tracker
|
|
72
|
+
* is configured for the workspace.
|
|
73
|
+
*/
|
|
74
|
+
export const TRACKER_AGENT_KIND = 'tracker';
|
|
75
|
+
/** Conclusions GitHub reports for a *completed* check that are NOT failures. */
|
|
76
|
+
const PASSING_CONCLUSIONS = new Set(['success', 'neutral', 'skipped']);
|
|
77
|
+
/**
|
|
78
|
+
* Reduce a set of check runs to a single verdict. A failure dominates (one red
|
|
79
|
+
* check fails the gate); otherwise a still-running check keeps it pending; with
|
|
80
|
+
* everything completed-and-passing it is green; with no checks at all it is
|
|
81
|
+
* `none` (the engine treats `none` as green so a repo with no CI configured isn't
|
|
82
|
+
* blocked forever).
|
|
83
|
+
*/
|
|
84
|
+
export function aggregateCi(checks) {
|
|
85
|
+
if (checks.length === 0)
|
|
86
|
+
return 'none';
|
|
87
|
+
let pending = false;
|
|
88
|
+
for (const check of checks) {
|
|
89
|
+
if (check.status !== 'completed') {
|
|
90
|
+
pending = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const conclusion = check.conclusion ?? '';
|
|
94
|
+
if (!PASSING_CONCLUSIONS.has(conclusion))
|
|
95
|
+
return 'failure';
|
|
96
|
+
}
|
|
97
|
+
return pending ? 'pending' : 'success';
|
|
98
|
+
}
|
|
99
|
+
/** Whether a verdict means the gate may advance (green or nothing to gate). */
|
|
100
|
+
export function isCiGreen(verdict) {
|
|
101
|
+
return verdict === 'success' || verdict === 'none';
|
|
102
|
+
}
|
|
103
|
+
/** The completed-and-non-passing checks behind a `failure` verdict. */
|
|
104
|
+
export function listFailingChecks(checks) {
|
|
105
|
+
return checks
|
|
106
|
+
.filter((c) => c.status === 'completed' && !PASSING_CONCLUSIONS.has(c.conclusion ?? ''))
|
|
107
|
+
.map((c) => ({ name: c.name, conclusion: c.conclusion }));
|
|
108
|
+
}
|
|
109
|
+
/** A short, human-readable summary of the failing checks, for the step output / notification. */
|
|
110
|
+
export function describeFailingChecks(checks) {
|
|
111
|
+
const failing = listFailingChecks(checks);
|
|
112
|
+
if (failing.length === 0)
|
|
113
|
+
return 'CI reported a failure.';
|
|
114
|
+
const names = failing.map((c) => `${c.name} (${c.conclusion ?? 'failure'})`).join(', ');
|
|
115
|
+
return `Failing checks: ${names}`;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=ci.logic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.logic.js","sourceRoot":"","sources":["../../../src/modules/execution/ci.logic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ExecutionService } from './ExecutionService.js';
|
|
2
|
+
/** Poll cadence + budgets for the gates a parked run waits on. */
|
|
3
|
+
export interface DriveConfig {
|
|
4
|
+
jobPollIntervalMs: number;
|
|
5
|
+
jobMaxPolls: number;
|
|
6
|
+
jobPollFailureTolerance: number;
|
|
7
|
+
ciPollIntervalMs: number;
|
|
8
|
+
ciMaxPolls: number;
|
|
9
|
+
}
|
|
10
|
+
/** Minimal structured logger the driver needs (pino is structurally compatible). */
|
|
11
|
+
export interface DriveLogger {
|
|
12
|
+
info(obj: unknown, msg?: string): void;
|
|
13
|
+
}
|
|
14
|
+
/** Runtime seams the driver loop needs; both have inert defaults. */
|
|
15
|
+
export interface DriveOptions {
|
|
16
|
+
/**
|
|
17
|
+
* How to wait between gate polls. Orchestration is runtime-neutral (no timers), so
|
|
18
|
+
* the default resolves INSTANTLY; the Node service injects a real `setTimeout` sleep
|
|
19
|
+
* (see its `drive.ts` wrapper), and the conformance harness keeps the instant default
|
|
20
|
+
* to drive the deterministic fakes without real waiting.
|
|
21
|
+
*/
|
|
22
|
+
sleep?: (ms: number) => Promise<void>;
|
|
23
|
+
/** Where to log lifecycle breadcrumbs. Defaults to a no-op. */
|
|
24
|
+
log?: DriveLogger;
|
|
25
|
+
}
|
|
26
|
+
/** What a drive ended on, so the runner can schedule follow-up work (a decision timeout). */
|
|
27
|
+
export interface DriveOutcome {
|
|
28
|
+
/** Set when the run parked awaiting a human decision/approval with this id. */
|
|
29
|
+
parkedDecisionId?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Drive one run to a standstill. The runtime-neutral driver loop: it contains NO
|
|
33
|
+
* business logic — every decision lives in {@link ExecutionService} — and uses plain
|
|
34
|
+
* async sleeps, so it is the exact analogue of the Cloudflare ExecutionWorkflow (which
|
|
35
|
+
* wraps the same advance/poll calls in durable steps). The Node service's pg-boss
|
|
36
|
+
* worker runs it with a real sleep + pino logger; the cross-runtime conformance harness
|
|
37
|
+
* runs the SAME function (instant sleep, no-op log) against each facade's real store, so
|
|
38
|
+
* the suite exercises the production driver rather than a hand-rolled twin — which is how
|
|
39
|
+
* the companion-failure clobber (a second `failRun` overwriting the rich record with a
|
|
40
|
+
* generic one) once slipped past the suite.
|
|
41
|
+
*
|
|
42
|
+
* On a human decision it parks (returning the id so the caller can arm a timeout); the
|
|
43
|
+
* pg-boss runner re-enqueues an advance when the decision is resolved. All run state
|
|
44
|
+
* lives in the store, so a re-run after a crash simply reads the current state.
|
|
45
|
+
*/
|
|
46
|
+
export declare function driveExecution(exec: ExecutionService, workspaceId: string, executionId: string, cfg: DriveConfig, opts?: DriveOptions): Promise<DriveOutcome>;
|
|
47
|
+
//# sourceMappingURL=drive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/drive.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAE7D,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvC;AAED,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,+DAA+D;IAC/D,GAAG,CAAC,EAAE,WAAW,CAAA;CAClB;AAED,6FAA6F;AAC7F,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,gBAAgB,EACtB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,YAAY,CAAC,CAkHvB"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const instantSleep = () => Promise.resolve();
|
|
2
|
+
const noopLogger = { info() { } };
|
|
3
|
+
/**
|
|
4
|
+
* Drive one run to a standstill. The runtime-neutral driver loop: it contains NO
|
|
5
|
+
* business logic — every decision lives in {@link ExecutionService} — and uses plain
|
|
6
|
+
* async sleeps, so it is the exact analogue of the Cloudflare ExecutionWorkflow (which
|
|
7
|
+
* wraps the same advance/poll calls in durable steps). The Node service's pg-boss
|
|
8
|
+
* worker runs it with a real sleep + pino logger; the cross-runtime conformance harness
|
|
9
|
+
* runs the SAME function (instant sleep, no-op log) against each facade's real store, so
|
|
10
|
+
* the suite exercises the production driver rather than a hand-rolled twin — which is how
|
|
11
|
+
* the companion-failure clobber (a second `failRun` overwriting the rich record with a
|
|
12
|
+
* generic one) once slipped past the suite.
|
|
13
|
+
*
|
|
14
|
+
* On a human decision it parks (returning the id so the caller can arm a timeout); the
|
|
15
|
+
* pg-boss runner re-enqueues an advance when the decision is resolved. All run state
|
|
16
|
+
* lives in the store, so a re-run after a crash simply reads the current state.
|
|
17
|
+
*/
|
|
18
|
+
export async function driveExecution(exec, workspaceId, executionId, cfg, opts = {}) {
|
|
19
|
+
const sleep = opts.sleep ?? instantSleep;
|
|
20
|
+
const log = opts.log ?? noopLogger;
|
|
21
|
+
const fail = (message, kind = 'agent', detail = null) => exec.failRun(workspaceId, executionId, message, kind, detail);
|
|
22
|
+
// Poll a parked gate (job / CI / conflicts) until it yields a non-awaiting result
|
|
23
|
+
// or the budget is spent. Tolerates a bounded run of status-read failures.
|
|
24
|
+
const pollUntil = async (awaiting, poll, intervalMs, maxPolls, label, onExhausted) => {
|
|
25
|
+
let readFailures = 0;
|
|
26
|
+
for (let p = 0; p < maxPolls; p++) {
|
|
27
|
+
await sleep(intervalMs);
|
|
28
|
+
let result;
|
|
29
|
+
try {
|
|
30
|
+
result = await poll();
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
readFailures += 1;
|
|
34
|
+
if (readFailures >= cfg.jobPollFailureTolerance) {
|
|
35
|
+
await fail(`${label} status was unreadable (${readFailures} polls)`, 'timeout');
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
readFailures = 0;
|
|
41
|
+
if (result.kind !== awaiting)
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
// Budget spent. A gate may resolve exhaustion itself (a watch gate PASSES rather than
|
|
45
|
+
// timing out) — let it; otherwise fail the run as a generic timeout.
|
|
46
|
+
if (onExhausted)
|
|
47
|
+
return onExhausted();
|
|
48
|
+
await fail(`${label} did not settle within its polling budget`, 'timeout');
|
|
49
|
+
return null;
|
|
50
|
+
};
|
|
51
|
+
for (;;) {
|
|
52
|
+
let result;
|
|
53
|
+
try {
|
|
54
|
+
result = await exec.advanceInstance(workspaceId, executionId, { rethrowAgentErrors: true });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
await fail(error instanceof Error ? error.message : String(error));
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
// Drain whatever gate the step parked on. A gate poll can resolve to a DIFFERENT
|
|
61
|
+
// gate — e.g. a `ci` step that finds CI red dispatches a `ci-fixer` and returns
|
|
62
|
+
// `awaiting_job` — so loop until the result is no longer an awaiting_* gate rather
|
|
63
|
+
// than relying on the next `advanceInstance` to re-establish the poll (which is why
|
|
64
|
+
// the order of these checks must not matter). `pollUntil` itself is bounded, so the
|
|
65
|
+
// outer guard only backstops a pathological gate↔gate ping-pong.
|
|
66
|
+
let gateHops = 0;
|
|
67
|
+
const MAX_GATE_HOPS = 64;
|
|
68
|
+
while (gateHops++ < MAX_GATE_HOPS) {
|
|
69
|
+
if (result.kind === 'awaiting_job') {
|
|
70
|
+
const next = await pollUntil('awaiting_job', () => exec.pollAgentJob(workspaceId, executionId), cfg.jobPollIntervalMs, cfg.jobMaxPolls, 'Implementation job');
|
|
71
|
+
if (!next)
|
|
72
|
+
return {};
|
|
73
|
+
result = next;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// A polling gate step (`ci` / `conflicts`): re-run its precheck between sleeps;
|
|
77
|
+
// which gate is resolved inside `pollGate` from the current step, so one branch
|
|
78
|
+
// drives both.
|
|
79
|
+
if (result.kind === 'awaiting_gate') {
|
|
80
|
+
const next = await pollUntil('awaiting_gate', () => exec.pollGate(workspaceId, executionId), cfg.ciPollIntervalMs, cfg.ciMaxPolls, 'Gate precheck', () => exec.resolveGatePollExhaustion(workspaceId, executionId));
|
|
81
|
+
if (!next)
|
|
82
|
+
return {};
|
|
83
|
+
result = next;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (result.kind === 'job_failed') {
|
|
89
|
+
// Single `failRun` funnel for a terminal step failure. An inline gate that already
|
|
90
|
+
// knows the precise classification + diagnostic carries them on the result
|
|
91
|
+
// (`failureKind`/`detail`) — e.g. an unparseable companion verdict
|
|
92
|
+
// (`companion_rejected`, with its raw reply as detail) — so the run records the
|
|
93
|
+
// accurate kind, hint and detail instead of a generic "container reported a
|
|
94
|
+
// failure". Defaults to `job_failed` for a genuine container-job failure.
|
|
95
|
+
await fail(result.error, result.failureKind ?? 'job_failed', result.detail ?? null);
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
if (result.kind === 'job_evicted') {
|
|
99
|
+
await fail(result.error, 'evicted');
|
|
100
|
+
return {};
|
|
101
|
+
}
|
|
102
|
+
// done / noop / paused: stop. awaiting_decision: park (resumed on signalDecision).
|
|
103
|
+
if (result.kind === 'done' || result.kind === 'noop' || result.kind === 'paused')
|
|
104
|
+
return {};
|
|
105
|
+
if (result.kind === 'awaiting_decision') {
|
|
106
|
+
log.info({ workspaceId, executionId, decisionId: result.decisionId }, 'run parked on decision');
|
|
107
|
+
return { parkedDecisionId: result.decisionId };
|
|
108
|
+
}
|
|
109
|
+
// 'continue': loop and advance the next step.
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=drive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive.js","sourceRoot":"","sources":["../../../src/modules/execution/drive.ts"],"names":[],"mappings":"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"}
|