strray-ai 1.7.2 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/hooks/post-commit +152 -55
- package/.opencode/hooks/post-commit.backup +110 -174
- package/.opencode/hooks/post-push +47 -64
- package/.opencode/hooks/post-push.backup +34 -38
- package/.opencode/strray/features.json +3 -3
- package/.opencode/strray/routing-mappings.json +90 -34
- package/AGENTS.md +7 -2
- package/dist/analytics/anonymization-engine.d.ts +108 -0
- package/dist/analytics/anonymization-engine.d.ts.map +1 -0
- package/dist/analytics/anonymization-engine.js +352 -0
- package/dist/analytics/anonymization-engine.js.map +1 -0
- package/dist/analytics/consent-manager.d.ts +94 -0
- package/dist/analytics/consent-manager.d.ts.map +1 -0
- package/dist/analytics/consent-manager.js +257 -0
- package/dist/analytics/consent-manager.js.map +1 -0
- package/dist/analytics/emerging-pattern-detector.d.ts +68 -0
- package/dist/analytics/emerging-pattern-detector.d.ts.map +1 -0
- package/dist/analytics/emerging-pattern-detector.js +250 -0
- package/dist/analytics/emerging-pattern-detector.js.map +1 -0
- package/dist/analytics/pattern-learning-engine.d.ts +81 -0
- package/dist/analytics/pattern-learning-engine.d.ts.map +1 -0
- package/dist/analytics/pattern-learning-engine.js +262 -0
- package/dist/analytics/pattern-learning-engine.js.map +1 -0
- package/dist/analytics/pattern-performance-tracker.d.ts +89 -0
- package/dist/analytics/pattern-performance-tracker.d.ts.map +1 -0
- package/dist/analytics/pattern-performance-tracker.js +289 -0
- package/dist/analytics/pattern-performance-tracker.js.map +1 -0
- package/dist/analytics/prompt-pattern-analyzer.d.ts +100 -0
- package/dist/analytics/prompt-pattern-analyzer.d.ts.map +1 -0
- package/dist/analytics/prompt-pattern-analyzer.js +372 -0
- package/dist/analytics/prompt-pattern-analyzer.js.map +1 -0
- package/dist/analytics/routing-performance-analyzer.d.ts +102 -0
- package/dist/analytics/routing-performance-analyzer.d.ts.map +1 -0
- package/dist/analytics/routing-performance-analyzer.js +342 -0
- package/dist/analytics/routing-performance-analyzer.js.map +1 -0
- package/dist/analytics/routing-refiner.d.ts +105 -0
- package/dist/analytics/routing-refiner.d.ts.map +1 -0
- package/dist/analytics/routing-refiner.js +381 -0
- package/dist/analytics/routing-refiner.js.map +1 -0
- package/dist/cli/commands/analytics-disable.d.ts +10 -0
- package/dist/cli/commands/analytics-disable.d.ts.map +1 -0
- package/dist/cli/commands/analytics-disable.js +73 -0
- package/dist/cli/commands/analytics-disable.js.map +1 -0
- package/dist/cli/commands/analytics-enable-action.d.ts +9 -0
- package/dist/cli/commands/analytics-enable-action.d.ts.map +1 -0
- package/dist/cli/commands/analytics-enable-action.js +83 -0
- package/dist/cli/commands/analytics-enable-action.js.map +1 -0
- package/dist/cli/commands/analytics-preview.d.ts +10 -0
- package/dist/cli/commands/analytics-preview.d.ts.map +1 -0
- package/dist/cli/commands/analytics-preview.js +107 -0
- package/dist/cli/commands/analytics-preview.js.map +1 -0
- package/dist/cli/commands/analytics-status.d.ts +10 -0
- package/dist/cli/commands/analytics-status.d.ts.map +1 -0
- package/dist/cli/commands/analytics-status.js +68 -0
- package/dist/cli/commands/analytics-status.js.map +1 -0
- package/dist/cli/index.js +6 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adaptive-kernel.d.ts +110 -0
- package/dist/core/adaptive-kernel.d.ts.map +1 -0
- package/dist/core/adaptive-kernel.js +193 -0
- package/dist/core/adaptive-kernel.js.map +1 -0
- package/dist/core/kernel-patterns.d.ts +105 -0
- package/dist/core/kernel-patterns.d.ts.map +1 -0
- package/dist/core/kernel-patterns.js +328 -0
- package/dist/core/kernel-patterns.js.map +1 -0
- package/dist/core/orchestrator.d.ts +1 -0
- package/dist/core/orchestrator.d.ts.map +1 -1
- package/dist/core/orchestrator.js +40 -11
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/delegation/agent-delegator.d.ts +1 -0
- package/dist/delegation/agent-delegator.d.ts.map +1 -1
- package/dist/delegation/agent-delegator.js +24 -2
- package/dist/delegation/agent-delegator.js.map +1 -1
- package/dist/delegation/task-skill-router.d.ts +269 -5
- package/dist/delegation/task-skill-router.d.ts.map +1 -1
- package/dist/delegation/task-skill-router.js +810 -23
- package/dist/delegation/task-skill-router.js.map +1 -1
- package/dist/postprocessor/PostProcessor.d.ts +10 -0
- package/dist/postprocessor/PostProcessor.d.ts.map +1 -1
- package/dist/postprocessor/PostProcessor.js +87 -17
- package/dist/postprocessor/PostProcessor.js.map +1 -1
- package/dist/processors/agents-md-validation-processor.d.ts +1 -0
- package/dist/processors/agents-md-validation-processor.d.ts.map +1 -1
- package/dist/processors/agents-md-validation-processor.js +34 -12
- package/dist/processors/agents-md-validation-processor.js.map +1 -1
- package/dist/processors/processor-manager.d.ts +7 -0
- package/dist/processors/processor-manager.d.ts.map +1 -1
- package/dist/processors/processor-manager.js +93 -0
- package/dist/processors/processor-manager.js.map +1 -1
- package/dist/processors/test-auto-creation-processor.d.ts.map +1 -1
- package/dist/processors/test-auto-creation-processor.js +52 -38
- package/dist/processors/test-auto-creation-processor.js.map +1 -1
- package/dist/scripts/analytics/daily-routing-analysis.d.ts +18 -0
- package/dist/scripts/analytics/daily-routing-analysis.d.ts.map +1 -0
- package/dist/scripts/analytics/daily-routing-analysis.js +268 -0
- package/dist/scripts/analytics/daily-routing-analysis.js.map +1 -0
- package/dist/scripts/analytics/index.d.ts +15 -0
- package/dist/scripts/analytics/index.d.ts.map +1 -0
- package/dist/scripts/analytics/index.js +17 -0
- package/dist/scripts/analytics/index.js.map +1 -0
- package/dist/scripts/test-p9.d.ts +15 -0
- package/dist/scripts/test-p9.d.ts.map +1 -0
- package/dist/scripts/test-p9.js +220 -0
- package/dist/scripts/test-p9.js.map +1 -0
- package/package.json +6 -2
- package/scripts/node/kernel-e2e-test.mjs +168 -0
- package/scripts/node/kernel-framework-test.mjs +127 -0
- package/scripts/node/kernel-live-test.mjs +147 -0
- package/scripts/node/kernel-real-framework-test.mjs +103 -0
- package/scripts/node/kernel-update.cjs +379 -0
- package/scripts/node/reflection-check.sh +245 -27
- package/scripts/node/test-simple-names-comprehensive.mjs +221 -0
- package/scripts/node/test-simple-names.mjs +39 -0
- package/dist/agents/documentation-writer.d.ts +0 -9
- package/dist/agents/documentation-writer.d.ts.map +0 -1
- package/dist/agents/documentation-writer.js +0 -85
- package/dist/agents/documentation-writer.js.map +0 -1
- package/dist/agents/explore.d.ts +0 -8
- package/dist/agents/explore.d.ts.map +0 -1
- package/dist/agents/explore.js +0 -55
- package/dist/agents/explore.js.map +0 -1
- package/dist/agents/librarian.d.ts +0 -3
- package/dist/agents/librarian.d.ts.map +0 -1
- package/dist/agents/librarian.js +0 -84
- package/dist/agents/librarian.js.map +0 -1
- package/dist/agents/marketing-expert.d.ts +0 -9
- package/dist/agents/marketing-expert.d.ts.map +0 -1
- package/dist/agents/marketing-expert.js +0 -112
- package/dist/agents/marketing-expert.js.map +0 -1
- package/dist/agents/oracle.d.ts +0 -8
- package/dist/agents/oracle.d.ts.map +0 -1
- package/dist/agents/oracle.js +0 -51
- package/dist/agents/oracle.js.map +0 -1
- package/dist/agents/seo-copywriter.d.ts +0 -10
- package/dist/agents/seo-copywriter.d.ts.map +0 -1
- package/dist/agents/seo-copywriter.js +0 -73
- package/dist/agents/seo-copywriter.js.map +0 -1
- package/dist/agents/seo-specialist.d.ts +0 -9
- package/dist/agents/seo-specialist.d.ts.map +0 -1
- package/dist/agents/seo-specialist.js +0 -54
- package/dist/agents/seo-specialist.js.map +0 -1
- package/dist/agents/test-architect.d.ts +0 -3
- package/dist/agents/test-architect.d.ts.map +0 -1
- package/dist/agents/test-architect.js +0 -96
- package/dist/agents/test-architect.js.map +0 -1
- package/dist/mcps/enhanced-orchestrator.server.d.ts +0 -14
- package/dist/mcps/enhanced-orchestrator.server.d.ts.map +0 -1
- package/dist/mcps/enhanced-orchestrator.server.js +0 -266
- package/dist/mcps/enhanced-orchestrator.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/analyzer.server.d.ts +0 -7
- package/dist/mcps/knowledge-skills/analyzer.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/analyzer.server.js +0 -282
- package/dist/mcps/knowledge-skills/analyzer.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/documentation-generation.server.d.ts +0 -48
- package/dist/mcps/knowledge-skills/documentation-generation.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/documentation-generation.server.js +0 -1238
- package/dist/mcps/knowledge-skills/documentation-generation.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/explore.server.d.ts +0 -21
- package/dist/mcps/knowledge-skills/explore.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/explore.server.js +0 -582
- package/dist/mcps/knowledge-skills/explore.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/marketing-expert.server.d.ts +0 -8
- package/dist/mcps/knowledge-skills/marketing-expert.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/marketing-expert.server.js +0 -356
- package/dist/mcps/knowledge-skills/marketing-expert.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/oracle.server.d.ts +0 -25
- package/dist/mcps/knowledge-skills/oracle.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/oracle.server.js +0 -569
- package/dist/mcps/knowledge-skills/oracle.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/seo-copywriter.server.d.ts +0 -8
- package/dist/mcps/knowledge-skills/seo-copywriter.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/seo-copywriter.server.js +0 -251
- package/dist/mcps/knowledge-skills/seo-copywriter.server.js.map +0 -1
- package/dist/mcps/knowledge-skills/seo-specialist.server.d.ts +0 -8
- package/dist/mcps/knowledge-skills/seo-specialist.server.d.ts.map +0 -1
- package/dist/mcps/knowledge-skills/seo-specialist.server.js +0 -211
- package/dist/mcps/knowledge-skills/seo-specialist.server.js.map +0 -1
- package/dist/mcps/librarian.server.d.ts +0 -17
- package/dist/mcps/librarian.server.d.ts.map +0 -1
- package/dist/mcps/librarian.server.js +0 -382
- package/dist/mcps/librarian.server.js.map +0 -1
- package/dist/optimization/performance-optimizer.d.ts +0 -179
- package/dist/optimization/performance-optimizer.d.ts.map +0 -1
- package/dist/optimization/performance-optimizer.js +0 -556
- package/dist/optimization/performance-optimizer.js.map +0 -1
- package/dist/utils/memory-pool.d.ts +0 -90
- package/dist/utils/memory-pool.d.ts.map +0 -1
- package/dist/utils/memory-pool.js +0 -245
- package/dist/utils/memory-pool.js.map +0 -1
|
@@ -9,8 +9,73 @@
|
|
|
9
9
|
* @since 2026-02-22
|
|
10
10
|
*/
|
|
11
11
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
12
|
+
import { getKernel } from "../core/kernel-patterns.js";
|
|
12
13
|
import * as fs from "fs";
|
|
13
14
|
import * as path from "path";
|
|
15
|
+
// Import analytics components
|
|
16
|
+
import { promptPatternAnalyzer } from "../analytics/prompt-pattern-analyzer.js";
|
|
17
|
+
import { routingPerformanceAnalyzer } from "../analytics/routing-performance-analyzer.js";
|
|
18
|
+
import { routingRefiner } from "../analytics/routing-refiner.js";
|
|
19
|
+
// Import P9 adaptive kernel components
|
|
20
|
+
import { getAdaptiveKernel } from "../core/adaptive-kernel.js";
|
|
21
|
+
import { patternPerformanceTracker } from "../analytics/pattern-performance-tracker.js";
|
|
22
|
+
// ===== SIMPLE NAME MAPPINGS =====
|
|
23
|
+
/**
|
|
24
|
+
* Simple name mappings for agents - user-friendly names with strategic [Function] + [Role] pattern
|
|
25
|
+
* Recommended by marketing strategist for optimal user understanding and brand consistency
|
|
26
|
+
*/
|
|
27
|
+
const AGENT_SIMPLE_NAMES = {
|
|
28
|
+
// Core Agents - Strategic Leadership
|
|
29
|
+
"enforcer": "Quality Guardian",
|
|
30
|
+
"orchestrator": "Task Orchestrator",
|
|
31
|
+
"architect": "Solution Designer",
|
|
32
|
+
// Specialized Agents - Technical Experts
|
|
33
|
+
"security-auditor": "Security Specialist",
|
|
34
|
+
"code-reviewer": "Quality Validator",
|
|
35
|
+
"refactorer": "Code Optimizer",
|
|
36
|
+
"testing-lead": "Quality Assurance Lead",
|
|
37
|
+
"bug-triage-specialist": "Error Resolver",
|
|
38
|
+
"researcher": "Code Researcher", // Changed from "Code Analyst" to avoid duplicate
|
|
39
|
+
// Strategy & Content - Business Value
|
|
40
|
+
"strategist": "Strategic Planner",
|
|
41
|
+
"seo-consultant": "Visibility Expert",
|
|
42
|
+
"content-creator": "Content Builder",
|
|
43
|
+
"growth-strategist": "Growth Strategist",
|
|
44
|
+
"tech-writer": "Documentation Expert",
|
|
45
|
+
// Technical Specialists - Implementation Experts
|
|
46
|
+
"log-monitor": "Log Analyst",
|
|
47
|
+
"multimodal-looker": "Visual Analyst",
|
|
48
|
+
"analyzer": "Data Analyst",
|
|
49
|
+
"code-analyzer": "Code Analyst", // Kept as "Code Analyst"
|
|
50
|
+
"database-engineer": "Database Specialist",
|
|
51
|
+
"devops-engineer": "Deployment Specialist",
|
|
52
|
+
"backend-engineer": "Backend Specialist",
|
|
53
|
+
"frontend-engineer": "Frontend Specialist",
|
|
54
|
+
"frontend-ui-ux-engineer": "UI/UX Designer",
|
|
55
|
+
"performance-engineer": "Performance Optimizer",
|
|
56
|
+
"mobile-developer": "App Developer",
|
|
57
|
+
// Legacy Aliases - Clear Migration Path
|
|
58
|
+
"librarian": "Research Analyst",
|
|
59
|
+
"seo-specialist": "SEO Expert",
|
|
60
|
+
"seo-copywriter": "Content Specialist",
|
|
61
|
+
"marketing-expert": "Growth Specialist",
|
|
62
|
+
"documentation-writer": "Documentation Writer",
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Get the simple/human-readable name for an agent
|
|
66
|
+
* @param agentName - The technical agent name (e.g., "strategist")
|
|
67
|
+
* @returns Human-readable name (e.g., "Planner")
|
|
68
|
+
*/
|
|
69
|
+
export function getAgentSimpleName(agentName) {
|
|
70
|
+
return AGENT_SIMPLE_NAMES[agentName] || agentName;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get all simple name mappings
|
|
74
|
+
* @returns Record of technical name -> simple name
|
|
75
|
+
*/
|
|
76
|
+
export function getAllSimpleNames() {
|
|
77
|
+
return { ...AGENT_SIMPLE_NAMES };
|
|
78
|
+
}
|
|
14
79
|
// ===== CONFIGURATION =====
|
|
15
80
|
const ROUTING_CONFIG = {
|
|
16
81
|
// Minimum confidence threshold - below this, escalate to LLM
|
|
@@ -27,15 +92,60 @@ const ROUTING_CONFIG = {
|
|
|
27
92
|
};
|
|
28
93
|
class RoutingOutcomeTracker {
|
|
29
94
|
outcomes = [];
|
|
30
|
-
|
|
95
|
+
promptData = [];
|
|
96
|
+
routingDecisions = [];
|
|
97
|
+
maxOutcomes = 5000; // Increased capacity for comprehensive analytics
|
|
98
|
+
maxPromptData = 10000;
|
|
99
|
+
maxDecisions = 10000;
|
|
100
|
+
// Enable/disable enhanced analytics
|
|
101
|
+
enhancedAnalyticsEnabled = process.env.ROUTING_ENHANCED_ANALYTICS !== "false";
|
|
102
|
+
/**
|
|
103
|
+
* Enhanced outcome recording with prompt data
|
|
104
|
+
*/
|
|
31
105
|
recordOutcome(outcome) {
|
|
32
106
|
if (!ROUTING_CONFIG.ENABLE_OUTCOME_TRACKING)
|
|
33
107
|
return;
|
|
34
|
-
|
|
35
|
-
|
|
108
|
+
const timestamp = new Date();
|
|
109
|
+
this.outcomes.push({ ...outcome, timestamp });
|
|
110
|
+
// Link to related prompt data if available
|
|
111
|
+
const relatedPromptData = this.promptData.find(p => p.taskId === outcome.taskId);
|
|
112
|
+
const promptAssign = relatedPromptData;
|
|
113
|
+
if (promptAssign && this.outcomes.length > 0) {
|
|
114
|
+
this.outcomes[this.outcomes.length - 1].promptData = promptAssign;
|
|
115
|
+
}
|
|
116
|
+
this.manageDataLimits();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Record prompt data point with template comparison
|
|
120
|
+
*/
|
|
121
|
+
recordPromptData(promptData) {
|
|
122
|
+
if (!this.enhancedAnalyticsEnabled)
|
|
123
|
+
return;
|
|
124
|
+
this.promptData.push(promptData);
|
|
125
|
+
this.manageDataLimits();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Record routing decision with alternatives and context
|
|
129
|
+
*/
|
|
130
|
+
recordRoutingDecision(decision) {
|
|
131
|
+
if (!ROUTING_CONFIG.ENABLE_OUTCOME_TRACKING)
|
|
132
|
+
return;
|
|
133
|
+
this.routingDecisions.push(decision);
|
|
134
|
+
this.manageDataLimits();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Data management: keep only recent data
|
|
138
|
+
*/
|
|
139
|
+
manageDataLimits() {
|
|
36
140
|
if (this.outcomes.length > this.maxOutcomes) {
|
|
37
141
|
this.outcomes = this.outcomes.slice(-this.maxOutcomes);
|
|
38
142
|
}
|
|
143
|
+
if (this.promptData.length > this.maxPromptData) {
|
|
144
|
+
this.promptData = this.promptData.slice(-this.maxPromptData);
|
|
145
|
+
}
|
|
146
|
+
if (this.routingDecisions.length > this.maxDecisions) {
|
|
147
|
+
this.routingDecisions = this.routingDecisions.slice(-this.maxDecisions);
|
|
148
|
+
}
|
|
39
149
|
}
|
|
40
150
|
getOutcomes(agent) {
|
|
41
151
|
if (agent) {
|
|
@@ -67,6 +177,34 @@ class RoutingOutcomeTracker {
|
|
|
67
177
|
successRate: data.total > 0 ? data.successes / data.total : 0,
|
|
68
178
|
}));
|
|
69
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Get prompt data analytics
|
|
182
|
+
*/
|
|
183
|
+
getPromptData() {
|
|
184
|
+
return this.promptData;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get routing decision analytics
|
|
188
|
+
*/
|
|
189
|
+
getRoutingDecisions() {
|
|
190
|
+
return this.routingDecisions;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Get template match rate
|
|
194
|
+
*/
|
|
195
|
+
getTemplateMatchRate() {
|
|
196
|
+
const templateMatches = this.promptData.filter(p => p.templatePrompt && p.templatePrompt.length > 0);
|
|
197
|
+
return this.promptData.length > 0 ? templateMatches.length / this.promptData.length : 0;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get average confidence score
|
|
201
|
+
*/
|
|
202
|
+
getAverageConfidence() {
|
|
203
|
+
if (this.promptData.length === 0)
|
|
204
|
+
return 0;
|
|
205
|
+
const totalConfidence = this.promptData.reduce((sum, p) => sum + p.confidence, 0);
|
|
206
|
+
return totalConfidence / this.promptData.length;
|
|
207
|
+
}
|
|
70
208
|
clear() {
|
|
71
209
|
this.outcomes = [];
|
|
72
210
|
}
|
|
@@ -80,7 +218,9 @@ function loadMappingsFromConfig() {
|
|
|
80
218
|
const configPath = path.resolve(process.cwd(), ROUTING_CONFIG.CONFIG_FILE_PATH);
|
|
81
219
|
if (fs.existsSync(configPath)) {
|
|
82
220
|
const content = fs.readFileSync(configPath, "utf-8");
|
|
83
|
-
|
|
221
|
+
const configMappings = JSON.parse(content);
|
|
222
|
+
// Return config mappings - they will be merged with DEFAULT_MAPPINGS in constructor
|
|
223
|
+
return configMappings;
|
|
84
224
|
}
|
|
85
225
|
}
|
|
86
226
|
catch (error) {
|
|
@@ -948,15 +1088,22 @@ const DEFAULT_MAPPINGS = [
|
|
|
948
1088
|
export class TaskSkillRouter {
|
|
949
1089
|
mappings;
|
|
950
1090
|
stateManager;
|
|
1091
|
+
kernel;
|
|
1092
|
+
adaptiveKernel = null;
|
|
1093
|
+
// P9: Enable adaptive pattern learning
|
|
1094
|
+
p9Enabled = process.env.P9_ENABLED !== "false";
|
|
951
1095
|
// In-memory cache for immediate access (persisted via stateManager)
|
|
952
1096
|
routingHistoryCache = new Map();
|
|
953
1097
|
constructor(stateManager) {
|
|
954
1098
|
// Try to load mappings from config file first
|
|
955
1099
|
const configMappings = loadMappingsFromConfig();
|
|
956
|
-
if (configMappings) {
|
|
957
|
-
|
|
1100
|
+
if (configMappings && configMappings.length > 0) {
|
|
1101
|
+
// MERGE: DEFAULT_MAPPINGS first (as base), then config mappings (to override)
|
|
1102
|
+
this.mappings = [...DEFAULT_MAPPINGS, ...configMappings];
|
|
958
1103
|
frameworkLogger.log("task-skill-router", "loaded-from-config", "info", {
|
|
959
1104
|
count: configMappings.length,
|
|
1105
|
+
defaultCount: DEFAULT_MAPPINGS.length,
|
|
1106
|
+
totalCount: this.mappings.length,
|
|
960
1107
|
source: ROUTING_CONFIG.CONFIG_FILE_PATH,
|
|
961
1108
|
});
|
|
962
1109
|
}
|
|
@@ -967,6 +1114,26 @@ export class TaskSkillRouter {
|
|
|
967
1114
|
this.stateManager = stateManager;
|
|
968
1115
|
this.loadHistory();
|
|
969
1116
|
}
|
|
1117
|
+
// Initialize P9 adaptive kernel if enabled
|
|
1118
|
+
if (this.p9Enabled) {
|
|
1119
|
+
try {
|
|
1120
|
+
this.adaptiveKernel = getAdaptiveKernel({
|
|
1121
|
+
enableP9Learning: true,
|
|
1122
|
+
learningIntervalMs: 300000, // 5 minutes
|
|
1123
|
+
autoApplyThreshold: 0.9
|
|
1124
|
+
});
|
|
1125
|
+
frameworkLogger.log("task-skill-router", "p9-initialized", "info", {
|
|
1126
|
+
p9Enabled: true
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
catch (error) {
|
|
1130
|
+
frameworkLogger.log("task-skill-router", "p9-init-failed", "info", {
|
|
1131
|
+
error: String(error)
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
// Initialize kernel instance for pattern-aware routing
|
|
1136
|
+
this.kernel = getKernel();
|
|
970
1137
|
}
|
|
971
1138
|
/**
|
|
972
1139
|
* Set state manager after construction
|
|
@@ -1033,34 +1200,74 @@ export class TaskSkillRouter {
|
|
|
1033
1200
|
};
|
|
1034
1201
|
}
|
|
1035
1202
|
/**
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1203
|
+
* Route a task to the appropriate agent and skill
|
|
1204
|
+
* Returns result with escalateToLlm flag when confidence is below threshold
|
|
1205
|
+
*
|
|
1206
|
+
* ENHANCED: Kernel patterns actively guide routing decisions
|
|
1207
|
+
*/
|
|
1039
1208
|
routeTask(taskDescription, options = {}) {
|
|
1040
1209
|
const { complexity, taskId, useHistoricalData = true } = options;
|
|
1041
1210
|
if (!taskDescription || typeof taskDescription !== "string") {
|
|
1042
1211
|
return this.getDefaultRouting("Invalid task description");
|
|
1043
1212
|
}
|
|
1044
1213
|
const descLower = taskDescription.toLowerCase();
|
|
1045
|
-
//
|
|
1046
|
-
const
|
|
1214
|
+
// KERNEL-FIRST APPROACH: Get kernel insights before routing
|
|
1215
|
+
const kernelInsights = this.kernel.analyze(taskDescription);
|
|
1216
|
+
// Apply P8 (Infrastructure Hardening) pattern detection FIRST
|
|
1217
|
+
if (kernelInsights.cascadePatterns?.some(p => p.id === 'P8')) {
|
|
1218
|
+
const p8Pattern = kernelInsights.cascadePatterns?.find(p => p.id === 'P8');
|
|
1219
|
+
if (p8Pattern) {
|
|
1220
|
+
frameworkLogger.log("task-skill-router", "kernel-guided-infrastructure", "info", {
|
|
1221
|
+
taskDescription: taskDescription.substring(0, 100),
|
|
1222
|
+
detectedPattern: p8Pattern.id,
|
|
1223
|
+
guidance: 'Handle infrastructure issues before routing',
|
|
1224
|
+
kernelAction: p8Pattern.fix,
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
// REAL-TIME ANALYTICS: Check if we have performance data for this task
|
|
1229
|
+
const analyticsBasedRouting = this.getAnalyticsBasedRouting(taskDescription, kernelInsights);
|
|
1230
|
+
if (analyticsBasedRouting && analyticsBasedRouting.confidence > ROUTING_CONFIG.MIN_CONFIDENCE_THRESHOLD) {
|
|
1231
|
+
frameworkLogger.log("task-skill-router", "analytics-guided-routing", "debug", {
|
|
1232
|
+
taskDescription: taskDescription.substring(0, 100),
|
|
1233
|
+
analyticsConfidence: analyticsBasedRouting.confidence,
|
|
1234
|
+
routingReason: analyticsBasedRouting.reason,
|
|
1235
|
+
}, options.sessionId);
|
|
1236
|
+
return {
|
|
1237
|
+
...analyticsBasedRouting,
|
|
1238
|
+
kernelInsights,
|
|
1239
|
+
escalateToLlm: analyticsBasedRouting.confidence < ROUTING_CONFIG.MIN_CONFIDENCE_THRESHOLD,
|
|
1240
|
+
analyticsGuided: true
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
// KERNEL-ENHANCED KEYWORD MATCHING: Use kernel insights to improve matching
|
|
1244
|
+
const keywordResult = this.matchByKeywordsWithKernel(descLower, kernelInsights);
|
|
1047
1245
|
if (keywordResult) {
|
|
1048
|
-
//
|
|
1049
|
-
const
|
|
1050
|
-
|
|
1051
|
-
frameworkLogger.log("task-skill-router", "keyword-matched", "debug", {
|
|
1246
|
+
// Combine keyword confidence with kernel confidence
|
|
1247
|
+
const combinedConfidence = this.combineConfidence(keywordResult.confidence, kernelInsights.confidence);
|
|
1248
|
+
frameworkLogger.log("task-skill-router", "kernel-enhanced-routing", "debug", {
|
|
1052
1249
|
taskDescription: taskDescription.substring(0, 100),
|
|
1053
1250
|
matchedKeyword: keywordResult.matchedKeyword,
|
|
1054
1251
|
agent: keywordResult.agent,
|
|
1055
1252
|
skill: keywordResult.skill,
|
|
1056
|
-
|
|
1057
|
-
|
|
1253
|
+
keywordConfidence: keywordResult.confidence,
|
|
1254
|
+
kernelConfidence: kernelInsights.confidence,
|
|
1255
|
+
combinedConfidence,
|
|
1256
|
+
alternatives: keywordResult.alternatives?.length || 0,
|
|
1058
1257
|
}, options.sessionId);
|
|
1059
|
-
//
|
|
1060
|
-
|
|
1061
|
-
|
|
1258
|
+
// Return kernel-enhanced routing with alternatives
|
|
1259
|
+
const result = {
|
|
1260
|
+
...keywordResult,
|
|
1261
|
+
confidence: combinedConfidence,
|
|
1262
|
+
kernelInsights,
|
|
1263
|
+
escalateToLlm: combinedConfidence < ROUTING_CONFIG.MIN_CONFIDENCE_THRESHOLD,
|
|
1264
|
+
kernelGuided: true,
|
|
1265
|
+
};
|
|
1266
|
+
// Only add alternatives if they exist (P2 compliance)
|
|
1267
|
+
if (keywordResult.alternatives !== undefined && keywordResult.alternatives.length > 0) {
|
|
1268
|
+
result.alternatives = keywordResult.alternatives;
|
|
1062
1269
|
}
|
|
1063
|
-
return
|
|
1270
|
+
return result;
|
|
1064
1271
|
}
|
|
1065
1272
|
// 2. Try historical data
|
|
1066
1273
|
if (useHistoricalData && taskId) {
|
|
@@ -1084,6 +1291,23 @@ export class TaskSkillRouter {
|
|
|
1084
1291
|
* Match task by keywords (ordered by specificity)
|
|
1085
1292
|
*/
|
|
1086
1293
|
matchByKeywords(descLower) {
|
|
1294
|
+
// First, check for direct @agent mentions and extract the agent name
|
|
1295
|
+
const atAgentMatch = descLower.match(/@(\w+)/);
|
|
1296
|
+
if (atAgentMatch && atAgentMatch[1]) {
|
|
1297
|
+
const agentName = atAgentMatch[1].toLowerCase();
|
|
1298
|
+
// Look for a mapping where the agent matches
|
|
1299
|
+
const agentMapping = this.mappings.find(m => m.agent?.toLowerCase() === agentName);
|
|
1300
|
+
if (agentMapping) {
|
|
1301
|
+
return {
|
|
1302
|
+
skill: agentMapping.skill,
|
|
1303
|
+
agent: agentMapping.agent,
|
|
1304
|
+
confidence: agentMapping.confidence,
|
|
1305
|
+
matchedKeyword: `@${agentName}`,
|
|
1306
|
+
reason: `Matched direct agent: @${agentName}`,
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
// Then try keyword matching
|
|
1087
1311
|
for (const mapping of this.mappings) {
|
|
1088
1312
|
for (const keyword of mapping.keywords) {
|
|
1089
1313
|
if (descLower.includes(keyword.toLowerCase())) {
|
|
@@ -1248,11 +1472,574 @@ export class TaskSkillRouter {
|
|
|
1248
1472
|
this.mappings.push(newMapping);
|
|
1249
1473
|
}
|
|
1250
1474
|
/**
|
|
1251
|
-
|
|
1252
|
-
|
|
1475
|
+
* Get all available mappings (for debugging/testing)
|
|
1476
|
+
*/
|
|
1253
1477
|
getMappings() {
|
|
1254
1478
|
return [...this.mappings];
|
|
1255
1479
|
}
|
|
1480
|
+
/**
|
|
1481
|
+
* KERNEL-ENHANCED: Get routing based on real-time analytics data
|
|
1482
|
+
* Uses analytics to improve routing decisions
|
|
1483
|
+
*/
|
|
1484
|
+
getAnalyticsBasedRouting(taskDescription, kernelInsights) {
|
|
1485
|
+
// Check if we have enough analytics data
|
|
1486
|
+
const promptAnalysis = promptPatternAnalyzer.analyzePromptPatterns();
|
|
1487
|
+
if (promptAnalysis.totalPrompts < 10) {
|
|
1488
|
+
return null; // Not enough data for analytics-based routing
|
|
1489
|
+
}
|
|
1490
|
+
// Look for similar tasks in analytics data
|
|
1491
|
+
const outcomes = routingOutcomeTracker.getOutcomes();
|
|
1492
|
+
const similarTasks = this.findSimilarTasks(taskDescription, outcomes);
|
|
1493
|
+
if (similarTasks.length === 0) {
|
|
1494
|
+
return null; // No similar tasks found
|
|
1495
|
+
}
|
|
1496
|
+
// Find the most successful similar routing
|
|
1497
|
+
const bestRouting = this.findBestRoutingFromSimilar(similarTasks);
|
|
1498
|
+
if (!bestRouting) {
|
|
1499
|
+
return null;
|
|
1500
|
+
}
|
|
1501
|
+
frameworkLogger.log("task-skill-router", "analytics-routing-match", "debug", {
|
|
1502
|
+
taskDescription: taskDescription.substring(0, 100),
|
|
1503
|
+
matchedSimilarTaskCount: similarTasks.length,
|
|
1504
|
+
bestAgent: bestRouting.routedAgent,
|
|
1505
|
+
bestSkill: bestRouting.routedSkill,
|
|
1506
|
+
confidence: bestRouting.successRate || 0.8,
|
|
1507
|
+
}, undefined);
|
|
1508
|
+
return {
|
|
1509
|
+
skill: bestRouting.routedSkill,
|
|
1510
|
+
agent: bestRouting.routedAgent,
|
|
1511
|
+
confidence: bestRouting.successRate || 0.8,
|
|
1512
|
+
reason: `Analytics-based routing: ${similarTasks.length} similar tasks found`,
|
|
1513
|
+
fromHistory: true,
|
|
1514
|
+
kernelGuided: true,
|
|
1515
|
+
analyticsGuided: true
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Find similar tasks based on semantic similarity and keywords
|
|
1520
|
+
*/
|
|
1521
|
+
findSimilarTasks(taskDescription, outcomes) {
|
|
1522
|
+
const keywords = this.extractKeywords(taskDescription.toLowerCase());
|
|
1523
|
+
const similarTasks = [];
|
|
1524
|
+
for (const outcome of outcomes) {
|
|
1525
|
+
if (!outcome.taskDescription)
|
|
1526
|
+
continue;
|
|
1527
|
+
// Check for keyword overlap
|
|
1528
|
+
const outcomeKeywords = this.extractKeywords(outcome.taskDescription.toLowerCase());
|
|
1529
|
+
const keywordOverlap = this.calculateKeywordOverlap(keywords, outcomeKeywords);
|
|
1530
|
+
// Check for semantic similarity (simple implementation)
|
|
1531
|
+
const semanticSimilarity = this.calculateSemanticSimilarity(taskDescription, outcome.taskDescription);
|
|
1532
|
+
// Consider task similar if it has significant keyword overlap or semantic similarity
|
|
1533
|
+
if (keywordOverlap > 0.3 || semanticSimilarity > 0.5) {
|
|
1534
|
+
similarTasks.push(outcome);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
// Return top 10 most similar tasks, sorted by success rate
|
|
1538
|
+
return similarTasks
|
|
1539
|
+
.filter(o => o.success !== undefined || o.successRate !== undefined)
|
|
1540
|
+
.sort((a, b) => {
|
|
1541
|
+
const aRate = a.successRate ?? (a.success ? 1 : 0);
|
|
1542
|
+
const bRate = b.successRate ?? (b.success ? 1 : 0);
|
|
1543
|
+
return bRate - aRate;
|
|
1544
|
+
})
|
|
1545
|
+
.slice(0, 10);
|
|
1546
|
+
}
|
|
1547
|
+
/**
|
|
1548
|
+
* Find the best routing from similar tasks based on success rate
|
|
1549
|
+
*/
|
|
1550
|
+
findBestRoutingFromSimilar(similarTasks) {
|
|
1551
|
+
if (similarTasks.length === 0)
|
|
1552
|
+
return null;
|
|
1553
|
+
// Return the most successful routing
|
|
1554
|
+
return similarTasks.reduce((best, current) => {
|
|
1555
|
+
if (!best)
|
|
1556
|
+
return current;
|
|
1557
|
+
const bestRate = best.successRate ?? (best.success ? 1 : 0);
|
|
1558
|
+
const currentRate = current.successRate ?? (current.success ? 1 : 0);
|
|
1559
|
+
if (currentRate > bestRate) {
|
|
1560
|
+
return current;
|
|
1561
|
+
}
|
|
1562
|
+
return best;
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Extract keywords from task description
|
|
1567
|
+
*/
|
|
1568
|
+
extractKeywords(text) {
|
|
1569
|
+
// Remove common words and extract meaningful keywords
|
|
1570
|
+
const stopWords = new Set(['the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'as']);
|
|
1571
|
+
const words = text.split(/\s+/).filter(word => word.length > 2 && !stopWords.has(word));
|
|
1572
|
+
return words;
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Calculate keyword overlap between two sets of keywords
|
|
1576
|
+
*/
|
|
1577
|
+
calculateKeywordOverlap(keywords1, keywords2) {
|
|
1578
|
+
if (keywords1.length === 0 || keywords2.length === 0)
|
|
1579
|
+
return 0;
|
|
1580
|
+
const set1 = new Set(keywords1);
|
|
1581
|
+
const set2 = new Set(keywords2);
|
|
1582
|
+
const intersection = new Set([...set1].filter(x => set2.has(x)));
|
|
1583
|
+
return intersection.size / Math.max(set1.size, set2.size);
|
|
1584
|
+
}
|
|
1585
|
+
/**
|
|
1586
|
+
* Calculate semantic similarity between two texts (simplified implementation)
|
|
1587
|
+
*/
|
|
1588
|
+
calculateSemanticSimilarity(text1, text2) {
|
|
1589
|
+
const words1 = new Set(this.extractKeywords(text1.toLowerCase()));
|
|
1590
|
+
const words2 = new Set(this.extractKeywords(text2.toLowerCase()));
|
|
1591
|
+
if (words1.size === 0 && words2.size === 0)
|
|
1592
|
+
return 1;
|
|
1593
|
+
if (words1.size === 0 || words2.size === 0)
|
|
1594
|
+
return 0;
|
|
1595
|
+
const intersection = new Set([...words1].filter(x => words2.has(x)));
|
|
1596
|
+
const union = new Set([...words1, ...words2]);
|
|
1597
|
+
return intersection.size / union.size;
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* KERNEL-ENHANCED: Match keywords with kernel insights
|
|
1601
|
+
* Uses kernel patterns to improve keyword matching quality
|
|
1602
|
+
*/
|
|
1603
|
+
matchByKeywordsWithKernel(descLower, kernelInsights) {
|
|
1604
|
+
const candidates = [];
|
|
1605
|
+
// Score all keyword matches
|
|
1606
|
+
for (const mapping of this.mappings) {
|
|
1607
|
+
for (const keyword of mapping.keywords) {
|
|
1608
|
+
if (descLower.includes(keyword.toLowerCase())) {
|
|
1609
|
+
// Calculate enhanced score using kernel insights
|
|
1610
|
+
const kernelScore = this.calculateKernelEnhancementScore(descLower, keyword, mapping, kernelInsights);
|
|
1611
|
+
candidates.push({
|
|
1612
|
+
mapping,
|
|
1613
|
+
keyword,
|
|
1614
|
+
score: kernelScore,
|
|
1615
|
+
kernelMatch: true
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
if (candidates.length === 0) {
|
|
1621
|
+
return null;
|
|
1622
|
+
}
|
|
1623
|
+
// Sort by combined score and get best match
|
|
1624
|
+
candidates.sort((a, b) => b.score - a.score);
|
|
1625
|
+
const bestMatch = candidates[0];
|
|
1626
|
+
// Generate alternatives from top candidates
|
|
1627
|
+
const alternatives = candidates.slice(1, 4).map(c => ({
|
|
1628
|
+
skill: c.mapping.skill,
|
|
1629
|
+
agent: c.mapping.agent,
|
|
1630
|
+
confidence: c.score,
|
|
1631
|
+
reason: `Alternative match: ${c.keyword}`
|
|
1632
|
+
}));
|
|
1633
|
+
// Add kernel recommendations as alternatives if available
|
|
1634
|
+
if (kernelInsights.recommendations && kernelInsights.recommendations.length > 0) {
|
|
1635
|
+
for (const recommendation of kernelInsights.recommendations) {
|
|
1636
|
+
// P2: Check if bestMatch exists before accessing properties
|
|
1637
|
+
if (bestMatch) {
|
|
1638
|
+
alternatives.push({
|
|
1639
|
+
skill: bestMatch.mapping.skill,
|
|
1640
|
+
agent: bestMatch.mapping.agent,
|
|
1641
|
+
confidence: kernelInsights.confidence * 0.8,
|
|
1642
|
+
reason: `Kernel recommendation: ${String(recommendation)}`
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
// P2: Check if bestMatch exists before logging
|
|
1648
|
+
const bestMatchLog = bestMatch ? {
|
|
1649
|
+
keyword: bestMatch.keyword,
|
|
1650
|
+
score: bestMatch.score
|
|
1651
|
+
} : null;
|
|
1652
|
+
frameworkLogger.log("task-skill-router", "kernel-keyword-matching", "debug", {
|
|
1653
|
+
taskDescription: descLower.substring(0, 100),
|
|
1654
|
+
totalCandidates: candidates.length,
|
|
1655
|
+
bestMatch: bestMatchLog?.keyword || 'none',
|
|
1656
|
+
bestScore: bestMatchLog?.score || 0,
|
|
1657
|
+
alternativesCount: alternatives.length
|
|
1658
|
+
}, undefined);
|
|
1659
|
+
// P2: Check if bestMatch exists before returning (null safety)
|
|
1660
|
+
if (!bestMatch) {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
return {
|
|
1664
|
+
skill: bestMatch.mapping.skill,
|
|
1665
|
+
agent: bestMatch.mapping.agent,
|
|
1666
|
+
confidence: bestMatch.score,
|
|
1667
|
+
matchedKeyword: bestMatch.keyword,
|
|
1668
|
+
reason: `Kernel-enhanced match: ${bestMatch.keyword}`,
|
|
1669
|
+
alternatives,
|
|
1670
|
+
kernelGuided: true
|
|
1671
|
+
};
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Calculate kernel-enhanced score for keyword matches
|
|
1675
|
+
*/
|
|
1676
|
+
calculateKernelEnhancementScore(taskDescription, keyword, mapping, kernelInsights) {
|
|
1677
|
+
const baseScore = mapping.confidence;
|
|
1678
|
+
// P2: UNDEFINED_PROPAGATION - Ensure all scores are defined
|
|
1679
|
+
if (baseScore === undefined || baseScore === null) {
|
|
1680
|
+
return 0.5; // Default score for undefined confidence
|
|
1681
|
+
}
|
|
1682
|
+
let enhancementFactor = 1.0;
|
|
1683
|
+
// Enhance based on kernel confidence
|
|
1684
|
+
if (kernelInsights.confidence > 0.7) {
|
|
1685
|
+
enhancementFactor *= 1.1; // 10% boost for high kernel confidence
|
|
1686
|
+
}
|
|
1687
|
+
// INTENT KEYWORD BOOST: Prioritize clear action/intent keywords
|
|
1688
|
+
// These keywords strongly indicate user intent and should be weighted higher
|
|
1689
|
+
const intentKeywords = [
|
|
1690
|
+
'test', 'testing', 'write test', 'create test', 'run test',
|
|
1691
|
+
'fix', 'debug', 'bug', 'triage',
|
|
1692
|
+
'review', 'refactor', 'optimize', 'performance',
|
|
1693
|
+
'security', 'audit', 'vulnerability',
|
|
1694
|
+
'build', 'develop', 'create', 'implement',
|
|
1695
|
+
'design', 'architecture', 'plan'
|
|
1696
|
+
];
|
|
1697
|
+
const keywordLower = keyword.toLowerCase();
|
|
1698
|
+
if (intentKeywords.some(intent => keywordLower === intent || keywordLower.includes(intent + ' '))) {
|
|
1699
|
+
enhancementFactor *= 1.08; // 8% boost for intent keywords
|
|
1700
|
+
}
|
|
1701
|
+
// Enhance based on keyword specificity (longer keywords are more specific)
|
|
1702
|
+
// BUT only if it's NOT an intent keyword (to prevent "login" beating "bug")
|
|
1703
|
+
const keywordLength = keyword.length;
|
|
1704
|
+
if (keywordLength > 10 && !intentKeywords.some(intent => keywordLower === intent)) {
|
|
1705
|
+
enhancementFactor *= 1.05; // 5% boost for specific non-intent keywords
|
|
1706
|
+
}
|
|
1707
|
+
// Enhance based on pattern matches
|
|
1708
|
+
if (kernelInsights.cascadePatterns && kernelInsights.cascadePatterns.length > 0) {
|
|
1709
|
+
// Check if this mapping aligns with detected patterns
|
|
1710
|
+
const patternAlignment = this.checkPatternAlignment(mapping, kernelInsights);
|
|
1711
|
+
if (patternAlignment > 0.5) {
|
|
1712
|
+
enhancementFactor *= 1.08; // 8% boost for pattern alignment
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
// P2: Prevent score from exceeding 1.0
|
|
1716
|
+
const enhancedScore = Math.min(baseScore * enhancementFactor, 1.0);
|
|
1717
|
+
return enhancedScore;
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Check if mapping aligns with detected kernel patterns
|
|
1721
|
+
*/
|
|
1722
|
+
checkPatternAlignment(mapping, kernelInsights) {
|
|
1723
|
+
if (!kernelInsights.cascadePatterns || kernelInsights.cascadePatterns.length === 0) {
|
|
1724
|
+
return 0.5; // Default alignment score
|
|
1725
|
+
}
|
|
1726
|
+
let alignmentScore = 0.5;
|
|
1727
|
+
const patternsChecked = new Set();
|
|
1728
|
+
for (const pattern of kernelInsights.cascadePatterns) {
|
|
1729
|
+
if (patternsChecked.has(pattern.id))
|
|
1730
|
+
continue;
|
|
1731
|
+
// Check if this mapping relates to the pattern
|
|
1732
|
+
if (this.mappingRelatesToPattern(mapping, pattern)) {
|
|
1733
|
+
alignmentScore += 0.15; // 15% boost per matching pattern
|
|
1734
|
+
patternsChecked.add(pattern.id);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
// P2: Prevent alignment from exceeding 1.0
|
|
1738
|
+
return Math.min(alignmentScore, 1.0);
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Check if a mapping relates to a kernel pattern
|
|
1742
|
+
*/
|
|
1743
|
+
mappingRelatesToPattern(mapping, pattern) {
|
|
1744
|
+
// P2: Undefined checks for mapping properties
|
|
1745
|
+
const mappingKeywords = mapping.keywords || [];
|
|
1746
|
+
const patternTriggers = pattern.trigger || [];
|
|
1747
|
+
// Check if any keyword overlaps with pattern triggers
|
|
1748
|
+
return mappingKeywords.some((kw) => patternTriggers.some((trigger) => kw.toLowerCase().includes(trigger.toLowerCase()) ||
|
|
1749
|
+
trigger.toLowerCase().includes(kw.toLowerCase())));
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* KERNEL-ENHANCED: Combine keyword and kernel confidence scores
|
|
1753
|
+
* Only blend kernel confidence when it has meaningful detection (> 0.5)
|
|
1754
|
+
*/
|
|
1755
|
+
combineConfidence(keywordConfidence, kernelConfidence) {
|
|
1756
|
+
// P2: Prevent undefined propagation
|
|
1757
|
+
const safeKeywordConfidence = keywordConfidence ?? 0.7;
|
|
1758
|
+
const safeKernelConfidence = kernelConfidence ?? 0.5;
|
|
1759
|
+
// If kernel has no meaningful detection (base 0.5), use keyword confidence directly
|
|
1760
|
+
// This prevents diluting high-confidence keyword matches with low-confidence kernel
|
|
1761
|
+
if (safeKernelConfidence <= 0.5) {
|
|
1762
|
+
return safeKeywordConfidence;
|
|
1763
|
+
}
|
|
1764
|
+
// Weighted combination: keyword confidence has more weight (60%), kernel has less (40%)
|
|
1765
|
+
const combinedConfidence = (safeKeywordConfidence * 0.6) + (safeKernelConfidence * 0.4);
|
|
1766
|
+
// Ensure confidence is within valid range
|
|
1767
|
+
return Math.max(0.0, Math.min(1.0, combinedConfidence));
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Get the simple/human-readable name for an agent
|
|
1771
|
+
* @param agentName - The technical agent name (e.g., "strategist")
|
|
1772
|
+
* @returns Human-readable name (e.g., "Planner")
|
|
1773
|
+
*/
|
|
1774
|
+
getSimpleName(agentName) {
|
|
1775
|
+
return getAgentSimpleName(agentName);
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Get all simple name mappings
|
|
1779
|
+
* @returns Record of technical name -> simple name
|
|
1780
|
+
*/
|
|
1781
|
+
getAllSimpleNames() {
|
|
1782
|
+
return getAllSimpleNames();
|
|
1783
|
+
}
|
|
1784
|
+
// ===== ENHANCED ROUTING ANALYTICS INTEGRATION =====
|
|
1785
|
+
/**
|
|
1786
|
+
* Get comprehensive routing analytics using all analytics components
|
|
1787
|
+
* @returns Complete routing analytics report
|
|
1788
|
+
*/
|
|
1789
|
+
getRoutingAnalytics() {
|
|
1790
|
+
return {
|
|
1791
|
+
promptPatterns: promptPatternAnalyzer.analyzePromptPatterns(),
|
|
1792
|
+
routingPerformance: routingPerformanceAnalyzer.generatePerformanceReport(),
|
|
1793
|
+
refinementSuggestions: routingRefiner.generateRefinementReport(),
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Get prompt pattern analysis results
|
|
1798
|
+
*/
|
|
1799
|
+
getPromptPatternAnalysis() {
|
|
1800
|
+
return promptPatternAnalyzer.analyzePromptPatterns();
|
|
1801
|
+
}
|
|
1802
|
+
/**
|
|
1803
|
+
* Get routing performance metrics
|
|
1804
|
+
*/
|
|
1805
|
+
getRoutingPerformanceMetrics() {
|
|
1806
|
+
return routingPerformanceAnalyzer.generatePerformanceReport();
|
|
1807
|
+
}
|
|
1808
|
+
/**
|
|
1809
|
+
* Get routing optimization suggestions
|
|
1810
|
+
*/
|
|
1811
|
+
getRoutingOptimizations() {
|
|
1812
|
+
return routingRefiner.generateRefinementReport();
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Apply automated routing refinements to mappings
|
|
1816
|
+
* @param applyChanges - Whether to actually apply changes or just preview
|
|
1817
|
+
* @returns Results of the refinement process
|
|
1818
|
+
*/
|
|
1819
|
+
applyRoutingRefinements(applyChanges = false) {
|
|
1820
|
+
const refinements = routingRefiner.generateRefinementReport();
|
|
1821
|
+
const configUpdate = refinements.configurationUpdate;
|
|
1822
|
+
const changes = [];
|
|
1823
|
+
let appliedMappings = 0;
|
|
1824
|
+
let optimizedMappings = 0;
|
|
1825
|
+
let removedMappings = 0;
|
|
1826
|
+
if (applyChanges) {
|
|
1827
|
+
// Apply suggested additions
|
|
1828
|
+
for (const newMapping of configUpdate.newMappings) {
|
|
1829
|
+
if (newMapping.priority === 'high' || newMapping.priority === 'medium') {
|
|
1830
|
+
this.addMapping(newMapping.keyword, newMapping.targetSkill, newMapping.targetAgent, newMapping.suggestedConfidence);
|
|
1831
|
+
appliedMappings++;
|
|
1832
|
+
changes.push({
|
|
1833
|
+
type: 'added',
|
|
1834
|
+
mapping: newMapping,
|
|
1835
|
+
reason: newMapping.reason
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
// Apply suggested optimizations
|
|
1840
|
+
for (const optimization of configUpdate.optimizations) {
|
|
1841
|
+
const mappingIndex = this.mappings.findIndex(m => m.skill === optimization.currentSkill && m.agent === optimization.currentAgent);
|
|
1842
|
+
if (mappingIndex >= 0 && optimization.suggestedChanges.newConfidence) {
|
|
1843
|
+
this.mappings[mappingIndex].confidence = optimization.suggestedChanges.newConfidence;
|
|
1844
|
+
optimizedMappings++;
|
|
1845
|
+
changes.push({
|
|
1846
|
+
type: 'optimized',
|
|
1847
|
+
mapping: this.mappings[mappingIndex],
|
|
1848
|
+
reason: optimization.reason
|
|
1849
|
+
});
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
// Note: removals are handled via warnings in ConfigurationUpdate
|
|
1853
|
+
// We can extract removal suggestions from warnings if needed
|
|
1854
|
+
for (const warning of configUpdate.warnings) {
|
|
1855
|
+
if (warning.includes('remove') || warning.includes('deprecated')) {
|
|
1856
|
+
// Parse warning for potential removal actions
|
|
1857
|
+
removedMappings++;
|
|
1858
|
+
changes.push({
|
|
1859
|
+
type: 'removed',
|
|
1860
|
+
mapping: { reason: warning },
|
|
1861
|
+
reason: warning
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
else {
|
|
1867
|
+
// Preview mode - just count what would be done
|
|
1868
|
+
appliedMappings = configUpdate.newMappings.filter(m => m.priority === 'high' || m.priority === 'medium').length;
|
|
1869
|
+
optimizedMappings = configUpdate.optimizations.length;
|
|
1870
|
+
// Count removal suggestions from warnings
|
|
1871
|
+
removedMappings = configUpdate.warnings.filter(w => w.includes('remove') || w.includes('deprecated')).length;
|
|
1872
|
+
}
|
|
1873
|
+
frameworkLogger.log("task-skill-router", "routing-refinements-applied", "info", {
|
|
1874
|
+
appliedMappings,
|
|
1875
|
+
optimizedMappings,
|
|
1876
|
+
removedMappings,
|
|
1877
|
+
applyChanges,
|
|
1878
|
+
totalChanges: changes.length
|
|
1879
|
+
});
|
|
1880
|
+
return {
|
|
1881
|
+
appliedMappings,
|
|
1882
|
+
optimizedMappings,
|
|
1883
|
+
removedMappings,
|
|
1884
|
+
changes
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Get daily routing analytics summary
|
|
1889
|
+
* Useful for monitoring and reporting
|
|
1890
|
+
*/
|
|
1891
|
+
getDailyAnalyticsSummary() {
|
|
1892
|
+
const promptAnalysis = promptPatternAnalyzer.analyzePromptPatterns();
|
|
1893
|
+
const performanceAnalysis = routingPerformanceAnalyzer.generatePerformanceReport();
|
|
1894
|
+
const date = new Date().toISOString().split('T')[0] || new Date().toISOString();
|
|
1895
|
+
const totalRoutings = routingOutcomeTracker.getOutcomes().length;
|
|
1896
|
+
const averageConfidence = performanceAnalysis.avgConfidence;
|
|
1897
|
+
const templateMatchRate = promptAnalysis.templateMatchRate;
|
|
1898
|
+
// Calculate overall success rate
|
|
1899
|
+
const outcomes = routingOutcomeTracker.getOutcomes();
|
|
1900
|
+
const successCount = outcomes.filter(o => o.success === true).length;
|
|
1901
|
+
const successRate = totalRoutings > 0 ? successCount / totalRoutings : 0;
|
|
1902
|
+
// Get top performing agents
|
|
1903
|
+
const topAgents = performanceAnalysis.agentMetrics
|
|
1904
|
+
.sort((a, b) => b.totalRoutings - a.totalRoutings)
|
|
1905
|
+
.slice(0, 5)
|
|
1906
|
+
.map((ap) => ({
|
|
1907
|
+
agent: ap.agent,
|
|
1908
|
+
count: ap.totalRoutings,
|
|
1909
|
+
successRate: ap.successRate
|
|
1910
|
+
}));
|
|
1911
|
+
// Get top performing keywords
|
|
1912
|
+
const topKeywords = performanceAnalysis.keywordEffectiveness
|
|
1913
|
+
.sort((a, b) => b.matchCount - a.matchCount)
|
|
1914
|
+
.slice(0, 10)
|
|
1915
|
+
.map((kp) => ({
|
|
1916
|
+
keyword: kp.keyword,
|
|
1917
|
+
count: kp.matchCount,
|
|
1918
|
+
successRate: kp.successRate
|
|
1919
|
+
}));
|
|
1920
|
+
// Generate insights
|
|
1921
|
+
const insights = [];
|
|
1922
|
+
if (templateMatchRate < 0.5) {
|
|
1923
|
+
insights.push(`Low template match rate (${(templateMatchRate * 100).toFixed(1)}%) - consider adding more templates`);
|
|
1924
|
+
}
|
|
1925
|
+
if (successRate < 0.7) {
|
|
1926
|
+
insights.push(`Routing success rate below target (${(successRate * 100).toFixed(1)}%) - review mapping accuracy`);
|
|
1927
|
+
}
|
|
1928
|
+
if (promptAnalysis.gaps.length > 5) {
|
|
1929
|
+
insights.push(`${promptAnalysis.gaps.length} template gaps detected - review emerging patterns`);
|
|
1930
|
+
}
|
|
1931
|
+
if (averageConfidence < 0.8) {
|
|
1932
|
+
insights.push(`Average routing confidence low (${averageConfidence.toFixed(2)}) - consider confidence threshold adjustments`);
|
|
1933
|
+
}
|
|
1934
|
+
if (insights.length === 0) {
|
|
1935
|
+
insights.push('Routing system performing within normal parameters');
|
|
1936
|
+
}
|
|
1937
|
+
return {
|
|
1938
|
+
date,
|
|
1939
|
+
totalRoutings,
|
|
1940
|
+
averageConfidence,
|
|
1941
|
+
templateMatchRate,
|
|
1942
|
+
successRate,
|
|
1943
|
+
topAgents,
|
|
1944
|
+
topKeywords,
|
|
1945
|
+
insights
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
// ===== P9: ADAPTIVE PATTERN LEARNING =====
|
|
1949
|
+
/**
|
|
1950
|
+
* P9: Get adaptive learning statistics
|
|
1951
|
+
*/
|
|
1952
|
+
getP9LearningStats() {
|
|
1953
|
+
if (!this.adaptiveKernel) {
|
|
1954
|
+
return {
|
|
1955
|
+
enabled: false,
|
|
1956
|
+
lastLearningRun: null,
|
|
1957
|
+
cacheValid: false,
|
|
1958
|
+
patternsTracked: 0,
|
|
1959
|
+
driftDetected: 0,
|
|
1960
|
+
thresholdsCalibrated: false
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
const stats = this.adaptiveKernel.getLearningStats();
|
|
1964
|
+
return {
|
|
1965
|
+
enabled: true,
|
|
1966
|
+
lastLearningRun: stats.lastLearningRun,
|
|
1967
|
+
cacheValid: stats.cacheValid,
|
|
1968
|
+
patternsTracked: stats.patternsTracked,
|
|
1969
|
+
driftDetected: stats.driftDetected,
|
|
1970
|
+
thresholdsCalibrated: stats.thresholdsCalibrated
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
/**
|
|
1974
|
+
* P9: Get pattern drift analysis
|
|
1975
|
+
*/
|
|
1976
|
+
getPatternDriftAnalysis() {
|
|
1977
|
+
if (!this.adaptiveKernel) {
|
|
1978
|
+
return [];
|
|
1979
|
+
}
|
|
1980
|
+
return this.adaptiveKernel.getPatternDrift();
|
|
1981
|
+
}
|
|
1982
|
+
/**
|
|
1983
|
+
* P9: Get adaptive confidence thresholds
|
|
1984
|
+
*/
|
|
1985
|
+
getAdaptiveThresholds() {
|
|
1986
|
+
if (!this.adaptiveKernel) {
|
|
1987
|
+
return null;
|
|
1988
|
+
}
|
|
1989
|
+
const thresholds = this.adaptiveKernel.getAdaptiveThresholds();
|
|
1990
|
+
return {
|
|
1991
|
+
overall: thresholds.overall,
|
|
1992
|
+
perAgent: Object.fromEntries(thresholds.perAgent),
|
|
1993
|
+
perSkill: Object.fromEntries(thresholds.perSkill),
|
|
1994
|
+
calibrationDate: thresholds.calibrationDate
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* P9: Trigger manual learning cycle
|
|
1999
|
+
*/
|
|
2000
|
+
triggerP9Learning() {
|
|
2001
|
+
if (!this.adaptiveKernel) {
|
|
2002
|
+
return {
|
|
2003
|
+
newPatterns: 0,
|
|
2004
|
+
modifiedPatterns: 0,
|
|
2005
|
+
removedPatterns: 0,
|
|
2006
|
+
thresholdUpdates: 0,
|
|
2007
|
+
recommendations: ['P9 not enabled']
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
// Collect current routing data
|
|
2011
|
+
const outcomes = routingOutcomeTracker.getOutcomes().map(o => ({
|
|
2012
|
+
taskId: o.taskId,
|
|
2013
|
+
taskDescription: o.taskDescription || '',
|
|
2014
|
+
routedAgent: o.routedAgent,
|
|
2015
|
+
routedSkill: o.routedSkill,
|
|
2016
|
+
confidence: o.confidence,
|
|
2017
|
+
success: o.success ?? false
|
|
2018
|
+
}));
|
|
2019
|
+
// Get existing mappings
|
|
2020
|
+
const existingMappings = this.getMappings();
|
|
2021
|
+
return this.adaptiveKernel.triggerLearning(outcomes, existingMappings);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* P9: Track routing outcome for learning
|
|
2025
|
+
*/
|
|
2026
|
+
trackOutcomeForLearning(taskId, taskDescription, agent, skill, confidence, success) {
|
|
2027
|
+
// Track in performance tracker
|
|
2028
|
+
const patternId = `${agent}:${skill}`;
|
|
2029
|
+
patternPerformanceTracker.trackPatternPerformance(patternId, {
|
|
2030
|
+
success,
|
|
2031
|
+
confidence
|
|
2032
|
+
});
|
|
2033
|
+
// Record in outcome tracker
|
|
2034
|
+
routingOutcomeTracker.recordOutcome({
|
|
2035
|
+
taskId,
|
|
2036
|
+
taskDescription,
|
|
2037
|
+
routedAgent: agent,
|
|
2038
|
+
routedSkill: skill,
|
|
2039
|
+
confidence,
|
|
2040
|
+
success
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
1256
2043
|
}
|
|
1257
2044
|
// Default instance (without state manager - must be set separately)
|
|
1258
2045
|
export const taskSkillRouter = new TaskSkillRouter();
|