// ── 工具组: sf_status, sf_plan, sf_plan_advance, sf_analyze, sf_review ──
// 从 tools.ts 第 3303-3738 行提取。
import path from "node:path";
import { promises as fsp } from "node:fs";
import { internalWarn } from "../../../engine/core/logger.js";
import { archiveStaleCurrentPointer, detectStaleCurrentTask } from "../../../engine/pipeline/stale_current_task_detector.js";
import { isSameOrDescendantPath } from "../../../engine/core/path_scope_utils.js";
import { createToolRegistrar } from "../middleware.js";
import { StatusSchema, PlanSchema, AnalyzeSchema, ReviewSchema } from "../schemas.js";
import { lazyJob, lazyPlanner, lazyImpact, lazyDecision, lazyReviewer, lazyDebt, lazyOodSolid, lazyBackendImplementation, lazyCodeObservability, } from "../lazy_loaders.js";
// ── sf_status、sf_plan、sf_plan_advance ──
export async function registerStatusPlanTools(ctx) {
    const { registerSafeTool, loadRelevantAnchors } = createToolRegistrar(ctx);
    const { config, knowledgeIndex, taskContext } = ctx;
    registerSafeTool("sf_status", "查询当前任务状态、列出近期任务、恢复中断任务或取消任务", StatusSchema, async (args) => {
        const action = args.action || "current";
        // Job 操作 — advisory，独立于任务操作
        if (args.job_action) {
            if (!args.job_id) {
                return {
                    result: { error: "job 操作需要 job_id" },
                };
            }
            const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
            const taskId = args.task_id ?? await jm.resolveTaskId(args.job_id) ?? "";
            if (args.job_action === "job_status") {
                const status = await jm.getJobStatus(args.job_id, taskId);
                if (!status) {
                    return {
                        result: { error: `job ${args.job_id} 不存在或已过期` },
                    };
                }
                return {
                    result: { job: status },
                };
            }
            if (args.job_action === "job_resume") {
                const checkpoint = await jm.resumeFromCheckpoint(args.job_id, taskId);
                if (!checkpoint) {
                    return {
                        result: { error: `job ${args.job_id} 无可恢复的 checkpoint` },
                    };
                }
                return {
                    result: {
                        advisory: "job 恢复为 advisory 操作，需确认 checkpoint 数据与当前状态一致",
                        job_id: checkpoint.job_id,
                        task_id: checkpoint.task_id,
                        phase: checkpoint.phase,
                        checkpoint_number: checkpoint.checkpoint_number,
                        cognitive_anchor: checkpoint.cognitive_anchor,
                    },
                };
            }
            if (args.job_action === "job_cancel") {
                const removed = await jm.cancelJob(args.job_id, taskId);
                return {
                    result: {
                        advisory: "job 取消为 advisory 操作",
                        job_id: args.job_id,
                        cancelled: removed,
                    },
                };
            }
        }
        // 读取前自动将过期非终态任务标记为失败
        try {
            await taskContext.autoFailStale();
        }
        catch (e) {
            internalWarn("autoFailStale", "出错:", e);
        }
        switch (action) {
            case "current": {
                const ctx = args.task_id
                    ? await taskContext.load(args.task_id)
                    : await taskContext.getCurrentTask();
                if (!ctx) {
                    return {
                        result: { message: "当前无活跃任务" },
                    };
                }
                const resumable = taskContext.isResumable(ctx);
                const result = {
                    task_id: ctx.task_id,
                    intent: ctx.intent,
                    status: ctx.status,
                    created_at: ctx.created_at,
                    resumable,
                };
                if (resumable) {
                    result.resume_hint = taskContext.getResumeHint(ctx);
                }
                if (ctx.classification) {
                    result.task_type = ctx.classification.task_type;
                    result.risk = ctx.classification.risk;
                    result.strategy = ctx.classification.strategy;
                }
                if (ctx.execution) {
                    result.changed_files = ctx.execution.changed_files;
                    result.attempt_count = ctx.execution.attempt_count;
                }
                // JobManager advisory: 查询关联 job 状态
                try {
                    const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
                    const activeJobs = await jm.listActiveJobs();
                    const relatedJob = activeJobs.find((j) => j.task_id === ctx.task_id);
                    if (relatedJob) {
                        result.job = {
                            job_id: relatedJob.job_id,
                            phase: relatedJob.current_phase,
                            checkpoint_count: relatedJob.checkpoint_count,
                            is_alive: relatedJob.is_alive,
                            latest_anchor_summary: relatedJob.latest_anchor?.summary,
                        };
                    }
                }
                catch {
                    // JobManager advisory — 忽略错误
                }
                return {
                    result: result,
                };
            }
            case "recent": {
                const recent = await taskContext.listRecent(10);
                return {
                    result: { tasks: recent },
                };
            }
            case "resume": {
                if (!args.task_id) {
                    return {
                        result: { error: "恢复任务需要 task_id" },
                    };
                }
                const ctx = await taskContext.load(args.task_id);
                if (!ctx) {
                    return {
                        result: { error: "任务不存在" },
                    };
                }
                if (!taskContext.isResumable(ctx)) {
                    return {
                        result: { error: `任务状态 ${ctx.status} 不可恢复`, status: ctx.status },
                    };
                }
                const resumeResult = {
                    task_id: ctx.task_id,
                    intent: ctx.intent,
                    status: ctx.status,
                    resume_hint: taskContext.getResumeHint(ctx),
                };
                if (ctx.execution)
                    resumeResult.execution = ctx.execution;
                const resumeAnchors = ctx.execution?.changed_files
                    ? await loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
                    : undefined;
                if (resumeAnchors && resumeAnchors.length > 0)
                    resumeResult.cognitive_anchors = resumeAnchors;
                return { result: resumeResult };
            }
            case "cancel": {
                if (!args.task_id) {
                    return {
                        result: { error: "取消任务需要 task_id" },
                    };
                }
                const cancelled = await taskContext.cancel(args.task_id);
                return {
                    result: { task_id: args.task_id, cancelled },
                };
            }
            case "retry_expand": {
                if (!args.task_id) {
                    return {
                        result: { error: "重试 expand 需要 task_id" },
                    };
                }
                const retried = await taskContext.retryExpand(args.task_id);
                if (!retried) {
                    return {
                        result: { error: "任务不存在、非 failed 状态或缺少 classification，无法重试 expand", task_id: args.task_id },
                    };
                }
                return {
                    result: { task_id: args.task_id, retried: true, hint: "任务已恢复到 expanding 状态，可重新调用 sf_expand" },
                };
            }
            case "archive_stale": {
                const stale = await detectStaleCurrentTask(taskContext.getStateDir());
                const taskId = args.task_id ?? stale.task_id;
                if (!taskId) {
                    return {
                        result: { error: "归档陈旧任务指针需要 task_id，且当前未检测到陈旧任务" },
                    };
                }
                if (!stale.is_stale || stale.task_id !== taskId) {
                    return {
                        result: {
                            error: "当前任务指针未被判定为陈旧，不执行归档",
                            task_id: taskId,
                            stale_task: stale.is_stale ? stale : null,
                        },
                    };
                }
                const archived = await archiveStaleCurrentPointer(taskContext.getStateDir(), taskId);
                return {
                    result: {
                        task_id: taskId,
                        archived,
                        archived_pointer_only: true,
                        task_file_preserved: true,
                    },
                };
            }
            default:
                return {
                    result: { error: `未知操作: ${action}` },
                };
        }
    });
    // ── sf_plan: 复杂意图任务拆解为子任务列表 ──
    registerSafeTool("sf_plan", "将复杂意图拆解为子任务列表。支持知识驱动的 pipeline_procedure 流程（自动绑定模板）和仓库边界拆分两种策略。仅在 complexity=high 时有效", PlanSchema, async (args) => {
        const ctx = await taskContext.load(args.task_id);
        if (!ctx?.classification) {
            return {
                result: { error: "任务不存在或尚未分类" },
            };
        }
        const result = (await lazyPlanner()).planTask({
            intent: ctx.intent,
            classification: ctx.classification,
            config,
            knowledgeIndex,
        });
        result.task_id = args.task_id;
        await taskContext.setPlanning(args.task_id, result);
        return {
            result: result,
        };
    });
    // ── sf_plan_advance: 推进多阶段计划到下一步 ──
    registerSafeTool("sf_plan_advance", "将多阶段计划推进到下一步。完成当前阶段后调用，自动更新 current_step_index 并返回下一阶段信息", PlanSchema, async (args) => {
        const ctx = await taskContext.load(args.task_id);
        if (!ctx?.planning || ctx.planning.sub_tasks.length === 0) {
            return {
                result: { error: "任务没有多阶段计划，请先调用 sf_plan" },
            };
        }
        const plan = ctx.planning;
        const previousStep = plan.sub_tasks[plan.current_step_index];
        const previousStepTitle = previousStep?.title ?? "未知";
        const nextIndex = plan.current_step_index + 1;
        if (nextIndex >= plan.sub_tasks.length) {
            return { result: {
                    task_id: args.task_id,
                    previous_step: previousStepTitle,
                    current_step_index: plan.current_step_index,
                    total_steps: plan.sub_tasks.length,
                    is_completed: true,
                    message: `所有 ${plan.sub_tasks.length} 个阶段已完成`,
                } };
        }
        // 推进阶段索引
        plan.current_step_index = nextIndex;
        await taskContext.setPlanning(args.task_id, plan);
        const nextStep = plan.sub_tasks[nextIndex];
        return {
            result: {
                task_id: args.task_id,
                previous_step: previousStepTitle,
                current_step_index: nextIndex,
                current_step: {
                    id: nextStep.id,
                    title: nextStep.title,
                    output_path: nextStep.output_path,
                },
                total_steps: plan.sub_tasks.length,
                is_completed: false,
                message: `阶段推进: ${previousStepTitle} → ${nextStep.title}`,
            },
        };
    });
}
// ── sf_analyze、sf_review ──
export async function registerAnalyzeReviewTools(ctx) {
    const { registerSafeTool } = createToolRegistrar(ctx);
    const { config, knowledgeIndex, taskContext, projectPath } = ctx;
    // ── sf_analyze: 影响范围分析，建议是否扩大作用域 ──
    registerSafeTool("sf_analyze", "分析意图的影响范围，对比声明范围，提示是否需要扩大作用域。建议性，不强制", AnalyzeSchema, async (args) => {
        const ctx = await taskContext.load(args.task_id);
        if (!ctx?.expansion) {
            return {
                result: { error: "任务尚未膨胀，请先调用 sf_expand" },
            };
        }
        const result = await (await lazyImpact()).analyzeImpact({
            intent: ctx.intent,
            classification: ctx.classification,
            expansion: ctx.expansion,
            config,
            projectPath,
        });
        result.task_id = args.task_id;
        // 决策契约 advisory: 校验 analyze 输出
        const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
        const advisoryExtras = {};
        if (!decisionContract.passed) {
            advisoryExtras.decision_contract_advisory = decisionContract.advisory;
        }
        return { result: Object.keys(advisoryExtras).length > 0 ? { ...result, ...advisoryExtras } : result };
    });
    // ── sf_review: 代码审查（质量、安全、性能、技术债务） ──
    registerSafeTool("sf_review", "审查代码变更的质量、安全、性能和技术债务。hotfix 场景可跳过。建议性，不强制修复", ReviewSchema, async (args) => {
        const ctx = await taskContext.load(args.task_id);
        if (!ctx) {
            return {
                result: { error: "任务不存在" },
            };
        }
        const tracker = new (await lazyDebt()).DebtTracker(projectPath);
        const result = await (await lazyReviewer()).reviewCode({
            changedFiles: args.changed_files,
            projectPath,
            config,
            classification: ctx.classification,
            fileContents: args.file_contents,
            knowledgeIndex,
            uncertainty_triggers: ctx.expansion?.uncertainty_triggers,
        }, tracker);
        result.task_id = args.task_id;
        await taskContext.setCodeReview(args.task_id, result);
        const contractContents = { ...(args.file_contents ?? {}) };
        for (const changedFile of args.changed_files) {
            if (contractContents[changedFile] !== undefined)
                continue;
            const absoluteFile = path.resolve(projectPath, changedFile);
            try {
                if (isSameOrDescendantPath(absoluteFile, path.resolve(projectPath), { caseSensitive: false }) && (await fsp.stat(absoluteFile)).isFile()) {
                    contractContents[changedFile] = await fsp.readFile(absoluteFile, "utf-8");
                }
            }
            catch {
                // 无法读取的文件留给现有 reviewer 报告，不制造假结论。
            }
        }
        const oodModule = await lazyOodSolid();
        const solidFindings = oodModule.requiresOodSolidContract(ctx.intent, ctx.expansion?.workflow_trace?.route, args.changed_files)
            || ctx.ood_solid_summary
            ? [
                ...oodModule.reviewSolidCode(contractContents),
                ...oodModule.evaluateOverdesignRisk(ctx.intent, ctx.ood_solid_summary),
            ]
            : [];
        const backendModule = await lazyBackendImplementation();
        const backendFindings = backendModule.requiresBackendImplementationContract(ctx.intent, ctx.expansion?.workflow_trace?.route, args.changed_files)
            || ctx.backend_implementation_work_package
            ? backendModule.reviewBackendImplementationFiles(contractContents)
            : [];
        // 问题六十八: 代码可维护性与可观测性审查
        const obsModule = await lazyCodeObservability();
        const obsFindings = obsModule.requiresCodeObservabilityContract(ctx.intent, ctx.expansion?.workflow_trace?.route, args.changed_files)
            || ctx.code_observability_work_package
            ? obsModule.reviewCodeObservability(contractContents)
            : [];
        if (solidFindings.length > 0 || backendFindings.length > 0 || obsFindings.length > 0) {
            const updatedCtx = await taskContext.load(args.task_id);
            if (updatedCtx) {
                updatedCtx.ood_solid_findings = solidFindings;
                updatedCtx.backend_implementation_findings = backendFindings;
                updatedCtx.code_observability_findings = obsFindings;
                await taskContext.save(updatedCtx);
            }
        }
        // 决策契约 advisory: 校验 review 输出
        const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
        const reviewExtras = {};
        if (!decisionContract.passed) {
            reviewExtras.decision_contract_advisory = decisionContract.advisory;
        }
        if (solidFindings.length > 0)
            reviewExtras.ood_solid_findings = solidFindings;
        if (backendFindings.length > 0)
            reviewExtras.backend_implementation_findings = backendFindings;
        if (obsFindings.length > 0)
            reviewExtras.code_observability_findings = obsFindings;
        if (oodModule.hasBlockingSolidFindings(solidFindings) || backendModule.hasBlockingBackendFindings(backendFindings) || obsModule.hasBlockingObservabilityFindings(obsFindings)) {
            reviewExtras.delivery_blocked = true;
            reviewExtras.diagnostic_code = "SF-IMPLEMENTATION-CONTRACT-REVIEW-BLOCKED";
        }
        return { result: Object.keys(reviewExtras).length > 0 ? { ...result, ...reviewExtras } : result };
    });
}
//# sourceMappingURL=status_plan_analyze_review.js.map