// engine/triagier/cost-guard.ts — SPEC-726: Wall-clock + token budget guard for Haiku calls
/**
 * Run `fn` under a wall-clock timeout.
 * If fn completes within the deadline → return its result.
 * If fn exceeds the deadline → return { fallback: true } and emit telemetry.
 *
 * Note: the in-flight promise from fn is not cancelled (JS has no cancellation primitives),
 * but callers will receive the fallback immediately and can ignore the late result.
 */
export async function runWithGuard(fn, opts) {
    const wallClockMs = opts?.wallClockMs ?? 5_000;
    const TIMEOUT_SENTINEL = Symbol('timeout');
    const timeoutRace = new Promise((resolve) => {
        setTimeout(() => {
            resolve(TIMEOUT_SENTINEL);
        }, wallClockMs);
    });
    let result;
    try {
        result = await Promise.race([fn(), timeoutRace]);
    }
    catch (err) {
        // fn threw — emit telemetry and return fallback
        console.warn('[triagier:cost-guard] fn_threw', {
            error: err instanceof Error ? err.message : String(err),
        });
        emitGuardTelemetry('fn_threw');
        return { fallback: true };
    }
    if (result === TIMEOUT_SENTINEL) {
        console.warn('[triagier:cost-guard] wall_clock_timeout', { wallClockMs });
        emitGuardTelemetry('wall_clock_timeout');
        return { fallback: true };
    }
    return result;
}
function emitGuardTelemetry(reason) {
    // Best-effort telemetry — fire and forget, never throw
    try {
        // eslint-disable-next-line no-console -- intentional best-effort telemetry; no telemetry client available in this context
        console.info('[triagier] triage_guard_tripped', {
            reason,
            timestamp: new Date().toISOString(),
        });
    }
    catch {
        // ignore
    }
}
//# sourceMappingURL=cost-guard.js.map