/**
 * @deprecated [DC-3] 无运行时消费方。保留供未来工作区隔离实现。
 *
 * 工作区隔离 — 问题二十八 (Workspace Isolation / Concurrency Contract)。
 *
 * 核心规则:
 * - 同 scope code_write 冲突必须 blocked 或 require_human
 * - delivery 必须互斥
 * - lease active/conflicted 不得交付
 * - out-of-scope write 必须 blocked
 */
import { createDiagnosticEvent } from "../audit/diagnostic_registry.js";
import { isPathInScope } from "../core/path_scope_utils.js";
/** 内存存储 */
const leaseStore = new Map();
/** 过期清理阈值: released 状态超过 1 小时的条目将被清理 */
const LEASE_EXPIRY_MS = 60 * 60 * 1000;
/**
 * 清理状态为 released 且超过 1 小时的过期条目。
 * 在 acquireLease 时调用，保持存储清洁。
 * @returns 清理的条目数量
 */
export function purgeExpiredLeases() {
    let purged = 0;
    const now = Date.now();
    for (const [id, lease] of leaseStore) {
        if (lease.status === "released") {
            const releasedAt = lease.expires_at ? new Date(lease.expires_at).getTime() : 0;
            if (now - releasedAt > LEASE_EXPIRY_MS) {
                leaseStore.delete(id);
                purged++;
            }
        }
    }
    return purged;
}
/** 获取 lease */
export function getLease(leaseId) {
    return leaseStore.get(leaseId);
}
/** 列出所有活跃 lease */
export function listActiveLeases() {
    return [...leaseStore.values()].filter((l) => l.status === "active");
}
/**
 * 尝试获取 lease。
 * 如果同 scope 有冲突，返回冲突信息。
 */
export function acquireLease(taskId, leaseType, scopePaths) {
    // 清理过期条目
    const purged = purgeExpiredLeases();
    const conflicts = [];
    const leaseId = `wl-${taskId}-${Date.now()}`;
    // 检查冲突
    const activeLeases = listActiveLeases();
    for (const existing of activeLeases) {
        if (existing.task_id === taskId)
            continue;
        // 同 scope 重叠检查
        const overlap = existing.scope_paths.some((p) => scopePaths.some((sp) => isPathInScope(p, sp, { caseSensitive: true }) || isPathInScope(sp, p, { caseSensitive: true })));
        if (overlap) {
            if (leaseType === "delivery" || existing.lease_type === "delivery") {
                // delivery 必须互斥
                conflicts.push({
                    lease_a_id: existing.lease_id,
                    lease_b_id: leaseId,
                    conflict_path: existing.scope_paths.find((p) => scopePaths.some((sp) => isPathInScope(p, sp, { caseSensitive: true }))) ?? "unknown",
                    conflict_type: "delivery_overlap",
                    resolved: false,
                });
            }
            else if (leaseType === "code_write" && existing.lease_type === "code_write") {
                // code_write 同文件冲突
                conflicts.push({
                    lease_a_id: existing.lease_id,
                    lease_b_id: leaseId,
                    conflict_path: existing.scope_paths.find((p) => scopePaths.some((sp) => isPathInScope(p, sp, { caseSensitive: true }))) ?? "unknown",
                    conflict_type: "scope_overlap",
                    resolved: false,
                });
            }
        }
    }
    if (conflicts.length > 0) {
        // 创建冲突 lease
        const diagEvent = createDiagnosticEvent("SF-WORKSPACE-0001", { taskId, leaseType });
        const lease = {
            lease_id: leaseId,
            task_id: taskId,
            lease_type: leaseType,
            scope_paths: scopePaths,
            status: "conflicted",
            acquired_at: new Date().toISOString(),
            diagnostic_event: diagEvent,
        };
        leaseStore.set(leaseId, lease);
        return { lease, conflicts, purged };
    }
    // 无冲突，创建活跃 lease
    const lease = {
        lease_id: leaseId,
        task_id: taskId,
        lease_type: leaseType,
        scope_paths: scopePaths,
        status: "active",
        acquired_at: new Date().toISOString(),
        diagnostic_event: null,
    };
    leaseStore.set(leaseId, lease);
    return { lease, conflicts: [], purged };
}
/** 释放 lease */
export function releaseLease(leaseId) {
    const lease = leaseStore.get(leaseId);
    if (!lease)
        return false;
    if (lease.status === "conflicted") {
        // conflicted lease 不得标记 released
        return false;
    }
    lease.status = "released";
    lease.expires_at = new Date().toISOString();
    return true;
}
/**
 * 检查是否超出 scope 写入。
 */
export function checkOutOfScopeWrite(_taskId, targetPath, allowedPaths) {
    const inScope = allowedPaths.some((p) => isPathInScope(targetPath, p, { caseSensitive: true }));
    if (!inScope) {
        return {
            allowed: false,
            reason: `写入 ${targetPath} 超出允许范围`,
        };
    }
    return { allowed: true };
}
/**
 * 生成工作区隔离报告。
 */
export function generateIsolationReport(taskId) {
    const activeLeases = listActiveLeases();
    const conflicts = [];
    // 检测冲突
    for (let i = 0; i < activeLeases.length; i++) {
        for (let j = i + 1; j < activeLeases.length; j++) {
            const a = activeLeases[i];
            const b = activeLeases[j];
            if (a.task_id === b.task_id)
                continue;
            const overlap = a.scope_paths.some((p) => b.scope_paths.some((bp) => isPathInScope(p, bp, { caseSensitive: true }) || isPathInScope(bp, p, { caseSensitive: true })));
            if (overlap) {
                conflicts.push({
                    lease_a_id: a.lease_id,
                    lease_b_id: b.lease_id,
                    conflict_path: a.scope_paths[0],
                    conflict_type: "scope_overlap",
                    resolved: false,
                });
            }
        }
    }
    const taskLeases = activeLeases.filter((l) => l.task_id === taskId);
    const hasDeliveryLease = taskLeases.some((l) => l.lease_type === "delivery" && l.status === "active");
    const hasConflict = conflicts.some((c) => taskLeases.some((l) => l.lease_id === c.lease_a_id || l.lease_id === c.lease_b_id));
    return {
        report_id: `wir-${taskId}-${Date.now()}`,
        task_id: taskId,
        active_leases: taskLeases,
        conflicts,
        out_of_scope_writes: [],
        delivery_blocked: hasConflict || !hasDeliveryLease,
        evaluated_at: new Date().toISOString(),
    };
}
/** 重置 lease 存储（测试用） */
export function resetLeaseStore() {
    leaseStore.clear();
}
//# sourceMappingURL=workspace_lease.js.map