/**
 * 知识模板场景注册表 — A-H 场景定义与运行器。
 *
 * 生产级场景矩阵，被 validate-release 和测试消费。
 * 不硬编码 PASS，每个场景通过真实函数调用产生 evidence。
 */
import { evaluatePromotion, checkKnowledgeHealth } from "./knowledge_lifecycle.js";
import { evaluateCandidateTrust, validateAiInferenceWrite } from "./knowledge_evolution.js";
import { executeSync, validateSyncSafety } from "../templates/template_sync.js";
import { validateAdapterPrompt, REQUIRED_ADAPTER_SECTIONS } from "../adapter_prompt_contract.js";
import { getCliCommandContracts, detectReadmeDrift, validateCommandDefaults } from "../contracts/user_promise.js";
import { getCurrentCompatibility, checkProjectCompatibility, createMigrationPlan } from "./release_compatibility.js";
import { getLanguagePolicyConfig, detectSemanticPollution } from "./language_policy.js";
import { evaluateSemanticPriority } from "./chinese_semantic_priority.js";
import { validateDesignDocEligibility } from "./documentation_governance.js";
// ── 场景定义 ──
export const KNOWLEDGE_SCENARIOS = [
    {
        id: "scenario-A", name: "知识晋级阻断",
        fixture: "AI inference / drift_detection / human 晋级请求",
        command_or_entry: "evaluatePromotion",
        expected_evidence: ["AI inference 阻断 active", "AI inference 阻断 core", "人工确认通过"],
        pass_fail_rules: ["AI inference 不得晋级 active", "AI inference 不得设 core"],
    },
    {
        id: "scenario-B", name: "用户模板保护",
        fixture: "outdated_modified / outdated_unmodified / core knowledge 资产",
        command_or_entry: "executeSync / validateSyncSafety",
        expected_evidence: ["用户修改被保护", "core knowledge 被保护", "dry-run 只读"],
        pass_fail_rules: ["用户修改资产不被覆盖", "core knowledge 不被同步"],
    },
    {
        id: "scenario-C", name: "适配器 Prompt 合规",
        fixture: "合规/不合规适配器契约",
        command_or_entry: "validateAdapterPrompt",
        expected_evidence: ["forbidden claim 被检测", "缺少章节被检测"],
        pass_fail_rules: ["含 forbidden claim 不合规", "缺少章节不合规"],
    },
    {
        id: "scenario-D", name: "README/CLI 漂移",
        fixture: "README 命令列表 vs CLI 契约",
        command_or_entry: "detectReadmeDrift / validateUserPromise",
        expected_evidence: ["fake 命令漂移", "完全匹配无漂移"],
        pass_fail_rules: ["README 命令必须映射 CLI contract"],
    },
    {
        id: "scenario-E", name: "发布安全",
        fixture: "兼容/不兼容项目 schema",
        command_or_entry: "createMigrationPlan / validateMigrationSafety",
        expected_evidence: ["migrate apply 无确认被阻断", "兼容项目通过"],
        pass_fail_rules: ["migrate 默认 dry-run", "apply 需确认"],
    },
    {
        id: "scenario-F", name: "语言策略覆盖",
        fixture: "zh_first / en_first / bilingual / source_preserving 配置",
        command_or_entry: "getLanguagePolicyConfig / detectSemanticPollution",
        expected_evidence: ["zh_first 默认正确", "污染检测正确", "en_first 不检测污染"],
        pass_fail_rules: ["英文项目可配置", "中文项目不被英文模板污染"],
    },
    {
        id: "scenario-G", name: "知识-模板同步联动",
        fixture: "sovereignty=core 模板清单 + outdated_unmodified 资产",
        command_or_entry: "executeSync + manifest",
        expected_evidence: ["core 资产不被同步", "deprecated 知识被检测"],
        pass_fail_rules: ["模板同步受知识主权约束"],
    },
    {
        id: "scenario-H", name: "生命周期-健康-污染联动",
        fixture: "知识条目 + 语言配置 + 文档策略",
        command_or_entry: "checkKnowledgeHealth + evaluateSemanticPriority + validateDesignDocEligibility",
        expected_evidence: ["active 无证据警告", "zh_first 域合规", "proposed 不准入"],
        pass_fail_rules: ["active 无证据警告", "zh_first 域合规", "proposed 不准入"],
    },
];
// ── 场景运行器 ──
function runScenarioA() {
    const evidence = [];
    const failures = [];
    const r1 = evaluatePromotion({
        entry_id: "g1", from_status: "draft", to_status: "active",
        from_sovereignty: "normal", to_sovereignty: "normal",
        evidence_ids: ["ev-1"], requested_by: "ai_inference",
    });
    if (!r1.allowed)
        evidence.push("AI inference 阻断 active");
    else
        failures.push("AI inference 应被阻断晋级 active");
    const r2 = evaluatePromotion({
        entry_id: "g2", from_status: "draft", to_status: "draft",
        from_sovereignty: "normal", to_sovereignty: "core",
        evidence_ids: [], requested_by: "ai_inference",
    });
    if (!r2.allowed)
        evidence.push("AI inference 阻断 core");
    else
        failures.push("AI inference 应被阻断设 core");
    const r3 = evaluatePromotion({
        entry_id: "g3", from_status: "draft", to_status: "active",
        from_sovereignty: "normal", to_sovereignty: "normal",
        evidence_ids: ["ev-1"], requested_by: "human",
    });
    if (r3.allowed)
        evidence.push("人工确认通过");
    else
        failures.push("人工确认应被允许晋级");
    const trust = evaluateCandidateTrust("ai_inference");
    if (trust.allowed_max_status === "draft")
        evidence.push("ai_inference 信任上限=draft");
    else
        failures.push(`ai_inference 信任上限应为 draft，实际 ${trust.allowed_max_status}`);
    const w1 = validateAiInferenceWrite("ai_inference", "core", "draft");
    if (!w1.allowed)
        evidence.push("AI 推理写入 core 被阻断");
    else
        failures.push("AI 推理应被阻断写入 core");
    return { scenario_id: "scenario-A", scenario_name: "知识晋级阻断", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
function runScenarioB() {
    const evidence = [];
    const failures = [];
    const a1 = {
        asset_id: "a-1", source_path: "t/r.md", target_path: ".soloforge/r.md",
        asset_kind: "knowledge_template", template_version: "1.0",
        source_hash: "new", installed_hash: "old",
        user_modified: true, template_asset_status: "outdated_modified",
    };
    const s1 = validateSyncSafety([a1]);
    if (!s1.safe)
        evidence.push("用户修改被保护");
    else
        failures.push("用户修改资产应被保护");
    const r2 = executeSync({ dry_run: true, apply: false, project_path: "/tmp", source_path: "/src" }, [a1], []);
    if (r2.dry_run && r2.success)
        evidence.push("dry-run 只读");
    else
        failures.push("dry-run 应为只读成功");
    const r3 = executeSync({ dry_run: false, apply: true, project_path: "/tmp", source_path: "/src" }, [], []);
    if (!r3.success)
        evidence.push("apply 无确认被阻断");
    else
        failures.push("apply 无确认应被阻断");
    return { scenario_id: "scenario-B", scenario_name: "用户模板保护", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
function runScenarioC() {
    const evidence = [];
    const failures = [];
    const good = {
        adapter_id: "good", host_type: "claude_code",
        required_sections: [...REQUIRED_ADAPTER_SECTIONS],
        forbidden_claims: [], sync_required: true,
        next_allowed_tools: ["sf_classify"], generated_from_contract_version: "1",
    };
    const r1 = validateAdapterPrompt(good);
    if (r1.compliant)
        evidence.push("合规适配器通过");
    else
        failures.push(`合规适配器不应失败: ${r1.findings.map(f => f.message_zh).join("; ")}`);
    const bad = { ...good, adapter_id: "bad", forbidden_claims: ["可以自由选择任意 sf_* 工具"], next_allowed_tools: [] };
    const r2 = validateAdapterPrompt(bad);
    if (!r2.compliant && r2.detected_forbidden_claims.length > 0)
        evidence.push("forbidden claim 被检测");
    else
        failures.push("forbidden claim 应被检测");
    const incomplete = { ...good, adapter_id: "inc", required_sections: ["when_to_use_soloforge"] };
    const r3 = validateAdapterPrompt(incomplete);
    if (!r3.compliant && r3.missing_sections.length > 0)
        evidence.push("缺少章节被检测");
    else
        failures.push("缺少章节应被检测");
    return { scenario_id: "scenario-C", scenario_name: "适配器 Prompt 合规", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
function runScenarioD(readmeCommands) {
    const evidence = [];
    const failures = [];
    const contracts = getCliCommandContracts();
    const r1 = detectReadmeDrift(["soloforce fake-command"], contracts);
    if (r1.has_drift)
        evidence.push("fake 命令漂移");
    else
        failures.push("fake 命令应产生漂移");
    const allCommands = contracts.map(c => c.command);
    const r2 = detectReadmeDrift(allCommands, contracts);
    if (!r2.has_drift)
        evidence.push("完全匹配无漂移");
    else
        failures.push("完全匹配不应漂移");
    if (readmeCommands) {
        const r3 = detectReadmeDrift(readmeCommands, contracts);
        const undocumented = contracts.filter(c => c.documented_in_readme && !readmeCommands.includes(c.command));
        if (undocumented.length === 0 && !r3.drift_items.some(d => d.drift_type === "missing_in_cli")) {
            evidence.push("README 与 CLI 契约无漂移");
        }
        else {
            if (undocumented.length > 0)
                failures.push(`README 缺少文档化命令: ${undocumented.map(c => c.command).join(", ")}`);
            const fakeInReadme = r3.drift_items.filter(d => d.drift_type === "missing_in_cli").map(d => d.command);
            if (fakeInReadme.length > 0)
                failures.push(`README 包含不存在命令: ${fakeInReadme.join(", ")}`);
        }
    }
    const r4 = validateCommandDefaults(contracts);
    if (!r4.some(f => f.severity === "hard_fail"))
        evidence.push("默认行为安全");
    else
        failures.push(`默认行为 hard_fail`);
    return { scenario_id: "scenario-D", scenario_name: "README/CLI 漂移", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
function runScenarioE() {
    const evidence = [];
    const failures = [];
    const compat = getCurrentCompatibility();
    const c1 = checkProjectCompatibility("1", compat);
    if (c1 === "compatible")
        evidence.push("兼容项目通过");
    else
        failures.push(`当前 schema 应兼容，实际 ${c1}`);
    const r2 = createMigrationPlan({ dry_run: true, apply: false, project_path: "/tmp", from_version: "1", to_version: "2" }, compat);
    if (r2.dry_run)
        evidence.push("migrate 默认 dry-run");
    else
        failures.push("migrate 应默认 dry-run");
    const r3 = createMigrationPlan({ dry_run: false, apply: true, confirm: false, project_path: "/tmp", from_version: "1", to_version: "2" }, compat);
    if (!r3.success)
        evidence.push("migrate apply 无确认被阻断");
    else
        failures.push("migrate apply 无确认应被阻断");
    return { scenario_id: "scenario-E", scenario_name: "发布安全", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
function runScenarioF() {
    const evidence = [];
    const failures = [];
    const zh = getLanguagePolicyConfig("zh_first");
    if (zh.default === "zh_first")
        evidence.push("zh_first 默认正确");
    else
        failures.push("zh_first 默认配置不正确");
    const poll = detectSemanticPollution(zh, [{ id: "e-1", content: "This is completely English text for testing pollution detection" }]);
    if (poll.length > 0 && poll[0].status === "polluted")
        evidence.push("污染检测正确");
    else
        failures.push("英文内容应被检测为污染");
    const en = getLanguagePolicyConfig("en_first");
    const poll2 = detectSemanticPollution(en, [{ id: "e-2", content: "This is completely English text" }]);
    if (poll2.length === 0)
        evidence.push("en_first 不检测污染");
    else
        failures.push("en_first 项目不应检测英文污染");
    return { scenario_id: "scenario-F", scenario_name: "语言策略覆盖", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
async function runScenarioG() {
    const evidence = [];
    const failures = [];
    const coreManifest = [{
            asset_id: "core-1", asset_kind: "core_knowledge",
            source_path: "t/core.md", target_path: ".soloforge/core.md",
            template_version: "1.0", source_hash: "old", installed_hash: "old",
            installed_at: new Date().toISOString(), sovereignty: "core",
        }];
    const r1 = executeSync({ dry_run: false, apply: true, confirm: true, project_path: "/tmp", source_path: "/src" }, [{ asset_id: "core-1", source_path: "t/core.md", target_path: ".soloforge/core.md", asset_kind: "core_knowledge", template_version: "1.0", source_hash: "new", installed_hash: "old", user_modified: false, template_asset_status: "outdated_unmodified" }], coreManifest);
    if (!r1.report.updated.includes("core-1"))
        evidence.push("core 资产不被同步");
    else
        failures.push("core 资产不应被同步");
    const h2 = await checkKnowledgeHealth([{
            id: "k-dep", knowledge_lifecycle_status: "deprecated",
            sovereignty: "normal", knowledge_write_stage: "committed",
            created_at: new Date().toISOString(), updated_at: new Date().toISOString(),
        }], new Map());
    if (h2.some(h => h.category === "lifecycle"))
        evidence.push("deprecated 知识被检测");
    else
        failures.push("deprecated 知识应被检测");
    return { scenario_id: "scenario-G", scenario_name: "知识-模板同步联动", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
async function runScenarioH() {
    const evidence = [];
    const failures = [];
    const h1 = await checkKnowledgeHealth([{
            id: "k-noev", knowledge_lifecycle_status: "active",
            sovereignty: "normal", knowledge_write_stage: "committed",
            created_at: new Date().toISOString(), updated_at: new Date().toISOString(),
        }], new Map());
    if (h1.some(h => h.category === "evidence"))
        evidence.push("active 无证据警告");
    else
        failures.push("active 无证据应产生警告");
    const config = getLanguagePolicyConfig("zh_first");
    const r2 = evaluateSemanticPriority(config, [{ domain: "business_semantics", content: "这是一个业务语义描述", id: "zh-1" }]);
    if (r2.compliant)
        evidence.push("zh_first 域合规");
    else
        failures.push("中文内容应合规");
    const r3 = validateDesignDocEligibility({ decision_id: "dec-1", doc_eligibility_status: "proposed", evidence_refs: ["ev-1"] });
    if (!r3.allowed)
        evidence.push("proposed 不准入");
    else
        failures.push("proposed 决策不应准入");
    return { scenario_id: "scenario-H", scenario_name: "生命周期-健康-污染联动", status: failures.length === 0 ? "PASS" : "FAIL", evidence, failures };
}
/** 运行全部 A-H 场景 */
export async function runAllKnowledgeScenarios(readmeCommands) {
    return [runScenarioA(), runScenarioB(), runScenarioC(), runScenarioD(readmeCommands), runScenarioE(), runScenarioF(), await runScenarioG(), await runScenarioH()];
}
/** 从 README.md 内容提取 soloforge 命令 */
export function extractReadmeCommands(readmeContent) {
    const commands = [];
    const codeBlockRegex = /```(?:bash)?\n([\s\S]*?)```/g;
    let match;
    while ((match = codeBlockRegex.exec(readmeContent)) !== null) {
        for (const line of match[1].split("\n")) {
            let trimmed = line.trim();
            // 移除行尾注释 (# ... 和 // ...)
            const commentIdx = trimmed.search(/\s+(#|\/\/)\s/);
            if (commentIdx > 0) {
                trimmed = trimmed.slice(0, commentIdx).trim();
            }
            if (trimmed.startsWith("#") || trimmed.startsWith("//"))
                continue;
            const cmdMatch = trimmed.match(/^soloforge\s+(\S+)(.*)/);
            if (cmdMatch) {
                const rest = cmdMatch[2].trim();
                const cmd = rest ? `soloforge ${cmdMatch[1]} ${rest}`.replace(/\s+/g, " ").trim() : `soloforge ${cmdMatch[1]}`;
                commands.push(cmd);
            }
        }
    }
    return [...new Set(commands)];
}
//# sourceMappingURL=knowledge_scenario_registry.js.map