/**
 * ConfidenceGate -- Self-reported confidence threshold gate.
 *
 * Fires during PreToolUse. Reads `tool.args.confidence` (a 0-1 float the
 * agent MAY emit). If confidence is below `minConfidenceForAutonomous` the
 * decision is routed to the approval queue. If below
 * `minConfidenceForReviewer` the gate fails closed per
 * `belowReviewerThresholdAction`. If confidence is absent the gate treats
 * the call as strict-fail-closed by default (configurable per pack).
 *
 * P3-T1 coverage gap: Confidence threshold enforcement before decision gates.
 *
 * Compliance bindings:
 *   - MRPC 1.6: legal agents -- very strict autonomous threshold (>= 0.95)
 *   - HIPAA 164.308(a)(1): risk analysis -- high-certainty bar for PHI decisions
 *   - FDA SaMD: autonomous clinical decisions require near-certain confidence
 *   - EU AI Act Art. 14: human oversight -- route uncertain decisions to human
 *   - ISO 42001 A.9.2: AI performance management
 *
 * @connexum/ai-governance
 */
// ---------------------------------------------------------------------------
// Errors
// ---------------------------------------------------------------------------
export class ConfidenceBelowAutonomousError extends Error {
    agentId;
    toolName;
    confidence;
    minConfidenceForAutonomous;
    packBinding;
    constructor(opts) {
        super(`Confidence ${opts.confidence.toFixed(3)} is below autonomous threshold ` +
            `${opts.minConfidenceForAutonomous} for agent '${opts.agentId}' tool '${opts.toolName}'. ` +
            `Decision routed to human reviewer via approval queue.`);
        this.name = 'ConfidenceBelowAutonomousError';
        this.agentId = opts.agentId;
        this.toolName = opts.toolName;
        this.confidence = opts.confidence;
        this.minConfidenceForAutonomous = opts.minConfidenceForAutonomous;
        this.packBinding = opts.packBinding ?? [];
    }
}
export class ConfidenceBelowReviewerError extends Error {
    agentId;
    toolName;
    confidence;
    minConfidenceForReviewer;
    packBinding;
    constructor(opts) {
        super(`Confidence ${opts.confidence.toFixed(3)} is below reviewer threshold ` +
            `${opts.minConfidenceForReviewer} for agent '${opts.agentId}' tool '${opts.toolName}'. ` +
            `Action denied (fail-closed) per belowReviewerThresholdAction policy.`);
        this.name = 'ConfidenceBelowReviewerError';
        this.agentId = opts.agentId;
        this.toolName = opts.toolName;
        this.confidence = opts.confidence;
        this.minConfidenceForReviewer = opts.minConfidenceForReviewer;
        this.packBinding = opts.packBinding ?? [];
    }
}
export class ConfidenceMissingError extends Error {
    agentId;
    toolName;
    packBinding;
    constructor(opts) {
        super(`No confidence score provided by agent '${opts.agentId}' for tool '${opts.toolName}'. ` +
            `Strict pack policy requires a confidence score. Action denied (fail-closed).`);
        this.name = 'ConfidenceMissingError';
        this.agentId = opts.agentId;
        this.toolName = opts.toolName;
        this.packBinding = opts.packBinding ?? [];
    }
}
// ---------------------------------------------------------------------------
// ConfidenceGate
// ---------------------------------------------------------------------------
const DEFAULT_MIN_AUTONOMOUS = 0.85;
const DEFAULT_MIN_REVIEWER = 0.60;
export class ConfidenceGate {
    config;
    constructor(config = {}) {
        this.config = {
            minConfidenceForAutonomous: DEFAULT_MIN_AUTONOMOUS,
            minConfidenceForReviewer: DEFAULT_MIN_REVIEWER,
            perPackOverrides: {},
            belowReviewerThresholdAction: 'deny',
            missingConfidencePolicy: 'strict',
            ...config,
        };
        // Validate thresholds are sane.
        if (this.config.minConfidenceForReviewer >= this.config.minConfidenceForAutonomous) {
            throw new Error('ConfidenceGate: minConfidenceForReviewer must be strictly less than minConfidenceForAutonomous.');
        }
    }
    /**
     * Resolve effective thresholds, considering active pack overrides.
     */
    resolveThresholds(activePackIds = []) {
        let autonomous = this.config.minConfidenceForAutonomous;
        let reviewer = this.config.minConfidenceForReviewer;
        // Apply the strictest matching pack override (take the highest threshold).
        for (const packId of activePackIds) {
            const override = this.config.perPackOverrides[packId];
            if (!override)
                continue;
            if (override.minConfidenceForAutonomous !== undefined) {
                autonomous = Math.max(autonomous, override.minConfidenceForAutonomous);
            }
            if (override.minConfidenceForReviewer !== undefined) {
                reviewer = Math.max(reviewer, override.minConfidenceForReviewer);
            }
        }
        return { minConfidenceForAutonomous: autonomous, minConfidenceForReviewer: reviewer };
    }
    /**
     * PreToolUse hook entry point.
     *
     * Reads `toolArgs.confidence` (if present) and applies the configured
     * threshold policy. Throws synchronously on any non-allow outcome.
     *
     * @param agentId      Identity of the calling agent.
     * @param toolName     Name of the tool being invoked.
     * @param toolArgs     Arguments supplied to the tool call (may include `confidence`).
     * @param activePackIds Active compliance pack IDs for override resolution.
     */
    hook(agentId, toolName, toolArgs, activePackIds = []) {
        const thresholds = this.resolveThresholds(activePackIds);
        const rawConfidence = toolArgs['confidence'];
        // --- Missing confidence ---
        if (rawConfidence === undefined || rawConfidence === null) {
            const event = {
                type: 'governance:confidence-missing',
                agentId,
                toolName,
                confidence: null,
                minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
                minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
                outcome: this.config.missingConfidencePolicy === 'strict' ? 'deny' : 'warn-missing',
                packBinding: activePackIds,
                timestamp: new Date().toISOString(),
            };
            this.config.onAuditEvent?.(event);
            if (this.config.missingConfidencePolicy === 'strict') {
                throw new ConfidenceMissingError({ agentId, toolName, packBinding: activePackIds });
            }
            // lax: emit warn and allow.
            return;
        }
        // M8a / PT-G8-CONFIDENCE-1: reject non-numeric confidence values.
        // Number("0.99") === 0.99, so a string would silently bypass the gate.
        // Confidence MUST be a JavaScript number primitive; strings are not valid.
        if (typeof rawConfidence !== 'number') {
            const event = {
                type: 'governance:confidence-missing',
                agentId,
                toolName,
                confidence: null,
                minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
                minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
                outcome: 'deny',
                packBinding: activePackIds,
                timestamp: new Date().toISOString(),
            };
            this.config.onAuditEvent?.(event);
            throw new ConfidenceMissingError({ agentId, toolName, packBinding: activePackIds });
        }
        const confidence = Number(rawConfidence);
        if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) {
            // Malformed confidence value -- treat as missing under strict policy.
            const event = {
                type: 'governance:confidence-missing',
                agentId,
                toolName,
                confidence: null,
                minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
                minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
                outcome: 'deny',
                packBinding: activePackIds,
                timestamp: new Date().toISOString(),
            };
            this.config.onAuditEvent?.(event);
            throw new ConfidenceMissingError({ agentId, toolName, packBinding: activePackIds });
        }
        // --- Below reviewer threshold ---
        if (confidence < thresholds.minConfidenceForReviewer) {
            const outcome = this.config.belowReviewerThresholdAction === 'require-second-agent'
                ? 'require-second-agent'
                : 'deny';
            const event = {
                type: 'governance:confidence-below-reviewer',
                agentId,
                toolName,
                confidence,
                minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
                minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
                outcome,
                packBinding: activePackIds,
                timestamp: new Date().toISOString(),
            };
            this.config.onAuditEvent?.(event);
            throw new ConfidenceBelowReviewerError({
                agentId,
                toolName,
                confidence,
                minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
                packBinding: activePackIds,
            });
        }
        // --- Below autonomous threshold (but above reviewer threshold) ---
        if (confidence < thresholds.minConfidenceForAutonomous) {
            const event = {
                type: 'governance:confidence-below-autonomous',
                agentId,
                toolName,
                confidence,
                minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
                minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
                outcome: 'route-to-reviewer',
                packBinding: activePackIds,
                timestamp: new Date().toISOString(),
            };
            this.config.onAuditEvent?.(event);
            throw new ConfidenceBelowAutonomousError({
                agentId,
                toolName,
                confidence,
                minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
                packBinding: activePackIds,
            });
        }
        // --- Passed ---
        const event = {
            type: 'governance:confidence-passed',
            agentId,
            toolName,
            confidence,
            minConfidenceForAutonomous: thresholds.minConfidenceForAutonomous,
            minConfidenceForReviewer: thresholds.minConfidenceForReviewer,
            outcome: 'allow',
            packBinding: activePackIds,
            timestamp: new Date().toISOString(),
        };
        this.config.onAuditEvent?.(event);
    }
}
//# sourceMappingURL=confidence-gate.js.map