feat(pr): pr-create/pr-respond/pr-merge node kinds + handlers (U3)
Adds the three first-class PR workflow node kinds and their handlers via createPrNodeHandlers(deps), registered in createDefaultNodeHandlers (fail-closed pr-nodes-unwired when absent). GitHub ops are injected as callbacks (PrNodeGithubOps) at all three CLI sites (daemon/serve/dashboard) so the engine never imports the dashboard client (FN-3049). pr-create routes open/failed as outcomes; pr-merge passes expectedHeadOid and never writes 'merged' (reconcile corroborates); pr-respond delegates to an injected respond callback (U5 fills the body). 10 tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import { InProcessRuntime } from "./runtimes/in-process-runtime.js";
|
||||
import type { WorktreePool } from "./worktree-pool.js";
|
||||
import type { ProjectRuntimeConfig } from "./project-runtime.js";
|
||||
import { PrMonitor } from "./pr-monitor.js";
|
||||
import type { PrNodeGithubOps } from "./pr-nodes.js";
|
||||
import { PrCommentHandler } from "./pr-comment-handler.js";
|
||||
import { NtfyNotifier } from "./notifier.js";
|
||||
import { NotificationService, OAuthAlertStateStore, OAuthExpiryMonitor, OAuthValidityLogger } from "./notification/index.js";
|
||||
@@ -220,6 +221,15 @@ export interface ProjectEngineOptions {
|
||||
* the PR body.
|
||||
*/
|
||||
syncGroupPr?: SyncGroupPrFn;
|
||||
/**
|
||||
* PR-entity node GitHub ops (U3): the injected `createPr`/`mergePr`/`respond`
|
||||
* callbacks (+ source resolver + audit) that back the `pr-create`/`pr-respond`/
|
||||
* `pr-merge` workflow nodes. Injected from the CLI layer because they close
|
||||
* over the dashboard `GitHubClient`; the engine must not statically import it
|
||||
* (FN-3049). Mirrors `createGroupPr`/`syncGroupPr`. When absent, the pr-* node
|
||||
* kinds fail closed (value:"pr-nodes-unwired").
|
||||
*/
|
||||
prNodeGithubOps?: PrNodeGithubOps;
|
||||
/**
|
||||
* Returns the merge blocker reason for a task, or null/undefined if
|
||||
* the task is eligible for merge. Imported from @fusion/core.
|
||||
@@ -364,10 +374,14 @@ export class ProjectEngine {
|
||||
centralCore: CentralCore,
|
||||
private options: ProjectEngineOptions = {},
|
||||
) {
|
||||
// Pass through externalTaskStore to the runtime config if provided
|
||||
const runtimeConfig: ProjectRuntimeConfig = options.externalTaskStore
|
||||
? { ...config, externalTaskStore: options.externalTaskStore }
|
||||
: config;
|
||||
// Pass through externalTaskStore + PR node GitHub ops (U3) to the runtime
|
||||
// config. The runtime binds the engine-owned store and hands the assembled
|
||||
// PrNodeDeps to the executor's workflow-graph runner.
|
||||
const runtimeConfig: ProjectRuntimeConfig = {
|
||||
...config,
|
||||
...(options.externalTaskStore ? { externalTaskStore: options.externalTaskStore } : {}),
|
||||
...(options.prNodeGithubOps ? { prNodeGithubOps: options.prNodeGithubOps } : {}),
|
||||
};
|
||||
this.runtime = new InProcessRuntime(runtimeConfig, centralCore);
|
||||
// Let the runtime's SelfHealingManager re-enqueue tasks directly into our
|
||||
// auto-merge queue when it clears a stale `merging` status, instead of
|
||||
|
||||
Reference in New Issue
Block a user