/**
 * 模板资产可见性与注入边界 — 控制标准资产全链路访问。
 *
 * 覆盖同步、索引、注入、脚手架、fallback、adapter prompt、
 * MCP tool、CLI 和 release gate 所有入口的可见性裁决。
 */
import fs from "node:fs";
import path from "node:path";
// ── 内部资产识别 — 由权威合同注册表驱动 ──
// 不再使用 denylist 猜测；改用 template_asset_contract_registry 的 asset_visibility 字段
import { getContractByPath, getContractDecision, listTemplateAssetContracts } from "./template_asset_contract_registry.js";
// 旧 denylist 已移除 — 全部由权威合同注册表驱动
// ── 用户可见资产内部术语扫描规则 ──
const INTERNAL_TERM_PATTERNS = [
    /\bBatch\d*\b/i,
    /\bvalidate-release\b/i,
    /\bvalidate-batch\b/i,
    /\bReleaseFix\b/i,
    /SoloForge Audit:\s*PASS/i,
    /掘地三尺/,
    /三重否定/,
    /变异防造假/,
    /\bMechanism Contract Registry\b/i,
    /\bConsumable Asset Registry\b/i,
    /\bsf_capability_update\b/i,
];
// ── 内容关键词 → 可见性推断 ──
const CONTENT_VISIBILITY_KEYWORDS = [
    {
        patterns: [/\bBatch\d*\b/i, /\bvalidate-release\b/i, /\b新问题回归门\b/, /\b注册表基础设施\b/],
        visibility: "soloforge_internal",
    },
    {
        patterns: [/\bsf_expand\b.*\bsf_verify\b.*\bsf_deliver\b/, /@sf-hard-rule/, /adapter_runtime/],
        visibility: "adapter_runtime_only",
    },
];
// ── 目录默认策略 ──
// ── 诊断用目录默认值 — 仅用于 inferVisibilityFromPath 的诊断输出，不作为正式门禁依据 ──
const DIAGNOSTIC_DIRECTORY_DEFAULTS = {
    "templates/internal/patterns": { visibility: "soloforge_internal", runtime: "internal_only" },
    "templates/scaffolds": { visibility: "scaffold_only", runtime: "scaffold_only" },
    "templates/patterns": { visibility: "global_pattern", runtime: "index_only" },
};
// ── 核心函数 ──
/**
 * 判断资产是否为内部资产 — 由权威合同注册表驱动。
 * 合同缺失时 fail-closed: 不视为内部也不视为可发布，由调用方决定阻断策略。
 */
export function isInherentlyInternal(assetPath) {
    const normalized = assetPath.replace(/\\/g, "/");
    const contract = getContractByPath(normalized);
    if (contract) {
        return contract.asset_visibility === "soloforge_internal" ||
            contract.asset_visibility === "scaffold_only";
    }
    // 合同缺失 → fail-closed，不再猜测
    return false;
}
export function inferVisibilityFromPath(assetPath) {
    const normalized = assetPath.replace(/\\/g, "/");
    // 目录前缀匹配（仅诊断用途）
    for (const [dir, policy] of Object.entries(DIAGNOSTIC_DIRECTORY_DEFAULTS)) {
        if (!dir.includes(".md") && normalized.includes(dir))
            return policy;
    }
    return { visibility: "user_project", runtime: "injectable" };
}
/**
 * 内容关键词推断可见性。
 */
export function inferVisibilityFromContent(content) {
    for (const rule of CONTENT_VISIBILITY_KEYWORDS) {
        if (rule.patterns.some((p) => p.test(content))) {
            return rule.visibility;
        }
    }
    return null;
}
/**
 * 从 frontmatter 解析显式可见性声明。
 */
export function parseFrontmatterVisibility(content) {
    const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
    if (!fmMatch)
        return null;
    const fm = fmMatch[1];
    const visMatch = fm.match(/asset_visibility:\s*["']?(\w+)["']?/);
    if (visMatch) {
        const value = visMatch[1];
        if (["user_project", "soloforge_internal", "adapter_runtime_only", "scaffold_only", "global_pattern"].includes(value)) {
            return value;
        }
    }
    return null;
}
/**
 * 可见性冲突检测 — 路径推断、frontmatter 和内容关键词三方对账。
 */
export function detectVisibilityConflict(assetPath, content) {
    // 优先使用合同注册表的权威可见性
    const normalized = assetPath.replace(/\\/g, "/");
    const contract = getContractByPath(normalized);
    const contractVisibility = contract?.asset_visibility ?? null;
    const pathInference = contractVisibility ?? inferVisibilityFromPath(assetPath).visibility;
    const frontmatterDeclaration = parseFrontmatterVisibility(content);
    const contentKeywords = inferVisibilityFromContent(content);
    const inferences = [pathInference, frontmatterDeclaration, contentKeywords].filter((v) => v !== null);
    const uniqueInferences = new Set(inferences);
    if (uniqueInferences.size <= 1) {
        return {
            has_conflict: false,
            path_inference: pathInference,
            frontmatter_declaration: frontmatterDeclaration,
            content_keywords: contentKeywords,
            resolution: "resolved",
            message: "可见性推断一致",
        };
    }
    // 冲突消解: 内部优先级最高
    const hasInternal = inferences.includes("soloforge_internal");
    const resolvedVisibility = hasInternal ? "soloforge_internal" : pathInference;
    const needsConfirmation = frontmatterDeclaration !== null && frontmatterDeclaration !== resolvedVisibility;
    return {
        has_conflict: true,
        path_inference: pathInference,
        frontmatter_declaration: frontmatterDeclaration,
        content_keywords: contentKeywords,
        resolution: needsConfirmation ? "awaiting_user_confirmation" : "hard_fail",
        message: needsConfirmation
            ? `可见性冲突: frontmatter 声明 ${frontmatterDeclaration}，但路径/内容推断为 ${resolvedVisibility}，需用户确认`
            : `可见性硬冲突: 路径=${pathInference}, frontmatter=${frontmatterDeclaration}, 内容=${contentKeywords}`,
    };
}
/**
 * 用户可见资产内部术语污染扫描。
 */
export function scanInternalTerms(content) {
    const violations = [];
    for (const pattern of INTERNAL_TERM_PATTERNS) {
        const match = content.match(pattern);
        if (match) {
            violations.push(match[0]);
        }
    }
    return violations;
}
/**
 * 按可见性过滤同步资产。
 */
export function filterAssetsForUserProject(assets) {
    return assets.filter((a) => a.sync_to_user_project && (a.asset_visibility === "user_project" || a.asset_visibility === "global_pattern"));
}
/**
 * 同步过滤 — 决定哪些资产应该复制到用户项目。
 */
export function filterSyncAssets(assetPaths, templateRoot) {
    const result = { copied: [], skipped: [], internal: [], quarantined: [] };
    for (const relPath of assetPaths) {
        const absPath = path.join(templateRoot, relPath);
        if (!fs.existsSync(absPath)) {
            result.skipped.push(relPath);
            continue;
        }
        const normalized = relPath.replace(/\\/g, "/");
        // 合同门禁: getContractDecision 统一裁决
        const decision = getContractDecision(normalized);
        if (decision.decision === "unregistered") {
            result.quarantined.push(relPath);
            continue;
        }
        if (decision.decision === "denied") {
            result.internal.push(relPath);
            continue;
        }
        const content = fs.readFileSync(absPath, "utf-8");
        // 冲突检测（诊断保留）
        const conflict = detectVisibilityConflict(normalized, content);
        if (conflict.has_conflict && conflict.resolution === "hard_fail") {
            result.quarantined.push(relPath);
            continue;
        }
        // global_pattern 特殊处理
        if (decision.contract?.asset_visibility === "global_pattern") {
            result.skipped.push(relPath); // global patterns 走独立路径
            continue;
        }
        // 需要同步且被允许的资产
        if (decision.contract?.sync_to_user_project) {
            result.copied.push(relPath);
        }
        else {
            result.skipped.push(relPath);
        }
    }
    return result;
}
/**
 * 可见性门禁 — 所有入口统一裁决。
 */
export function checkAssetVisibilityGate(meta, route) {
    // 合同门禁优先: getContractDecision 统一裁决
    const decision = getContractDecision(meta.asset_id.includes("/") ? meta.asset_id : "");
    if (meta.asset_id && decision.decision !== "allowed" && decision.decision !== "unregistered")
        return false;
    if (meta.asset_visibility === "soloforge_internal" || meta.asset_visibility === "scaffold_only")
        return false;
    if (meta.runtime_visibility === "internal_only")
        return false;
    if (meta.applicable_routes.length > 0 && !meta.applicable_routes.includes(route))
        return false;
    return true;
}
/**
 * 按技术栈过滤 — review_rules 必须匹配技术栈。
 */
export function filterByTechStack(assets, techStack) {
    return assets.filter((a) => {
        if (a.applicable_tech_stack.length === 0)
            return true; // 通用规则
        return a.applicable_tech_stack.some((t) => techStack.includes(t));
    });
}
/**
 * 脚手架资产检查 — 只能由脚手架机制消费。
 */
export function isScaffoldAsset(assetPath) {
    return assetPath.replace(/\\/g, "/").includes("templates/scaffolds/");
}
/**
 * 包内路径检查 — scaffold 不依赖 process.cwd()/templates。
 */
export function isPackageInternalPath(absPath, packageRoot) {
    return absPath.startsWith(packageRoot);
}
/**
 * 审计模板可见性。
 */
export function auditTemplateVisibility(assets) {
    const report = {
        total_assets: assets.length,
        user_project_assets: 0,
        soloforge_internal_assets: 0,
        adapter_runtime_only_assets: 0,
        scaffold_only_assets: 0,
        global_pattern_assets: 0,
        missing_metadata: 0,
        visibility_conflicts: 0,
        leaked_internal_assets: 0,
        internal_term_violations: 0,
        scaffold_variable_gaps: 0,
    };
    for (const a of assets) {
        switch (a.asset_visibility) {
            case "user_project":
                report.user_project_assets++;
                break;
            case "soloforge_internal":
                report.soloforge_internal_assets++;
                break;
            case "adapter_runtime_only":
                report.adapter_runtime_only_assets++;
                break;
            case "scaffold_only":
                report.scaffold_only_assets++;
                break;
            case "global_pattern":
                report.global_pattern_assets++;
                break;
        }
        if (!a.asset_id || !a.owner_mechanism_id)
            report.missing_metadata++;
    }
    return report;
}
/**
 * 全量可见性审计 — 由权威合同注册表驱动。
 */
export function auditAllTemplateAssets(templateRoot) {
    const assets = [];
    if (!fs.existsSync(templateRoot)) {
        return auditTemplateVisibility(assets);
    }
    // 使用权威合同注册表作为单一数据源
    const contracts = listTemplateAssetContracts();
    for (const contract of contracts) {
        assets.push({
            asset_id: contract.asset_id,
            asset_visibility: contract.asset_visibility,
            sync_to_user_project: contract.sync_to_user_project,
            sync_target: contract.sync_target,
            runtime_visibility: contract.runtime_visibility,
            evidence_role: contract.evidence_role,
            user_visible: contract.user_visible,
            owner_mechanism_id: contract.owner_mechanism_id,
            applicable_routes: contract.applicable_routes,
            applicable_tech_stack: contract.applicable_tech_stack,
            source: "builtin",
            lifecycle_status: contract.lifecycle_status,
        });
    }
    return auditTemplateVisibility(assets);
}
//# sourceMappingURL=template_asset_visibility.js.map