agentic-qe 3.8.10 → 3.8.12

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 (119) hide show
  1. package/.claude/skills/skills-manifest.json +1 -1
  2. package/CHANGELOG.md +40 -0
  3. package/dist/cli/bundle.js +1345 -1003
  4. package/dist/cli/command-registry.js +5 -1
  5. package/dist/cli/commands/pipeline.d.ts +16 -0
  6. package/dist/cli/commands/pipeline.js +314 -0
  7. package/dist/cli/commands/ruvector-commands.js +17 -0
  8. package/dist/cli/commands/token-usage.js +24 -1
  9. package/dist/cli/handlers/heartbeat-handler.d.ts +26 -0
  10. package/dist/cli/handlers/heartbeat-handler.js +382 -0
  11. package/dist/cli/handlers/index.d.ts +2 -0
  12. package/dist/cli/handlers/index.js +2 -0
  13. package/dist/cli/handlers/routing-handler.d.ts +22 -0
  14. package/dist/cli/handlers/routing-handler.js +227 -0
  15. package/dist/cli/index.js +2 -0
  16. package/dist/coordination/deterministic-actions.d.ts +36 -0
  17. package/dist/coordination/deterministic-actions.js +257 -0
  18. package/dist/coordination/workflow-orchestrator.d.ts +18 -1
  19. package/dist/coordination/workflow-orchestrator.js +113 -3
  20. package/dist/coordination/workflow-types.d.ts +19 -1
  21. package/dist/coordination/workflow-types.js +3 -0
  22. package/dist/coordination/yaml-pipeline-loader.d.ts +1 -0
  23. package/dist/coordination/yaml-pipeline-loader.js +34 -0
  24. package/dist/domains/code-intelligence/coordinator-gnn.d.ts +21 -0
  25. package/dist/domains/code-intelligence/coordinator-gnn.js +102 -0
  26. package/dist/domains/contract-testing/coordinator.js +13 -0
  27. package/dist/domains/coverage-analysis/coordinator.js +5 -0
  28. package/dist/domains/defect-intelligence/coordinator.d.ts +1 -0
  29. package/dist/domains/defect-intelligence/coordinator.js +43 -0
  30. package/dist/domains/quality-assessment/coordinator.js +26 -0
  31. package/dist/domains/test-generation/coordinator.js +14 -0
  32. package/dist/integrations/agentic-flow/reasoning-bank/experience-replay.d.ts +11 -0
  33. package/dist/integrations/agentic-flow/reasoning-bank/experience-replay.js +44 -1
  34. package/dist/integrations/rl-suite/algorithms/eprop.d.ts +79 -0
  35. package/dist/integrations/rl-suite/algorithms/eprop.js +284 -0
  36. package/dist/integrations/rl-suite/algorithms/index.d.ts +2 -1
  37. package/dist/integrations/rl-suite/algorithms/index.js +2 -1
  38. package/dist/integrations/rl-suite/index.d.ts +2 -2
  39. package/dist/integrations/rl-suite/index.js +2 -2
  40. package/dist/integrations/rl-suite/interfaces.d.ts +3 -3
  41. package/dist/integrations/rl-suite/interfaces.js +1 -1
  42. package/dist/integrations/rl-suite/orchestrator.d.ts +2 -2
  43. package/dist/integrations/rl-suite/orchestrator.js +3 -2
  44. package/dist/integrations/rl-suite/reward-signals.d.ts +1 -1
  45. package/dist/integrations/rl-suite/reward-signals.js +1 -1
  46. package/dist/integrations/ruvector/coherence-gate-cohomology.d.ts +41 -0
  47. package/dist/integrations/ruvector/coherence-gate-cohomology.js +47 -0
  48. package/dist/integrations/ruvector/coherence-gate-core.d.ts +200 -0
  49. package/dist/integrations/ruvector/coherence-gate-core.js +294 -0
  50. package/dist/integrations/ruvector/coherence-gate-energy.d.ts +136 -0
  51. package/dist/integrations/ruvector/coherence-gate-energy.js +373 -0
  52. package/dist/integrations/ruvector/coherence-gate-vector.d.ts +38 -0
  53. package/dist/integrations/ruvector/coherence-gate-vector.js +76 -0
  54. package/dist/integrations/ruvector/coherence-gate.d.ts +10 -311
  55. package/dist/integrations/ruvector/coherence-gate.js +10 -652
  56. package/dist/integrations/ruvector/cold-tier-trainer.d.ts +103 -0
  57. package/dist/integrations/ruvector/cold-tier-trainer.js +377 -0
  58. package/dist/integrations/ruvector/cusum-detector.d.ts +70 -0
  59. package/dist/integrations/ruvector/cusum-detector.js +142 -0
  60. package/dist/integrations/ruvector/delta-tracker.d.ts +122 -0
  61. package/dist/integrations/ruvector/delta-tracker.js +311 -0
  62. package/dist/integrations/ruvector/domain-transfer.d.ts +79 -1
  63. package/dist/integrations/ruvector/domain-transfer.js +158 -2
  64. package/dist/integrations/ruvector/eprop-learner.d.ts +135 -0
  65. package/dist/integrations/ruvector/eprop-learner.js +351 -0
  66. package/dist/integrations/ruvector/feature-flags.d.ts +177 -0
  67. package/dist/integrations/ruvector/feature-flags.js +145 -0
  68. package/dist/integrations/ruvector/graphmae-encoder.d.ts +88 -0
  69. package/dist/integrations/ruvector/graphmae-encoder.js +360 -0
  70. package/dist/integrations/ruvector/hdc-fingerprint.d.ts +127 -0
  71. package/dist/integrations/ruvector/hdc-fingerprint.js +222 -0
  72. package/dist/integrations/ruvector/hopfield-memory.d.ts +97 -0
  73. package/dist/integrations/ruvector/hopfield-memory.js +238 -0
  74. package/dist/integrations/ruvector/index.d.ts +13 -2
  75. package/dist/integrations/ruvector/index.js +46 -2
  76. package/dist/integrations/ruvector/mincut-wrapper.d.ts +7 -0
  77. package/dist/integrations/ruvector/mincut-wrapper.js +54 -2
  78. package/dist/integrations/ruvector/reservoir-replay.d.ts +172 -0
  79. package/dist/integrations/ruvector/reservoir-replay.js +335 -0
  80. package/dist/integrations/ruvector/solver-adapter.d.ts +93 -0
  81. package/dist/integrations/ruvector/solver-adapter.js +299 -0
  82. package/dist/integrations/ruvector/sona-persistence.d.ts +33 -0
  83. package/dist/integrations/ruvector/sona-persistence.js +47 -0
  84. package/dist/integrations/ruvector/spectral-sparsifier.d.ts +154 -0
  85. package/dist/integrations/ruvector/spectral-sparsifier.js +389 -0
  86. package/dist/integrations/ruvector/temporal-causality.d.ts +63 -0
  87. package/dist/integrations/ruvector/temporal-causality.js +317 -0
  88. package/dist/learning/pattern-promotion.d.ts +63 -0
  89. package/dist/learning/pattern-promotion.js +235 -1
  90. package/dist/learning/pattern-store.d.ts +2 -0
  91. package/dist/learning/pattern-store.js +187 -1
  92. package/dist/learning/sqlite-persistence.d.ts +2 -0
  93. package/dist/learning/sqlite-persistence.js +4 -0
  94. package/dist/mcp/bundle.js +477 -380
  95. package/dist/mcp/handlers/heartbeat-handlers.d.ts +67 -0
  96. package/dist/mcp/handlers/heartbeat-handlers.js +180 -0
  97. package/dist/mcp/handlers/index.d.ts +2 -1
  98. package/dist/mcp/handlers/index.js +5 -1
  99. package/dist/mcp/handlers/task-handlers.d.ts +28 -0
  100. package/dist/mcp/handlers/task-handlers.js +39 -0
  101. package/dist/mcp/protocol-server.js +45 -1
  102. package/dist/mcp/server.js +41 -1
  103. package/dist/optimization/index.d.ts +2 -0
  104. package/dist/optimization/index.js +1 -0
  105. package/dist/optimization/session-cache.d.ts +80 -0
  106. package/dist/optimization/session-cache.js +227 -0
  107. package/dist/optimization/token-optimizer-service.d.ts +10 -0
  108. package/dist/optimization/token-optimizer-service.js +51 -0
  109. package/dist/routing/economic-routing.d.ts +126 -0
  110. package/dist/routing/economic-routing.js +290 -0
  111. package/dist/routing/index.d.ts +2 -0
  112. package/dist/routing/index.js +2 -0
  113. package/dist/routing/routing-feedback.d.ts +29 -0
  114. package/dist/routing/routing-feedback.js +75 -0
  115. package/dist/shared/utils/index.d.ts +1 -0
  116. package/dist/shared/utils/index.js +1 -0
  117. package/dist/shared/utils/xorshift128.d.ts +24 -0
  118. package/dist/shared/utils/xorshift128.js +50 -0
  119. package/package.json +1 -1
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Economic Routing Model — Imp-18 (Issue #334)
3
+ *
4
+ * Quality-weighted cost optimization for the routing system.
5
+ * Scores tiers by quality-per-dollar efficiency, respects budget limits,
6
+ * and produces cost-adjusted rewards so the neural router learns to
7
+ * prefer cost-efficient tiers.
8
+ *
9
+ * @module routing/economic-routing
10
+ */
11
+ // ============================================================================
12
+ // Constants & Types
13
+ // ============================================================================
14
+ /**
15
+ * Tier cost estimates (per typical QE task, in USD).
16
+ * Based on average token usage per task type.
17
+ */
18
+ export const TIER_COST_ESTIMATES = {
19
+ booster: { avgInputTokens: 0, avgOutputTokens: 0, costPerTask: 0 },
20
+ haiku: { avgInputTokens: 2000, avgOutputTokens: 1000, costPerTask: 0.0035 },
21
+ sonnet: { avgInputTokens: 2000, avgOutputTokens: 1000, costPerTask: 0.021 },
22
+ opus: { avgInputTokens: 2000, avgOutputTokens: 1000, costPerTask: 0.105 },
23
+ };
24
+ /** All tiers ordered cheapest to most expensive */
25
+ const TIER_ORDER = ['booster', 'haiku', 'sonnet', 'opus'];
26
+ /** Maximum cost per task across all tiers (used for normalization) */
27
+ const MAX_TIER_COST = TIER_COST_ESTIMATES.opus.costPerTask;
28
+ export const DEFAULT_ECONOMIC_CONFIG = {
29
+ qualityWeight: 0.6,
30
+ costWeight: 0.4,
31
+ budgetPerHourUsd: 0,
32
+ budgetPerDayUsd: 0,
33
+ minQualityThreshold: 0.5,
34
+ enabled: true,
35
+ };
36
+ // ============================================================================
37
+ // EconomicRoutingModel
38
+ // ============================================================================
39
+ /** EMA smoothing factor for quality estimate updates */
40
+ const EMA_ALPHA = 0.15;
41
+ export class EconomicRoutingModel {
42
+ config;
43
+ costTracker;
44
+ tierQualityEstimates = new Map();
45
+ tierOutcomeCounts = new Map();
46
+ constructor(costTracker, config) {
47
+ const merged = { ...DEFAULT_ECONOMIC_CONFIG, ...config };
48
+ // Validate and clamp config values to safe ranges
49
+ merged.qualityWeight = Math.max(0, Math.min(1, merged.qualityWeight));
50
+ merged.costWeight = Math.max(0, Math.min(1, merged.costWeight));
51
+ merged.minQualityThreshold = Math.max(0, Math.min(1, merged.minQualityThreshold));
52
+ merged.budgetPerHourUsd = Math.max(0, merged.budgetPerHourUsd);
53
+ merged.budgetPerDayUsd = Math.max(0, merged.budgetPerDayUsd);
54
+ // Normalize weights so they sum to 1.0
55
+ const weightSum = merged.qualityWeight + merged.costWeight;
56
+ if (weightSum > 0 && weightSum !== 1) {
57
+ merged.qualityWeight /= weightSum;
58
+ merged.costWeight /= weightSum;
59
+ }
60
+ this.config = merged;
61
+ this.costTracker = costTracker;
62
+ // Initialize with prior assumptions
63
+ this.tierQualityEstimates.set('booster', 0.3);
64
+ this.tierQualityEstimates.set('haiku', 0.55);
65
+ this.tierQualityEstimates.set('sonnet', 0.75);
66
+ this.tierQualityEstimates.set('opus', 0.90);
67
+ }
68
+ // --------------------------------------------------------------------------
69
+ // Core Methods
70
+ // --------------------------------------------------------------------------
71
+ /**
72
+ * Score each tier by quality-per-dollar efficiency.
73
+ * Returns all tiers sorted by economicScore descending.
74
+ */
75
+ scoreTiers(taskComplexity) {
76
+ const scores = TIER_ORDER.map(tier => {
77
+ const qualityScore = this.getQualityEstimate(tier, taskComplexity);
78
+ const estimatedCostUsd = TIER_COST_ESTIMATES[tier].costPerTask;
79
+ // quality / cost (handle zero-cost booster)
80
+ const qualityPerDollar = estimatedCostUsd > 0
81
+ ? qualityScore / estimatedCostUsd
82
+ : qualityScore > 0 ? Infinity : 0;
83
+ // Normalized cost efficiency: 1 - (cost / maxCost)
84
+ const costEfficiency = MAX_TIER_COST > 0
85
+ ? 1 - estimatedCostUsd / MAX_TIER_COST
86
+ : 1;
87
+ const economicScore = this.config.qualityWeight * qualityScore +
88
+ this.config.costWeight * costEfficiency;
89
+ return { tier, qualityScore, estimatedCostUsd, qualityPerDollar, economicScore };
90
+ });
91
+ scores.sort((a, b) => b.economicScore - a.economicScore);
92
+ return scores;
93
+ }
94
+ /**
95
+ * Select the best tier considering quality AND cost.
96
+ * Respects budget limits and minimum quality thresholds.
97
+ */
98
+ selectTier(taskComplexity) {
99
+ const scores = this.scoreTiers(taskComplexity);
100
+ for (const score of scores) {
101
+ // Skip tiers below minimum quality threshold
102
+ if (score.qualityScore < this.config.minQualityThreshold) {
103
+ continue;
104
+ }
105
+ // Skip tiers that would exceed budget
106
+ if (this.wouldExceedBudget(score.tier)) {
107
+ continue;
108
+ }
109
+ return {
110
+ tier: score.tier,
111
+ reason: `Best economic score (${score.economicScore.toFixed(3)}): ` +
112
+ `quality=${score.qualityScore.toFixed(2)}, cost=$${score.estimatedCostUsd.toFixed(4)}`,
113
+ scores,
114
+ };
115
+ }
116
+ // Fallback: pick the cheapest tier that meets quality, ignoring budget
117
+ // Use spread copies to avoid mutating the original scores array
118
+ const qualityFiltered = scores.filter(s => s.qualityScore >= this.config.minQualityThreshold);
119
+ if (qualityFiltered.length > 0) {
120
+ const cheapest = [...qualityFiltered].sort((a, b) => a.estimatedCostUsd - b.estimatedCostUsd)[0];
121
+ return {
122
+ tier: cheapest.tier,
123
+ reason: `Budget constrained fallback to ${cheapest.tier}`,
124
+ scores,
125
+ };
126
+ }
127
+ // Final fallback: pick the best quality regardless
128
+ const bestQuality = [...scores].sort((a, b) => b.qualityScore - a.qualityScore)[0];
129
+ return {
130
+ tier: bestQuality.tier,
131
+ reason: `No tier meets quality threshold ${this.config.minQualityThreshold}; ` +
132
+ `using best quality: ${bestQuality.tier}`,
133
+ scores,
134
+ };
135
+ }
136
+ /**
137
+ * Check if a tier would exceed the budget.
138
+ */
139
+ wouldExceedBudget(tier) {
140
+ const cost = TIER_COST_ESTIMATES[tier].costPerTask;
141
+ if (cost === 0)
142
+ return false;
143
+ const hourlyCost = this.costTracker.getCurrentCost('hour');
144
+ const dailyCost = this.costTracker.getCurrentCost('day');
145
+ if (this.config.budgetPerHourUsd > 0 &&
146
+ hourlyCost + cost > this.config.budgetPerHourUsd) {
147
+ return true;
148
+ }
149
+ if (this.config.budgetPerDayUsd > 0 &&
150
+ dailyCost + cost > this.config.budgetPerDayUsd) {
151
+ return true;
152
+ }
153
+ return false;
154
+ }
155
+ /**
156
+ * Update quality estimates from observed outcomes.
157
+ * Uses EMA to smooth estimates.
158
+ */
159
+ updateFromOutcome(outcome, tier) {
160
+ const observedQuality = outcome.outcome.qualityScore;
161
+ const current = this.tierQualityEstimates.get(tier) ?? 0.5;
162
+ const count = this.tierOutcomeCounts.get(tier) ?? 0;
163
+ // Use EMA; for the first few observations, use a higher alpha
164
+ const alpha = count < 5 ? 0.4 : EMA_ALPHA;
165
+ const updated = current * (1 - alpha) + observedQuality * alpha;
166
+ this.tierQualityEstimates.set(tier, updated);
167
+ this.tierOutcomeCounts.set(tier, count + 1);
168
+ }
169
+ /**
170
+ * Get economic efficiency report.
171
+ */
172
+ getEconomicReport() {
173
+ const tierEfficiency = this.scoreTiers(0.5); // mid-complexity as baseline
174
+ const currentHourlyCostUsd = this.costTracker.getCurrentCost('hour');
175
+ const currentDailyCostUsd = this.costTracker.getCurrentCost('day');
176
+ const budgetRemaining = {
177
+ hourly: this.config.budgetPerHourUsd > 0
178
+ ? Math.max(0, this.config.budgetPerHourUsd - currentHourlyCostUsd)
179
+ : null,
180
+ daily: this.config.budgetPerDayUsd > 0
181
+ ? Math.max(0, this.config.budgetPerDayUsd - currentDailyCostUsd)
182
+ : null,
183
+ };
184
+ // Find savings opportunity: compare most-used expensive tier vs cheaper alternative
185
+ let savingsOpportunity = null;
186
+ const sorted = [...tierEfficiency].sort((a, b) => b.qualityPerDollar - a.qualityPerDollar);
187
+ const mostEfficient = sorted.find(s => s.estimatedCostUsd > 0 && isFinite(s.qualityPerDollar));
188
+ const leastEfficient = [...sorted].reverse().find((s) => s.estimatedCostUsd > 0 && isFinite(s.qualityPerDollar));
189
+ if (mostEfficient && leastEfficient && mostEfficient.tier !== leastEfficient.tier) {
190
+ const potentialSavings = leastEfficient.estimatedCostUsd - mostEfficient.estimatedCostUsd;
191
+ if (potentialSavings > 0) {
192
+ savingsOpportunity = {
193
+ usd: potentialSavings,
194
+ description: `Switch from ${leastEfficient.tier} ($${leastEfficient.estimatedCostUsd.toFixed(4)}/task) ` +
195
+ `to ${mostEfficient.tier} ($${mostEfficient.estimatedCostUsd.toFixed(4)}/task) ` +
196
+ `for comparable tasks to save ~$${potentialSavings.toFixed(4)}/task`,
197
+ };
198
+ }
199
+ }
200
+ const recommendation = this.generateRecommendation(tierEfficiency, budgetRemaining);
201
+ return {
202
+ tierEfficiency,
203
+ currentHourlyCostUsd,
204
+ currentDailyCostUsd,
205
+ budgetRemaining,
206
+ recommendation,
207
+ savingsOpportunity,
208
+ };
209
+ }
210
+ /**
211
+ * Compute cost-adjusted reward for the neural router.
212
+ * Penalizes expensive tiers that don't deliver proportionally higher quality.
213
+ */
214
+ computeCostAdjustedReward(baseReward, tier, qualityScore) {
215
+ const tierCost = TIER_COST_ESTIMATES[tier].costPerTask;
216
+ if (MAX_TIER_COST === 0)
217
+ return baseReward;
218
+ const costRatio = tierCost / MAX_TIER_COST; // 0-1, where opus=1.0
219
+ const qualityGain = Math.max(0, qualityScore - this.config.minQualityThreshold);
220
+ const costPenalty = costRatio * (1 - qualityGain);
221
+ const adjusted = baseReward - costPenalty * this.config.costWeight;
222
+ // Clamp to [-1, 1]
223
+ return Math.max(-1, Math.min(1, adjusted));
224
+ }
225
+ // --------------------------------------------------------------------------
226
+ // Persistence helpers
227
+ // --------------------------------------------------------------------------
228
+ /**
229
+ * Serialize quality estimates for persistence.
230
+ */
231
+ serializeEstimates() {
232
+ const result = {};
233
+ for (const tier of TIER_ORDER) {
234
+ result[tier] = {
235
+ quality: this.tierQualityEstimates.get(tier) ?? 0.5,
236
+ count: this.tierOutcomeCounts.get(tier) ?? 0,
237
+ };
238
+ }
239
+ return result;
240
+ }
241
+ /**
242
+ * Deserialize quality estimates from persistence.
243
+ */
244
+ deserializeEstimates(data) {
245
+ for (const tier of TIER_ORDER) {
246
+ if (data[tier]) {
247
+ this.tierQualityEstimates.set(tier, data[tier].quality);
248
+ this.tierOutcomeCounts.set(tier, data[tier].count);
249
+ }
250
+ }
251
+ }
252
+ /**
253
+ * Get the current config (read-only copy).
254
+ */
255
+ getConfig() {
256
+ return { ...this.config };
257
+ }
258
+ // --------------------------------------------------------------------------
259
+ // Private helpers
260
+ // --------------------------------------------------------------------------
261
+ /**
262
+ * Get quality estimate for a tier, adjusted by task complexity.
263
+ * Higher complexity tasks benefit more from higher-tier models.
264
+ */
265
+ getQualityEstimate(tier, taskComplexity) {
266
+ const baseQuality = this.tierQualityEstimates.get(tier) ?? 0.5;
267
+ // For complex tasks, cheaper tiers degrade more
268
+ const complexityPenalty = tier === 'booster'
269
+ ? taskComplexity * 0.4
270
+ : tier === 'haiku'
271
+ ? taskComplexity * 0.2
272
+ : 0;
273
+ return Math.max(0, Math.min(1, baseQuality - complexityPenalty));
274
+ }
275
+ generateRecommendation(tierEfficiency, budgetRemaining) {
276
+ if (budgetRemaining.hourly !== null && budgetRemaining.hourly < 0.01) {
277
+ return 'Hourly budget nearly exhausted. Consider increasing budget or routing to cheaper tiers.';
278
+ }
279
+ if (budgetRemaining.daily !== null && budgetRemaining.daily < 0.1) {
280
+ return 'Daily budget nearly exhausted. Only critical tasks should use expensive tiers.';
281
+ }
282
+ const best = tierEfficiency[0];
283
+ if (best) {
284
+ return `Most cost-efficient tier: ${best.tier} ` +
285
+ `(score=${best.economicScore.toFixed(3)}, quality=${best.qualityScore.toFixed(2)})`;
286
+ }
287
+ return 'No economic data available yet.';
288
+ }
289
+ }
290
+ //# sourceMappingURL=economic-routing.js.map
@@ -16,6 +16,8 @@ export type { CoExecutionRecord, CoExecutionStats, } from './co-execution-reposi
16
16
  export { SignalMerger, createSignalMerger, DEFAULT_SIGNAL_MERGER_CONFIG, } from './signal-merger.js';
17
17
  export type { SignalSource, RoutingSignal, MergedAgentScore, SignalMergerConfig, } from './signal-merger.js';
18
18
  export { RoutingFeedbackCollector, createRoutingFeedbackCollector, } from './routing-feedback.js';
19
+ export { EconomicRoutingModel, TIER_COST_ESTIMATES, DEFAULT_ECONOMIC_CONFIG, } from './economic-routing.js';
20
+ export type { EconomicScore, EconomicRoutingConfig, EconomicReport, } from './economic-routing.js';
19
21
  export { classifyTask, isSimpleTask, requiresOpus, getRecommendedModel, getComplexityScore, COMPLEX_DOMAINS, MODERATE_DOMAINS, COMPLEX_CAPABILITIES, COMPLEXITY_THRESHOLDS, COMPLEXITY_TO_MODEL, } from './task-classifier.js';
20
22
  export type { TaskComplexity, ClaudeModel, ComplexityFactor, ClassificationResult, ClassifiableTask, } from './task-classifier.js';
21
23
  export { TinyDancerRouter, createTinyDancerRouter, createSmartTinyDancerRouter, } from './tiny-dancer-router.js';
@@ -18,6 +18,8 @@ export { CoExecutionRepository, getCoExecutionRepository, } from './co-execution
18
18
  export { SignalMerger, createSignalMerger, DEFAULT_SIGNAL_MERGER_CONFIG, } from './signal-merger.js';
19
19
  // Feedback
20
20
  export { RoutingFeedbackCollector, createRoutingFeedbackCollector, } from './routing-feedback.js';
21
+ // Economic Routing (Imp-18, Issue #334)
22
+ export { EconomicRoutingModel, TIER_COST_ESTIMATES, DEFAULT_ECONOMIC_CONFIG, } from './economic-routing.js';
21
23
  // Task Classifier (TD-002)
22
24
  export { classifyTask, isSimpleTask, requiresOpus, getRecommendedModel, getComplexityScore, COMPLEX_DOMAINS, MODERATE_DOMAINS, COMPLEX_CAPABILITIES, COMPLEXITY_THRESHOLDS, COMPLEXITY_TO_MODEL, } from './task-classifier.js';
23
25
  // TinyDancer Router (TD-003)
@@ -10,6 +10,8 @@ import type { QETaskRouter } from './qe-task-router.js';
10
10
  import { type EMAConfig } from './calibration/index.js';
11
11
  import { type EscalationConfig, type EscalationState } from './escalation/index.js';
12
12
  import type { RoutingConfig } from './routing-config.js';
13
+ import { type EconomicRoutingConfig, type EconomicScore, type EconomicReport } from './economic-routing.js';
14
+ import { CostTracker } from '../shared/llm/cost-tracker.js';
13
15
  /**
14
16
  * Collects and processes routing feedback for continuous learning
15
17
  */
@@ -19,6 +21,9 @@ export declare class RoutingFeedbackCollector {
19
21
  private db;
20
22
  private calibrator;
21
23
  private escalationTracker;
24
+ private economicModel;
25
+ private economicPersistCounter;
26
+ private static readonly ECONOMIC_PERSIST_INTERVAL;
22
27
  private persistCount;
23
28
  private readonly maxOutcomes;
24
29
  private static readonly RETENTION_CLEANUP_INTERVAL;
@@ -53,6 +58,14 @@ export declare class RoutingFeedbackCollector {
53
58
  * Persist EMA calibrator state to the database
54
59
  */
55
60
  private persistCalibratorState;
61
+ /**
62
+ * Load persisted economic routing state from the database
63
+ */
64
+ private loadEconomicState;
65
+ /**
66
+ * Persist economic routing state to the database
67
+ */
68
+ private persistEconomicState;
56
69
  /**
57
70
  * Connect to router for automatic performance updates
58
71
  */
@@ -77,6 +90,22 @@ export declare class RoutingFeedbackCollector {
77
90
  * Returns null if auto-escalation is not enabled or agent has no state.
78
91
  */
79
92
  getEscalationState(agentId: string): EscalationState | null;
93
+ /**
94
+ * Enable economic routing model for quality-weighted cost optimization.
95
+ * Once enabled, every recorded outcome feeds economic quality estimates
96
+ * and the neural router receives cost-adjusted rewards.
97
+ */
98
+ enableEconomicRouting(config?: Partial<EconomicRoutingConfig>, costTracker?: CostTracker): void;
99
+ /**
100
+ * Get the economic routing report.
101
+ * Returns null if economic routing is not enabled.
102
+ */
103
+ getEconomicReport(): EconomicReport | null;
104
+ /**
105
+ * Get economic scores for a given task complexity.
106
+ * Returns null if economic routing is not enabled.
107
+ */
108
+ getEconomicScore(taskComplexity: number): EconomicScore[] | null;
80
109
  /**
81
110
  * Record a routing outcome
82
111
  */
@@ -12,6 +12,8 @@ import { safeJsonParse } from '../shared/safe-json.js';
12
12
  import { toErrorMessage } from '../shared/error-utils.js';
13
13
  import { EMACalibrator } from './calibration/index.js';
14
14
  import { AutoEscalationTracker } from './escalation/index.js';
15
+ import { EconomicRoutingModel, } from './economic-routing.js';
16
+ import { getGlobalCostTracker } from '../shared/llm/cost-tracker.js';
15
17
  // ============================================================================
16
18
  // In-Memory Storage (can be replaced with SQLite)
17
19
  // ============================================================================
@@ -64,6 +66,9 @@ export class RoutingFeedbackCollector {
64
66
  db = null;
65
67
  calibrator = null;
66
68
  escalationTracker = null;
69
+ economicModel = null;
70
+ economicPersistCounter = 0;
71
+ static ECONOMIC_PERSIST_INTERVAL = 10;
67
72
  persistCount = 0;
68
73
  maxOutcomes;
69
74
  static RETENTION_CLEANUP_INTERVAL = 100;
@@ -229,6 +234,42 @@ export class RoutingFeedbackCollector {
229
234
  console.warn('[RoutingFeedbackCollector] Failed to persist calibrator state:', toErrorMessage(error));
230
235
  }
231
236
  }
237
+ /**
238
+ * Load persisted economic routing state from the database
239
+ */
240
+ loadEconomicState() {
241
+ if (!this.db || !this.economicModel)
242
+ return;
243
+ try {
244
+ const database = this.db.getDatabase();
245
+ const row = database.prepare(`SELECT value FROM kv_store WHERE key = 'routing:economic_quality_estimates'`).get();
246
+ if (row) {
247
+ const data = safeJsonParse(row.value);
248
+ if (data && typeof data === 'object') {
249
+ this.economicModel.deserializeEstimates(data);
250
+ console.log('[RoutingFeedbackCollector] Loaded economic quality estimates from DB');
251
+ }
252
+ }
253
+ }
254
+ catch (error) {
255
+ console.warn('[RoutingFeedbackCollector] Failed to load economic state:', toErrorMessage(error));
256
+ }
257
+ }
258
+ /**
259
+ * Persist economic routing state to the database
260
+ */
261
+ persistEconomicState() {
262
+ if (!this.db || !this.economicModel)
263
+ return;
264
+ try {
265
+ const database = this.db.getDatabase();
266
+ const serialized = JSON.stringify(this.economicModel.serializeEstimates());
267
+ database.prepare(`INSERT OR REPLACE INTO kv_store (key, value, updated_at) VALUES (?, ?, datetime('now'))`).run('routing:economic_quality_estimates', serialized);
268
+ }
269
+ catch (error) {
270
+ console.warn('[RoutingFeedbackCollector] Failed to persist economic state:', toErrorMessage(error));
271
+ }
272
+ }
232
273
  /**
233
274
  * Connect to router for automatic performance updates
234
275
  */
@@ -263,6 +304,30 @@ export class RoutingFeedbackCollector {
263
304
  getEscalationState(agentId) {
264
305
  return this.escalationTracker?.getState(agentId) ?? null;
265
306
  }
307
+ /**
308
+ * Enable economic routing model for quality-weighted cost optimization.
309
+ * Once enabled, every recorded outcome feeds economic quality estimates
310
+ * and the neural router receives cost-adjusted rewards.
311
+ */
312
+ enableEconomicRouting(config, costTracker) {
313
+ const tracker = costTracker ?? getGlobalCostTracker();
314
+ this.economicModel = new EconomicRoutingModel(tracker, config);
315
+ this.loadEconomicState();
316
+ }
317
+ /**
318
+ * Get the economic routing report.
319
+ * Returns null if economic routing is not enabled.
320
+ */
321
+ getEconomicReport() {
322
+ return this.economicModel?.getEconomicReport() ?? null;
323
+ }
324
+ /**
325
+ * Get economic scores for a given task complexity.
326
+ * Returns null if economic routing is not enabled.
327
+ */
328
+ getEconomicScore(taskComplexity) {
329
+ return this.economicModel?.scoreTiers(taskComplexity) ?? null;
330
+ }
266
331
  /**
267
332
  * Record a routing outcome
268
333
  */
@@ -301,6 +366,16 @@ export class RoutingFeedbackCollector {
301
366
  `${escalationAction.previousTier} → ${escalationAction.newTier}`);
302
367
  }
303
368
  }
369
+ // Update economic model if enabled
370
+ if (this.economicModel) {
371
+ const tier = this.inferTier(usedAgent);
372
+ this.economicModel.updateFromOutcome(routingOutcome, tier);
373
+ // Persist economic state periodically
374
+ this.economicPersistCounter++;
375
+ if (this.economicPersistCounter % RoutingFeedbackCollector.ECONOMIC_PERSIST_INTERVAL === 0) {
376
+ this.persistEconomicState();
377
+ }
378
+ }
304
379
  return routingOutcome;
305
380
  }
306
381
  /**
@@ -2,4 +2,5 @@ export * from './circular-buffer.js';
2
2
  export * from './vector-math.js';
3
3
  export * from './binary-insert.js';
4
4
  export * from './crypto-random.js';
5
+ export { Xorshift128 } from './xorshift128.js';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,5 @@ export * from './circular-buffer.js';
2
2
  export * from './vector-math.js';
3
3
  export * from './binary-insert.js';
4
4
  export * from './crypto-random.js';
5
+ export { Xorshift128 } from './xorshift128.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Xorshift128 PRNG — Deterministic pseudo-random number generator
3
+ *
4
+ * Seeded xorshift128 producing repeatable sequences for use in
5
+ * fingerprinting, graph training, weight initialization, and
6
+ * any context requiring deterministic randomness.
7
+ *
8
+ * @module shared/utils/xorshift128
9
+ */
10
+ export declare class Xorshift128 {
11
+ private s0;
12
+ private s1;
13
+ private s2;
14
+ private s3;
15
+ constructor(seed: number);
16
+ private splitmix32;
17
+ /** Returns a raw unsigned 32-bit integer */
18
+ next(): number;
19
+ /** Returns a float in [0, 1) */
20
+ nextFloat(): number;
21
+ /** Returns a standard normal variate via Box-Muller transform */
22
+ nextGaussian(): number;
23
+ }
24
+ //# sourceMappingURL=xorshift128.d.ts.map
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Xorshift128 PRNG — Deterministic pseudo-random number generator
3
+ *
4
+ * Seeded xorshift128 producing repeatable sequences for use in
5
+ * fingerprinting, graph training, weight initialization, and
6
+ * any context requiring deterministic randomness.
7
+ *
8
+ * @module shared/utils/xorshift128
9
+ */
10
+ export class Xorshift128 {
11
+ s0;
12
+ s1;
13
+ s2;
14
+ s3;
15
+ constructor(seed) {
16
+ this.s0 = this.splitmix32(seed);
17
+ this.s1 = this.splitmix32(this.s0);
18
+ this.s2 = this.splitmix32(this.s1);
19
+ this.s3 = this.splitmix32(this.s2);
20
+ }
21
+ splitmix32(state) {
22
+ state = (state + 0x9e3779b9) | 0;
23
+ state = Math.imul(state ^ (state >>> 16), 0x85ebca6b);
24
+ state = Math.imul(state ^ (state >>> 13), 0xc2b2ae35);
25
+ return (state ^ (state >>> 16)) >>> 0;
26
+ }
27
+ /** Returns a raw unsigned 32-bit integer */
28
+ next() {
29
+ const t = this.s3;
30
+ let s = this.s0;
31
+ this.s3 = this.s2;
32
+ this.s2 = this.s1;
33
+ this.s1 = s;
34
+ s ^= s << 11;
35
+ s ^= s >>> 8;
36
+ this.s0 = s ^ t ^ (t >>> 19);
37
+ return this.s0 >>> 0;
38
+ }
39
+ /** Returns a float in [0, 1) */
40
+ nextFloat() {
41
+ return this.next() / 0x100000000;
42
+ }
43
+ /** Returns a standard normal variate via Box-Muller transform */
44
+ nextGaussian() {
45
+ const u1 = this.nextFloat() || 1e-10;
46
+ const u2 = this.nextFloat();
47
+ return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
48
+ }
49
+ }
50
+ //# sourceMappingURL=xorshift128.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-qe",
3
- "version": "3.8.10",
3
+ "version": "3.8.12",
4
4
  "description": "Agentic Quality Engineering V3 - Domain-Driven Design Architecture with 13 Bounded Contexts, O(log n) coverage analysis, ReasoningBank learning, 60 specialized QE agents, mathematical Coherence verification, deep Claude Flow integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",