"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assessChangeRisk = assessChangeRisk;
const coreModuleIds = new Set(['config', 'policy', 'validation', 'security', 'compliance']);
function isCoreModuleTouched(changedModules) {
    if (!changedModules || changedModules.length === 0) {
        return undefined;
    }
    return changedModules.some((moduleId) => coreModuleIds.has(moduleId.toLowerCase()));
}
function assessChangeRisk(input) {
    const changedModules = [...(input.changedModules ?? [])].sort((left, right) => left.localeCompare(right));
    const directlyAffectedModules = [...(input.directlyAffectedModules ?? [])].sort((left, right) => left.localeCompare(right));
    const transitivelyAffectedModules = [...(input.transitivelyAffectedModules ?? [])].sort((left, right) => left.localeCompare(right));
    const touchedContracts = [...(input.touchedContracts ?? [])].sort((left, right) => left.localeCompare(right));
    const touchedPublicEntrypoints = [...(input.touchedPublicEntrypoints ?? [])].sort((left, right) => left.localeCompare(right));
    const touchedArchitectureArtifacts = [...(input.touchedArchitectureArtifacts ?? [])].sort((left, right) => left.localeCompare(right));
    const touchedAdrs = [...(input.touchedAdrs ?? [])].sort((left, right) => left.localeCompare(right));
    const changedModulesCount = changedModules.length > 0 ? changedModules.length : undefined;
    const directDependentsCount = directlyAffectedModules.length > 0 ? directlyAffectedModules.length : undefined;
    const transitiveDependentsCount = transitivelyAffectedModules.length > 0 ? transitivelyAffectedModules.length : undefined;
    const affectedDependentsCount = input.affectedDependentsCount ??
        (directDependentsCount ?? 0) + (transitiveDependentsCount ?? 0);
    const coreModuleTouched = isCoreModuleTouched(changedModules);
    const crossModuleContractViolations = input.crossModuleContractViolations ?? 0;
    const cycleViolations = input.cycleViolations ?? 0;
    const multiCategoryViolations = input.multiCategoryViolations ?? 0;
    const diffContextAvailable = input.diffContextAvailable ?? changedModules.length > 0;
    const factorCatalog = [
        {
            id: 'CRF-001',
            label: 'Multiple modules changed',
            description: 'Three or more modules changed in this diff scope.',
            weight: 10,
            category: 'scope',
        },
        {
            id: 'CRF-002',
            label: 'Large direct dependents blast radius',
            description: 'Many modules directly depend on changed modules.',
            weight: 12,
            category: 'scope',
        },
        {
            id: 'CRF-003',
            label: 'Transitive dependents impacted',
            description: 'Transitive dependent modules are impacted by changed scope.',
            weight: 12,
            category: 'scope',
        },
        {
            id: 'CRF-004',
            label: 'Public entrypoint touched',
            description: 'Changed files include module public entrypoints.',
            weight: 8,
            category: 'contracts',
        },
        {
            id: 'CRF-005',
            label: 'Module contract touched',
            description: 'Changed files include module contract files.',
            weight: 10,
            category: 'contracts',
        },
        {
            id: 'CRF-006',
            label: 'Architecture artifact touched',
            description: 'Changed files include architecture governance artifacts.',
            weight: 8,
            category: 'architecture-artifacts',
        },
        {
            id: 'CRF-007',
            label: 'ADR touched',
            description: 'Changed files include ADR documents.',
            weight: 5,
            category: 'governance',
        },
        {
            id: 'CRF-008',
            label: 'Cross-module dependency violations',
            description: 'Validation found cross-module dependency violations.',
            weight: 18,
            category: 'violations',
        },
        {
            id: 'CRF-009',
            label: 'Cross-module contract violations',
            description: 'Validation found cross-module contract boundary violations.',
            weight: 16,
            category: 'violations',
        },
        {
            id: 'CRF-010',
            label: 'Dependency cycle violations',
            description: 'Validation found circular or transitive cycle violations.',
            weight: 20,
            category: 'dependencies',
        },
        {
            id: 'CRF-011',
            label: 'Multi-category architecture impact',
            description: 'Findings span multiple architecture categories.',
            weight: 10,
            category: 'violations',
        },
        {
            id: 'CRF-012',
            label: 'Foundational module touched',
            description: 'Changed scope includes foundational/shared modules.',
            weight: 12,
            category: 'scope',
        },
        {
            id: 'CRF-013',
            label: 'Validation errors present',
            description: 'Error-level validation findings are present.',
            weight: 24,
            category: 'violations',
        },
        {
            id: 'CRF-014',
            label: 'Validation warnings present',
            description: 'Warning-level validation findings are present.',
            weight: 8,
            category: 'violations',
        },
        {
            id: 'CRF-016',
            label: 'Warnings with moderate blast radius',
            description: 'Warning findings are present alongside multiple affected dependent modules.',
            weight: 14,
            category: 'scope',
        },
        {
            id: 'CRF-015',
            label: 'Full validation mode (no scoped diff provided)',
            description: 'No scoped diff was provided; risk uses full validation context.',
            weight: 2,
            category: 'scope',
        },
    ];
    const factorsById = new Map(factorCatalog.map((factor) => [factor.id, factor]));
    const triggeredFactors = [];
    const trigger = (factorId, evidence) => {
        const factor = factorsById.get(factorId);
        if (!factor) {
            return;
        }
        triggeredFactors.push({
            ...factor,
            evidence,
        });
    };
    if ((changedModulesCount ?? 0) >= 3) {
        trigger('CRF-001', `changedModules=${changedModulesCount}`);
    }
    if ((directDependentsCount ?? 0) >= 3) {
        trigger('CRF-002', `directDependents=${directDependentsCount}`);
    }
    if ((transitiveDependentsCount ?? 0) >= 2) {
        trigger('CRF-003', `transitiveDependents=${transitiveDependentsCount}`);
    }
    if (touchedPublicEntrypoints.length > 0) {
        trigger('CRF-004', `touchedPublicEntrypoints=${touchedPublicEntrypoints.length}`);
    }
    if (touchedContracts.length > 0) {
        trigger('CRF-005', `touchedContracts=${touchedContracts.length}`);
    }
    if (touchedArchitectureArtifacts.length > 0) {
        trigger('CRF-006', `touchedArchitectureArtifacts=${touchedArchitectureArtifacts.length}`);
    }
    if (touchedAdrs.length > 0) {
        trigger('CRF-007', `touchedAdrs=${touchedAdrs.length}`);
    }
    if (input.crossModuleDependencyViolations > 0) {
        trigger('CRF-008', `crossModuleDependencyViolations=${input.crossModuleDependencyViolations}`);
    }
    if (crossModuleContractViolations > 0) {
        trigger('CRF-009', `crossModuleContractViolations=${crossModuleContractViolations}`);
    }
    if (cycleViolations > 0) {
        trigger('CRF-010', `cycleViolations=${cycleViolations}`);
    }
    if (multiCategoryViolations >= 2) {
        trigger('CRF-011', `multiCategoryViolations=${multiCategoryViolations}`);
    }
    if (coreModuleTouched === true) {
        trigger('CRF-012', 'foundational module changed');
    }
    if (input.errorCount > 0) {
        trigger('CRF-013', `errorCount=${input.errorCount}`);
    }
    if (input.warningCount > 0) {
        trigger('CRF-014', `warningCount=${input.warningCount}`);
    }
    if (input.warningCount > 0 && (affectedDependentsCount ?? 0) >= 3) {
        trigger('CRF-016', `warningCount=${input.warningCount}, affectedDependents=${affectedDependentsCount}`);
    }
    if (!diffContextAvailable) {
        trigger('CRF-015', 'no scoped diff was provided; full validation context used');
    }
    const signals = {
        ...(changedModulesCount !== undefined ? { changedModulesCount } : {}),
        ...(affectedDependentsCount !== undefined ? { affectedDependentsCount } : {}),
        ...(directDependentsCount !== undefined ? { directDependentsCount } : {}),
        ...(transitiveDependentsCount !== undefined ? { transitiveDependentsCount } : {}),
        errorCount: input.errorCount,
        warningCount: input.warningCount,
        crossModuleDependencyViolations: input.crossModuleDependencyViolations,
        crossModuleContractViolations,
        cycleViolations,
        multiCategoryViolations,
        touchedContractsCount: touchedContracts.length,
        touchedPublicEntrypointsCount: touchedPublicEntrypoints.length,
        touchedArchitectureArtifactsCount: touchedArchitectureArtifacts.length,
        touchedAdrsCount: touchedAdrs.length,
        ...(coreModuleTouched !== undefined ? { coreModuleTouched } : {}),
        diffContextAvailable,
    };
    const score = Math.min(100, triggeredFactors.reduce((accumulator, factor) => accumulator + factor.weight, 0));
    const riskLevel = score >= 45 ? 'high' : score >= 20 ? 'medium' : 'low';
    const reasons = triggeredFactors.length > 0
        ? triggeredFactors
            .map((factor) => factor.label)
            .sort((left, right) => left.localeCompare(right))
        : ['No high-risk architecture signals detected'];
    const summary = riskLevel === 'high'
        ? 'High blast radius or boundary-risk signals detected.'
        : riskLevel === 'medium'
            ? 'Moderate architectural blast-radius signals detected.'
            : 'No significant architecture blast-radius signals detected.';
    return {
        riskLevel,
        level: riskLevel,
        score,
        scoreImpact: score,
        summary,
        reasons,
        factors: [...triggeredFactors].sort((left, right) => left.id.localeCompare(right.id)),
        changedModules,
        directlyAffectedModules,
        transitivelyAffectedModules,
        touchedContracts,
        touchedPublicEntrypoints,
        touchedArchitectureArtifacts,
        touchedAdrs,
        signals,
    };
}
//# sourceMappingURL=changeRiskAssessment.js.map