@cat-factory/orchestration 0.129.0 → 0.129.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/execution/RunDispatcher.d.ts +1 -102
- package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
- package/dist/modules/execution/RunDispatcher.js +25 -232
- package/dist/modules/execution/RunDispatcher.js.map +1 -1
- package/dist/modules/execution/RunRepoOpsController.d.ts +129 -0
- package/dist/modules/execution/RunRepoOpsController.d.ts.map +1 -0
- package/dist/modules/execution/RunRepoOpsController.js +261 -0
- package/dist/modules/execution/RunRepoOpsController.js.map +1 -0
- package/dist/modules/execution/prReview.logic.d.ts +11 -1
- package/dist/modules/execution/prReview.logic.d.ts.map +1 -1
- package/dist/modules/execution/prReview.logic.js +21 -0
- package/dist/modules/execution/prReview.logic.js.map +1 -1
- package/package.json +8 -8
|
@@ -160,6 +160,7 @@ export declare class RunDispatcher {
|
|
|
160
160
|
* back as callbacks so the agent and deployer paths share one implementation of each.
|
|
161
161
|
*/
|
|
162
162
|
private readonly deployer;
|
|
163
|
+
private readonly repoOps;
|
|
163
164
|
/**
|
|
164
165
|
* The Follow-up companion gate (the future-looking Coder's streamed items, the
|
|
165
166
|
* park-until-decided gate, and the human-action API), extracted to
|
|
@@ -386,108 +387,6 @@ export declare class RunDispatcher {
|
|
|
386
387
|
* undefined for a non-gate kind. See {@link GateDefinition} and {@link evaluateGate}.
|
|
387
388
|
*/
|
|
388
389
|
gateFor(agentKind: string): GateDefinition | undefined;
|
|
389
|
-
/**
|
|
390
|
-
* Resolve the concrete branch a registered kind's pre/post-op reads or writes, from
|
|
391
|
-
* its declared clone target — mirroring the container executor's mapping so a backend
|
|
392
|
-
* op and the container agent operate on the SAME branch:
|
|
393
|
-
* - `base` → the repo default branch (the ONLY way a committing op targets `main`).
|
|
394
|
-
* - `pr` → the block's PR branch (the coder's branch); when no PR is open, the
|
|
395
|
-
* per-block work branch (created from base if missing) — NOT base, so a
|
|
396
|
-
* committing post-op can't silently land on the default branch.
|
|
397
|
-
* - `work` (default) → the per-block work branch, ENSURED to exist exactly as
|
|
398
|
-
* {@link ContainerAgentExecutor}'s `ensureWorkBranch` does. The old code
|
|
399
|
-
* returned base here whenever no PR was open yet, diverging from the
|
|
400
|
-
* container agent (which clones `cat-factory/<blockId>`) and letting a
|
|
401
|
-
* post-op commit onto the default branch.
|
|
402
|
-
* The work-branch name (`cat-factory/<blockId>`) is the same convention
|
|
403
|
-
* {@link ContainerAgentExecutor} uses.
|
|
404
|
-
*/
|
|
405
|
-
private resolveRepoOpBranch;
|
|
406
|
-
/**
|
|
407
|
-
* The task's apriori WORKING branch (an existing branch it names as the run's starting
|
|
408
|
-
* point), or undefined when none is set. Rejects the degenerate case where it equals the
|
|
409
|
-
* repo base — the run would have nothing to diff / no PR to open — via the same shared
|
|
410
|
-
* `resolveAprioriWorkingBranch` guard the executor uses, so the two rejections can't drift.
|
|
411
|
-
*/
|
|
412
|
-
private aprioriWorkBranch;
|
|
413
|
-
/**
|
|
414
|
-
* Ensure the per-block work branch `cat-factory/<blockId>` exists — creating it from the
|
|
415
|
-
* repo default branch's head when absent — and return it. The checkout-free analogue of
|
|
416
|
-
* {@link ContainerAgentExecutor}'s `ensureWorkBranch`, so a backend pre/post-op writes
|
|
417
|
-
* the SAME branch the container agent does instead of the default branch. Falls back to
|
|
418
|
-
* the base branch only when the repo has no default-branch head to fork from (an empty
|
|
419
|
-
* repo), so the caller always gets a real branch.
|
|
420
|
-
*
|
|
421
|
-
* `apriori` (the resolved apriori working branch name, when this run has one) flips the
|
|
422
|
-
* behaviour to PROBE-ONLY: an apriori branch must pre-exist, so a missing one throws
|
|
423
|
-
* loudly rather than being silently created off base (the mirror of the executor's rule).
|
|
424
|
-
*/
|
|
425
|
-
private ensureWorkBranch;
|
|
426
|
-
/**
|
|
427
|
-
* Run a registered kind's PRE-op hooks before its agent step dispatches: deterministic
|
|
428
|
-
* backend work (read a baseline artifact into the prompt, etc.) over a checkout-free
|
|
429
|
-
* {@link RepoFiles}. No-op for built-in / unregistered kinds, when the kind declares no
|
|
430
|
-
* pre-ops, or when GitHub isn't wired (no `resolveRunRepoContext`) — so the engine runs
|
|
431
|
-
* unchanged without the feature. A throwing op propagates to fail the step.
|
|
432
|
-
*/
|
|
433
|
-
private runRegisteredPreOps;
|
|
434
|
-
/**
|
|
435
|
-
* Resolve a block's run-repo context for its pre/post-op hooks. Returns null only when
|
|
436
|
-
* the resolver is UNWIRED (tests / GitHub not connected) so a deployment without the
|
|
437
|
-
* feature simply skips the hooks. When the resolver IS wired, its result — including a
|
|
438
|
-
* THROW from `resolveRepoTarget` for a block that isn't under a linked service — is
|
|
439
|
-
* propagated as-is: a registered kind with repo hooks run on a misconfigured block fails
|
|
440
|
-
* the run loudly rather than silently committing nothing (or guessing a repo), the same
|
|
441
|
-
* way a container custom kind fails at dispatch.
|
|
442
|
-
*/
|
|
443
|
-
private resolveRunRepo;
|
|
444
|
-
/**
|
|
445
|
-
* Run a registered kind's POST-op hooks after its agent step's result is recorded:
|
|
446
|
-
* deterministic backend work that consumes the agent's structured output (coerce its
|
|
447
|
-
* JSON, render artifact files, commit them via {@link RepoFiles}) — the
|
|
448
|
-
* blueprint/spec rendering that used to live in the harness. Same gating + symmetry as
|
|
449
|
-
* {@link runRegisteredPreOps}; the agent's {@link AgentRunResult} is threaded through.
|
|
450
|
-
*/
|
|
451
|
-
private runRegisteredPostOps;
|
|
452
|
-
/**
|
|
453
|
-
* Record a pull request a registered post-op opened onto the block, mirroring the
|
|
454
|
-
* container-coding path in {@link recordStepResult}: set `block.pullRequest`, and (when newly
|
|
455
|
-
* opened) fire the best-effort tracker-issue writeback. Idempotent — re-recording the same PR
|
|
456
|
-
* (a durable-driver replay) writes the same ref and skips the non-idempotent writeback.
|
|
457
|
-
*/
|
|
458
|
-
private recordPostOpPullRequest;
|
|
459
|
-
/**
|
|
460
|
-
* The BUILT-IN (non-registry) post-ops for a migrated built-in kind, keyed by agent
|
|
461
|
-
* kind — the deterministic render + commit lifted out of the executor-harness. Kept
|
|
462
|
-
* OUT of the agent-kind registry on purpose: registering the built-ins would leak them
|
|
463
|
-
* into `customAgentKinds` / the SPA palette. Empty for every other kind.
|
|
464
|
-
*/
|
|
465
|
-
private builtInPostOps;
|
|
466
|
-
/**
|
|
467
|
-
* The built-in (NON-registry) post-ops keyed by kind. A small map rather than an
|
|
468
|
-
* `if`-chain so each migrated built-in is one entry as the strangler converts more
|
|
469
|
-
* kinds; deliberately NOT the agent-kind registry (that would leak the built-ins into
|
|
470
|
-
* `customAgentKinds` / the SPA palette).
|
|
471
|
-
*/
|
|
472
|
-
private static readonly BUILT_IN_POST_OPS;
|
|
473
|
-
/**
|
|
474
|
-
* The branch a built-in kind's post-op reads/commits, resolved to MATCH the kind's
|
|
475
|
-
* container dispatch (so the post-op commits onto exactly the branch the explore agent
|
|
476
|
-
* cloned).
|
|
477
|
-
* - blueprints clones the PR branch when one is open, else the repo's default branch —
|
|
478
|
-
* so the initial bootstrap map lands directly on the default branch, mirroring
|
|
479
|
-
* {@link ContainerAgentExecutor}'s `pr`-clone resolution (`prBranch ?? baseBranch`).
|
|
480
|
-
* Deliberately NOT {@link resolveRepoOpBranch}, whose `pr` case ensures a work branch
|
|
481
|
-
* for the no-PR case — correct for a committing CUSTOM kind, wrong for the blueprint.
|
|
482
|
-
* - spec-writer commits onto the per-block WORK branch (`cat-factory/<blockId>`), created
|
|
483
|
-
* from base when absent. It is a WRITER (not read-only), so its container dispatch
|
|
484
|
-
* always ensures + clones that work branch ({@link ContainerAgentExecutor}'s
|
|
485
|
-
* `workBranchReady ? workBranch : …` resolves to the work branch). We mirror that
|
|
486
|
-
* DETERMINISTICALLY here — NOT via {@link resolveRepoOpBranch}'s `work` case, whose
|
|
487
|
-
* PR-preferring branch would commit onto a divergent PR branch (read one tree, write
|
|
488
|
-
* another) if a PR were ever open on a branch other than `cat-factory/<blockId>`.
|
|
489
|
-
*/
|
|
490
|
-
private builtInRepoOpBranch;
|
|
491
390
|
/**
|
|
492
391
|
* The post-completion resolver for an agent kind, or undefined when the kind has none.
|
|
493
392
|
* A resolver runs DETERMINISTIC backend follow-up once the step's agent finishes — e.g.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunDispatcher.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/RunDispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAEb,eAAe,EACf,cAAc,
|
|
1
|
+
{"version":3,"file":"RunDispatcher.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/RunDispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConflictError, DEFAULT_RISK_POLICY, failureKindFromHarnessCause, FIXER_AGENT_KIND, getErrorMessage, INITIATIVE_ANALYST_AGENT_KIND, INITIATIVE_COMMITTER_AGENT_KIND, INITIATIVE_PLANNER_AGENT_KIND, isAsyncAgentExecutor, NotFoundError, parseLocalModelId, recordGateAttempt, RunContendedError, sameSubtasks, } from '@cat-factory/kernel';
|
|
2
|
-
import { parseBlueprintService, parseSpecDoc
|
|
3
|
-
import {
|
|
2
|
+
import { parseBlueprintService, parseSpecDoc } from '@cat-factory/contracts';
|
|
3
|
+
import { commitInitiativeTracker, FORK_PROPOSER_KIND, PR_REVIEWER_KIND, hasTrait, isCompanionKind, isContainerBackedCompanion, INTERVIEW_GATE_TRAIT, TASK_ESTIMATOR_AGENT_KIND, } from '@cat-factory/agents';
|
|
4
4
|
import { DEPLOYER_AGENT_KIND, isDeployStep } from '@cat-factory/integrations';
|
|
5
5
|
import { BUG_INTAKE_AGENT_KIND } from '../pipelines/pipelineShape.js';
|
|
6
6
|
import { coerceTaskEstimate, summarizeEstimate } from '../estimation/estimate.logic.js';
|
|
@@ -12,13 +12,14 @@ import { classifyDispatchFailure, MAX_EVICTION_RECOVERIES, MAX_TRANSIENT_EVICTIO
|
|
|
12
12
|
import { AgentContextBuilder } from './AgentContextBuilder.js';
|
|
13
13
|
import { DeployerStepController } from './DeployerStepController.js';
|
|
14
14
|
import { FollowUpGateController } from './FollowUpGateController.js';
|
|
15
|
+
import { RunRepoOpsController } from './RunRepoOpsController.js';
|
|
15
16
|
import { CompanionController } from './CompanionController.js';
|
|
16
17
|
import { HumanTestController } from './HumanTestController.js';
|
|
17
18
|
import { MergeResolver } from './MergeResolver.js';
|
|
18
19
|
import { ReviewGateController } from './ReviewGateController.js';
|
|
19
20
|
import { ForkDecisionController } from './ForkDecisionController.js';
|
|
20
21
|
import { PrReviewController, PR_REVIEW_STEP_KIND } from './PrReviewController.js';
|
|
21
|
-
import { buildPrReviewPost, renderPrReviewFixerFeedback } from './prReview.logic.js';
|
|
22
|
+
import { buildPrReviewPost, initialPrReviewState, renderPrReviewFixerFeedback, } from './prReview.logic.js';
|
|
22
23
|
import { DEFAULT_FORK_MAX_CHAT_TURNS, forkPhasePending, resolveForkTriState, shouldProposeForkAuto, } from './forkDecision.logic.js';
|
|
23
24
|
import { RunStateMachine } from './RunStateMachine.js';
|
|
24
25
|
import { StepGraph } from './StepGraph.js';
|
|
@@ -37,16 +38,6 @@ const REVIEW_GATE_AGENT_KINDS = new Set([
|
|
|
37
38
|
REQUIREMENTS_BRAINSTORM_AGENT_KIND,
|
|
38
39
|
ARCHITECTURE_BRAINSTORM_AGENT_KIND,
|
|
39
40
|
]);
|
|
40
|
-
/**
|
|
41
|
-
* Whether a run delivers a committing kind's artifact through a PULL REQUEST rather than a
|
|
42
|
-
* direct commit — true when the pipeline carries a `merger` step to merge that PR. Threaded to
|
|
43
|
-
* the pre/post-op {@link RepoOpContext} so a delivering kind (e.g. `spike`) follows the chosen
|
|
44
|
-
* pipeline's shape (PR tail ⇒ open a PR; no tail ⇒ commit direct) with no separate per-task flag
|
|
45
|
-
* to drift. Mirrors {@link RunStateMachine.finalizeBlock}'s `hasMerger` distinction.
|
|
46
|
-
*/
|
|
47
|
-
function runOpensPr(instance) {
|
|
48
|
-
return instance.steps.some((s) => s.agentKind === MERGER_AGENT_KIND);
|
|
49
|
-
}
|
|
50
41
|
/**
|
|
51
42
|
* The PR number a `review` task targets: the explicit `prNumber` field wins, else parse it from
|
|
52
43
|
* the `prUrl` (`…/pull/42` on GitHub, `…/merge_requests/42` on GitLab). Undefined when neither
|
|
@@ -126,6 +117,7 @@ export class RunDispatcher {
|
|
|
126
117
|
* back as callbacks so the agent and deployer paths share one implementation of each.
|
|
127
118
|
*/
|
|
128
119
|
deployer;
|
|
120
|
+
repoOps;
|
|
129
121
|
/**
|
|
130
122
|
* The Follow-up companion gate (the future-looking Coder's streamed items, the
|
|
131
123
|
* park-until-decided gate, and the human-action API), extracted to
|
|
@@ -206,6 +198,13 @@ export class RunDispatcher {
|
|
|
206
198
|
notificationService: deps.notificationService,
|
|
207
199
|
ticketTrackerProvider: deps.ticketTrackerProvider,
|
|
208
200
|
});
|
|
201
|
+
this.repoOps = new RunRepoOpsController({
|
|
202
|
+
blockRepository: deps.blockRepository,
|
|
203
|
+
contextBuilder: deps.contextBuilder,
|
|
204
|
+
agentKindRegistry: deps.agentKindRegistry,
|
|
205
|
+
resolveRunRepoContext: deps.resolveRunRepoContext,
|
|
206
|
+
issueWriteback: deps.issueWriteback,
|
|
207
|
+
});
|
|
209
208
|
}
|
|
210
209
|
/**
|
|
211
210
|
* Run a durable-driver entry point, turning a lost optimistic-concurrency race into a
|
|
@@ -259,7 +258,7 @@ export class RunDispatcher {
|
|
|
259
258
|
// step not having dispatched yet so a Workflows replay (jobId already set) doesn't
|
|
260
259
|
// re-run them; a no-op for built-in kinds and when GitHub isn't wired.
|
|
261
260
|
if (!step.jobId) {
|
|
262
|
-
await this.runRegisteredPreOps(workspaceId, instance, block, step, context);
|
|
261
|
+
await this.repoOps.runRegisteredPreOps(workspaceId, instance, block, step, context);
|
|
263
262
|
}
|
|
264
263
|
const executor = this.agentExecutor;
|
|
265
264
|
if (isAsyncAgentExecutor(executor) && executor.runsAsync(context)) {
|
|
@@ -276,6 +275,16 @@ export class RunDispatcher {
|
|
|
276
275
|
// `starting` now lets the details show the boot (and then the live phase + the
|
|
277
276
|
// container id/url) instead of a blank "working" state.
|
|
278
277
|
step.container = { status: 'starting' };
|
|
278
|
+
// Seed the in-flight PR-review state so a `pr-reviewer` run surfaces a real `reviewing`
|
|
279
|
+
// phase in the deep-review window (the reviewed PR + the live slices-reviewed progress
|
|
280
|
+
// off the step's todo subtasks) instead of an empty panel until the findings land. Only
|
|
281
|
+
// on the reviewer's OWN first dispatch: a `fix`/`post` re-dispatch reuses this step under
|
|
282
|
+
// an overriding kind and already carries `prReview` (`fixing`/`posting`), which must not
|
|
283
|
+
// be reset back to `reviewing`.
|
|
284
|
+
if (step.agentKind === PR_REVIEWER_KIND && !step.prReview) {
|
|
285
|
+
const prUrl = block?.taskTypeFields?.prUrl?.trim() || null;
|
|
286
|
+
step.prReview = initialPrReviewState(prUrl, step.model ?? null);
|
|
287
|
+
}
|
|
279
288
|
// Surface the block's ephemeral environment (if any) alongside the cold-boot
|
|
280
289
|
// phase, so a run's details show the env spinning up next to the container.
|
|
281
290
|
await this.deployer.attachEnvironmentProjection(workspaceId, instance.blockId, step);
|
|
@@ -1153,7 +1162,7 @@ export class RunDispatcher {
|
|
|
1153
1162
|
// the checkout-free RepoFiles port — the blueprint/spec rendering that used to live in
|
|
1154
1163
|
// the harness). Position-independent like the resolver above; a no-op for built-ins
|
|
1155
1164
|
// and when GitHub isn't wired. A throwing op propagates to fail the step/run.
|
|
1156
|
-
await this.runRegisteredPostOps(workspaceId, instance, step, isFinalStep, result);
|
|
1165
|
+
await this.repoOps.runRegisteredPostOps(workspaceId, instance, step, isFinalStep, result);
|
|
1157
1166
|
if (isFinalStep) {
|
|
1158
1167
|
instance.status = 'done';
|
|
1159
1168
|
// Merge resolution (and confidence persistence) already happened above,
|
|
@@ -1338,7 +1347,7 @@ export class RunDispatcher {
|
|
|
1338
1347
|
// such a misconfiguration aborts the committer with the entity still truthfully
|
|
1339
1348
|
// `awaiting_approval` — instead of flipping to `executing` and THEN throwing, which would
|
|
1340
1349
|
// fail the run while leaving a committed status whose plan never got mirrored (a lie).
|
|
1341
|
-
const runRepo = await this.resolveRunRepo(workspaceId, block.id);
|
|
1350
|
+
const runRepo = await this.repoOps.resolveRunRepo(workspaceId, block.id);
|
|
1342
1351
|
// Now flip to `executing` and render the tracker from the flipped entity — the committed
|
|
1343
1352
|
// mirror (and its content hash) must record the REAL `executing` status. Committing the
|
|
1344
1353
|
// pre-flip entity would bake a stale `awaiting_approval` status into
|
|
@@ -1385,222 +1394,6 @@ export class RunDispatcher {
|
|
|
1385
1394
|
this.gateRegistryCache = this.buildGateRegistry();
|
|
1386
1395
|
return this.gateRegistryCache.get(agentKind);
|
|
1387
1396
|
}
|
|
1388
|
-
/**
|
|
1389
|
-
* Resolve the concrete branch a registered kind's pre/post-op reads or writes, from
|
|
1390
|
-
* its declared clone target — mirroring the container executor's mapping so a backend
|
|
1391
|
-
* op and the container agent operate on the SAME branch:
|
|
1392
|
-
* - `base` → the repo default branch (the ONLY way a committing op targets `main`).
|
|
1393
|
-
* - `pr` → the block's PR branch (the coder's branch); when no PR is open, the
|
|
1394
|
-
* per-block work branch (created from base if missing) — NOT base, so a
|
|
1395
|
-
* committing post-op can't silently land on the default branch.
|
|
1396
|
-
* - `work` (default) → the per-block work branch, ENSURED to exist exactly as
|
|
1397
|
-
* {@link ContainerAgentExecutor}'s `ensureWorkBranch` does. The old code
|
|
1398
|
-
* returned base here whenever no PR was open yet, diverging from the
|
|
1399
|
-
* container agent (which clones `cat-factory/<blockId>`) and letting a
|
|
1400
|
-
* post-op commit onto the default branch.
|
|
1401
|
-
* The work-branch name (`cat-factory/<blockId>`) is the same convention
|
|
1402
|
-
* {@link ContainerAgentExecutor} uses.
|
|
1403
|
-
*/
|
|
1404
|
-
async resolveRepoOpBranch(step, block, runRepo) {
|
|
1405
|
-
const { repo, baseBranch } = runRepo;
|
|
1406
|
-
const prBranch = block.pullRequest?.branch;
|
|
1407
|
-
// An apriori WORKING branch overrides the deterministic work branch: the backend op must
|
|
1408
|
-
// read/write the SAME branch the container agent builds inside. It is probe-only (a
|
|
1409
|
-
// missing branch fails loudly, never a silent create — the mirror of the executor).
|
|
1410
|
-
const aprioriWork = this.aprioriWorkBranch(block, baseBranch);
|
|
1411
|
-
const workBranch = aprioriWork ?? `cat-factory/${block.id}`;
|
|
1412
|
-
switch (step?.clone?.branch) {
|
|
1413
|
-
case 'base':
|
|
1414
|
-
return baseBranch;
|
|
1415
|
-
case 'pr':
|
|
1416
|
-
// `pr-or-work` reads/writes the PR branch when one exists (amend in place), else the work
|
|
1417
|
-
// branch — the same resolution as `pr`, so it shares this arm.
|
|
1418
|
-
case 'pr-or-work':
|
|
1419
|
-
return prBranch ?? (await this.ensureWorkBranch(repo, workBranch, baseBranch, aprioriWork));
|
|
1420
|
-
default:
|
|
1421
|
-
// 'work' (or unspecified): the work branch the container agent operates on. A PR
|
|
1422
|
-
// is normally opened on that branch, but even before one exists we ensure it so
|
|
1423
|
-
// the backend op and the container agent share the same branch.
|
|
1424
|
-
return prBranch && prBranch !== workBranch
|
|
1425
|
-
? prBranch
|
|
1426
|
-
: await this.ensureWorkBranch(repo, workBranch, baseBranch, aprioriWork);
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
/**
|
|
1430
|
-
* The task's apriori WORKING branch (an existing branch it names as the run's starting
|
|
1431
|
-
* point), or undefined when none is set. Rejects the degenerate case where it equals the
|
|
1432
|
-
* repo base — the run would have nothing to diff / no PR to open — via the same shared
|
|
1433
|
-
* `resolveAprioriWorkingBranch` guard the executor uses, so the two rejections can't drift.
|
|
1434
|
-
*/
|
|
1435
|
-
aprioriWorkBranch(block, baseBranch) {
|
|
1436
|
-
return resolveAprioriWorkingBranch(block.aprioriBranches, baseBranch);
|
|
1437
|
-
}
|
|
1438
|
-
/**
|
|
1439
|
-
* Ensure the per-block work branch `cat-factory/<blockId>` exists — creating it from the
|
|
1440
|
-
* repo default branch's head when absent — and return it. The checkout-free analogue of
|
|
1441
|
-
* {@link ContainerAgentExecutor}'s `ensureWorkBranch`, so a backend pre/post-op writes
|
|
1442
|
-
* the SAME branch the container agent does instead of the default branch. Falls back to
|
|
1443
|
-
* the base branch only when the repo has no default-branch head to fork from (an empty
|
|
1444
|
-
* repo), so the caller always gets a real branch.
|
|
1445
|
-
*
|
|
1446
|
-
* `apriori` (the resolved apriori working branch name, when this run has one) flips the
|
|
1447
|
-
* behaviour to PROBE-ONLY: an apriori branch must pre-exist, so a missing one throws
|
|
1448
|
-
* loudly rather than being silently created off base (the mirror of the executor's rule).
|
|
1449
|
-
*/
|
|
1450
|
-
async ensureWorkBranch(repo, workBranch, baseBranch, apriori) {
|
|
1451
|
-
if (await repo.headSha(workBranch))
|
|
1452
|
-
return workBranch;
|
|
1453
|
-
if (apriori) {
|
|
1454
|
-
throw new Error(`Apriori working branch '${workBranch}' does not exist on the target repo; ` +
|
|
1455
|
-
`push it before starting the run (the platform never creates an apriori branch).`);
|
|
1456
|
-
}
|
|
1457
|
-
const baseSha = await repo.headSha(baseBranch);
|
|
1458
|
-
if (!baseSha)
|
|
1459
|
-
return baseBranch;
|
|
1460
|
-
await repo.createBranch(workBranch, baseSha);
|
|
1461
|
-
return workBranch;
|
|
1462
|
-
}
|
|
1463
|
-
/**
|
|
1464
|
-
* Run a registered kind's PRE-op hooks before its agent step dispatches: deterministic
|
|
1465
|
-
* backend work (read a baseline artifact into the prompt, etc.) over a checkout-free
|
|
1466
|
-
* {@link RepoFiles}. No-op for built-in / unregistered kinds, when the kind declares no
|
|
1467
|
-
* pre-ops, or when GitHub isn't wired (no `resolveRunRepoContext`) — so the engine runs
|
|
1468
|
-
* unchanged without the feature. A throwing op propagates to fail the step.
|
|
1469
|
-
*/
|
|
1470
|
-
async runRegisteredPreOps(workspaceId, instance, block, step, context) {
|
|
1471
|
-
const ops = this.agentKindRegistry.preOps(step.agentKind);
|
|
1472
|
-
if (ops.length === 0)
|
|
1473
|
-
return;
|
|
1474
|
-
const runRepo = await this.resolveRunRepo(workspaceId, block.id);
|
|
1475
|
-
if (!runRepo)
|
|
1476
|
-
return;
|
|
1477
|
-
const branch = await this.resolveRepoOpBranch(this.agentKindRegistry.agentStep(step.agentKind), block, runRepo);
|
|
1478
|
-
await runRepoOps(ops, { repo: runRepo.repo, context, branch, opensPr: runOpensPr(instance) });
|
|
1479
|
-
}
|
|
1480
|
-
/**
|
|
1481
|
-
* Resolve a block's run-repo context for its pre/post-op hooks. Returns null only when
|
|
1482
|
-
* the resolver is UNWIRED (tests / GitHub not connected) so a deployment without the
|
|
1483
|
-
* feature simply skips the hooks. When the resolver IS wired, its result — including a
|
|
1484
|
-
* THROW from `resolveRepoTarget` for a block that isn't under a linked service — is
|
|
1485
|
-
* propagated as-is: a registered kind with repo hooks run on a misconfigured block fails
|
|
1486
|
-
* the run loudly rather than silently committing nothing (or guessing a repo), the same
|
|
1487
|
-
* way a container custom kind fails at dispatch.
|
|
1488
|
-
*/
|
|
1489
|
-
async resolveRunRepo(workspaceId, blockId) {
|
|
1490
|
-
if (!this.resolveRunRepoContext)
|
|
1491
|
-
return null;
|
|
1492
|
-
return this.resolveRunRepoContext(workspaceId, blockId);
|
|
1493
|
-
}
|
|
1494
|
-
/**
|
|
1495
|
-
* Run a registered kind's POST-op hooks after its agent step's result is recorded:
|
|
1496
|
-
* deterministic backend work that consumes the agent's structured output (coerce its
|
|
1497
|
-
* JSON, render artifact files, commit them via {@link RepoFiles}) — the
|
|
1498
|
-
* blueprint/spec rendering that used to live in the harness. Same gating + symmetry as
|
|
1499
|
-
* {@link runRegisteredPreOps}; the agent's {@link AgentRunResult} is threaded through.
|
|
1500
|
-
*/
|
|
1501
|
-
async runRegisteredPostOps(workspaceId, instance, step, isFinalStep, result) {
|
|
1502
|
-
const registered = this.agentKindRegistry.postOps(step.agentKind);
|
|
1503
|
-
const builtIn = this.builtInPostOps(step.agentKind);
|
|
1504
|
-
if (registered.length === 0 && builtIn.length === 0)
|
|
1505
|
-
return;
|
|
1506
|
-
const block = await this.blockRepository.get(workspaceId, instance.blockId);
|
|
1507
|
-
if (!block)
|
|
1508
|
-
return;
|
|
1509
|
-
const runRepo = await this.resolveRunRepo(workspaceId, block.id);
|
|
1510
|
-
if (!runRepo)
|
|
1511
|
-
return;
|
|
1512
|
-
const context = await this.contextBuilder.buildContext(workspaceId, instance, step, isFinalStep, block);
|
|
1513
|
-
const opensPr = runOpensPr(instance);
|
|
1514
|
-
// Registered (custom) kinds resolve their branch from their declared clone target.
|
|
1515
|
-
if (registered.length > 0) {
|
|
1516
|
-
const branch = await this.resolveRepoOpBranch(this.agentKindRegistry.agentStep(step.agentKind), block, runRepo);
|
|
1517
|
-
const opResult = await runRepoOps(registered, {
|
|
1518
|
-
repo: runRepo.repo,
|
|
1519
|
-
context,
|
|
1520
|
-
branch,
|
|
1521
|
-
opensPr,
|
|
1522
|
-
result,
|
|
1523
|
-
});
|
|
1524
|
-
// A delivering kind (e.g. `spike` in PR mode) opened a PR for the findings; record it on
|
|
1525
|
-
// the block so the downstream conflicts/CI/human-review/merge tail acts on it — the SAME
|
|
1526
|
-
// linkage a container-coding step's `result.pullRequest` produces (see recordStepResult).
|
|
1527
|
-
if (opResult.pullRequest) {
|
|
1528
|
-
await this.recordPostOpPullRequest(workspaceId, block.id, opResult.pullRequest);
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
// Built-in (migrated) kinds resolve their branch to MATCH their container dispatch
|
|
1532
|
-
// exactly (see {@link builtInRepoOpBranch}), which differs from the generic clone
|
|
1533
|
-
// resolution for the no-PR case — so the post-op commits where the agent read.
|
|
1534
|
-
if (builtIn.length > 0) {
|
|
1535
|
-
const branch = await this.builtInRepoOpBranch(step.agentKind, block, runRepo);
|
|
1536
|
-
await runRepoOps(builtIn, { repo: runRepo.repo, context, branch, opensPr, result });
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
/**
|
|
1540
|
-
* Record a pull request a registered post-op opened onto the block, mirroring the
|
|
1541
|
-
* container-coding path in {@link recordStepResult}: set `block.pullRequest`, and (when newly
|
|
1542
|
-
* opened) fire the best-effort tracker-issue writeback. Idempotent — re-recording the same PR
|
|
1543
|
-
* (a durable-driver replay) writes the same ref and skips the non-idempotent writeback.
|
|
1544
|
-
*/
|
|
1545
|
-
async recordPostOpPullRequest(workspaceId, blockId, pullRequest) {
|
|
1546
|
-
const priorBlock = await this.blockRepository.get(workspaceId, blockId);
|
|
1547
|
-
if (priorBlock?.pullRequest?.url === pullRequest.url)
|
|
1548
|
-
return;
|
|
1549
|
-
await this.blockRepository.update(workspaceId, blockId, { pullRequest });
|
|
1550
|
-
if (this.issueWriteback && priorBlock) {
|
|
1551
|
-
await this.issueWriteback
|
|
1552
|
-
.onPullRequestOpened(workspaceId, priorBlock, pullRequest)
|
|
1553
|
-
.catch(() => { });
|
|
1554
|
-
}
|
|
1555
|
-
}
|
|
1556
|
-
/**
|
|
1557
|
-
* The BUILT-IN (non-registry) post-ops for a migrated built-in kind, keyed by agent
|
|
1558
|
-
* kind — the deterministic render + commit lifted out of the executor-harness. Kept
|
|
1559
|
-
* OUT of the agent-kind registry on purpose: registering the built-ins would leak them
|
|
1560
|
-
* into `customAgentKinds` / the SPA palette. Empty for every other kind.
|
|
1561
|
-
*/
|
|
1562
|
-
builtInPostOps(agentKind) {
|
|
1563
|
-
return RunDispatcher.BUILT_IN_POST_OPS[agentKind] ?? [];
|
|
1564
|
-
}
|
|
1565
|
-
/**
|
|
1566
|
-
* The built-in (NON-registry) post-ops keyed by kind. A small map rather than an
|
|
1567
|
-
* `if`-chain so each migrated built-in is one entry as the strangler converts more
|
|
1568
|
-
* kinds; deliberately NOT the agent-kind registry (that would leak the built-ins into
|
|
1569
|
-
* `customAgentKinds` / the SPA palette).
|
|
1570
|
-
*/
|
|
1571
|
-
static BUILT_IN_POST_OPS = {
|
|
1572
|
-
[BLUEPRINTS_AGENT_KIND]: [blueprintPostOp],
|
|
1573
|
-
[SPEC_WRITER_AGENT_KIND]: [specPostOp],
|
|
1574
|
-
};
|
|
1575
|
-
/**
|
|
1576
|
-
* The branch a built-in kind's post-op reads/commits, resolved to MATCH the kind's
|
|
1577
|
-
* container dispatch (so the post-op commits onto exactly the branch the explore agent
|
|
1578
|
-
* cloned).
|
|
1579
|
-
* - blueprints clones the PR branch when one is open, else the repo's default branch —
|
|
1580
|
-
* so the initial bootstrap map lands directly on the default branch, mirroring
|
|
1581
|
-
* {@link ContainerAgentExecutor}'s `pr`-clone resolution (`prBranch ?? baseBranch`).
|
|
1582
|
-
* Deliberately NOT {@link resolveRepoOpBranch}, whose `pr` case ensures a work branch
|
|
1583
|
-
* for the no-PR case — correct for a committing CUSTOM kind, wrong for the blueprint.
|
|
1584
|
-
* - spec-writer commits onto the per-block WORK branch (`cat-factory/<blockId>`), created
|
|
1585
|
-
* from base when absent. It is a WRITER (not read-only), so its container dispatch
|
|
1586
|
-
* always ensures + clones that work branch ({@link ContainerAgentExecutor}'s
|
|
1587
|
-
* `workBranchReady ? workBranch : …` resolves to the work branch). We mirror that
|
|
1588
|
-
* DETERMINISTICALLY here — NOT via {@link resolveRepoOpBranch}'s `work` case, whose
|
|
1589
|
-
* PR-preferring branch would commit onto a divergent PR branch (read one tree, write
|
|
1590
|
-
* another) if a PR were ever open on a branch other than `cat-factory/<blockId>`.
|
|
1591
|
-
*/
|
|
1592
|
-
async builtInRepoOpBranch(agentKind, block, runRepo) {
|
|
1593
|
-
if (agentKind === SPEC_WRITER_AGENT_KIND) {
|
|
1594
|
-
// The spec-writer commits onto the run's WORK branch — the apriori working branch when
|
|
1595
|
-
// the task names one (probe-only, must pre-exist), else the deterministic per-block
|
|
1596
|
-
// branch. Miss this swap and the spec lands on a phantom `cat-factory/<blockId>` while
|
|
1597
|
-
// the agent explored the apriori branch.
|
|
1598
|
-
const aprioriWork = this.aprioriWorkBranch(block, runRepo.baseBranch);
|
|
1599
|
-
const workBranch = aprioriWork ?? `cat-factory/${block.id}`;
|
|
1600
|
-
return this.ensureWorkBranch(runRepo.repo, workBranch, runRepo.baseBranch, aprioriWork);
|
|
1601
|
-
}
|
|
1602
|
-
return block.pullRequest?.branch ?? runRepo.baseBranch;
|
|
1603
|
-
}
|
|
1604
1397
|
/**
|
|
1605
1398
|
* The post-completion resolver for an agent kind, or undefined when the kind has none.
|
|
1606
1399
|
* A resolver runs DETERMINISTIC backend follow-up once the step's agent finishes — e.g.
|