blax
Version:
Blax - HMS-Powered Multi-Agent Platform with Government Agency Analysis, Deep Research, and Enterprise-Ready Deployment. No local LLM keys required.
521 lines • 22.2 kB
JavaScript
import { EventEmitter } from 'events';
/**
* Deal Evaluator for agent decision-making
* Implements value delta calculation and metrics assessment
*/
export class DealEvaluator extends EventEmitter {
dealRegistry;
config;
evaluationCache = new Map();
constructor(dealRegistry, config) {
super();
this.dealRegistry = dealRegistry;
this.config = {
riskAversion: config?.riskAversion ?? 0.3,
timeDiscountRate: config?.timeDiscountRate ?? 0.05,
qualityWeight: config?.qualityWeight ?? 0.4,
complianceWeight: config?.complianceWeight ?? 0.3,
stakeholderSatisfactionWeight: config?.stakeholderSatisfactionWeight ?? 0.3,
...config
};
}
/**
* Evaluate an action's impact on a deal
* Returns YES/NO recommendation based on value delta
*/
async evaluateDeal(dealId, actionContext) {
const startTime = Date.now();
try {
const deal = await this.dealRegistry.getDeal(dealId);
if (!deal) {
throw new Error(`Deal ${dealId} not found`);
}
// Calculate current expected value
const expectedValueBefore = this.calculateExpectedValue(deal);
// Simulate action impact
const expectedValueAfter = await this.simulateActionImpact(deal, actionContext);
const valueDelta = expectedValueAfter - expectedValueBefore;
// Assess metrics impact
const metricsImpact = this.assessMetricsImpact(deal, actionContext);
// Calculate risk score
const riskAssessment = this.assessRisk(deal, actionContext);
// Evaluate compliance impact
const complianceImpact = this.evaluateComplianceImpact(deal, actionContext);
// Generate recommendation
const recommendation = this.generateRecommendation(valueDelta, riskAssessment.riskScore, metricsImpact, complianceImpact);
const evaluation = {
dealId,
actionId: actionContext.actionId,
agentId: actionContext.agentId,
expectedValueBefore,
expectedValueAfter,
valueDelta,
valueConfidence: this.calculateValueConfidence(deal, actionContext),
metricsImpact,
riskScore: riskAssessment.riskScore,
riskFactors: riskAssessment.riskFactors,
complianceImpact,
recommendation: recommendation.decision,
confidence: recommendation.confidence,
reasoning: recommendation.reasoning,
suggestedModifications: recommendation.modifications,
evaluatedAt: new Date(),
evaluationDuration: Date.now() - startTime,
evaluationMethod: 'value_delta_analysis',
dataSourcesUsed: ['deal_metrics', 'risk_model', 'compliance_rules'],
assumptionsMade: this.getAssumptions(deal, actionContext)
};
// Cache the evaluation
this.evaluationCache.set(`${dealId}_${actionContext.actionId}`, evaluation);
this.emit('dealEvaluated', evaluation);
return evaluation;
}
catch (error) {
this.emit('evaluationError', { dealId, actionContext, error });
throw error;
}
}
/**
* Calculate the current expected value of a deal
*/
calculateExpectedValue(deal) {
let baseValue = deal.financing.totalBudget;
// Adjust for progress
const progressMultiplier = 1 + (deal.progress * 0.2); // 20% bonus for progress
baseValue *= progressMultiplier;
// Adjust for quality metrics
const qualityScore = this.calculateQualityScore(deal);
const qualityAdjustment = (qualityScore - 0.5) * this.config.qualityWeight;
baseValue *= (1 + qualityAdjustment);
// Adjust for compliance
const complianceScore = this.calculateComplianceScore(deal);
const complianceAdjustment = (complianceScore - 0.5) * this.config.complianceWeight;
baseValue *= (1 + complianceAdjustment);
// Adjust for stakeholder satisfaction
const stakeholderScore = this.calculateStakeholderSatisfaction(deal);
const stakeholderAdjustment = (stakeholderScore - 0.5) * this.config.stakeholderSatisfactionWeight;
baseValue *= (1 + stakeholderAdjustment);
// Apply risk discount
const riskScore = this.calculateRiskScore(deal);
const riskDiscount = riskScore * this.config.riskAversion;
baseValue *= (1 - riskDiscount);
// Apply time discount if deadline is set
if (deal.deadline) {
const timeToDeadline = (deal.deadline.getTime() - Date.now()) / (1000 * 60 * 60 * 24 * 365);
const timeDiscount = Math.pow(1 + this.config.timeDiscountRate, timeToDeadline);
baseValue /= timeDiscount;
}
return Math.max(0, baseValue);
}
/**
* Simulate the impact of an action on deal value
*/
async simulateActionImpact(deal, actionContext) {
// Create a simulation copy of the deal
const simulatedDeal = { ...deal };
// Apply action effects
simulatedDeal.progress = Math.min(1.0, simulatedDeal.progress + (actionContext.estimatedDuration / 100));
// Adjust metrics based on action type
const metricsAdjustment = this.simulateMetricsImpact(deal, actionContext);
// Adjust for action-specific risks
const actionRiskAdjustment = actionContext.riskLevel * 0.1; // 10% max negative impact
// Calculate new expected value
const baseValue = this.calculateExpectedValue(simulatedDeal);
const adjustedValue = baseValue * (1 + metricsAdjustment - actionRiskAdjustment);
return Math.max(0, adjustedValue);
}
/**
* Assess the impact of an action on deal metrics
*/
assessMetricsImpact(deal, actionContext) {
return deal.metrics.map(metric => {
const impact = this.calculateMetricImpact(metric, actionContext);
return {
metricId: metric.metricId,
currentValue: metric.currentValue,
projectedValue: metric.currentValue + impact.deltaValue,
improvement: impact.deltaValue,
attainabilityChange: impact.attainabilityChange
};
});
}
/**
* Calculate the impact of an action on a specific metric
*/
calculateMetricImpact(metric, actionContext) {
let deltaValue = 0;
let attainabilityChange = 0;
// Base impact based on action type and metric type
const typeCompatibility = this.getActionMetricCompatibility(actionContext.actionType, metric.type);
deltaValue = typeCompatibility * actionContext.confidence * 10; // Scaled impact
// Adjust for resource investment
const resourceFactor = Math.min(1.0, actionContext.resourceCost / 1000); // Normalize
deltaValue *= (1 + resourceFactor * 0.5);
// Adjust for risk
deltaValue *= (1 - actionContext.riskLevel * 0.3);
// Calculate attainability change
if (!metric.attainable && deltaValue > 0) {
attainabilityChange = 0.2; // Positive action might make unattainable metrics achievable
}
return { deltaValue, attainabilityChange };
}
/**
* Assess risk factors for the action
*/
assessRisk(deal, actionContext) {
const riskFactors = [];
// Base action risk
riskFactors.push({
factor: 'Action inherent risk',
probability: actionContext.riskLevel,
impact: 0.3,
mitigation: 'Proper testing and validation'
});
// Complexity risk
if (actionContext.dependencies.length > 3) {
riskFactors.push({
factor: 'High dependency complexity',
probability: 0.4,
impact: 0.5,
mitigation: 'Dependency mapping and contingency planning'
});
}
// Resource risk
const resourceRisk = Math.min(1.0, actionContext.resourceCost / deal.financing.totalBudget);
if (resourceRisk > 0.2) {
riskFactors.push({
factor: 'High resource consumption',
probability: resourceRisk,
impact: 0.4,
mitigation: 'Budget monitoring and resource optimization'
});
}
// Timeline risk
if (deal.deadline) {
const timeRemaining = (deal.deadline.getTime() - Date.now()) / (1000 * 60 * 60);
const timeRisk = Math.max(0, (actionContext.estimatedDuration - timeRemaining) / timeRemaining);
if (timeRisk > 0.1) {
riskFactors.push({
factor: 'Timeline pressure',
probability: Math.min(1.0, timeRisk),
impact: 0.6,
mitigation: 'Scope adjustment or deadline extension'
});
}
}
// Calculate overall risk score
const riskScore = riskFactors.reduce((total, risk) => {
return total + (risk.probability * risk.impact);
}, 0) / riskFactors.length;
return { riskScore: Math.min(1.0, riskScore), riskFactors };
}
/**
* Evaluate compliance impact
*/
evaluateComplianceImpact(deal, actionContext) {
const impact = {};
for (const standard of deal.requiredStandards) {
if (actionContext.standards.includes(standard)) {
impact[standard] = 'positive';
}
else if (this.hasComplianceRisk(standard, actionContext)) {
impact[standard] = 'negative';
}
else {
impact[standard] = 'neutral';
}
}
return impact;
}
/**
* Generate recommendation based on analysis
*/
generateRecommendation(valueDelta, riskScore, metricsImpact, complianceImpact) {
const modifications = [];
let reasoning = '';
// Primary decision based on value delta
const primaryDecision = valueDelta > 0 ? 'approve' : 'reject';
// Check for red flags
const hasNegativeCompliance = Object.values(complianceImpact).includes('negative');
const highRisk = riskScore > 0.7;
const negativeMetrics = metricsImpact.filter(m => m.improvement < 0).length > metricsImpact.length / 2;
// Decision logic
if (hasNegativeCompliance) {
reasoning += 'Negative compliance impact detected. ';
modifications.push('Address compliance concerns before proceeding');
if (valueDelta > 100) { // High value might justify some compliance risks
return {
decision: 'modify',
confidence: 0.6,
reasoning: reasoning + 'High value potential but requires compliance modifications.',
modifications
};
}
else {
return {
decision: 'reject',
confidence: 0.8,
reasoning: reasoning + 'Compliance risks outweigh value benefits.',
modifications
};
}
}
if (highRisk) {
reasoning += `High risk score (${(riskScore * 100).toFixed(1)}%). `;
modifications.push('Implement additional risk mitigation measures');
if (valueDelta > 200) { // Very high value might justify high risk
return {
decision: 'modify',
confidence: 0.7,
reasoning: reasoning + 'High value potential justifies modified approach with risk mitigation.',
modifications
};
}
else if (valueDelta > 0) {
return {
decision: 'escalate',
confidence: 0.6,
reasoning: reasoning + 'Risk-value tradeoff requires human judgment.',
modifications
};
}
else {
return {
decision: 'reject',
confidence: 0.9,
reasoning: reasoning + 'High risk with negative value delta.',
modifications
};
}
}
if (negativeMetrics) {
reasoning += 'Majority of metrics show negative impact. ';
modifications.push('Review and optimize metrics impact');
if (valueDelta > 50) {
return {
decision: 'modify',
confidence: 0.6,
reasoning: reasoning + 'Value positive but metrics need optimization.',
modifications
};
}
}
// Standard decisions
if (valueDelta > 100) {
return {
decision: 'approve',
confidence: 0.9,
reasoning: `Strong positive value delta (${valueDelta.toFixed(2)}). Low risk and positive metrics impact.`,
modifications
};
}
else if (valueDelta > 0) {
return {
decision: 'approve',
confidence: 0.7,
reasoning: `Positive value delta (${valueDelta.toFixed(2)}). Acceptable risk level.`,
modifications
};
}
else if (valueDelta > -50) {
return {
decision: 'escalate',
confidence: 0.5,
reasoning: `Small negative value delta (${valueDelta.toFixed(2)}). Requires human judgment for intangible benefits.`,
modifications
};
}
else {
return {
decision: 'reject',
confidence: 0.8,
reasoning: `Significant negative value delta (${valueDelta.toFixed(2)}).`,
modifications
};
}
}
// Helper methods
calculateQualityScore(deal) {
const qualityMetrics = deal.metrics.filter(m => m.type === 'quality');
if (qualityMetrics.length === 0)
return 0.5;
const avgQuality = qualityMetrics.reduce((sum, m) => sum + (m.currentValue / m.targetValue), 0) / qualityMetrics.length;
return Math.min(1.0, Math.max(0.0, avgQuality));
}
calculateComplianceScore(deal) {
if (deal.requiredStandards.length === 0)
return 1.0;
const compliantCount = Object.values(deal.complianceStatus).filter(s => s === 'compliant').length;
return compliantCount / deal.requiredStandards.length;
}
calculateStakeholderSatisfaction(deal) {
// In a full implementation, this would aggregate actual stakeholder feedback
// For now, return a default value based on progress
return 0.5 + (deal.progress * 0.3);
}
calculateRiskScore(deal) {
if (deal.proposedSolutions.length === 0)
return 0.5;
let totalRisk = 0;
let riskCount = 0;
for (const solution of deal.proposedSolutions) {
for (const risk of solution.risks) {
totalRisk += risk.probability * risk.impact;
riskCount++;
}
}
return riskCount > 0 ? totalRisk / riskCount : 0.2;
}
calculateValueConfidence(deal, actionContext) {
let confidence = actionContext.confidence;
// Reduce confidence for complex deals
if (deal.proposedSolutions.length > 3) {
confidence *= 0.9;
}
// Reduce confidence for high-risk actions
confidence *= (1 - actionContext.riskLevel * 0.3);
// Increase confidence for well-defined metrics
const measurableMetrics = deal.metrics.filter(m => m.measurable).length;
if (measurableMetrics > 0) {
confidence *= (1 + (measurableMetrics / deal.metrics.length) * 0.2);
}
return Math.min(1.0, Math.max(0.1, confidence));
}
simulateMetricsImpact(deal, actionContext) {
if (deal.metrics.length === 0)
return 0;
const totalImpact = deal.metrics.reduce((sum, metric) => {
const impact = this.calculateMetricImpact(metric, actionContext);
return sum + (impact.deltaValue / metric.targetValue);
}, 0);
return totalImpact / deal.metrics.length;
}
getActionMetricCompatibility(actionType, metricType) {
// Define compatibility matrix
const compatibility = {
'implementation': { 'operational': 0.8, 'quality': 0.6, 'financial': 0.3, 'time': 0.7, 'compliance': 0.4 },
'testing': { 'quality': 0.9, 'compliance': 0.7, 'operational': 0.5, 'financial': 0.2, 'time': -0.2 },
'optimization': { 'operational': 0.9, 'financial': 0.6, 'quality': 0.5, 'time': 0.4, 'compliance': 0.3 },
'documentation': { 'compliance': 0.8, 'quality': 0.4, 'operational': 0.3, 'financial': 0.1, 'time': -0.1 },
'deployment': { 'operational': 0.7, 'time': 0.8, 'financial': 0.4, 'quality': 0.2, 'compliance': 0.5 }
};
return compatibility[actionType]?.[metricType] ?? 0.5;
}
hasComplianceRisk(standard, actionContext) {
// In a full implementation, this would check specific compliance rules
// For now, return true if action doesn't explicitly support the standard
return !actionContext.standards.includes(standard) && actionContext.riskLevel > 0.5;
}
getAssumptions(deal, actionContext) {
const assumptions = [
'Linear relationship between effort and progress',
'Stakeholder requirements remain stable',
'No external market changes during execution'
];
if (deal.deadline) {
assumptions.push('Deadline is fixed and non-negotiable');
}
if (actionContext.dependencies.length > 0) {
assumptions.push('All dependencies will be resolved as planned');
}
return assumptions;
}
/**
* Generate financial provenance for audit trail
*/
async generateFinancialProvenance(dealId, actionContext) {
const deal = await this.dealRegistry.getDeal(dealId);
if (!deal) {
throw new Error(`Deal ${dealId} not found`);
}
const traceId = `trace_${dealId}_${actionContext.actionId}_${Date.now()}`;
return {
dealId,
actionId: actionContext.actionId,
traceId,
costBreakdown: {
directCosts: actionContext.resourceCost,
indirectCosts: actionContext.resourceCost * 0.2,
opportunityCosts: this.calculateOpportunityCost(deal, actionContext),
riskCosts: actionContext.riskLevel * actionContext.resourceCost * 0.1
},
valueChain: this.generateValueChain(deal, actionContext),
calculations: [
{
formula: 'expectedValue = baseValue * progressMultiplier * qualityAdjustment * complianceAdjustment',
inputs: {
baseValue: deal.financing.totalBudget,
progressMultiplier: 1 + (deal.progress * 0.2),
qualityAdjustment: this.calculateQualityScore(deal),
complianceAdjustment: this.calculateComplianceScore(deal)
},
output: this.calculateExpectedValue(deal),
timestamp: new Date()
}
],
validationRules: [
'Value delta must be calculated consistently',
'Risk assessment must include all identified factors',
'Compliance impact must be evaluated for all required standards'
],
validationResults: [
{ rule: 'Value delta calculation', passed: true },
{ rule: 'Risk factor completeness', passed: true },
{ rule: 'Compliance coverage', passed: true }
]
};
}
calculateOpportunityCost(deal, actionContext) {
// Simplified opportunity cost calculation
const timeValue = (actionContext.estimatedDuration / 40) * 1000; // $1000 per week
const resourceOpportunity = actionContext.resourceCost * 0.1; // 10% opportunity cost
return timeValue + resourceOpportunity;
}
generateValueChain(deal, actionContext) {
return [
{
step: 'Action execution',
valueContribution: actionContext.resourceCost * 1.5,
confidence: actionContext.confidence,
dependencies: actionContext.dependencies
},
{
step: 'Metrics improvement',
valueContribution: deal.metrics.length * 100,
confidence: 0.7,
dependencies: ['successful_execution']
},
{
step: 'Stakeholder satisfaction',
valueContribution: deal.stakeholders.length * 50,
confidence: 0.6,
dependencies: ['metrics_improvement']
}
];
}
/**
* Get cached evaluation
*/
getCachedEvaluation(dealId, actionId) {
return this.evaluationCache.get(`${dealId}_${actionId}`) || null;
}
/**
* Clear evaluation cache
*/
clearCache() {
this.evaluationCache.clear();
}
/**
* Health check
*/
async healthCheck() {
return {
status: 'healthy',
details: {
cacheSize: this.evaluationCache.size,
config: this.config
}
};
}
}
//# sourceMappingURL=dealEvaluator.js.map