/**
 * cache-invalidator.ts — require.cache 精确清除（Phase 2B）
 *
 * 当源码变更时，不能清除所有 require.cache（那等于重启），
 * 必须只清除变更文件及其"上游依赖链"（依赖该文件的所有模块）。
 *
 * 所有 require.cache 操作的对象都是 `.vext/dev/` 下的编译产物（纯 CJS .js），
 * 不涉及 TS 文件或 ESM 模块。CJS 的 `require.cache` 和 `Module.children`
 * 完整可用，是精确清除的基础。
 *
 * 核心流程：
 *
 *   1. buildReverseDependencyGraph()
 *      — 遍历 require.cache，利用 Module.children 构建反向依赖图
 *        key=被依赖模块, value=依赖它的模块集合
 *
 *   2. computeInvalidationSet(compiledFiles, outDir)
 *      — 从变更文件出发，BFS 沿反向依赖图向上传播
 *        收集所有需要失效的模块路径
 *        安全边界：不越过 node_modules 和 config 目录
 *
 *   3. evictModules(modulePaths)
 *      — 从 require.cache 中删除失效集合中的所有模块
 *
 *   4. detectCircularInvalidation(invalidated)
 *      — 检测失效集合是否过大（>80% 缓存），
 *        过大说明存在循环依赖级联，建议 cold restart
 *
 * 安全边界设计：
 *
 *   | 边界                | 原因                                          |
 *   |---------------------|-----------------------------------------------|
 *   | node_modules        | 第三方包不应被失效（它们不会被用户修改）        |
 *   | config 目录         | 配置变更走 cold restart（Tier 3），不走 soft    |
 *   | 级联 > 80%          | 可能存在循环依赖导致爆炸性传播，降级 cold      |
 *
 * @module lib/dev/cache-invalidator
 * @see 11b-soft-reload.md §2（require.cache 精确清除）
 * @see 11e-edge-cases.md §1（Reload 失败回退）
 * @see 11e-edge-cases.md §2（循环依赖处理）
 * @see 11e-edge-cases.md §4（内存泄漏防护）
 * @see IMPLEMENTATION-PLAN.md 任务 2.2a
 */
/**
 * 缓存失效结果
 *
 * computeInvalidationSet 的返回结果，包含失效集合和元数据。
 */
export interface InvalidationResult {
    /**
     * 需要从 require.cache 中驱逐的模块绝对路径集合
     */
    invalidated: Set<string>;
    /**
     * 是否检测到级联爆炸（失效集合 > 80% 缓存）
     *
     * 为 true 时调用方应降级到 cold restart。
     */
    cascadeDetected: boolean;
}
/**
 * 缓存驱逐结果
 *
 * evictModules 的返回结果。
 */
export interface EvictionResult {
    /**
     * 实际从 require.cache 中删除的模块数量
     *
     * 可能小于 invalidated.size（某些模块可能已经不在缓存中）。
     */
    evicted: number;
    /**
     * 失效集合中但不在 require.cache 中的模块数量（跳过的）
     */
    skipped: number;
}
/**
 * buildReverseDependencyGraph — 构建模块反向依赖图
 *
 * 遍历 require.cache 中所有已加载的模块，
 * 利用 Module.children 关系构建反向图：
 *
 *   正向: A requires B  →  A.children 包含 B
 *   反向: B 被 A 依赖  →  reverseGraph.get(B) 包含 A
 *
 * 反向图的用途：当 B 变更时，需要失效 B 以及所有依赖 B 的模块（A），
 * 因为 A 的模块导出可能缓存了对 B 导出值的引用。
 *
 * 注意：
 *   - 只处理 CJS 模块（require.cache 中的条目）
 *   - ESM 模块不在 require.cache 中，不受影响
 *   - 由于所有编译产物都是 CJS（esbuild 输出），这是完备的
 *
 * @returns 反向依赖图：key=被依赖模块路径, value=依赖它的模块路径集合
 */
export declare function buildReverseDependencyGraph(): Map<string, Set<string>>;
/**
 * computeInvalidationSet — 计算需要失效的所有模块路径
 *
 * 给定变更文件列表（编译产物路径），使用 BFS 沿反向依赖图向上传播，
 * 收集所有直接或间接依赖变更文件的模块。
 *
 * BFS 传播示例：
 *
 * ```
 *   变更: routes/user.js
 *
 *   反向图:
 *     routes/user.js ← router-loader.js ← bootstrap.js
 *                    ← routes/index.js
 *
 *   失效集合: {routes/user.js, router-loader.js, bootstrap.js, routes/index.js}
 * ```
 *
 * 安全边界：
 *   - **node_modules**: 第三方包不应被失效。用户代码不会修改 node_modules，
 *     且第三方包的模块导出通常是不可变的。
 *   - **config 目录**: 配置变更走 cold restart（Tier 3），在 soft reload 路径中
 *     不应传播到 config 相关模块。
 *
 * @param compiledFiles 变更的编译产物绝对路径（.vext/dev/ 下的 .js 文件）
 * @param outDir 编译产物根目录（.vext/dev/ 的绝对路径）
 * @returns 失效结果（包含失效集合和级联检测标志）
 */
export declare function computeInvalidationSet(compiledFiles: string[], outDir: string): InvalidationResult;
/**
 * evictModules — 从 require.cache 中删除指定模块集合
 *
 * 在失效集合计算完成后调用。删除 require.cache 中的条目后，
 * 下次 require() 同一路径时会重新从磁盘加载（加载最新编译产物）。
 *
 * 注意：
 *   - 删除 require.cache 条目不会影响已加载模块的导出对象。
 *     已经通过 `const x = require('...')` 获取的引用仍然有效。
 *   - 旧 handler 闭包中持有的模块引用独立于 require.cache，
 *     GC 前一直有效（这是失败回退机制的基础）。
 *
 * 清除操作还需要处理 Module.children 中的引用。当从 require.cache
 * 中删除一个模块后，如果父模块的 children 数组仍引用它，
 * 可能导致反向依赖图不准确。因此在驱逐时也清理父模块的 children 引用。
 *
 * @param modulePaths 需要驱逐的模块绝对路径集合
 * @returns 驱逐结果（实际删除数 + 跳过数）
 */
export declare function evictModules(modulePaths: Set<string>): EvictionResult;
/**
 * detectCircularInvalidation — 检测失效集合是否过大
 *
 * 如果失效集合超过 require.cache 总条目数的 80%，
 * 说明可能存在循环依赖导致的级联爆炸，此时 soft reload
 * 几乎等于全量重启，性能上不如直接 cold restart。
 *
 * 触发级联爆炸的典型场景：
 *   - 所有模块都 import 了某个"上帝模块"（如 app 实例）
 *   - 循环依赖链导致整个依赖图互相关联
 *   - 入口文件（bootstrap.js）被修改
 *
 * @param invalidated 失效的模块路径集合
 * @returns 是否检测到级联爆炸（true = 建议 cold restart）
 */
export declare function detectCircularInvalidation(invalidated: Set<string>): boolean;
/**
 * invalidateAndEvict — 一站式失效 + 驱逐
 *
 * 组合 computeInvalidationSet + evictModules 的便捷方法。
 * 在 soft reload 流程中作为单一调用点使用。
 *
 * 流程：
 *   1. 计算失效集合（BFS 传播）
 *   2. 检查级联爆炸
 *   3. 如果未检测到级联 → 执行驱逐
 *   4. 如果检测到级联 → 不执行驱逐，返回级联标志
 *
 * 调用方根据 cascadeDetected 决定是否降级到 cold restart：
 *
 * ```ts
 * const result = invalidateAndEvict(compiledFiles, outDir);
 * if (result.cascadeDetected) {
 *   process.send?.({ type: 'request-cold-restart', reason: 'cascade too large' });
 *   return;
 * }
 * // 继续 soft reload...
 * ```
 *
 * @param compiledFiles 变更的编译产物绝对路径列表
 * @param outDir 编译产物根目录（.vext/dev/ 的绝对路径）
 * @returns 组合结果
 */
export declare function invalidateAndEvict(compiledFiles: string[], outDir: string): InvalidationResult & EvictionResult;
