/
home
/
techb158
/
trellopowerup.abdallabala.com
/
src
/
/home/techb158/trellopowerup.abdallabala.com/src
mkdir
upload
Name
Size
Mode
Actions
assessmentAnalytics.js
7144
0644
edit
dl
rm
riskEngine.js
5756
0644
edit
dl
rm
server.js
7079
0644
edit
dl
rm
store.js
3545
0644
edit
dl
rm
Edit:
/home/techb158/trellopowerup.abdallabala.com/src/riskEngine.js
(5756B)
const DIMENSION_WEIGHTS = { organizational: 0.34, technical: 0.43, human: 0.23 }; const LIFECYCLE_WEIGHTS = { needs_analysis: 1.0, data_preparation: 1.25, design: 1.1, model_development: 1.35, testing_evaluation: 1.3, deployment_monitoring: 1.4 }; const TYPOLOGY_WEIGHTS = { incremental: 0.85, disruptive: 1.25, applied_research: 1.2, ai_enabler: 1.05, citizen_led: 1.15 }; const MATURITY_DISCOUNT = { ad_hoc: 1.2, defined: 1.0, measured: 0.9, controlled: 0.8 }; function clamp(value, min, max) { const numeric = Number(value); if (Number.isNaN(numeric)) return min; return Math.max(min, Math.min(max, numeric)); } function normalizeItem(item) { const probability = clamp(item.probability ?? 3, 1, 5); const impact = clamp(item.impact ?? 3, 1, 5); const detectionDifficulty = clamp(item.detectionDifficulty ?? 3, 1, 5); const mitigationCompleteness = clamp(item.mitigationCompleteness ?? 0, 0, 100); const residualFactor = 1 - mitigationCompleteness / 100; return { id: item.id, title: item.title || 'Untitled risk', category: item.category || 'technical', dimension: item.dimension || 'technical', lifecyclePhase: item.lifecyclePhase || 'model_development', probability, impact, detectionDifficulty, mitigationCompleteness, owner: item.owner || null, dueDate: item.dueDate || null, mitigation: item.mitigation || '', approvalState: item.approvalState || 'draft', rawScore: probability * impact * detectionDifficulty, residualScore: probability * impact * detectionDifficulty * residualFactor }; } function statusFromScore(score) { if (score >= 55) return 'critical'; if (score >= 35) return 'high'; if (score >= 18) return 'medium'; return 'low'; } function approvalGateStatus({ status, approvalState, mitigationCompleteness, metrics = {} }) { const blocking = []; if (status === 'critical') blocking.push('Critical residual risk requires explicit approval.'); if (mitigationCompleteness < 60) blocking.push('Mitigation completeness is below 60%.'); if (!['approved', 'accepted'].includes(approvalState)) blocking.push('Risk is not approved or accepted.'); if (metrics.modelPerformanceScore !== undefined && Number(metrics.modelPerformanceScore) < 70) { blocking.push('Model performance score is below 70%.'); } if (metrics.dataReadinessScore !== undefined && Number(metrics.dataReadinessScore) < 70) { blocking.push('Data readiness score is below 70%.'); } if (metrics.ethicalReviewCompleted === false) blocking.push('Ethical review is not completed.'); if (metrics.legalReviewCompleted === false) blocking.push('Legal review is not completed.'); return { deploymentReady: blocking.length === 0, blockingReasons: blocking }; } export function scoreRiskAssessment(input = {}) { const projectTypology = input.projectTypology || 'ai_enabler'; const lifecyclePhase = input.lifecyclePhase || 'model_development'; const maturity = input.measurementMaturity || 'defined'; const metrics = input.metrics || {}; const items = Array.isArray(input.risks) ? input.risks.map(normalizeItem) : []; const dimensionTotals = { organizational: 0, technical: 0, human: 0 }; for (const item of items) { const dimension = dimensionTotals[item.dimension] !== undefined ? item.dimension : 'technical'; dimensionTotals[dimension] += item.residualScore; } const weightedDimensionScore = Object.entries(dimensionTotals).reduce((sum, [dimension, total]) => { return sum + total * (DIMENSION_WEIGHTS[dimension] || 0.33); }, 0); const lifecycleMultiplier = LIFECYCLE_WEIGHTS[lifecyclePhase] || 1; const typologyMultiplier = TYPOLOGY_WEIGHTS[projectTypology] || 1; const maturityMultiplier = MATURITY_DISCOUNT[maturity] || 1; const normalizedScore = Math.round( clamp(weightedDimensionScore * lifecycleMultiplier * typologyMultiplier * maturityMultiplier, 0, 100) ); const status = statusFromScore(normalizedScore); const averageMitigation = items.length ? Math.round(items.reduce((sum, item) => sum + item.mitigationCompleteness, 0) / items.length) : 0; const highestRisk = [...items].sort((a, b) => b.residualScore - a.residualScore)[0] || null; const approvalState = input.approvalState || 'draft'; const gate = approvalGateStatus({ status, approvalState, mitigationCompleteness: averageMitigation, metrics }); return { projectTypology, lifecyclePhase, measurementMaturity: maturity, score: normalizedScore, status, averageMitigationCompleteness: averageMitigation, dimensionTotals, highestRisk, gate, risks: items, interpretation: buildInterpretation(normalizedScore, status, gate) }; } function buildInterpretation(score, status, gate) { const base = `Residual AI project risk is ${status} with a normalized score of ${score}/100.`; if (gate.deploymentReady) { return `${base} Deployment gate can proceed if accountable stakeholders approve the record.`; } return `${base} Deployment gate is blocked by ${gate.blockingReasons.length} criterion or criteria.`; } export function getReferenceTaxonomy() { return { lifecyclePhases: Object.keys(LIFECYCLE_WEIGHTS), projectTypologies: Object.keys(TYPOLOGY_WEIGHTS), maturityLevels: Object.keys(MATURITY_DISCOUNT), dimensions: Object.keys(DIMENSION_WEIGHTS), categories: ['strategic_organizational', 'technical', 'legal_ethical'], gateCriteria: [ 'risk_status', 'mitigation_completeness', 'approval_state', 'model_performance_metrics', 'data_readiness', 'ethical_review', 'legal_review', 'deployment_readiness' ] }; }
Save
cmd:
run