/**
 * Knowledge Asset Schema — 问题五十七核心机制之一。
 *
 * 定义所有知识资产的统一 frontmatter 标准、类型枚举和校验规则。
 * 所有 templates/**（internal/rules、procedures、rules/shared、checklists、artifacts/shared、domain、internal/patterns、profiles）、templates/patterns/**、项目 .soloforge/knowledge/**
 * 和全局 patterns 必须遵守此 schema。
 */
// ── 必需字段定义 ──
const REQUIRED_FIELDS = [
    "id", "name", "asset_kind", "lifecycle_status", "authority",
    "scope", "products", "routes", "primary_triggers",
    "priority", "specificity", "version", "last_reviewed",
];
const REQUIRED_FIELDS_BY_KIND = {
    hard_rule: ["owner_mechanism_id", "hard_blocks", "required_evidence", "fallback"],
    workflow: ["owner_mechanism_id", "consumes", "emits"],
    procedure: ["consumes", "emits"],
    pipeline: ["consumes", "emits"],
    checklist: [],
    artifact_template: ["emits"],
    review_rule: ["required_evidence"],
    domain_knowledge: [],
    product_profile: ["scope"],
};
const REQUIRED_EVIDENCE_PRIORITIES = ["P0", "P1"];
// ── 校验函数 ──
/**
 * 校验知识资产 frontmatter 的完整性。
 */
export function validateKnowledgeAssetFrontmatter(frontmatter, filePath) {
    const findings = [];
    const assetId = frontmatter.id ?? "unknown";
    // 1. 必填字段检查
    for (const field of REQUIRED_FIELDS) {
        if (frontmatter[field] === undefined || frontmatter[field] === null) {
            findings.push({
                asset_id: assetId,
                file_path: filePath,
                severity: "hard_fail",
                kind: "missing_required_field",
                field,
                message_zh: `知识资产缺少必填 frontmatter 字段: ${field} (SF-KA-5701)`,
            });
        }
    }
    // 2. asset_kind 校验
    const validKinds = [
        "hard_rule", "workflow", "procedure", "pipeline", "pattern",
        "checklist", "artifact_template", "review_rule", "domain_knowledge", "product_profile",
    ];
    if (frontmatter.asset_kind && !validKinds.includes(frontmatter.asset_kind)) {
        findings.push({
            asset_id: assetId,
            file_path: filePath,
            severity: "hard_fail",
            kind: "invalid_enum",
            field: "asset_kind",
            message_zh: `asset_kind ${frontmatter.asset_kind} 不在允许的枚举值中 (SF-KA-5701)`,
        });
    }
    // 3. 按 asset_kind 检查特定必需字段
    const kind = frontmatter.asset_kind;
    if (kind && REQUIRED_FIELDS_BY_KIND[kind]) {
        for (const field of REQUIRED_FIELDS_BY_KIND[kind]) {
            if (frontmatter[field] === undefined || frontmatter[field] === null ||
                (Array.isArray(frontmatter[field]) && frontmatter[field].length === 0)) {
                findings.push({
                    asset_id: assetId,
                    file_path: filePath,
                    severity: "hard_fail",
                    kind: field === "owner_mechanism_id"
                        ? "owner_missing"
                        : field === "required_evidence"
                            ? "required_evidence_missing"
                            : "missing_required_field",
                    field,
                    message_zh: `资产类型 ${kind} 缺少必需字段: ${field} (SF-KA-5704/SF-KA-5706)`,
                });
            }
        }
    }
    // 4. P0/P1 必须声明 required_evidence
    if (frontmatter.priority && REQUIRED_EVIDENCE_PRIORITIES.includes(frontmatter.priority)) {
        if (!frontmatter.required_evidence || frontmatter.required_evidence.length === 0) {
            findings.push({
                asset_id: assetId,
                file_path: filePath,
                severity: "hard_fail",
                kind: "required_evidence_missing",
                field: "required_evidence",
                message_zh: `P0/P1 资产必须声明 required_evidence (SF-KA-5706)`,
            });
        }
    }
    // 5. hard_rule/workflow 必须有 owner_mechanism_id
    if (kind && ["hard_rule", "workflow"].includes(kind)) {
        if (!frontmatter.owner_mechanism_id) {
            findings.push({
                asset_id: assetId,
                file_path: filePath,
                severity: "hard_fail",
                kind: "owner_missing",
                field: "owner_mechanism_id",
                message_zh: `hard_rule/workflow 必须有 owner_mechanism_id (SF-KA-5704)`,
            });
        }
    }
    // 6. authority 校验
    if (frontmatter.authority && !["canonical", "supporting", "example"].includes(frontmatter.authority)) {
        findings.push({
            asset_id: assetId,
            file_path: filePath,
            severity: "hard_fail",
            kind: "invalid_enum",
            field: "authority",
            message_zh: `authority ${frontmatter.authority} 不在允许值中`,
        });
    }
    // 7. lifecycle_status 校验
    if (frontmatter.lifecycle_status && !["draft", "active", "deprecated", "quarantine"].includes(frontmatter.lifecycle_status)) {
        findings.push({
            asset_id: assetId,
            file_path: filePath,
            severity: "hard_fail",
            kind: "invalid_enum",
            field: "lifecycle_status",
            message_zh: `lifecycle_status ${frontmatter.lifecycle_status} 不在允许值中`,
        });
    }
    // 8. version 格式
    if (frontmatter.version && !/^\d+\.\d+\.\d+/.test(frontmatter.version)) {
        findings.push({
            asset_id: assetId,
            file_path: filePath,
            severity: "warning",
            kind: "invalid_version",
            field: "version",
            message_zh: `version ${frontmatter.version} 不符合 semver 格式建议`,
        });
    }
    // 9. P0/P1 必填数组字段不得为空
    if (frontmatter.priority && ["P0", "P1"].includes(frontmatter.priority)) {
        // required_evidence 不得为空数组或字符串 "[]"
        if (isEmptyArrayValue(frontmatter.required_evidence)) {
            findings.push({
                asset_id: assetId, file_path: filePath, severity: "hard_fail",
                kind: "required_evidence_missing", field: "required_evidence",
                message_zh: `P0/P1 资产 required_evidence 不能为空数组或字符串 "[]" (SF-KA-5706)`,
            });
        }
        // primary_triggers 不得为空
        if (isEmptyArrayValue(frontmatter.primary_triggers)) {
            findings.push({
                asset_id: assetId, file_path: filePath, severity: "hard_fail",
                kind: "missing_required_field", field: "primary_triggers",
                message_zh: `P0/P1 资产 primary_triggers 不能为空 (SF-KA-5701)`,
            });
        }
    }
    // 10. hard_rule/workflow/procedure 的 consumes 不得为空
    if (kind && ["hard_rule", "workflow", "procedure"].includes(kind)) {
        if (isEmptyArrayValue(frontmatter.consumes)) {
            findings.push({
                asset_id: assetId, file_path: filePath, severity: "hard_fail",
                kind: "missing_required_field", field: "consumes",
                message_zh: `${kind} 必须声明 consumes，不能为空数组 (SF-KA-5709)`,
            });
        }
    }
    // 11. hard_rule 的 hard_blocks 不得为空
    if (kind === "hard_rule") {
        if (isEmptyArrayValue(frontmatter.hard_blocks)) {
            findings.push({
                asset_id: assetId, file_path: filePath, severity: "hard_fail",
                kind: "missing_required_field", field: "hard_blocks",
                message_zh: `hard_rule 必须声明 hard_blocks，不能为空 (SF-KA-5704)`,
            });
        }
    }
    // 12. procedure/pipeline 的 emits 不得为空
    if (kind && ["procedure", "pipeline"].includes(kind)) {
        if (isEmptyArrayValue(frontmatter.emits)) {
            findings.push({
                asset_id: assetId, file_path: filePath, severity: "hard_fail",
                kind: "missing_required_field", field: "emits",
                message_zh: `${kind} 必须声明 emits，不能为空数组 (SF-KA-5709)`,
            });
        }
    }
    // 13. routes 为 ["*"] 且无具体约束 → hard_fail（仅对需要精确路由的类型）
    const routeStrictKinds = ["hard_rule", "workflow", "procedure", "pipeline"];
    if (routeStrictKinds.includes(kind) && isGenericStarRoute(frontmatter.routes)) {
        findings.push({
            asset_id: assetId, file_path: filePath, severity: "hard_fail",
            kind: "missing_required_field", field: "routes",
            message_zh: `routes 不能仅为 ["*"]，必须声明具体 route/execution_shape 约束 (SF-KA-5701)`,
        });
    }
    // 14. owner_mechanism_id 必须能映射到 MechanismLayerMap
    if (frontmatter.owner_mechanism_id && typeof frontmatter.owner_mechanism_id === "string") {
        if (!frontmatter.owner_mechanism_id.startsWith("mc-")) {
            findings.push({
                asset_id: assetId, file_path: filePath, severity: "warning",
                kind: "owner_missing", field: "owner_mechanism_id",
                message_zh: `owner_mechanism_id "${frontmatter.owner_mechanism_id}" 格式不正确，应以 "mc-" 开头`,
            });
        }
    }
    return findings;
}
/** 判断值是否为空数组或字符串 "[]" */
function isEmptyArrayValue(val) {
    if (val === undefined || val === null)
        return true;
    if (Array.isArray(val))
        return val.length === 0;
    if (typeof val === "string") {
        const trimmed = val.trim();
        return trimmed === "[]" || trimmed === "";
    }
    return false;
}
/** 判断 routes 是否为泛 ["*"] 无具体约束 */
function isGenericStarRoute(val) {
    if (val === undefined || val === null)
        return true;
    if (Array.isArray(val)) {
        return val.length === 0 || (val.length === 1 && val[0] === "*");
    }
    if (typeof val === "string") {
        const trimmed = val.trim();
        return trimmed === '["*"]' || trimmed === "*" || trimmed === "";
    }
    return false;
}
/**
 * 批量校验知识资产注册表。
 */
export function validateKnowledgeAssets(assets) {
    const allFindings = [];
    const idSet = new Set();
    const canonicalMap = new Map(); // subject → [id, file_path]
    for (const asset of assets) {
        // Schema 校验
        const findings = validateKnowledgeAssetFrontmatter(asset.frontmatter, asset.file_path);
        allFindings.push(...findings);
        const id = asset.frontmatter.id;
        if (!id)
            continue;
        // 重复 id 检查
        if (idSet.has(id)) {
            allFindings.push({
                asset_id: id,
                file_path: asset.file_path,
                severity: "hard_fail",
                kind: "duplicate_id",
                message_zh: `知识资产 id 重复: ${id} (SF-KA-5702)`,
            });
        }
        idSet.add(id);
        // canonical 重复检查
        if (asset.frontmatter.authority === "canonical" && asset.frontmatter.name) {
            const subject = asset.frontmatter.name;
            const existing = canonicalMap.get(subject) ?? [];
            existing.push(id);
            canonicalMap.set(subject, existing);
        }
        // deprecated/draft/quarantine 注入检查
        if (asset.frontmatter.lifecycle_status &&
            ["deprecated", "draft", "quarantine"].includes(asset.frontmatter.lifecycle_status)) {
            if (asset.frontmatter.routes && asset.frontmatter.routes.length > 0) {
                allFindings.push({
                    asset_id: id,
                    file_path: asset.file_path,
                    severity: "hard_fail",
                    kind: "deprecated_injected",
                    message_zh: `${asset.frontmatter.lifecycle_status} 资产 ${id} 不应有活跃路由，防止被注入 prompt (SF-KA-5705)`,
                });
            }
        }
        // checklist 平行定义硬规则检查
        if (asset.frontmatter.asset_kind === "checklist" && asset.frontmatter.hard_blocks && asset.frontmatter.hard_blocks.length > 0) {
            allFindings.push({
                asset_id: id,
                file_path: asset.file_path,
                severity: "hard_fail",
                kind: "checklist_hard_rule_violation",
                message_zh: `checklist ${id} 平行定义了硬规则，只能引用 canonical hard_rule (SF-KA-5704)`,
            });
        }
    }
    // canonical 重复检查结果
    for (const [subject, ids] of canonicalMap) {
        if (ids.length > 1) {
            for (const dupId of ids) {
                allFindings.push({
                    asset_id: dupId,
                    file_path: "",
                    severity: "hard_fail",
                    kind: "duplicate_canonical",
                    message_zh: `同一主题 "${subject}" 存在多个 canonical 权威定义: ${ids.join(", ")} (SF-KA-5703)`,
                });
            }
        }
    }
    return allFindings;
}
/**
 * 构建知识资产注册表 — 从资产列表中建立索引。
 */
export function buildKnowledgeAssetRegistry(assets) {
    const registry = new Map();
    for (const asset of assets) {
        registry.set(asset.frontmatter.id, asset);
    }
    return registry;
}
/**
 * 检测重复与冲突。
 */
export function detectDuplicateAndConflicts(assets) {
    const findings = [];
    for (let i = 0; i < assets.length; i++) {
        for (let j = i + 1; j < assets.length; j++) {
            const a = assets[i];
            const b = assets[j];
            // ID 相同 → exact_duplicate
            if (a.frontmatter.id === b.frontmatter.id) {
                findings.push({
                    kind: "exact_duplicate",
                    asset_ids: [a.frontmatter.id, b.frontmatter.id],
                    detail_zh: `资产 ${a.frontmatter.id} 存在重复 ID`,
                    suggested_action: "merge",
                });
                continue;
            }
            // 名称高度相似 → semantic_overlap
            const aName = a.frontmatter.name.toLowerCase();
            const bName = b.frontmatter.name.toLowerCase();
            if (aName === bName && a.frontmatter.id !== b.frontmatter.id) {
                findings.push({
                    kind: "semantic_overlap",
                    asset_ids: [a.frontmatter.id, b.frontmatter.id],
                    detail_zh: `资产 ${a.frontmatter.id} 和 ${b.frontmatter.id} 名称相同但 ID 不同`,
                    suggested_action: "resolve_canonical",
                });
            }
            // primary_triggers 重叠 > 50% → semantic_overlap
            const aTriggers = new Set(a.frontmatter.primary_triggers);
            const bTriggers = new Set(b.frontmatter.primary_triggers);
            const overlap = [...aTriggers].filter((t) => bTriggers.has(t));
            const total = new Set([...aTriggers, ...bTriggers]).size;
            if (total > 0 && overlap.length / total > 0.5 && a.frontmatter.authority === "canonical" && b.frontmatter.authority === "canonical") {
                findings.push({
                    kind: "semantic_overlap",
                    asset_ids: [a.frontmatter.id, b.frontmatter.id],
                    detail_zh: `触发词重叠 ${Math.round((overlap.length / total) * 100)}%: ${overlap.join(", ")}`,
                    suggested_action: "declare_boundary",
                });
            }
            // hard_blocks 冲突 → conflict
            if (a.frontmatter.hard_blocks && b.frontmatter.hard_blocks) {
                // 简单检测: 如果两者同为主题但 hard_blocks 不同
                if (aName === bName && JSON.stringify(a.frontmatter.hard_blocks) !== JSON.stringify(b.frontmatter.hard_blocks)) {
                    findings.push({
                        kind: "conflict",
                        asset_ids: [a.frontmatter.id, b.frontmatter.id],
                        detail_zh: `hard_blocks 定义冲突`,
                        suggested_action: "manual_required",
                    });
                }
            }
            // 合理交叉引用检测
            if (a.frontmatter.consumes?.includes(b.frontmatter.id) || b.frontmatter.consumes?.includes(a.frontmatter.id)) {
                findings.push({
                    kind: "legitimate_cross_reference",
                    asset_ids: [a.frontmatter.id, b.frontmatter.id],
                    detail_zh: `${a.frontmatter.id} 与 ${b.frontmatter.id} 存在合理交叉引用`,
                    suggested_action: "keep_reference",
                });
            }
        }
    }
    return findings;
}
/**
 * 解析 canonical 权威 — 确定哪个资产是主题的权威定义。
 */
export function resolveCanonicalAuthority(assets, subject) {
    const matching = assets.filter((a) => a.frontmatter.name.toLowerCase().includes(subject.toLowerCase()) ||
        a.frontmatter.primary_triggers.some((t) => t.toLowerCase().includes(subject.toLowerCase())));
    const canonicals = matching.filter((a) => a.frontmatter.authority === "canonical");
    const supporting = matching.filter((a) => a.frontmatter.authority === "supporting");
    if (canonicals.length === 1) {
        return {
            canonical_id: canonicals[0].frontmatter.id,
            supporting_ids: supporting.map((s) => s.frontmatter.id),
            conflicts: [],
        };
    }
    if (canonicals.length > 1) {
        return {
            canonical_id: undefined,
            supporting_ids: supporting.map((s) => s.frontmatter.id),
            conflicts: canonicals.map((c) => c.frontmatter.id),
        };
    }
    return { canonical_id: undefined, supporting_ids: [], conflicts: [] };
}
//# sourceMappingURL=knowledge_asset_schema.js.map