"use strict";
/**
 * MissionGovernor — the single authorization chokepoint every autonomous
 * mission traverses before execution.
 *
 * Phase 3 (Governance on Every Mission) of the autonomous-agent milestone.
 *
 * Before Phase 3, GovernanceLayer.evaluate() ran on Telegram text and
 * advisorily inside OrchestrationLoop, but missions enqueued by the
 * GoalTicker / CLI / HTTP could reach the orchestration loop and start
 * spending tokens before any hard gate. MissionGovernor closes that hole:
 * it is called as the FIRST thing in MissionExecutor.execute(), blocks
 * disallowed missions before any LLM spend, layers the VortexAuthorityGuard
 * on top (push/PR/publish need an explicit token), and records every
 * decision in the SHA-chained GovernanceScopeLedger.
 *
 * Defense in depth: OrchestrationLoop still runs its own internal governance
 * — this chokepoint is the outer gate, not a replacement.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.MissionGovernor = void 0;
const GovernanceLayer_1 = require("./GovernanceLayer");
const GovernanceScopeLedger_1 = require("./GovernanceScopeLedger");
const VortexAuthorityGuard_1 = require("./VortexAuthorityGuard");
class MissionGovernor {
    governance;
    ledger;
    vortexGuard;
    constructor(opts = {}) {
        this.governance = opts.governance || new GovernanceLayer_1.GovernanceLayer();
        this.ledger = opts.ledger || new GovernanceScopeLedger_1.GovernanceScopeLedger();
        this.vortexGuard = opts.vortexGuard || new VortexAuthorityGuard_1.VortexAuthorityGuard();
    }
    /**
     * Authorize a mission. Never throws. Always appends to the ledger so the
     * audit trail records denials as well as approvals.
     */
    authorize(mission) {
        const project = mission.context?.project || 'default';
        const baseDecision = this.governance.evaluate(mission.goal, project);
        // GovernanceLayer.evaluate() already appended the base decision to the
        // ledger internally. We only append again when the vortex layer OVERRIDES
        // that decision, so the trail records the override without duplicating the
        // base evaluation.
        const vortex = this.vortexGuard.check(mission.goal, mission.context);
        let decision = baseDecision;
        let vortexBlocked = false;
        if (vortex.requiresAuthority && !vortex.authorized) {
            vortexBlocked = true;
            decision = {
                ...baseDecision,
                allowed: false,
                riskLevel: 'high',
                requiresConsent: false,
                blockedCapabilities: Array.from(new Set([...(baseDecision.blockedCapabilities || []), ...vortex.matchedOps])),
            };
            // Record the vortex override as a distinct ledger entry.
            try {
                this.ledger.append(mission.goal, project, decision);
            }
            catch {
                // Ledger failure must not crash the gate — the decision still stands.
            }
        }
        if (!decision.allowed) {
            const reason = vortexBlocked
                ? `vortex_authority_required: ${vortex.matchedOps.join(',')}`
                : `mission_blocked_by_governance: risk=${decision.riskLevel} blocked=${(decision.blockedCapabilities || []).join(',')}`;
            return {
                allowed: false,
                decision,
                reason,
                vortexBlocked,
                matchedVortexOps: vortex.requiresAuthority ? vortex.matchedOps : undefined,
            };
        }
        return { allowed: true, decision };
    }
}
exports.MissionGovernor = MissionGovernor;
