import fss from "node:fs";
import path from "node:path";
import { resolveProjectConfig, getProjectKnowledgeDir } from "../../knowledge/loader.js";
import { buildHookAdditionalContext } from "../../engine/pipeline/hook_context_types.js";
import YAML from "yaml";
import { loadConfigEvidenceEntries, } from "../config_commands.js";
import { resolveCurrentProjectConfigReports, validateConfigPrecedence, } from "../../engine/config/config_precedence_contract.js";
import { routeIntent } from "../../engine/pipeline/intent_router.js";
import { debugLog, debug, userInfo, userError, internalWarn } from "../../engine/core/logger.js";
import { auditControlPlaneProject } from "../../engine/contracts/control_plane_contract.js";
import { resolveProjectPath, args } from "../args.js";
import { errorMessage, safeJsonParse } from "../../engine/core/helpers.js";
export async function cmdDoctor() {
    debugLog("CLI: 执行 cmdDoctor");
    const isJson = args.includes("--json");
    const projectPath = process.cwd();
    const report = auditControlPlaneProject(projectPath);
    if (isJson) {
        process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
        return;
    }
    userInfo(`SoloForge 控制面诊断: ${projectPath}`);
    userInfo(`  状态: ${report.passed ? "通过" : "需修复"}`);
    userInfo(`  控制面矩阵: ${report.matrix_count} 类`);
    userInfo(`  枝叶细节: ${report.branch_detail_count} 条`);
    if (report.findings.length === 0) {
        userInfo("  finding: 0");
        return;
    }
    for (const finding of report.findings) {
        const marker = finding.severity === "hard_fail" ? "❌" : finding.severity === "warning" ? "⚠️" : "ℹ️";
        userInfo(`  ${marker} [${finding.code}] ${finding.message}`);
        userInfo(`     恢复: ${finding.recovery}`);
    }
}
export async function cmdPrePrompt() {
    debugLog("CLI: 执行 cmdPrePrompt");
    try {
        // UserPromptSubmit hook 从 stdin 接收 JSON { prompt: "..." }
        const chunks = [];
        for await (const chunk of process.stdin) {
            chunks.push(chunk);
        }
        const stdin = Buffer.concat(chunks).toString().trim();
        if (!stdin) {
            process.exit(0);
            return;
        }
        let userMessage = "";
        try {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any -- MCP SDK 桥接/动态 JSON 解析，字段由运行时决定
            const parsed = safeJsonParse(stdin);
            userMessage = parsed.prompt || parsed.message || "";
        }
        catch {
            userMessage = stdin;
        }
        if (!userMessage || userMessage.length < 2) {
            process.exit(0);
            return;
        }
        // 使用意图路由器分类 — 如果路由属于 SoloForge 范畴，注入结构化上下文
        const decision = routeIntent({ intent: userMessage });
        const additionalContext = buildHookAdditionalContext(decision);
        if (additionalContext) {
            const output = {
                hookSpecificOutput: {
                    hookEventName: "UserPromptSubmit",
                    additionalContext: typeof additionalContext === "string"
                        ? additionalContext
                        : JSON.stringify(additionalContext),
                },
            };
            process.stdout.write(JSON.stringify(output));
        }
    }
    catch (e) {
        internalWarn("CLI", "pre-prompt hook 错误:", e);
    }
    process.exit(0);
}
export async function checkEvidenceWarnings(projectPath) {
    debug("CLI", "执行 checkEvidenceWarnings —", projectPath);
    const warnings = [];
    const configPath = path.join(projectPath, ".soloforge", "config.yaml");
    const evidencePath = path.join(projectPath, ".soloforge", "config.evidence.json");
    if (!fss.existsSync(configPath))
        return warnings;
    if (!fss.existsSync(evidencePath)) {
        warnings.push("config.yaml 存在但 config.evidence.json 缺失 — 来源追溯性丢失");
        return warnings;
    }
    // 检查 mtime 过期
    try {
        const configStat = fss.statSync(configPath);
        const evidenceStat = fss.statSync(evidencePath);
        if (configStat.mtimeMs > evidenceStat.mtimeMs) {
            warnings.push("config.evidence.json 已过期（config.yaml 在 evidence 生成后被修改）");
        }
    }
    catch (e) {
        debug("validate", "文件 mtime 过期检查失败，跳过 —", e);
    }
    // 旧版字段一致性检查（schema v1 evidence）
    try {
        const evidenceRaw = safeJsonParse(fss.readFileSync(evidencePath, "utf-8"));
        if (!evidenceRaw)
            throw new Error("无法解析 config evidence");
        const configContent = fss.readFileSync(configPath, "utf-8");
        const config = YAML.parse(configContent);
        for (const [key, field] of Object.entries(evidenceRaw.fields)) {
            const actualValue = getConfigFieldValue(config, key);
            if (actualValue !== undefined && JSON.stringify(field.value) !== JSON.stringify(actualValue)) {
                warnings.push(`evidence 字段 '${key}' 的值与 config.yaml 不匹配`);
            }
        }
    }
    catch (e) {
        debug("validate", "旧版字段一致性检查失败，跳过 —", e);
    }
    // 使用 schema v2 条目验证配置优先级
    try {
        const entries = loadConfigEvidenceEntries(projectPath);
        // 检查 C 类字段自动写入违规
        for (const e of entries) {
            if (e.source === "cli_flag" || e.source === "mcp_param") {
                if (e.lifetime === "project_persistent") {
                    warnings.push(`CLI/MCP 参数（${e.source}）已持久化到 config — 字段: ${e.field_path}`);
                }
            }
        }
        // 运行实时解析的配置优先级验证
        try {
            const { reports } = await resolveCurrentProjectConfigReports(projectPath);
            const findings = validateConfigPrecedence(reports, entries);
            for (const f of findings) {
                if (f.severity === "hard_fail") {
                    warnings.push(`[${f.rule}] ${f.message}`);
                }
            }
        }
        catch (e) {
            debug("validate", "配置优先级实时验证失败，跳过 —", e);
        }
    }
    catch (e) {
        debug("validate", "schema v2 条目验证失败，跳过 —", e);
    }
    return warnings;
}
export function getConfigFieldValue(config, key) {
    const parts = key.split(".");
    let obj = config;
    for (const part of parts) {
        if (obj === null || typeof obj !== "object")
            return undefined;
        obj = obj[part];
    }
    return obj;
}
export async function cmdValidate() {
    debug("CLI", "执行 cmdValidate");
    const projectPath = resolveProjectPath();
    try {
        const { config, source } = await resolveProjectConfig(projectPath);
        if (source === "inferred") {
            userInfo("ℹ️  配置来源: 自动推断");
        }
        else {
            userInfo("✅ config.yaml 有效");
        }
        // 使用共享函数验证配置优先级
        let hasHardFail = false;
        const hardFailSources = new Set();
        try {
            const { reports, entries } = await resolveCurrentProjectConfigReports(projectPath);
            const findings = validateConfigPrecedence(reports, entries);
            const hardFails = findings.filter(f => f.severity === "hard_fail");
            const advisory = findings.filter(f => f.severity === "advisory");
            if (hardFails.length > 0) {
                hasHardFail = true;
                hardFailSources.add("配置优先级");
                userInfo(`❌ 配置优先级: ${hardFails.length} hard_fail`);
                for (const f of hardFails) {
                    userInfo(`  - [${f.rule}] ${f.field_path ?? "N/A"}: ${f.message}`);
                }
            }
            if (advisory.length > 0) {
                userInfo(`⚠️  配置优先级: ${advisory.length} advisory`);
                for (const f of advisory) {
                    userInfo(`  - [${f.rule}] ${f.field_path ?? "N/A"}: ${f.message}`);
                }
            }
            if (hardFails.length === 0 && advisory.length === 0) {
                userInfo("✅ 配置优先级验证通过");
            }
        }
        catch (e) {
            debug("validate", "配置优先级验证失败，跳过 —", e);
        }
        // Evidence 检查
        const evidenceWarnings = await checkEvidenceWarnings(projectPath);
        for (const w of evidenceWarnings) {
            userInfo(`⚠️  evidence: ${w}`);
        }
        // 知识治理统一入口：生命周期、语义、文档与语言策略的轻量主链路消费
        try {
            const { runKnowledgeGovernanceCheck } = await import("../../engine/knowledge/knowledge_governance_gate.js");
            const kgReport = runKnowledgeGovernanceCheck({
                project_language: "zh",
                contents: [{ id: "cli-validate", domain: "user_feedback", content: "SoloForge 校验输出保持中文语义优先" }],
            });
            if (kgReport.hard_fail_count > 0) {
                userInfo(`❌ 知识治理: ${kgReport.hard_fail_count} hard_fail`);
                for (const f of kgReport.findings.filter((f) => f.severity === "hard_fail")) {
                    userInfo(`  - [${f.kind}] ${f.message_zh}`);
                }
                hasHardFail = true;
                hardFailSources.add("知识治理");
            }
            else {
                userInfo(`✅ 知识治理检查: ${kgReport.warning_count} warning, 0 hard_fail`);
            }
        }
        catch (e) {
            userInfo(`  ⚠ 知识治理检查异常: ${errorMessage(e)}`);
        }
        // 检查知识文件
        const knowledgeDir = getProjectKnowledgeDir(config);
        if (fss.existsSync(knowledgeDir)) {
            const { KnowledgeIndexManager } = await import("../../knowledge/index_manager.js");
            const index = new KnowledgeIndexManager(config, { watch: false });
            try {
                await index.build();
                const entries = index.getAllEntries();
                userInfo(`✅ ${entries.project.length} 条项目知识已索引`);
                const issues = await index.checkHealth();
                if (issues.length > 0) {
                    userInfo(`⚠️  ${issues.length} 个健康问题:`);
                    for (const { entry, issue } of issues) {
                        userInfo(`  - ${entry.name}: ${issue}`);
                    }
                }
            }
            finally {
                await index.close();
            }
            const { auditProjectKnowledge } = await import("../../engine/contracts/project_knowledge_contract.js");
            const pkReport = auditProjectKnowledge(projectPath, config);
            if (pkReport.hard_fail_count > 0) {
                userInfo(`❌ 项目知识承载: ${pkReport.hard_fail_count} hard_fail`);
                for (const asset of pkReport.assets) {
                    for (const finding of asset.findings.filter((f) => f.severity === "hard_fail")) {
                        userInfo(`  - ${asset.rel_path}: [${finding.code}] ${finding.message_zh}`);
                    }
                }
                hasHardFail = true;
                hardFailSources.add("项目知识承载");
            }
            else {
                userInfo(`✅ 项目知识承载: ${pkReport.total} 条，${pkReport.injectable} 条可注入，${pkReport.index_only} 条仅索引，0 hard_fail`);
            }
        }
        // 扩展清单校验 (problem-39: validateExtensionManifest)
        try {
            const { validateExtensionManifest } = await import("../../engine/contracts/extension_contract.js");
            const extResult = validateExtensionManifest({ extension_id: "soloforge-cli-validate", name: "SoloForge CLI 验证", version: "1.0.0", provider: "soloforge", extension_type: "workflow", contract_ids: [], capability_ids: [], permissions: ["read_project"], entrypoints: [], outputs: [], default_state: "disabled", compatibility: { min_soloforge_version: "1.0.0" } }, { extension_id: "soloforge-cli-validate", claimed_capabilities: [], claimed_enforcement: "advisory", third_party: false });
            if (extResult.violations.length > 0) {
                userInfo("  ✗ 扩展清单校验失败:");
                for (const v of extResult.violations)
                    userInfo(`    - ${v}`);
                hasHardFail = true;
                hardFailSources.add("扩展清单");
            }
            else {
                userInfo("  ✓ 扩展清单校验通过");
            }
        }
        catch (e) {
            userInfo(`  ⚠ 扩展清单校验异常: ${errorMessage(e)}`);
        }
        // 演进回归门禁验证 (problem-54: checkDuplicateIssue 消费路径)
        try {
            const { checkDuplicateIssue } = await import("../../engine/contracts/evolution_regression_gate.js");
            // 验证 checkDuplicateIssue 可正常调用（空场景）
            const dupResult = checkDuplicateIssue("__validate_smoke__", []);
            if (dupResult && !dupResult.can_merge_into_existing_issue) {
                userInfo("  ✓ 演进回归门禁: checkDuplicateIssue 入口点可消费");
            }
        }
        catch (e) {
            userInfo(`  ⚠ 演进回归门禁异常: ${errorMessage(e)}`);
        }
        // 平台兼容性检查 (problem-40: normalizePathRef via generatePlatformReport)
        try {
            const { generatePlatformReport } = await import("../../engine/contracts/platform_context.js");
            const platform = {
                os: process.platform,
                arch: process.arch,
                shell: (process.env.SHELL?.includes("zsh") ? "zsh" : process.env.SHELL?.includes("fish") ? "fish" : "bash"),
                path_case_sensitive: process.platform !== "darwin" && process.platform !== "win32",
                path_separator: process.platform === "win32" ? "\\" : "/",
                line_ending: process.platform === "win32" ? "crlf" : "lf",
                supports_symlink: process.platform !== "win32",
                workspace_realpath: projectPath,
            };
            const platformReport = generatePlatformReport(platform, ["package.json", "tsconfig.json"], process.cwd());
            if (platformReport.platform_compatibility_status === "blocked") {
                userInfo(`  ✗ 平台兼容性阻断: ${platformReport.issues_found.join(", ")}`);
                hasHardFail = true;
                hardFailSources.add("平台兼容性");
            }
            else {
                userInfo(`  ✓ 平台兼容性检查: ${platformReport.platform_compatibility_status}`);
            }
        }
        catch (e) {
            userInfo(`  ⚠ 平台兼容性检查异常: ${errorMessage(e)}`);
        }
        // README 命令漂移检测 (problem-30: detectReadmeDrift via validateUserPromise)
        try {
            const { validateUserPromise, getCliCommandContracts } = await import("../../engine/contracts/user_promise.js");
            const { extractReadmeCommands } = await import("../../engine/knowledge/knowledge_scenario_registry.js");
            const fs = await import("node:fs");
            const pathMod = await import("node:path");
            const readmePath = pathMod.join(projectPath, "README.md");
            if (fs.existsSync(readmePath)) {
                const readmeContent = fs.readFileSync(readmePath, "utf-8");
                const readmeCommands = extractReadmeCommands(readmeContent);
                const promiseResult = validateUserPromise(readmeCommands, getCliCommandContracts());
                const hardFails = promiseResult.findings.filter(f => f.severity === "hard_fail");
                const warnings = promiseResult.findings.filter(f => f.severity === "warning");
                if (hardFails.length > 0) {
                    userInfo("  ✗ README 命令漂移:");
                    for (const hf of hardFails)
                        userInfo(`    - ${hf.message_zh}`);
                    hasHardFail = true;
                    hardFailSources.add("README 命令漂移");
                }
                else if (warnings.length > 0) {
                    userInfo("  ⚠ README 命令漂移警告:");
                    for (const w of warnings)
                        userInfo(`    - ${w.message_zh}`);
                }
                else {
                    userInfo("  ✓ README 命令一致性检查通过");
                }
            }
        }
        catch (e) {
            userInfo(`  ⚠ README 命令漂移检测异常: ${errorMessage(e)}`);
        }
        // 双层机制验证 (仅限 SoloForge 自身源码目录)
        if (fss.existsSync(path.join(projectPath, "src", "engine", "contracts", "dual_layer_mechanism_registry.ts"))) {
            const { validateMechanismLayerMaps } = await import("../../engine/contracts/dual_layer_mechanism_registry.js");
            const dlFindings = validateMechanismLayerMaps();
            const dlHard = dlFindings.filter((f) => f.severity === "hard_fail");
            const dlAdvisory = dlFindings.filter((f) => f.severity === "advisory");
            if (dlHard.length > 0) {
                userInfo(`❌ 双层机制验证: ${dlHard.length} hard_fail`);
                for (const f of dlHard) {
                    userInfo(`  - [${f.finding_type}] ${f.mechanism_id}: ${f.message}`);
                }
                userError(`❌ validate 失败: 双层机制存在 ${dlHard.length} hard_fail`);
                process.exit(1);
            }
            else {
                userInfo(`✅ 双层机制验证: ${dlAdvisory.length} advisory, 0 hard_fail`);
            }
            // problem-34: 测试策略覆盖验证 — 从 contract_registry 真实元数据构建
            try {
                const { validateTestStrategy } = await import("../../engine/audit/test_strategy.js");
                const { getAllContracts } = await import("../../engine/contracts/contract_registry.js");
                const enforcedContracts = getAllContracts().filter((c) => c.state === "enforced");
                let tsHardFail = false;
                let tsChecked = 0;
                let tsPending = 0;
                for (const c of enforcedContracts) {
                    const hasTests = c.test_files && c.test_files.length > 0;
                    const hasLifecycle = c.lifecycle_test_files && c.lifecycle_test_files.length > 0;
                    if (!hasTests) {
                        // enforced 契约无测试文件元数据 → hard_fail，不得用 required_test_types:[] 掩盖
                        userInfo(`❌ 测试策略: ${c.contract_id} — enforced 契约缺少 test_files 元数据，无法验证覆盖`);
                        tsHardFail = true;
                        tsPending++;
                        continue;
                    }
                    const coverage = {
                        contract_id: c.contract_id,
                        required_test_types: ["unit"],
                        coverage_status: hasLifecycle ? "satisfied" : "partial",
                        satisfied_types: ["unit"],
                        missing_types: hasLifecycle ? [] : ["lifecycle"],
                        test_files: c.test_files ?? [],
                        has_lifecycle_test: hasLifecycle,
                        has_must_fail_case: false,
                    };
                    const tsErrors = validateTestStrategy(c.contract_id, true, coverage);
                    tsChecked++;
                    for (const e of tsErrors) {
                        if (e.severity === "hard_fail") {
                            tsHardFail = true;
                            userInfo(`❌ 测试策略: ${c.contract_id} — ${e.error}`);
                        }
                    }
                }
                if (tsHardFail) {
                    userError(`❌ 测试策略覆盖验证失败: ${tsChecked} 个已检查, ${tsPending} 个元数据缺失`);
                    hasHardFail = true;
                    hardFailSources.add("测试策略覆盖");
                }
                else {
                    userInfo(`✅ 测试策略覆盖: 已检查 ${tsChecked} 个 enforced 契约`);
                }
            }
            catch (e) {
                userError(`❌ 测试策略验证异常: ${errorMessage(e)}`);
                hasHardFail = true;
                hardFailSources.add("测试策略覆盖");
            }
        } // 双层机制检查结束
        try {
            const { planNextAction } = await import("../../engine/workflow/next_action_planner.js");
            const navigation = await planNextAction(projectPath);
            userInfo(`  阶段: ${navigation.project_stage}${navigation.task_stage ? ` / ${navigation.task_stage}` : ""}`);
            if (navigation.blocking_reasons.length > 0) {
                userInfo(`  导航阻断: ${navigation.blocking_reasons.join("; ")}`);
            }
            userInfo(`  下一步: ${navigation.work_package?.goal_zh ?? navigation.recommended_prompt_zh}`);
        }
        catch (e) {
            userInfo(`  ⚠ 导航摘要异常: ${errorMessage(e)}`);
        }
        if (hasHardFail) {
            const sources = hardFailSources.size > 0 ? Array.from(hardFailSources).join("、") : "校验项";
            userError(`❌ validate 失败: ${sources} 存在 hard_fail`);
            process.exit(1);
        }
    }
    catch (e) {
        userError(`❌ 验证失败: ${errorMessage(e)}`);
        process.exit(1);
    }
}
export async function cmdValidateMechanisms() {
    debug("CLI", "执行 cmdValidateMechanisms");
    // 从编译后的二进制位置推导根目录: dist/bin/soloforge.js -> 项目根
    const soloforgeRoot = path.resolve(import.meta.dirname, "..", "..");
    const projectPath = fss.existsSync(path.join(soloforgeRoot, "src", "engine"))
        ? soloforgeRoot
        : process.cwd();
    try {
        const { validateMechanismLayerMaps } = await import("../../engine/contracts/dual_layer_mechanism_registry.js");
        const findings = validateMechanismLayerMaps(undefined, projectPath);
        const hardFails = findings.filter((f) => f.severity === "hard_fail");
        const advisory = findings.filter((f) => f.severity === "advisory");
        if (findings.length === 0) {
            userInfo("✅ 所有双层机制映射验证通过，无发现。");
            process.exit(0);
            return;
        }
        if (advisory.length > 0) {
            userInfo(`⚠️  advisory findings (${advisory.length}):`);
            for (const f of advisory) {
                userInfo(`  - [${f.finding_type}] ${f.mechanism_id}: ${f.message}`);
            }
        }
        if (hardFails.length > 0) {
            userInfo(`❌ hard_fail findings (${hardFails.length}):`);
            for (const f of hardFails) {
                userInfo(`  - [${f.finding_type}] ${f.mechanism_id}: ${f.message}`);
            }
            userInfo(`\n❌ 双层机制验证失败: ${hardFails.length} hard_fail`);
            process.exit(1);
        }
        userInfo(`\n✅ 双层机制验证通过，${advisory.length} advisory findings`);
        // 审计摘要
        try {
            const { auditTemplateMechanisms } = await import("../../engine/templates/template_mechanism_auditor.js");
            const audit = auditTemplateMechanisms(projectPath);
            if (audit.hard_fail_count > 0) {
                userInfo(`\n❌ 模板审计摘要: ${audit.hard_fail_count} hard_fail, ${audit.unmapped_template_assets.length} unmapped`);
                process.exit(1);
            }
            else {
                userInfo(`\n📊 模板审计: ${audit.total_template_files} 文件, ${audit.unmapped_template_assets.length} unmapped, ${audit.advisory_count} advisory`);
            }
        }
        catch (e) {
            userError(`❌ 模板审计异常: ${errorMessage(e)}`);
            process.exit(1);
        }
        try {
            const { runFullHealthCheck } = await import("../../engine/contracts/mechanism_health_check.js");
            const health = runFullHealthCheck(projectPath);
            if (health.hard_fail_count > 0) {
                userInfo(`\n❌ 机制运行时健康度: ${health.hard_fail_count} hard_fail`);
                for (const f of health.findings.filter((f) => f.severity === "hard_fail")) {
                    userInfo(`  - [${f.kind}] ${f.target}: ${f.message_zh}`);
                }
                process.exit(1);
            }
            userInfo(`\n📊 机制运行时健康度: ${health.warning_count} warning, 0 hard_fail`);
        }
        catch (e) {
            userError(`❌ 机制运行时健康度检查异常: ${errorMessage(e)}`);
            process.exit(1);
        }
    }
    catch (e) {
        userError(`❌ validate-mechanisms 失败: ${errorMessage(e)}`);
        process.exit(1);
    }
}
//# sourceMappingURL=validate.js.map