import { buildControlFrame } from "./control-frame.ts"; import { maybeSeedLitePlan } from "./demand-loop.ts"; import { collectMetadataEvidence, formatMetadataAutocollectResult } from "./metadata-autocollect.ts"; import { advanceRunIfReady, readActiveRun, refreshGate } from "./state.ts"; import type { ActiveRun } from "./types.ts"; export interface DemandSchedulerOutcome { handled: boolean; run: ActiveRun; promptText?: string; notices: Array<{ message: string; level: "info" | "warning" }>; } export function executeDeterministicNext(cwd: string, run: ActiveRun, userText: string): DemandSchedulerOutcome { let current = run; const notices: DemandSchedulerOutcome["notices"] = []; const progress: string[] = []; for (let turn = 0; turn < 6; turn++) { const seeded = maybeSeedLitePlan(cwd, current); if (seeded.changed) { current = seeded.run; notices.push({ message: "已根据需求和项目线索生成最小可执行 PLAN。", level: "info" }); progress.push("已生成最小可执行 PLAN"); continue; } if (current.phase === "execute" || current.phase === "verify" || current.phase === "ship") { return { handled: progress.length > 0, run: current, promptText: progress.length > 0 ? `${progress.join(";")}。现在执行当前 Demand Loop。` : undefined, notices, }; } const frame = buildControlFrame(cwd, current, userText); if (frame.nextAction.kind === "answer-question") { const questionId = frame.openQuestion?.id ?? "Q-001"; return { handled: true, run: current, notices: [ ...notices, { message: `需要先回答问题:${frame.nextAction.reason}\n使用 /kd answer ${questionId} <答案>,或直接回复答案。`, level: "warning", }, ], }; } if (frame.nextAction.kind === "advance-phase" && frame.nextAction.executable) { const result = advanceRunIfReady(cwd, current); current = result.run; notices.push({ message: result.message, level: result.advanced || result.run.gate.passed ? "info" : "warning" }); progress.push(result.message); if (result.advanced) continue; return { handled: true, run: current, promptText: `当前不能推进:${result.message}。只处理当前阻塞项。`, notices, }; } if (frame.nextAction.kind === "collect-metadata-evidence") { const collected = collectMetadataEvidence(cwd, current); if (collected.status !== "collected" && collected.status !== "already-present") { return { handled: false, run: current, notices: [...notices, { message: collected.message, level: "warning" }], }; } notices.push({ message: formatMetadataAutocollectResult(collected), level: "info" }); progress.push("元数据证据已就绪"); current = refreshGate(cwd, readActiveRun(cwd) ?? current); continue; } return { handled: progress.length > 0, run: current, promptText: progress.length > 0 ? `${progress.join(";")}。现在执行当前 Demand Loop。` : undefined, notices, }; } return { handled: true, run: current, promptText: `${progress.join(";")}。已达到确定性 loop 步数上限,现在执行当前 Demand Loop。`, notices, }; }