agentic-qe 3.7.21 → 3.8.0

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 (164) hide show
  1. package/.claude/helpers/brain-checkpoint.cjs +4 -1
  2. package/.claude/helpers/statusline-v3.cjs +3 -1
  3. package/.claude/skills/skills-manifest.json +1 -1
  4. package/CHANGELOG.md +45 -0
  5. package/README.md +2 -14
  6. package/assets/helpers/statusline-v3.cjs +3 -1
  7. package/dist/cli/brain-commands.js +6 -10
  8. package/dist/cli/bundle.js +7441 -4327
  9. package/dist/cli/commands/audit.d.ts +43 -0
  10. package/dist/cli/commands/audit.js +125 -0
  11. package/dist/cli/commands/hooks.js +29 -6
  12. package/dist/cli/commands/init.js +1 -73
  13. package/dist/cli/commands/learning.js +270 -13
  14. package/dist/cli/commands/ruvector-commands.d.ts +15 -0
  15. package/dist/cli/commands/ruvector-commands.js +271 -0
  16. package/dist/cli/handlers/init-handler.d.ts +0 -1
  17. package/dist/cli/handlers/init-handler.js +0 -6
  18. package/dist/cli/index.js +4 -2
  19. package/dist/context/sources/defect-source.js +2 -2
  20. package/dist/context/sources/memory-source.js +2 -2
  21. package/dist/context/sources/requirements-source.js +2 -2
  22. package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
  23. package/dist/coordination/behavior-tree/decorators.js +251 -0
  24. package/dist/coordination/behavior-tree/index.d.ts +12 -0
  25. package/dist/coordination/behavior-tree/index.js +15 -0
  26. package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
  27. package/dist/coordination/behavior-tree/nodes.js +338 -0
  28. package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
  29. package/dist/coordination/behavior-tree/qe-trees.js +181 -0
  30. package/dist/coordination/coherence-action-gate.d.ts +284 -0
  31. package/dist/coordination/coherence-action-gate.js +512 -0
  32. package/dist/coordination/index.d.ts +4 -0
  33. package/dist/coordination/index.js +8 -0
  34. package/dist/coordination/reasoning-qec.d.ts +315 -0
  35. package/dist/coordination/reasoning-qec.js +585 -0
  36. package/dist/coordination/task-executor.d.ts +16 -0
  37. package/dist/coordination/task-executor.js +99 -0
  38. package/dist/coordination/workflow-orchestrator.d.ts +29 -0
  39. package/dist/coordination/workflow-orchestrator.js +42 -0
  40. package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
  41. package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
  42. package/dist/domains/visual-accessibility/index.d.ts +1 -0
  43. package/dist/domains/visual-accessibility/index.js +4 -0
  44. package/dist/governance/coherence-validator.d.ts +112 -0
  45. package/dist/governance/coherence-validator.js +180 -0
  46. package/dist/governance/index.d.ts +1 -0
  47. package/dist/governance/index.js +2 -0
  48. package/dist/governance/witness-chain.d.ts +311 -0
  49. package/dist/governance/witness-chain.js +509 -0
  50. package/dist/init/index.d.ts +0 -2
  51. package/dist/init/index.js +0 -1
  52. package/dist/init/init-wizard-steps.d.ts +10 -0
  53. package/dist/init/init-wizard-steps.js +87 -1
  54. package/dist/init/init-wizard.d.ts +1 -9
  55. package/dist/init/init-wizard.js +3 -69
  56. package/dist/init/orchestrator.js +0 -1
  57. package/dist/init/phases/01-detection.js +0 -27
  58. package/dist/init/phases/07-hooks.js +6 -4
  59. package/dist/init/phases/phase-interface.d.ts +0 -1
  60. package/dist/init/settings-merge.js +1 -1
  61. package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
  62. package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
  63. package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
  64. package/dist/integrations/browser/qe-dashboard/index.js +15 -0
  65. package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
  66. package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
  67. package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
  68. package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
  69. package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
  70. package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
  71. package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
  72. package/dist/integrations/ruvector/cognitive-container.js +306 -0
  73. package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
  74. package/dist/integrations/ruvector/coherence-gate.js +631 -0
  75. package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
  76. package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
  77. package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
  78. package/dist/integrations/ruvector/dither-adapter.js +295 -0
  79. package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
  80. package/dist/integrations/ruvector/domain-transfer.js +220 -0
  81. package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
  82. package/dist/integrations/ruvector/feature-flags.js +167 -2
  83. package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
  84. package/dist/integrations/ruvector/filter-adapter.js +285 -0
  85. package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
  86. package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
  87. package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
  88. package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
  89. package/dist/integrations/ruvector/index.d.ts +8 -2
  90. package/dist/integrations/ruvector/index.js +18 -2
  91. package/dist/integrations/ruvector/interfaces.d.ts +40 -0
  92. package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
  93. package/dist/integrations/ruvector/sona-persistence.js +162 -0
  94. package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
  95. package/dist/integrations/ruvector/sona-three-loop.js +814 -0
  96. package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
  97. package/dist/integrations/ruvector/sona-wrapper.js +147 -3
  98. package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
  99. package/dist/integrations/ruvector/spectral-math.js +254 -0
  100. package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
  101. package/dist/integrations/ruvector/temporal-compression.js +318 -0
  102. package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
  103. package/dist/integrations/ruvector/thompson-sampler.js +118 -0
  104. package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
  105. package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
  106. package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
  107. package/dist/integrations/ruvector/transfer-verification.js +115 -0
  108. package/dist/kernel/hnsw-adapter.d.ts +52 -1
  109. package/dist/kernel/hnsw-adapter.js +139 -4
  110. package/dist/kernel/hnsw-index-provider.d.ts +5 -0
  111. package/dist/kernel/native-hnsw-backend.d.ts +110 -0
  112. package/dist/kernel/native-hnsw-backend.js +408 -0
  113. package/dist/kernel/unified-memory.js +5 -6
  114. package/dist/learning/aqe-learning-engine.d.ts +2 -0
  115. package/dist/learning/aqe-learning-engine.js +65 -0
  116. package/dist/learning/experience-capture-middleware.js +20 -0
  117. package/dist/learning/experience-capture.d.ts +10 -0
  118. package/dist/learning/experience-capture.js +34 -0
  119. package/dist/learning/index.d.ts +2 -2
  120. package/dist/learning/index.js +4 -4
  121. package/dist/learning/metrics-tracker.d.ts +11 -0
  122. package/dist/learning/metrics-tracker.js +29 -13
  123. package/dist/learning/pattern-lifecycle.d.ts +30 -1
  124. package/dist/learning/pattern-lifecycle.js +92 -20
  125. package/dist/learning/pattern-store.d.ts +8 -0
  126. package/dist/learning/pattern-store.js +8 -2
  127. package/dist/learning/qe-unified-memory.js +1 -28
  128. package/dist/learning/regret-tracker.d.ts +201 -0
  129. package/dist/learning/regret-tracker.js +361 -0
  130. package/dist/mcp/bundle.js +5915 -474
  131. package/dist/routing/index.d.ts +4 -2
  132. package/dist/routing/index.js +3 -1
  133. package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
  134. package/dist/routing/neural-tiny-dancer-router.js +514 -0
  135. package/dist/routing/queen-integration.js +5 -5
  136. package/dist/routing/routing-config.d.ts +6 -0
  137. package/dist/routing/routing-config.js +1 -0
  138. package/dist/routing/simple-neural-router.d.ts +76 -0
  139. package/dist/routing/simple-neural-router.js +202 -0
  140. package/dist/routing/tiny-dancer-router.d.ts +20 -1
  141. package/dist/routing/tiny-dancer-router.js +21 -2
  142. package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
  143. package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
  144. package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
  145. package/dist/test-scheduling/dag-attention-types.js +10 -0
  146. package/dist/test-scheduling/index.d.ts +1 -0
  147. package/dist/test-scheduling/index.js +4 -0
  148. package/dist/test-scheduling/pipeline.d.ts +8 -0
  149. package/dist/test-scheduling/pipeline.js +28 -0
  150. package/package.json +6 -2
  151. package/dist/cli/commands/migrate.d.ts +0 -9
  152. package/dist/cli/commands/migrate.js +0 -566
  153. package/dist/init/init-wizard-migration.d.ts +0 -52
  154. package/dist/init/init-wizard-migration.js +0 -345
  155. package/dist/init/migration/config-migrator.d.ts +0 -31
  156. package/dist/init/migration/config-migrator.js +0 -149
  157. package/dist/init/migration/data-migrator.d.ts +0 -72
  158. package/dist/init/migration/data-migrator.js +0 -232
  159. package/dist/init/migration/detector.d.ts +0 -44
  160. package/dist/init/migration/detector.js +0 -105
  161. package/dist/init/migration/index.d.ts +0 -8
  162. package/dist/init/migration/index.js +0 -8
  163. package/dist/learning/v2-to-v3-migration.d.ts +0 -86
  164. package/dist/learning/v2-to-v3-migration.js +0 -529
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Agentic QE v3 - Regret Tracker
3
+ * Task 2.4: Regret Tracking and Learning Health Dashboard
4
+ *
5
+ * Tracks cumulative regret per domain over time to determine whether
6
+ * QE agents are actually learning. Uses log-log regression on the
7
+ * regret curve to classify growth rate:
8
+ *
9
+ * - Sublinear: R(n) ~ n^alpha where alpha < 1 (learning is happening)
10
+ * - Linear: R(n) ~ n (stagnation, needs intervention)
11
+ * - Superlinear: R(n) ~ n^alpha where alpha > 1 (getting worse)
12
+ *
13
+ * @module learning/regret-tracker
14
+ */
15
+ /** A single point on the regret curve */
16
+ export interface RegretPoint {
17
+ /** Number of decisions made so far */
18
+ decisionCount: number;
19
+ /** Cumulative regret at this point */
20
+ cumulativeRegret: number;
21
+ /** Timestamp when this decision was recorded */
22
+ timestamp: number;
23
+ }
24
+ /** Growth rate classification for a domain's regret curve */
25
+ export type GrowthRate = 'sublinear' | 'linear' | 'superlinear' | 'insufficient_data';
26
+ /** Health summary for a single domain */
27
+ export interface DomainHealthSummary {
28
+ /** Domain identifier */
29
+ domain: string;
30
+ /** Total number of decisions recorded */
31
+ totalDecisions: number;
32
+ /** Current cumulative regret */
33
+ cumulativeRegret: number;
34
+ /** Growth rate classification */
35
+ growthRate: GrowthRate;
36
+ /** Whether stagnation has been detected */
37
+ stagnating: boolean;
38
+ /** Log-log slope (undefined if insufficient data) */
39
+ slope: number | undefined;
40
+ /** Average regret per decision (recent window) */
41
+ recentAvgRegret: number;
42
+ }
43
+ /** Alert emitted when a domain's regret growth rate changes */
44
+ export interface RegretAlert {
45
+ /** Domain that triggered the alert */
46
+ domain: string;
47
+ /** Previous growth rate */
48
+ previousRate: GrowthRate;
49
+ /** New growth rate */
50
+ newRate: GrowthRate;
51
+ /** Timestamp of the alert */
52
+ timestamp: number;
53
+ /** Human-readable message */
54
+ message: string;
55
+ }
56
+ /** Callback for regret alerts */
57
+ export type RegretAlertCallback = (alert: RegretAlert) => void;
58
+ /**
59
+ * Compute the slope of a simple linear regression (y = mx + b).
60
+ *
61
+ * Uses the ordinary least squares formula:
62
+ * m = (n * sum(xy) - sum(x) * sum(y)) / (n * sum(x^2) - (sum(x))^2)
63
+ *
64
+ * @param xs - Independent variable values
65
+ * @param ys - Dependent variable values
66
+ * @returns Slope of the regression line
67
+ */
68
+ export declare function linearRegressionSlope(xs: number[], ys: number[]): number;
69
+ /**
70
+ * Tracks cumulative regret per domain to assess whether QE agents
71
+ * are learning over time. Regret_i = optimal_reward - actual_reward.
72
+ * R(n) = sum of regret_i for i=1..n. Sublinear R(n) ~ n^alpha (alpha < 1)
73
+ * indicates learning; linear or superlinear indicates stagnation.
74
+ */
75
+ export declare class RegretTracker {
76
+ /** Per-domain regret tracking state */
77
+ private domains;
78
+ /** Alert callbacks */
79
+ private alertCallbacks;
80
+ /** Historical alerts for review */
81
+ private alerts;
82
+ /** Maximum number of alerts to retain */
83
+ private readonly maxAlerts;
84
+ /** Window size for recent average regret calculation */
85
+ private readonly recentWindow;
86
+ constructor(options?: {
87
+ maxAlerts?: number;
88
+ recentWindow?: number;
89
+ });
90
+ /**
91
+ * Record a decision outcome for regret tracking.
92
+ *
93
+ * @param domain - The QE domain (e.g. 'test-generation', 'coverage-analysis')
94
+ * @param reward - The actual reward received (0 to 1)
95
+ * @param optimalReward - The best possible reward (0 to 1)
96
+ */
97
+ recordDecision(domain: string, reward: number, optimalReward: number): void;
98
+ /**
99
+ * Get the current cumulative regret for a domain.
100
+ *
101
+ * @param domain - Domain identifier
102
+ * @returns Cumulative regret, or 0 if domain not tracked
103
+ */
104
+ getCumulativeRegret(domain: string): number;
105
+ /**
106
+ * Get the full regret curve for a domain.
107
+ *
108
+ * @param domain - Domain identifier
109
+ * @returns Array of regret data points, or empty array if not tracked
110
+ */
111
+ getRegretCurve(domain: string): RegretPoint[];
112
+ /**
113
+ * Classify the growth rate of cumulative regret for a domain.
114
+ *
115
+ * Uses log-log linear regression: if R(n) ~ n^alpha, then
116
+ * log(R) ~ alpha * log(n), so the slope of log(R) vs log(n)
117
+ * gives us alpha.
118
+ *
119
+ * @param domain - Domain identifier
120
+ * @returns Growth rate classification
121
+ */
122
+ getRegretGrowthRate(domain: string): GrowthRate;
123
+ /**
124
+ * Detect whether a domain is stagnating (linear or superlinear regret growth).
125
+ *
126
+ * @param domain - Domain identifier
127
+ * @returns true if the domain shows stagnation
128
+ */
129
+ detectStagnation(domain: string): boolean;
130
+ /**
131
+ * Get a health summary for all tracked domains.
132
+ *
133
+ * @returns Array of domain health summaries, sorted by domain name
134
+ */
135
+ getHealthSummary(): DomainHealthSummary[];
136
+ /**
137
+ * Register a callback for regret growth rate transition alerts.
138
+ *
139
+ * @param callback - Function to call when a growth rate transition occurs
140
+ */
141
+ onAlert(callback: RegretAlertCallback): void;
142
+ /**
143
+ * Get all historical alerts.
144
+ *
145
+ * @returns Array of past alerts
146
+ */
147
+ getAlerts(): RegretAlert[];
148
+ /**
149
+ * Get list of all tracked domains.
150
+ */
151
+ getTrackedDomains(): string[];
152
+ /**
153
+ * Get the total number of decisions across all domains.
154
+ */
155
+ getTotalDecisions(): number;
156
+ /**
157
+ * Reset tracking data for a specific domain (or all domains).
158
+ *
159
+ * @param domain - Domain to reset, or undefined to reset all
160
+ */
161
+ reset(domain?: string): void;
162
+ /**
163
+ * Get or create domain tracking state.
164
+ */
165
+ private getOrCreateDomainState;
166
+ /**
167
+ * Classify the growth rate of a regret curve using log-log regression.
168
+ *
169
+ * @param points - Regret data points
170
+ * @returns Growth rate classification
171
+ */
172
+ private classifyGrowthRate;
173
+ /**
174
+ * Compute the slope of log(regret) vs log(n) for the regret curve.
175
+ *
176
+ * Filters out points where cumulative regret is zero (log(0) is undefined).
177
+ *
178
+ * @param points - Regret data points
179
+ * @returns Slope value, or undefined if insufficient valid data
180
+ */
181
+ private computeLogLogSlope;
182
+ /**
183
+ * Compute the average per-decision regret over the recent window.
184
+ */
185
+ private computeRecentAvgRegret;
186
+ /**
187
+ * Emit a growth rate transition alert.
188
+ */
189
+ private emitAlert;
190
+ }
191
+ /**
192
+ * Create a new RegretTracker instance.
193
+ *
194
+ * @param options - Optional configuration
195
+ * @returns New RegretTracker
196
+ */
197
+ export declare function createRegretTracker(options?: {
198
+ maxAlerts?: number;
199
+ recentWindow?: number;
200
+ }): RegretTracker;
201
+ //# sourceMappingURL=regret-tracker.d.ts.map
@@ -0,0 +1,361 @@
1
+ /**
2
+ * Agentic QE v3 - Regret Tracker
3
+ * Task 2.4: Regret Tracking and Learning Health Dashboard
4
+ *
5
+ * Tracks cumulative regret per domain over time to determine whether
6
+ * QE agents are actually learning. Uses log-log regression on the
7
+ * regret curve to classify growth rate:
8
+ *
9
+ * - Sublinear: R(n) ~ n^alpha where alpha < 1 (learning is happening)
10
+ * - Linear: R(n) ~ n (stagnation, needs intervention)
11
+ * - Superlinear: R(n) ~ n^alpha where alpha > 1 (getting worse)
12
+ *
13
+ * @module learning/regret-tracker
14
+ */
15
+ import { LoggerFactory } from '../logging/index.js';
16
+ const logger = LoggerFactory.create('regret-tracker');
17
+ // ============================================================================
18
+ // Constants
19
+ // ============================================================================
20
+ /** Minimum data points required for reliable growth rate classification */
21
+ const MIN_DATA_POINTS_FOR_CLASSIFICATION = 50;
22
+ /** Slope threshold below which growth is classified as sublinear */
23
+ const SUBLINEAR_THRESHOLD = 0.9;
24
+ /** Slope threshold above which growth is classified as superlinear */
25
+ const SUPERLINEAR_THRESHOLD = 1.1;
26
+ // ============================================================================
27
+ // Linear Regression Helper
28
+ // ============================================================================
29
+ /**
30
+ * Compute the slope of a simple linear regression (y = mx + b).
31
+ *
32
+ * Uses the ordinary least squares formula:
33
+ * m = (n * sum(xy) - sum(x) * sum(y)) / (n * sum(x^2) - (sum(x))^2)
34
+ *
35
+ * @param xs - Independent variable values
36
+ * @param ys - Dependent variable values
37
+ * @returns Slope of the regression line
38
+ */
39
+ export function linearRegressionSlope(xs, ys) {
40
+ const n = xs.length;
41
+ if (n < 2)
42
+ return 0;
43
+ let sumX = 0;
44
+ let sumY = 0;
45
+ let sumXY = 0;
46
+ let sumX2 = 0;
47
+ for (let i = 0; i < n; i++) {
48
+ sumX += xs[i];
49
+ sumY += ys[i];
50
+ sumXY += xs[i] * ys[i];
51
+ sumX2 += xs[i] * xs[i];
52
+ }
53
+ const denominator = n * sumX2 - sumX * sumX;
54
+ if (Math.abs(denominator) < 1e-10)
55
+ return 0;
56
+ return (n * sumXY - sumX * sumY) / denominator;
57
+ }
58
+ // ============================================================================
59
+ // RegretTracker
60
+ // ============================================================================
61
+ /**
62
+ * Tracks cumulative regret per domain to assess whether QE agents
63
+ * are learning over time. Regret_i = optimal_reward - actual_reward.
64
+ * R(n) = sum of regret_i for i=1..n. Sublinear R(n) ~ n^alpha (alpha < 1)
65
+ * indicates learning; linear or superlinear indicates stagnation.
66
+ */
67
+ export class RegretTracker {
68
+ /** Per-domain regret tracking state */
69
+ domains = new Map();
70
+ /** Alert callbacks */
71
+ alertCallbacks = [];
72
+ /** Historical alerts for review */
73
+ alerts = [];
74
+ /** Maximum number of alerts to retain */
75
+ maxAlerts;
76
+ /** Window size for recent average regret calculation */
77
+ recentWindow;
78
+ constructor(options) {
79
+ this.maxAlerts = options?.maxAlerts ?? 100;
80
+ this.recentWindow = options?.recentWindow ?? 20;
81
+ }
82
+ // ==========================================================================
83
+ // Core Recording
84
+ // ==========================================================================
85
+ /**
86
+ * Record a decision outcome for regret tracking.
87
+ *
88
+ * @param domain - The QE domain (e.g. 'test-generation', 'coverage-analysis')
89
+ * @param reward - The actual reward received (0 to 1)
90
+ * @param optimalReward - The best possible reward (0 to 1)
91
+ */
92
+ recordDecision(domain, reward, optimalReward) {
93
+ const state = this.getOrCreateDomainState(domain);
94
+ const regret = Math.max(0, optimalReward - reward);
95
+ state.cumulativeRegret += regret;
96
+ state.decisionCount++;
97
+ state.points.push({
98
+ decisionCount: state.decisionCount,
99
+ cumulativeRegret: state.cumulativeRegret,
100
+ timestamp: Date.now(),
101
+ });
102
+ // Check for growth rate transitions after enough data
103
+ if (state.decisionCount >= MIN_DATA_POINTS_FOR_CLASSIFICATION) {
104
+ const currentRate = this.classifyGrowthRate(state.points);
105
+ if (state.lastGrowthRate !== 'insufficient_data' &&
106
+ currentRate !== state.lastGrowthRate) {
107
+ this.emitAlert(domain, state.lastGrowthRate, currentRate);
108
+ }
109
+ state.lastGrowthRate = currentRate;
110
+ }
111
+ }
112
+ // ==========================================================================
113
+ // Regret Queries
114
+ // ==========================================================================
115
+ /**
116
+ * Get the current cumulative regret for a domain.
117
+ *
118
+ * @param domain - Domain identifier
119
+ * @returns Cumulative regret, or 0 if domain not tracked
120
+ */
121
+ getCumulativeRegret(domain) {
122
+ const state = this.domains.get(domain);
123
+ return state?.cumulativeRegret ?? 0;
124
+ }
125
+ /**
126
+ * Get the full regret curve for a domain.
127
+ *
128
+ * @param domain - Domain identifier
129
+ * @returns Array of regret data points, or empty array if not tracked
130
+ */
131
+ getRegretCurve(domain) {
132
+ const state = this.domains.get(domain);
133
+ if (!state)
134
+ return [];
135
+ return [...state.points];
136
+ }
137
+ /**
138
+ * Classify the growth rate of cumulative regret for a domain.
139
+ *
140
+ * Uses log-log linear regression: if R(n) ~ n^alpha, then
141
+ * log(R) ~ alpha * log(n), so the slope of log(R) vs log(n)
142
+ * gives us alpha.
143
+ *
144
+ * @param domain - Domain identifier
145
+ * @returns Growth rate classification
146
+ */
147
+ getRegretGrowthRate(domain) {
148
+ const state = this.domains.get(domain);
149
+ if (!state)
150
+ return 'insufficient_data';
151
+ return this.classifyGrowthRate(state.points);
152
+ }
153
+ /**
154
+ * Detect whether a domain is stagnating (linear or superlinear regret growth).
155
+ *
156
+ * @param domain - Domain identifier
157
+ * @returns true if the domain shows stagnation
158
+ */
159
+ detectStagnation(domain) {
160
+ const rate = this.getRegretGrowthRate(domain);
161
+ return rate === 'linear' || rate === 'superlinear';
162
+ }
163
+ // ==========================================================================
164
+ // Health Dashboard
165
+ // ==========================================================================
166
+ /**
167
+ * Get a health summary for all tracked domains.
168
+ *
169
+ * @returns Array of domain health summaries, sorted by domain name
170
+ */
171
+ getHealthSummary() {
172
+ const summaries = [];
173
+ for (const [domain, state] of this.domains) {
174
+ const growthRate = this.classifyGrowthRate(state.points);
175
+ const slope = this.computeLogLogSlope(state.points);
176
+ // Compute recent average regret
177
+ const recentAvgRegret = this.computeRecentAvgRegret(state);
178
+ summaries.push({
179
+ domain,
180
+ totalDecisions: state.decisionCount,
181
+ cumulativeRegret: state.cumulativeRegret,
182
+ growthRate,
183
+ stagnating: growthRate === 'linear' || growthRate === 'superlinear',
184
+ slope,
185
+ recentAvgRegret,
186
+ });
187
+ }
188
+ // Sort alphabetically by domain
189
+ summaries.sort((a, b) => a.domain.localeCompare(b.domain));
190
+ return summaries;
191
+ }
192
+ // ==========================================================================
193
+ // Alert System
194
+ // ==========================================================================
195
+ /**
196
+ * Register a callback for regret growth rate transition alerts.
197
+ *
198
+ * @param callback - Function to call when a growth rate transition occurs
199
+ */
200
+ onAlert(callback) {
201
+ this.alertCallbacks.push(callback);
202
+ }
203
+ /**
204
+ * Get all historical alerts.
205
+ *
206
+ * @returns Array of past alerts
207
+ */
208
+ getAlerts() {
209
+ return [...this.alerts];
210
+ }
211
+ // ==========================================================================
212
+ // Accessors
213
+ // ==========================================================================
214
+ /**
215
+ * Get list of all tracked domains.
216
+ */
217
+ getTrackedDomains() {
218
+ return [...this.domains.keys()].sort();
219
+ }
220
+ /**
221
+ * Get the total number of decisions across all domains.
222
+ */
223
+ getTotalDecisions() {
224
+ let total = 0;
225
+ for (const state of this.domains.values()) {
226
+ total += state.decisionCount;
227
+ }
228
+ return total;
229
+ }
230
+ /**
231
+ * Reset tracking data for a specific domain (or all domains).
232
+ *
233
+ * @param domain - Domain to reset, or undefined to reset all
234
+ */
235
+ reset(domain) {
236
+ if (domain) {
237
+ this.domains.delete(domain);
238
+ }
239
+ else {
240
+ this.domains.clear();
241
+ this.alerts = [];
242
+ }
243
+ }
244
+ // ==========================================================================
245
+ // Private Helpers
246
+ // ==========================================================================
247
+ /**
248
+ * Get or create domain tracking state.
249
+ */
250
+ getOrCreateDomainState(domain) {
251
+ let state = this.domains.get(domain);
252
+ if (!state) {
253
+ state = {
254
+ points: [],
255
+ cumulativeRegret: 0,
256
+ decisionCount: 0,
257
+ lastGrowthRate: 'insufficient_data',
258
+ };
259
+ this.domains.set(domain, state);
260
+ }
261
+ return state;
262
+ }
263
+ /**
264
+ * Classify the growth rate of a regret curve using log-log regression.
265
+ *
266
+ * @param points - Regret data points
267
+ * @returns Growth rate classification
268
+ */
269
+ classifyGrowthRate(points) {
270
+ if (points.length < MIN_DATA_POINTS_FOR_CLASSIFICATION) {
271
+ return 'insufficient_data';
272
+ }
273
+ const slope = this.computeLogLogSlope(points);
274
+ if (slope === undefined)
275
+ return 'insufficient_data';
276
+ if (slope < SUBLINEAR_THRESHOLD)
277
+ return 'sublinear';
278
+ if (slope <= SUPERLINEAR_THRESHOLD)
279
+ return 'linear';
280
+ return 'superlinear';
281
+ }
282
+ /**
283
+ * Compute the slope of log(regret) vs log(n) for the regret curve.
284
+ *
285
+ * Filters out points where cumulative regret is zero (log(0) is undefined).
286
+ *
287
+ * @param points - Regret data points
288
+ * @returns Slope value, or undefined if insufficient valid data
289
+ */
290
+ computeLogLogSlope(points) {
291
+ if (points.length < MIN_DATA_POINTS_FOR_CLASSIFICATION) {
292
+ return undefined;
293
+ }
294
+ // Filter to points with positive regret and positive decision count
295
+ const validPoints = points.filter(p => p.cumulativeRegret > 0 && p.decisionCount > 0);
296
+ if (validPoints.length < 2)
297
+ return undefined;
298
+ const logN = validPoints.map(p => Math.log(p.decisionCount));
299
+ const logR = validPoints.map(p => Math.log(p.cumulativeRegret));
300
+ return linearRegressionSlope(logN, logR);
301
+ }
302
+ /**
303
+ * Compute the average per-decision regret over the recent window.
304
+ */
305
+ computeRecentAvgRegret(state) {
306
+ if (state.points.length < 2)
307
+ return 0;
308
+ const windowSize = Math.min(this.recentWindow, state.points.length);
309
+ const recentPoints = state.points.slice(-windowSize);
310
+ // Recent regret = difference in cumulative regret over the window
311
+ const firstPoint = recentPoints[0];
312
+ const lastPoint = recentPoints[recentPoints.length - 1];
313
+ const regretInWindow = lastPoint.cumulativeRegret - firstPoint.cumulativeRegret;
314
+ const decisionsInWindow = lastPoint.decisionCount - firstPoint.decisionCount;
315
+ if (decisionsInWindow <= 0)
316
+ return 0;
317
+ return regretInWindow / decisionsInWindow;
318
+ }
319
+ /**
320
+ * Emit a growth rate transition alert.
321
+ */
322
+ emitAlert(domain, previousRate, newRate) {
323
+ const alert = {
324
+ domain,
325
+ previousRate,
326
+ newRate,
327
+ timestamp: Date.now(),
328
+ message: `Domain "${domain}" regret growth changed from ${previousRate} to ${newRate}`,
329
+ };
330
+ this.alerts.push(alert);
331
+ if (this.alerts.length > this.maxAlerts) {
332
+ this.alerts.shift();
333
+ }
334
+ logger.info('Regret growth rate transition', {
335
+ domain,
336
+ previousRate,
337
+ newRate,
338
+ });
339
+ for (const callback of this.alertCallbacks) {
340
+ try {
341
+ callback(alert);
342
+ }
343
+ catch (err) {
344
+ logger.error('Alert callback error', err instanceof Error ? err : undefined);
345
+ }
346
+ }
347
+ }
348
+ }
349
+ // ============================================================================
350
+ // Factory Function
351
+ // ============================================================================
352
+ /**
353
+ * Create a new RegretTracker instance.
354
+ *
355
+ * @param options - Optional configuration
356
+ * @returns New RegretTracker
357
+ */
358
+ export function createRegretTracker(options) {
359
+ return new RegretTracker(options);
360
+ }
361
+ //# sourceMappingURL=regret-tracker.js.map