export function defaultLoopBudget(overrides = {}) {
    return {
        max_iterations: 2,
        max_wall_ms: 15 * 60 * 1000,
        max_model_calls: 8,
        max_subagents: 4,
        max_tokens_estimate: 120000,
        max_changed_files: 16,
        max_patch_bytes: 256000,
        ...overrides
    };
}
export function validateLoopPlan(plan) {
    const blockers = [
        ...(plan.schema !== 'sks.loop-plan.v1' ? ['loop_plan_schema_invalid'] : []),
        ...(!plan.mission_id ? ['loop_plan_mission_id_missing'] : []),
        ...(!plan.request ? ['loop_plan_request_missing'] : []),
        ...(!plan.integration_loop_id ? ['loop_plan_integration_loop_missing'] : []),
        ...(plan.graph.nodes.length === 0 ? ['loop_plan_nodes_missing'] : []),
        ...(!plan.graph.nodes.some((node) => node.loop_id === plan.integration_loop_id) ? ['loop_plan_integration_node_missing'] : [])
    ];
    const ids = new Set();
    for (const node of plan.graph.nodes) {
        const result = validateLoopNode(node);
        blockers.push(...result.blockers);
        if (ids.has(node.loop_id))
            blockers.push(`loop_node_duplicate:${node.loop_id}`);
        ids.add(node.loop_id);
    }
    for (const edge of plan.graph.edges) {
        if (!ids.has(edge.from) || !ids.has(edge.to))
            blockers.push(`loop_edge_unknown:${edge.from}->${edge.to}`);
    }
    return { ok: blockers.length === 0, blockers };
}
export function validateLoopNode(node) {
    const blockers = [
        ...(node.schema !== 'sks.loop-node.v1' ? [`loop_node_schema_invalid:${node.loop_id}`] : []),
        ...(!node.loop_id ? ['loop_node_id_missing'] : []),
        ...(!node.mission_id ? [`loop_node_mission_missing:${node.loop_id}`] : []),
        ...(!node.state_file ? [`loop_state_file_missing:${node.loop_id}`] : []),
        ...(!node.run_log_file ? [`loop_run_log_file_missing:${node.loop_id}`] : []),
        ...(!node.owner_scope ? [`loop_owner_scope_missing:${node.loop_id}`] : []),
        ...validateLoopBudget(node.budget).blockers.map((blocker) => `${node.loop_id}:${blocker}`),
        ...(node.level === 'L3-unattended' && ['high', 'critical'].includes(node.risk.level) ? [`loop_l3_risk_blocked:${node.loop_id}`] : []),
        ...(node.level === 'L2-action' && !node.checker.required_before_next_iteration ? [`loop_action_checker_missing:${node.loop_id}`] : [])
    ];
    return { ok: blockers.length === 0, blockers };
}
export function validateLoopBudget(budget) {
    const blockers = [];
    for (const [key, value] of Object.entries(budget)) {
        if (!Number.isFinite(value) || value < 0)
            blockers.push(`loop_budget_invalid:${key}`);
    }
    if (budget.max_iterations < 1)
        blockers.push('loop_budget_iterations_missing');
    return { ok: blockers.length === 0, blockers };
}
export function allGateIds(gates) {
    return [...new Set([...gates.triage, ...gates.local, ...gates.checker, ...gates.integration, ...gates.final])];
}
//# sourceMappingURL=loop-schema.js.map