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
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import type { MemoryBackend, EventBus } from '../kernel/interfaces.js';
16
16
  import type { Result } from '../shared/types/index.js';
17
+ import type { WitnessChain } from '../governance/witness-chain.js';
17
18
  import type { QEDomain } from './qe-patterns.js';
18
19
  import type { PatternStore } from './pattern-store.js';
19
20
  /**
@@ -78,6 +79,8 @@ export interface TaskExperience {
78
79
  trajectoryId?: string;
79
80
  /** Additional metadata */
80
81
  metadata?: Record<string, unknown>;
82
+ /** Witness receipt hash from witness chain audit trail (when useWitnessChain enabled) */
83
+ witnessHash?: string;
81
84
  }
82
85
  /**
83
86
  * Experience step
@@ -164,7 +167,14 @@ export declare class ExperienceCaptureService {
164
167
  private activeExperiences;
165
168
  private stats;
166
169
  private sessionCaptureCount;
170
+ /** Optional witness chain for attaching audit receipts to experiences */
171
+ private witnessChain?;
167
172
  constructor(memory: MemoryBackend, patternStore?: PatternStore | undefined, eventBus?: EventBus | undefined, config?: Partial<ExperienceCaptureConfig>);
173
+ /**
174
+ * Set the witness chain for attaching audit receipts to captured experiences.
175
+ * Only creates witness records when the useWitnessChain feature flag is enabled.
176
+ */
177
+ setWitnessChain(chain: WitnessChain): void;
168
178
  /**
169
179
  * Initialize the experience capture service
170
180
  */
@@ -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
@@ -57,8 +57,6 @@ export { SQLitePatternStore, createSQLitePatternStore, DEFAULT_SQLITE_CONFIG, }
57
57
  export type { SQLitePersistenceConfig, } from './sqlite-persistence.js';
58
58
  export { QEUnifiedMemory, createQEUnifiedMemory, createDefaultQEUnifiedMemory, QE_MEMORY_DOMAINS, QE_DOMAIN_HNSW_CONFIGS, DEFAULT_QE_UNIFIED_MEMORY_CONFIG, } from './qe-unified-memory.js';
59
59
  export type { QEMemoryDomain, QEMemoryMetadata, TestSuiteMetadata, DefectMetadata, QualityMetricsMetadata, LearningPatternMetadata, CoordinationMetadata, QEMemorySearchResult, QEMemorySearchOptions, MigrationConfig, MigrationProgress, MigrationResult, MigrationSource, QEUnifiedMemoryConfig, QEUnifiedMemoryStats, QEMemoryDomainStats, IQEUnifiedMemory, } from './qe-unified-memory.js';
60
- export { V2ToV3Migrator, migrateV2ToV3, } from './v2-to-v3-migration.js';
61
- export type { V2MigrationConfig, V2MigrationProgress, V2MigrationResult, } from './v2-to-v3-migration.js';
62
60
  export { TokenMetricsCollector, TokenMetricsCollectorImpl, formatCostUsd, estimateTokens, } from './token-tracker.js';
63
61
  export type { TokenUsage, TaskTokenMetric, AgentTokenMetrics, SessionTokenSummary, TokenEfficiencyReport, Timeframe, TokenCostConfig, } from './token-tracker.js';
64
62
  export { ConceptGraph, createConceptGraph, DEFAULT_CONCEPT_GRAPH_CONFIG, } from './dream/index.js';
@@ -79,6 +77,8 @@ export { generateRemediationHints, findCommonKeywords, } from './opd-remediation
79
77
  export type { RemediationHint, RemediationCategory, RemediationConfig, PatternInput, ExecutionRecord, } from './opd-remediation.js';
80
78
  export { LearningMetricsTracker, createLearningMetricsTracker, } from './metrics-tracker.js';
81
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';
82
82
  export { DailyLogger } from './daily-log.js';
83
83
  export type { DailyLogEntry, DailyLogConfig, } from './daily-log.js';
84
84
  //# sourceMappingURL=index.d.ts.map
@@ -92,10 +92,6 @@ export { SQLitePatternStore, createSQLitePatternStore, DEFAULT_SQLITE_CONFIG, }
92
92
  // ============================================================================
93
93
  export { QEUnifiedMemory, createQEUnifiedMemory, createDefaultQEUnifiedMemory, QE_MEMORY_DOMAINS, QE_DOMAIN_HNSW_CONFIGS, DEFAULT_QE_UNIFIED_MEMORY_CONFIG, } from './qe-unified-memory.js';
94
94
  // ============================================================================
95
- // V2 to V3 Migration (ADR-038)
96
- // ============================================================================
97
- export { V2ToV3Migrator, migrateV2ToV3, } from './v2-to-v3-migration.js';
98
- // ============================================================================
99
95
  // Token Tracking (ADR-042)
100
96
  // ============================================================================
101
97
  export {
@@ -146,6 +142,10 @@ export { generateRemediationHints, findCommonKeywords, } from './opd-remediation
146
142
  // ============================================================================
147
143
  export { LearningMetricsTracker, createLearningMetricsTracker, } from './metrics-tracker.js';
148
144
  // ============================================================================
145
+ // Regret Tracker (Task 2.4: Regret Tracking & Learning Health)
146
+ // ============================================================================
147
+ export { RegretTracker, createRegretTracker, linearRegressionSlope, } from './regret-tracker.js';
148
+ // ============================================================================
149
149
  // Daily Log Tier (OpenClaw Daily Log Pattern)
150
150
  // ============================================================================
151
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';
@@ -87,7 +88,7 @@ export class LearningMetricsTracker {
87
88
  const oneWeekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
88
89
  // Pattern metrics
89
90
  const patternStats = this.getPatternStats(today);
90
- // Experience metrics (from learning_experiences if exists, or qe_pattern_usage)
91
+ // Experience metrics (from captured_experiences or qe_pattern_usage)
91
92
  const experienceStats = this.getExperienceStats(today);
92
93
  // Q-value metrics
93
94
  const qValueStats = this.getQValueStats();
@@ -169,16 +170,17 @@ export class LearningMetricsTracker {
169
170
  if (!this.db) {
170
171
  return { total: 0, recordedToday: 0, avgReward: 0, successRate: 0 };
171
172
  }
172
- // Try learning_experiences table first (v2 compatible)
173
- const learningTableExists = this.db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='learning_experiences'`).get();
174
- if (learningTableExists) {
173
+ // Use captured_experiences table
174
+ const capturedTableExists = this.db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='captured_experiences'`).get();
175
+ if (capturedTableExists) {
175
176
  const stats = this.db.prepare(`
176
177
  SELECT
177
178
  COUNT(*) as total,
178
- SUM(CASE WHEN date(datetime(created_at, 'unixepoch')) = ? THEN 1 ELSE 0 END) as recorded_today,
179
- AVG(reward) as avg_reward,
180
- AVG(CASE WHEN reward >= 0.5 THEN 1.0 ELSE 0.0 END) as success_rate
181
- FROM learning_experiences
179
+ SUM(CASE WHEN date(started_at) = ? THEN 1 ELSE 0 END) as recorded_today,
180
+ AVG(quality) as avg_reward,
181
+ AVG(CASE WHEN success = 1 THEN 1.0 ELSE 0.0 END) as success_rate
182
+ FROM captured_experiences
183
+ WHERE agent != 'cli-hook'
182
184
  `).get(today);
183
185
  return {
184
186
  total: stats.total || 0,
@@ -252,13 +254,14 @@ export class LearningMetricsTracker {
252
254
  getHistoricalAvgReward(date) {
253
255
  if (!this.db)
254
256
  return 0;
255
- // Try learning_experiences first
256
- const tableExists = this.db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='learning_experiences'`).get();
257
+ // Use captured_experiences
258
+ const tableExists = this.db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='captured_experiences'`).get();
257
259
  if (tableExists) {
258
260
  const result = this.db.prepare(`
259
- SELECT AVG(reward) as avg_reward
260
- FROM learning_experiences
261
- WHERE datetime(created_at, 'unixepoch') <= datetime(?)
261
+ SELECT AVG(quality) as avg_reward
262
+ FROM captured_experiences
263
+ WHERE started_at <= datetime(?)
264
+ AND agent != 'cli-hook'
262
265
  `).get(date + ' 23:59:59');
263
266
  return result?.avg_reward || 0;
264
267
  }
@@ -377,6 +380,19 @@ export class LearningMetricsTracker {
377
380
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
378
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));
379
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
+ }
380
396
  /**
381
397
  * Close the database connection
382
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,13 +121,16 @@ 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
126
130
  */
127
131
  private ensureSchema;
128
132
  /**
129
- * Get recent experiences from learning_experiences table
133
+ * Get recent experiences from captured_experiences table.
130
134
  */
131
135
  getRecentExperiences(options?: {
132
136
  minReward?: number;
@@ -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 };
@@ -99,40 +103,38 @@ export class PatternLifecycleManager {
99
103
  // Experience Extraction
100
104
  // ============================================================================
101
105
  /**
102
- * Get recent experiences from learning_experiences table
106
+ * Get recent experiences from captured_experiences table.
103
107
  */
104
108
  getRecentExperiences(options = {}) {
105
109
  const minReward = options.minReward ?? this.config.promotionRewardThreshold;
106
110
  const limit = options.limit ?? 100;
107
111
  const sinceDays = options.sinceDays ?? 7;
108
- const sinceTimestamp = Date.now() - (sinceDays * 24 * 60 * 60 * 1000);
109
- // Check if learning_experiences table exists
110
- const tableExists = this.db.prepare(`
111
- SELECT name FROM sqlite_master
112
- WHERE type='table' AND name='learning_experiences'
113
- `).get();
112
+ const tableExists = this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='captured_experiences'").get();
114
113
  if (!tableExists) {
115
- console.log('[PatternLifecycle] learning_experiences table not found');
114
+ logger.debug('captured_experiences table not found');
116
115
  return [];
117
116
  }
117
+ const sinceDate = new Date(Date.now() - sinceDays * 86400000)
118
+ .toISOString().replace('T', ' ').slice(0, 19);
118
119
  const aggregates = this.db.prepare(`
119
120
  SELECT
120
- task_type,
121
+ domain as task_type,
121
122
  COUNT(*) as count,
122
- AVG(reward) as avg_reward,
123
- MAX(reward) as max_reward,
124
- MIN(reward) as min_reward,
125
- SUM(CASE WHEN reward >= ? THEN 1 ELSE 0 END) as success_count,
126
- GROUP_CONCAT(DISTINCT action) as actions,
127
- MAX(created_at) as latest_at
128
- FROM learning_experiences
129
- WHERE created_at >= ? AND reward >= ?
130
- GROUP BY task_type
123
+ AVG(quality) as avg_reward,
124
+ MAX(quality) as max_reward,
125
+ MIN(quality) as min_reward,
126
+ SUM(CASE WHEN quality >= ? THEN 1 ELSE 0 END) as success_count,
127
+ GROUP_CONCAT(DISTINCT agent) as actions,
128
+ MAX(started_at) as latest_at
129
+ FROM captured_experiences
130
+ WHERE started_at >= ?
131
+ AND quality >= ?
132
+ AND agent != 'cli-hook'
133
+ GROUP BY domain
131
134
  HAVING COUNT(*) >= ?
132
135
  ORDER BY avg_reward DESC
133
136
  LIMIT ?
134
- `).all(minReward, sinceTimestamp, minReward * 0.5, // Include experiences above half threshold for context
135
- this.config.promotionMinOccurrences, limit);
137
+ `).all(minReward, sinceDate, minReward * 0.5, this.config.promotionMinOccurrences, limit);
136
138
  return aggregates.map(agg => ({
137
139
  taskType: agg.task_type,
138
140
  domain: this.taskTypeToQEDomain(agg.task_type),
@@ -636,6 +638,76 @@ Pattern extracted from ${exp.count} successful experiences.`;
636
638
  return this.asymmetricEngine;
637
639
  }
638
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
+ // ============================================================================
639
711
  // Statistics
640
712
  // ============================================================================
641
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 and limit
518
+ // Sort by score
518
519
  results.sort((a, b) => b.score - a.score);
519
- const finalResults = results.slice(0, limit);
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);
@@ -22,7 +22,6 @@
22
22
  import { LoggerFactory } from '../logging/index.js';
23
23
  const logger = LoggerFactory.create('qe-unified-memory');
24
24
  import { ok, err } from '../shared/types/index.js';
25
- import { migrateV2ToV3 } from './v2-to-v3-migration.js';
26
25
  import { EMBEDDING_CONFIG } from '../shared/embeddings/types.js';
27
26
  import { toErrorMessage } from '../shared/error-utils.js';
28
27
  import { HNSWIndex, } from '../domains/coverage-analysis/services/hnsw-index.js';
@@ -508,33 +507,7 @@ export class QEUnifiedMemory {
508
507
  // Private Migration Helpers
509
508
  // -------------------------------------------------------------------------
510
509
  async migrateFromSQLite(config) {
511
- // Check if this is a V2 to V3 migration (patterns table)
512
- const sourcePath = config.sourceConfig?.path || '.agentic-qe/memory.db';
513
- // For V2 to V3 migration, use the dedicated migrator
514
- if (config.domain === 'learning' || config.migrateAll) {
515
- logger.info('Starting V2 to V3 migration', { sourcePath });
516
- const result = await migrateV2ToV3(sourcePath, '.agentic-qe/memory.db', (progress) => {
517
- logger.info('Migration progress', {
518
- stage: progress.stage,
519
- message: progress.message,
520
- table: progress.table,
521
- current: progress.current,
522
- total: progress.total,
523
- });
524
- });
525
- if (result.success) {
526
- logger.info('V2 migration completed successfully', {
527
- tablesMigrated: result.tablesMigrated,
528
- totalRecords: Object.values(result.counts).reduce((a, b) => a + b, 0),
529
- durationSeconds: Number((result.duration / 1000).toFixed(2)),
530
- });
531
- }
532
- else {
533
- logger.error('V2 migration failed', undefined, { errors: result.errors });
534
- }
535
- return Object.values(result.counts).reduce((a, b) => a + b, 0);
536
- }
537
- // Generic SQLite migration for other domains
510
+ // Generic SQLite migration
538
511
  logger.warn('Generic SQLite migration not yet implemented', { domain: config.domain });
539
512
  return 0;
540
513
  }