import path from 'node:path';
import { readJson } from '../fsx.js';
export async function resolveLoopGate(root, gateId) {
    const builtin = builtinLoopGate(gateId);
    if (builtin)
        return builtin;
    const releaseGate = await resolveReleaseGate(root, gateId);
    if (releaseGate)
        return releaseGate;
    const packageGate = await resolvePackageScriptGate(root, gateId);
    if (packageGate)
        return packageGate;
    return null;
}
export async function listLoopGateDefinitions(root) {
    const packageJson = await readJson(path.join(root, 'package.json'), {});
    const release = await readJson(path.join(root, 'release-gates.v2.json'), {});
    const packageScripts = packageJson && typeof packageJson === 'object' && packageJson.scripts && typeof packageJson.scripts === 'object'
        ? Object.keys(packageJson.scripts)
        : [];
    const releaseGates = Array.isArray(release.gates) ? release.gates : [];
    const definitions = [
        ...['gpt:final-arbiter', 'human:handoff-required', 'loop:checker-fresh-session', 'loop:state-valid', 'loop:budget-valid'].map((id) => builtinLoopGate(id)).filter((row) => Boolean(row)),
        ...releaseGates.map((gate) => normalizeReleaseGate(gate)).filter((row) => Boolean(row)),
        ...packageScripts.map((id) => ({
            id,
            command: `npm run ${shellQuote(id)} --silent`,
            source: 'package-json',
            side_effect: 'hermetic',
            timeout_ms: 300000,
            cache_allowed: true
        }))
    ];
    const byId = new Map();
    for (const definition of definitions)
        if (!byId.has(definition.id))
            byId.set(definition.id, definition);
    return [...byId.values()];
}
function builtinLoopGate(gateId) {
    if (gateId === 'gpt:final-arbiter') {
        return { id: gateId, command: 'builtin:gpt-final-arbiter', source: 'builtin-pseudo', side_effect: 'read-only', timeout_ms: 300000, cache_allowed: false };
    }
    if (gateId === 'human:handoff-required') {
        return { id: gateId, command: 'builtin:human-handoff-required', source: 'builtin-pseudo', side_effect: 'human', timeout_ms: 0, cache_allowed: false };
    }
    if (gateId === 'loop:checker-fresh-session') {
        return { id: gateId, command: 'builtin:loop-checker-fresh-session', source: 'builtin-pseudo', side_effect: 'read-only', timeout_ms: 30000, cache_allowed: false };
    }
    if (gateId === 'loop:state-valid') {
        return { id: gateId, command: 'builtin:loop-state-valid', source: 'builtin-pseudo', side_effect: 'read-only', timeout_ms: 30000, cache_allowed: true };
    }
    if (gateId === 'loop:budget-valid') {
        return { id: gateId, command: 'builtin:loop-budget-valid', source: 'builtin-pseudo', side_effect: 'read-only', timeout_ms: 30000, cache_allowed: true };
    }
    return null;
}
async function resolveReleaseGate(root, gateId) {
    const release = await readJson(path.join(root, 'release-gates.v2.json'), {});
    const gate = Array.isArray(release.gates) ? release.gates.find((row) => row.id === gateId) : null;
    return gate ? normalizeReleaseGate(gate) : null;
}
function normalizeReleaseGate(gate) {
    const id = String(gate.id || '');
    const command = String(gate.command || '');
    if (!id || !command)
        return null;
    return {
        id,
        command,
        source: 'release-gates-v2',
        side_effect: normalizeSideEffect(gate.side_effect),
        timeout_ms: Number.isFinite(Number(gate.timeout_ms)) ? Math.max(1, Number(gate.timeout_ms)) : 300000,
        cache_allowed: gate.cache?.enabled !== false
    };
}
async function resolvePackageScriptGate(root, gateId) {
    const packageJson = await readJson(path.join(root, 'package.json'), {});
    if (!packageJson?.scripts || typeof packageJson.scripts !== 'object' || !(gateId in packageJson.scripts))
        return null;
    return {
        id: gateId,
        command: `npm run ${shellQuote(gateId)} --silent`,
        source: 'package-json',
        side_effect: 'hermetic',
        timeout_ms: 300000,
        cache_allowed: true
    };
}
function normalizeSideEffect(value) {
    return value === 'read-only' || value === 'mutation' || value === 'human' ? value : 'hermetic';
}
function shellQuote(value) {
    return `'${String(value).replace(/'/g, `'\\''`)}'`;
}
//# sourceMappingURL=loop-gate-registry.js.map