// ── sf_verify、sf_record_verification_execution、sf_learn 工具注册 ──
// 从 tools.ts 第 2578-3300 行提取。
import path from "node:path";
import { promises as fsp } from "node:fs";
import crypto from "node:crypto";
import { internalWarn } from "../../../engine/core/logger.js";
import { isSameOrDescendantPath } from "../../../engine/core/path_scope_utils.js";
import { detectTaskStage } from "../../../engine/pipeline/task_stage_detector.js";
import { verifyArtifact } from "../../../engine/contracts/artifact_contract_registry.js";
import { verifyRouteDecisionContract } from "../../../engine/contracts/route_decision_contract_verifier.js";
import { scanArtifactForOmissions } from "../../../engine/contracts/omission_scanner.js";
import { detectLazyPatterns } from "../../../engine/contracts/lazy_pattern_detector.js";
import { verifyErrorHandlingPaths } from "../../../engine/contracts/error_path_verifier.js";
import { verifyBehaviorCoverage } from "../../../engine/contracts/behavior_coverage_verifier.js";
import { inferArtifactKindFromPath } from "../../../bin/commands/check_write.js";
import { TOOL_DIAGNOSTIC_CODES } from "../../../engine/audit/diagnostic_registry.js";
import { createToolRegistrar } from "../middleware.js";
import { VerifySchema, RecordVerificationExecutionSchema, LearnSchema } from "../schemas.js";
import { lazyVerifier, lazyEvolver, lazyTraceability, lazyOodSolid, lazyBackendImplementation, lazyCodeObservability, lazyDesignArtifactPack, lazyStandardAssetContract, lazyVerificationContract, lazyEnforcementGuard, lazyFailureReport, lazyDegradation, } from "../lazy_loaders.js";
import { errorMessage } from "../../../engine/core/helpers.js";
export async function registerVerifyLearnTools(ctx) {
    const { registerSafeTool, loadRelevantAnchors } = createToolRegistrar(ctx);
    const { taskContext, config, projectPath, ioController, knowledgeIndex } = ctx;
    // ── sf_verify: 生成验证命令（构建、测试、验收检查） ──
    registerSafeTool("sf_verify", "根据变更文件生成验证命令（构建、测试、验收检查），由 Claude Code Bash 执行", VerifySchema, async (args) => {
        const loadedCtx = await taskContext.load(args.task_id);
        if (!loadedCtx) {
            return {
                result: { error: "任务不存在" },
            };
        }
        // Phase 9a: 知识感知 — 加载阶段匹配的审查规则、代码模式和检查清单
        if (knowledgeIndex) {
            const stage = detectTaskStage(loadedCtx);
            const reviewRules = knowledgeIndex.query({
                type: "review_rule",
                stages: stage ? [stage] : undefined,
                limit: 5,
            });
            const codePatterns = knowledgeIndex.query({
                type: "pattern",
                stages: stage ? [stage] : undefined,
                limit: 3,
            });
            const checklists = knowledgeIndex.query({
                type: "checklist",
                stages: stage ? [stage] : undefined,
                limit: 2,
            });
            loadedCtx.review_knowledge_hints = [...reviewRules, ...codePatterns, ...checklists]
                .map(e => e.body ?? e.when).filter(Boolean);
            await taskContext.save(loadedCtx);
        }
        const implementationFiles = args.changed_files.filter((file) => /\.(?:ts|tsx|js|jsx|java|kt|cs|go|py)$/.test(file)
            && !/(?:^|\/)tests?\//.test(file));
        if (implementationFiles.length > 0) {
            const implementationContents = {};
            for (const changedFile of implementationFiles) {
                const absoluteFile = path.resolve(projectPath, changedFile);
                try {
                    if (isSameOrDescendantPath(absoluteFile, path.resolve(projectPath), { caseSensitive: false }) && (await fsp.stat(absoluteFile)).isFile()) {
                        implementationContents[changedFile] = await fsp.readFile(absoluteFile, "utf-8");
                    }
                }
                catch {
                    // 文件缺失会由验证命令或现有产物检查报告。
                }
            }
            const traceabilityModule = await lazyTraceability();
            const traceVerification = traceabilityModule.verifyChangedFilesAgainstDesignTraceability(projectPath, implementationFiles, loadedCtx);
            if (!traceVerification.passed) {
                loadedCtx.traceability_binding = {
                    requirement_ids: traceVerification.binding_ids.filter((id) => id.startsWith("REQ-")),
                    prototype_ids: traceVerification.binding_ids.filter((id) => id.startsWith("PROTO-")),
                    architecture_ids: traceVerification.binding_ids.filter((id) => id.startsWith("ARCH-")),
                    detail_design_ids: traceVerification.binding_ids.filter((id) => id.startsWith("DD-")),
                    phase_ids: traceVerification.binding_ids.filter((id) => id.startsWith("PHASE-")),
                    slice_ids: traceVerification.binding_ids.filter((id) => id.startsWith("SLICE-")),
                    acceptance_ids: traceVerification.binding_ids.filter((id) => id.startsWith("AC-")),
                    status: "missing",
                    findings: traceVerification.findings.map((finding) => `${finding.code}: ${finding.message_zh}`),
                };
                await taskContext.save(loadedCtx);
                return {
                    result: {
                        error: "编码变更未绑定需求/原型/设计/切片/验收追踪链路，需修复后重验",
                        status: "blocked",
                        diagnostic_code: TOOL_DIAGNOSTIC_CODES.traceabilityVerifyFailed,
                        traceability_findings: traceVerification.findings,
                        recovery: "补齐追踪矩阵并在任务中绑定 PHASE-*、SLICE-*、DD-*、AC-* 后重新执行 sf_verify",
                    },
                };
            }
            const oodModule = await lazyOodSolid();
            const oodGate = oodModule.evaluateOodDesignGate({
                task_id: args.task_id,
                intent: loadedCtx.intent,
                route: loadedCtx.expansion?.workflow_trace?.route,
                changed_files: implementationFiles,
                summary: loadedCtx.ood_solid_summary,
            });
            if (!oodGate.allowed) {
                return {
                    result: {
                        error: oodGate.reason_zh,
                        status: "blocked",
                        diagnostic_code: TOOL_DIAGNOSTIC_CODES.oodMissingSummary,
                        ood_solid_summary: oodGate.required_summary,
                        recovery: "完成 OOD/SOLID 摘要后重新执行 sf_expand 与 sf_verify",
                    },
                };
            }
            const backendModule = await lazyBackendImplementation();
            const backendGate = backendModule.evaluateBackendImplementationGate({
                task_id: args.task_id,
                intent: loadedCtx.intent,
                route: loadedCtx.expansion?.workflow_trace?.route,
                changed_files: implementationFiles,
                work_package: loadedCtx.backend_implementation_work_package,
            });
            if (!backendGate.allowed) {
                return {
                    result: {
                        error: backendGate.reason_zh,
                        status: "blocked",
                        diagnostic_code: TOOL_DIAGNOSTIC_CODES.backendMissingSummary,
                        backend_implementation_work_package: backendGate.work_package,
                        recovery: "完成后端工程工作包后重新执行 sf_expand 与 sf_verify",
                    },
                };
            }
            const solidFindings = oodGate.applicable ? oodModule.reviewSolidCode(implementationContents) : [];
            const backendFindings = backendGate.applicable ? backendModule.reviewBackendImplementationFiles(implementationContents) : [];
            if (backendGate.applicable) {
                const openApiPath = path.join(projectPath, "docs", "api", "openapi.yaml");
                const apiMarkdownPath = path.join(projectPath, "docs", "architecture", "03-API接口规格文档.md");
                const migrationDirectory = path.join(projectPath, "db", "migrations");
                const openapiText = await fsp.access(openApiPath).then(() => true, () => false) ? await fsp.readFile(openApiPath, "utf-8") : undefined;
                const apiDocumentText = await fsp.access(apiMarkdownPath).then(() => true, () => false) ? await fsp.readFile(apiMarkdownPath, "utf-8") : undefined;
                let migrationText;
                if (await fsp.access(migrationDirectory).then(() => true, () => false)) {
                    const migrationFiles = (await fsp.readdir(migrationDirectory)).filter((name) => /\.sql$/i.test(name));
                    const migrationContents = await Promise.all(migrationFiles.map((name) => fsp.readFile(path.join(migrationDirectory, name), "utf-8")));
                    migrationText = migrationContents.join("\n");
                }
                backendFindings.push(...backendModule.verifyBackendArtifactAlignment({
                    openapiText,
                    apiDocumentText,
                    migrationText,
                    sourceFiles: implementationContents,
                }));
            }
            loadedCtx.ood_solid_findings = solidFindings;
            loadedCtx.backend_implementation_findings = backendFindings;
            await taskContext.save(loadedCtx);
            if (oodModule.hasBlockingSolidFindings(solidFindings)) {
                return {
                    result: {
                        error: "OOD/SOLID 代码复验发现阻断项，需修复后重验",
                        status: "blocked",
                        diagnostic_code: TOOL_DIAGNOSTIC_CODES.oodDeliveryBlock,
                        ood_solid_findings: solidFindings,
                    },
                };
            }
            if (backendModule.hasBlockingBackendFindings(backendFindings)) {
                return {
                    result: {
                        error: "后端实现工程复验发现阻断项，需修复后重验",
                        status: "blocked",
                        diagnostic_code: TOOL_DIAGNOSTIC_CODES.backendDeliveryBlock,
                        backend_implementation_findings: backendFindings,
                    },
                };
            }
            // 问题六十八: 代码可维护性与可观测性契约
            const codeObsModule = await lazyCodeObservability();
            const obsFindings = codeObsModule.verifyChangedFilesObservability({
                changed_files: implementationFiles,
                file_contents: implementationContents,
                intent: loadedCtx.intent,
            });
            loadedCtx.code_observability_findings = obsFindings;
            await taskContext.save(loadedCtx);
            if (codeObsModule.hasBlockingObservabilityFindings(obsFindings)) {
                return {
                    result: {
                        error: "代码可维护性/可观测性复验发现阻断项，需修复后重验",
                        status: "blocked",
                        diagnostic_code: TOOL_DIAGNOSTIC_CODES.codeObservabilityFinding,
                        code_observability_findings: obsFindings,
                    },
                };
            }
        }
        // 问题六十二: 设计产物验证必须读取用户项目真实文件，不接受占位合同自证通过。
        const verifyWorkflowIntent = loadedCtx.route_decision?.workflow_intent ?? loadedCtx.classification?.route_decision?.workflow_intent;
        const touchesDesignArtifacts = args.changed_files.some((file) => /docs\/architecture\/|docs\/api\/|openapi|db\/(?:migrations|schema)|架构设计|数据库设计|API接口规格/i.test(file));
        if (verifyWorkflowIntent === "architecture_design" || touchesDesignArtifacts) {
            const designModule = await lazyDesignArtifactPack();
            const designPack = loadedCtx.design_artifact_pack ?? designModule.createDesignArtifactPack(args.task_id);
            const designVerification = designModule.verifyDesignArtifactPack(projectPath, designPack);
            loadedCtx.design_artifact_pack = {
                ...designPack,
                status: designVerification.status,
                findings: designVerification.findings,
                baseline_hashes: designVerification.hashes,
                verified_at: new Date().toISOString(),
            };
            await taskContext.save(loadedCtx);
            if (!designVerification.passed) {
                return {
                    result: {
                        error: "设计产物包复验未通过，不得继续生成编码或交付结论",
                        status: "blocked",
                        diagnostic_code: "SF-DESIGN-PACK-VERIFY-FAILED",
                        design_artifact_findings: designVerification.findings,
                        checked_files: designVerification.checked_files,
                        recovery: "修复设计产物、补充用户确认并重新执行 sf_verify；不得只提交报告绕过缺口",
                    },
                };
            }
        }
        // 问题六十三: 模板契约验证 — 按文件逐一匹配契约并校验
        const sacModule = await lazyStandardAssetContract();
        const formalArtifactContract = sacModule.matchTemplateContract({
            output_artifact_kind: loadedCtx.artifact_output?.kind,
            workflow_intent: verifyWorkflowIntent,
            route_decision: loadedCtx.route_decision?.workflow_intent,
        });
        if (formalArtifactContract || !sacModule.isLowRiskTask({
            route_decision: verifyWorkflowIntent ?? loadedCtx.classification?.route_decision?.workflow_intent,
            workflow_intent: verifyWorkflowIntent,
            changed_files: args.changed_files,
        })) {
            for (const changedFile of args.changed_files) {
                const absFile = path.join(projectPath, changedFile);
                if (!await fsp.access(absFile).then(() => true, () => false) || !/\.md$/.test(changedFile))
                    continue;
                // 按实际文件路径匹配契约（不再使用 changed_files[0] 的契约校验全部文件）
                const perFileContract = sacModule.matchTemplateContract({
                    output_artifact_kind: loadedCtx.artifact_output?.kind,
                    workflow_intent: verifyWorkflowIntent,
                    route_decision: loadedCtx.route_decision?.workflow_intent,
                    file_path: changedFile,
                });
                if (!perFileContract)
                    continue;
                const content = await fsp.readFile(absFile, "utf-8");
                // 草稿阻断下游消费 — 不再静默跳过
                if (sacModule.isDraftDocument(content)) {
                    loadedCtx.repair_reverify_directive = {
                        contract_id: perFileContract.asset_id,
                        file_path: changedFile,
                        status: "draft_blocked",
                        repair_suggestion: `文件 ${changedFile} 仍为草稿状态，草稿不可用于实现。请完善内容后重新验证。`,
                        blocked: true,
                    };
                    await taskContext.save(loadedCtx);
                    return {
                        result: {
                            error: `草稿文件 ${changedFile} 不可用于实现，需完善后重新验证`,
                            status: "blocked",
                            diagnostic_code: "SF-CONTRACT-DRAFT",
                            template_contract_id: perFileContract.asset_id,
                            recovery: "完善草稿内容后重新执行 sf_verify",
                        },
                    };
                }
                const contractResult = sacModule.verifyOutputAgainstContract(perFileContract, content, projectPath);
                if (!contractResult.passed) {
                    const repairDirective = sacModule.createRepairReverifyDirective(perFileContract, contractResult);
                    loadedCtx.repair_reverify_directive = {
                        contract_id: perFileContract.asset_id,
                        file_path: changedFile,
                        status: "repair_required",
                        repair_suggestion: repairDirective.repair_suggestion,
                        blocked: true,
                    };
                    await taskContext.save(loadedCtx);
                    return {
                        result: {
                            error: `文件 ${changedFile} 模板契约验证未通过，进入修复重验闭环`,
                            status: "blocked",
                            diagnostic_code: TOOL_DIAGNOSTIC_CODES.contractDraft,
                            template_contract_id: perFileContract.asset_id,
                            missing_fields: contractResult.missing_fields,
                            messages: contractResult.messages,
                            repair_suggestion: repairDirective.repair_suggestion,
                            recovery: "修复文档缺口后重新执行 sf_verify；不得只报告不修复",
                        },
                    };
                }
            }
            // 全部契约验证通过 — 清零修复重验指令
            if (loadedCtx.repair_reverify_directive) {
                delete loadedCtx.repair_reverify_directive;
                await taskContext.save(loadedCtx);
            }
        }
        // ── 遗漏扫描：检测空洞章节、占位符、空表格（防 AI 偷懒） ──
        const omissionScannedFiles = [];
        const allOmissionFindings = [];
        for (const changedFile of args.changed_files) {
            if (!/\.md$/.test(changedFile))
                continue;
            const kind = inferArtifactKindFromPath(changedFile);
            if (!kind)
                continue;
            const absFile = path.join(projectPath, changedFile);
            if (!await fsp.access(absFile).then(() => true, () => false))
                continue;
            const content = await fsp.readFile(absFile, "utf-8");
            if (content.length < 100)
                continue; // 初始写入跳过
            const omissionResult = scanArtifactForOmissions(kind, content, {
                generate_adversarial_prompt: true,
            });
            if (omissionResult.findings.length > 0) {
                omissionScannedFiles.push(changedFile);
                allOmissionFindings.push({ file: changedFile, findings: omissionResult.findings });
            }
            if (!omissionResult.passed) {
                const hardFails = omissionResult.findings.filter((f) => f.severity === "hard_fail");
                const reasons = hardFails.map((f) => f.message).join("；");
                await taskContext.save(loadedCtx);
                return {
                    result: {
                        error: `产物遗漏扫描失败（${changedFile}）：${reasons}`,
                        status: "blocked",
                        diagnostic_code: "SF-OMISSION-SCAN-FAILED",
                        recovery: `补齐以下缺失内容后重新执行 sf_verify：${reasons}`,
                    },
                };
            }
        }
        // 将遗漏扫描结果写入 VerifyResult（通过 loadedCtx 传递到最终结果组装）
        if (omissionScannedFiles.length > 0) {
            const totalFindings = allOmissionFindings.reduce((s, o) => s + o.findings.length, 0);
            const hardFailCount = allOmissionFindings.reduce((s, o) => s + o.findings.filter((f) => f.severity === "hard_fail").length, 0);
            // 生成对抗性 prompt（取第一个有 findings 的文件的 prompt）
            const firstResultWithPrompt = allOmissionFindings[0];
            loadedCtx.omission_scan_result = {
                scanned_files: omissionScannedFiles,
                total_findings: totalFindings,
                hard_fail_count: hardFailCount,
                summary: hardFailCount > 0
                    ? `❌ 遗漏扫描发现 ${totalFindings} 项问题（${hardFailCount} 个阻塞）`
                    : `⚠️ 遗漏扫描发现 ${totalFindings} 个警告`,
                adversarial_prompt: firstResultWithPrompt?.findings.length
                    ? `对文件 ${firstResultWithPrompt.file} 执行深度遗漏审计`
                    : undefined,
            };
            await taskContext.save(loadedCtx);
        }
        // ── 步骤 7a: 偷懒模式检测（.ts 文件） ──
        let lazyPatternHardFails = 0;
        let lazyPatternWarnings = 0;
        for (const changedFile of args.changed_files) {
            if (!/\.ts$/.test(changedFile) || /\.d\.ts$/.test(changedFile))
                continue;
            const absFile = path.join(projectPath, changedFile);
            if (!await fsp.access(absFile).then(() => true, () => false))
                continue;
            const content = await fsp.readFile(absFile, "utf-8");
            const findings = detectLazyPatterns(content, changedFile);
            const hfs = findings.filter((f) => f.severity === "hard_fail");
            const wfs = findings.filter((f) => f.severity === "warning");
            lazyPatternHardFails += hfs.length;
            lazyPatternWarnings += wfs.length;
            if (hfs.length > 0) {
                const reasons = hfs.map((f) => f.message).join("；");
                await taskContext.save(loadedCtx);
                return {
                    result: {
                        error: `代码偷懒模式检测失败（${changedFile}）：${reasons}`,
                        status: "blocked",
                        diagnostic_code: "SF-LAZY-PATTERN-DETECTED",
                        recovery: `修复以下代码质量问题后重新执行 sf_verify：${reasons}`,
                    },
                };
            }
        }
        // ── 步骤 7b: 错误处理路径验证（.ts 文件） ──
        let errorPathHardFails = 0;
        for (const changedFile of args.changed_files) {
            if (!/\.ts$/.test(changedFile) || /\.d\.ts$/.test(changedFile))
                continue;
            const absFile = path.join(projectPath, changedFile);
            if (!await fsp.access(absFile).then(() => true, () => false))
                continue;
            const content = await fsp.readFile(absFile, "utf-8");
            const findings = verifyErrorHandlingPaths(content, changedFile);
            const hfs = findings.filter((f) => f.severity === "hard_fail");
            errorPathHardFails += hfs.length;
            if (hfs.length > 0) {
                const reasons = hfs.map((f) => f.message).join("；");
                await taskContext.save(loadedCtx);
                return {
                    result: {
                        error: `错误处理路径验证失败（${changedFile}）：${reasons}`,
                        status: "blocked",
                        diagnostic_code: "SF-ERROR-PATH-VERIFICATION-FAILED",
                        recovery: `修复以下错误处理问题后重新执行 sf_verify：${reasons}`,
                    },
                };
            }
        }
        // ── 步骤 7c: 行为覆盖率检查 ──
        const coverageFindings = verifyBehaviorCoverage(args.changed_files, projectPath);
        const coverageWarnings = coverageFindings.length;
        // ── 汇总 code_quality 结果到 loadedCtx ──
        if (lazyPatternHardFails > 0 || lazyPatternWarnings > 0 || errorPathHardFails > 0 || coverageWarnings > 0) {
            loadedCtx.code_quality_result = {
                lazy_pattern_findings: lazyPatternHardFails + lazyPatternWarnings,
                error_path_findings: errorPathHardFails,
                test_quality_hard_fails: 0,
                mutation_hard_fails: 0,
                behavior_coverage_warnings: coverageWarnings,
                summary: `偷懒模式: ${lazyPatternHardFails} 阻塞/${lazyPatternWarnings} 警告；错误路径: ${errorPathHardFails}；行为覆盖: ${coverageWarnings} 警告`,
            };
            await taskContext.save(loadedCtx);
        }
        // RouteDecision 合同验证 — 无条件，在状态预检之前
        const rdFromCtx = loadedCtx.route_decision ?? loadedCtx.classification?.route_decision ?? null;
        const wtFromCtx = loadedCtx.workflow_trace ?? loadedCtx.expansion?.workflow_trace ?? null;
        const rdContractInput = {
            route_decision: rdFromCtx,
            workflow_trace: wtFromCtx,
            expansion_input_materials: loadedCtx.expansion?.input_materials?.map((m) => ({ path_or_ref: m.path_or_ref })),
            expansion_output_artifact: loadedCtx.artifact_output ? { kind: loadedCtx.artifact_output.kind, path: loadedCtx.artifact_output.path } : null,
            expansion_constraints: loadedCtx.expansion?.contract?.constraints,
        };
        const rdFindings = verifyRouteDecisionContract(rdContractInput);
        const hasHardFail = rdFindings.some(f => f.severity === "hard_fail" || f.severity === "blocked");
        if (hasHardFail) {
            return {
                result: {
                    error: "RouteDecision 合同检查失败",
                    route_decision_contract_findings: rdFindings,
                    status: "blocked",
                },
            };
        }
        const VALID_VERIFY_STATES = ["executing", "retrying"];
        if (!VALID_VERIFY_STATES.includes(loadedCtx.status)) {
            return {
                result: { error: `任务状态 ${loadedCtx.status} 不可验证，需要 executing 或 retrying`, status: loadedCtx.status },
            };
        }
        const acceptanceItems = loadedCtx.expansion
            ? [...loadedCtx.expansion.acceptance.automated, ...loadedCtx.expansion.acceptance.manual]
            : [];
        // H4: 工作区完整性检查 — advisory 模式，仅警告不阻断
        const integrity = await ioController.verify();
        const h4Warning = !integrity.clean
            ? { warning: `H4 advisory: ${integrity.message}`, dirty_files: integrity.dirty_files }
            : undefined;
        const verifyResult = (await lazyVerifier()).generateVerifyCommands(config, args.changed_files, acceptanceItems, loadedCtx?.expansion?.workflow_trace?.route);
        verifyResult.task_id = args.task_id;
        // 创建 VerificationPlan（plan_only，非执行结果）
        const vcModule = await lazyVerificationContract();
        const allCommands = [
            ...(verifyResult.checks?.build ?? []),
            ...(verifyResult.checks?.tests ?? []),
        ].map((c) => c.command);
        const vPlan = vcModule.createVerificationPlan(args.task_id, allCommands, acceptanceItems.map((a) => a.description));
        // sf_verify 仅生成计划，不执行命令 — 始终保存 not_executed
        // 真实执行结果必须通过 recordVerificationExecution 单独录入
        const vResult = vcModule.createNotExecutedResult(args.task_id, vPlan.plan_id, "sf_verify 生成命令，等待执行");
        // 存储验证契约到任务上下文
        const ctxForV = await taskContext.load(args.task_id);
        if (ctxForV) {
            ctxForV.verification_plan = vPlan;
            ctxForV.verification_result = vResult;
            await taskContext.save(ctxForV);
        }
        // 产物生命周期检查: draft → verified 需要 ArtifactVerificationResult.passed
        let artifactVerificationResult;
        let artifactFileMissing = false;
        if (loadedCtx.artifact_output && loadedCtx.artifact_output.status === "draft") {
            // 验证前解析产物文件并计算 hash
            const artifact = loadedCtx.artifact_output;
            const fullPath = path.join(projectPath, artifact.path);
            if (await fsp.access(fullPath).then(() => true, () => false)) {
                const fileContent = await fsp.readFile(fullPath);
                const hash = crypto.createHash("sha256").update(fileContent).digest("hex");
                artifact.hash = `sha256:${hash}`;
                if (!artifact.evidence_refs.some(r => r.startsWith("file:artifact:"))) {
                    artifact.evidence_refs.push(`file:artifact:path=${artifact.path} hash=sha256:${hash}`);
                }
                // 保存更新后的产物（含 hash）
                const ctxForHash = await taskContext.load(args.task_id);
                if (ctxForHash?.artifact_output) {
                    ctxForHash.artifact_output.hash = artifact.hash;
                    if (!ctxForHash.artifact_output.evidence_refs.some(r => r.startsWith("file:artifact:"))) {
                        ctxForHash.artifact_output.evidence_refs.push(`file:artifact:path=${artifact.path} hash=sha256:${hash}`);
                    }
                    await taskContext.save(ctxForHash);
                }
            }
            else {
                artifactFileMissing = true;
            }
            artifactVerificationResult = verifyArtifact(artifact.kind, artifact);
        }
        // 记录变更文件
        // 写入护栏 — 检查变更文件是否在允许范围
        if (args.changed_files.length > 0) {
            const guardModule = await lazyEnforcementGuard();
            const scopePaths = loadedCtx.expansion?.scope?.allowed_paths ?? [];
            for (const cf of args.changed_files) {
                const writeFindings = guardModule.evaluateWriteGuard(loadedCtx.classification?.route_decision?.route ?? "code_execution", cf, scopePaths, "command_execution_contract");
                if (writeFindings.some((f) => f.blocked)) {
                    return {
                        result: {
                            error: `写入护栏阻断: ${writeFindings[0].reason_zh}`,
                            blocked_file: cf,
                            guard_id: writeFindings[0].guard_id,
                        },
                    };
                }
            }
        }
        await taskContext.setExecution(args.task_id, args.changed_files);
        // 无实际文件变更但存在产物时标记 no_change_artifact
        if (args.changed_files.length === 0 && loadedCtx.artifact_output) {
            const execCtx = await taskContext.load(args.task_id);
            if (execCtx?.execution) {
                execCtx.execution.no_change_artifact = true;
                await taskContext.save(execCtx);
            }
        }
        // 生成验证命令成功后再转换状态，避免操作失败导致任务卡在 verifying
        if (loadedCtx.status === "retrying") {
            await taskContext.updateStatus(args.task_id, "executing");
        }
        await taskContext.updateStatus(args.task_id, "verifying");
        // 存储验证结果
        await taskContext.setVerification(args.task_id, verifyResult);
        // 产物生命周期转换: draft → verified 仅在 ArtifactVerificationResult.passed 时
        if (loadedCtx.artifact_output && loadedCtx.artifact_output.status === "draft" && artifactVerificationResult?.passed) {
            const evidenceRef = `verification:${loadedCtx.task_id}:checks=${artifactVerificationResult.checks.length}:summary=${artifactVerificationResult.summary.slice(0, 60)}`;
            try {
                await taskContext.updateArtifactStatus(args.task_id, {
                    status: "verified",
                    evidenceRef,
                    hasVerification: true,
                });
            }
            catch {
                // 转换被阻止 — 产物保持 draft，流水线继续
            }
        }
        // 认知锚点上下文回放（按变更文件相关性）
        const verifyAnchors = await loadRelevantAnchors({ file_paths: args.changed_files });
        const verifyExtras = {};
        if (h4Warning)
            verifyExtras.h4_advisory = h4Warning;
        if (verifyAnchors && verifyAnchors.length > 0)
            verifyExtras.cognitive_anchors = verifyAnchors;
        if (loadedCtx.artifact_output && loadedCtx.artifact_output.status === "draft" && artifactVerificationResult && !artifactVerificationResult.passed) {
            const reason = artifactFileMissing
                ? `产物文件不存在 (${loadedCtx.artifact_output.path})，无法计算 hash`
                : artifactVerificationResult.summary;
            verifyExtras.artifact_warning = `产物验收检查未通过: ${reason}`;
            verifyExtras.artifact_verification = artifactVerificationResult;
        }
        const verifyPayload = Object.keys(verifyExtras).length > 0
            ? { ...verifyResult, ...verifyExtras }
            : { ...verifyResult };
        // 附加验证契约引用到返回结果
        verifyPayload.verification_plan = vPlan;
        verifyPayload.verification_result = vResult;
        // 问题六十：验证结论必须经过 FactClaimVerifier，不得把计划当结果
        {
            const { createEvidenceGroundingSystem, assessTaskRisk } = await import("../../../engine/contracts/evidence_grounding_contract.js");
            const _vRoute = loadedCtx.route_decision?.route ?? loadedCtx.classification?.route_decision?.route;
            const _vRisk = assessTaskRisk(loadedCtx.classification?.task_type, _vRoute, loadedCtx.intent);
            if (_vRisk !== "low") {
                const _veg = createEvidenceGroundingSystem();
                // 只有真实执行结果才能作为 validation_result 证据
                const _hasRealPassed = loadedCtx.verification_result && loadedCtx.verification_result.status === "passed";
                if (_hasRealPassed) {
                    _veg.registry.register({
                        source_type: "validation_result",
                        authority: "authoritative",
                        freshness: "current",
                        permission: "allowed",
                        scope: "verification",
                        description: `验证状态: ${loadedCtx.verification_result?.status ?? "unknown"}`,
                        source_ref: `verification:${args.task_id}`,
                    });
                }
                // 验证计划注册为 task_context，不冒充 validation_result
                _veg.registry.register({
                    source_type: "task_context",
                    authority: "supporting",
                    freshness: "current",
                    permission: "allowed",
                    scope: "verification_plan",
                    description: `验证计划: ${vPlan ? "已生成" : "未生成"}`,
                    source_ref: `verification-plan:${args.task_id}`,
                });
                if (args.changed_files.length > 0) {
                    _veg.registry.register({
                        source_type: "project_file",
                        authority: "authoritative",
                        freshness: "current",
                        permission: "allowed",
                        scope: "changed_files",
                        description: `变更文件: ${args.changed_files.join(", ")}`,
                        source_ref: `files:${args.changed_files.join(",")}`,
                    });
                }
                const _vClaims = [{
                        id: "claim-verify-1",
                        category: "validation_result",
                        claim_text: "验证结果基于真实命令执行",
                        evidence_ids: _veg.registry.query({ source_type: "validation_result" }).map((e) => e.id),
                        is_uncertain: false,
                        risk_level: _vRisk,
                    }];
                const _vVerResult = _veg.verifier.verify(_vClaims, _vRisk);
                const _vMatrix = _veg.builder.buildContext(_vClaims, {
                    target_claims: _vClaims.map((c) => c.claim_text),
                    source_types: [], keywords: [], max_results: 10,
                });
                _vMatrix.task_id = args.task_id;
                const _vGate = _veg.gate.evaluate(_vMatrix, _vRisk);
                // 写回 TaskContext
                await taskContext.setEvidenceGroundingResult(args.task_id, {
                    evidence_matrix: _vMatrix,
                    evidence_gate_result: _vGate,
                    unsupported_claims: _vGate.unsupported_claims,
                    conflict_resolutions: _vMatrix.conflicts,
                });
                if (_vVerResult.unsupported.length > 0) {
                    // 高风险：只有 plan 无 result → 写入 payload（不用 verifyExtras）
                    verifyPayload._evidence_status = "not_verified";
                    verifyPayload._evidence_reason = "验证结论需真实命令执行结果支撑，验证计划不能当作验证结果。请通过 sf_record_verification_execution 录入真实验证结果。";
                    if (_vRisk === "high" || _vRisk === "critical") {
                        verifyPayload._evidence_blocked = true;
                    }
                    else {
                        verifyPayload._evidence_advisory = "验证结论需真实命令执行结果支撑，验证计划不能当作验证结果";
                    }
                }
            }
        }
        // 验证后核心体验评估
        try {
            const hasVerificationEvidence = (verifyResult.checks?.build?.length ?? 0) > 0 || (verifyResult.checks?.tests?.length ?? 0) > 0;
            // 将完整 CEP 结果写入 TaskContext
            const cepModule = await import("../../../engine/audit/core_experience_principle.js");
            const fullCepEval = cepModule.evaluateCoreExperiencePrinciple({
                task_id: args.task_id, workflow_id: "sf_verify",
                has_mainline_hooks: true, has_owner_contracts: true, natural_language_entry: true,
                requires_internal_contract_knowledge: false, user_path_steps: 3,
                has_failures: false, hard_fail_downgraded: false, forced_heavy_process: false,
                has_sufficient_evidence: hasVerificationEvidence,
                output_too_long_no_summary: false, report_only_no_repair: false,
                failed_but_marked_done: false, auto_repair_overreach: false,
                repair_reverified: false, outputs_raw_noise: false,
            });
            const ctxForCep = await taskContext.load(args.task_id);
            if (ctxForCep) {
                ctxForCep.core_experience_evaluation = fullCepEval;
                await taskContext.save(ctxForCep);
            }
        }
        catch (cepErr) {
            internalWarn("CEP评估", "评估异常 (task=" + args.task_id + "):", errorMessage(cepErr));
        }
        return {
            result: verifyPayload,
        };
    });
    // ── sf_record_verification_execution: 录入真实验证执行结果（唯一 passed 入口） ──
    registerSafeTool("sf_record_verification_execution", "录入真实验证执行结果，VerificationResult.status=passed 的唯一合法入口", RecordVerificationExecutionSchema, async (args) => {
        const ctx = await taskContext.load(args.task_id);
        if (!ctx) {
            return { result: { error: "任务不存在" } };
        }
        // 必须有 VerificationPlan
        const currentPlan = ctx.verification_plan;
        if (!currentPlan) {
            return { result: { error: "任务无 VerificationPlan，先执行 sf_verify 生成计划" } };
        }
        // plan_id 必须与 TaskContext 中当前 plan 一致
        if (args.plan_id !== currentPlan.plan_id) {
            return {
                result: {
                    error: `plan_id 不匹配: 请求 "${args.plan_id}"，当前任务计划 "${currentPlan.plan_id}" [${TOOL_DIAGNOSTIC_CODES.verifyPlanMismatch}]`,
                    diagnostic_code: TOOL_DIAGNOSTIC_CODES.verifyPlanMismatch,
                },
            };
        }
        const vcModule = await lazyVerificationContract();
        const result = vcModule.recordVerificationExecution(args.task_id, args.plan_id, args.execution_records, currentPlan);
        // 持久化到 TaskContext
        const ctxForSave = await taskContext.load(args.task_id);
        if (ctxForSave) {
            ctxForSave.verification_result = result;
            await taskContext.save(ctxForSave);
        }
        return { result };
    });
    // ── sf_learn: 从执行结果中提取知识，支持重试循环控制 ──
    registerSafeTool("sf_learn", "从任务执行结果中提取知识，低置信度暂存，高置信度直接入库", LearnSchema, async (args) => {
        const ctx = await taskContext.load(args.task_id);
        if (!ctx) {
            return {
                result: { error: "任务不存在" },
            };
        }
        const VALID_LEARN_STATES = ["verifying", "executing"];
        if (!VALID_LEARN_STATES.includes(ctx.status)) {
            return {
                result: { error: `任务状态 ${ctx.status} 不可学习，需要 verifying 或 executing`, status: ctx.status },
            };
        }
        // 如适用，记录失败
        if (args.result === "failure" && args.failure_type) {
            await taskContext.setExecution(args.task_id, [], {
                attempt: (ctx.execution?.attempt_count ?? 0) + 1,
                type: args.failure_type,
                message: args.verify_output
                    ? `build=${args.verify_output.build_passed} tests=${args.verify_output.tests_passed}`
                    : "unknown failure",
                timestamp: new Date().toISOString(),
            });
            // 创建 FailureReport（脱敏，非 raw error_output）
            const frModule = await lazyFailureReport();
            const failureClass = args.failure_type;
            const errorOutput = args.verify_output
                ? `build=${args.verify_output.build_passed} tests=${args.verify_output.tests_passed}`
                : "unknown failure";
            const retryCount = (ctx.execution?.attempt_count ?? 0) + 1;
            const policy = frModule.getRecoveryPolicy(failureClass);
            const failureReport = frModule.createFailureReport(args.task_id, failureClass, errorOutput, retryCount, policy?.max_retries ?? 0);
            // 存储 FailureReport 到任务上下文
            const ctxForFailure = await taskContext.load(args.task_id);
            if (ctxForFailure) {
                ctxForFailure.failure_report = failureReport;
                await taskContext.save(ctxForFailure);
            }
            // verifier 不可用时创建 DegradationEvent
            if (!args.verify_output) {
                const degModule = await lazyDegradation();
                const degradationEvent = degModule.createDegradationEvent(args.task_id, "verifier", "full", "验证器输出不可用，无法判断 build/test 结果", ["verification_execution"]);
                if (degradationEvent) {
                    const ctxForDeg = await taskContext.load(args.task_id);
                    if (ctxForDeg) {
                        ctxForDeg.degradation_event = degradationEvent;
                        await taskContext.save(ctxForDeg);
                    }
                }
            }
        }
        // 转换到学习阶段
        await taskContext.updateStatus(args.task_id, "learning");
        const learnResult = await (await lazyEvolver()).evolve({
            taskContext: ctx,
            result: args.result,
            verifyOutput: args.verify_output,
            failureType: args.failure_type,
            retryCount: ctx.execution?.attempt_count ?? 0,
        }, projectPath);
        // 确定最终状态: 重试或完成
        const attemptCount = (ctx.execution?.attempt_count ?? 0) + (args.result === "failure" ? 1 : 0);
        const maxAttempts = ctx.execution?.max_attempts ?? 3;
        if (args.result === "failure" && attemptCount < maxAttempts && args.failure_type !== "deterministic") {
            // 可重试: 转换到重试阶段
            await taskContext.updateStatus(args.task_id, "retrying");
            learnResult.retry_hint = `第 ${attemptCount}/${maxAttempts} 次尝试失败，${args.failure_type === "scope_insufficient" ? "需要扩大范围" : "请修复后重试"}`;
        }
        else {
            // 检查主链路集成 — 即使 build/test 全绿，孤岛仍阻断 done
            const integrationBlocked = ctx.verification?.main_path_integration
                && !ctx.verification.main_path_integration.passed;
            // 核心工程执行原则门禁 — required 原则失败不能进入 completed
            const principlesBlocked = ctx.verification?.core_principles
                && !ctx.verification.core_principles.overall_passed;
            const finalStatus = args.result === "failure"
                ? "failed"
                : (integrationBlocked || principlesBlocked) ? "retrying" : "done";
            await taskContext.updateStatus(args.task_id, finalStatus);
            if (integrationBlocked && finalStatus === "retrying") {
                learnResult.retry_hint = "主链路集成检查失败: 存在孤岛模块，请接入主链路后重试";
            }
            if (principlesBlocked && finalStatus === "retrying") {
                const failedPrinciples = (ctx.verification?.core_principles?.principles ?? [])
                    .filter((p) => p.status === "failed")
                    .map((p) => p.principle_id);
                learnResult.retry_hint = `核心工程执行原则检查失败: ${failedPrinciples.join(", ")}，请修复后重试`;
            }
        }
        return {
            result: learnResult,
        };
    });
}
//# sourceMappingURL=verify_learn.js.map