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.
Files changed (189) hide show
  1. package/.opencode/hooks/post-commit +152 -55
  2. package/.opencode/hooks/post-commit.backup +110 -174
  3. package/.opencode/hooks/post-push +47 -64
  4. package/.opencode/hooks/post-push.backup +34 -38
  5. package/.opencode/strray/features.json +3 -3
  6. package/.opencode/strray/routing-mappings.json +90 -34
  7. package/AGENTS.md +7 -2
  8. package/dist/analytics/anonymization-engine.d.ts +108 -0
  9. package/dist/analytics/anonymization-engine.d.ts.map +1 -0
  10. package/dist/analytics/anonymization-engine.js +352 -0
  11. package/dist/analytics/anonymization-engine.js.map +1 -0
  12. package/dist/analytics/consent-manager.d.ts +94 -0
  13. package/dist/analytics/consent-manager.d.ts.map +1 -0
  14. package/dist/analytics/consent-manager.js +257 -0
  15. package/dist/analytics/consent-manager.js.map +1 -0
  16. package/dist/analytics/emerging-pattern-detector.d.ts +68 -0
  17. package/dist/analytics/emerging-pattern-detector.d.ts.map +1 -0
  18. package/dist/analytics/emerging-pattern-detector.js +250 -0
  19. package/dist/analytics/emerging-pattern-detector.js.map +1 -0
  20. package/dist/analytics/pattern-learning-engine.d.ts +81 -0
  21. package/dist/analytics/pattern-learning-engine.d.ts.map +1 -0
  22. package/dist/analytics/pattern-learning-engine.js +262 -0
  23. package/dist/analytics/pattern-learning-engine.js.map +1 -0
  24. package/dist/analytics/pattern-performance-tracker.d.ts +89 -0
  25. package/dist/analytics/pattern-performance-tracker.d.ts.map +1 -0
  26. package/dist/analytics/pattern-performance-tracker.js +289 -0
  27. package/dist/analytics/pattern-performance-tracker.js.map +1 -0
  28. package/dist/analytics/prompt-pattern-analyzer.d.ts +100 -0
  29. package/dist/analytics/prompt-pattern-analyzer.d.ts.map +1 -0
  30. package/dist/analytics/prompt-pattern-analyzer.js +372 -0
  31. package/dist/analytics/prompt-pattern-analyzer.js.map +1 -0
  32. package/dist/analytics/routing-performance-analyzer.d.ts +102 -0
  33. package/dist/analytics/routing-performance-analyzer.d.ts.map +1 -0
  34. package/dist/analytics/routing-performance-analyzer.js +342 -0
  35. package/dist/analytics/routing-performance-analyzer.js.map +1 -0
  36. package/dist/analytics/routing-refiner.d.ts +105 -0
  37. package/dist/analytics/routing-refiner.d.ts.map +1 -0
  38. package/dist/analytics/routing-refiner.js +381 -0
  39. package/dist/analytics/routing-refiner.js.map +1 -0
  40. package/dist/cli/commands/analytics-disable.d.ts +10 -0
  41. package/dist/cli/commands/analytics-disable.d.ts.map +1 -0
  42. package/dist/cli/commands/analytics-disable.js +73 -0
  43. package/dist/cli/commands/analytics-disable.js.map +1 -0
  44. package/dist/cli/commands/analytics-enable-action.d.ts +9 -0
  45. package/dist/cli/commands/analytics-enable-action.d.ts.map +1 -0
  46. package/dist/cli/commands/analytics-enable-action.js +83 -0
  47. package/dist/cli/commands/analytics-enable-action.js.map +1 -0
  48. package/dist/cli/commands/analytics-preview.d.ts +10 -0
  49. package/dist/cli/commands/analytics-preview.d.ts.map +1 -0
  50. package/dist/cli/commands/analytics-preview.js +107 -0
  51. package/dist/cli/commands/analytics-preview.js.map +1 -0
  52. package/dist/cli/commands/analytics-status.d.ts +10 -0
  53. package/dist/cli/commands/analytics-status.d.ts.map +1 -0
  54. package/dist/cli/commands/analytics-status.js +68 -0
  55. package/dist/cli/commands/analytics-status.js.map +1 -0
  56. package/dist/cli/index.js +6 -3
  57. package/dist/cli/index.js.map +1 -1
  58. package/dist/core/adaptive-kernel.d.ts +110 -0
  59. package/dist/core/adaptive-kernel.d.ts.map +1 -0
  60. package/dist/core/adaptive-kernel.js +193 -0
  61. package/dist/core/adaptive-kernel.js.map +1 -0
  62. package/dist/core/kernel-patterns.d.ts +105 -0
  63. package/dist/core/kernel-patterns.d.ts.map +1 -0
  64. package/dist/core/kernel-patterns.js +328 -0
  65. package/dist/core/kernel-patterns.js.map +1 -0
  66. package/dist/core/orchestrator.d.ts +1 -0
  67. package/dist/core/orchestrator.d.ts.map +1 -1
  68. package/dist/core/orchestrator.js +40 -11
  69. package/dist/core/orchestrator.js.map +1 -1
  70. package/dist/delegation/agent-delegator.d.ts +1 -0
  71. package/dist/delegation/agent-delegator.d.ts.map +1 -1
  72. package/dist/delegation/agent-delegator.js +24 -2
  73. package/dist/delegation/agent-delegator.js.map +1 -1
  74. package/dist/delegation/task-skill-router.d.ts +269 -5
  75. package/dist/delegation/task-skill-router.d.ts.map +1 -1
  76. package/dist/delegation/task-skill-router.js +810 -23
  77. package/dist/delegation/task-skill-router.js.map +1 -1
  78. package/dist/postprocessor/PostProcessor.d.ts +10 -0
  79. package/dist/postprocessor/PostProcessor.d.ts.map +1 -1
  80. package/dist/postprocessor/PostProcessor.js +87 -17
  81. package/dist/postprocessor/PostProcessor.js.map +1 -1
  82. package/dist/processors/agents-md-validation-processor.d.ts +1 -0
  83. package/dist/processors/agents-md-validation-processor.d.ts.map +1 -1
  84. package/dist/processors/agents-md-validation-processor.js +34 -12
  85. package/dist/processors/agents-md-validation-processor.js.map +1 -1
  86. package/dist/processors/processor-manager.d.ts +7 -0
  87. package/dist/processors/processor-manager.d.ts.map +1 -1
  88. package/dist/processors/processor-manager.js +93 -0
  89. package/dist/processors/processor-manager.js.map +1 -1
  90. package/dist/processors/test-auto-creation-processor.d.ts.map +1 -1
  91. package/dist/processors/test-auto-creation-processor.js +52 -38
  92. package/dist/processors/test-auto-creation-processor.js.map +1 -1
  93. package/dist/scripts/analytics/daily-routing-analysis.d.ts +18 -0
  94. package/dist/scripts/analytics/daily-routing-analysis.d.ts.map +1 -0
  95. package/dist/scripts/analytics/daily-routing-analysis.js +268 -0
  96. package/dist/scripts/analytics/daily-routing-analysis.js.map +1 -0
  97. package/dist/scripts/analytics/index.d.ts +15 -0
  98. package/dist/scripts/analytics/index.d.ts.map +1 -0
  99. package/dist/scripts/analytics/index.js +17 -0
  100. package/dist/scripts/analytics/index.js.map +1 -0
  101. package/dist/scripts/test-p9.d.ts +15 -0
  102. package/dist/scripts/test-p9.d.ts.map +1 -0
  103. package/dist/scripts/test-p9.js +220 -0
  104. package/dist/scripts/test-p9.js.map +1 -0
  105. package/package.json +6 -2
  106. package/scripts/node/kernel-e2e-test.mjs +168 -0
  107. package/scripts/node/kernel-framework-test.mjs +127 -0
  108. package/scripts/node/kernel-live-test.mjs +147 -0
  109. package/scripts/node/kernel-real-framework-test.mjs +103 -0
  110. package/scripts/node/kernel-update.cjs +379 -0
  111. package/scripts/node/reflection-check.sh +245 -27
  112. package/scripts/node/test-simple-names-comprehensive.mjs +221 -0
  113. package/scripts/node/test-simple-names.mjs +39 -0
  114. package/dist/agents/documentation-writer.d.ts +0 -9
  115. package/dist/agents/documentation-writer.d.ts.map +0 -1
  116. package/dist/agents/documentation-writer.js +0 -85
  117. package/dist/agents/documentation-writer.js.map +0 -1
  118. package/dist/agents/explore.d.ts +0 -8
  119. package/dist/agents/explore.d.ts.map +0 -1
  120. package/dist/agents/explore.js +0 -55
  121. package/dist/agents/explore.js.map +0 -1
  122. package/dist/agents/librarian.d.ts +0 -3
  123. package/dist/agents/librarian.d.ts.map +0 -1
  124. package/dist/agents/librarian.js +0 -84
  125. package/dist/agents/librarian.js.map +0 -1
  126. package/dist/agents/marketing-expert.d.ts +0 -9
  127. package/dist/agents/marketing-expert.d.ts.map +0 -1
  128. package/dist/agents/marketing-expert.js +0 -112
  129. package/dist/agents/marketing-expert.js.map +0 -1
  130. package/dist/agents/oracle.d.ts +0 -8
  131. package/dist/agents/oracle.d.ts.map +0 -1
  132. package/dist/agents/oracle.js +0 -51
  133. package/dist/agents/oracle.js.map +0 -1
  134. package/dist/agents/seo-copywriter.d.ts +0 -10
  135. package/dist/agents/seo-copywriter.d.ts.map +0 -1
  136. package/dist/agents/seo-copywriter.js +0 -73
  137. package/dist/agents/seo-copywriter.js.map +0 -1
  138. package/dist/agents/seo-specialist.d.ts +0 -9
  139. package/dist/agents/seo-specialist.d.ts.map +0 -1
  140. package/dist/agents/seo-specialist.js +0 -54
  141. package/dist/agents/seo-specialist.js.map +0 -1
  142. package/dist/agents/test-architect.d.ts +0 -3
  143. package/dist/agents/test-architect.d.ts.map +0 -1
  144. package/dist/agents/test-architect.js +0 -96
  145. package/dist/agents/test-architect.js.map +0 -1
  146. package/dist/mcps/enhanced-orchestrator.server.d.ts +0 -14
  147. package/dist/mcps/enhanced-orchestrator.server.d.ts.map +0 -1
  148. package/dist/mcps/enhanced-orchestrator.server.js +0 -266
  149. package/dist/mcps/enhanced-orchestrator.server.js.map +0 -1
  150. package/dist/mcps/knowledge-skills/analyzer.server.d.ts +0 -7
  151. package/dist/mcps/knowledge-skills/analyzer.server.d.ts.map +0 -1
  152. package/dist/mcps/knowledge-skills/analyzer.server.js +0 -282
  153. package/dist/mcps/knowledge-skills/analyzer.server.js.map +0 -1
  154. package/dist/mcps/knowledge-skills/documentation-generation.server.d.ts +0 -48
  155. package/dist/mcps/knowledge-skills/documentation-generation.server.d.ts.map +0 -1
  156. package/dist/mcps/knowledge-skills/documentation-generation.server.js +0 -1238
  157. package/dist/mcps/knowledge-skills/documentation-generation.server.js.map +0 -1
  158. package/dist/mcps/knowledge-skills/explore.server.d.ts +0 -21
  159. package/dist/mcps/knowledge-skills/explore.server.d.ts.map +0 -1
  160. package/dist/mcps/knowledge-skills/explore.server.js +0 -582
  161. package/dist/mcps/knowledge-skills/explore.server.js.map +0 -1
  162. package/dist/mcps/knowledge-skills/marketing-expert.server.d.ts +0 -8
  163. package/dist/mcps/knowledge-skills/marketing-expert.server.d.ts.map +0 -1
  164. package/dist/mcps/knowledge-skills/marketing-expert.server.js +0 -356
  165. package/dist/mcps/knowledge-skills/marketing-expert.server.js.map +0 -1
  166. package/dist/mcps/knowledge-skills/oracle.server.d.ts +0 -25
  167. package/dist/mcps/knowledge-skills/oracle.server.d.ts.map +0 -1
  168. package/dist/mcps/knowledge-skills/oracle.server.js +0 -569
  169. package/dist/mcps/knowledge-skills/oracle.server.js.map +0 -1
  170. package/dist/mcps/knowledge-skills/seo-copywriter.server.d.ts +0 -8
  171. package/dist/mcps/knowledge-skills/seo-copywriter.server.d.ts.map +0 -1
  172. package/dist/mcps/knowledge-skills/seo-copywriter.server.js +0 -251
  173. package/dist/mcps/knowledge-skills/seo-copywriter.server.js.map +0 -1
  174. package/dist/mcps/knowledge-skills/seo-specialist.server.d.ts +0 -8
  175. package/dist/mcps/knowledge-skills/seo-specialist.server.d.ts.map +0 -1
  176. package/dist/mcps/knowledge-skills/seo-specialist.server.js +0 -211
  177. package/dist/mcps/knowledge-skills/seo-specialist.server.js.map +0 -1
  178. package/dist/mcps/librarian.server.d.ts +0 -17
  179. package/dist/mcps/librarian.server.d.ts.map +0 -1
  180. package/dist/mcps/librarian.server.js +0 -382
  181. package/dist/mcps/librarian.server.js.map +0 -1
  182. package/dist/optimization/performance-optimizer.d.ts +0 -179
  183. package/dist/optimization/performance-optimizer.d.ts.map +0 -1
  184. package/dist/optimization/performance-optimizer.js +0 -556
  185. package/dist/optimization/performance-optimizer.js.map +0 -1
  186. package/dist/utils/memory-pool.d.ts +0 -90
  187. package/dist/utils/memory-pool.d.ts.map +0 -1
  188. package/dist/utils/memory-pool.js +0 -245
  189. 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
- maxOutcomes = 1000;
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
- this.outcomes.push({ ...outcome, timestamp: new Date() });
35
- // Keep only recent outcomes
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
- return JSON.parse(content);
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
- this.mappings = configMappings;
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
- * Route a task to the appropriate agent and skill
1037
- * Returns result with escalateToLlm flag when confidence is below threshold
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
- // 1. Try keyword matching first (highest priority)
1046
- const keywordResult = this.matchByKeywords(descLower);
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
- // Check confidence threshold
1049
- const shouldEscalate = ROUTING_CONFIG.ESCALATE_ON_LOW_CONFIDENCE &&
1050
- keywordResult.confidence < ROUTING_CONFIG.MIN_CONFIDENCE_THRESHOLD;
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
- confidence: keywordResult.confidence,
1057
- belowThreshold: shouldEscalate,
1253
+ keywordConfidence: keywordResult.confidence,
1254
+ kernelConfidence: kernelInsights.confidence,
1255
+ combinedConfidence,
1256
+ alternatives: keywordResult.alternatives?.length || 0,
1058
1257
  }, options.sessionId);
1059
- // Add escalation flag if below threshold
1060
- if (shouldEscalate) {
1061
- return { ...keywordResult, escalateToLlm: true };
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 keywordResult;
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
- * Get all available mappings (for debugging/testing)
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();