import os from 'node:os';
export function defaultReleaseGateBudget() {
    const cores = Math.max(1, os.cpus().length || 1);
    const base = {
        'cpu-light': Math.min(48, cores * 6),
        'cpu-heavy': Math.max(1, cores),
        'io-light': Math.min(96, cores * 10),
        'io-heavy': Math.min(12, Math.max(1, cores)),
        git: Math.min(12, Math.max(1, cores)),
        'git-worktree': Math.min(8, Math.max(1, cores)),
        python: Math.min(12, Math.max(1, cores)),
        network: 12,
        'zellij-real': 1,
        'local-llm-real': Math.max(1, Number(process.env.SKS_LOCAL_LLM_MAX_PARALLEL || 1)),
        'remote-model-real': 6,
        'global-config': 1,
        publish: 1,
        'fs-read': Math.min(96, cores * 10)
    };
    for (const key of Object.keys(base)) {
        const envName = `SKS_RELEASE_MAX_${key.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}`;
        base[key] = envInt(envName, base[key]);
    }
    return base;
}
export function summarizeReleaseGateBudget(budget = defaultReleaseGateBudget()) {
    return Object.entries(budget)
        .filter(([, value]) => Number(value) > 0)
        .map(([resource, value]) => `${resource}=${value}`)
        .join(' ');
}
export function countReleaseGateResources(running) {
    return usedResources(running);
}
export function pickLaunchableReleaseGates(input) {
    const budget = input.budget || defaultReleaseGateBudget();
    const used = usedResources(input.running);
    const launchable = [];
    const maxTotal = envInt('SKS_RELEASE_MAX_TOTAL', Number.POSITIVE_INFINITY);
    for (const gate of input.ready) {
        if (input.running.length + launchable.length >= maxTotal)
            break;
        if (fits(gate, used, budget)) {
            launchable.push(gate);
            for (const resource of gate.resource)
                used[resource] = (used[resource] || 0) + 1;
        }
    }
    return launchable;
}
function envInt(name, fallback) {
    const parsed = Number(process.env[name]);
    return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;
}
function usedResources(running) {
    const used = {};
    for (const gate of running) {
        for (const resource of gate.resource)
            used[resource] = (used[resource] || 0) + 1;
    }
    return used;
}
function fits(gate, used, budget) {
    return gate.resource.every((resource) => (used[resource] || 0) < budget[resource]);
}
//# sourceMappingURL=release-gate-resource-governor.js.map