/**
 * .map.json 认知锚点 — 结构化可追溯压缩。
 * 备忘录要求: 每个锚点必须有 source_refs, confidence, last_verified_at。
 * 自动生成的锚点默认 advisory，核心锚点更新需人工确认。
 */
import fss from "node:fs";
import path from "node:path";
import { debug } from "./core/logger.js";
import { safeJsonParse } from "./core/helpers.js";
/**
 * 写入 .map.json 文件。
 * @param filePath - 目标文件路径
 * @param anchors - 要写入的锚点列表
 */
export function writeMapJson(filePath, anchors) {
    const dir = path.dirname(filePath);
    fss.mkdirSync(dir, { recursive: true });
    const data = {
        version: 1,
        anchors,
        generated_at: new Date().toISOString(),
    };
    const tmpPath = `${filePath}.tmp`;
    fss.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
    fss.renameSync(tmpPath, filePath);
    debug("认知锚点", `写入完成，锚点数: ${anchors.length}，路径: ${filePath}`);
}
/**
 * 读取 .map.json 文件。文件不存在时返回空锚点列表。
 * @param filePath - 目标文件路径
 * @returns 解析后的地图文件，文件不存在或解析失败时返回 null
 */
export function readMapJson(filePath) {
    if (!fss.existsSync(filePath))
        return null;
    const result = safeJsonParse(fss.readFileSync(filePath, "utf-8"));
    if (!result) {
        debug("认知锚点", `读取失败，文件解析错误，路径: ${filePath}`);
        return null;
    }
    debug("认知锚点", `读取完成，锚点数: ${result.anchors.length}，路径: ${filePath}`);
    return result;
}
/**
 * 检查锚点是否过时 — 与当前文件列表比对 source_refs。
 * 文件不存在的 source_ref 标记 stale_anchor。
 * @param anchors - 要检查的锚点列表
 * @param existingFiles - 当前存在的文件路径集合
 * @returns 更新了 stale_anchor 标记的锚点列表
 */
export function checkAnchorStaleness(anchors, existingFiles) {
    let staleCount = 0;
    for (const anchor of anchors) {
        const hasMissing = anchor.source_refs.some((ref) => ref.type === "file" && !existingFiles.has(ref.ref));
        if (hasMissing) {
            anchor.stale_anchor = true;
            staleCount++;
        }
        else {
            anchor.stale_anchor = false;
        }
    }
    if (staleCount > 0) {
        debug("认知锚点", `检测到 ${staleCount} 个过时锚点（引用的源文件已不存在）`);
    }
    return anchors;
}
/**
 * 按相关性筛选锚点 — 根据模块名或文件路径前缀匹配。
 * 不全量加载，避免污染上下文。
 * @param anchors - 锚点列表
 * @param query - 查询条件
 * @param query.module - 按模块名精确匹配
 * @param query.file_path - 按文件路径前缀匹配
 * @returns 匹配的锚点列表
 */
export function filterRelevantAnchors(anchors, query) {
    debug("认知锚点", `按相关性筛选锚点 — 模块: ${query.module ?? '无'}, 文件路径: ${query.file_path ?? '无'}, 锚点总数: ${anchors.length}`);
    const result = anchors.filter((anchor) => {
        if (query.module && anchor.module === query.module)
            return true;
        if (query.file_path) {
            const matchesRef = anchor.source_refs.some((ref) => ref.type === "file" && ((query.file_path ?? "").startsWith(ref.ref) || ref.ref.startsWith(query.file_path ?? "")));
            if (matchesRef)
                return true;
        }
        return false;
    });
    debug("认知锚点", `筛选完成 — 匹配 ${result.length} 个锚点`);
    return result;
}
//# sourceMappingURL=cognitive_anchor.js.map