agentic-qe 3.7.22 → 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.
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +31 -0
- package/README.md +2 -2
- package/dist/cli/bundle.js +5688 -1243
- package/dist/cli/commands/audit.d.ts +43 -0
- package/dist/cli/commands/audit.js +125 -0
- package/dist/cli/commands/learning.js +106 -1
- package/dist/cli/commands/ruvector-commands.d.ts +15 -0
- package/dist/cli/commands/ruvector-commands.js +271 -0
- package/dist/cli/index.js +4 -0
- package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
- package/dist/coordination/behavior-tree/decorators.js +251 -0
- package/dist/coordination/behavior-tree/index.d.ts +12 -0
- package/dist/coordination/behavior-tree/index.js +15 -0
- package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
- package/dist/coordination/behavior-tree/nodes.js +338 -0
- package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
- package/dist/coordination/behavior-tree/qe-trees.js +181 -0
- package/dist/coordination/coherence-action-gate.d.ts +284 -0
- package/dist/coordination/coherence-action-gate.js +512 -0
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +8 -0
- package/dist/coordination/reasoning-qec.d.ts +315 -0
- package/dist/coordination/reasoning-qec.js +585 -0
- package/dist/coordination/task-executor.d.ts +16 -0
- package/dist/coordination/task-executor.js +99 -0
- package/dist/coordination/workflow-orchestrator.d.ts +29 -0
- package/dist/coordination/workflow-orchestrator.js +42 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
- package/dist/domains/visual-accessibility/index.d.ts +1 -0
- package/dist/domains/visual-accessibility/index.js +4 -0
- package/dist/governance/coherence-validator.d.ts +112 -0
- package/dist/governance/coherence-validator.js +180 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/witness-chain.d.ts +311 -0
- package/dist/governance/witness-chain.js +509 -0
- package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
- package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
- package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
- package/dist/integrations/browser/qe-dashboard/index.js +15 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
- package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
- package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
- package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
- package/dist/integrations/ruvector/cognitive-container.js +306 -0
- package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
- package/dist/integrations/ruvector/coherence-gate.js +631 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
- package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
- package/dist/integrations/ruvector/dither-adapter.js +295 -0
- package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
- package/dist/integrations/ruvector/domain-transfer.js +220 -0
- package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
- package/dist/integrations/ruvector/feature-flags.js +167 -2
- package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
- package/dist/integrations/ruvector/filter-adapter.js +285 -0
- package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
- package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
- package/dist/integrations/ruvector/index.d.ts +8 -2
- package/dist/integrations/ruvector/index.js +18 -2
- package/dist/integrations/ruvector/interfaces.d.ts +40 -0
- package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
- package/dist/integrations/ruvector/sona-persistence.js +162 -0
- package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
- package/dist/integrations/ruvector/sona-three-loop.js +814 -0
- package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
- package/dist/integrations/ruvector/sona-wrapper.js +147 -3
- package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
- package/dist/integrations/ruvector/spectral-math.js +254 -0
- package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
- package/dist/integrations/ruvector/temporal-compression.js +318 -0
- package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
- package/dist/integrations/ruvector/thompson-sampler.js +118 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
- package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
- package/dist/integrations/ruvector/transfer-verification.js +115 -0
- package/dist/kernel/hnsw-adapter.d.ts +52 -1
- package/dist/kernel/hnsw-adapter.js +139 -4
- package/dist/kernel/hnsw-index-provider.d.ts +5 -0
- package/dist/kernel/native-hnsw-backend.d.ts +110 -0
- package/dist/kernel/native-hnsw-backend.js +408 -0
- package/dist/learning/aqe-learning-engine.d.ts +2 -0
- package/dist/learning/aqe-learning-engine.js +65 -0
- package/dist/learning/experience-capture.d.ts +10 -0
- package/dist/learning/experience-capture.js +34 -0
- package/dist/learning/index.d.ts +2 -0
- package/dist/learning/index.js +4 -0
- package/dist/learning/metrics-tracker.d.ts +11 -0
- package/dist/learning/metrics-tracker.js +14 -0
- package/dist/learning/pattern-lifecycle.d.ts +29 -0
- package/dist/learning/pattern-lifecycle.js +74 -0
- package/dist/learning/pattern-store.d.ts +8 -0
- package/dist/learning/pattern-store.js +8 -2
- package/dist/learning/regret-tracker.d.ts +201 -0
- package/dist/learning/regret-tracker.js +361 -0
- package/dist/mcp/bundle.js +5834 -398
- package/dist/routing/index.d.ts +4 -2
- package/dist/routing/index.js +3 -1
- package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
- package/dist/routing/neural-tiny-dancer-router.js +514 -0
- package/dist/routing/queen-integration.js +5 -5
- package/dist/routing/routing-config.d.ts +6 -0
- package/dist/routing/routing-config.js +1 -0
- package/dist/routing/simple-neural-router.d.ts +76 -0
- package/dist/routing/simple-neural-router.js +202 -0
- package/dist/routing/tiny-dancer-router.d.ts +20 -1
- package/dist/routing/tiny-dancer-router.js +21 -2
- package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
- package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-types.js +10 -0
- package/dist/test-scheduling/index.d.ts +1 -0
- package/dist/test-scheduling/index.js +4 -0
- package/dist/test-scheduling/pipeline.d.ts +8 -0
- package/dist/test-scheduling/pipeline.js +28 -0
- package/package.json +6 -2
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { v4 as uuidv4 } from 'uuid';
|
|
16
16
|
import { ok, err } from '../shared/types/index.js';
|
|
17
17
|
import { LoggerFactory } from '../logging/index.js';
|
|
18
|
+
import { getRuVectorFeatureFlags } from '../integrations/ruvector/feature-flags.js';
|
|
18
19
|
const logger = LoggerFactory.create('experience-capture');
|
|
19
20
|
import { PROMOTION_THRESHOLD } from './qe-patterns.js';
|
|
20
21
|
/**
|
|
@@ -91,12 +92,21 @@ export class ExperienceCaptureService {
|
|
|
91
92
|
};
|
|
92
93
|
// Session-level counter (not persisted, tracks only this session)
|
|
93
94
|
sessionCaptureCount = 0;
|
|
95
|
+
/** Optional witness chain for attaching audit receipts to experiences */
|
|
96
|
+
witnessChain;
|
|
94
97
|
constructor(memory, patternStore, eventBus, config = {}) {
|
|
95
98
|
this.memory = memory;
|
|
96
99
|
this.patternStore = patternStore;
|
|
97
100
|
this.eventBus = eventBus;
|
|
98
101
|
this.config = { ...DEFAULT_EXPERIENCE_CONFIG, ...config };
|
|
99
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Set the witness chain for attaching audit receipts to captured experiences.
|
|
105
|
+
* Only creates witness records when the useWitnessChain feature flag is enabled.
|
|
106
|
+
*/
|
|
107
|
+
setWitnessChain(chain) {
|
|
108
|
+
this.witnessChain = chain;
|
|
109
|
+
}
|
|
100
110
|
/**
|
|
101
111
|
* Initialize the experience capture service
|
|
102
112
|
*/
|
|
@@ -176,6 +186,30 @@ export class ExperienceCaptureService {
|
|
|
176
186
|
experience.testOutcome = rawOutcome;
|
|
177
187
|
experience.reward = computeBinaryReward(rawOutcome);
|
|
178
188
|
}
|
|
189
|
+
// Attach witness receipt when witness chain is available and feature flag enabled
|
|
190
|
+
if (this.witnessChain && getRuVectorFeatureFlags().useWitnessChain) {
|
|
191
|
+
try {
|
|
192
|
+
const receipt = this.witnessChain.appendWitness({
|
|
193
|
+
type: 'experience-capture',
|
|
194
|
+
decision: experience.success ? 'PASS' : 'FAIL',
|
|
195
|
+
context: {
|
|
196
|
+
experienceId: experience.id,
|
|
197
|
+
task: experience.task,
|
|
198
|
+
quality: experience.quality,
|
|
199
|
+
domain: experience.domain,
|
|
200
|
+
reward: experience.reward,
|
|
201
|
+
},
|
|
202
|
+
evidence: experience.reward,
|
|
203
|
+
});
|
|
204
|
+
experience.witnessHash = receipt.hash;
|
|
205
|
+
}
|
|
206
|
+
catch (witnessError) {
|
|
207
|
+
logger.warn('Failed to create witness receipt for experience', {
|
|
208
|
+
experienceId: experience.id,
|
|
209
|
+
error: witnessError instanceof Error ? witnessError.message : String(witnessError),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
179
213
|
// Remove from active
|
|
180
214
|
this.activeExperiences.delete(experienceId);
|
|
181
215
|
// Store experience
|
package/dist/learning/index.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export { generateRemediationHints, findCommonKeywords, } from './opd-remediation
|
|
|
77
77
|
export type { RemediationHint, RemediationCategory, RemediationConfig, PatternInput, ExecutionRecord, } from './opd-remediation.js';
|
|
78
78
|
export { LearningMetricsTracker, createLearningMetricsTracker, } from './metrics-tracker.js';
|
|
79
79
|
export type { LearningMetricsSnapshot, DashboardData, } from './metrics-tracker.js';
|
|
80
|
+
export { RegretTracker, createRegretTracker, linearRegressionSlope, } from './regret-tracker.js';
|
|
81
|
+
export type { RegretPoint, GrowthRate, DomainHealthSummary, RegretAlert, RegretAlertCallback, } from './regret-tracker.js';
|
|
80
82
|
export { DailyLogger } from './daily-log.js';
|
|
81
83
|
export type { DailyLogEntry, DailyLogConfig, } from './daily-log.js';
|
|
82
84
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/learning/index.js
CHANGED
|
@@ -142,6 +142,10 @@ export { generateRemediationHints, findCommonKeywords, } from './opd-remediation
|
|
|
142
142
|
// ============================================================================
|
|
143
143
|
export { LearningMetricsTracker, createLearningMetricsTracker, } from './metrics-tracker.js';
|
|
144
144
|
// ============================================================================
|
|
145
|
+
// Regret Tracker (Task 2.4: Regret Tracking & Learning Health)
|
|
146
|
+
// ============================================================================
|
|
147
|
+
export { RegretTracker, createRegretTracker, linearRegressionSlope, } from './regret-tracker.js';
|
|
148
|
+
// ============================================================================
|
|
145
149
|
// Daily Log Tier (OpenClaw Daily Log Pattern)
|
|
146
150
|
// ============================================================================
|
|
147
151
|
export { DailyLogger } from './daily-log.js';
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
* - Domain coverage metrics
|
|
11
11
|
* - Daily snapshots for trend analysis
|
|
12
12
|
* - Dashboard data generation
|
|
13
|
+
* - Regret tracking integration (Task 2.4)
|
|
13
14
|
*/
|
|
14
15
|
import type { QEDomain } from './qe-patterns.js';
|
|
16
|
+
import type { DomainHealthSummary } from './regret-tracker.js';
|
|
15
17
|
/**
|
|
16
18
|
* Learning metrics snapshot
|
|
17
19
|
*/
|
|
@@ -66,6 +68,8 @@ export interface DashboardData {
|
|
|
66
68
|
domain: QEDomain;
|
|
67
69
|
count: number;
|
|
68
70
|
}>;
|
|
71
|
+
/** Per-domain learning health from regret tracking (Task 2.4, optional) */
|
|
72
|
+
regretHealth?: DomainHealthSummary[];
|
|
69
73
|
}
|
|
70
74
|
/**
|
|
71
75
|
* Learning Metrics Tracker
|
|
@@ -121,6 +125,13 @@ export declare class LearningMetricsTracker {
|
|
|
121
125
|
* Save a daily metrics snapshot
|
|
122
126
|
*/
|
|
123
127
|
saveSnapshot(): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Get dashboard data enriched with regret health information.
|
|
130
|
+
*
|
|
131
|
+
* @param regretHealth - Optional per-domain regret health summaries from RegretTracker
|
|
132
|
+
* @returns Dashboard data with regret health attached
|
|
133
|
+
*/
|
|
134
|
+
getDashboardDataWithRegret(regretHealth?: DomainHealthSummary[]): Promise<DashboardData>;
|
|
124
135
|
/**
|
|
125
136
|
* Close the database connection
|
|
126
137
|
*/
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - Domain coverage metrics
|
|
11
11
|
* - Daily snapshots for trend analysis
|
|
12
12
|
* - Dashboard data generation
|
|
13
|
+
* - Regret tracking integration (Task 2.4)
|
|
13
14
|
*/
|
|
14
15
|
import { openDatabase } from '../shared/safe-db.js';
|
|
15
16
|
import path from 'node:path';
|
|
@@ -379,6 +380,19 @@ export class LearningMetricsTracker {
|
|
|
379
380
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
380
381
|
`).run(today, metrics.totalPatterns, metrics.patternsCreatedToday, metrics.totalExperiences, metrics.experiencesToday, metrics.totalQValues, metrics.avgReward, metrics.avgConfidence, metrics.avgQualityScore, metrics.successRate, metrics.patternReuseCount, metrics.shortTermPatterns, metrics.longTermPatterns, JSON.stringify(metrics.domainCoverage));
|
|
381
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* Get dashboard data enriched with regret health information.
|
|
385
|
+
*
|
|
386
|
+
* @param regretHealth - Optional per-domain regret health summaries from RegretTracker
|
|
387
|
+
* @returns Dashboard data with regret health attached
|
|
388
|
+
*/
|
|
389
|
+
async getDashboardDataWithRegret(regretHealth) {
|
|
390
|
+
const data = await this.getDashboardData();
|
|
391
|
+
if (regretHealth && regretHealth.length > 0) {
|
|
392
|
+
data.regretHealth = regretHealth;
|
|
393
|
+
}
|
|
394
|
+
return data;
|
|
395
|
+
}
|
|
382
396
|
/**
|
|
383
397
|
* Close the database connection
|
|
384
398
|
*/
|
|
@@ -12,6 +12,7 @@ import type { Database as DatabaseType } from 'better-sqlite3';
|
|
|
12
12
|
import { type QEDomain, type QEPatternType } from './qe-patterns.js';
|
|
13
13
|
import { AsymmetricLearningEngine, type AsymmetricLearningConfig } from './asymmetric-learning.js';
|
|
14
14
|
import type { WitnessChain } from '../audit/witness-chain.js';
|
|
15
|
+
import type { TemporalCompressionService, CompressedVector } from '../integrations/ruvector/temporal-compression.js';
|
|
15
16
|
/**
|
|
16
17
|
* Pattern lifecycle configuration
|
|
17
18
|
*/
|
|
@@ -120,6 +121,9 @@ export declare class PatternLifecycleManager {
|
|
|
120
121
|
/** Optional witness chain for audit trail of lifecycle events (ADR-070) */
|
|
121
122
|
private _witnessChain;
|
|
122
123
|
set witnessChain(wc: WitnessChain | null);
|
|
124
|
+
/** Optional temporal compression service for embedding compression (ADR-085) */
|
|
125
|
+
private _compressionService;
|
|
126
|
+
set compressionService(svc: TemporalCompressionService | null);
|
|
123
127
|
constructor(db: DatabaseType, config?: Partial<PatternLifecycleConfig>);
|
|
124
128
|
/**
|
|
125
129
|
* Ensure required schema extensions exist
|
|
@@ -224,6 +228,31 @@ export declare class PatternLifecycleManager {
|
|
|
224
228
|
* Get the asymmetric learning engine for external use (ADR-061)
|
|
225
229
|
*/
|
|
226
230
|
getAsymmetricEngine(): AsymmetricLearningEngine;
|
|
231
|
+
/**
|
|
232
|
+
* Compress a pattern's embedding based on its access recency (ADR-085).
|
|
233
|
+
*
|
|
234
|
+
* Only operates when the temporal compression feature flag is enabled
|
|
235
|
+
* and a compression service has been injected. Returns null when
|
|
236
|
+
* compression is not active, allowing callers to fall back gracefully.
|
|
237
|
+
*/
|
|
238
|
+
compressPatternEmbedding(patternId: string): CompressedVector | null;
|
|
239
|
+
/**
|
|
240
|
+
* Decompress a compressed embedding back to Float32Array (ADR-085).
|
|
241
|
+
*
|
|
242
|
+
* Returns null when the compression service is not available.
|
|
243
|
+
* Consumers receive a standard Float32Array transparently.
|
|
244
|
+
*/
|
|
245
|
+
decompressPatternEmbedding(compressed: CompressedVector): Float32Array | null;
|
|
246
|
+
/**
|
|
247
|
+
* Sweep all active patterns and compress their embeddings (ADR-085).
|
|
248
|
+
*
|
|
249
|
+
* Intended to be called periodically (e.g., during maintenance windows)
|
|
250
|
+
* to apply tier-appropriate compression to pattern embeddings. Only
|
|
251
|
+
* operates when the feature flag is on and a compression service is set.
|
|
252
|
+
*
|
|
253
|
+
* @returns Count of patterns compressed, or 0 if compression is disabled.
|
|
254
|
+
*/
|
|
255
|
+
compressAllPatternEmbeddings(): number;
|
|
227
256
|
/**
|
|
228
257
|
* Get pattern lifecycle statistics
|
|
229
258
|
*/
|
|
@@ -12,6 +12,7 @@ import { PROMOTION_THRESHOLD } from './qe-patterns.js';
|
|
|
12
12
|
import { AsymmetricLearningEngine } from './asymmetric-learning.js';
|
|
13
13
|
import { safeJsonParse } from '../shared/safe-json.js';
|
|
14
14
|
import { LoggerFactory } from '../logging/index.js';
|
|
15
|
+
import { isTemporalCompressionEnabled } from '../integrations/ruvector/feature-flags.js';
|
|
15
16
|
const logger = LoggerFactory.create('pattern-lifecycle');
|
|
16
17
|
/**
|
|
17
18
|
* Default lifecycle configuration
|
|
@@ -44,6 +45,9 @@ export class PatternLifecycleManager {
|
|
|
44
45
|
/** Optional witness chain for audit trail of lifecycle events (ADR-070) */
|
|
45
46
|
_witnessChain = null;
|
|
46
47
|
set witnessChain(wc) { this._witnessChain = wc; }
|
|
48
|
+
/** Optional temporal compression service for embedding compression (ADR-085) */
|
|
49
|
+
_compressionService = null;
|
|
50
|
+
set compressionService(svc) { this._compressionService = svc; }
|
|
47
51
|
constructor(db, config = {}) {
|
|
48
52
|
this.db = db;
|
|
49
53
|
this.config = { ...DEFAULT_LIFECYCLE_CONFIG, ...config };
|
|
@@ -634,6 +638,76 @@ Pattern extracted from ${exp.count} successful experiences.`;
|
|
|
634
638
|
return this.asymmetricEngine;
|
|
635
639
|
}
|
|
636
640
|
// ============================================================================
|
|
641
|
+
// ADR-085: Temporal Tensor Compression
|
|
642
|
+
// ============================================================================
|
|
643
|
+
/**
|
|
644
|
+
* Compress a pattern's embedding based on its access recency (ADR-085).
|
|
645
|
+
*
|
|
646
|
+
* Only operates when the temporal compression feature flag is enabled
|
|
647
|
+
* and a compression service has been injected. Returns null when
|
|
648
|
+
* compression is not active, allowing callers to fall back gracefully.
|
|
649
|
+
*/
|
|
650
|
+
compressPatternEmbedding(patternId) {
|
|
651
|
+
if (!isTemporalCompressionEnabled() || !this._compressionService) {
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
const pattern = this.getPattern(patternId);
|
|
655
|
+
if (!pattern || !pattern.embedding || pattern.embedding.length === 0) {
|
|
656
|
+
return null;
|
|
657
|
+
}
|
|
658
|
+
const lastAccess = pattern.lastUsedAt ?? pattern.createdAt;
|
|
659
|
+
const tier = this._compressionService.classifyTier(lastAccess);
|
|
660
|
+
const vector = new Float32Array(pattern.embedding);
|
|
661
|
+
const compressed = this._compressionService.compress(vector, tier);
|
|
662
|
+
logger.debug('Compressed pattern embedding', {
|
|
663
|
+
patternId,
|
|
664
|
+
tier,
|
|
665
|
+
ratio: (compressed.originalByteSize / compressed.compressedByteSize).toFixed(1),
|
|
666
|
+
});
|
|
667
|
+
return compressed;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Decompress a compressed embedding back to Float32Array (ADR-085).
|
|
671
|
+
*
|
|
672
|
+
* Returns null when the compression service is not available.
|
|
673
|
+
* Consumers receive a standard Float32Array transparently.
|
|
674
|
+
*/
|
|
675
|
+
decompressPatternEmbedding(compressed) {
|
|
676
|
+
if (!this._compressionService) {
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
679
|
+
return this._compressionService.decompress(compressed);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Sweep all active patterns and compress their embeddings (ADR-085).
|
|
683
|
+
*
|
|
684
|
+
* Intended to be called periodically (e.g., during maintenance windows)
|
|
685
|
+
* to apply tier-appropriate compression to pattern embeddings. Only
|
|
686
|
+
* operates when the feature flag is on and a compression service is set.
|
|
687
|
+
*
|
|
688
|
+
* @returns Count of patterns compressed, or 0 if compression is disabled.
|
|
689
|
+
*/
|
|
690
|
+
compressAllPatternEmbeddings() {
|
|
691
|
+
if (!isTemporalCompressionEnabled() || !this._compressionService) {
|
|
692
|
+
return 0;
|
|
693
|
+
}
|
|
694
|
+
const patterns = this.db.prepare(`
|
|
695
|
+
SELECT id FROM qe_patterns
|
|
696
|
+
WHERE deprecated_at IS NULL
|
|
697
|
+
`).all();
|
|
698
|
+
let compressed = 0;
|
|
699
|
+
for (const { id } of patterns) {
|
|
700
|
+
const result = this.compressPatternEmbedding(id);
|
|
701
|
+
if (result)
|
|
702
|
+
compressed++;
|
|
703
|
+
}
|
|
704
|
+
logger.info('Bulk pattern embedding compression complete', {
|
|
705
|
+
total: patterns.length,
|
|
706
|
+
compressed,
|
|
707
|
+
});
|
|
708
|
+
return compressed;
|
|
709
|
+
}
|
|
710
|
+
// ============================================================================
|
|
637
711
|
// Statistics
|
|
638
712
|
// ============================================================================
|
|
639
713
|
/**
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import type { MemoryBackend } from '../kernel/interfaces.js';
|
|
9
9
|
import type { Result } from '../shared/types/index.js';
|
|
10
10
|
import { QEPattern, QEPatternContext, QEPatternType, QEDomain, CreateQEPatternOptions } from './qe-patterns.js';
|
|
11
|
+
import type { FilterExpression } from '../integrations/ruvector/interfaces.js';
|
|
11
12
|
/**
|
|
12
13
|
* Token tracking configuration (ADR-042)
|
|
13
14
|
*/
|
|
@@ -122,6 +123,13 @@ export interface PatternSearchOptions {
|
|
|
122
123
|
context?: Partial<QEPatternContext>;
|
|
123
124
|
/** Include vector similarity search */
|
|
124
125
|
useVectorSearch?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Composable metadata filter expression (Task 1.2: ruvector-filter).
|
|
128
|
+
* Applied post-search to refine results by domain, severity,
|
|
129
|
+
* confidence range, tags, date range, etc.
|
|
130
|
+
* When undefined, no additional filtering is applied (backward compatible).
|
|
131
|
+
*/
|
|
132
|
+
filter?: FilterExpression;
|
|
125
133
|
}
|
|
126
134
|
/**
|
|
127
135
|
* Pattern search result with reuse optimization (ADR-042)
|
|
@@ -9,6 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
9
9
|
import { ok, err } from '../shared/types/index.js';
|
|
10
10
|
import { toErrorMessage, toError } from '../shared/error-utils.js';
|
|
11
11
|
import { calculateQualityScore, shouldPromotePattern, validateQEPattern, mapQEDomainToAQE, PROMOTION_THRESHOLD, } from './qe-patterns.js';
|
|
12
|
+
import { applyFilterSync } from '../integrations/ruvector/filter-adapter.js';
|
|
12
13
|
/**
|
|
13
14
|
* Default pattern store configuration
|
|
14
15
|
*/
|
|
@@ -514,9 +515,14 @@ export class PatternStore {
|
|
|
514
515
|
// while penalizing stale patterns (decayFactor is 0-1)
|
|
515
516
|
result.score = result.score * (0.7 + 0.3 * effectiveDecay);
|
|
516
517
|
}
|
|
517
|
-
// Sort by score
|
|
518
|
+
// Sort by score
|
|
518
519
|
results.sort((a, b) => b.score - a.score);
|
|
519
|
-
|
|
520
|
+
// Apply metadata filter BEFORE limit so we don't lose matching results (W-3 fix)
|
|
521
|
+
let filteredResults = results;
|
|
522
|
+
if (options.filter) {
|
|
523
|
+
filteredResults = applyFilterSync(results, options.filter);
|
|
524
|
+
}
|
|
525
|
+
const finalResults = filteredResults.slice(0, limit);
|
|
520
526
|
// Record stats
|
|
521
527
|
const latency = performance.now() - startTime;
|
|
522
528
|
this.recordSearchLatency(latency);
|
|
@@ -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
|