// Phase 3 多进程执行:worker 侧【纯执行管线】。 // // 这是旧 `orchestrator.executeTask` 函数体「劈出来」的执行半边——只负责跑 // worktree→执行→verify→双复审→产出,并把每一步的进度/结果经 `emit` 写进 outbox 文件。 // 它【完全不碰 DB】(连读都不碰),也【不做任何重试 / needs_attention 决策】: // - 失败(executor 报错 / verify 不过)→ emit failed,然后 emit done,结束(不抛错)。 // - 成功 → emit result(四要素),然后 emit done。 // 重试次数、退避、转终态等判断全部归 daemon(它读 outbox 后决策)。 // // daemon 侧的 store.* 调用与本模块 emit 的对应关系(仅为说明,本模块不引用 store): // store.transition(executing) / startRun(executor) → emit started(由 worker 在入口发,不在此) // runner 失败 / verify 失败 finishRun(failed) → emit failed // 双复审 + setResult(四字段) + transition(exec_review) → emit result // (worker 退出) → emit done import type { JobSpec, OutboxPayload, ReviewReport } from './protocol.js'; import { createWorktree, worktreeDiff, type WorktreeDiff, type WorktreeInfo } from './worktree.js'; import { runTask, type RunnerFn } from './runner.js'; import { runVerify, type VerifyFn } from './verify.js'; import { reviewCode, reviewSecurity, type ReviewerFn } from './reviewer.js'; /** pipeline 的依赖注入面(便于单测 mock);默认值取真实现。 */ export interface PipelineDeps { createWorktree: (repoPath: string, taskId: string, baseBranch: string) => Promise; worktreeDiff: (repoPath: string, dir: string, branch: string, baseBranch: string) => Promise; runTask: RunnerFn; verify: VerifyFn; reviewCode: ReviewerFn; // code review(daemon 落成 kind=reviewer 的 run) reviewSecurity: ReviewerFn; // 安全审计(daemon 落成 kind=security 的 run) } /** 真实依赖(worker 生产用)。 */ export const realDeps: PipelineDeps = { createWorktree, worktreeDiff, runTask, verify: runVerify, reviewCode, reviewSecurity, }; /** emit:把一条 OutboxPayload 交给 outbox(worker 传 appendOutbox 包装,测试传收集器)。 */ export type Emit = (payload: OutboxPayload) => void; /** * 跑一个独立复审(code / security),复刻旧 `runOneReview` 的兜底: * 任何失败折叠成 `{summary:'自动复审失败:'+msg, verdict:null, transcriptRef:null}`,不抛错、不挡任务。 * 成功时把 ReviewResult 映射成 ReviewReport(丢弃 sessionId——result 记录里复审只留 transcriptRef)。 */ async function runOneReview( fn: ReviewerFn, job: JobSpec, wt: WorktreeInfo, reviewRunId: string, executorReport: string, ): Promise { try { const rv = await fn(job.task, job.project, wt, reviewRunId, executorReport); return { summary: rv.summary, verdict: rv.verdict, transcriptRef: rv.transcriptRef }; } catch (e) { return { summary: `自动复审失败:${(e as Error).message}`, verdict: null, transcriptRef: null }; } } /** * 纯执行管线。复刻旧 in-process 流程的【执行与产出】,但所有 store.* 改成 emit(outbox): * 1. createWorktree * 2. runTask;!ok → emit failed{error,transcriptRef,sessionId} + done,返回(不抛) * 3. runVerify;!ok → emit failed{error,rr.transcriptRef,rr.sessionId} + done,返回 * 4. worktreeDiff * 5. 双复审(顺序,任一失败不挡,见 runOneReview 兜底) * 6. emit result(branch/worktree/diffSummary/commits/executor/code/security)+ done * * 不抛错(除非 emit 自身抛——那由 worker 顶层兜底)。全程总会 emit 一条终态(failed|result)后再 emit done。 */ export async function runPipeline(job: JobSpec, deps: PipelineDeps = realDeps, emit: Emit): Promise { // 1. 建 worktree(其 dir/branch 应与 job.worktreeDir/branch 一致;以 deps 真建的为准) const wt = await deps.createWorktree(job.project.repoPath, job.task.id, job.project.defaultBranch); // 2. 执行 emit({ type: 'phase', phase: 'executing' }); const rr = await deps.runTask(job.task, job.project, wt, job.runId); if (!rr.ok) { emit({ type: 'failed', error: rr.error ?? '执行失败', transcriptRef: rr.transcriptRef, sessionId: rr.sessionId }); emit({ type: 'done' }); return; } // 3. 校验 emit({ type: 'phase', phase: 'verifying' }); const vr = await deps.verify(job.project, wt.dir, job.runId); if (!vr.ok) { // transcriptRef/sessionId 沿用 executor 的(verify 自身无转录) emit({ type: 'failed', error: vr.error ?? 'verify 失败', transcriptRef: rr.transcriptRef, sessionId: rr.sessionId }); emit({ type: 'done' }); return; } // 4. diff const diff = await deps.worktreeDiff(job.project.repoPath, wt.dir, wt.branch, job.project.defaultBranch); // 5. 双复审(顺序;任一失败不挡)。runId 派生子 id,与旧实现一致(${runId}.review / ${runId}.security) emit({ type: 'phase', phase: 'reviewing' }); const report = rr.finalText ?? ''; const code = await runOneReview(deps.reviewCode, job, wt, `${job.runId}.review`, report); const security = await runOneReview(deps.reviewSecurity, job, wt, `${job.runId}.security`, report); // 6. 成功终态 emit({ type: 'result', branch: wt.branch, worktree: wt.dir, diffSummary: diff.diffSummary, commits: diff.commits, executor: { transcriptRef: rr.transcriptRef, sessionId: rr.sessionId }, code, security, }); emit({ type: 'done' }); }