@cat-factory/orchestration 0.35.1 → 0.36.1
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/container.d.ts +7 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +15 -0
- package/dist/container.js.map +1 -1
- package/dist/modules/execution/AgentContextBuilder.d.ts +22 -1
- package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -1
- package/dist/modules/execution/AgentContextBuilder.js +11 -2
- package/dist/modules/execution/AgentContextBuilder.js.map +1 -1
- package/dist/modules/execution/ExecutionService.d.ts +35 -2
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +92 -18
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/step-handler-registry.d.ts +40 -0
- package/dist/modules/execution/step-handler-registry.d.ts.map +1 -0
- package/dist/modules/execution/step-handler-registry.js +7 -0
- package/dist/modules/execution/step-handler-registry.js.map +1 -0
- package/package.json +10 -10
|
@@ -9,7 +9,7 @@ import { assertFound, ConflictError, getErrorMessage, isModelUsable, NotFoundErr
|
|
|
9
9
|
import { DEFAULT_MERGE_PRESET } from '@cat-factory/kernel';
|
|
10
10
|
import { CONFLICTS_AGENT_KIND, MERGER_AGENT_KIND, REQUIREMENTS_REVIEW_AGENT_KIND, CLARITY_REVIEW_AGENT_KIND, REQUIREMENTS_BRAINSTORM_AGENT_KIND, ARCHITECTURE_BRAINSTORM_AGENT_KIND, BUG_INVESTIGATOR_AGENT_KIND, TRACKER_AGENT_KIND, ANALYSIS_AGENT_KIND, TESTER_AGENT_KIND, UI_TESTER_AGENT_KIND, isTesterKind, HUMAN_TEST_AGENT_KIND, VISUAL_CONFIRM_AGENT_KIND, HUMAN_REVIEW_AGENT_KIND, BLUEPRINTS_AGENT_KIND, SPEC_WRITER_AGENT_KIND, } from './ci.logic.js';
|
|
11
11
|
import { DEFAULT_FOLLOW_UP_MAX_LOOPS, FOLLOW_UP_PRODUCER_KIND, followUpsToSendBack, hasPendingFollowUps, renderFollowUpRework, shouldLoopCoder, } from './followUp.logic.js';
|
|
12
|
-
import { AgentContextBuilder } from './AgentContextBuilder.js';
|
|
12
|
+
import { AgentContextBuilder, } from './AgentContextBuilder.js';
|
|
13
13
|
import { CompanionController } from './CompanionController.js';
|
|
14
14
|
import { inferTechnicalLabel } from './technical.logic.js';
|
|
15
15
|
import { MergeResolver } from './MergeResolver.js';
|
|
@@ -17,9 +17,10 @@ import { ReviewGateController } from './ReviewGateController.js';
|
|
|
17
17
|
import { TesterController } from './TesterController.js';
|
|
18
18
|
import { HumanTestController } from './HumanTestController.js';
|
|
19
19
|
import { VisualConfirmationController } from './VisualConfirmationController.js';
|
|
20
|
+
import { FALLTHROUGH_STEP_HANDLER_ORDER, } from './step-handler-registry.js';
|
|
20
21
|
import { getProvider, recordGateAttempt, registeredGateFactories, registeredStepResolverFactories, requireProvider, } from '@cat-factory/kernel';
|
|
21
22
|
import { isAsyncAgentExecutor } from '@cat-factory/kernel';
|
|
22
|
-
import { isDeployStep } from '@cat-factory/integrations';
|
|
23
|
+
import { isDeployStep, DEPLOYER_AGENT_KIND } from '@cat-factory/integrations';
|
|
23
24
|
import { dependenciesMet, descendantIds, serviceOf, unmetDependencies, } from '../board/board.logic.js';
|
|
24
25
|
import { requireWorkspace } from '@cat-factory/kernel';
|
|
25
26
|
import { planResumedSteps, planRestartFromStep } from './retry.logic.js';
|
|
@@ -147,7 +148,12 @@ export class ExecutionService {
|
|
|
147
148
|
* {@link stepResolverFor} and {@link StepCompletionResolver}.
|
|
148
149
|
*/
|
|
149
150
|
stepResolverCache;
|
|
150
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Lazily-built, order-sorted per-step-kind handler list. See {@link dispatchStepHandler}
|
|
153
|
+
* and {@link StepHandler}. Engine-internal (no public registration seam).
|
|
154
|
+
*/
|
|
155
|
+
stepHandlerCache;
|
|
156
|
+
constructor({ workspaceRepository, blockRepository, pipelineRepository, executionRepository, accountRepository, idGenerator, clock, agentExecutor, workRunner, executionEventPublisher, boardService, spendService, documentRepository, documentUrlResolver, taskRepository, requirementReviewRepository, requirementReviewService, kaizenScheduler, clarityReviewRepository, clarityReviewService, brainstormServices, brainstormSessionRepository, fragmentResolver, environmentProvisioning, environmentTeardown, branchUpdater, blueprintReconciler, notificationService, binaryArtifactStore, workspaceSettingsService, llmObservability, pullRequestMerger, mergePresetRepository, ticketTrackerProvider, issueWriteback, subscriptionActivationRepository, resolveWorkspaceModelDefault, resolveProviderCapabilities, localTestInfraSupported, resolveRunRepoContext, resolveTesterFallbackDefault, resolveRequireEnvironmentProvider, assertAgentBackendConfigured, runInitiatorScope, }) {
|
|
151
157
|
this.runInitiatorScope = runInitiatorScope ?? ((_initiatedBy, fn) => fn());
|
|
152
158
|
this.workspaceRepository = workspaceRepository;
|
|
153
159
|
this.blockRepository = blockRepository;
|
|
@@ -173,6 +179,7 @@ export class ExecutionService {
|
|
|
173
179
|
blockRepository,
|
|
174
180
|
accountRepository,
|
|
175
181
|
documents: documentRepository,
|
|
182
|
+
documentUrlResolver,
|
|
176
183
|
tasks: taskRepository,
|
|
177
184
|
requirementReviews: requirementReviewRepository,
|
|
178
185
|
clarityReviews: clarityReviewRepository,
|
|
@@ -810,21 +817,29 @@ export class ExecutionService {
|
|
|
810
817
|
if (step.gating?.enabled && !shouldRunGatedStep(block.estimate, step.gating)) {
|
|
811
818
|
return this.skipGatedStep(workspaceId, instance, step, isFinalStep);
|
|
812
819
|
}
|
|
813
|
-
//
|
|
814
|
-
//
|
|
815
|
-
//
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
820
|
+
// The fixed run-lifecycle preamble is done; hand the per-kind work to the
|
|
821
|
+
// engine-internal StepHandler registry (the first handler whose `canHandle` claims
|
|
822
|
+
// this step). See {@link dispatchStepHandler} / {@link runStepBody}.
|
|
823
|
+
return this.dispatchStepHandler({
|
|
824
|
+
workspaceId,
|
|
825
|
+
instance,
|
|
826
|
+
step,
|
|
827
|
+
block,
|
|
828
|
+
isFinalStep,
|
|
829
|
+
options,
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* The per-step-kind body run by the StepHandler registry once {@link stepInstance}'s
|
|
834
|
+
* preamble has completed. Phase 0 of the ExecutionService split: a single fallthrough
|
|
835
|
+
* handler delegates the ENTIRE body here unchanged (so dispatch is wired with zero
|
|
836
|
+
* behaviour change); later phases lift each branch below into its own handler and shrink
|
|
837
|
+
* this method until only the generic container/inline-agent tail remains.
|
|
838
|
+
*/
|
|
839
|
+
async runStepBody(ctx) {
|
|
840
|
+
const { workspaceId, instance, step, block, isFinalStep, options } = ctx;
|
|
841
|
+
// (The `deployer` and `tracker` steps are handled by their own StepHandlers — see
|
|
842
|
+
// {@link buildStepHandlerRegistry} — so they no longer branch here.)
|
|
828
843
|
// A `requirements-review` step runs the inline reviewer and parks for the dedicated
|
|
829
844
|
// review window, driving the iterative answer → incorporate → re-review loop. NOT a
|
|
830
845
|
// container/prose agent. Pass-through when the reviewer isn't wired. The clarity gate
|
|
@@ -2055,6 +2070,65 @@ export class ExecutionService {
|
|
|
2055
2070
|
* startup import side effect (see {@link gateFor} for the same caching caveat). See
|
|
2056
2071
|
* {@link StepCompletionResolver}.
|
|
2057
2072
|
*/
|
|
2073
|
+
/**
|
|
2074
|
+
* Dispatch a step (whose preamble already ran in {@link stepInstance}) to the first
|
|
2075
|
+
* registered {@link StepHandler} whose `canHandle` claims it, ordered by `order`. The
|
|
2076
|
+
* fallthrough handler claims everything, so this always resolves to a handler.
|
|
2077
|
+
*/
|
|
2078
|
+
dispatchStepHandler(ctx) {
|
|
2079
|
+
if (!this.stepHandlerCache)
|
|
2080
|
+
this.stepHandlerCache = this.buildStepHandlerRegistry();
|
|
2081
|
+
const handler = this.stepHandlerCache.find((h) => h.canHandle(ctx));
|
|
2082
|
+
// The fallthrough handler's `canHandle` is unconditional, so this is unreachable; it
|
|
2083
|
+
// exists only to satisfy the type and to fail loudly if that invariant is ever broken.
|
|
2084
|
+
if (!handler)
|
|
2085
|
+
throw new Error(`No step handler for agentKind "${ctx.step.agentKind}"`);
|
|
2086
|
+
return handler.handle(ctx);
|
|
2087
|
+
}
|
|
2088
|
+
/**
|
|
2089
|
+
* Build the order-sorted per-step-kind handler list, mirroring
|
|
2090
|
+
* {@link buildStepResolverRegistry} (built-ins constructed inline, closing over `this`).
|
|
2091
|
+
* Engine-internal: there is no public `registerStepHandler` seam. Phase 0 registers only
|
|
2092
|
+
* the generic fallthrough; later phases prepend more-specific handlers with lower `order`.
|
|
2093
|
+
*/
|
|
2094
|
+
buildStepHandlerRegistry() {
|
|
2095
|
+
const handlers = [
|
|
2096
|
+
// A `deployer` step provisions an ephemeral environment deterministically via the
|
|
2097
|
+
// provider — no LLM, no token usage — when the integration is wired. Unwired, its
|
|
2098
|
+
// `canHandle` is false so the step falls through to the generic agent path.
|
|
2099
|
+
{
|
|
2100
|
+
kind: DEPLOYER_AGENT_KIND,
|
|
2101
|
+
order: 100,
|
|
2102
|
+
canHandle: ({ step }) => !!this.environmentProvisioning && isDeployStep(step.agentKind),
|
|
2103
|
+
handle: async ({ workspaceId, instance, step, block, isFinalStep, options }) => {
|
|
2104
|
+
const result = await this.runDeployer(workspaceId, instance, block, options);
|
|
2105
|
+
return this.recordStepResult(workspaceId, instance, step, isFinalStep, result);
|
|
2106
|
+
},
|
|
2107
|
+
},
|
|
2108
|
+
// A `tracker` step files a GitHub issue / Jira ticket from the preceding `analysis`
|
|
2109
|
+
// output (the tech-debt pipeline) — no LLM of its own. It is a pass-through when no
|
|
2110
|
+
// tracker provider is wired or none is configured for the workspace (handled inside
|
|
2111
|
+
// {@link runTracker}, which still records a result), so it always claims the step.
|
|
2112
|
+
{
|
|
2113
|
+
kind: TRACKER_AGENT_KIND,
|
|
2114
|
+
order: 110,
|
|
2115
|
+
canHandle: ({ step }) => step.agentKind === TRACKER_AGENT_KIND,
|
|
2116
|
+
handle: async ({ workspaceId, instance, step, block, isFinalStep }) => {
|
|
2117
|
+
const result = await this.runTracker(workspaceId, instance, block);
|
|
2118
|
+
return this.recordStepResult(workspaceId, instance, step, isFinalStep, result);
|
|
2119
|
+
},
|
|
2120
|
+
},
|
|
2121
|
+
// The generic container/inline-agent fallthrough — claims every step no more-specific
|
|
2122
|
+
// handler did (today's `runStepBody` tail). Highest order so it always runs last.
|
|
2123
|
+
{
|
|
2124
|
+
kind: '*',
|
|
2125
|
+
order: FALLTHROUGH_STEP_HANDLER_ORDER,
|
|
2126
|
+
canHandle: () => true,
|
|
2127
|
+
handle: (ctx) => this.runStepBody(ctx),
|
|
2128
|
+
},
|
|
2129
|
+
];
|
|
2130
|
+
return handlers.sort((a, b) => a.order - b.order);
|
|
2131
|
+
}
|
|
2058
2132
|
stepResolverFor(agentKind) {
|
|
2059
2133
|
if (!this.stepResolverCache)
|
|
2060
2134
|
this.stepResolverCache = this.buildStepResolverRegistry();
|