package orchestrator import ( "context" "time" "github.com/google/uuid" "github.com/yan1h/agent-coding-workflow/internal/project" ) // StepEnqueuer 是建好 step 后入队其 orchestrator.step job 的窄接口(service 实现, // 包装 jobs.Repository.Enqueue)。导出以便 app.go 在启动恢复时直接调用 EnqueueStep。 type StepEnqueuer interface { EnqueueStep(ctx context.Context, runID, stepID uuid.UUID, scheduledAt time.Time) error } // AuditRecorder 是编排器写审计的窄接口(app 层用 audit.Recorder 适配)。导出以便 // 外部包(app)的适配器可实现(unexported 方法的接口无法被跨包实现)。 type AuditRecorder interface { Record(ctx context.Context, userID uuid.UUID, action, targetID string, meta map[string]any) } // buildPhaseStep 为 run 在指定 phase 建一个新 step(pending 状态),解析 agent-kind // 与 prompt 后落库。parent 非 nil 时记录 parent_step_id(request_subtask fan-out)。 // 解析失败(如缺 agent-kind)返回 error,调用方据此处理(标 run 失败 / 拒绝 subtask)。 func buildPhaseStep(ctx context.Context, repo Repository, pm PMAccess, run *Run, phase project.Phase, parentStepID *uuid.UUID, depth int, defaults map[project.Phase]uuid.UUID) (*Step, error) { akID, err := PhaseAgentKind(run.Config, phase, defaults) if err != nil { return nil, err } req, err := pm.GetRequirementByID(ctx, run.RequirementID) if err != nil { return nil, err } artifacts, _ := pm.ListLatestArtifacts(ctx, run.RequirementID) override := run.Config.PromptOverrides[phase] prompt := BuildPrompt(phase, req, artifacts, override) step := &Step{ ID: uuid.New(), RunID: run.ID, Phase: phase, Attempt: 1, ParentStepID: parentStepID, Depth: depth, Status: StepPending, AgentKindID: akID, Prompt: prompt, } return repo.InsertStep(ctx, step) }