/**
 * 回归矩阵 + 复杂度预算 — fixture 项目回归测试 + capability 代码量预算。
 *
 * 职责:
 * - fixture 项目模板: Spring Boot, React, Go 的标准结构
 * - 回归矩阵: 对 fixture 验证 classify/expand/verify 兼容性
 * - 复杂度预算: 每个能力模块的代码行数预算，超出 advisory 告警
 */
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { detectFingerprint, generateConfigDraft } from "./zero_config_init.js";
import { debug } from "../core/logger.js";
/** Spring Boot + React 混合项目 fixture，包含 pom.xml、Java Controller 和前端代码 */
export const FIXTURE_SPRING_BOOT = {
    name: "spring-boot-demo",
    tech_stack: "spring-boot + react",
    files: {
        "pom.xml": '<project><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId></parent></project>',
        "src/main/java/com/example/DemoApplication.java": "package com.example;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class DemoApplication {\n    public static void main(String[] args) {\n        SpringApplication.run(DemoApplication.class, args);\n    }\n}",
        "src/main/java/com/example/controller/UserController.java": "package com.example.controller;\nimport org.springframework.web.bind.annotation.*;\nimport java.util.List;\n\n@RestController\n@RequestMapping(\"/api/users\")\npublic class UserController {\n    @GetMapping\n    public List<String> listUsers() {\n        return List.of(\"alice\", \"bob\");\n    }\n}",
        "package.json": '{"name": "frontend", "dependencies": {"react": "^18.2.0"}, "devDependencies": {"vitest": "^2.0.0"}}',
        "web/src/App.tsx": "import React from 'react';\nexport default function App() {\n    return <div>Hello</div>;\n}",
        "tsconfig.json": '{"compilerOptions": {"target": "ES2022"}}',
    },
};
/** React + Vitest 项目 fixture，包含标准 React 应用和测试文件 */
export const FIXTURE_REACT = {
    name: "react-demo",
    tech_stack: "react + vitest",
    files: {
        "package.json": '{"name": "react-demo", "dependencies": {"react": "^18.2.0", "react-dom": "^18.2.0"}, "devDependencies": {"vitest": "^2.0.0", "vite": "^5.0.0", "typescript": "^5.0.0"}}',
        "src/App.tsx": "import React from 'react';\nexport default function App() {\n    return <h1>Hello React</h1>;\n}",
        "src/App.test.ts": "import { describe, it, expect } from 'vitest';\nimport App from './App';\ndescribe('App', () => {\n    it('exposes the React app component', () => {\n        expect(App.name).toBe('App');\n    });\n});",
        "vite.config.ts": "import { defineConfig } from 'vite';\nexport default defineConfig({});",
        "tsconfig.json": '{"compilerOptions": {"target": "ES2022", "jsx": "react-jsx"}}',
    },
};
/** Go 标准项目 fixture，包含 go.mod、main 入口和 service 包 */
export const FIXTURE_GO = {
    name: "go-demo",
    tech_stack: "go",
    files: {
        "go.mod": "module github.com/example/demo\ngo 1.22\n",
        "cmd/main.go": "package main\n\nimport \"fmt\"\n\nfunc main() {\n    fmt.Println(\"hello\")\n}",
        "internal/service/user.go": "package service\n\ntype UserService struct{}\n\nfunc (s *UserService) ListUsers() []string {\n    return []string{\"alice\", \"bob\"}\n}",
    },
};
/** Node.js TypeScript 工具库项目 fixture，包含 TypeScript 编译和 Vitest 测试 */
export const FIXTURE_NODE_TS = {
    name: "node-ts-toolkit",
    tech_stack: "node",
    files: {
        "package.json": '{"name": "my-toolkit", "type": "module", "main": "dist/index.js", "devDependencies": {"typescript": "^5.0.0", "vitest": "^2.0.0"}}',
        "tsconfig.json": '{"compilerOptions": {"target": "ES2022", "module": "ES2022", "outDir": "dist", "rootDir": "src"}}',
        "src/index.ts": "export function add(a: number, b: number): number { return a + b; }\nexport function greet(name: string): string { return `Hello, ${name}!`; }",
        "src/index.test.ts": "import { describe, it, expect } from 'vitest';\nimport { add, greet } from './index.js';\ndescribe('toolkit', () => {\n    it('adds', () => { expect(add(1, 2)).toBe(3); });\n    it('greets', () => { expect(greet('world')).toBe('Hello, world!'); });\n});",
    },
};
/** Monorepo 项目 fixture，包含 backend 和 frontend 两个 workspace 包 */
export const FIXTURE_MONOREPO = {
    name: "monorepo-demo",
    tech_stack: "node",
    files: {
        "package.json": '{"name": "monorepo-root", "private": true, "workspaces": ["packages/*"]}',
        "packages/backend/package.json": '{"name": "@repo/backend", "dependencies": {"express": "^4.18.0"}, "devDependencies": {"typescript": "^5.0.0"}}',
        "packages/backend/tsconfig.json": '{"compilerOptions": {"target": "ES2022", "module": "commonjs", "outDir": "dist"}}',
        "packages/backend/src/server.ts": "import express from 'express';\nconst app = express();\napp.get('/api/health', (_req, res) => res.json({ ok: true }));\nexport { app };",
        "packages/frontend/package.json": '{"name": "@repo/frontend", "dependencies": {"react": "^18.2.0"}, "devDependencies": {"vitest": "^2.0.0", "vite": "^5.0.0"}}',
        "packages/frontend/src/App.tsx": "import React from 'react';\nexport default function App() {\n    return <h1>Monorepo</h1>;\n}",
        "packages/frontend/vite.config.ts": "import { defineConfig } from 'vite';\nexport default defineConfig({});",
    },
};
/** 纯文档项目 fixture，仅包含 Markdown 文档，无代码文件 */
export const FIXTURE_DOCS = {
    name: "docs-only",
    tech_stack: "docs",
    files: {
        "README.md": "# My Project\n\nA documentation-only project with no code.\n",
        "docs/guide.md": "# Getting Started\n\nFollow these steps to get started.\n",
        "docs/api-reference.md": "# API Reference\n\n## Endpoints\n\n- `GET /health`\n- `GET /status`\n",
    },
};
/**
 * 对 fixture 项目运行回归检查矩阵。
 * 纯确定性检查，不依赖 LLM。验证指纹检测、测试框架识别、源码结构和配置文件的存在性。
 * @param fixture - fixture 仓库定义（含名称、技术栈和文件列表）
 * @param fingerprintFn - 指纹检测函数，接收文件映射返回后端/前端/测试框架信息
 * @returns 回归报告，包含各项检查结果和总体通过状态
 */
export function runRegressionMatrix(fixture, fingerprintFn) {
    debug("回归矩阵", "开始运行回归检查，fixture=" + fixture.name);
    const checks = [];
    const fileNames = Object.keys(fixture.files);
    // 1. 指纹检测
    const fp = fingerprintFn(fixture.files);
    const expectsBackend = fixture.tech_stack.includes("spring-boot") || fixture.tech_stack.includes("go");
    const expectsFrontend = fixture.tech_stack.includes("react") || fixture.tech_stack.includes("vue");
    checks.push({
        fixture: fixture.name,
        check: "backend_detection",
        passed: expectsBackend ? fp.backend !== null : true,
        detail: fp.backend ? `检测到: ${fp.backend.framework}` : (expectsBackend ? "预期存在但未检测到" : "不预期"),
    });
    checks.push({
        fixture: fixture.name,
        check: "frontend_detection",
        passed: expectsFrontend ? fp.frontend !== null : true,
        detail: fp.frontend ? `检测到: ${fp.frontend.framework}` : (expectsFrontend ? "预期存在但未检测到" : "不预期"),
    });
    // 2. 测试框架检测
    const expectsTestFramework = fixture.tech_stack.includes("vitest") || fixture.tech_stack.includes("jest");
    checks.push({
        fixture: fixture.name,
        check: "test_framework_detection",
        passed: expectsTestFramework ? fp.test_frameworks.length > 0 : true,
        detail: fp.test_frameworks.length > 0 ? fp.test_frameworks.join(", ") : "none detected (not expected)",
    });
    // 3. 文件结构验证
    const hasSource = fileNames.some((f) => f.includes("src") || f.includes("cmd") || f.includes("internal"));
    checks.push({
        fixture: fixture.name,
        check: "source_structure",
        passed: hasSource,
        detail: hasSource ? "找到源文件" : "无源码目录",
    });
    // 4. 配置文件存在性
    const hasConfig = fileNames.some((f) => f.endsWith(".json") || f.endsWith(".xml") || f.endsWith(".mod") || f.endsWith(".yaml"));
    checks.push({
        fixture: fixture.name,
        check: "config_files",
        passed: hasConfig,
        detail: hasConfig ? "找到配置文件" : "无配置文件",
    });
    const allPassed = checks.every((c) => c.passed);
    debug("回归矩阵", "回归检查完成，全部通过=" + allPassed + "，检查数=" + checks.length);
    return {
        fixture: fixture.name,
        checks,
        passed: allPassed,
        summary: allPassed
            ? `${fixture.name}: all ${checks.length} checks passed`
            : `${fixture.name}: ${checks.filter((c) => !c.passed).length}/${checks.length} checks failed`,
    };
}
/**
 * 在临时目录中写入 fixture 文件并运行真实指纹检测，自动清理临时目录。
 * 用于验证 detectFingerprint 在实际文件系统上的准确性。
 * @param fixtures - 待检测的 fixture 仓库列表（默认包含全部内置 fixture）
 * @returns 真实指纹回归报告，包含各 fixture 的检测匹配结果
 */
export async function runRealFingerprintRegression(fixtures = [FIXTURE_SPRING_BOOT, FIXTURE_REACT, FIXTURE_GO, FIXTURE_NODE_TS, FIXTURE_MONOREPO, FIXTURE_DOCS]) {
    debug("回归矩阵", "开始运行真实指纹回归，fixture 数量=" + fixtures.length);
    const checks = [];
    for (const fixture of fixtures) {
        const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `sf-regression-${fixture.name}-`));
        try {
            debug("回归矩阵", "检查 fixture " + fixture.name);
            // 将 fixture 文件写入临时目录
            for (const [relPath, content] of Object.entries(fixture.files)) {
                const fullPath = path.join(tmpDir, relPath);
                fs.mkdirSync(path.dirname(fullPath), { recursive: true });
                fs.writeFileSync(fullPath, content, "utf-8");
            }
            const fp = await detectFingerprint(tmpDir);
            const expectsBackend = fixture.tech_stack.includes("spring-boot") || fixture.tech_stack.includes("go");
            const expectedBackend = expectsBackend
                ? (fixture.tech_stack.includes("spring-boot") ? "spring-boot" : "stdlib")
                : null;
            const expectsFrontend = fixture.tech_stack.includes("react") || fixture.tech_stack.includes("vue");
            const expectedFrontend = expectsFrontend
                ? (fixture.tech_stack.includes("react") ? "react" : "vue")
                : null;
            const backendMatch = expectedBackend
                ? fp.backend?.framework === expectedBackend
                : fp.backend === null;
            const frontendMatch = expectedFrontend
                ? fp.frontend?.framework === expectedFrontend
                : true;
            const passed = backendMatch && frontendMatch;
            if (!passed)
                debug("回归矩阵", "fixture " + fixture.name + " 指纹不匹配");
            checks.push({
                fixture: fixture.name,
                expected_backend: expectedBackend,
                detected_backend: fp.backend?.framework ?? null,
                expected_frontend: expectedFrontend,
                detected_frontend: fp.frontend?.framework ?? null,
                backend_match: backendMatch,
                frontend_match: frontendMatch,
                passed,
                advisory: passed
                    ? `${fixture.name}: fingerprint match`
                    : `${fixture.name}: mismatch — expected backend=${expectedBackend}, got ${fp.backend?.framework}; expected frontend=${expectedFrontend}, got ${fp.frontend?.framework}`,
            });
        }
        finally {
            // 清理临时目录
            fs.rmSync(tmpDir, { recursive: true, force: true });
        }
    }
    const allPassed = checks.every((c) => c.passed);
    debug("回归矩阵", "真实指纹回归完成，全部通过=" + allPassed);
    return {
        checks,
        all_passed: allPassed,
        summary: allPassed
            ? `all ${checks.length} fixture(s) fingerprint matched`
            : `${checks.filter((c) => !c.passed).length}/${checks.length} fixture(s) fingerprint mismatch`,
    };
}
/**
 * 在临时目录中对 fixture 运行完整的端到端流水线回归测试。
 * 依次执行 fingerprint → classify → expand → verify → learn → governance_report 六个步骤。
 * @param fixture - fixture 仓库定义
 * @returns 端到端流水线报告，包含各步骤执行结果和总体通过状态
 */
export async function runE2EPipeline(fixture) {
    debug("回归矩阵", "开始 E2E 流水线回归，fixture=" + fixture.name);
    const steps = [];
    const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `sf-e2e-${fixture.name}-`));
    try {
        // 写入 fixture 文件
        for (const [relPath, content] of Object.entries(fixture.files)) {
            const fullPath = path.join(tmpDir, relPath);
            fs.mkdirSync(path.dirname(fullPath), { recursive: true });
            fs.writeFileSync(fullPath, content, "utf-8");
        }
        // 步骤 1: detectFingerprint
        const fp = await detectFingerprint(tmpDir);
        steps.push({
            step: "fingerprint",
            passed: true,
            detail: `backend=${fp.backend?.framework ?? "无"}, frontend=${fp.frontend?.framework ?? "无"}`,
        });
        // 步骤 2: classify（确定性，无 IO）
        const { classify } = await import("../pipeline/classifier.js");
        const classifyResult = classify({ intent: `add feature to ${fixture.name}` });
        debug("回归矩阵", "classify 步骤完成");
        steps.push({
            step: "classify",
            passed: classifyResult.task_type !== null && classifyResult.strategy !== null,
            detail: `type=${classifyResult.task_type}, strategy=${classifyResult.strategy}`,
        });
        // 步骤 3: expand（使用 KnowledgeIndexManager — 提供最小内存实现）
        const { expand } = await import("../pipeline/intent_expander.js");
        const configDraft = generateConfigDraft(fp);
        const projectConfig = {
            name: configDraft.name,
            tech_stack: {
                backend: configDraft.tech_stack.backend,
                frontend: configDraft.tech_stack.frontend,
            },
            product_profile: configDraft.product_profile,
            repos: [],
            build_commands: configDraft.build_commands,
            scope: configDraft.scope,
            _projectPath: tmpDir,
        };
        const minimalKnowledgeIndex = {
            query: () => [],
            markUsed: () => { },
            getAllEntries: () => ({ global: [], project: [] }),
            getEntry: () => undefined,
            addEntryInMemory: () => { },
            reload: () => { },
            checkHealth: () => ({ healthy: true, errors: [] }),
            close: () => { },
        };
        let expandOk = false;
        try {
            const expandResult = await expand({
                intent: `add feature to ${fixture.name}`,
                classification: classifyResult,
                projectPath: tmpDir,
                config: projectConfig,
                knowledgeIndex: minimalKnowledgeIndex,
            });
            expandOk = expandResult.prompt !== null && expandResult.prompt.length > 0;
        }
        catch {
            expandOk = false;
        }
        debug("回归矩阵", "expand 步骤完成，成功=" + expandOk);
        steps.push({
            step: "expand",
            passed: expandOk,
            detail: expandOk ? "prompt 已生成" : "expand 失败或返回为空",
        });
        // 步骤 4: generateVerifyCommands
        const { generateVerifyCommands } = await import("../release/verifier.js");
        const verifyResult = generateVerifyCommands(projectConfig, Object.keys(fixture.files), []);
        steps.push({
            step: "verify_commands",
            passed: true,
            detail: `build=${verifyResult.checks.build.length}, test=${verifyResult.checks.tests.length}`,
        });
        // 步骤 5: learn (evolve) — 最小输入
        const { evolve } = await import("../audit/evolver.js");
        let learnOk = false;
        try {
            const learnResult = await evolve({
                taskContext: {
                    task_id: "e2e-test",
                    created_at: new Date().toISOString(),
                    intent: `add feature to ${fixture.name}`,
                    product_profile: configDraft.product_profile,
                    status: "done",
                },
                result: "success",
                verifyOutput: { build_passed: true, tests_passed: true },
            }, tmpDir);
            learnOk = learnResult.task_id === "e2e-test";
        }
        catch {
            learnOk = false;
        }
        debug("回归矩阵", "learn 步骤完成，成功=" + learnOk);
        steps.push({
            step: "learn",
            passed: learnOk,
            detail: learnOk ? "evolve 返回结果" : "evolve 失败",
        });
        // 步骤 6: governance report（空数据 — 确认函数不会崩溃）
        const { generateReport } = await import("../audit/governance_report.js");
        const emptyEscapeByType = {
            rule_gap: 0, weak_test: 0, bad_evidence: 0, ai_escape: 0,
            human_miss: 0, tool_bug: 0, false_positive: 0,
        };
        const emptyEscapeByAction = {
            keep: 0, downgrade: 0, disable: 0, promote_blocked: 0,
        };
        const report = generateReport({ total: 0, by_risk: { low: 0, medium: 0, high: 0, critical: 0 } }, [], [], { total: 0, by_type: emptyEscapeByType, by_action: emptyEscapeByAction }, []);
        steps.push({
            step: "governance_report",
            passed: report.generated_at !== null && report.generated_at.length > 0,
            detail: `报告已生成，total_tasks=${report.total_tasks}`,
        });
        const allPassed = steps.every((s) => s.passed);
        debug("回归矩阵", "E2E 流水线完成，全部通过=" + allPassed);
        return {
            fixture: fixture.name,
            steps,
            passed: allPassed,
            summary: allPassed
                ? `${fixture.name}: all ${steps.length} e2e steps passed`
                : `${fixture.name}: ${steps.filter((s) => !s.passed).length}/${steps.length} e2e steps failed`,
        };
    }
    finally {
        fs.rmSync(tmpDir, { recursive: true, force: true });
    }
}
const CAPABILITY_BUDGETS = {
    "task_context.ts": 600,
    "diff_ownership_store.ts": 400,
    "diff_ownership.ts": 300,
    "scope_lease.ts": 150,
    "conflict_gate.ts": 100,
    "workspace_resumer.ts": 200,
    "semantic_evidence.ts": 150,
    "mutation_audit.ts": 200,
    "knowledge_sovereignty.ts": 250,
    "developer_sovereignty.ts": 150,
    "job_manager.ts": 250,
    "zero_config_init.ts": 350,
    "java_quality_guard.ts": 300,
    "runtime_safety.ts": 350,
    "audit_pool.ts": 200,
    "evolver.ts": 300,
    "test_quality.ts": 400,
};
/**
 * 检查能力模块的复杂度预算，对比实际代码行数与预设限额，超限模块产生 advisory 告警。
 * @param fileLineCounts - 模块名到实际代码行数的映射
 * @returns 复杂度预算报告，包含各模块的预算对比和超限统计
 */
export function checkComplexityBudget(fileLineCounts) {
    debug("回归矩阵", "开始检查复杂度预算，模块数=" + Object.keys(fileLineCounts).length);
    const modules = [];
    for (const [module, budget] of Object.entries(CAPABILITY_BUDGETS)) {
        const actual = fileLineCounts[module] ?? 0;
        const exceeded = actual > budget;
        if (exceeded)
            debug("回归矩阵", "复杂度预算超限 — " + module + " (" + actual + "/" + budget + " 行)");
        modules.push({
            module,
            budget_lines: budget,
            actual_lines: actual,
            exceeded,
            advisory: exceeded
                ? `advisory: ${module} exceeded budget (${actual}/${budget} lines, +${actual - budget})`
                : `${module}: ${actual}/${budget} lines`,
        });
    }
    const totalBudget = modules.reduce((s, m) => s + m.budget_lines, 0);
    const totalActual = modules.reduce((s, m) => s + m.actual_lines, 0);
    const exceededCount = modules.filter((m) => m.exceeded).length;
    debug("回归矩阵", "复杂度预算检查完成，超限模块数=" + exceededCount + "，总计=" + totalActual + "/" + totalBudget);
    return {
        modules,
        total_budget: totalBudget,
        total_actual: totalActual,
        exceeded_modules: exceededCount,
        summary: exceededCount > 0
            ? `advisory: ${exceededCount} module(s) exceeded complexity budget (total: ${totalActual}/${totalBudget} lines)`
            : `all modules within budget (total: ${totalActual}/${totalBudget} lines)`,
    };
}
//# sourceMappingURL=regression_matrix.js.map