/**
 * Protocol Enforcement for CLEO
 *
 * Validates RCASD-IVTR+C lifecycle compliance with exit codes 60-70.
 * Intercepts domain operations to enforce protocol requirements before execution.
 *
 * Moved from src/mcp/lib/protocol-enforcement.ts to core for proper layering.
 *
 * @task T2918
 * @task T5707
 * @epic T2908
 */
import { PROTOCOL_RULES, } from './protocol-rules.js';
import { ProtocolExitCode } from './protocol-types.js';
/**
 * Protocol types aligned with RCASD-IVTR+C lifecycle
 */
export var ProtocolType;
(function (ProtocolType) {
    ProtocolType["RESEARCH"] = "research";
    ProtocolType["CONSENSUS"] = "consensus";
    ProtocolType["SPECIFICATION"] = "specification";
    ProtocolType["DECOMPOSITION"] = "decomposition";
    ProtocolType["IMPLEMENTATION"] = "implementation";
    ProtocolType["CONTRIBUTION"] = "contribution";
    ProtocolType["RELEASE"] = "release";
    ProtocolType["VALIDATION"] = "validation";
    ProtocolType["TESTING"] = "testing";
})(ProtocolType || (ProtocolType = {}));
/**
 * Exit code mapping for protocol violations
 */
const PROTOCOL_EXIT_CODES = {
    [ProtocolType.RESEARCH]: ProtocolExitCode.E_PROTOCOL_RESEARCH,
    [ProtocolType.CONSENSUS]: ProtocolExitCode.E_PROTOCOL_CONSENSUS,
    [ProtocolType.SPECIFICATION]: ProtocolExitCode.E_PROTOCOL_SPECIFICATION,
    [ProtocolType.DECOMPOSITION]: ProtocolExitCode.E_PROTOCOL_DECOMPOSITION,
    [ProtocolType.IMPLEMENTATION]: ProtocolExitCode.E_PROTOCOL_IMPLEMENTATION,
    [ProtocolType.CONTRIBUTION]: ProtocolExitCode.E_PROTOCOL_CONTRIBUTION,
    [ProtocolType.RELEASE]: ProtocolExitCode.E_PROTOCOL_RELEASE,
    [ProtocolType.VALIDATION]: ProtocolExitCode.E_PROTOCOL_VALIDATION,
    [ProtocolType.TESTING]: ProtocolExitCode.E_TESTS_SKIPPED,
};
/**
 * Lifecycle stage dependencies
 */
const LIFECYCLE_GATES = {
    research: [],
    consensus: ['research'],
    architecture_decision: ['research', 'consensus'],
    specification: ['research', 'consensus', 'architecture_decision'],
    decomposition: ['research', 'specification', 'architecture_decision'],
    implementation: ['research', 'specification', 'decomposition', 'architecture_decision'],
    contribution: [], // Cross-cutting: no strict prerequisites
    validation: ['implementation'],
    testing: ['implementation', 'validation'],
    release: ['implementation', 'validation', 'testing'],
};
/**
 * Main protocol enforcement class
 */
export class ProtocolEnforcer {
    violations = [];
    strictMode;
    constructor(strictMode = true) {
        this.strictMode = strictMode;
    }
    /**
     * Validate protocol compliance for a manifest entry
     */
    async validateProtocol(protocol, manifestEntry, additionalData) {
        const rules = PROTOCOL_RULES[protocol];
        if (!rules) {
            return {
                valid: false,
                violations: [
                    {
                        requirement: 'UNKNOWN',
                        severity: 'error',
                        message: `Unknown protocol type: ${protocol}`,
                        fix: 'Use valid protocol type',
                    },
                ],
                score: 0,
            };
        }
        const violations = [];
        let score = 100;
        // Validate each rule
        for (const rule of rules) {
            const violation = await this.validateRule(rule, manifestEntry, additionalData);
            if (violation) {
                violations.push(violation);
                score -= this.calculatePenalty(violation.severity);
            }
        }
        return {
            valid: violations.filter((v) => v.severity === 'error').length === 0,
            violations,
            score,
        };
    }
    /**
     * Validate a single rule
     */
    async validateRule(rule, manifestEntry, additionalData) {
        try {
            const isValid = await rule.validate(manifestEntry, additionalData);
            if (!isValid) {
                return {
                    requirement: rule.id,
                    severity: rule.level === 'MUST' ? 'error' : 'warning',
                    message: rule.message,
                    fix: rule.fix,
                };
            }
            return null;
        }
        catch (error) {
            return {
                requirement: rule.id,
                severity: 'error',
                message: `Validation error: ${error instanceof Error ? error.message : String(error)}`,
                fix: rule.fix,
            };
        }
    }
    /**
     * Check lifecycle gate prerequisites
     */
    async checkLifecycleGate(_taskId, targetStage, lifecycleManifest) {
        const prerequisites = LIFECYCLE_GATES[targetStage] || [];
        if (!lifecycleManifest) {
            // No manifest available - warn but allow
            return {
                passed: true,
                missingPrerequisites: [],
                message: 'No RCASD manifest found - gate check skipped',
            };
        }
        const missingPrerequisites = [];
        for (const prereq of prerequisites) {
            const stageStatus = lifecycleManifest[prereq];
            if (stageStatus !== 'completed' && stageStatus !== 'skipped') {
                missingPrerequisites.push(prereq);
            }
        }
        if (missingPrerequisites.length > 0) {
            return {
                passed: false,
                missingPrerequisites,
                message: `Lifecycle gate failed: missing prerequisites [${missingPrerequisites.join(', ')}]`,
            };
        }
        return {
            passed: true,
            missingPrerequisites: [],
            message: 'All prerequisites met',
        };
    }
    /**
     * Record a protocol violation
     */
    recordViolation(protocol, violations, score, taskId) {
        const entry = {
            timestamp: new Date().toISOString(),
            taskId,
            protocol,
            violations,
            score,
            blocked: this.strictMode && violations.some((v) => v.severity === 'error'),
        };
        this.violations.push(entry);
        // Keep last 1000 violations
        if (this.violations.length > 1000) {
            this.violations.shift();
        }
    }
    /**
     * Get recent violations
     */
    getViolations(limit) {
        return limit ? this.violations.slice(-limit) : this.violations;
    }
    /**
     * Calculate penalty for violation severity
     */
    calculatePenalty(severity) {
        return severity === 'error' ? 20 : 5;
    }
    /**
     * Middleware function for domain router
     *
     * Intercepts operations and validates protocol compliance before execution.
     */
    async enforceProtocol(request, next) {
        // Only enforce on mutate operations that may create outputs
        if (request.gateway !== 'mutate') {
            return next();
        }
        // Check if operation requires protocol validation
        const requiresValidation = this.requiresProtocolValidation(request);
        if (!requiresValidation) {
            return next();
        }
        // Execute the operation
        const response = await next();
        // Skip validation if operation failed
        if (!response.success) {
            return response;
        }
        // Extract protocol type from request/response
        const protocol = this.detectProtocol(request, response);
        if (!protocol) {
            return response;
        }
        // Validate protocol compliance
        const manifestEntry = this.extractManifestEntry(response);
        if (!manifestEntry) {
            return response; // No manifest to validate
        }
        const result = await this.validateProtocol(protocol, manifestEntry, request.params);
        // Record violation
        const taskId = request.params?.taskId;
        this.recordViolation(protocol, result.violations, result.score, taskId);
        // If strict mode and errors found, block the operation
        if (this.strictMode && !result.valid) {
            return {
                _meta: response._meta,
                success: false,
                error: {
                    code: `E_PROTOCOL_${protocol.toUpperCase()}`,
                    exitCode: PROTOCOL_EXIT_CODES[protocol],
                    message: `Protocol violation: ${protocol}`,
                    details: {
                        violations: result.violations,
                        score: result.score,
                    },
                    fix: result.violations[0]?.fix || 'Fix protocol violations',
                    alternatives: result.violations.map((v) => ({
                        action: v.requirement,
                        command: v.fix,
                    })),
                },
            };
        }
        return response;
    }
    /**
     * Determine if operation requires protocol validation
     */
    requiresProtocolValidation(request) {
        // Operations that create outputs requiring validation
        const validatedOperations = [
            'session.context.inject',
            'pipeline.manifest.append',
            'orchestrate.spawn',
            'tasks.complete',
            'release.ship',
            'validate.compliance.record',
        ];
        const key = `${request.domain}.${request.operation}`;
        return validatedOperations.includes(key);
    }
    /**
     * Detect protocol type from request/response
     */
    detectProtocol(request, _response) {
        // Check params for explicit protocol
        if (request.params?.protocolType) {
            return request.params.protocolType;
        }
        // Infer from domain
        const domainProtocolMap = {
            research: ProtocolType.RESEARCH,
            orchestrate: ProtocolType.DECOMPOSITION,
            release: ProtocolType.RELEASE,
            validate: ProtocolType.VALIDATION,
            testing: ProtocolType.TESTING,
            contribution: ProtocolType.CONTRIBUTION,
        };
        // Infer from operation name
        if (request.operation) {
            const opProtocolMap = {
                'consensus.record': ProtocolType.CONSENSUS,
                'specification.validate': ProtocolType.SPECIFICATION,
                'implementation.complete': ProtocolType.IMPLEMENTATION,
                'contribution.merge': ProtocolType.CONTRIBUTION,
            };
            const opKey = `${request.domain}.${request.operation}`;
            if (opProtocolMap[opKey]) {
                return opProtocolMap[opKey];
            }
        }
        return domainProtocolMap[request.domain] || null;
    }
    /**
     * Extract manifest entry from response
     */
    extractManifestEntry(response) {
        const data = response.data;
        if (!data) {
            return null;
        }
        // Check for manifest entry in response
        if (data.manifestEntry) {
            return data.manifestEntry;
        }
        // Check for entry field
        if (data.entry) {
            return data.entry;
        }
        return null;
    }
    /**
     * Set strict mode
     */
    setStrictMode(strict) {
        this.strictMode = strict;
    }
    /**
     * Get strict mode status
     */
    isStrictMode() {
        return this.strictMode;
    }
}
/**
 * Default protocol enforcer instance
 */
export const protocolEnforcer = new ProtocolEnforcer();
//# sourceMappingURL=protocol-enforcement.js.map