/**
 * Operation Verification Gate System for CLEO
 *
 * Implements 4-layer validation gate system for dispatch operations:
 * Layer 1: Schema Validation (JSON Schema compliance)
 * Layer 2: Semantic Validation (Business rules)
 * Layer 3: Referential Validation (Cross-entity integrity)
 * Layer 4: Protocol Validation (RCASD-IVTR+C lifecycle)
 *
 * Moved to core for proper layering (formerly in dispatch).
 *
 * @task T2936
 * @task T5707
 * @epic T2908
 */
import { ProtocolEnforcer } from '../compliance/protocol-enforcement.js';
import { ErrorCategory, ErrorSeverity, ProtocolExitCode } from '../compliance/protocol-types.js';
import { validateLayer1Schema, validateLayer2Semantic, validateLayer3Referential, validateLayer4Protocol, } from './operation-gate-validators.js';
/**
 * Gate layer enumeration
 */
export var GateLayer;
(function (GateLayer) {
    GateLayer[GateLayer["SCHEMA"] = 1] = "SCHEMA";
    GateLayer[GateLayer["SEMANTIC"] = 2] = "SEMANTIC";
    GateLayer[GateLayer["REFERENTIAL"] = 3] = "REFERENTIAL";
    GateLayer[GateLayer["PROTOCOL"] = 4] = "PROTOCOL";
})(GateLayer || (GateLayer = {}));
/**
 * Gate status for each layer
 */
export var GateStatus;
(function (GateStatus) {
    GateStatus["PENDING"] = "pending";
    GateStatus["PASSED"] = "passed";
    GateStatus["FAILED"] = "failed";
    GateStatus["BLOCKED"] = "blocked";
    GateStatus["SKIPPED"] = "skipped";
})(GateStatus || (GateStatus = {}));
/**
 * Main Verification Gate class
 *
 * Orchestrates 4-layer validation and determines pass/fail status.
 * Each layer must pass before proceeding to the next.
 */
export class VerificationGate {
    protocolEnforcer;
    strictMode;
    constructor(strictMode = true) {
        this.protocolEnforcer = new ProtocolEnforcer(strictMode);
        this.strictMode = strictMode;
    }
    /**
     * Execute all 4 gate layers sequentially
     *
     * Stops at first failure unless in advisory mode.
     */
    async verifyOperation(context) {
        const layers = {};
        // Layer 1: Schema Validation
        const schemaResult = await this.runLayer(GateLayer.SCHEMA, () => validateLayer1Schema(context));
        layers[GateLayer.SCHEMA] = schemaResult;
        if (!schemaResult.passed && this.strictMode) {
            return this.buildFailureResult(layers, GateLayer.SCHEMA);
        }
        // Layer 2: Semantic Validation
        const semanticResult = await this.runLayer(GateLayer.SEMANTIC, () => validateLayer2Semantic(context));
        layers[GateLayer.SEMANTIC] = semanticResult;
        if (!semanticResult.passed && this.strictMode) {
            return this.buildFailureResult(layers, GateLayer.SEMANTIC);
        }
        // Layer 3: Referential Validation
        const referentialResult = await this.runLayer(GateLayer.REFERENTIAL, () => validateLayer3Referential(context));
        layers[GateLayer.REFERENTIAL] = referentialResult;
        if (!referentialResult.passed && this.strictMode) {
            return this.buildFailureResult(layers, GateLayer.REFERENTIAL);
        }
        // Layer 4: Protocol Validation
        const protocolResult = await this.runLayer(GateLayer.PROTOCOL, () => validateLayer4Protocol(context, this.protocolEnforcer));
        layers[GateLayer.PROTOCOL] = protocolResult;
        if (!protocolResult.passed && this.strictMode) {
            return this.buildFailureResult(layers, GateLayer.PROTOCOL);
        }
        // All gates passed
        return this.buildSuccessResult(layers);
    }
    /**
     * Run a single validation layer with timing
     */
    async runLayer(layer, validator) {
        const startTime = Date.now();
        try {
            const result = await validator();
            result.duration_ms = Date.now() - startTime;
            return result;
        }
        catch (error) {
            // Convert exceptions to layer failures
            return {
                layer,
                status: GateStatus.FAILED,
                passed: false,
                violations: [
                    {
                        layer,
                        severity: ErrorSeverity.ERROR,
                        code: 'E_VALIDATION_ERROR',
                        message: error instanceof Error ? error.message : String(error),
                    },
                ],
                duration_ms: Date.now() - startTime,
            };
        }
    }
    /**
     * Build success result when all gates pass
     */
    buildSuccessResult(layers) {
        return {
            passed: true,
            layers,
            totalViolations: 0,
            exitCode: ProtocolExitCode.SUCCESS,
            category: ErrorCategory.GENERAL,
            summary: 'All verification gates passed',
        };
    }
    /**
     * Build failure result when a gate fails
     */
    buildFailureResult(layers, blockedAt) {
        const failedLayer = layers[blockedAt];
        const totalViolations = Object.values(layers).reduce((sum, layer) => sum + layer.violations.length, 0);
        // Determine exit code based on layer and violation type
        let exitCode = ProtocolExitCode.E_VALIDATION_ERROR;
        let category = ErrorCategory.GENERAL;
        if (blockedAt === GateLayer.SCHEMA) {
            exitCode = ProtocolExitCode.E_VALIDATION_ERROR;
            category = ErrorCategory.GENERAL;
        }
        else if (blockedAt === GateLayer.SEMANTIC) {
            exitCode = this.determineSemanticExitCode(failedLayer.violations);
            category = ErrorCategory.HIERARCHY;
        }
        else if (blockedAt === GateLayer.REFERENTIAL) {
            exitCode = this.determineReferentialExitCode(failedLayer.violations);
            category = ErrorCategory.HIERARCHY;
        }
        else if (blockedAt === GateLayer.PROTOCOL) {
            exitCode = this.determineProtocolExitCode(failedLayer.violations);
            category = ErrorCategory.PROTOCOL;
        }
        return {
            passed: false,
            layers,
            totalViolations,
            exitCode,
            category,
            summary: `Verification failed at layer ${blockedAt}: ${failedLayer.violations[0]?.message || 'Unknown error'}`,
            blockedAt,
        };
    }
    /**
     * Determine semantic layer exit code from violations
     */
    determineSemanticExitCode(violations) {
        for (const v of violations) {
            if (v.code.includes('PARENT'))
                return ProtocolExitCode.E_PARENT_NOT_FOUND;
            if (v.code.includes('DEPTH'))
                return ProtocolExitCode.E_DEPTH_EXCEEDED;
            if (v.code.includes('SIBLING'))
                return ProtocolExitCode.E_SIBLING_LIMIT;
            if (v.code.includes('CIRCULAR'))
                return ProtocolExitCode.E_CIRCULAR_REFERENCE;
            if (v.code.includes('SESSION'))
                return ProtocolExitCode.E_SESSION_REQUIRED;
        }
        return ProtocolExitCode.E_VALIDATION_ERROR;
    }
    /**
     * Determine referential layer exit code from violations
     */
    determineReferentialExitCode(violations) {
        for (const v of violations) {
            if (v.code.includes('NOT_FOUND'))
                return ProtocolExitCode.E_NOT_FOUND;
            if (v.code.includes('PARENT'))
                return ProtocolExitCode.E_PARENT_NOT_FOUND;
            if (v.code.includes('DEPENDENCY'))
                return ProtocolExitCode.E_DEPENDENCY_ERROR;
        }
        return ProtocolExitCode.E_NOT_FOUND;
    }
    /**
     * Determine protocol layer exit code from violations
     */
    determineProtocolExitCode(violations) {
        for (const v of violations) {
            if (v.code.includes('RESEARCH'))
                return ProtocolExitCode.E_PROTOCOL_RESEARCH;
            if (v.code.includes('CONSENSUS'))
                return ProtocolExitCode.E_PROTOCOL_CONSENSUS;
            if (v.code.includes('SPECIFICATION'))
                return ProtocolExitCode.E_PROTOCOL_SPECIFICATION;
            if (v.code.includes('DECOMPOSITION'))
                return ProtocolExitCode.E_PROTOCOL_DECOMPOSITION;
            if (v.code.includes('IMPLEMENTATION'))
                return ProtocolExitCode.E_PROTOCOL_IMPLEMENTATION;
            if (v.code.includes('CONTRIBUTION'))
                return ProtocolExitCode.E_PROTOCOL_CONTRIBUTION;
            if (v.code.includes('RELEASE'))
                return ProtocolExitCode.E_PROTOCOL_RELEASE;
            if (v.code.includes('VALIDATION'))
                return ProtocolExitCode.E_PROTOCOL_VALIDATION;
            if (v.code.includes('TESTING'))
                return ProtocolExitCode.E_TESTS_SKIPPED;
            if (v.code.includes('LIFECYCLE'))
                return ProtocolExitCode.E_LIFECYCLE_GATE_FAILED;
        }
        return ProtocolExitCode.E_PROTOCOL_GENERIC;
    }
    /**
     * Check if an operation requires gate validation
     *
     * All mutate operations require validation.
     * Query operations skip validation for performance.
     */
    static requiresValidation(context) {
        if (context.gateway === 'mutate') {
            return true;
        }
        return false;
    }
    /**
     * Get human-readable layer name
     */
    static getLayerName(layer) {
        const names = {
            [GateLayer.SCHEMA]: 'Schema Validation',
            [GateLayer.SEMANTIC]: 'Semantic Validation',
            [GateLayer.REFERENTIAL]: 'Referential Validation',
            [GateLayer.PROTOCOL]: 'Protocol Validation',
        };
        return names[layer];
    }
}
/**
 * Factory function for creating verification gates
 */
export function createVerificationGate(strictMode = true) {
    return new VerificationGate(strictMode);
}
/**
 * Export gate layer sequence for external use
 */
export const GATE_SEQUENCE = [
    GateLayer.SCHEMA,
    GateLayer.SEMANTIC,
    GateLayer.REFERENTIAL,
    GateLayer.PROTOCOL,
];
// ============================================================================
// Section 7: Workflow Verification Gates
// ============================================================================
/**
 * Workflow gate names per protocol specification Section 7.1
 *
 * @task T3141
 */
export var WorkflowGateName;
(function (WorkflowGateName) {
    WorkflowGateName["IMPLEMENTED"] = "implemented";
    WorkflowGateName["TESTS_PASSED"] = "testsPassed";
    WorkflowGateName["QA_PASSED"] = "qaPassed";
    WorkflowGateName["CLEANUP_DONE"] = "cleanupDone";
    WorkflowGateName["SECURITY_PASSED"] = "securityPassed";
    WorkflowGateName["DOCUMENTED"] = "documented";
})(WorkflowGateName || (WorkflowGateName = {}));
/**
 * Complete workflow gate definitions per Section 7.2
 */
export const WORKFLOW_GATE_DEFINITIONS = [
    {
        name: WorkflowGateName.IMPLEMENTED,
        agent: 'coder',
        dependsOn: [],
        description: 'Code implementation complete',
    },
    {
        name: WorkflowGateName.TESTS_PASSED,
        agent: 'testing',
        dependsOn: [WorkflowGateName.IMPLEMENTED],
        description: 'All tests passing',
    },
    {
        name: WorkflowGateName.QA_PASSED,
        agent: 'qa',
        dependsOn: [WorkflowGateName.TESTS_PASSED],
        description: 'QA review approved',
    },
    {
        name: WorkflowGateName.CLEANUP_DONE,
        agent: 'cleanup',
        dependsOn: [WorkflowGateName.QA_PASSED],
        description: 'Code cleanup finished',
    },
    {
        name: WorkflowGateName.SECURITY_PASSED,
        agent: 'security',
        dependsOn: [WorkflowGateName.CLEANUP_DONE],
        description: 'Security audit passed',
    },
    {
        name: WorkflowGateName.DOCUMENTED,
        agent: 'docs',
        dependsOn: [WorkflowGateName.SECURITY_PASSED],
        description: 'Documentation complete',
    },
];
/**
 * Ordered workflow gate sequence per Section 7.1
 */
export const WORKFLOW_GATE_SEQUENCE = [
    WorkflowGateName.IMPLEMENTED,
    WorkflowGateName.TESTS_PASSED,
    WorkflowGateName.QA_PASSED,
    WorkflowGateName.CLEANUP_DONE,
    WorkflowGateName.SECURITY_PASSED,
    WorkflowGateName.DOCUMENTED,
];
/**
 * Map from gate name to definition for fast lookup
 */
const GATE_DEF_MAP = Object.fromEntries(WORKFLOW_GATE_DEFINITIONS.map((d) => [d.name, d]));
/**
 * WorkflowGateTracker
 *
 * Tracks the status of all 6 workflow verification gates for a task.
 * Implements Section 7.4 failure cascade behavior: when a gate fails,
 * all downstream gates reset to null.
 *
 * @task T3141
 */
export class WorkflowGateTracker {
    gates;
    constructor() {
        this.gates = new Map();
        for (const def of WORKFLOW_GATE_DEFINITIONS) {
            this.gates.set(def.name, {
                name: def.name,
                status: null,
                agent: def.agent,
                updatedAt: null,
            });
        }
    }
    /**
     * Get the status of a specific gate
     */
    getGateStatus(gateName) {
        const gate = this.gates.get(gateName);
        return gate ? gate.status : null;
    }
    /**
     * Get the full state of a specific gate
     */
    getGateState(gateName) {
        return this.gates.get(gateName);
    }
    /**
     * Get all gate states
     */
    getAllGates() {
        return WORKFLOW_GATE_SEQUENCE.map((name) => this.gates.get(name));
    }
    /**
     * Check if a gate can be attempted (all dependencies passed)
     */
    canAttempt(gateName) {
        const def = GATE_DEF_MAP[gateName];
        if (!def)
            return false;
        for (const dep of def.dependsOn) {
            const depState = this.gates.get(dep);
            if (!depState || depState.status !== 'passed') {
                return false;
            }
        }
        return true;
    }
    /**
     * Mark a gate as passed.
     */
    passGate(gateName, agent) {
        if (!this.isValidGate(gateName))
            return false;
        if (!this.canAttempt(gateName))
            return false;
        const gate = this.gates.get(gateName);
        const expectedAgent = GATE_DEF_MAP[gateName].agent;
        if (agent && agent !== expectedAgent)
            return false;
        gate.status = 'passed';
        gate.updatedAt = new Date().toISOString();
        delete gate.failureReason;
        return true;
    }
    /**
     * Mark a gate as failed.
     *
     * Per Section 7.4: When a gate fails, all downstream gates reset to null.
     */
    failGate(gateName, reason) {
        if (!this.isValidGate(gateName))
            return false;
        const gate = this.gates.get(gateName);
        gate.status = 'failed';
        gate.updatedAt = new Date().toISOString();
        if (reason)
            gate.failureReason = reason;
        // Section 7.4 failure cascade: reset all downstream gates to null
        this.cascadeReset(gateName);
        return true;
    }
    /**
     * Reset a gate and all downstream gates to null.
     */
    cascadeReset(failedGateName) {
        const failedIndex = WORKFLOW_GATE_SEQUENCE.indexOf(failedGateName);
        if (failedIndex === -1)
            return;
        for (let i = failedIndex + 1; i < WORKFLOW_GATE_SEQUENCE.length; i++) {
            const downstreamName = WORKFLOW_GATE_SEQUENCE[i];
            const downstreamGate = this.gates.get(downstreamName);
            downstreamGate.status = null;
            downstreamGate.updatedAt = null;
            delete downstreamGate.failureReason;
        }
    }
    /**
     * Update blocked status for all gates based on current state.
     */
    updateBlockedStatus() {
        for (const name of WORKFLOW_GATE_SEQUENCE) {
            const gate = this.gates.get(name);
            if (gate.status === null && !this.canAttempt(name)) {
                gate.status = 'blocked';
            }
            if (gate.status === 'blocked' && this.canAttempt(name)) {
                gate.status = null;
            }
        }
    }
    /**
     * Check if all gates have passed
     */
    allPassed() {
        for (const name of WORKFLOW_GATE_SEQUENCE) {
            if (this.gates.get(name).status !== 'passed')
                return false;
        }
        return true;
    }
    /**
     * Get all gates that are currently blocked or have null status
     */
    getPendingGates() {
        return this.getAllGates().filter((g) => g.status === null || g.status === 'blocked');
    }
    /**
     * Get the next gate that can be attempted
     */
    getNextAttemptable() {
        for (const name of WORKFLOW_GATE_SEQUENCE) {
            const gate = this.gates.get(name);
            if (gate.status !== 'passed' && this.canAttempt(name)) {
                return name;
            }
        }
        return null;
    }
    /**
     * Get downstream gates of a given gate (not including the gate itself)
     */
    getDownstreamGates(gateName) {
        const index = WORKFLOW_GATE_SEQUENCE.indexOf(gateName);
        if (index === -1)
            return [];
        return WORKFLOW_GATE_SEQUENCE.slice(index + 1);
    }
    /**
     * Serialize gate states to a plain record
     */
    toRecord() {
        const record = {};
        for (const name of WORKFLOW_GATE_SEQUENCE) {
            record[name] = this.gates.get(name).status;
        }
        return record;
    }
    /**
     * Restore gate states from a record
     */
    fromRecord(record) {
        for (const [name, status] of Object.entries(record)) {
            const gate = this.gates.get(name);
            if (gate) {
                gate.status = status;
            }
        }
    }
    /**
     * Check if a gate name is valid
     */
    isValidGate(gateName) {
        return this.gates.has(gateName);
    }
}
/**
 * Validate a workflow gate name string
 */
export function isValidWorkflowGateName(name) {
    return WORKFLOW_GATE_SEQUENCE.includes(name);
}
/**
 * Get the definition for a workflow gate
 */
export function getWorkflowGateDefinition(name) {
    return GATE_DEF_MAP[name];
}
//# sourceMappingURL=operation-verification-gates.js.map