agentic-qe 3.3.1 → 3.3.2
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/package.json +1 -1
- package/v3/CHANGELOG.md +46 -0
- package/v3/dist/cli/bundle.js +3675 -342
- package/v3/dist/coordination/queen-coordinator.d.ts +13 -1
- package/v3/dist/coordination/queen-coordinator.d.ts.map +1 -1
- package/v3/dist/coordination/queen-coordinator.js +91 -3
- package/v3/dist/coordination/queen-coordinator.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/plugin.d.ts +6 -1
- package/v3/dist/domains/coverage-analysis/plugin.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/plugin.js +73 -0
- package/v3/dist/domains/coverage-analysis/plugin.js.map +1 -1
- package/v3/dist/domains/domain-interface.d.ts +39 -2
- package/v3/dist/domains/domain-interface.d.ts.map +1 -1
- package/v3/dist/domains/domain-interface.js +99 -0
- package/v3/dist/domains/domain-interface.js.map +1 -1
- package/v3/dist/domains/learning-optimization/coordinator.d.ts +83 -0
- package/v3/dist/domains/learning-optimization/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/learning-optimization/coordinator.js +174 -0
- package/v3/dist/domains/learning-optimization/coordinator.js.map +1 -1
- package/v3/dist/domains/learning-optimization/interfaces.d.ts +14 -0
- package/v3/dist/domains/learning-optimization/interfaces.d.ts.map +1 -1
- package/v3/dist/domains/quality-assessment/coordinator.d.ts +23 -0
- package/v3/dist/domains/quality-assessment/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/quality-assessment/coordinator.js +139 -1
- package/v3/dist/domains/quality-assessment/coordinator.js.map +1 -1
- package/v3/dist/domains/quality-assessment/plugin.d.ts +6 -1
- package/v3/dist/domains/quality-assessment/plugin.d.ts.map +1 -1
- package/v3/dist/domains/quality-assessment/plugin.js +67 -0
- package/v3/dist/domains/quality-assessment/plugin.js.map +1 -1
- package/v3/dist/domains/test-execution/plugin.d.ts +6 -1
- package/v3/dist/domains/test-execution/plugin.d.ts.map +1 -1
- package/v3/dist/domains/test-execution/plugin.js +77 -0
- package/v3/dist/domains/test-execution/plugin.js.map +1 -1
- package/v3/dist/domains/test-generation/coordinator.d.ts +40 -0
- package/v3/dist/domains/test-generation/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/test-generation/coordinator.js +184 -1
- package/v3/dist/domains/test-generation/coordinator.js.map +1 -1
- package/v3/dist/domains/test-generation/plugin.d.ts +6 -1
- package/v3/dist/domains/test-generation/plugin.d.ts.map +1 -1
- package/v3/dist/domains/test-generation/plugin.js +84 -0
- package/v3/dist/domains/test-generation/plugin.js.map +1 -1
- package/v3/dist/kernel/interfaces.d.ts +54 -1
- package/v3/dist/kernel/interfaces.d.ts.map +1 -1
- package/v3/dist/learning/dream/dream-scheduler.d.ts +302 -0
- package/v3/dist/learning/dream/dream-scheduler.d.ts.map +1 -0
- package/v3/dist/learning/dream/dream-scheduler.js +551 -0
- package/v3/dist/learning/dream/dream-scheduler.js.map +1 -0
- package/v3/dist/learning/dream/index.d.ts +1 -0
- package/v3/dist/learning/dream/index.d.ts.map +1 -1
- package/v3/dist/learning/dream/index.js +4 -0
- package/v3/dist/learning/dream/index.js.map +1 -1
- package/v3/dist/mcp/bundle.js +66391 -60131
- package/v3/dist/mcp/handlers/core-handlers.d.ts.map +1 -1
- package/v3/dist/mcp/handlers/core-handlers.js +16 -2
- package/v3/dist/mcp/handlers/core-handlers.js.map +1 -1
- package/v3/dist/mcp/handlers/task-handlers.d.ts +1 -0
- package/v3/dist/mcp/handlers/task-handlers.d.ts.map +1 -1
- package/v3/dist/mcp/handlers/task-handlers.js +46 -12
- package/v3/dist/mcp/handlers/task-handlers.js.map +1 -1
- package/v3/dist/mcp/services/reasoning-bank-service.d.ts +87 -13
- package/v3/dist/mcp/services/reasoning-bank-service.d.ts.map +1 -1
- package/v3/dist/mcp/services/reasoning-bank-service.js +291 -31
- package/v3/dist/mcp/services/reasoning-bank-service.js.map +1 -1
- package/v3/dist/routing/qe-agent-registry.d.ts +27 -0
- package/v3/dist/routing/qe-agent-registry.d.ts.map +1 -1
- package/v3/dist/routing/qe-agent-registry.js +96 -0
- package/v3/dist/routing/qe-agent-registry.js.map +1 -1
- package/v3/dist/shared/events/domain-events.d.ts +27 -0
- package/v3/dist/shared/events/domain-events.d.ts.map +1 -1
- package/v3/dist/shared/events/domain-events.js +1 -0
- package/v3/dist/shared/events/domain-events.js.map +1 -1
- package/v3/package.json +1 -1
package/v3/dist/cli/bundle.js
CHANGED
|
@@ -9372,7 +9372,11 @@ var HybridMemoryBackend = class {
|
|
|
9372
9372
|
import * as path9 from "path";
|
|
9373
9373
|
import * as fs8 from "fs";
|
|
9374
9374
|
|
|
9375
|
+
// src/domains/test-generation/plugin.ts
|
|
9376
|
+
init_types();
|
|
9377
|
+
|
|
9375
9378
|
// src/domains/domain-interface.ts
|
|
9379
|
+
init_types();
|
|
9376
9380
|
var BaseDomainPlugin = class {
|
|
9377
9381
|
constructor(eventBus, memory) {
|
|
9378
9382
|
this.eventBus = eventBus;
|
|
@@ -9428,6 +9432,95 @@ var BaseDomainPlugin = class {
|
|
|
9428
9432
|
updateHealth(updates) {
|
|
9429
9433
|
this._health = { ...this._health, ...updates };
|
|
9430
9434
|
}
|
|
9435
|
+
// ============================================================================
|
|
9436
|
+
// Task Execution (Queen-Domain Integration)
|
|
9437
|
+
// ============================================================================
|
|
9438
|
+
/**
|
|
9439
|
+
* Get task type to handler mapping
|
|
9440
|
+
* Override in subclasses to register domain-specific task handlers
|
|
9441
|
+
*
|
|
9442
|
+
* @example
|
|
9443
|
+
* protected override getTaskHandlers(): Map<string, TaskHandler> {
|
|
9444
|
+
* return new Map([
|
|
9445
|
+
* ['execute-tests', async (payload) => this.coordinator.execute(payload)],
|
|
9446
|
+
* ['detect-flaky', async (payload) => this.coordinator.detectFlaky(payload)],
|
|
9447
|
+
* ]);
|
|
9448
|
+
* }
|
|
9449
|
+
*/
|
|
9450
|
+
getTaskHandlers() {
|
|
9451
|
+
return /* @__PURE__ */ new Map();
|
|
9452
|
+
}
|
|
9453
|
+
/**
|
|
9454
|
+
* Check if domain can handle a task type
|
|
9455
|
+
* Based on registered task handlers
|
|
9456
|
+
*/
|
|
9457
|
+
canHandleTask(taskType) {
|
|
9458
|
+
return this.getTaskHandlers().has(taskType);
|
|
9459
|
+
}
|
|
9460
|
+
/**
|
|
9461
|
+
* Execute a task assigned by Queen Coordinator
|
|
9462
|
+
* Routes to the appropriate handler based on task type
|
|
9463
|
+
*
|
|
9464
|
+
* @param request - Task execution request from Queen
|
|
9465
|
+
* @param onComplete - Callback to report task completion
|
|
9466
|
+
* @returns Success if task was accepted, Error if no handler exists
|
|
9467
|
+
*/
|
|
9468
|
+
async executeTask(request, onComplete) {
|
|
9469
|
+
const handlers = this.getTaskHandlers();
|
|
9470
|
+
const handler = handlers.get(request.taskType);
|
|
9471
|
+
if (!handler) {
|
|
9472
|
+
return err(
|
|
9473
|
+
new Error(`Domain ${this.name} has no handler for task type: ${request.taskType}`)
|
|
9474
|
+
);
|
|
9475
|
+
}
|
|
9476
|
+
this.runTaskAsync(request, handler, onComplete);
|
|
9477
|
+
return ok(void 0);
|
|
9478
|
+
}
|
|
9479
|
+
/**
|
|
9480
|
+
* Run task asynchronously and report completion via callback
|
|
9481
|
+
* Handles timing, success/failure, and error capture
|
|
9482
|
+
*/
|
|
9483
|
+
async runTaskAsync(request, handler, onComplete) {
|
|
9484
|
+
const startTime = Date.now();
|
|
9485
|
+
try {
|
|
9486
|
+
const result = await handler(request.payload);
|
|
9487
|
+
const duration = Date.now() - startTime;
|
|
9488
|
+
const taskResult = {
|
|
9489
|
+
taskId: request.taskId,
|
|
9490
|
+
success: result.success,
|
|
9491
|
+
data: result.success ? result.value : void 0,
|
|
9492
|
+
error: !result.success ? result.error?.message : void 0,
|
|
9493
|
+
duration
|
|
9494
|
+
};
|
|
9495
|
+
await onComplete(taskResult);
|
|
9496
|
+
this.updateHealth({
|
|
9497
|
+
lastActivity: /* @__PURE__ */ new Date(),
|
|
9498
|
+
agents: {
|
|
9499
|
+
...this._health.agents,
|
|
9500
|
+
active: Math.max(0, this._health.agents.active - 1),
|
|
9501
|
+
idle: this._health.agents.idle + 1
|
|
9502
|
+
}
|
|
9503
|
+
});
|
|
9504
|
+
} catch (error) {
|
|
9505
|
+
const duration = Date.now() - startTime;
|
|
9506
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
9507
|
+
await onComplete({
|
|
9508
|
+
taskId: request.taskId,
|
|
9509
|
+
success: false,
|
|
9510
|
+
error: errorMessage,
|
|
9511
|
+
duration
|
|
9512
|
+
});
|
|
9513
|
+
this.updateHealth({
|
|
9514
|
+
lastActivity: /* @__PURE__ */ new Date(),
|
|
9515
|
+
errors: [...this._health.errors.slice(-9), errorMessage],
|
|
9516
|
+
agents: {
|
|
9517
|
+
...this._health.agents,
|
|
9518
|
+
active: Math.max(0, this._health.agents.active - 1),
|
|
9519
|
+
failed: this._health.agents.failed + 1
|
|
9520
|
+
}
|
|
9521
|
+
});
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9431
9524
|
};
|
|
9432
9525
|
|
|
9433
9526
|
// src/domains/test-generation/coordinator.ts
|
|
@@ -9487,7 +9580,8 @@ var SecurityComplianceEvents = {
|
|
|
9487
9580
|
var LearningOptimizationEvents = {
|
|
9488
9581
|
PatternConsolidated: "learning-optimization.PatternConsolidated",
|
|
9489
9582
|
TransferCompleted: "learning-optimization.TransferCompleted",
|
|
9490
|
-
OptimizationApplied: "learning-optimization.OptimizationApplied"
|
|
9583
|
+
OptimizationApplied: "learning-optimization.OptimizationApplied",
|
|
9584
|
+
DreamCycleCompleted: "learning-optimization.dream.completed"
|
|
9491
9585
|
};
|
|
9492
9586
|
var AllDomainEvents = {
|
|
9493
9587
|
...TestGenerationEvents,
|
|
@@ -15573,6 +15667,10 @@ var TestGenerationCoordinator = class {
|
|
|
15573
15667
|
flashAttention = null;
|
|
15574
15668
|
decisionTransformer = null;
|
|
15575
15669
|
testEmbeddings = /* @__PURE__ */ new Map();
|
|
15670
|
+
// Domain identifier for dream insight filtering
|
|
15671
|
+
domainName = "test-generation";
|
|
15672
|
+
// Cache of recent dream insights for test enhancement
|
|
15673
|
+
recentDreamInsights = [];
|
|
15576
15674
|
// Coherence gate (ADR-052)
|
|
15577
15675
|
coherenceGate = null;
|
|
15578
15676
|
/**
|
|
@@ -16006,6 +16104,181 @@ var TestGenerationCoordinator = class {
|
|
|
16006
16104
|
"test-execution.TestRunCompleted",
|
|
16007
16105
|
this.handleTestRunCompleted.bind(this)
|
|
16008
16106
|
);
|
|
16107
|
+
this.subscribeToDreamEvents();
|
|
16108
|
+
}
|
|
16109
|
+
// ============================================================================
|
|
16110
|
+
// Dream Event Handling (ADR-021 Integration)
|
|
16111
|
+
// ============================================================================
|
|
16112
|
+
/**
|
|
16113
|
+
* Subscribe to dream cycle completion events from learning-optimization domain.
|
|
16114
|
+
* Dream insights can suggest edge cases, novel test patterns, and optimization opportunities.
|
|
16115
|
+
*/
|
|
16116
|
+
subscribeToDreamEvents() {
|
|
16117
|
+
this.eventBus.subscribe(
|
|
16118
|
+
LearningOptimizationEvents.DreamCycleCompleted,
|
|
16119
|
+
this.handleDreamCycleCompleted.bind(this)
|
|
16120
|
+
);
|
|
16121
|
+
}
|
|
16122
|
+
/**
|
|
16123
|
+
* Handle dream cycle completion event.
|
|
16124
|
+
* Filters insights relevant to test generation and applies actionable ones.
|
|
16125
|
+
*/
|
|
16126
|
+
async handleDreamCycleCompleted(event) {
|
|
16127
|
+
const { insights, cycleId } = event.payload;
|
|
16128
|
+
if (!insights || insights.length === 0) {
|
|
16129
|
+
return;
|
|
16130
|
+
}
|
|
16131
|
+
const relevantInsights = insights.filter((insight) => {
|
|
16132
|
+
const actionRelevant = insight.suggestedAction?.toLowerCase().includes(this.domainName) || insight.suggestedAction?.toLowerCase().includes("test") || insight.suggestedAction?.toLowerCase().includes("coverage");
|
|
16133
|
+
const conceptsRelevant = insight.sourceConcepts.some(
|
|
16134
|
+
(c) => c.toLowerCase().includes("test") || c.toLowerCase().includes(this.domainName) || c.toLowerCase().includes("coverage") || c.toLowerCase().includes("edge-case")
|
|
16135
|
+
);
|
|
16136
|
+
const typeRelevant = insight.type === "optimization" || insight.type === "gap_detection" || insight.type === "novel_association";
|
|
16137
|
+
return actionRelevant || conceptsRelevant || typeRelevant && insight.actionable;
|
|
16138
|
+
});
|
|
16139
|
+
if (relevantInsights.length === 0) {
|
|
16140
|
+
return;
|
|
16141
|
+
}
|
|
16142
|
+
console.log(
|
|
16143
|
+
`[${this.domainName}] Received ${relevantInsights.length} relevant dream insights from cycle ${cycleId}`
|
|
16144
|
+
);
|
|
16145
|
+
for (const insight of relevantInsights) {
|
|
16146
|
+
if (insight.confidenceScore > 0.7 && insight.actionable) {
|
|
16147
|
+
await this.applyDreamInsight(insight, cycleId);
|
|
16148
|
+
}
|
|
16149
|
+
this.recentDreamInsights.push({
|
|
16150
|
+
...insight,
|
|
16151
|
+
receivedAt: /* @__PURE__ */ new Date()
|
|
16152
|
+
});
|
|
16153
|
+
}
|
|
16154
|
+
if (this.recentDreamInsights.length > 50) {
|
|
16155
|
+
this.recentDreamInsights = this.recentDreamInsights.slice(-50);
|
|
16156
|
+
}
|
|
16157
|
+
}
|
|
16158
|
+
/**
|
|
16159
|
+
* Apply a dream insight by storing it as a learned pattern via SONA.
|
|
16160
|
+
* This allows the insight to influence future test generation decisions.
|
|
16161
|
+
*
|
|
16162
|
+
* @param insight - The dream insight to apply
|
|
16163
|
+
* @param cycleId - The dream cycle ID for tracking
|
|
16164
|
+
*/
|
|
16165
|
+
async applyDreamInsight(insight, cycleId) {
|
|
16166
|
+
console.log(
|
|
16167
|
+
`[${this.domainName}] Applying dream insight: ${insight.description.slice(0, 100)}...`
|
|
16168
|
+
);
|
|
16169
|
+
if (this.qesona) {
|
|
16170
|
+
try {
|
|
16171
|
+
const state2 = {
|
|
16172
|
+
id: `dream-insight-${insight.id}`,
|
|
16173
|
+
features: this.encodeInsightAsFeatures(insight),
|
|
16174
|
+
metadata: {
|
|
16175
|
+
insightType: insight.type,
|
|
16176
|
+
cycleId,
|
|
16177
|
+
sourceConcepts: insight.sourceConcepts
|
|
16178
|
+
}
|
|
16179
|
+
};
|
|
16180
|
+
const action = {
|
|
16181
|
+
type: "dream-insight",
|
|
16182
|
+
value: insight.suggestedAction || insight.description
|
|
16183
|
+
};
|
|
16184
|
+
const pattern = this.qesona.createPattern(
|
|
16185
|
+
state2,
|
|
16186
|
+
action,
|
|
16187
|
+
{
|
|
16188
|
+
reward: insight.confidenceScore,
|
|
16189
|
+
success: true,
|
|
16190
|
+
quality: insight.noveltyScore
|
|
16191
|
+
},
|
|
16192
|
+
"dream-derived",
|
|
16193
|
+
this.domainName,
|
|
16194
|
+
{
|
|
16195
|
+
insightId: insight.id,
|
|
16196
|
+
cycleId,
|
|
16197
|
+
description: insight.description,
|
|
16198
|
+
suggestedAction: insight.suggestedAction
|
|
16199
|
+
}
|
|
16200
|
+
);
|
|
16201
|
+
console.log(
|
|
16202
|
+
`[${this.domainName}] Created SONA pattern ${pattern.id} from dream insight`
|
|
16203
|
+
);
|
|
16204
|
+
} catch (error) {
|
|
16205
|
+
console.error(
|
|
16206
|
+
`[${this.domainName}] Failed to store dream insight pattern:`,
|
|
16207
|
+
error
|
|
16208
|
+
);
|
|
16209
|
+
}
|
|
16210
|
+
}
|
|
16211
|
+
await this.memory.set(
|
|
16212
|
+
`${this.domainName}:dream-insight:${insight.id}`,
|
|
16213
|
+
{
|
|
16214
|
+
insight,
|
|
16215
|
+
cycleId,
|
|
16216
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16217
|
+
},
|
|
16218
|
+
{ namespace: this.domainName, ttl: 86400 * 7 }
|
|
16219
|
+
// 7 days
|
|
16220
|
+
);
|
|
16221
|
+
}
|
|
16222
|
+
/**
|
|
16223
|
+
* Get recent dream insights filtered by type.
|
|
16224
|
+
* Used by test generation methods to enhance test case discovery.
|
|
16225
|
+
*
|
|
16226
|
+
* @param insightType - Optional type filter (e.g., 'novel_association', 'gap_detection')
|
|
16227
|
+
* @returns Array of recent dream insights
|
|
16228
|
+
*/
|
|
16229
|
+
getRecentDreamInsights(insightType) {
|
|
16230
|
+
const cutoffTime = Date.now() - 24 * 60 * 60 * 1e3;
|
|
16231
|
+
return this.recentDreamInsights.filter((insight) => {
|
|
16232
|
+
const isRecent = insight.receivedAt.getTime() > cutoffTime;
|
|
16233
|
+
const matchesType = !insightType || insight.type === insightType;
|
|
16234
|
+
return isRecent && matchesType;
|
|
16235
|
+
});
|
|
16236
|
+
}
|
|
16237
|
+
/**
|
|
16238
|
+
* Enhance test generation request with dream insights for edge case discovery.
|
|
16239
|
+
* Queries recent dream insights to suggest additional test scenarios.
|
|
16240
|
+
*
|
|
16241
|
+
* @param request - The original test generation request
|
|
16242
|
+
* @returns Array of suggested edge case descriptions from dream insights
|
|
16243
|
+
*/
|
|
16244
|
+
async enhanceWithDreamInsights(request) {
|
|
16245
|
+
const suggestions = [];
|
|
16246
|
+
const insights = this.getRecentDreamInsights();
|
|
16247
|
+
const edgeCaseInsights = insights.filter(
|
|
16248
|
+
(i) => (i.type === "novel_association" || i.type === "gap_detection") && i.actionable && i.confidenceScore > 0.6
|
|
16249
|
+
);
|
|
16250
|
+
for (const insight of edgeCaseInsights) {
|
|
16251
|
+
if (insight.suggestedAction) {
|
|
16252
|
+
const isRelevant = request.sourceFiles.some(
|
|
16253
|
+
(f) => insight.sourceConcepts.some((c) => f.toLowerCase().includes(c.toLowerCase()))
|
|
16254
|
+
) || insight.suggestedAction.toLowerCase().includes(request.testType);
|
|
16255
|
+
if (isRelevant) {
|
|
16256
|
+
suggestions.push(insight.suggestedAction);
|
|
16257
|
+
}
|
|
16258
|
+
}
|
|
16259
|
+
}
|
|
16260
|
+
return suggestions.slice(0, 5);
|
|
16261
|
+
}
|
|
16262
|
+
/**
|
|
16263
|
+
* Encode a dream insight as feature vector for SONA pattern creation.
|
|
16264
|
+
*/
|
|
16265
|
+
encodeInsightAsFeatures(insight) {
|
|
16266
|
+
const features = [];
|
|
16267
|
+
const typeMap = {
|
|
16268
|
+
pattern_merge: 0.2,
|
|
16269
|
+
novel_association: 0.4,
|
|
16270
|
+
optimization: 0.6,
|
|
16271
|
+
gap_detection: 0.8
|
|
16272
|
+
};
|
|
16273
|
+
features.push(typeMap[insight.type] || 0.5);
|
|
16274
|
+
features.push(insight.confidenceScore);
|
|
16275
|
+
features.push(insight.noveltyScore);
|
|
16276
|
+
features.push(insight.actionable ? 1 : 0);
|
|
16277
|
+
features.push(Math.min(1, insight.sourceConcepts.length / 10));
|
|
16278
|
+
while (features.length < 384) {
|
|
16279
|
+
features.push(0);
|
|
16280
|
+
}
|
|
16281
|
+
return features.slice(0, 384);
|
|
16009
16282
|
}
|
|
16010
16283
|
async handleCoverageGapDetected(event) {
|
|
16011
16284
|
const payload = event.payload;
|
|
@@ -16407,6 +16680,89 @@ var TestGenerationPlugin = class extends BaseDomainPlugin {
|
|
|
16407
16680
|
return api;
|
|
16408
16681
|
}
|
|
16409
16682
|
// ============================================================================
|
|
16683
|
+
// Task Handlers (Queen-Domain Integration)
|
|
16684
|
+
// ============================================================================
|
|
16685
|
+
/**
|
|
16686
|
+
* Get task handlers for direct Queen-Domain integration
|
|
16687
|
+
* Maps task types to coordinator methods
|
|
16688
|
+
*/
|
|
16689
|
+
getTaskHandlers() {
|
|
16690
|
+
return /* @__PURE__ */ new Map([
|
|
16691
|
+
// Generate tests task - main task type for this domain
|
|
16692
|
+
["generate-tests", async (payload) => {
|
|
16693
|
+
if (!this.coordinator) {
|
|
16694
|
+
return err(new Error("Coordinator not initialized"));
|
|
16695
|
+
}
|
|
16696
|
+
const sourceFiles = payload.sourceFiles;
|
|
16697
|
+
const testType = payload.testType;
|
|
16698
|
+
const framework = payload.framework;
|
|
16699
|
+
if (!sourceFiles || sourceFiles.length === 0) {
|
|
16700
|
+
return err(new Error("Invalid generate-tests payload: missing sourceFiles"));
|
|
16701
|
+
}
|
|
16702
|
+
const request = {
|
|
16703
|
+
sourceFiles,
|
|
16704
|
+
testType: testType ?? "unit",
|
|
16705
|
+
framework: framework ?? "vitest",
|
|
16706
|
+
coverageTarget: payload.coverageTarget,
|
|
16707
|
+
patterns: payload.patterns
|
|
16708
|
+
};
|
|
16709
|
+
return this.coordinator.generateTests(request);
|
|
16710
|
+
}],
|
|
16711
|
+
// TDD tests generation task
|
|
16712
|
+
["generate-tdd-tests", async (payload) => {
|
|
16713
|
+
if (!this.coordinator) {
|
|
16714
|
+
return err(new Error("Coordinator not initialized"));
|
|
16715
|
+
}
|
|
16716
|
+
const feature = payload.feature;
|
|
16717
|
+
const behavior = payload.behavior;
|
|
16718
|
+
const framework = payload.framework;
|
|
16719
|
+
const phase = payload.phase;
|
|
16720
|
+
if (!feature || !behavior) {
|
|
16721
|
+
return err(new Error("Invalid generate-tdd-tests payload: missing feature or behavior"));
|
|
16722
|
+
}
|
|
16723
|
+
return this.coordinator.generateTDDTests({
|
|
16724
|
+
feature,
|
|
16725
|
+
behavior,
|
|
16726
|
+
framework: framework ?? "vitest",
|
|
16727
|
+
phase: phase ?? "red"
|
|
16728
|
+
});
|
|
16729
|
+
}],
|
|
16730
|
+
// Property-based tests generation task
|
|
16731
|
+
["generate-property-tests", async (payload) => {
|
|
16732
|
+
if (!this.coordinator) {
|
|
16733
|
+
return err(new Error("Coordinator not initialized"));
|
|
16734
|
+
}
|
|
16735
|
+
const fn = payload.function;
|
|
16736
|
+
const properties = payload.properties;
|
|
16737
|
+
if (!fn || !properties || properties.length === 0) {
|
|
16738
|
+
return err(new Error("Invalid generate-property-tests payload: missing function or properties"));
|
|
16739
|
+
}
|
|
16740
|
+
return this.coordinator.generatePropertyTests({
|
|
16741
|
+
function: fn,
|
|
16742
|
+
properties,
|
|
16743
|
+
constraints: payload.constraints
|
|
16744
|
+
});
|
|
16745
|
+
}],
|
|
16746
|
+
// Test data generation task
|
|
16747
|
+
["generate-test-data", async (payload) => {
|
|
16748
|
+
if (!this.coordinator) {
|
|
16749
|
+
return err(new Error("Coordinator not initialized"));
|
|
16750
|
+
}
|
|
16751
|
+
const schema = payload.schema;
|
|
16752
|
+
const count = payload.count;
|
|
16753
|
+
if (!schema) {
|
|
16754
|
+
return err(new Error("Invalid generate-test-data payload: missing schema"));
|
|
16755
|
+
}
|
|
16756
|
+
return this.coordinator.generateTestData({
|
|
16757
|
+
schema,
|
|
16758
|
+
count: count ?? 10,
|
|
16759
|
+
locale: payload.locale,
|
|
16760
|
+
preserveRelationships: payload.preserveRelationships
|
|
16761
|
+
});
|
|
16762
|
+
}]
|
|
16763
|
+
]);
|
|
16764
|
+
}
|
|
16765
|
+
// ============================================================================
|
|
16410
16766
|
// Lifecycle Methods
|
|
16411
16767
|
// ============================================================================
|
|
16412
16768
|
async onInitialize() {
|
|
@@ -16592,6 +16948,9 @@ function createTestGenerationPlugin(eventBus, memory, agentCoordinator, config)
|
|
|
16592
16948
|
return new TestGenerationPlugin(eventBus, memory, agentCoordinator, config);
|
|
16593
16949
|
}
|
|
16594
16950
|
|
|
16951
|
+
// src/domains/test-execution/plugin.ts
|
|
16952
|
+
init_types();
|
|
16953
|
+
|
|
16595
16954
|
// src/domains/test-execution/coordinator.ts
|
|
16596
16955
|
init_types();
|
|
16597
16956
|
import { v4 as uuidv410 } from "uuid";
|
|
@@ -20270,7 +20629,7 @@ function resolveTarget(target) {
|
|
|
20270
20629
|
return target.value;
|
|
20271
20630
|
}
|
|
20272
20631
|
}
|
|
20273
|
-
function
|
|
20632
|
+
function ok3(value) {
|
|
20274
20633
|
return { success: true, value };
|
|
20275
20634
|
}
|
|
20276
20635
|
function err2(error) {
|
|
@@ -20355,7 +20714,7 @@ var AgentBrowserClient = class {
|
|
|
20355
20714
|
if (options?.viewport) {
|
|
20356
20715
|
await this.setViewport(options.viewport.width, options.viewport.height);
|
|
20357
20716
|
}
|
|
20358
|
-
return
|
|
20717
|
+
return ok3(toSessionInfo(existingSession));
|
|
20359
20718
|
}
|
|
20360
20719
|
}
|
|
20361
20720
|
const available = await this.isAvailable();
|
|
@@ -20382,7 +20741,7 @@ var AgentBrowserClient = class {
|
|
|
20382
20741
|
if (options?.deviceName) {
|
|
20383
20742
|
await this.setDevice(options.deviceName);
|
|
20384
20743
|
}
|
|
20385
|
-
return
|
|
20744
|
+
return ok3(toSessionInfo(session));
|
|
20386
20745
|
} catch (error) {
|
|
20387
20746
|
const browserError = new BrowserError(
|
|
20388
20747
|
error instanceof Error ? error.message : String(error),
|
|
@@ -20415,7 +20774,7 @@ var AgentBrowserClient = class {
|
|
|
20415
20774
|
}
|
|
20416
20775
|
this.isLaunched = false;
|
|
20417
20776
|
this.currentSessionId = null;
|
|
20418
|
-
return
|
|
20777
|
+
return ok3(void 0);
|
|
20419
20778
|
} catch (error) {
|
|
20420
20779
|
this.isLaunched = false;
|
|
20421
20780
|
this.currentSessionId = null;
|
|
@@ -20463,7 +20822,7 @@ var AgentBrowserClient = class {
|
|
|
20463
20822
|
"JSON.stringify({ title: document.title, url: window.location.href })"
|
|
20464
20823
|
);
|
|
20465
20824
|
const pageInfo = evalResult.success && evalResult.data ? typeof evalResult.data === "string" ? JSON.parse(evalResult.data) : evalResult.data : { title: "", url };
|
|
20466
|
-
return
|
|
20825
|
+
return ok3({
|
|
20467
20826
|
url: pageInfo.url || url,
|
|
20468
20827
|
title: pageInfo.title || "",
|
|
20469
20828
|
success: true,
|
|
@@ -20489,7 +20848,7 @@ var AgentBrowserClient = class {
|
|
|
20489
20848
|
if (!result.success) {
|
|
20490
20849
|
return err2(new BrowserError(result.error ?? "Reload failed", "RELOAD_FAILED", "agent-browser"));
|
|
20491
20850
|
}
|
|
20492
|
-
return
|
|
20851
|
+
return ok3(void 0);
|
|
20493
20852
|
} catch (error) {
|
|
20494
20853
|
return err2(
|
|
20495
20854
|
new BrowserError(
|
|
@@ -20510,7 +20869,7 @@ var AgentBrowserClient = class {
|
|
|
20510
20869
|
if (!result.success) {
|
|
20511
20870
|
return err2(new BrowserError(result.error ?? "Go back failed", "HISTORY_FAILED", "agent-browser"));
|
|
20512
20871
|
}
|
|
20513
|
-
return
|
|
20872
|
+
return ok3(void 0);
|
|
20514
20873
|
} catch (error) {
|
|
20515
20874
|
return err2(
|
|
20516
20875
|
new BrowserError(
|
|
@@ -20531,7 +20890,7 @@ var AgentBrowserClient = class {
|
|
|
20531
20890
|
if (!result.success) {
|
|
20532
20891
|
return err2(new BrowserError(result.error ?? "Go forward failed", "HISTORY_FAILED", "agent-browser"));
|
|
20533
20892
|
}
|
|
20534
|
-
return
|
|
20893
|
+
return ok3(void 0);
|
|
20535
20894
|
} catch (error) {
|
|
20536
20895
|
return err2(
|
|
20537
20896
|
new BrowserError(
|
|
@@ -20556,7 +20915,7 @@ var AgentBrowserClient = class {
|
|
|
20556
20915
|
if (!result.success) {
|
|
20557
20916
|
return err2(new BrowserElementNotFoundError("agent-browser", target, new Error(result.error)));
|
|
20558
20917
|
}
|
|
20559
|
-
return
|
|
20918
|
+
return ok3(void 0);
|
|
20560
20919
|
} catch (error) {
|
|
20561
20920
|
return err2(
|
|
20562
20921
|
new BrowserError(
|
|
@@ -20578,7 +20937,7 @@ var AgentBrowserClient = class {
|
|
|
20578
20937
|
if (!result.success) {
|
|
20579
20938
|
return err2(new BrowserElementNotFoundError("agent-browser", target, new Error(result.error)));
|
|
20580
20939
|
}
|
|
20581
|
-
return
|
|
20940
|
+
return ok3(void 0);
|
|
20582
20941
|
} catch (error) {
|
|
20583
20942
|
return err2(
|
|
20584
20943
|
new BrowserError(
|
|
@@ -20616,7 +20975,7 @@ var AgentBrowserClient = class {
|
|
|
20616
20975
|
text = obj.result;
|
|
20617
20976
|
}
|
|
20618
20977
|
}
|
|
20619
|
-
return
|
|
20978
|
+
return ok3(String(text ?? ""));
|
|
20620
20979
|
} catch (error) {
|
|
20621
20980
|
return err2(
|
|
20622
20981
|
new BrowserError(
|
|
@@ -20636,9 +20995,9 @@ var AgentBrowserClient = class {
|
|
|
20636
20995
|
const resolvedTarget = resolveTarget(target);
|
|
20637
20996
|
const result = this.executor.isVisible(resolvedTarget);
|
|
20638
20997
|
if (!result.success) {
|
|
20639
|
-
return
|
|
20998
|
+
return ok3(false);
|
|
20640
20999
|
}
|
|
20641
|
-
return
|
|
21000
|
+
return ok3(Boolean(result.data));
|
|
20642
21001
|
} catch (error) {
|
|
20643
21002
|
return err2(
|
|
20644
21003
|
new BrowserError(
|
|
@@ -20670,7 +21029,7 @@ var AgentBrowserClient = class {
|
|
|
20670
21029
|
const parsed = typeof dimensionsResult.data === "string" ? JSON.parse(dimensionsResult.data) : dimensionsResult.data;
|
|
20671
21030
|
dimensions = { width: parsed.width || 1280, height: parsed.height || 720 };
|
|
20672
21031
|
}
|
|
20673
|
-
return
|
|
21032
|
+
return ok3({
|
|
20674
21033
|
base64: options?.path ? void 0 : String(result.data ?? ""),
|
|
20675
21034
|
path: options?.path,
|
|
20676
21035
|
format: "png",
|
|
@@ -20711,7 +21070,7 @@ var AgentBrowserClient = class {
|
|
|
20711
21070
|
value = obj.result;
|
|
20712
21071
|
}
|
|
20713
21072
|
}
|
|
20714
|
-
return
|
|
21073
|
+
return ok3(value);
|
|
20715
21074
|
} catch (error) {
|
|
20716
21075
|
return err2(
|
|
20717
21076
|
new BrowserError(
|
|
@@ -20752,7 +21111,7 @@ var AgentBrowserClient = class {
|
|
|
20752
21111
|
if (titleResult.success) {
|
|
20753
21112
|
parsed.title = String(titleResult.data);
|
|
20754
21113
|
}
|
|
20755
|
-
return
|
|
21114
|
+
return ok3(toTypedSnapshot(parsed));
|
|
20756
21115
|
} catch (error) {
|
|
20757
21116
|
return err2(
|
|
20758
21117
|
new BrowserError(
|
|
@@ -20773,7 +21132,7 @@ var AgentBrowserClient = class {
|
|
|
20773
21132
|
async createSession(name) {
|
|
20774
21133
|
try {
|
|
20775
21134
|
const session = await this.sessionManager.createSession({ name });
|
|
20776
|
-
return
|
|
21135
|
+
return ok3(toSessionInfo(session));
|
|
20777
21136
|
} catch (error) {
|
|
20778
21137
|
return err2(
|
|
20779
21138
|
new BrowserError(
|
|
@@ -20798,7 +21157,7 @@ var AgentBrowserClient = class {
|
|
|
20798
21157
|
headed: this.config.headed,
|
|
20799
21158
|
debug: this.config.debug
|
|
20800
21159
|
});
|
|
20801
|
-
return
|
|
21160
|
+
return ok3(void 0);
|
|
20802
21161
|
} catch (error) {
|
|
20803
21162
|
return err2(
|
|
20804
21163
|
new BrowserError(
|
|
@@ -20816,7 +21175,7 @@ var AgentBrowserClient = class {
|
|
|
20816
21175
|
async listSessions() {
|
|
20817
21176
|
try {
|
|
20818
21177
|
const sessions = this.sessionManager.listSessions();
|
|
20819
|
-
return
|
|
21178
|
+
return ok3(sessions.map(toSessionInfo));
|
|
20820
21179
|
} catch (error) {
|
|
20821
21180
|
return err2(
|
|
20822
21181
|
new BrowserError(
|
|
@@ -20845,7 +21204,7 @@ var AgentBrowserClient = class {
|
|
|
20845
21204
|
if (!result.success) {
|
|
20846
21205
|
return err2(new BrowserError(result.error ?? "Mock route failed", "MOCK_ROUTE_FAILED", "agent-browser"));
|
|
20847
21206
|
}
|
|
20848
|
-
return
|
|
21207
|
+
return ok3(void 0);
|
|
20849
21208
|
} catch (error) {
|
|
20850
21209
|
return err2(
|
|
20851
21210
|
new BrowserError(
|
|
@@ -20866,7 +21225,7 @@ var AgentBrowserClient = class {
|
|
|
20866
21225
|
if (!result.success) {
|
|
20867
21226
|
return err2(new BrowserError(result.error ?? "Abort route failed", "ABORT_ROUTE_FAILED", "agent-browser"));
|
|
20868
21227
|
}
|
|
20869
|
-
return
|
|
21228
|
+
return ok3(void 0);
|
|
20870
21229
|
} catch (error) {
|
|
20871
21230
|
return err2(
|
|
20872
21231
|
new BrowserError(
|
|
@@ -20887,7 +21246,7 @@ var AgentBrowserClient = class {
|
|
|
20887
21246
|
if (!result.success) {
|
|
20888
21247
|
return err2(new BrowserError(result.error ?? "Clear routes failed", "CLEAR_ROUTES_FAILED", "agent-browser"));
|
|
20889
21248
|
}
|
|
20890
|
-
return
|
|
21249
|
+
return ok3(void 0);
|
|
20891
21250
|
} catch (error) {
|
|
20892
21251
|
return err2(
|
|
20893
21252
|
new BrowserError(
|
|
@@ -20911,7 +21270,7 @@ var AgentBrowserClient = class {
|
|
|
20911
21270
|
if (!result.success) {
|
|
20912
21271
|
return err2(new BrowserError(result.error ?? "Set device failed", "SET_DEVICE_FAILED", "agent-browser"));
|
|
20913
21272
|
}
|
|
20914
|
-
return
|
|
21273
|
+
return ok3(void 0);
|
|
20915
21274
|
} catch (error) {
|
|
20916
21275
|
return err2(
|
|
20917
21276
|
new BrowserError(
|
|
@@ -20932,7 +21291,7 @@ var AgentBrowserClient = class {
|
|
|
20932
21291
|
if (!result.success) {
|
|
20933
21292
|
return err2(new BrowserError(result.error ?? "Set viewport failed", "SET_VIEWPORT_FAILED", "agent-browser"));
|
|
20934
21293
|
}
|
|
20935
|
-
return
|
|
21294
|
+
return ok3(void 0);
|
|
20936
21295
|
} catch (error) {
|
|
20937
21296
|
return err2(
|
|
20938
21297
|
new BrowserError(
|
|
@@ -20956,7 +21315,7 @@ var AgentBrowserClient = class {
|
|
|
20956
21315
|
if (!result.success) {
|
|
20957
21316
|
return err2(new BrowserError(result.error ?? "Save state failed", "SAVE_STATE_FAILED", "agent-browser"));
|
|
20958
21317
|
}
|
|
20959
|
-
return
|
|
21318
|
+
return ok3(void 0);
|
|
20960
21319
|
} catch (error) {
|
|
20961
21320
|
return err2(
|
|
20962
21321
|
new BrowserError(
|
|
@@ -20977,7 +21336,7 @@ var AgentBrowserClient = class {
|
|
|
20977
21336
|
if (!result.success) {
|
|
20978
21337
|
return err2(new BrowserError(result.error ?? "Load state failed", "LOAD_STATE_FAILED", "agent-browser"));
|
|
20979
21338
|
}
|
|
20980
|
-
return
|
|
21339
|
+
return ok3(void 0);
|
|
20981
21340
|
} catch (error) {
|
|
20982
21341
|
return err2(
|
|
20983
21342
|
new BrowserError(
|
|
@@ -21004,7 +21363,7 @@ var AgentBrowserClient = class {
|
|
|
21004
21363
|
new BrowserTimeoutError("agent-browser", `waitForElement(${resolvedTarget})`, new Error(result.error))
|
|
21005
21364
|
);
|
|
21006
21365
|
}
|
|
21007
|
-
return
|
|
21366
|
+
return ok3(void 0);
|
|
21008
21367
|
} catch (error) {
|
|
21009
21368
|
return err2(
|
|
21010
21369
|
new BrowserError(
|
|
@@ -21026,7 +21385,7 @@ var AgentBrowserClient = class {
|
|
|
21026
21385
|
if (!result.success) {
|
|
21027
21386
|
return err2(new BrowserTimeoutError("agent-browser", `waitForText("${text}")`, new Error(result.error)));
|
|
21028
21387
|
}
|
|
21029
|
-
return
|
|
21388
|
+
return ok3(void 0);
|
|
21030
21389
|
} catch (error) {
|
|
21031
21390
|
return err2(
|
|
21032
21391
|
new BrowserError(
|
|
@@ -21048,7 +21407,7 @@ var AgentBrowserClient = class {
|
|
|
21048
21407
|
if (!result.success) {
|
|
21049
21408
|
return err2(new BrowserTimeoutError("agent-browser", `waitForUrl("${pattern}")`, new Error(result.error)));
|
|
21050
21409
|
}
|
|
21051
|
-
return
|
|
21410
|
+
return ok3(void 0);
|
|
21052
21411
|
} catch (error) {
|
|
21053
21412
|
return err2(
|
|
21054
21413
|
new BrowserError(
|
|
@@ -21070,7 +21429,7 @@ var AgentBrowserClient = class {
|
|
|
21070
21429
|
if (!result.success) {
|
|
21071
21430
|
return err2(new BrowserTimeoutError("agent-browser", "waitForNetworkIdle", new Error(result.error)));
|
|
21072
21431
|
}
|
|
21073
|
-
return
|
|
21432
|
+
return ok3(void 0);
|
|
21074
21433
|
} catch (error) {
|
|
21075
21434
|
return err2(
|
|
21076
21435
|
new BrowserError(
|
|
@@ -21097,7 +21456,7 @@ var AgentBrowserClient = class {
|
|
|
21097
21456
|
if (!result.success) {
|
|
21098
21457
|
return err2(new BrowserError(result.error ?? "Start trace failed", "START_TRACE_FAILED", "agent-browser"));
|
|
21099
21458
|
}
|
|
21100
|
-
return
|
|
21459
|
+
return ok3(void 0);
|
|
21101
21460
|
} catch (error) {
|
|
21102
21461
|
return err2(
|
|
21103
21462
|
new BrowserError(
|
|
@@ -21121,7 +21480,7 @@ var AgentBrowserClient = class {
|
|
|
21121
21480
|
if (!result.success) {
|
|
21122
21481
|
return err2(new BrowserError(result.error ?? "Stop trace failed", "STOP_TRACE_FAILED", "agent-browser"));
|
|
21123
21482
|
}
|
|
21124
|
-
return
|
|
21483
|
+
return ok3(result.data ?? outputPath);
|
|
21125
21484
|
} catch (error) {
|
|
21126
21485
|
return err2(
|
|
21127
21486
|
new BrowserError(
|
|
@@ -23446,6 +23805,78 @@ var TestExecutionPlugin = class extends BaseDomainPlugin {
|
|
|
23446
23805
|
return api;
|
|
23447
23806
|
}
|
|
23448
23807
|
// ============================================================================
|
|
23808
|
+
// Task Handlers (Queen-Domain Integration)
|
|
23809
|
+
// ============================================================================
|
|
23810
|
+
/**
|
|
23811
|
+
* Get task handlers for direct Queen-Domain integration
|
|
23812
|
+
* Maps task types to coordinator methods
|
|
23813
|
+
*/
|
|
23814
|
+
getTaskHandlers() {
|
|
23815
|
+
return /* @__PURE__ */ new Map([
|
|
23816
|
+
// Execute tests task - main task type for this domain
|
|
23817
|
+
["execute-tests", async (payload) => {
|
|
23818
|
+
if (!this.coordinator) {
|
|
23819
|
+
return err(new Error("Coordinator not initialized"));
|
|
23820
|
+
}
|
|
23821
|
+
if (payload.testFiles && Array.isArray(payload.testFiles)) {
|
|
23822
|
+
const request = {
|
|
23823
|
+
testFiles: payload.testFiles,
|
|
23824
|
+
parallel: payload.parallel,
|
|
23825
|
+
retryCount: payload.retryCount,
|
|
23826
|
+
timeout: payload.timeout,
|
|
23827
|
+
workers: payload.workers
|
|
23828
|
+
};
|
|
23829
|
+
return this.coordinator.runTests(request);
|
|
23830
|
+
} else if (payload.framework) {
|
|
23831
|
+
const request = {
|
|
23832
|
+
testFiles: payload.testFiles || [],
|
|
23833
|
+
framework: payload.framework,
|
|
23834
|
+
timeout: payload.timeout,
|
|
23835
|
+
env: payload.env,
|
|
23836
|
+
reporters: payload.reporters
|
|
23837
|
+
};
|
|
23838
|
+
return this.coordinator.execute(request);
|
|
23839
|
+
}
|
|
23840
|
+
return err(new Error("Invalid execute-tests payload: missing testFiles or framework"));
|
|
23841
|
+
}],
|
|
23842
|
+
// Detect flaky tests task
|
|
23843
|
+
["detect-flaky", async (payload) => {
|
|
23844
|
+
if (!this.coordinator) {
|
|
23845
|
+
return err(new Error("Coordinator not initialized"));
|
|
23846
|
+
}
|
|
23847
|
+
const testFiles = payload.testFiles;
|
|
23848
|
+
const runs = payload.runs;
|
|
23849
|
+
const threshold = payload.threshold;
|
|
23850
|
+
if (!testFiles) {
|
|
23851
|
+
return err(new Error("Invalid detect-flaky payload: missing testFiles"));
|
|
23852
|
+
}
|
|
23853
|
+
return this.coordinator.detectFlaky({
|
|
23854
|
+
testFiles,
|
|
23855
|
+
runs: runs ?? 5,
|
|
23856
|
+
threshold: threshold ?? 0.1
|
|
23857
|
+
});
|
|
23858
|
+
}],
|
|
23859
|
+
// Retry failed tests task
|
|
23860
|
+
["retry-tests", async (payload) => {
|
|
23861
|
+
if (!this.coordinator) {
|
|
23862
|
+
return err(new Error("Coordinator not initialized"));
|
|
23863
|
+
}
|
|
23864
|
+
const runId = payload.runId;
|
|
23865
|
+
const failedTests = payload.failedTests;
|
|
23866
|
+
const maxRetries = payload.maxRetries;
|
|
23867
|
+
if (!runId || !failedTests) {
|
|
23868
|
+
return err(new Error("Invalid retry-tests payload: missing runId or failedTests"));
|
|
23869
|
+
}
|
|
23870
|
+
return this.coordinator.retry({
|
|
23871
|
+
runId,
|
|
23872
|
+
failedTests,
|
|
23873
|
+
maxRetries: maxRetries ?? 3,
|
|
23874
|
+
backoff: payload.backoff
|
|
23875
|
+
});
|
|
23876
|
+
}]
|
|
23877
|
+
]);
|
|
23878
|
+
}
|
|
23879
|
+
// ============================================================================
|
|
23449
23880
|
// Lifecycle Hooks
|
|
23450
23881
|
// ============================================================================
|
|
23451
23882
|
async onInitialize() {
|
|
@@ -23553,6 +23984,9 @@ function createTestExecutionPlugin(eventBus, memory) {
|
|
|
23553
23984
|
return new TestExecutionPlugin(eventBus, memory);
|
|
23554
23985
|
}
|
|
23555
23986
|
|
|
23987
|
+
// src/domains/coverage-analysis/plugin.ts
|
|
23988
|
+
init_types();
|
|
23989
|
+
|
|
23556
23990
|
// src/domains/coverage-analysis/coordinator.ts
|
|
23557
23991
|
init_types();
|
|
23558
23992
|
|
|
@@ -26003,6 +26437,75 @@ var CoverageAnalysisPlugin = class _CoverageAnalysisPlugin extends BaseDomainPlu
|
|
|
26003
26437
|
return this.coordinator;
|
|
26004
26438
|
}
|
|
26005
26439
|
// ============================================================================
|
|
26440
|
+
// Task Handlers (Queen-Domain Integration)
|
|
26441
|
+
// ============================================================================
|
|
26442
|
+
/**
|
|
26443
|
+
* Get task handlers for direct Queen-Domain integration
|
|
26444
|
+
* Maps task types to coordinator methods
|
|
26445
|
+
*/
|
|
26446
|
+
getTaskHandlers() {
|
|
26447
|
+
return /* @__PURE__ */ new Map([
|
|
26448
|
+
// Analyze coverage task - main task type for this domain
|
|
26449
|
+
["analyze-coverage", async (payload) => {
|
|
26450
|
+
const coverageData = payload.coverageData;
|
|
26451
|
+
if (!coverageData) {
|
|
26452
|
+
return err(new Error("Invalid analyze-coverage payload: missing coverageData"));
|
|
26453
|
+
}
|
|
26454
|
+
this._activeAnalyses++;
|
|
26455
|
+
this.updateAgentMetrics();
|
|
26456
|
+
try {
|
|
26457
|
+
return await this.coordinator.analyze({
|
|
26458
|
+
coverageData,
|
|
26459
|
+
threshold: payload.threshold,
|
|
26460
|
+
includeFileDetails: payload.includeFileDetails
|
|
26461
|
+
});
|
|
26462
|
+
} finally {
|
|
26463
|
+
this._activeAnalyses--;
|
|
26464
|
+
this.updateAgentMetrics();
|
|
26465
|
+
}
|
|
26466
|
+
}],
|
|
26467
|
+
// Detect gaps task
|
|
26468
|
+
["detect-gaps", async (payload) => {
|
|
26469
|
+
const coverageData = payload.coverageData;
|
|
26470
|
+
if (!coverageData) {
|
|
26471
|
+
return err(new Error("Invalid detect-gaps payload: missing coverageData"));
|
|
26472
|
+
}
|
|
26473
|
+
this._activeAnalyses++;
|
|
26474
|
+
this.updateAgentMetrics();
|
|
26475
|
+
try {
|
|
26476
|
+
return await this.coordinator.detectGaps({
|
|
26477
|
+
coverageData,
|
|
26478
|
+
minCoverage: payload.minCoverage,
|
|
26479
|
+
prioritize: payload.prioritize
|
|
26480
|
+
});
|
|
26481
|
+
} finally {
|
|
26482
|
+
this._activeAnalyses--;
|
|
26483
|
+
this.updateAgentMetrics();
|
|
26484
|
+
}
|
|
26485
|
+
}],
|
|
26486
|
+
// Calculate risk task
|
|
26487
|
+
["calculate-risk", async (payload) => {
|
|
26488
|
+
const file = payload.file;
|
|
26489
|
+
const uncoveredLines = payload.uncoveredLines;
|
|
26490
|
+
if (!file || !uncoveredLines) {
|
|
26491
|
+
return err(new Error("Invalid calculate-risk payload: missing file or uncoveredLines"));
|
|
26492
|
+
}
|
|
26493
|
+
this._activeAnalyses++;
|
|
26494
|
+
this.updateAgentMetrics();
|
|
26495
|
+
try {
|
|
26496
|
+
return await this.coordinator.calculateRisk({
|
|
26497
|
+
file,
|
|
26498
|
+
uncoveredLines,
|
|
26499
|
+
factors: payload.factors
|
|
26500
|
+
});
|
|
26501
|
+
} finally {
|
|
26502
|
+
this._activeAnalyses--;
|
|
26503
|
+
this.updateAgentMetrics();
|
|
26504
|
+
}
|
|
26505
|
+
}]
|
|
26506
|
+
]);
|
|
26507
|
+
}
|
|
26508
|
+
// ============================================================================
|
|
26006
26509
|
// Lifecycle Hooks
|
|
26007
26510
|
// ============================================================================
|
|
26008
26511
|
async onInitialize() {
|
|
@@ -26086,6 +26589,9 @@ function createCoverageAnalysisPlugin(eventBus, memory) {
|
|
|
26086
26589
|
return new CoverageAnalysisPlugin(eventBus, memory);
|
|
26087
26590
|
}
|
|
26088
26591
|
|
|
26592
|
+
// src/domains/quality-assessment/plugin.ts
|
|
26593
|
+
init_types();
|
|
26594
|
+
|
|
26089
26595
|
// src/domains/quality-assessment/coordinator.ts
|
|
26090
26596
|
init_types();
|
|
26091
26597
|
import { v4 as uuidv414 } from "uuid";
|
|
@@ -29461,6 +29967,8 @@ var QualityAssessmentCoordinator = class {
|
|
|
29461
29967
|
claimVerifier;
|
|
29462
29968
|
// Quality domain name for SONA
|
|
29463
29969
|
domain = "quality-assessment";
|
|
29970
|
+
// Cache of recent dream insights for quality assessment enhancement
|
|
29971
|
+
recentDreamInsights = [];
|
|
29464
29972
|
/**
|
|
29465
29973
|
* Initialize the coordinator
|
|
29466
29974
|
* Sets up Ruvector integrations: ActorCritic, QESONA, QEFlashAttention
|
|
@@ -29820,6 +30328,142 @@ var QualityAssessmentCoordinator = class {
|
|
|
29820
30328
|
"security-compliance.SecurityAuditCompleted",
|
|
29821
30329
|
this.handleSecurityAuditCompleted.bind(this)
|
|
29822
30330
|
);
|
|
30331
|
+
this.subscribeToDreamEvents();
|
|
30332
|
+
}
|
|
30333
|
+
// ============================================================================
|
|
30334
|
+
// Dream Event Handling (ADR-021 Integration)
|
|
30335
|
+
// ============================================================================
|
|
30336
|
+
/**
|
|
30337
|
+
* Subscribe to dream cycle completion events from learning-optimization domain.
|
|
30338
|
+
* Dream insights can suggest quality improvements, threshold adjustments, and risk patterns.
|
|
30339
|
+
*/
|
|
30340
|
+
subscribeToDreamEvents() {
|
|
30341
|
+
this.eventBus.subscribe(
|
|
30342
|
+
LearningOptimizationEvents.DreamCycleCompleted,
|
|
30343
|
+
this.handleDreamCycleCompleted.bind(this)
|
|
30344
|
+
);
|
|
30345
|
+
}
|
|
30346
|
+
/**
|
|
30347
|
+
* Handle dream cycle completion event.
|
|
30348
|
+
* Filters insights relevant to quality assessment and applies actionable ones.
|
|
30349
|
+
*/
|
|
30350
|
+
async handleDreamCycleCompleted(event) {
|
|
30351
|
+
const { insights, cycleId } = event.payload;
|
|
30352
|
+
if (!insights || insights.length === 0) {
|
|
30353
|
+
return;
|
|
30354
|
+
}
|
|
30355
|
+
const relevantInsights = insights.filter((insight) => {
|
|
30356
|
+
const actionRelevant = insight.suggestedAction?.toLowerCase().includes(this.domain) || insight.suggestedAction?.toLowerCase().includes("quality") || insight.suggestedAction?.toLowerCase().includes("gate") || insight.suggestedAction?.toLowerCase().includes("threshold");
|
|
30357
|
+
const conceptsRelevant = insight.sourceConcepts.some(
|
|
30358
|
+
(c) => c.toLowerCase().includes("quality") || c.toLowerCase().includes(this.domain) || c.toLowerCase().includes("metric") || c.toLowerCase().includes("gate")
|
|
30359
|
+
);
|
|
30360
|
+
const typeRelevant = insight.type === "optimization" || insight.type === "pattern_merge";
|
|
30361
|
+
return actionRelevant || conceptsRelevant || typeRelevant && insight.actionable;
|
|
30362
|
+
});
|
|
30363
|
+
if (relevantInsights.length === 0) {
|
|
30364
|
+
return;
|
|
30365
|
+
}
|
|
30366
|
+
console.log(
|
|
30367
|
+
`[${this.domain}] Received ${relevantInsights.length} relevant dream insights from cycle ${cycleId}`
|
|
30368
|
+
);
|
|
30369
|
+
for (const insight of relevantInsights) {
|
|
30370
|
+
if (insight.confidenceScore > 0.7 && insight.actionable) {
|
|
30371
|
+
await this.applyDreamInsight(insight, cycleId);
|
|
30372
|
+
}
|
|
30373
|
+
this.recentDreamInsights.push({
|
|
30374
|
+
...insight,
|
|
30375
|
+
receivedAt: /* @__PURE__ */ new Date()
|
|
30376
|
+
});
|
|
30377
|
+
}
|
|
30378
|
+
if (this.recentDreamInsights.length > 50) {
|
|
30379
|
+
this.recentDreamInsights = this.recentDreamInsights.slice(-50);
|
|
30380
|
+
}
|
|
30381
|
+
}
|
|
30382
|
+
/**
|
|
30383
|
+
* Apply a dream insight by storing it as a learned pattern via SONA.
|
|
30384
|
+
* This allows the insight to influence future quality assessment decisions.
|
|
30385
|
+
*
|
|
30386
|
+
* @param insight - The dream insight to apply
|
|
30387
|
+
* @param cycleId - The dream cycle ID for tracking
|
|
30388
|
+
*/
|
|
30389
|
+
async applyDreamInsight(insight, cycleId) {
|
|
30390
|
+
console.log(
|
|
30391
|
+
`[${this.domain}] Applying dream insight: ${insight.description.slice(0, 100)}...`
|
|
30392
|
+
);
|
|
30393
|
+
if (this.qesona) {
|
|
30394
|
+
try {
|
|
30395
|
+
const state2 = {
|
|
30396
|
+
id: `dream-insight-${insight.id}`,
|
|
30397
|
+
features: this.encodeInsightAsFeatures(insight),
|
|
30398
|
+
metadata: {
|
|
30399
|
+
insightType: insight.type,
|
|
30400
|
+
cycleId,
|
|
30401
|
+
sourceConcepts: insight.sourceConcepts
|
|
30402
|
+
}
|
|
30403
|
+
};
|
|
30404
|
+
const action = {
|
|
30405
|
+
type: "dream-insight",
|
|
30406
|
+
value: insight.suggestedAction || insight.description
|
|
30407
|
+
};
|
|
30408
|
+
this.qesona.createPattern(
|
|
30409
|
+
state2,
|
|
30410
|
+
action,
|
|
30411
|
+
{
|
|
30412
|
+
reward: insight.confidenceScore,
|
|
30413
|
+
success: true,
|
|
30414
|
+
quality: insight.noveltyScore
|
|
30415
|
+
},
|
|
30416
|
+
"quality-assessment",
|
|
30417
|
+
this.domain,
|
|
30418
|
+
{
|
|
30419
|
+
insightId: insight.id,
|
|
30420
|
+
cycleId,
|
|
30421
|
+
description: insight.description,
|
|
30422
|
+
suggestedAction: insight.suggestedAction,
|
|
30423
|
+
dreamDerived: true
|
|
30424
|
+
}
|
|
30425
|
+
);
|
|
30426
|
+
console.log(
|
|
30427
|
+
`[${this.domain}] Created SONA pattern from dream insight ${insight.id}`
|
|
30428
|
+
);
|
|
30429
|
+
} catch (error) {
|
|
30430
|
+
console.error(
|
|
30431
|
+
`[${this.domain}] Failed to store dream insight pattern:`,
|
|
30432
|
+
error
|
|
30433
|
+
);
|
|
30434
|
+
}
|
|
30435
|
+
}
|
|
30436
|
+
await this.memory.set(
|
|
30437
|
+
`${this.domain}:dream-insight:${insight.id}`,
|
|
30438
|
+
{
|
|
30439
|
+
insight,
|
|
30440
|
+
cycleId,
|
|
30441
|
+
appliedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
30442
|
+
},
|
|
30443
|
+
{ namespace: this.domain, ttl: 86400 * 7 }
|
|
30444
|
+
// 7 days
|
|
30445
|
+
);
|
|
30446
|
+
}
|
|
30447
|
+
/**
|
|
30448
|
+
* Encode a dream insight as feature vector for SONA pattern creation.
|
|
30449
|
+
*/
|
|
30450
|
+
encodeInsightAsFeatures(insight) {
|
|
30451
|
+
const features = [];
|
|
30452
|
+
const typeMap = {
|
|
30453
|
+
pattern_merge: 0.2,
|
|
30454
|
+
novel_association: 0.4,
|
|
30455
|
+
optimization: 0.6,
|
|
30456
|
+
gap_detection: 0.8
|
|
30457
|
+
};
|
|
30458
|
+
features.push(typeMap[insight.type] || 0.5);
|
|
30459
|
+
features.push(insight.confidenceScore);
|
|
30460
|
+
features.push(insight.noveltyScore);
|
|
30461
|
+
features.push(insight.actionable ? 1 : 0);
|
|
30462
|
+
features.push(Math.min(1, insight.sourceConcepts.length / 10));
|
|
30463
|
+
while (features.length < 384) {
|
|
30464
|
+
features.push(0);
|
|
30465
|
+
}
|
|
30466
|
+
return features.slice(0, 384);
|
|
29823
30467
|
}
|
|
29824
30468
|
async handleTestRunCompleted(event) {
|
|
29825
30469
|
if (!this.config.enableAutoGating) return;
|
|
@@ -30392,6 +31036,72 @@ var QualityAssessmentPlugin = class extends BaseDomainPlugin {
|
|
|
30392
31036
|
return api;
|
|
30393
31037
|
}
|
|
30394
31038
|
// ============================================================================
|
|
31039
|
+
// Task Handlers (Queen-Domain Integration)
|
|
31040
|
+
// ============================================================================
|
|
31041
|
+
/**
|
|
31042
|
+
* Get task handlers for direct Queen-Domain integration
|
|
31043
|
+
* Maps task types to coordinator methods
|
|
31044
|
+
*/
|
|
31045
|
+
getTaskHandlers() {
|
|
31046
|
+
return /* @__PURE__ */ new Map([
|
|
31047
|
+
// Evaluate quality gate task - main task type for this domain
|
|
31048
|
+
["evaluate-gate", async (payload) => {
|
|
31049
|
+
const gateName = payload.gateName;
|
|
31050
|
+
const metrics = payload.metrics;
|
|
31051
|
+
const thresholds = payload.thresholds;
|
|
31052
|
+
if (!gateName || !metrics || !thresholds) {
|
|
31053
|
+
return err(new Error("Invalid evaluate-gate payload: missing gateName, metrics, or thresholds"));
|
|
31054
|
+
}
|
|
31055
|
+
const request = {
|
|
31056
|
+
gateName,
|
|
31057
|
+
metrics,
|
|
31058
|
+
thresholds
|
|
31059
|
+
};
|
|
31060
|
+
return this.evaluateGate(request);
|
|
31061
|
+
}],
|
|
31062
|
+
// Analyze quality task
|
|
31063
|
+
["analyze-quality", async (payload) => {
|
|
31064
|
+
const sourceFiles = payload.sourceFiles;
|
|
31065
|
+
if (!sourceFiles || sourceFiles.length === 0) {
|
|
31066
|
+
return err(new Error("Invalid analyze-quality payload: missing sourceFiles"));
|
|
31067
|
+
}
|
|
31068
|
+
const request = {
|
|
31069
|
+
sourceFiles,
|
|
31070
|
+
includeMetrics: payload.includeMetrics ?? ["coverage", "complexity", "maintainability"],
|
|
31071
|
+
compareBaseline: payload.compareBaseline
|
|
31072
|
+
};
|
|
31073
|
+
return this.analyzeQuality(request);
|
|
31074
|
+
}],
|
|
31075
|
+
// Get deployment advice task
|
|
31076
|
+
["deployment-advice", async (payload) => {
|
|
31077
|
+
const releaseCandidate = payload.releaseCandidate;
|
|
31078
|
+
const metrics = payload.metrics;
|
|
31079
|
+
const riskTolerance = payload.riskTolerance;
|
|
31080
|
+
if (!releaseCandidate || !metrics) {
|
|
31081
|
+
return err(new Error("Invalid deployment-advice payload: missing releaseCandidate or metrics"));
|
|
31082
|
+
}
|
|
31083
|
+
const request = {
|
|
31084
|
+
releaseCandidate,
|
|
31085
|
+
metrics,
|
|
31086
|
+
riskTolerance: riskTolerance ?? "medium"
|
|
31087
|
+
};
|
|
31088
|
+
return this.getDeploymentAdvice(request);
|
|
31089
|
+
}],
|
|
31090
|
+
// Analyze complexity task
|
|
31091
|
+
["analyze-complexity", async (payload) => {
|
|
31092
|
+
const sourceFiles = payload.sourceFiles;
|
|
31093
|
+
if (!sourceFiles || sourceFiles.length === 0) {
|
|
31094
|
+
return err(new Error("Invalid analyze-complexity payload: missing sourceFiles"));
|
|
31095
|
+
}
|
|
31096
|
+
const request = {
|
|
31097
|
+
sourceFiles,
|
|
31098
|
+
metrics: payload.metrics ?? ["cyclomatic", "cognitive"]
|
|
31099
|
+
};
|
|
31100
|
+
return this.analyzeComplexity(request);
|
|
31101
|
+
}]
|
|
31102
|
+
]);
|
|
31103
|
+
}
|
|
31104
|
+
// ============================================================================
|
|
30395
31105
|
// Lifecycle Methods
|
|
30396
31106
|
// ============================================================================
|
|
30397
31107
|
async onInitialize() {
|
|
@@ -62074,7 +62784,7 @@ init_types();
|
|
|
62074
62784
|
|
|
62075
62785
|
// src/domains/learning-optimization/coordinator.ts
|
|
62076
62786
|
init_types();
|
|
62077
|
-
import { v4 as
|
|
62787
|
+
import { v4 as uuidv445 } from "uuid";
|
|
62078
62788
|
|
|
62079
62789
|
// src/domains/learning-optimization/services/learning-coordinator.ts
|
|
62080
62790
|
init_types();
|
|
@@ -64403,316 +65113,2689 @@ var ProductionIntelService = class {
|
|
|
64403
65113
|
"Multiple critical incidents detected. Consider system-wide review."
|
|
64404
65114
|
);
|
|
64405
65115
|
}
|
|
64406
|
-
if (recommendations.length === 0) {
|
|
64407
|
-
recommendations.push("All systems operating within normal parameters.");
|
|
64408
|
-
}
|
|
64409
|
-
return recommendations;
|
|
65116
|
+
if (recommendations.length === 0) {
|
|
65117
|
+
recommendations.push("All systems operating within normal parameters.");
|
|
65118
|
+
}
|
|
65119
|
+
return recommendations;
|
|
65120
|
+
}
|
|
65121
|
+
// ============================================================================
|
|
65122
|
+
// Intelligence Extraction
|
|
65123
|
+
// ============================================================================
|
|
65124
|
+
/**
|
|
65125
|
+
* Extract insights from production data
|
|
65126
|
+
*/
|
|
65127
|
+
async extractInsights(timeRange, domain) {
|
|
65128
|
+
try {
|
|
65129
|
+
const metricsResult = await this.getMetricsHistory("*", timeRange, domain);
|
|
65130
|
+
const metrics = metricsResult.success ? metricsResult.value : [];
|
|
65131
|
+
const incidentsResult = await this.getRecentIncidents(50, domain);
|
|
65132
|
+
const incidents = incidentsResult.success ? incidentsResult.value : [];
|
|
65133
|
+
const experienceCount = metrics.length;
|
|
65134
|
+
const resolvedIncidents = incidents.filter((i) => i.resolvedAt);
|
|
65135
|
+
const successRate = incidents.length > 0 ? resolvedIncidents.length / incidents.length : 1;
|
|
65136
|
+
const avgReward = this.calculateRewardFromIncidents(incidents);
|
|
65137
|
+
const recommendations = this.generateInsightRecommendations(
|
|
65138
|
+
metrics,
|
|
65139
|
+
incidents
|
|
65140
|
+
);
|
|
65141
|
+
const anomalies = this.detectMetricAnomalies(metrics);
|
|
65142
|
+
return ok({
|
|
65143
|
+
experienceCount,
|
|
65144
|
+
successRate,
|
|
65145
|
+
avgReward,
|
|
65146
|
+
patterns: [],
|
|
65147
|
+
anomalies,
|
|
65148
|
+
recommendations
|
|
65149
|
+
});
|
|
65150
|
+
} catch (error) {
|
|
65151
|
+
return err(error instanceof Error ? error : new Error(String(error)));
|
|
65152
|
+
}
|
|
65153
|
+
}
|
|
65154
|
+
/**
|
|
65155
|
+
* Record production milestone
|
|
65156
|
+
*/
|
|
65157
|
+
async recordMilestone(name, domain, metrics) {
|
|
65158
|
+
try {
|
|
65159
|
+
const milestone = {
|
|
65160
|
+
name,
|
|
65161
|
+
achievedAt: /* @__PURE__ */ new Date(),
|
|
65162
|
+
domain
|
|
65163
|
+
};
|
|
65164
|
+
await this.memory.set(
|
|
65165
|
+
`production:milestone:${uuidv441()}`,
|
|
65166
|
+
{ ...milestone, metrics },
|
|
65167
|
+
{ namespace: "learning-optimization", persist: true }
|
|
65168
|
+
);
|
|
65169
|
+
return ok(milestone);
|
|
65170
|
+
} catch (error) {
|
|
65171
|
+
return err(error instanceof Error ? error : new Error(String(error)));
|
|
65172
|
+
}
|
|
65173
|
+
}
|
|
65174
|
+
/**
|
|
65175
|
+
* Get recent milestones
|
|
65176
|
+
*/
|
|
65177
|
+
async getRecentMilestones(limit = 10) {
|
|
65178
|
+
try {
|
|
65179
|
+
const keys = await this.memory.search("production:milestone:*", limit);
|
|
65180
|
+
const milestones = [];
|
|
65181
|
+
for (const key of keys) {
|
|
65182
|
+
const milestone = await this.memory.get(key);
|
|
65183
|
+
if (milestone) {
|
|
65184
|
+
milestones.push(milestone);
|
|
65185
|
+
}
|
|
65186
|
+
}
|
|
65187
|
+
milestones.sort((a, b) => b.achievedAt.getTime() - a.achievedAt.getTime());
|
|
65188
|
+
return ok(milestones.slice(0, limit));
|
|
65189
|
+
} catch (error) {
|
|
65190
|
+
return err(error instanceof Error ? error : new Error(String(error)));
|
|
65191
|
+
}
|
|
65192
|
+
}
|
|
65193
|
+
// ============================================================================
|
|
65194
|
+
// Private Helper Methods
|
|
65195
|
+
// ============================================================================
|
|
65196
|
+
async indexMetric(metric) {
|
|
65197
|
+
await this.memory.set(
|
|
65198
|
+
`production:metric:index:${metric.name}:${metric.domain}:${metric.id}`,
|
|
65199
|
+
metric.id,
|
|
65200
|
+
{
|
|
65201
|
+
namespace: "learning-optimization",
|
|
65202
|
+
ttl: this.config.metricsRetentionDays * 86400
|
|
65203
|
+
}
|
|
65204
|
+
);
|
|
65205
|
+
}
|
|
65206
|
+
async indexIncident(incident) {
|
|
65207
|
+
await this.memory.set(
|
|
65208
|
+
`production:incident:index:domain:${incident.domain}:${incident.id}`,
|
|
65209
|
+
incident.id,
|
|
65210
|
+
{ namespace: "learning-optimization", persist: true }
|
|
65211
|
+
);
|
|
65212
|
+
await this.memory.set(
|
|
65213
|
+
`production:incident:index:severity:${incident.severity}:${incident.id}`,
|
|
65214
|
+
incident.id,
|
|
65215
|
+
{ namespace: "learning-optimization", persist: true }
|
|
65216
|
+
);
|
|
65217
|
+
}
|
|
65218
|
+
async checkForAnomalies(metric) {
|
|
65219
|
+
const timeRange = TimeRange.lastNDays(7);
|
|
65220
|
+
const historyResult = await this.getMetricsHistory(
|
|
65221
|
+
metric.name,
|
|
65222
|
+
timeRange,
|
|
65223
|
+
metric.domain
|
|
65224
|
+
);
|
|
65225
|
+
if (!historyResult.success || historyResult.value.length < 10) {
|
|
65226
|
+
return;
|
|
65227
|
+
}
|
|
65228
|
+
const values = historyResult.value.map((m) => m.value);
|
|
65229
|
+
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
|
65230
|
+
const stdDev = Math.sqrt(
|
|
65231
|
+
values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length
|
|
65232
|
+
);
|
|
65233
|
+
const deviation = Math.abs(metric.value - mean) / (stdDev || 1);
|
|
65234
|
+
if (deviation > this.config.anomalyThreshold) {
|
|
65235
|
+
await this.memory.set(
|
|
65236
|
+
`production:anomaly:${uuidv441()}`,
|
|
65237
|
+
{
|
|
65238
|
+
metricId: metric.id,
|
|
65239
|
+
metricName: metric.name,
|
|
65240
|
+
value: metric.value,
|
|
65241
|
+
mean,
|
|
65242
|
+
stdDev,
|
|
65243
|
+
deviation,
|
|
65244
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
65245
|
+
},
|
|
65246
|
+
{ namespace: "learning-optimization", ttl: 86400 * 7 }
|
|
65247
|
+
);
|
|
65248
|
+
}
|
|
65249
|
+
}
|
|
65250
|
+
async createExperienceFromIncident(incident) {
|
|
65251
|
+
const state2 = {
|
|
65252
|
+
context: {
|
|
65253
|
+
incidentId: incident.id,
|
|
65254
|
+
severity: incident.severity,
|
|
65255
|
+
domain: incident.domain
|
|
65256
|
+
},
|
|
65257
|
+
metrics: incident.metrics
|
|
65258
|
+
};
|
|
65259
|
+
const result = {
|
|
65260
|
+
success: false,
|
|
65261
|
+
outcome: incident.metrics,
|
|
65262
|
+
duration: 0
|
|
65263
|
+
};
|
|
65264
|
+
const experience = {
|
|
65265
|
+
id: uuidv441(),
|
|
65266
|
+
agentId: {
|
|
65267
|
+
value: "production-intel",
|
|
65268
|
+
domain: "learning-optimization",
|
|
65269
|
+
type: "analyzer"
|
|
65270
|
+
},
|
|
65271
|
+
domain: incident.domain,
|
|
65272
|
+
action: `incident-${incident.severity}`,
|
|
65273
|
+
state: state2,
|
|
65274
|
+
result,
|
|
65275
|
+
reward: this.calculateIncidentReward(incident),
|
|
65276
|
+
timestamp: incident.startedAt
|
|
65277
|
+
};
|
|
65278
|
+
await this.memory.set(
|
|
65279
|
+
`learning:experience:${experience.id}`,
|
|
65280
|
+
experience,
|
|
65281
|
+
{ namespace: "learning-optimization", ttl: 86400 * 30 }
|
|
65282
|
+
);
|
|
65283
|
+
}
|
|
65284
|
+
async updateExperienceWithResolution(incident) {
|
|
65285
|
+
if (!incident.resolvedAt) return;
|
|
65286
|
+
const state2 = {
|
|
65287
|
+
context: {
|
|
65288
|
+
incidentId: incident.id,
|
|
65289
|
+
rootCause: incident.rootCause,
|
|
65290
|
+
resolution: incident.resolution
|
|
65291
|
+
},
|
|
65292
|
+
metrics: incident.metrics
|
|
65293
|
+
};
|
|
65294
|
+
const duration = incident.resolvedAt.getTime() - incident.startedAt.getTime();
|
|
65295
|
+
const result = {
|
|
65296
|
+
success: true,
|
|
65297
|
+
outcome: {
|
|
65298
|
+
...incident.metrics,
|
|
65299
|
+
resolution_time_ms: duration
|
|
65300
|
+
},
|
|
65301
|
+
duration
|
|
65302
|
+
};
|
|
65303
|
+
const experience = {
|
|
65304
|
+
id: uuidv441(),
|
|
65305
|
+
agentId: {
|
|
65306
|
+
value: "production-intel",
|
|
65307
|
+
domain: "learning-optimization",
|
|
65308
|
+
type: "analyzer"
|
|
65309
|
+
},
|
|
65310
|
+
domain: incident.domain,
|
|
65311
|
+
action: `resolution-${incident.severity}`,
|
|
65312
|
+
state: state2,
|
|
65313
|
+
result,
|
|
65314
|
+
reward: 1 - this.calculateIncidentReward(incident),
|
|
65315
|
+
// Inverse - resolution is good
|
|
65316
|
+
timestamp: incident.resolvedAt
|
|
65317
|
+
};
|
|
65318
|
+
await this.memory.set(
|
|
65319
|
+
`learning:experience:${experience.id}`,
|
|
65320
|
+
experience,
|
|
65321
|
+
{ namespace: "learning-optimization", ttl: 86400 * 30 }
|
|
65322
|
+
);
|
|
65323
|
+
}
|
|
65324
|
+
calculateIncidentReward(incident) {
|
|
65325
|
+
const severityScores = {
|
|
65326
|
+
critical: 0.9,
|
|
65327
|
+
high: 0.7,
|
|
65328
|
+
medium: 0.4,
|
|
65329
|
+
low: 0.2
|
|
65330
|
+
};
|
|
65331
|
+
return -(severityScores[incident.severity] || 0.5);
|
|
65332
|
+
}
|
|
65333
|
+
calculateRewardFromIncidents(incidents) {
|
|
65334
|
+
if (incidents.length === 0) return 0.8;
|
|
65335
|
+
const severityWeights = {
|
|
65336
|
+
critical: 0.1,
|
|
65337
|
+
high: 0.3,
|
|
65338
|
+
medium: 0.6,
|
|
65339
|
+
low: 0.8
|
|
65340
|
+
};
|
|
65341
|
+
let totalReward = 0;
|
|
65342
|
+
let count = 0;
|
|
65343
|
+
for (const incident of incidents) {
|
|
65344
|
+
const base = severityWeights[incident.severity] || 0.5;
|
|
65345
|
+
const resolved = incident.resolvedAt ? 0.2 : 0;
|
|
65346
|
+
totalReward += base + resolved;
|
|
65347
|
+
count++;
|
|
65348
|
+
}
|
|
65349
|
+
return count > 0 ? totalReward / count : 0.8;
|
|
65350
|
+
}
|
|
65351
|
+
generateInsightRecommendations(metrics, incidents) {
|
|
65352
|
+
const recommendations = [];
|
|
65353
|
+
const metricGroups = /* @__PURE__ */ new Map();
|
|
65354
|
+
for (const metric of metrics) {
|
|
65355
|
+
const existing = metricGroups.get(metric.name) || [];
|
|
65356
|
+
existing.push(metric.value);
|
|
65357
|
+
metricGroups.set(metric.name, existing);
|
|
65358
|
+
}
|
|
65359
|
+
for (const [name, values] of metricGroups) {
|
|
65360
|
+
const trend = this.calculateTrendDirection(values);
|
|
65361
|
+
if (trend === "increasing" && name.includes("error")) {
|
|
65362
|
+
recommendations.push(`${name} is trending upward. Investigate root causes.`);
|
|
65363
|
+
} else if (trend === "decreasing" && name.includes("success")) {
|
|
65364
|
+
recommendations.push(`${name} is declining. Review recent changes.`);
|
|
65365
|
+
}
|
|
65366
|
+
}
|
|
65367
|
+
if (incidents.length > 0) {
|
|
65368
|
+
const domainIncidents = /* @__PURE__ */ new Map();
|
|
65369
|
+
for (const incident of incidents) {
|
|
65370
|
+
domainIncidents.set(
|
|
65371
|
+
incident.domain,
|
|
65372
|
+
(domainIncidents.get(incident.domain) || 0) + 1
|
|
65373
|
+
);
|
|
65374
|
+
}
|
|
65375
|
+
for (const [domain, count] of domainIncidents) {
|
|
65376
|
+
if (count > 3) {
|
|
65377
|
+
recommendations.push(
|
|
65378
|
+
`Domain ${domain} has ${count} incidents. Consider preventive measures.`
|
|
65379
|
+
);
|
|
65380
|
+
}
|
|
65381
|
+
}
|
|
65382
|
+
}
|
|
65383
|
+
return recommendations;
|
|
65384
|
+
}
|
|
65385
|
+
detectMetricAnomalies(metrics) {
|
|
65386
|
+
const anomalies = [];
|
|
65387
|
+
const groups = /* @__PURE__ */ new Map();
|
|
65388
|
+
for (const metric of metrics) {
|
|
65389
|
+
const existing = groups.get(metric.name) || [];
|
|
65390
|
+
existing.push(metric);
|
|
65391
|
+
groups.set(metric.name, existing);
|
|
65392
|
+
}
|
|
65393
|
+
for (const [name, groupMetrics] of groups) {
|
|
65394
|
+
if (groupMetrics.length < 5) continue;
|
|
65395
|
+
const values = groupMetrics.map((m) => m.value);
|
|
65396
|
+
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
|
65397
|
+
const stdDev = Math.sqrt(
|
|
65398
|
+
values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length
|
|
65399
|
+
);
|
|
65400
|
+
for (const metric of groupMetrics) {
|
|
65401
|
+
const deviation = Math.abs(metric.value - mean) / (stdDev || 1);
|
|
65402
|
+
if (deviation > this.config.anomalyThreshold) {
|
|
65403
|
+
anomalies.push({
|
|
65404
|
+
experienceId: metric.id,
|
|
65405
|
+
type: "outlier-reward",
|
|
65406
|
+
description: `${name} value ${metric.value.toFixed(2)} is ${deviation.toFixed(1)} std deviations from mean`,
|
|
65407
|
+
deviation
|
|
65408
|
+
});
|
|
65409
|
+
}
|
|
65410
|
+
}
|
|
65411
|
+
}
|
|
65412
|
+
return anomalies;
|
|
65413
|
+
}
|
|
65414
|
+
calculateTrendDirection(values) {
|
|
65415
|
+
if (values.length < 3) return "stable";
|
|
65416
|
+
const firstHalf = values.slice(0, Math.floor(values.length / 2));
|
|
65417
|
+
const secondHalf = values.slice(Math.floor(values.length / 2));
|
|
65418
|
+
const firstAvg = firstHalf.reduce((a, b) => a + b, 0) / firstHalf.length;
|
|
65419
|
+
const secondAvg = secondHalf.reduce((a, b) => a + b, 0) / secondHalf.length;
|
|
65420
|
+
const change = (secondAvg - firstAvg) / (firstAvg || 1);
|
|
65421
|
+
if (change > 0.1) return "increasing";
|
|
65422
|
+
if (change < -0.1) return "decreasing";
|
|
65423
|
+
return "stable";
|
|
65424
|
+
}
|
|
65425
|
+
};
|
|
65426
|
+
|
|
65427
|
+
// src/learning/dream/types.ts
|
|
65428
|
+
var DEFAULT_CONCEPT_GRAPH_CONFIG = {
|
|
65429
|
+
// IGNORED: ConceptGraph uses getUnifiedPersistence() which uses memory.db (ADR-046)
|
|
65430
|
+
dbPath: ".aqe/dream.db",
|
|
65431
|
+
similarityThreshold: 0.5,
|
|
65432
|
+
maxEdgesPerNode: 20,
|
|
65433
|
+
walMode: true,
|
|
65434
|
+
debug: false
|
|
65435
|
+
};
|
|
65436
|
+
|
|
65437
|
+
// src/learning/dream/concept-graph.ts
|
|
65438
|
+
import { v4 as uuidv442 } from "uuid";
|
|
65439
|
+
var ConceptGraph = class {
|
|
65440
|
+
config;
|
|
65441
|
+
db = null;
|
|
65442
|
+
persistence = null;
|
|
65443
|
+
prepared = /* @__PURE__ */ new Map();
|
|
65444
|
+
initialized = false;
|
|
65445
|
+
constructor(config) {
|
|
65446
|
+
this.config = { ...DEFAULT_CONCEPT_GRAPH_CONFIG, ...config };
|
|
65447
|
+
}
|
|
65448
|
+
// ==========================================================================
|
|
65449
|
+
// Initialization
|
|
65450
|
+
// ==========================================================================
|
|
65451
|
+
/**
|
|
65452
|
+
* Initialize using unified persistence
|
|
65453
|
+
*/
|
|
65454
|
+
async initialize() {
|
|
65455
|
+
if (this.initialized) return;
|
|
65456
|
+
try {
|
|
65457
|
+
this.persistence = getUnifiedPersistence();
|
|
65458
|
+
if (!this.persistence.isInitialized()) {
|
|
65459
|
+
await this.persistence.initialize();
|
|
65460
|
+
}
|
|
65461
|
+
this.db = this.persistence.getDatabase();
|
|
65462
|
+
this.prepareStatements();
|
|
65463
|
+
this.initialized = true;
|
|
65464
|
+
if (this.config.debug) {
|
|
65465
|
+
const stats = await this.getStats();
|
|
65466
|
+
console.log(`[ConceptGraph] Initialized: ${this.persistence.getDbPath()}`, stats);
|
|
65467
|
+
}
|
|
65468
|
+
} catch (error) {
|
|
65469
|
+
throw new Error(
|
|
65470
|
+
`Failed to initialize ConceptGraph: ${error instanceof Error ? error.message : String(error)}`
|
|
65471
|
+
);
|
|
65472
|
+
}
|
|
65473
|
+
}
|
|
65474
|
+
/**
|
|
65475
|
+
* Prepare commonly used SQL statements
|
|
65476
|
+
*/
|
|
65477
|
+
prepareStatements() {
|
|
65478
|
+
if (!this.db) throw new Error("Database not initialized");
|
|
65479
|
+
this.prepared.set(
|
|
65480
|
+
"insertNode",
|
|
65481
|
+
this.db.prepare(`
|
|
65482
|
+
INSERT INTO concept_nodes
|
|
65483
|
+
(id, concept_type, content, embedding, activation_level, last_activated, pattern_id, metadata)
|
|
65484
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
65485
|
+
`)
|
|
65486
|
+
);
|
|
65487
|
+
this.prepared.set(
|
|
65488
|
+
"getNode",
|
|
65489
|
+
this.db.prepare(`
|
|
65490
|
+
SELECT * FROM concept_nodes WHERE id = ?
|
|
65491
|
+
`)
|
|
65492
|
+
);
|
|
65493
|
+
this.prepared.set(
|
|
65494
|
+
"updateActivation",
|
|
65495
|
+
this.db.prepare(`
|
|
65496
|
+
UPDATE concept_nodes
|
|
65497
|
+
SET activation_level = ?, last_activated = datetime('now')
|
|
65498
|
+
WHERE id = ?
|
|
65499
|
+
`)
|
|
65500
|
+
);
|
|
65501
|
+
this.prepared.set(
|
|
65502
|
+
"getActiveNodes",
|
|
65503
|
+
this.db.prepare(`
|
|
65504
|
+
SELECT * FROM concept_nodes
|
|
65505
|
+
WHERE activation_level >= ?
|
|
65506
|
+
ORDER BY activation_level DESC
|
|
65507
|
+
`)
|
|
65508
|
+
);
|
|
65509
|
+
this.prepared.set(
|
|
65510
|
+
"getNodesByType",
|
|
65511
|
+
this.db.prepare(`
|
|
65512
|
+
SELECT * FROM concept_nodes WHERE concept_type = ?
|
|
65513
|
+
`)
|
|
65514
|
+
);
|
|
65515
|
+
this.prepared.set(
|
|
65516
|
+
"getAllNodes",
|
|
65517
|
+
this.db.prepare(`
|
|
65518
|
+
SELECT * FROM concept_nodes
|
|
65519
|
+
`)
|
|
65520
|
+
);
|
|
65521
|
+
this.prepared.set(
|
|
65522
|
+
"insertEdge",
|
|
65523
|
+
this.db.prepare(`
|
|
65524
|
+
INSERT INTO concept_edges
|
|
65525
|
+
(id, source, target, edge_type, weight, evidence)
|
|
65526
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
65527
|
+
`)
|
|
65528
|
+
);
|
|
65529
|
+
this.prepared.set(
|
|
65530
|
+
"getEdge",
|
|
65531
|
+
this.db.prepare(`
|
|
65532
|
+
SELECT * FROM concept_edges WHERE source = ? AND target = ?
|
|
65533
|
+
`)
|
|
65534
|
+
);
|
|
65535
|
+
this.prepared.set(
|
|
65536
|
+
"updateEdge",
|
|
65537
|
+
this.db.prepare(`
|
|
65538
|
+
UPDATE concept_edges
|
|
65539
|
+
SET weight = ?, evidence = evidence + 1, updated_at = datetime('now')
|
|
65540
|
+
WHERE source = ? AND target = ?
|
|
65541
|
+
`)
|
|
65542
|
+
);
|
|
65543
|
+
this.prepared.set(
|
|
65544
|
+
"getOutgoingEdges",
|
|
65545
|
+
this.db.prepare(`
|
|
65546
|
+
SELECT * FROM concept_edges WHERE source = ?
|
|
65547
|
+
`)
|
|
65548
|
+
);
|
|
65549
|
+
this.prepared.set(
|
|
65550
|
+
"getIncomingEdges",
|
|
65551
|
+
this.db.prepare(`
|
|
65552
|
+
SELECT * FROM concept_edges WHERE target = ?
|
|
65553
|
+
`)
|
|
65554
|
+
);
|
|
65555
|
+
this.prepared.set(
|
|
65556
|
+
"countNodes",
|
|
65557
|
+
this.db.prepare(`
|
|
65558
|
+
SELECT COUNT(*) as count FROM concept_nodes
|
|
65559
|
+
`)
|
|
65560
|
+
);
|
|
65561
|
+
this.prepared.set(
|
|
65562
|
+
"countEdges",
|
|
65563
|
+
this.db.prepare(`
|
|
65564
|
+
SELECT COUNT(*) as count FROM concept_edges
|
|
65565
|
+
`)
|
|
65566
|
+
);
|
|
65567
|
+
this.prepared.set(
|
|
65568
|
+
"countByType",
|
|
65569
|
+
this.db.prepare(`
|
|
65570
|
+
SELECT concept_type, COUNT(*) as count FROM concept_nodes GROUP BY concept_type
|
|
65571
|
+
`)
|
|
65572
|
+
);
|
|
65573
|
+
}
|
|
65574
|
+
// ==========================================================================
|
|
65575
|
+
// Node Operations
|
|
65576
|
+
// ==========================================================================
|
|
65577
|
+
/**
|
|
65578
|
+
* Add a new concept node to the graph
|
|
65579
|
+
* @returns The ID of the created node
|
|
65580
|
+
*/
|
|
65581
|
+
async addNode(node) {
|
|
65582
|
+
this.ensureInitialized();
|
|
65583
|
+
const id = uuidv442();
|
|
65584
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
65585
|
+
const stmt = this.prepared.get("insertNode");
|
|
65586
|
+
if (!stmt) throw new Error("Prepared statement not found: insertNode");
|
|
65587
|
+
const embeddingBlob = node.embedding ? Buffer.from(new Float32Array(node.embedding).buffer) : null;
|
|
65588
|
+
stmt.run(
|
|
65589
|
+
id,
|
|
65590
|
+
node.conceptType,
|
|
65591
|
+
node.content,
|
|
65592
|
+
embeddingBlob,
|
|
65593
|
+
0,
|
|
65594
|
+
// Initial activation level
|
|
65595
|
+
now,
|
|
65596
|
+
node.patternId || null,
|
|
65597
|
+
node.metadata ? JSON.stringify(node.metadata) : null
|
|
65598
|
+
);
|
|
65599
|
+
if (this.config.debug) {
|
|
65600
|
+
console.log(`[ConceptGraph] Added node: ${id} (${node.conceptType})`);
|
|
65601
|
+
}
|
|
65602
|
+
return id;
|
|
65603
|
+
}
|
|
65604
|
+
/**
|
|
65605
|
+
* Get a concept node by ID
|
|
65606
|
+
*/
|
|
65607
|
+
async getNode(id) {
|
|
65608
|
+
this.ensureInitialized();
|
|
65609
|
+
const stmt = this.prepared.get("getNode");
|
|
65610
|
+
if (!stmt) throw new Error("Prepared statement not found: getNode");
|
|
65611
|
+
const row = stmt.get(id);
|
|
65612
|
+
if (!row) return null;
|
|
65613
|
+
return this.rowToNode(row);
|
|
65614
|
+
}
|
|
65615
|
+
/**
|
|
65616
|
+
* Update the activation level of a node
|
|
65617
|
+
*/
|
|
65618
|
+
async updateActivation(id, level) {
|
|
65619
|
+
this.ensureInitialized();
|
|
65620
|
+
const stmt = this.prepared.get("updateActivation");
|
|
65621
|
+
if (!stmt) throw new Error("Prepared statement not found: updateActivation");
|
|
65622
|
+
const clampedLevel = Math.max(0, Math.min(1, level));
|
|
65623
|
+
stmt.run(clampedLevel, id);
|
|
65624
|
+
}
|
|
65625
|
+
/**
|
|
65626
|
+
* Get all nodes with activation level at or above threshold
|
|
65627
|
+
*/
|
|
65628
|
+
async getActiveNodes(minActivation = 0.1) {
|
|
65629
|
+
this.ensureInitialized();
|
|
65630
|
+
const stmt = this.prepared.get("getActiveNodes");
|
|
65631
|
+
if (!stmt) throw new Error("Prepared statement not found: getActiveNodes");
|
|
65632
|
+
const rows = stmt.all(minActivation);
|
|
65633
|
+
return rows.map((row) => this.rowToNode(row));
|
|
65634
|
+
}
|
|
65635
|
+
/**
|
|
65636
|
+
* Get all nodes of a specific type
|
|
65637
|
+
*/
|
|
65638
|
+
async getNodesByType(type) {
|
|
65639
|
+
this.ensureInitialized();
|
|
65640
|
+
const stmt = this.prepared.get("getNodesByType");
|
|
65641
|
+
if (!stmt) throw new Error("Prepared statement not found: getNodesByType");
|
|
65642
|
+
const rows = stmt.all(type);
|
|
65643
|
+
return rows.map((row) => this.rowToNode(row));
|
|
65644
|
+
}
|
|
65645
|
+
// ==========================================================================
|
|
65646
|
+
// Edge Operations
|
|
65647
|
+
// ==========================================================================
|
|
65648
|
+
/**
|
|
65649
|
+
* Add an edge between two nodes
|
|
65650
|
+
* @returns The ID of the created edge
|
|
65651
|
+
*/
|
|
65652
|
+
async addEdge(source, target, type, weight = 1) {
|
|
65653
|
+
this.ensureInitialized();
|
|
65654
|
+
const existing = await this.getEdgeBetween(source, target);
|
|
65655
|
+
if (existing) {
|
|
65656
|
+
await this.strengthenEdge(source, target, 0.1);
|
|
65657
|
+
return existing.id;
|
|
65658
|
+
}
|
|
65659
|
+
const id = uuidv442();
|
|
65660
|
+
const stmt = this.prepared.get("insertEdge");
|
|
65661
|
+
if (!stmt) throw new Error("Prepared statement not found: insertEdge");
|
|
65662
|
+
stmt.run(id, source, target, type, Math.max(0, Math.min(1, weight)), 1);
|
|
65663
|
+
if (this.config.debug) {
|
|
65664
|
+
console.log(`[ConceptGraph] Added edge: ${source} -> ${target} (${type})`);
|
|
65665
|
+
}
|
|
65666
|
+
return id;
|
|
65667
|
+
}
|
|
65668
|
+
/**
|
|
65669
|
+
* Strengthen an existing edge between two nodes
|
|
65670
|
+
*/
|
|
65671
|
+
async strengthenEdge(source, target, delta = 0.1) {
|
|
65672
|
+
this.ensureInitialized();
|
|
65673
|
+
const existing = await this.getEdgeBetween(source, target);
|
|
65674
|
+
if (!existing) return;
|
|
65675
|
+
const newWeight = Math.min(1, existing.weight + delta);
|
|
65676
|
+
const stmt = this.prepared.get("updateEdge");
|
|
65677
|
+
if (!stmt) throw new Error("Prepared statement not found: updateEdge");
|
|
65678
|
+
stmt.run(newWeight, source, target);
|
|
65679
|
+
}
|
|
65680
|
+
/**
|
|
65681
|
+
* Get neighbors of a node (both outgoing and incoming edges)
|
|
65682
|
+
*/
|
|
65683
|
+
async getNeighbors(nodeId) {
|
|
65684
|
+
this.ensureInitialized();
|
|
65685
|
+
const results = [];
|
|
65686
|
+
const outStmt = this.prepared.get("getOutgoingEdges");
|
|
65687
|
+
if (!outStmt) throw new Error("Prepared statement not found: getOutgoingEdges");
|
|
65688
|
+
const outEdges = outStmt.all(nodeId);
|
|
65689
|
+
for (const edgeRow of outEdges) {
|
|
65690
|
+
const node = await this.getNode(edgeRow.target);
|
|
65691
|
+
if (node) {
|
|
65692
|
+
results.push({
|
|
65693
|
+
node,
|
|
65694
|
+
edge: this.rowToEdge(edgeRow)
|
|
65695
|
+
});
|
|
65696
|
+
}
|
|
65697
|
+
}
|
|
65698
|
+
const inStmt = this.prepared.get("getIncomingEdges");
|
|
65699
|
+
if (!inStmt) throw new Error("Prepared statement not found: getIncomingEdges");
|
|
65700
|
+
const inEdges = inStmt.all(nodeId);
|
|
65701
|
+
for (const edgeRow of inEdges) {
|
|
65702
|
+
const node = await this.getNode(edgeRow.source);
|
|
65703
|
+
if (node) {
|
|
65704
|
+
results.push({
|
|
65705
|
+
node,
|
|
65706
|
+
edge: this.rowToEdge(edgeRow)
|
|
65707
|
+
});
|
|
65708
|
+
}
|
|
65709
|
+
}
|
|
65710
|
+
return results;
|
|
65711
|
+
}
|
|
65712
|
+
// ==========================================================================
|
|
65713
|
+
// Graph Queries
|
|
65714
|
+
// ==========================================================================
|
|
65715
|
+
/**
|
|
65716
|
+
* Find a path between two nodes using BFS
|
|
65717
|
+
* @param maxHops Maximum number of hops (default: 5)
|
|
65718
|
+
*/
|
|
65719
|
+
async findPath(from, to, maxHops = 5) {
|
|
65720
|
+
this.ensureInitialized();
|
|
65721
|
+
const visited = /* @__PURE__ */ new Set();
|
|
65722
|
+
const queue = [{ nodeId: from, path: [from] }];
|
|
65723
|
+
while (queue.length > 0) {
|
|
65724
|
+
const current = queue.shift();
|
|
65725
|
+
if (current.nodeId === to) {
|
|
65726
|
+
const nodes = [];
|
|
65727
|
+
for (const nodeId of current.path) {
|
|
65728
|
+
const node = await this.getNode(nodeId);
|
|
65729
|
+
if (node) nodes.push(node);
|
|
65730
|
+
}
|
|
65731
|
+
return nodes;
|
|
65732
|
+
}
|
|
65733
|
+
if (current.path.length > maxHops) continue;
|
|
65734
|
+
if (visited.has(current.nodeId)) continue;
|
|
65735
|
+
visited.add(current.nodeId);
|
|
65736
|
+
const neighbors = await this.getNeighbors(current.nodeId);
|
|
65737
|
+
for (const { node } of neighbors) {
|
|
65738
|
+
if (!visited.has(node.id)) {
|
|
65739
|
+
queue.push({
|
|
65740
|
+
nodeId: node.id,
|
|
65741
|
+
path: [...current.path, node.id]
|
|
65742
|
+
});
|
|
65743
|
+
}
|
|
65744
|
+
}
|
|
65745
|
+
}
|
|
65746
|
+
return [];
|
|
65747
|
+
}
|
|
65748
|
+
/**
|
|
65749
|
+
* Get a cluster of nodes around a central node
|
|
65750
|
+
* @param depth How many hops to traverse (default: 2)
|
|
65751
|
+
*/
|
|
65752
|
+
async getCluster(nodeId, depth = 2) {
|
|
65753
|
+
this.ensureInitialized();
|
|
65754
|
+
const visited = /* @__PURE__ */ new Set();
|
|
65755
|
+
const result = [];
|
|
65756
|
+
const traverse = async (id, currentDepth) => {
|
|
65757
|
+
if (visited.has(id) || currentDepth > depth) return;
|
|
65758
|
+
visited.add(id);
|
|
65759
|
+
const node = await this.getNode(id);
|
|
65760
|
+
if (node) {
|
|
65761
|
+
result.push(node);
|
|
65762
|
+
if (currentDepth < depth) {
|
|
65763
|
+
const neighbors = await this.getNeighbors(id);
|
|
65764
|
+
for (const { node: neighbor } of neighbors) {
|
|
65765
|
+
await traverse(neighbor.id, currentDepth + 1);
|
|
65766
|
+
}
|
|
65767
|
+
}
|
|
65768
|
+
}
|
|
65769
|
+
};
|
|
65770
|
+
await traverse(nodeId, 0);
|
|
65771
|
+
return result;
|
|
65772
|
+
}
|
|
65773
|
+
// ==========================================================================
|
|
65774
|
+
// Pattern Import
|
|
65775
|
+
// ==========================================================================
|
|
65776
|
+
/**
|
|
65777
|
+
* Load patterns into the concept graph as nodes
|
|
65778
|
+
* @returns Number of patterns loaded
|
|
65779
|
+
*/
|
|
65780
|
+
async loadFromPatterns(patterns) {
|
|
65781
|
+
this.ensureInitialized();
|
|
65782
|
+
let loaded = 0;
|
|
65783
|
+
for (const pattern of patterns) {
|
|
65784
|
+
try {
|
|
65785
|
+
await this.addNode({
|
|
65786
|
+
conceptType: "pattern",
|
|
65787
|
+
content: `${pattern.name}: ${pattern.description}`,
|
|
65788
|
+
patternId: pattern.id,
|
|
65789
|
+
metadata: {
|
|
65790
|
+
domain: pattern.domain,
|
|
65791
|
+
patternType: pattern.patternType,
|
|
65792
|
+
confidence: pattern.confidence,
|
|
65793
|
+
successRate: pattern.successRate
|
|
65794
|
+
}
|
|
65795
|
+
});
|
|
65796
|
+
loaded++;
|
|
65797
|
+
const domainNode = await this.findDomainNode(pattern.domain);
|
|
65798
|
+
if (!domainNode) {
|
|
65799
|
+
await this.addNode({
|
|
65800
|
+
conceptType: "domain",
|
|
65801
|
+
content: pattern.domain,
|
|
65802
|
+
metadata: { patternCount: 1 }
|
|
65803
|
+
});
|
|
65804
|
+
}
|
|
65805
|
+
} catch (error) {
|
|
65806
|
+
if (this.config.debug) {
|
|
65807
|
+
console.error(`[ConceptGraph] Failed to load pattern: ${pattern.id}`, error);
|
|
65808
|
+
}
|
|
65809
|
+
}
|
|
65810
|
+
}
|
|
65811
|
+
if (this.config.debug) {
|
|
65812
|
+
console.log(`[ConceptGraph] Loaded ${loaded} patterns`);
|
|
65813
|
+
}
|
|
65814
|
+
return loaded;
|
|
65815
|
+
}
|
|
65816
|
+
// ==========================================================================
|
|
65817
|
+
// Statistics
|
|
65818
|
+
// ==========================================================================
|
|
65819
|
+
/**
|
|
65820
|
+
* Get graph statistics
|
|
65821
|
+
*/
|
|
65822
|
+
async getStats() {
|
|
65823
|
+
this.ensureInitialized();
|
|
65824
|
+
const countNodesStmt = this.prepared.get("countNodes");
|
|
65825
|
+
const countEdgesStmt = this.prepared.get("countEdges");
|
|
65826
|
+
const countByTypeStmt = this.prepared.get("countByType");
|
|
65827
|
+
if (!countNodesStmt || !countEdgesStmt || !countByTypeStmt) {
|
|
65828
|
+
throw new Error("Prepared statements not found");
|
|
65829
|
+
}
|
|
65830
|
+
const nodeCount = countNodesStmt.get().count;
|
|
65831
|
+
const edgeCount = countEdgesStmt.get().count;
|
|
65832
|
+
const byType = {
|
|
65833
|
+
pattern: 0,
|
|
65834
|
+
technique: 0,
|
|
65835
|
+
domain: 0,
|
|
65836
|
+
outcome: 0,
|
|
65837
|
+
error: 0
|
|
65838
|
+
};
|
|
65839
|
+
const typeRows = countByTypeStmt.all();
|
|
65840
|
+
for (const row of typeRows) {
|
|
65841
|
+
byType[row.concept_type] = row.count;
|
|
65842
|
+
}
|
|
65843
|
+
let avgActivation = 0;
|
|
65844
|
+
if (nodeCount > 0) {
|
|
65845
|
+
const avgStmt = this.db.prepare(
|
|
65846
|
+
"SELECT AVG(activation_level) as avg FROM concept_nodes"
|
|
65847
|
+
);
|
|
65848
|
+
const result = avgStmt.get();
|
|
65849
|
+
avgActivation = result.avg || 0;
|
|
65850
|
+
}
|
|
65851
|
+
return {
|
|
65852
|
+
nodeCount,
|
|
65853
|
+
edgeCount,
|
|
65854
|
+
byType,
|
|
65855
|
+
avgEdgesPerNode: nodeCount > 0 ? edgeCount / nodeCount : 0,
|
|
65856
|
+
avgActivation
|
|
65857
|
+
};
|
|
65858
|
+
}
|
|
65859
|
+
// ==========================================================================
|
|
65860
|
+
// Cleanup
|
|
65861
|
+
// ==========================================================================
|
|
65862
|
+
/**
|
|
65863
|
+
* Release resources (does NOT close the shared database)
|
|
65864
|
+
*/
|
|
65865
|
+
async close() {
|
|
65866
|
+
this.prepared.clear();
|
|
65867
|
+
this.db = null;
|
|
65868
|
+
this.persistence = null;
|
|
65869
|
+
this.initialized = false;
|
|
65870
|
+
}
|
|
65871
|
+
// ==========================================================================
|
|
65872
|
+
// Private Helpers
|
|
65873
|
+
// ==========================================================================
|
|
65874
|
+
ensureInitialized() {
|
|
65875
|
+
if (!this.initialized || !this.db) {
|
|
65876
|
+
throw new Error("ConceptGraph not initialized. Call initialize() first.");
|
|
65877
|
+
}
|
|
65878
|
+
}
|
|
65879
|
+
async getEdgeBetween(source, target) {
|
|
65880
|
+
const stmt = this.prepared.get("getEdge");
|
|
65881
|
+
if (!stmt) throw new Error("Prepared statement not found: getEdge");
|
|
65882
|
+
const row = stmt.get(source, target);
|
|
65883
|
+
if (!row) return null;
|
|
65884
|
+
return this.rowToEdge(row);
|
|
65885
|
+
}
|
|
65886
|
+
async findDomainNode(domain) {
|
|
65887
|
+
if (!this.db) return null;
|
|
65888
|
+
const stmt = this.db.prepare(
|
|
65889
|
+
"SELECT * FROM concept_nodes WHERE concept_type = 'domain' AND content = ?"
|
|
65890
|
+
);
|
|
65891
|
+
const row = stmt.get(domain);
|
|
65892
|
+
if (!row) return null;
|
|
65893
|
+
return this.rowToNode(row);
|
|
65894
|
+
}
|
|
65895
|
+
rowToNode(row) {
|
|
65896
|
+
let embedding;
|
|
65897
|
+
if (row.embedding) {
|
|
65898
|
+
const buffer = row.embedding;
|
|
65899
|
+
const float32 = new Float32Array(
|
|
65900
|
+
buffer.buffer,
|
|
65901
|
+
buffer.byteOffset,
|
|
65902
|
+
buffer.byteLength / 4
|
|
65903
|
+
);
|
|
65904
|
+
embedding = Array.from(float32);
|
|
65905
|
+
}
|
|
65906
|
+
return {
|
|
65907
|
+
id: row.id,
|
|
65908
|
+
conceptType: row.concept_type,
|
|
65909
|
+
content: row.content,
|
|
65910
|
+
embedding,
|
|
65911
|
+
activationLevel: row.activation_level || 0,
|
|
65912
|
+
lastActivated: row.last_activated ? new Date(row.last_activated) : void 0,
|
|
65913
|
+
patternId: row.pattern_id || void 0,
|
|
65914
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
65915
|
+
createdAt: row.created_at ? new Date(row.created_at) : void 0
|
|
65916
|
+
};
|
|
65917
|
+
}
|
|
65918
|
+
rowToEdge(row) {
|
|
65919
|
+
return {
|
|
65920
|
+
id: row.id,
|
|
65921
|
+
source: row.source,
|
|
65922
|
+
target: row.target,
|
|
65923
|
+
weight: row.weight,
|
|
65924
|
+
edgeType: row.edge_type,
|
|
65925
|
+
evidence: row.evidence,
|
|
65926
|
+
createdAt: row.created_at ? new Date(row.created_at) : void 0,
|
|
65927
|
+
updatedAt: row.updated_at ? new Date(row.updated_at) : void 0
|
|
65928
|
+
};
|
|
65929
|
+
}
|
|
65930
|
+
};
|
|
65931
|
+
|
|
65932
|
+
// src/learning/dream/spreading-activation.ts
|
|
65933
|
+
var DEFAULT_ACTIVATION_CONFIG = {
|
|
65934
|
+
decayRate: 0.1,
|
|
65935
|
+
spreadFactor: 0.5,
|
|
65936
|
+
threshold: 0.1,
|
|
65937
|
+
maxIterations: 20,
|
|
65938
|
+
noiseLevel: 0.05
|
|
65939
|
+
};
|
|
65940
|
+
var SpreadingActivation = class {
|
|
65941
|
+
graph;
|
|
65942
|
+
config;
|
|
65943
|
+
activationHistory = /* @__PURE__ */ new Map();
|
|
65944
|
+
coActivationCounts = /* @__PURE__ */ new Map();
|
|
65945
|
+
constructor(graph, config = {}) {
|
|
65946
|
+
this.graph = graph;
|
|
65947
|
+
this.config = { ...DEFAULT_ACTIVATION_CONFIG, ...config };
|
|
65948
|
+
}
|
|
65949
|
+
// ==========================================================================
|
|
65950
|
+
// Core Spreading
|
|
65951
|
+
// ==========================================================================
|
|
65952
|
+
/**
|
|
65953
|
+
* Spread activation from seed nodes through the concept graph.
|
|
65954
|
+
*
|
|
65955
|
+
* Algorithm:
|
|
65956
|
+
* 1. Initialize seed nodes with activation
|
|
65957
|
+
* 2. For each iteration:
|
|
65958
|
+
* a. For each active node, spread activation to neighbors (weighted by edge weight)
|
|
65959
|
+
* b. Apply decay to all nodes
|
|
65960
|
+
* c. Inject small random noise for exploration
|
|
65961
|
+
* 3. Track co-activated nodes for novel association detection
|
|
65962
|
+
* 4. Stop when stable or max iterations reached
|
|
65963
|
+
*
|
|
65964
|
+
* @param seedNodes - Array of node IDs to seed with initial activation
|
|
65965
|
+
* @param seedActivation - Initial activation level for seed nodes. Default: 1.0
|
|
65966
|
+
* @returns Activation result with statistics and discovered associations
|
|
65967
|
+
*/
|
|
65968
|
+
async spread(seedNodes, seedActivation = 1) {
|
|
65969
|
+
const validSeeds = seedNodes.filter((id) => this.graph.getConcept(id) !== void 0);
|
|
65970
|
+
if (validSeeds.length === 0) {
|
|
65971
|
+
return {
|
|
65972
|
+
iterations: 0,
|
|
65973
|
+
nodesActivated: 0,
|
|
65974
|
+
peakActivation: 0,
|
|
65975
|
+
activatedNodes: [],
|
|
65976
|
+
novelAssociations: []
|
|
65977
|
+
};
|
|
65978
|
+
}
|
|
65979
|
+
for (const nodeId of validSeeds) {
|
|
65980
|
+
this.graph.setActivation(nodeId, seedActivation);
|
|
65981
|
+
this.recordActivation(nodeId, seedActivation);
|
|
65982
|
+
}
|
|
65983
|
+
let iterations = 0;
|
|
65984
|
+
let peakActivation = seedActivation;
|
|
65985
|
+
let previousActiveCount = 0;
|
|
65986
|
+
let stableIterations = 0;
|
|
65987
|
+
while (iterations < this.config.maxIterations) {
|
|
65988
|
+
const nodesUpdated = await this.spreadIteration();
|
|
65989
|
+
const activeNodes = this.graph.getActiveNodes(this.config.threshold);
|
|
65990
|
+
for (const node of activeNodes) {
|
|
65991
|
+
if (node.activationLevel > peakActivation) {
|
|
65992
|
+
peakActivation = node.activationLevel;
|
|
65993
|
+
}
|
|
65994
|
+
}
|
|
65995
|
+
if (activeNodes.length === previousActiveCount && nodesUpdated === 0) {
|
|
65996
|
+
stableIterations++;
|
|
65997
|
+
if (stableIterations >= 3) {
|
|
65998
|
+
break;
|
|
65999
|
+
}
|
|
66000
|
+
} else {
|
|
66001
|
+
stableIterations = 0;
|
|
66002
|
+
}
|
|
66003
|
+
previousActiveCount = activeNodes.length;
|
|
66004
|
+
iterations++;
|
|
66005
|
+
}
|
|
66006
|
+
const activatedNodes = this.graph.getActiveNodes(this.config.threshold).map((node) => ({
|
|
66007
|
+
nodeId: node.id,
|
|
66008
|
+
activation: node.activationLevel
|
|
66009
|
+
})).sort((a, b) => b.activation - a.activation);
|
|
66010
|
+
const novelAssociations = await this.findNovelAssociations(this.config.threshold);
|
|
66011
|
+
return {
|
|
66012
|
+
iterations,
|
|
66013
|
+
nodesActivated: activatedNodes.length,
|
|
66014
|
+
peakActivation,
|
|
66015
|
+
activatedNodes,
|
|
66016
|
+
novelAssociations: novelAssociations.map((a) => ({
|
|
66017
|
+
source: a.source.id,
|
|
66018
|
+
target: a.target.id,
|
|
66019
|
+
strength: a.coActivation
|
|
66020
|
+
}))
|
|
66021
|
+
};
|
|
66022
|
+
}
|
|
66023
|
+
// ==========================================================================
|
|
66024
|
+
// Dream Mode
|
|
66025
|
+
// ==========================================================================
|
|
66026
|
+
/**
|
|
66027
|
+
* Dream mode: Random activation with increased noise.
|
|
66028
|
+
* Simulates the "reduced logical filtering" of REM sleep.
|
|
66029
|
+
*
|
|
66030
|
+
* During dreaming:
|
|
66031
|
+
* - Random nodes are periodically activated
|
|
66032
|
+
* - Activation spreads with higher noise
|
|
66033
|
+
* - Novel associations are discovered from unexpected co-activations
|
|
66034
|
+
*
|
|
66035
|
+
* @param durationMs - How long to dream in milliseconds
|
|
66036
|
+
* @returns Activation result from the dream cycle
|
|
66037
|
+
*/
|
|
66038
|
+
async dream(durationMs) {
|
|
66039
|
+
const startTime = Date.now();
|
|
66040
|
+
const allNovelAssociations = [];
|
|
66041
|
+
let totalIterations = 0;
|
|
66042
|
+
let maxPeakActivation = 0;
|
|
66043
|
+
const activatedNodeSet = /* @__PURE__ */ new Set();
|
|
66044
|
+
const allConcepts = this.graph.getAllConcepts(0);
|
|
66045
|
+
if (allConcepts.length === 0) {
|
|
66046
|
+
return {
|
|
66047
|
+
iterations: 0,
|
|
66048
|
+
nodesActivated: 0,
|
|
66049
|
+
peakActivation: 0,
|
|
66050
|
+
activatedNodes: [],
|
|
66051
|
+
novelAssociations: []
|
|
66052
|
+
};
|
|
66053
|
+
}
|
|
66054
|
+
while (Date.now() - startTime < durationMs) {
|
|
66055
|
+
const randomIndex = Math.floor(Math.random() * allConcepts.length);
|
|
66056
|
+
const randomNode = allConcepts[randomIndex];
|
|
66057
|
+
if (randomNode) {
|
|
66058
|
+
const noiseBoost = this.config.noiseLevel + Math.random() * this.config.noiseLevel * 2;
|
|
66059
|
+
const currentActivation = randomNode.activationLevel;
|
|
66060
|
+
const newActivation = Math.min(1, currentActivation + noiseBoost + 0.3);
|
|
66061
|
+
this.graph.setActivation(randomNode.id, newActivation);
|
|
66062
|
+
const result = await this.spread([randomNode.id], newActivation);
|
|
66063
|
+
totalIterations += result.iterations;
|
|
66064
|
+
if (result.peakActivation > maxPeakActivation) {
|
|
66065
|
+
maxPeakActivation = result.peakActivation;
|
|
66066
|
+
}
|
|
66067
|
+
for (const activated of result.activatedNodes) {
|
|
66068
|
+
activatedNodeSet.add(activated.nodeId);
|
|
66069
|
+
}
|
|
66070
|
+
for (const assoc of result.novelAssociations) {
|
|
66071
|
+
allNovelAssociations.push(assoc);
|
|
66072
|
+
}
|
|
66073
|
+
}
|
|
66074
|
+
await this.sleep(50 + Math.random() * 50);
|
|
66075
|
+
}
|
|
66076
|
+
const uniqueAssociations = this.deduplicateAssociations(allNovelAssociations);
|
|
66077
|
+
const activatedNodes = Array.from(activatedNodeSet).map((id) => {
|
|
66078
|
+
const node = this.graph.getConcept(id);
|
|
66079
|
+
return {
|
|
66080
|
+
nodeId: id,
|
|
66081
|
+
activation: node?.activationLevel ?? 0
|
|
66082
|
+
};
|
|
66083
|
+
}).filter((n) => n.activation > 0).sort((a, b) => b.activation - a.activation);
|
|
66084
|
+
return {
|
|
66085
|
+
iterations: totalIterations,
|
|
66086
|
+
nodesActivated: activatedNodes.length,
|
|
66087
|
+
peakActivation: maxPeakActivation,
|
|
66088
|
+
activatedNodes,
|
|
66089
|
+
novelAssociations: uniqueAssociations.slice(0, 20)
|
|
66090
|
+
// Top 20
|
|
66091
|
+
};
|
|
66092
|
+
}
|
|
66093
|
+
// ==========================================================================
|
|
66094
|
+
// Novel Association Detection
|
|
66095
|
+
// ==========================================================================
|
|
66096
|
+
/**
|
|
66097
|
+
* Find novel associations from co-activated nodes.
|
|
66098
|
+
*
|
|
66099
|
+
* Novel associations are pairs of nodes that:
|
|
66100
|
+
* 1. Are both highly activated (above minActivation)
|
|
66101
|
+
* 2. Either have no existing edge, or have a weak edge
|
|
66102
|
+
* 3. Haven't been frequently co-activated before
|
|
66103
|
+
*
|
|
66104
|
+
* @param minActivation - Minimum activation level to consider. Default: threshold
|
|
66105
|
+
* @returns Array of novel associations with source, target, and co-activation strength
|
|
66106
|
+
*/
|
|
66107
|
+
async findNovelAssociations(minActivation) {
|
|
66108
|
+
const threshold = minActivation ?? this.config.threshold;
|
|
66109
|
+
const activeNodes = this.graph.getActiveNodes(threshold);
|
|
66110
|
+
if (activeNodes.length < 2) {
|
|
66111
|
+
return [];
|
|
66112
|
+
}
|
|
66113
|
+
const associations = [];
|
|
66114
|
+
for (let i = 0; i < activeNodes.length; i++) {
|
|
66115
|
+
for (let j = i + 1; j < activeNodes.length; j++) {
|
|
66116
|
+
const nodeA = activeNodes[i];
|
|
66117
|
+
const nodeB = activeNodes[j];
|
|
66118
|
+
const coActivation = Math.sqrt(
|
|
66119
|
+
nodeA.activationLevel * nodeB.activationLevel
|
|
66120
|
+
);
|
|
66121
|
+
const existingEdge = this.graph.getEdge(nodeA.id, nodeB.id);
|
|
66122
|
+
const reverseEdge = this.graph.getEdge(nodeB.id, nodeA.id);
|
|
66123
|
+
const hasEdge = existingEdge !== void 0 || reverseEdge !== void 0;
|
|
66124
|
+
const edgeWeight = existingEdge?.weight ?? reverseEdge?.weight ?? 0;
|
|
66125
|
+
const isNovel = !hasEdge || edgeWeight < 0.3;
|
|
66126
|
+
if (coActivation > 0.3) {
|
|
66127
|
+
associations.push({
|
|
66128
|
+
source: nodeA,
|
|
66129
|
+
target: nodeB,
|
|
66130
|
+
coActivation,
|
|
66131
|
+
isNovel
|
|
66132
|
+
});
|
|
66133
|
+
this.trackCoActivation(nodeA.id, nodeB.id);
|
|
66134
|
+
}
|
|
66135
|
+
}
|
|
66136
|
+
}
|
|
66137
|
+
return associations.sort((a, b) => {
|
|
66138
|
+
if (a.isNovel !== b.isNovel) {
|
|
66139
|
+
return a.isNovel ? -1 : 1;
|
|
66140
|
+
}
|
|
66141
|
+
return b.coActivation - a.coActivation;
|
|
66142
|
+
}).slice(0, 10);
|
|
66143
|
+
}
|
|
66144
|
+
// ==========================================================================
|
|
66145
|
+
// State Management
|
|
66146
|
+
// ==========================================================================
|
|
66147
|
+
/**
|
|
66148
|
+
* Reset all activations to zero and clear history
|
|
66149
|
+
*/
|
|
66150
|
+
async reset() {
|
|
66151
|
+
const allNodes = this.graph.getAllConcepts(0);
|
|
66152
|
+
for (const node of allNodes) {
|
|
66153
|
+
this.graph.setActivation(node.id, 0);
|
|
66154
|
+
}
|
|
66155
|
+
this.activationHistory.clear();
|
|
66156
|
+
this.coActivationCounts.clear();
|
|
66157
|
+
}
|
|
66158
|
+
/**
|
|
66159
|
+
* Get current configuration
|
|
66160
|
+
*/
|
|
66161
|
+
getConfig() {
|
|
66162
|
+
return { ...this.config };
|
|
66163
|
+
}
|
|
66164
|
+
// ==========================================================================
|
|
66165
|
+
// Private Methods
|
|
66166
|
+
// ==========================================================================
|
|
66167
|
+
/**
|
|
66168
|
+
* Perform one iteration of activation spreading
|
|
66169
|
+
* @returns Number of nodes that had their activation updated
|
|
66170
|
+
*/
|
|
66171
|
+
async spreadIteration() {
|
|
66172
|
+
const activeNodes = this.graph.getActiveNodes(this.config.threshold);
|
|
66173
|
+
let nodesUpdated = 0;
|
|
66174
|
+
const updates = [];
|
|
66175
|
+
for (const activeNode of activeNodes) {
|
|
66176
|
+
const edges = this.graph.getEdges(activeNode.id);
|
|
66177
|
+
for (const edge of edges) {
|
|
66178
|
+
const targetNode = this.graph.getConcept(edge.target);
|
|
66179
|
+
if (!targetNode) continue;
|
|
66180
|
+
const spreadAmount = activeNode.activationLevel * edge.weight * this.config.spreadFactor;
|
|
66181
|
+
if (spreadAmount > 0.01) {
|
|
66182
|
+
const currentActivation = targetNode.activationLevel;
|
|
66183
|
+
const newActivation = Math.min(1, currentActivation + spreadAmount);
|
|
66184
|
+
updates.push({ nodeId: edge.target, newActivation });
|
|
66185
|
+
}
|
|
66186
|
+
}
|
|
66187
|
+
}
|
|
66188
|
+
for (const update of updates) {
|
|
66189
|
+
const currentNode = this.graph.getConcept(update.nodeId);
|
|
66190
|
+
if (currentNode && update.newActivation > currentNode.activationLevel) {
|
|
66191
|
+
this.graph.setActivation(update.nodeId, update.newActivation);
|
|
66192
|
+
this.recordActivation(update.nodeId, update.newActivation);
|
|
66193
|
+
nodesUpdated++;
|
|
66194
|
+
}
|
|
66195
|
+
}
|
|
66196
|
+
this.applyDecay();
|
|
66197
|
+
this.injectNoise();
|
|
66198
|
+
return nodesUpdated;
|
|
66199
|
+
}
|
|
66200
|
+
/**
|
|
66201
|
+
* Apply decay to all activation levels
|
|
66202
|
+
*/
|
|
66203
|
+
applyDecay() {
|
|
66204
|
+
const decayFactor = 1 - this.config.decayRate;
|
|
66205
|
+
this.graph.decayActivations(decayFactor);
|
|
66206
|
+
}
|
|
66207
|
+
/**
|
|
66208
|
+
* Inject small random noise to activations for exploration
|
|
66209
|
+
*/
|
|
66210
|
+
injectNoise() {
|
|
66211
|
+
if (this.config.noiseLevel <= 0) return;
|
|
66212
|
+
const allNodes = this.graph.getAllConcepts(0);
|
|
66213
|
+
for (const node of allNodes) {
|
|
66214
|
+
if (node.activationLevel > 0) {
|
|
66215
|
+
const noise = (Math.random() - 0.5) * 2 * this.config.noiseLevel;
|
|
66216
|
+
const newActivation = Math.max(0, Math.min(1, node.activationLevel + noise));
|
|
66217
|
+
this.graph.setActivation(node.id, newActivation);
|
|
66218
|
+
}
|
|
66219
|
+
}
|
|
66220
|
+
}
|
|
66221
|
+
/**
|
|
66222
|
+
* Record activation level for history tracking
|
|
66223
|
+
*/
|
|
66224
|
+
recordActivation(nodeId, level) {
|
|
66225
|
+
const history = this.activationHistory.get(nodeId) || [];
|
|
66226
|
+
history.push(level);
|
|
66227
|
+
if (history.length > 50) {
|
|
66228
|
+
history.shift();
|
|
66229
|
+
}
|
|
66230
|
+
this.activationHistory.set(nodeId, history);
|
|
66231
|
+
}
|
|
66232
|
+
/**
|
|
66233
|
+
* Track co-activation between two nodes
|
|
66234
|
+
*/
|
|
66235
|
+
trackCoActivation(nodeA, nodeB) {
|
|
66236
|
+
const key = [nodeA, nodeB].sort().join(":");
|
|
66237
|
+
const count = this.coActivationCounts.get(key) || 0;
|
|
66238
|
+
this.coActivationCounts.set(key, count + 1);
|
|
66239
|
+
}
|
|
66240
|
+
/**
|
|
66241
|
+
* Deduplicate associations by keeping the strongest
|
|
66242
|
+
*/
|
|
66243
|
+
deduplicateAssociations(associations) {
|
|
66244
|
+
const unique = /* @__PURE__ */ new Map();
|
|
66245
|
+
for (const assoc of associations) {
|
|
66246
|
+
const key = [assoc.source, assoc.target].sort().join(":");
|
|
66247
|
+
const existing = unique.get(key);
|
|
66248
|
+
if (!existing || assoc.strength > existing.strength) {
|
|
66249
|
+
unique.set(key, assoc);
|
|
66250
|
+
}
|
|
66251
|
+
}
|
|
66252
|
+
return Array.from(unique.values()).sort((a, b) => b.strength - a.strength);
|
|
66253
|
+
}
|
|
66254
|
+
/**
|
|
66255
|
+
* Helper to sleep for a duration
|
|
66256
|
+
*/
|
|
66257
|
+
sleep(ms) {
|
|
66258
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
66259
|
+
}
|
|
66260
|
+
};
|
|
66261
|
+
|
|
66262
|
+
// src/learning/dream/insight-generator.ts
|
|
66263
|
+
var DEFAULT_INSIGHT_CONFIG = {
|
|
66264
|
+
minNoveltyScore: 0.3,
|
|
66265
|
+
minConfidence: 0.5,
|
|
66266
|
+
maxInsightsPerCycle: 10
|
|
66267
|
+
};
|
|
66268
|
+
var InsightGenerator = class {
|
|
66269
|
+
graph;
|
|
66270
|
+
config;
|
|
66271
|
+
constructor(graph, config = {}) {
|
|
66272
|
+
this.graph = graph;
|
|
66273
|
+
this.config = { ...DEFAULT_INSIGHT_CONFIG, ...config };
|
|
66274
|
+
}
|
|
66275
|
+
// ==========================================================================
|
|
66276
|
+
// Main Generation Method
|
|
66277
|
+
// ==========================================================================
|
|
66278
|
+
/**
|
|
66279
|
+
* Generate insights from an activation result.
|
|
66280
|
+
*
|
|
66281
|
+
* Analyzes the activated nodes and novel associations to produce
|
|
66282
|
+
* actionable insights about patterns, optimizations, and gaps.
|
|
66283
|
+
*
|
|
66284
|
+
* @param cycleId - ID of the dream cycle that produced the activation
|
|
66285
|
+
* @param activationResult - Result from SpreadingActivation.spread() or .dream()
|
|
66286
|
+
* @returns Array of generated insights
|
|
66287
|
+
*/
|
|
66288
|
+
async generateFromActivation(cycleId, activationResult) {
|
|
66289
|
+
const allInsights = [];
|
|
66290
|
+
const activeNodes = activationResult.activatedNodes.map((n) => this.graph.getConcept(n.nodeId)).filter((n) => n !== void 0);
|
|
66291
|
+
if (activeNodes.length < 2) {
|
|
66292
|
+
return [];
|
|
66293
|
+
}
|
|
66294
|
+
const patternMerges = await this.detectPatternMerges(activeNodes);
|
|
66295
|
+
for (const insight of patternMerges) {
|
|
66296
|
+
insight.cycleId = cycleId;
|
|
66297
|
+
allInsights.push(insight);
|
|
66298
|
+
}
|
|
66299
|
+
const novelAssociations = await this.detectNovelAssociations(
|
|
66300
|
+
activationResult.novelAssociations
|
|
66301
|
+
);
|
|
66302
|
+
for (const insight of novelAssociations) {
|
|
66303
|
+
insight.cycleId = cycleId;
|
|
66304
|
+
allInsights.push(insight);
|
|
66305
|
+
}
|
|
66306
|
+
const optimizations = await this.detectOptimizations(activeNodes);
|
|
66307
|
+
for (const insight of optimizations) {
|
|
66308
|
+
insight.cycleId = cycleId;
|
|
66309
|
+
allInsights.push(insight);
|
|
66310
|
+
}
|
|
66311
|
+
const gaps = await this.detectGaps(activeNodes);
|
|
66312
|
+
for (const insight of gaps) {
|
|
66313
|
+
insight.cycleId = cycleId;
|
|
66314
|
+
allInsights.push(insight);
|
|
66315
|
+
}
|
|
66316
|
+
return allInsights.filter((i) => i.noveltyScore >= this.config.minNoveltyScore).sort((a, b) => b.noveltyScore - a.noveltyScore).slice(0, this.config.maxInsightsPerCycle);
|
|
66317
|
+
}
|
|
66318
|
+
// ==========================================================================
|
|
66319
|
+
// Pattern Merge Detection
|
|
66320
|
+
// ==========================================================================
|
|
66321
|
+
/**
|
|
66322
|
+
* Detect opportunities to merge similar patterns.
|
|
66323
|
+
*
|
|
66324
|
+
* Pattern merges are detected when:
|
|
66325
|
+
* - Multiple pattern-type concepts are co-activated
|
|
66326
|
+
* - They share similar content or metadata
|
|
66327
|
+
* - They have high edge weights between them (similarity)
|
|
66328
|
+
*
|
|
66329
|
+
* @param activeNodes - Currently activated concept nodes
|
|
66330
|
+
* @returns Array of pattern merge insights
|
|
66331
|
+
*/
|
|
66332
|
+
async detectPatternMerges(activeNodes) {
|
|
66333
|
+
const insights = [];
|
|
66334
|
+
const patternNodes = activeNodes.filter(
|
|
66335
|
+
(n) => n.conceptType === "pattern" || n.conceptType === "technique"
|
|
66336
|
+
);
|
|
66337
|
+
if (patternNodes.length < 2) {
|
|
66338
|
+
return insights;
|
|
66339
|
+
}
|
|
66340
|
+
for (let i = 0; i < patternNodes.length; i++) {
|
|
66341
|
+
for (let j = i + 1; j < patternNodes.length; j++) {
|
|
66342
|
+
const nodeA = patternNodes[i];
|
|
66343
|
+
const nodeB = patternNodes[j];
|
|
66344
|
+
const edge = this.graph.getEdge(nodeA.id, nodeB.id);
|
|
66345
|
+
const reverseEdge = this.graph.getEdge(nodeB.id, nodeA.id);
|
|
66346
|
+
const edgeWeight = Math.max(edge?.weight ?? 0, reverseEdge?.weight ?? 0);
|
|
66347
|
+
const contentSimilarity = this.calculateContentSimilarity(
|
|
66348
|
+
nodeA.content,
|
|
66349
|
+
nodeB.content
|
|
66350
|
+
);
|
|
66351
|
+
const coActivation = Math.sqrt(
|
|
66352
|
+
nodeA.activationLevel * nodeB.activationLevel
|
|
66353
|
+
);
|
|
66354
|
+
const mergeScore = edgeWeight * 0.4 + contentSimilarity * 0.3 + coActivation * 0.3;
|
|
66355
|
+
if (mergeScore > 0.5) {
|
|
66356
|
+
const novelty = this.calculateNovelty({
|
|
66357
|
+
type: "pattern_merge",
|
|
66358
|
+
sourceConcepts: [nodeA.id, nodeB.id]
|
|
66359
|
+
});
|
|
66360
|
+
const confidence = this.calculateConfidence({
|
|
66361
|
+
type: "pattern_merge",
|
|
66362
|
+
sourceConcepts: [nodeA.id, nodeB.id],
|
|
66363
|
+
edgeWeight,
|
|
66364
|
+
contentSimilarity,
|
|
66365
|
+
coActivation
|
|
66366
|
+
});
|
|
66367
|
+
insights.push({
|
|
66368
|
+
id: this.generateId(),
|
|
66369
|
+
cycleId: "",
|
|
66370
|
+
// Set by caller
|
|
66371
|
+
type: "pattern_merge",
|
|
66372
|
+
sourceConcepts: [nodeA.id, nodeB.id],
|
|
66373
|
+
description: this.generatePatternMergeDescription(nodeA, nodeB, mergeScore),
|
|
66374
|
+
noveltyScore: novelty,
|
|
66375
|
+
confidenceScore: confidence,
|
|
66376
|
+
actionable: confidence >= this.config.minConfidence,
|
|
66377
|
+
applied: false,
|
|
66378
|
+
suggestedAction: confidence >= this.config.minConfidence ? `Merge "${this.truncate(nodeA.content, 30)}" with "${this.truncate(nodeB.content, 30)}" into a unified pattern.` : void 0,
|
|
66379
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
66380
|
+
});
|
|
66381
|
+
}
|
|
66382
|
+
}
|
|
66383
|
+
}
|
|
66384
|
+
return insights;
|
|
66385
|
+
}
|
|
66386
|
+
// ==========================================================================
|
|
66387
|
+
// Novel Association Detection
|
|
66388
|
+
// ==========================================================================
|
|
66389
|
+
/**
|
|
66390
|
+
* Detect insights from novel associations.
|
|
66391
|
+
*
|
|
66392
|
+
* Novel associations are unexpected links between concepts that
|
|
66393
|
+
* may represent new understanding or connection opportunities.
|
|
66394
|
+
*
|
|
66395
|
+
* @param associations - Novel associations from activation result
|
|
66396
|
+
* @returns Array of novel association insights
|
|
66397
|
+
*/
|
|
66398
|
+
async detectNovelAssociations(associations) {
|
|
66399
|
+
const insights = [];
|
|
66400
|
+
for (const assoc of associations) {
|
|
66401
|
+
const sourceNode = this.graph.getConcept(assoc.source);
|
|
66402
|
+
const targetNode = this.graph.getConcept(assoc.target);
|
|
66403
|
+
if (!sourceNode || !targetNode) continue;
|
|
66404
|
+
const edge = this.graph.getEdge(assoc.source, assoc.target);
|
|
66405
|
+
if (edge && edge.weight > 0.5) continue;
|
|
66406
|
+
const isCrossDomain = sourceNode.conceptType !== targetNode.conceptType;
|
|
66407
|
+
const novelty = this.calculateNovelty({
|
|
66408
|
+
type: "novel_association",
|
|
66409
|
+
sourceConcepts: [assoc.source, assoc.target],
|
|
66410
|
+
isCrossDomain,
|
|
66411
|
+
strength: assoc.strength
|
|
66412
|
+
});
|
|
66413
|
+
const confidence = this.calculateConfidence({
|
|
66414
|
+
type: "novel_association",
|
|
66415
|
+
sourceConcepts: [assoc.source, assoc.target],
|
|
66416
|
+
coActivation: assoc.strength,
|
|
66417
|
+
isCrossDomain
|
|
66418
|
+
});
|
|
66419
|
+
insights.push({
|
|
66420
|
+
id: this.generateId(),
|
|
66421
|
+
cycleId: "",
|
|
66422
|
+
// Set by caller
|
|
66423
|
+
type: "novel_association",
|
|
66424
|
+
sourceConcepts: [assoc.source, assoc.target],
|
|
66425
|
+
description: this.generateNovelAssociationDescription(
|
|
66426
|
+
sourceNode,
|
|
66427
|
+
targetNode,
|
|
66428
|
+
assoc.strength,
|
|
66429
|
+
isCrossDomain
|
|
66430
|
+
),
|
|
66431
|
+
noveltyScore: novelty,
|
|
66432
|
+
confidenceScore: confidence,
|
|
66433
|
+
actionable: confidence >= this.config.minConfidence,
|
|
66434
|
+
applied: false,
|
|
66435
|
+
suggestedAction: confidence >= this.config.minConfidence ? `Investigate connection between "${this.truncate(sourceNode.content, 25)}" and "${this.truncate(targetNode.content, 25)}".` : void 0,
|
|
66436
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
66437
|
+
});
|
|
66438
|
+
}
|
|
66439
|
+
return insights;
|
|
66440
|
+
}
|
|
66441
|
+
// ==========================================================================
|
|
66442
|
+
// Optimization Detection
|
|
66443
|
+
// ==========================================================================
|
|
66444
|
+
/**
|
|
66445
|
+
* Detect optimization opportunities from active patterns.
|
|
66446
|
+
*
|
|
66447
|
+
* Optimizations are detected when:
|
|
66448
|
+
* - A pattern has low success rate metadata
|
|
66449
|
+
* - A technique has high execution count but mediocre outcomes
|
|
66450
|
+
* - Multiple related patterns could be consolidated
|
|
66451
|
+
*
|
|
66452
|
+
* @param activeNodes - Currently activated concept nodes
|
|
66453
|
+
* @returns Array of optimization insights
|
|
66454
|
+
*/
|
|
66455
|
+
async detectOptimizations(activeNodes) {
|
|
66456
|
+
const insights = [];
|
|
66457
|
+
for (const node of activeNodes) {
|
|
66458
|
+
if (node.conceptType !== "pattern" && node.conceptType !== "technique") {
|
|
66459
|
+
continue;
|
|
66460
|
+
}
|
|
66461
|
+
const metadata = node.metadata ?? {};
|
|
66462
|
+
const successRate = metadata.successRate;
|
|
66463
|
+
const executionCount = metadata.executionCount;
|
|
66464
|
+
const confidence = metadata.confidence;
|
|
66465
|
+
const hasLowSuccess = successRate !== void 0 && successRate < 0.7;
|
|
66466
|
+
const hasHighUsage = executionCount !== void 0 && executionCount > 10;
|
|
66467
|
+
const hasLowConfidence = confidence !== void 0 && confidence < 0.6;
|
|
66468
|
+
if (hasLowSuccess || hasHighUsage && hasLowConfidence) {
|
|
66469
|
+
const novelty = this.calculateNovelty({
|
|
66470
|
+
type: "optimization",
|
|
66471
|
+
sourceConcepts: [node.id],
|
|
66472
|
+
hasLowSuccess,
|
|
66473
|
+
hasHighUsage
|
|
66474
|
+
});
|
|
66475
|
+
const insightConfidence = this.calculateConfidence({
|
|
66476
|
+
type: "optimization",
|
|
66477
|
+
sourceConcepts: [node.id],
|
|
66478
|
+
hasLowSuccess,
|
|
66479
|
+
hasHighUsage,
|
|
66480
|
+
metadata
|
|
66481
|
+
});
|
|
66482
|
+
insights.push({
|
|
66483
|
+
id: this.generateId(),
|
|
66484
|
+
cycleId: "",
|
|
66485
|
+
// Set by caller
|
|
66486
|
+
type: "optimization",
|
|
66487
|
+
sourceConcepts: [node.id],
|
|
66488
|
+
description: this.generateOptimizationDescription(
|
|
66489
|
+
node,
|
|
66490
|
+
successRate,
|
|
66491
|
+
executionCount
|
|
66492
|
+
),
|
|
66493
|
+
noveltyScore: novelty,
|
|
66494
|
+
confidenceScore: insightConfidence,
|
|
66495
|
+
actionable: insightConfidence >= this.config.minConfidence,
|
|
66496
|
+
applied: false,
|
|
66497
|
+
suggestedAction: insightConfidence >= this.config.minConfidence ? `Review and optimize "${this.truncate(node.content, 40)}" to improve success rate.` : void 0,
|
|
66498
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
66499
|
+
});
|
|
66500
|
+
}
|
|
66501
|
+
}
|
|
66502
|
+
return insights;
|
|
66503
|
+
}
|
|
66504
|
+
// ==========================================================================
|
|
66505
|
+
// Gap Detection
|
|
66506
|
+
// ==========================================================================
|
|
66507
|
+
/**
|
|
66508
|
+
* Detect knowledge gaps from active patterns.
|
|
66509
|
+
*
|
|
66510
|
+
* Gaps are detected when:
|
|
66511
|
+
* - Expected concepts are not activated (missing connections)
|
|
66512
|
+
* - Outcome nodes lack corresponding technique nodes
|
|
66513
|
+
* - Error patterns exist without resolution patterns
|
|
66514
|
+
*
|
|
66515
|
+
* @param activeNodes - Currently activated concept nodes
|
|
66516
|
+
* @returns Array of gap detection insights
|
|
66517
|
+
*/
|
|
66518
|
+
async detectGaps(activeNodes) {
|
|
66519
|
+
const insights = [];
|
|
66520
|
+
const byType = {
|
|
66521
|
+
pattern: [],
|
|
66522
|
+
technique: [],
|
|
66523
|
+
domain: [],
|
|
66524
|
+
outcome: [],
|
|
66525
|
+
error: []
|
|
66526
|
+
};
|
|
66527
|
+
for (const node of activeNodes) {
|
|
66528
|
+
const typeKey = node.conceptType ?? "pattern";
|
|
66529
|
+
if (!byType[typeKey]) {
|
|
66530
|
+
byType[typeKey] = [];
|
|
66531
|
+
}
|
|
66532
|
+
byType[typeKey].push(node);
|
|
66533
|
+
}
|
|
66534
|
+
for (const errorNode of byType.error ?? []) {
|
|
66535
|
+
const edges = this.graph.getEdges(errorNode.id);
|
|
66536
|
+
const hasResolution = edges.some((e) => {
|
|
66537
|
+
const target = this.graph.getConcept(e.target);
|
|
66538
|
+
return target && (target.conceptType === "pattern" || target.conceptType === "technique");
|
|
66539
|
+
});
|
|
66540
|
+
if (!hasResolution) {
|
|
66541
|
+
const novelty = this.calculateNovelty({
|
|
66542
|
+
type: "gap_detection",
|
|
66543
|
+
sourceConcepts: [errorNode.id],
|
|
66544
|
+
gapType: "missing_resolution"
|
|
66545
|
+
});
|
|
66546
|
+
const confidence = this.calculateConfidence({
|
|
66547
|
+
type: "gap_detection",
|
|
66548
|
+
sourceConcepts: [errorNode.id],
|
|
66549
|
+
gapType: "missing_resolution"
|
|
66550
|
+
});
|
|
66551
|
+
insights.push({
|
|
66552
|
+
id: this.generateId(),
|
|
66553
|
+
cycleId: "",
|
|
66554
|
+
// Set by caller
|
|
66555
|
+
type: "gap_detection",
|
|
66556
|
+
sourceConcepts: [errorNode.id],
|
|
66557
|
+
description: `No resolution pattern found for error: "${this.truncate(errorNode.content, 50)}". Consider creating a fix pattern.`,
|
|
66558
|
+
noveltyScore: novelty,
|
|
66559
|
+
confidenceScore: confidence,
|
|
66560
|
+
actionable: true,
|
|
66561
|
+
applied: false,
|
|
66562
|
+
suggestedAction: `Create a resolution pattern for: "${this.truncate(errorNode.content, 40)}".`,
|
|
66563
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
66564
|
+
});
|
|
66565
|
+
}
|
|
66566
|
+
}
|
|
66567
|
+
for (const outcomeNode of byType.outcome ?? []) {
|
|
66568
|
+
const edges = this.graph.getEdges(outcomeNode.id);
|
|
66569
|
+
const hasTechnique = edges.some((e) => {
|
|
66570
|
+
const target = this.graph.getConcept(e.target);
|
|
66571
|
+
return target && target.conceptType === "technique";
|
|
66572
|
+
});
|
|
66573
|
+
if (!hasTechnique && (byType.technique?.length ?? 0) === 0) {
|
|
66574
|
+
const novelty = this.calculateNovelty({
|
|
66575
|
+
type: "gap_detection",
|
|
66576
|
+
sourceConcepts: [outcomeNode.id],
|
|
66577
|
+
gapType: "missing_technique"
|
|
66578
|
+
});
|
|
66579
|
+
const confidence = this.calculateConfidence({
|
|
66580
|
+
type: "gap_detection",
|
|
66581
|
+
sourceConcepts: [outcomeNode.id],
|
|
66582
|
+
gapType: "missing_technique"
|
|
66583
|
+
});
|
|
66584
|
+
insights.push({
|
|
66585
|
+
id: this.generateId(),
|
|
66586
|
+
cycleId: "",
|
|
66587
|
+
// Set by caller
|
|
66588
|
+
type: "gap_detection",
|
|
66589
|
+
sourceConcepts: [outcomeNode.id],
|
|
66590
|
+
description: `Outcome "${this.truncate(outcomeNode.content, 40)}" has no associated technique. Document how this outcome is achieved.`,
|
|
66591
|
+
noveltyScore: novelty,
|
|
66592
|
+
confidenceScore: confidence,
|
|
66593
|
+
actionable: true,
|
|
66594
|
+
applied: false,
|
|
66595
|
+
suggestedAction: `Document the technique for achieving: "${this.truncate(outcomeNode.content, 35)}".`,
|
|
66596
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
66597
|
+
});
|
|
66598
|
+
}
|
|
66599
|
+
}
|
|
66600
|
+
return insights;
|
|
66601
|
+
}
|
|
66602
|
+
// ==========================================================================
|
|
66603
|
+
// Scoring Methods
|
|
66604
|
+
// ==========================================================================
|
|
66605
|
+
/**
|
|
66606
|
+
* Calculate novelty score for an insight.
|
|
66607
|
+
*
|
|
66608
|
+
* Novelty is higher when:
|
|
66609
|
+
* - Concepts are from different types/domains
|
|
66610
|
+
* - No existing strong edges between concepts
|
|
66611
|
+
* - Co-activation pattern is unusual
|
|
66612
|
+
*/
|
|
66613
|
+
calculateNovelty(context2) {
|
|
66614
|
+
let novelty = 0.5;
|
|
66615
|
+
if (context2.isCrossDomain) {
|
|
66616
|
+
novelty += 0.2;
|
|
66617
|
+
}
|
|
66618
|
+
if (context2.strength !== void 0 && context2.strength > 0.5) {
|
|
66619
|
+
novelty += 0.15;
|
|
66620
|
+
}
|
|
66621
|
+
if (context2.type === "gap_detection") {
|
|
66622
|
+
novelty += 0.2;
|
|
66623
|
+
}
|
|
66624
|
+
if (context2.hasHighUsage && context2.hasLowSuccess) {
|
|
66625
|
+
novelty += 0.15;
|
|
66626
|
+
}
|
|
66627
|
+
if (context2.sourceConcepts.length >= 2) {
|
|
66628
|
+
const edge = this.graph.getEdge(
|
|
66629
|
+
context2.sourceConcepts[0],
|
|
66630
|
+
context2.sourceConcepts[1]
|
|
66631
|
+
);
|
|
66632
|
+
if (!edge) {
|
|
66633
|
+
novelty += 0.1;
|
|
66634
|
+
} else if (edge.weight < 0.3) {
|
|
66635
|
+
novelty += 0.05;
|
|
66636
|
+
}
|
|
66637
|
+
}
|
|
66638
|
+
return Math.min(1, Math.max(0, novelty));
|
|
66639
|
+
}
|
|
66640
|
+
/**
|
|
66641
|
+
* Calculate confidence score for an insight.
|
|
66642
|
+
*
|
|
66643
|
+
* Confidence is higher when:
|
|
66644
|
+
* - High co-activation strength
|
|
66645
|
+
* - Strong evidence (edge weights, execution counts)
|
|
66646
|
+
* - Consistent metadata supports the insight
|
|
66647
|
+
*/
|
|
66648
|
+
calculateConfidence(context2) {
|
|
66649
|
+
let confidence = 0.4;
|
|
66650
|
+
if (context2.coActivation !== void 0) {
|
|
66651
|
+
confidence += context2.coActivation * 0.3;
|
|
66652
|
+
}
|
|
66653
|
+
if (context2.edgeWeight !== void 0) {
|
|
66654
|
+
confidence += context2.edgeWeight * 0.2;
|
|
66655
|
+
}
|
|
66656
|
+
if (context2.contentSimilarity !== void 0 && context2.type === "pattern_merge") {
|
|
66657
|
+
confidence += context2.contentSimilarity * 0.2;
|
|
66658
|
+
}
|
|
66659
|
+
if (context2.isCrossDomain) {
|
|
66660
|
+
confidence -= 0.1;
|
|
66661
|
+
}
|
|
66662
|
+
if (context2.hasHighUsage && context2.hasLowSuccess) {
|
|
66663
|
+
confidence += 0.15;
|
|
66664
|
+
}
|
|
66665
|
+
if (context2.metadata) {
|
|
66666
|
+
const metadataQuality = Math.min(Object.keys(context2.metadata).length * 0.05, 0.15);
|
|
66667
|
+
confidence += metadataQuality;
|
|
66668
|
+
}
|
|
66669
|
+
if (context2.gapType) {
|
|
66670
|
+
confidence += 0.1;
|
|
66671
|
+
}
|
|
66672
|
+
return Math.min(1, Math.max(0, confidence));
|
|
66673
|
+
}
|
|
66674
|
+
// ==========================================================================
|
|
66675
|
+
// Pattern Conversion
|
|
66676
|
+
// ==========================================================================
|
|
66677
|
+
/**
|
|
66678
|
+
* Convert an actionable insight into a pattern template.
|
|
66679
|
+
*
|
|
66680
|
+
* @param insight - The insight to convert
|
|
66681
|
+
* @returns Pattern template or null if not convertible
|
|
66682
|
+
*/
|
|
66683
|
+
async insightToPattern(insight) {
|
|
66684
|
+
if (!insight.actionable) {
|
|
66685
|
+
return null;
|
|
66686
|
+
}
|
|
66687
|
+
const concepts = insight.sourceConcepts.map((id) => this.graph.getConcept(id)).filter((c) => c !== void 0);
|
|
66688
|
+
if (concepts.length === 0) {
|
|
66689
|
+
return null;
|
|
66690
|
+
}
|
|
66691
|
+
switch (insight.type) {
|
|
66692
|
+
case "pattern_merge": {
|
|
66693
|
+
const [conceptA, conceptB] = concepts;
|
|
66694
|
+
return {
|
|
66695
|
+
name: `Merged: ${this.truncate(conceptA?.content ?? "", 20)} + ${this.truncate(conceptB?.content ?? "", 20)}`,
|
|
66696
|
+
description: insight.description,
|
|
66697
|
+
template: {
|
|
66698
|
+
type: "merged_pattern",
|
|
66699
|
+
sourcePatterns: insight.sourceConcepts,
|
|
66700
|
+
mergedContent: concepts.map((c) => c.content).join(" | "),
|
|
66701
|
+
metadata: {
|
|
66702
|
+
noveltyScore: insight.noveltyScore,
|
|
66703
|
+
confidenceScore: insight.confidenceScore,
|
|
66704
|
+
createdFrom: "dream_insight"
|
|
66705
|
+
}
|
|
66706
|
+
}
|
|
66707
|
+
};
|
|
66708
|
+
}
|
|
66709
|
+
case "novel_association": {
|
|
66710
|
+
const [sourceNode, targetNode] = concepts;
|
|
66711
|
+
return {
|
|
66712
|
+
name: `Association: ${sourceNode?.conceptType} - ${targetNode?.conceptType}`,
|
|
66713
|
+
description: insight.description,
|
|
66714
|
+
template: {
|
|
66715
|
+
type: "association_pattern",
|
|
66716
|
+
source: {
|
|
66717
|
+
id: sourceNode?.id,
|
|
66718
|
+
type: sourceNode?.conceptType,
|
|
66719
|
+
content: sourceNode?.content
|
|
66720
|
+
},
|
|
66721
|
+
target: {
|
|
66722
|
+
id: targetNode?.id,
|
|
66723
|
+
type: targetNode?.conceptType,
|
|
66724
|
+
content: targetNode?.content
|
|
66725
|
+
},
|
|
66726
|
+
metadata: {
|
|
66727
|
+
noveltyScore: insight.noveltyScore,
|
|
66728
|
+
confidenceScore: insight.confidenceScore,
|
|
66729
|
+
createdFrom: "dream_insight"
|
|
66730
|
+
}
|
|
66731
|
+
}
|
|
66732
|
+
};
|
|
66733
|
+
}
|
|
66734
|
+
case "optimization": {
|
|
66735
|
+
const [concept] = concepts;
|
|
66736
|
+
return {
|
|
66737
|
+
name: `Optimized: ${this.truncate(concept?.content ?? "", 30)}`,
|
|
66738
|
+
description: insight.description,
|
|
66739
|
+
template: {
|
|
66740
|
+
type: "optimization_pattern",
|
|
66741
|
+
originalPattern: concept?.id,
|
|
66742
|
+
suggestedAction: insight.suggestedAction,
|
|
66743
|
+
metadata: {
|
|
66744
|
+
noveltyScore: insight.noveltyScore,
|
|
66745
|
+
confidenceScore: insight.confidenceScore,
|
|
66746
|
+
createdFrom: "dream_insight"
|
|
66747
|
+
}
|
|
66748
|
+
}
|
|
66749
|
+
};
|
|
66750
|
+
}
|
|
66751
|
+
case "gap_detection": {
|
|
66752
|
+
const [concept] = concepts;
|
|
66753
|
+
return {
|
|
66754
|
+
name: `Gap Fill: ${this.truncate(concept?.content ?? "", 30)}`,
|
|
66755
|
+
description: insight.description,
|
|
66756
|
+
template: {
|
|
66757
|
+
type: "gap_fill_pattern",
|
|
66758
|
+
relatedConcept: concept?.id,
|
|
66759
|
+
gapType: concept?.conceptType === "error" ? "missing_resolution" : "missing_technique",
|
|
66760
|
+
suggestedAction: insight.suggestedAction,
|
|
66761
|
+
metadata: {
|
|
66762
|
+
noveltyScore: insight.noveltyScore,
|
|
66763
|
+
confidenceScore: insight.confidenceScore,
|
|
66764
|
+
createdFrom: "dream_insight"
|
|
66765
|
+
}
|
|
66766
|
+
}
|
|
66767
|
+
};
|
|
66768
|
+
}
|
|
66769
|
+
default:
|
|
66770
|
+
return null;
|
|
66771
|
+
}
|
|
66772
|
+
}
|
|
66773
|
+
// ==========================================================================
|
|
66774
|
+
// Helper Methods
|
|
66775
|
+
// ==========================================================================
|
|
66776
|
+
/**
|
|
66777
|
+
* Generate a unique ID for an insight
|
|
66778
|
+
*/
|
|
66779
|
+
generateId() {
|
|
66780
|
+
const timestamp = Date.now();
|
|
66781
|
+
const random = Math.random().toString(36).substring(2, 10);
|
|
66782
|
+
return `insight-${timestamp}-${random}`;
|
|
66783
|
+
}
|
|
66784
|
+
/**
|
|
66785
|
+
* Calculate content similarity using Jaccard similarity
|
|
66786
|
+
*/
|
|
66787
|
+
calculateContentSimilarity(contentA, contentB) {
|
|
66788
|
+
const wordsA = contentA.toLowerCase().split(/\s+/);
|
|
66789
|
+
const wordsB = contentB.toLowerCase().split(/\s+/);
|
|
66790
|
+
const setA = new Set(wordsA);
|
|
66791
|
+
const setB = new Set(wordsB);
|
|
66792
|
+
const intersection = wordsA.filter((w) => setB.has(w));
|
|
66793
|
+
const unionSize = setA.size + setB.size - intersection.length;
|
|
66794
|
+
if (unionSize === 0) return 0;
|
|
66795
|
+
return intersection.length / unionSize;
|
|
66796
|
+
}
|
|
66797
|
+
/**
|
|
66798
|
+
* Truncate string to max length
|
|
66799
|
+
*/
|
|
66800
|
+
truncate(str, maxLength) {
|
|
66801
|
+
if (str.length <= maxLength) return str;
|
|
66802
|
+
return str.substring(0, maxLength - 3) + "...";
|
|
66803
|
+
}
|
|
66804
|
+
/**
|
|
66805
|
+
* Generate description for pattern merge insight
|
|
66806
|
+
*/
|
|
66807
|
+
generatePatternMergeDescription(nodeA, nodeB, mergeScore) {
|
|
66808
|
+
const scorePercent = Math.round(mergeScore * 100);
|
|
66809
|
+
return `Pattern merge opportunity (${scorePercent}% match): "${this.truncate(nodeA.content, 40)}" and "${this.truncate(nodeB.content, 40)}" share similar structure and could be combined.`;
|
|
66810
|
+
}
|
|
66811
|
+
/**
|
|
66812
|
+
* Generate description for novel association insight
|
|
66813
|
+
*/
|
|
66814
|
+
generateNovelAssociationDescription(source, target, strength, isCrossDomain) {
|
|
66815
|
+
const strengthPercent = Math.round(strength * 100);
|
|
66816
|
+
const domainNote = isCrossDomain ? " (cross-domain)" : "";
|
|
66817
|
+
return `Novel association discovered${domainNote}: [${source.conceptType}] "${this.truncate(source.content, 30)}" is connected to [${target.conceptType}] "${this.truncate(target.content, 30)}" with ${strengthPercent}% co-activation strength.`;
|
|
66818
|
+
}
|
|
66819
|
+
/**
|
|
66820
|
+
* Generate description for optimization insight
|
|
66821
|
+
*/
|
|
66822
|
+
generateOptimizationDescription(node, successRate, executionCount) {
|
|
66823
|
+
const parts = [
|
|
66824
|
+
`Optimization opportunity for "${this.truncate(node.content, 40)}":`
|
|
66825
|
+
];
|
|
66826
|
+
if (successRate !== void 0) {
|
|
66827
|
+
parts.push(`Success rate is ${Math.round(successRate * 100)}%.`);
|
|
66828
|
+
}
|
|
66829
|
+
if (executionCount !== void 0) {
|
|
66830
|
+
parts.push(`Used ${executionCount} times.`);
|
|
66831
|
+
}
|
|
66832
|
+
parts.push("Consider reviewing and improving this pattern.");
|
|
66833
|
+
return parts.join(" ");
|
|
66834
|
+
}
|
|
66835
|
+
/**
|
|
66836
|
+
* Get configuration
|
|
66837
|
+
*/
|
|
66838
|
+
getConfig() {
|
|
66839
|
+
return { ...this.config };
|
|
66840
|
+
}
|
|
66841
|
+
};
|
|
66842
|
+
|
|
66843
|
+
// src/learning/dream/dream-engine.ts
|
|
66844
|
+
import { v4 as uuidv443 } from "uuid";
|
|
66845
|
+
var DEFAULT_DREAM_CONFIG = {
|
|
66846
|
+
maxDurationMs: 3e4,
|
|
66847
|
+
minConceptsRequired: 10,
|
|
66848
|
+
activationConfig: {
|
|
66849
|
+
decayRate: 0.1,
|
|
66850
|
+
spreadFactor: 0.5,
|
|
66851
|
+
threshold: 0.1,
|
|
66852
|
+
maxIterations: 20,
|
|
66853
|
+
noiseLevel: 0.05
|
|
66854
|
+
},
|
|
66855
|
+
insightConfig: {
|
|
66856
|
+
minNoveltyScore: 0.3,
|
|
66857
|
+
minConfidence: 0.5,
|
|
66858
|
+
maxInsightsPerCycle: 10
|
|
66859
|
+
}
|
|
66860
|
+
};
|
|
66861
|
+
var ConceptGraphAdapter = class {
|
|
66862
|
+
constructor(graph) {
|
|
66863
|
+
this.graph = graph;
|
|
66864
|
+
}
|
|
66865
|
+
nodeCache = /* @__PURE__ */ new Map();
|
|
66866
|
+
edgeCache = /* @__PURE__ */ new Map();
|
|
66867
|
+
activationLevels = /* @__PURE__ */ new Map();
|
|
66868
|
+
/**
|
|
66869
|
+
* Load all nodes and edges into memory for fast access
|
|
66870
|
+
*/
|
|
66871
|
+
async loadIntoMemory() {
|
|
66872
|
+
this.nodeCache.clear();
|
|
66873
|
+
this.edgeCache.clear();
|
|
66874
|
+
this.activationLevels.clear();
|
|
66875
|
+
const nodes = await this.graph.getActiveNodes(0);
|
|
66876
|
+
for (const node of nodes) {
|
|
66877
|
+
this.nodeCache.set(node.id, node);
|
|
66878
|
+
this.activationLevels.set(node.id, node.activationLevel);
|
|
66879
|
+
}
|
|
66880
|
+
for (const node of nodes) {
|
|
66881
|
+
const neighbors = await this.graph.getNeighbors(node.id);
|
|
66882
|
+
const edges = neighbors.map((n) => n.edge);
|
|
66883
|
+
this.edgeCache.set(node.id, edges);
|
|
66884
|
+
}
|
|
66885
|
+
}
|
|
66886
|
+
/**
|
|
66887
|
+
* Persist activation levels back to the database
|
|
66888
|
+
*/
|
|
66889
|
+
async persistActivations() {
|
|
66890
|
+
const entries = Array.from(this.activationLevels.entries());
|
|
66891
|
+
for (const [nodeId, level] of entries) {
|
|
66892
|
+
await this.graph.updateActivation(nodeId, level);
|
|
66893
|
+
}
|
|
66894
|
+
}
|
|
66895
|
+
// SpreadingConceptGraph interface implementation
|
|
66896
|
+
getConcept(id) {
|
|
66897
|
+
const node = this.nodeCache.get(id);
|
|
66898
|
+
if (node) {
|
|
66899
|
+
return {
|
|
66900
|
+
...node,
|
|
66901
|
+
activationLevel: this.activationLevels.get(id) ?? node.activationLevel
|
|
66902
|
+
};
|
|
66903
|
+
}
|
|
66904
|
+
return void 0;
|
|
66905
|
+
}
|
|
66906
|
+
getAllConcepts(minActivation) {
|
|
66907
|
+
const threshold = minActivation ?? 0;
|
|
66908
|
+
return Array.from(this.nodeCache.values()).map((node) => ({
|
|
66909
|
+
...node,
|
|
66910
|
+
activationLevel: this.activationLevels.get(node.id) ?? node.activationLevel
|
|
66911
|
+
})).filter((node) => node.activationLevel >= threshold);
|
|
66912
|
+
}
|
|
66913
|
+
getActiveNodes(threshold) {
|
|
66914
|
+
return this.getAllConcepts(threshold);
|
|
66915
|
+
}
|
|
66916
|
+
getEdges(nodeId) {
|
|
66917
|
+
return this.edgeCache.get(nodeId) ?? [];
|
|
66918
|
+
}
|
|
66919
|
+
getEdge(source, target) {
|
|
66920
|
+
const edges = this.edgeCache.get(source) ?? [];
|
|
66921
|
+
return edges.find((e) => e.target === target);
|
|
66922
|
+
}
|
|
66923
|
+
setActivation(nodeId, level) {
|
|
66924
|
+
this.activationLevels.set(nodeId, Math.max(0, Math.min(1, level)));
|
|
66925
|
+
}
|
|
66926
|
+
decayActivations(factor) {
|
|
66927
|
+
const entries = Array.from(this.activationLevels.entries());
|
|
66928
|
+
for (const [nodeId, level] of entries) {
|
|
66929
|
+
this.activationLevels.set(nodeId, level * factor);
|
|
66930
|
+
}
|
|
66931
|
+
}
|
|
66932
|
+
getStats() {
|
|
66933
|
+
const nodes = Array.from(this.nodeCache.values());
|
|
66934
|
+
const byType = {
|
|
66935
|
+
pattern: 0,
|
|
66936
|
+
technique: 0,
|
|
66937
|
+
domain: 0,
|
|
66938
|
+
outcome: 0,
|
|
66939
|
+
error: 0
|
|
66940
|
+
};
|
|
66941
|
+
let totalActivation = 0;
|
|
66942
|
+
for (const node of nodes) {
|
|
66943
|
+
byType[node.conceptType] = (byType[node.conceptType] ?? 0) + 1;
|
|
66944
|
+
totalActivation += this.activationLevels.get(node.id) ?? node.activationLevel;
|
|
66945
|
+
}
|
|
66946
|
+
let totalEdges = 0;
|
|
66947
|
+
const edgeValues = Array.from(this.edgeCache.values());
|
|
66948
|
+
for (const edges of edgeValues) {
|
|
66949
|
+
totalEdges += edges.length;
|
|
66950
|
+
}
|
|
66951
|
+
return {
|
|
66952
|
+
nodeCount: nodes.length,
|
|
66953
|
+
edgeCount: totalEdges,
|
|
66954
|
+
byType,
|
|
66955
|
+
avgEdgesPerNode: nodes.length > 0 ? totalEdges / nodes.length : 0,
|
|
66956
|
+
avgActivation: nodes.length > 0 ? totalActivation / nodes.length : 0
|
|
66957
|
+
};
|
|
66958
|
+
}
|
|
66959
|
+
};
|
|
66960
|
+
var DreamEngine = class {
|
|
66961
|
+
config;
|
|
66962
|
+
persistence = null;
|
|
66963
|
+
graph = null;
|
|
66964
|
+
db = null;
|
|
66965
|
+
currentCycle = null;
|
|
66966
|
+
initialized = false;
|
|
66967
|
+
cancelled = false;
|
|
66968
|
+
constructor(config) {
|
|
66969
|
+
this.config = { ...DEFAULT_DREAM_CONFIG, ...config };
|
|
66970
|
+
}
|
|
66971
|
+
// ==========================================================================
|
|
66972
|
+
// Initialization
|
|
66973
|
+
// ==========================================================================
|
|
66974
|
+
/**
|
|
66975
|
+
* Initialize using unified persistence
|
|
66976
|
+
*/
|
|
66977
|
+
async initialize() {
|
|
66978
|
+
if (this.initialized) return;
|
|
66979
|
+
try {
|
|
66980
|
+
this.persistence = getUnifiedPersistence();
|
|
66981
|
+
if (!this.persistence.isInitialized()) {
|
|
66982
|
+
await this.persistence.initialize();
|
|
66983
|
+
}
|
|
66984
|
+
this.db = this.persistence.getDatabase();
|
|
66985
|
+
this.graph = new ConceptGraph();
|
|
66986
|
+
await this.graph.initialize();
|
|
66987
|
+
this.initialized = true;
|
|
66988
|
+
console.log(`[DreamEngine] Initialized: ${this.persistence.getDbPath()}`);
|
|
66989
|
+
} catch (error) {
|
|
66990
|
+
throw new Error(
|
|
66991
|
+
`Failed to initialize DreamEngine: ${error instanceof Error ? error.message : String(error)}`
|
|
66992
|
+
);
|
|
66993
|
+
}
|
|
66994
|
+
}
|
|
66995
|
+
// ==========================================================================
|
|
66996
|
+
// Main Dream Cycle
|
|
66997
|
+
// ==========================================================================
|
|
66998
|
+
/**
|
|
66999
|
+
* Run a complete dream cycle.
|
|
67000
|
+
*
|
|
67001
|
+
* The dream cycle:
|
|
67002
|
+
* 1. Checks for sufficient concepts
|
|
67003
|
+
* 2. Runs spreading activation (the "dreaming")
|
|
67004
|
+
* 3. Finds novel associations
|
|
67005
|
+
* 4. Generates insights from activation patterns
|
|
67006
|
+
* 5. Persists the cycle and insights
|
|
67007
|
+
*
|
|
67008
|
+
* @param durationMs - Maximum duration in milliseconds (default: config.maxDurationMs)
|
|
67009
|
+
* @returns Dream cycle result with insights and statistics
|
|
67010
|
+
*/
|
|
67011
|
+
async dream(durationMs) {
|
|
67012
|
+
this.ensureInitialized();
|
|
67013
|
+
this.cancelled = false;
|
|
67014
|
+
const maxDuration = durationMs ?? this.config.maxDurationMs;
|
|
67015
|
+
const startTime = Date.now();
|
|
67016
|
+
this.currentCycle = {
|
|
67017
|
+
id: uuidv443(),
|
|
67018
|
+
startTime: /* @__PURE__ */ new Date(),
|
|
67019
|
+
conceptsProcessed: 0,
|
|
67020
|
+
associationsFound: 0,
|
|
67021
|
+
insightsGenerated: 0,
|
|
67022
|
+
status: "running"
|
|
67023
|
+
};
|
|
67024
|
+
await this.saveCycle(this.currentCycle);
|
|
67025
|
+
try {
|
|
67026
|
+
const allNodes = await this.graph.getActiveNodes(0);
|
|
67027
|
+
if (allNodes.length < this.config.minConceptsRequired) {
|
|
67028
|
+
throw new Error(
|
|
67029
|
+
`Insufficient concepts: ${allNodes.length} < ${this.config.minConceptsRequired}`
|
|
67030
|
+
);
|
|
67031
|
+
}
|
|
67032
|
+
const adapter = new ConceptGraphAdapter(this.graph);
|
|
67033
|
+
await adapter.loadIntoMemory();
|
|
67034
|
+
const activation = new SpreadingActivation(adapter, this.config.activationConfig);
|
|
67035
|
+
const activationResult = await activation.dream(maxDuration);
|
|
67036
|
+
if (this.cancelled) {
|
|
67037
|
+
this.currentCycle.status = "interrupted";
|
|
67038
|
+
this.currentCycle.endTime = /* @__PURE__ */ new Date();
|
|
67039
|
+
this.currentCycle.durationMs = Date.now() - startTime;
|
|
67040
|
+
await this.updateCycle(this.currentCycle);
|
|
67041
|
+
throw new Error("Dream cycle cancelled");
|
|
67042
|
+
}
|
|
67043
|
+
this.currentCycle.conceptsProcessed = activationResult.nodesActivated;
|
|
67044
|
+
this.currentCycle.associationsFound = activationResult.novelAssociations.length;
|
|
67045
|
+
await adapter.persistActivations();
|
|
67046
|
+
const generator = new InsightGenerator(adapter, this.config.insightConfig);
|
|
67047
|
+
const insights = await generator.generateFromActivation(
|
|
67048
|
+
this.currentCycle.id,
|
|
67049
|
+
activationResult
|
|
67050
|
+
);
|
|
67051
|
+
this.currentCycle.insightsGenerated = insights.length;
|
|
67052
|
+
for (const insight of insights) {
|
|
67053
|
+
await this.saveInsight(insight);
|
|
67054
|
+
}
|
|
67055
|
+
this.currentCycle.endTime = /* @__PURE__ */ new Date();
|
|
67056
|
+
this.currentCycle.durationMs = Date.now() - startTime;
|
|
67057
|
+
this.currentCycle.status = "completed";
|
|
67058
|
+
await this.updateCycle(this.currentCycle);
|
|
67059
|
+
const result = {
|
|
67060
|
+
cycle: { ...this.currentCycle },
|
|
67061
|
+
insights,
|
|
67062
|
+
activationStats: {
|
|
67063
|
+
totalIterations: activationResult.iterations,
|
|
67064
|
+
peakActivation: activationResult.peakActivation,
|
|
67065
|
+
nodesActivated: activationResult.nodesActivated
|
|
67066
|
+
},
|
|
67067
|
+
patternsCreated: 0
|
|
67068
|
+
// Updated when insights are applied
|
|
67069
|
+
};
|
|
67070
|
+
this.currentCycle = null;
|
|
67071
|
+
return result;
|
|
67072
|
+
} catch (error) {
|
|
67073
|
+
if (this.currentCycle) {
|
|
67074
|
+
if (this.currentCycle.status === "running") {
|
|
67075
|
+
this.currentCycle.status = "failed";
|
|
67076
|
+
}
|
|
67077
|
+
this.currentCycle.error = error instanceof Error ? error.message : String(error);
|
|
67078
|
+
this.currentCycle.endTime = /* @__PURE__ */ new Date();
|
|
67079
|
+
this.currentCycle.durationMs = Date.now() - startTime;
|
|
67080
|
+
await this.updateCycle(this.currentCycle);
|
|
67081
|
+
}
|
|
67082
|
+
this.currentCycle = null;
|
|
67083
|
+
throw error;
|
|
67084
|
+
}
|
|
67085
|
+
}
|
|
67086
|
+
// ==========================================================================
|
|
67087
|
+
// Pattern Loading
|
|
67088
|
+
// ==========================================================================
|
|
67089
|
+
/**
|
|
67090
|
+
* Load patterns as concepts for dreaming.
|
|
67091
|
+
*
|
|
67092
|
+
* Converts patterns from the pattern store into concept nodes
|
|
67093
|
+
* that can be activated during dream cycles.
|
|
67094
|
+
*
|
|
67095
|
+
* @param patterns - Array of pattern data to load
|
|
67096
|
+
* @returns Number of patterns successfully loaded
|
|
67097
|
+
*/
|
|
67098
|
+
async loadPatternsAsConcepts(patterns) {
|
|
67099
|
+
this.ensureInitialized();
|
|
67100
|
+
return this.graph.loadFromPatterns(patterns);
|
|
67101
|
+
}
|
|
67102
|
+
// ==========================================================================
|
|
67103
|
+
// Insight Management
|
|
67104
|
+
// ==========================================================================
|
|
67105
|
+
/**
|
|
67106
|
+
* Apply an insight by converting it to a pattern.
|
|
67107
|
+
*
|
|
67108
|
+
* @param insightId - ID of the insight to apply
|
|
67109
|
+
* @returns Result with success status and pattern ID
|
|
67110
|
+
*/
|
|
67111
|
+
async applyInsight(insightId) {
|
|
67112
|
+
this.ensureInitialized();
|
|
67113
|
+
try {
|
|
67114
|
+
const insightRow = await this.getInsightRowById(insightId);
|
|
67115
|
+
if (!insightRow) {
|
|
67116
|
+
return { success: false, error: `Insight not found: ${insightId}` };
|
|
67117
|
+
}
|
|
67118
|
+
if (insightRow.actionable !== 1) {
|
|
67119
|
+
return { success: false, error: "Insight is not actionable" };
|
|
67120
|
+
}
|
|
67121
|
+
if (insightRow.applied === 1) {
|
|
67122
|
+
return {
|
|
67123
|
+
success: true,
|
|
67124
|
+
patternId: insightRow.pattern_id ?? void 0,
|
|
67125
|
+
error: "Insight already applied"
|
|
67126
|
+
};
|
|
67127
|
+
}
|
|
67128
|
+
const patternId = `dream-pattern-${uuidv443()}`;
|
|
67129
|
+
const stmt = this.db.prepare(`
|
|
67130
|
+
UPDATE dream_insights
|
|
67131
|
+
SET applied = 1, pattern_id = ?
|
|
67132
|
+
WHERE id = ?
|
|
67133
|
+
`);
|
|
67134
|
+
stmt.run(patternId, insightId);
|
|
67135
|
+
return { success: true, patternId };
|
|
67136
|
+
} catch (error) {
|
|
67137
|
+
return {
|
|
67138
|
+
success: false,
|
|
67139
|
+
error: error instanceof Error ? error.message : String(error)
|
|
67140
|
+
};
|
|
67141
|
+
}
|
|
67142
|
+
}
|
|
67143
|
+
/**
|
|
67144
|
+
* Get pending insights that haven't been applied.
|
|
67145
|
+
*
|
|
67146
|
+
* @param limit - Maximum number of insights to return (default: 20)
|
|
67147
|
+
* @returns Array of pending insights
|
|
67148
|
+
*/
|
|
67149
|
+
async getPendingInsights(limit) {
|
|
67150
|
+
this.ensureInitialized();
|
|
67151
|
+
const maxResults = limit ?? 20;
|
|
67152
|
+
const stmt = this.db.prepare(`
|
|
67153
|
+
SELECT * FROM dream_insights
|
|
67154
|
+
WHERE applied = 0 AND actionable = 1
|
|
67155
|
+
ORDER BY novelty_score DESC, confidence_score DESC
|
|
67156
|
+
LIMIT ?
|
|
67157
|
+
`);
|
|
67158
|
+
const rows = stmt.all(maxResults);
|
|
67159
|
+
return rows.map((row) => this.rowToInsight(row));
|
|
67160
|
+
}
|
|
67161
|
+
/**
|
|
67162
|
+
* Get dream cycle history.
|
|
67163
|
+
*
|
|
67164
|
+
* @param limit - Maximum number of cycles to return (default: 20)
|
|
67165
|
+
* @returns Array of dream cycles
|
|
67166
|
+
*/
|
|
67167
|
+
async getDreamHistory(limit) {
|
|
67168
|
+
this.ensureInitialized();
|
|
67169
|
+
const maxResults = limit ?? 20;
|
|
67170
|
+
const stmt = this.db.prepare(`
|
|
67171
|
+
SELECT * FROM dream_cycles
|
|
67172
|
+
ORDER BY start_time DESC
|
|
67173
|
+
LIMIT ?
|
|
67174
|
+
`);
|
|
67175
|
+
const rows = stmt.all(maxResults);
|
|
67176
|
+
return rows.map((row) => this.rowToCycle(row));
|
|
67177
|
+
}
|
|
67178
|
+
// ==========================================================================
|
|
67179
|
+
// Dream Control
|
|
67180
|
+
// ==========================================================================
|
|
67181
|
+
/**
|
|
67182
|
+
* Cancel the running dream cycle.
|
|
67183
|
+
*/
|
|
67184
|
+
async cancelDream() {
|
|
67185
|
+
this.cancelled = true;
|
|
67186
|
+
}
|
|
67187
|
+
/**
|
|
67188
|
+
* Check if a dream is currently running.
|
|
67189
|
+
*/
|
|
67190
|
+
isDreaming() {
|
|
67191
|
+
return this.currentCycle !== null && this.currentCycle.status === "running";
|
|
67192
|
+
}
|
|
67193
|
+
/**
|
|
67194
|
+
* Get the current dream cycle status.
|
|
67195
|
+
*/
|
|
67196
|
+
getCurrentCycle() {
|
|
67197
|
+
return this.currentCycle ? { ...this.currentCycle } : null;
|
|
67198
|
+
}
|
|
67199
|
+
// ==========================================================================
|
|
67200
|
+
// Persistence
|
|
67201
|
+
// ==========================================================================
|
|
67202
|
+
async saveCycle(cycle) {
|
|
67203
|
+
if (!this.db) return;
|
|
67204
|
+
const stmt = this.db.prepare(`
|
|
67205
|
+
INSERT INTO dream_cycles
|
|
67206
|
+
(id, start_time, end_time, duration_ms, concepts_processed, associations_found,
|
|
67207
|
+
insights_generated, status, error)
|
|
67208
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
67209
|
+
`);
|
|
67210
|
+
stmt.run(
|
|
67211
|
+
cycle.id,
|
|
67212
|
+
cycle.startTime.toISOString(),
|
|
67213
|
+
cycle.endTime?.toISOString() ?? null,
|
|
67214
|
+
cycle.durationMs ?? null,
|
|
67215
|
+
cycle.conceptsProcessed,
|
|
67216
|
+
cycle.associationsFound,
|
|
67217
|
+
cycle.insightsGenerated,
|
|
67218
|
+
cycle.status,
|
|
67219
|
+
cycle.error ?? null
|
|
67220
|
+
);
|
|
67221
|
+
}
|
|
67222
|
+
async updateCycle(cycle) {
|
|
67223
|
+
if (!this.db) return;
|
|
67224
|
+
const stmt = this.db.prepare(`
|
|
67225
|
+
UPDATE dream_cycles
|
|
67226
|
+
SET end_time = ?, duration_ms = ?, concepts_processed = ?, associations_found = ?,
|
|
67227
|
+
insights_generated = ?, status = ?, error = ?
|
|
67228
|
+
WHERE id = ?
|
|
67229
|
+
`);
|
|
67230
|
+
stmt.run(
|
|
67231
|
+
cycle.endTime?.toISOString() ?? null,
|
|
67232
|
+
cycle.durationMs ?? null,
|
|
67233
|
+
cycle.conceptsProcessed,
|
|
67234
|
+
cycle.associationsFound,
|
|
67235
|
+
cycle.insightsGenerated,
|
|
67236
|
+
cycle.status,
|
|
67237
|
+
cycle.error ?? null,
|
|
67238
|
+
cycle.id
|
|
67239
|
+
);
|
|
67240
|
+
}
|
|
67241
|
+
async saveInsight(insight) {
|
|
67242
|
+
if (!this.db) return;
|
|
67243
|
+
const stmt = this.db.prepare(`
|
|
67244
|
+
INSERT INTO dream_insights
|
|
67245
|
+
(id, cycle_id, insight_type, source_concepts, description, novelty_score,
|
|
67246
|
+
confidence_score, actionable, applied, suggested_action, pattern_id)
|
|
67247
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
67248
|
+
`);
|
|
67249
|
+
stmt.run(
|
|
67250
|
+
insight.id,
|
|
67251
|
+
insight.cycleId,
|
|
67252
|
+
insight.type,
|
|
67253
|
+
JSON.stringify(insight.sourceConcepts),
|
|
67254
|
+
insight.description,
|
|
67255
|
+
insight.noveltyScore,
|
|
67256
|
+
insight.confidenceScore,
|
|
67257
|
+
insight.actionable ? 1 : 0,
|
|
67258
|
+
0,
|
|
67259
|
+
// Not applied yet
|
|
67260
|
+
insight.suggestedAction ?? null,
|
|
67261
|
+
null
|
|
67262
|
+
// No pattern yet
|
|
67263
|
+
);
|
|
67264
|
+
}
|
|
67265
|
+
async getInsightRowById(id) {
|
|
67266
|
+
if (!this.db) return null;
|
|
67267
|
+
const stmt = this.db.prepare("SELECT * FROM dream_insights WHERE id = ?");
|
|
67268
|
+
const row = stmt.get(id);
|
|
67269
|
+
return row ?? null;
|
|
67270
|
+
}
|
|
67271
|
+
// ==========================================================================
|
|
67272
|
+
// Cleanup
|
|
67273
|
+
// ==========================================================================
|
|
67274
|
+
/**
|
|
67275
|
+
* Release resources (does NOT close the shared database)
|
|
67276
|
+
*/
|
|
67277
|
+
async close() {
|
|
67278
|
+
if (this.graph) {
|
|
67279
|
+
await this.graph.close();
|
|
67280
|
+
this.graph = null;
|
|
67281
|
+
}
|
|
67282
|
+
this.db = null;
|
|
67283
|
+
this.persistence = null;
|
|
67284
|
+
this.initialized = false;
|
|
67285
|
+
this.currentCycle = null;
|
|
67286
|
+
}
|
|
67287
|
+
// ==========================================================================
|
|
67288
|
+
// Private Helpers
|
|
67289
|
+
// ==========================================================================
|
|
67290
|
+
ensureInitialized() {
|
|
67291
|
+
if (!this.initialized || !this.graph || !this.db) {
|
|
67292
|
+
throw new Error("DreamEngine not initialized. Call initialize() first.");
|
|
67293
|
+
}
|
|
67294
|
+
}
|
|
67295
|
+
rowToCycle(row) {
|
|
67296
|
+
return {
|
|
67297
|
+
id: row.id,
|
|
67298
|
+
startTime: new Date(row.start_time),
|
|
67299
|
+
endTime: row.end_time ? new Date(row.end_time) : void 0,
|
|
67300
|
+
durationMs: row.duration_ms ?? void 0,
|
|
67301
|
+
conceptsProcessed: row.concepts_processed,
|
|
67302
|
+
associationsFound: row.associations_found,
|
|
67303
|
+
insightsGenerated: row.insights_generated,
|
|
67304
|
+
status: row.status,
|
|
67305
|
+
error: row.error ?? void 0
|
|
67306
|
+
};
|
|
67307
|
+
}
|
|
67308
|
+
rowToInsight(row) {
|
|
67309
|
+
return {
|
|
67310
|
+
id: row.id,
|
|
67311
|
+
cycleId: row.cycle_id,
|
|
67312
|
+
type: row.insight_type,
|
|
67313
|
+
sourceConcepts: JSON.parse(row.source_concepts),
|
|
67314
|
+
description: row.description,
|
|
67315
|
+
noveltyScore: row.novelty_score,
|
|
67316
|
+
confidenceScore: row.confidence_score,
|
|
67317
|
+
actionable: row.actionable === 1,
|
|
67318
|
+
applied: row.applied === 1,
|
|
67319
|
+
patternId: row.pattern_id ?? void 0,
|
|
67320
|
+
suggestedAction: row.suggested_action ?? void 0,
|
|
67321
|
+
createdAt: new Date(row.created_at)
|
|
67322
|
+
};
|
|
67323
|
+
}
|
|
67324
|
+
};
|
|
67325
|
+
function createDreamEngine(config) {
|
|
67326
|
+
return new DreamEngine(config);
|
|
67327
|
+
}
|
|
67328
|
+
|
|
67329
|
+
// src/learning/dream/dream-scheduler.ts
|
|
67330
|
+
import { v4 as uuidv444 } from "uuid";
|
|
67331
|
+
var DEFAULT_DREAM_SCHEDULER_CONFIG = {
|
|
67332
|
+
// Time-based scheduling
|
|
67333
|
+
autoScheduleIntervalMs: 36e5,
|
|
67334
|
+
// 1 hour
|
|
67335
|
+
minTimeBetweenDreamsMs: 3e5,
|
|
67336
|
+
// 5 minutes
|
|
67337
|
+
// Experience-based triggers
|
|
67338
|
+
experienceThreshold: 20,
|
|
67339
|
+
enableExperienceTrigger: true,
|
|
67340
|
+
// Event-based triggers
|
|
67341
|
+
enableQualityGateFailureTrigger: true,
|
|
67342
|
+
enableDomainMilestoneTrigger: false,
|
|
67343
|
+
// Dream configuration
|
|
67344
|
+
defaultDreamDurationMs: 1e4,
|
|
67345
|
+
// 10 seconds
|
|
67346
|
+
quickDreamDurationMs: 5e3,
|
|
67347
|
+
// 5 seconds
|
|
67348
|
+
fullDreamDurationMs: 3e4,
|
|
67349
|
+
// 30 seconds
|
|
67350
|
+
// Insight handling
|
|
67351
|
+
autoApplyHighConfidenceInsights: false,
|
|
67352
|
+
insightConfidenceThreshold: 0.8
|
|
67353
|
+
};
|
|
67354
|
+
var DreamScheduler = class {
|
|
67355
|
+
config;
|
|
67356
|
+
dreamEngine;
|
|
67357
|
+
eventBus;
|
|
67358
|
+
memoryBackend;
|
|
67359
|
+
// State
|
|
67360
|
+
initialized = false;
|
|
67361
|
+
running = false;
|
|
67362
|
+
dreaming = false;
|
|
67363
|
+
// Experience buffer
|
|
67364
|
+
experienceBuffer = [];
|
|
67365
|
+
// Timing
|
|
67366
|
+
lastDreamTime = null;
|
|
67367
|
+
scheduledDreamTimer = null;
|
|
67368
|
+
totalDreamsCompleted = 0;
|
|
67369
|
+
// Event subscriptions
|
|
67370
|
+
subscriptions = [];
|
|
67371
|
+
// Last result
|
|
67372
|
+
lastDreamResult = null;
|
|
67373
|
+
/**
|
|
67374
|
+
* Create a new DreamScheduler instance.
|
|
67375
|
+
*
|
|
67376
|
+
* @param dependencies - Required dependencies (dreamEngine, eventBus, memoryBackend)
|
|
67377
|
+
* @param config - Optional configuration overrides
|
|
67378
|
+
* @throws {Error} If required dependencies are missing
|
|
67379
|
+
*/
|
|
67380
|
+
constructor(dependencies, config) {
|
|
67381
|
+
if (!dependencies.dreamEngine) {
|
|
67382
|
+
throw new Error("DreamScheduler requires dreamEngine dependency");
|
|
67383
|
+
}
|
|
67384
|
+
if (!dependencies.eventBus) {
|
|
67385
|
+
throw new Error("DreamScheduler requires eventBus dependency");
|
|
67386
|
+
}
|
|
67387
|
+
this.dreamEngine = dependencies.dreamEngine;
|
|
67388
|
+
this.eventBus = dependencies.eventBus;
|
|
67389
|
+
this.memoryBackend = dependencies.memoryBackend;
|
|
67390
|
+
this.config = { ...DEFAULT_DREAM_SCHEDULER_CONFIG, ...config };
|
|
67391
|
+
}
|
|
67392
|
+
// ==========================================================================
|
|
67393
|
+
// Lifecycle Methods
|
|
67394
|
+
// ==========================================================================
|
|
67395
|
+
/**
|
|
67396
|
+
* Initialize the scheduler.
|
|
67397
|
+
*
|
|
67398
|
+
* Sets up event subscriptions and restores state from memory if available.
|
|
67399
|
+
*/
|
|
67400
|
+
async initialize() {
|
|
67401
|
+
if (this.initialized) return;
|
|
67402
|
+
if (this.config.enableQualityGateFailureTrigger) {
|
|
67403
|
+
const qualitySubscription = this.eventBus.subscribe(
|
|
67404
|
+
"quality-assessment:gate:completed",
|
|
67405
|
+
this.handleQualityGateEvent.bind(this)
|
|
67406
|
+
);
|
|
67407
|
+
this.subscriptions.push(qualitySubscription);
|
|
67408
|
+
}
|
|
67409
|
+
if (this.config.enableDomainMilestoneTrigger) {
|
|
67410
|
+
const milestoneSubscription = this.eventBus.subscribe(
|
|
67411
|
+
"coordination:milestone:reached",
|
|
67412
|
+
this.handleDomainMilestoneEvent.bind(this)
|
|
67413
|
+
);
|
|
67414
|
+
this.subscriptions.push(milestoneSubscription);
|
|
67415
|
+
}
|
|
67416
|
+
await this.restoreState();
|
|
67417
|
+
this.initialized = true;
|
|
67418
|
+
console.log("[DreamScheduler] Initialized");
|
|
67419
|
+
}
|
|
67420
|
+
/**
|
|
67421
|
+
* Start the scheduler.
|
|
67422
|
+
*
|
|
67423
|
+
* Begins automatic dream scheduling based on the configured interval.
|
|
67424
|
+
*/
|
|
67425
|
+
start() {
|
|
67426
|
+
this.ensureInitialized();
|
|
67427
|
+
if (this.running) return;
|
|
67428
|
+
this.running = true;
|
|
67429
|
+
this.scheduleNextDream();
|
|
67430
|
+
console.log("[DreamScheduler] Started");
|
|
67431
|
+
}
|
|
67432
|
+
/**
|
|
67433
|
+
* Stop the scheduler.
|
|
67434
|
+
*
|
|
67435
|
+
* Stops automatic scheduling but does not dispose resources.
|
|
67436
|
+
*/
|
|
67437
|
+
stop() {
|
|
67438
|
+
if (!this.running) return;
|
|
67439
|
+
this.running = false;
|
|
67440
|
+
this.clearScheduledDream();
|
|
67441
|
+
console.log("[DreamScheduler] Stopped");
|
|
67442
|
+
}
|
|
67443
|
+
/**
|
|
67444
|
+
* Dispose of all resources.
|
|
67445
|
+
*
|
|
67446
|
+
* Stops scheduling, unsubscribes from events, and saves state.
|
|
67447
|
+
*/
|
|
67448
|
+
async dispose() {
|
|
67449
|
+
this.stop();
|
|
67450
|
+
for (const subscription of this.subscriptions) {
|
|
67451
|
+
subscription.unsubscribe();
|
|
67452
|
+
}
|
|
67453
|
+
this.subscriptions = [];
|
|
67454
|
+
await this.saveState();
|
|
67455
|
+
this.initialized = false;
|
|
67456
|
+
console.log("[DreamScheduler] Disposed");
|
|
67457
|
+
}
|
|
67458
|
+
// ==========================================================================
|
|
67459
|
+
// Manual Dream Triggers
|
|
67460
|
+
// ==========================================================================
|
|
67461
|
+
/**
|
|
67462
|
+
* Manually trigger a dream cycle.
|
|
67463
|
+
*
|
|
67464
|
+
* @param duration - Optional duration override in ms
|
|
67465
|
+
* @returns Result of the dream cycle
|
|
67466
|
+
*/
|
|
67467
|
+
async triggerDream(duration) {
|
|
67468
|
+
this.ensureInitialized();
|
|
67469
|
+
if (!this.canDream()) {
|
|
67470
|
+
const waitTime = this.getTimeUntilCanDream();
|
|
67471
|
+
throw new Error(
|
|
67472
|
+
`Cannot start dream: minimum interval not met. Wait ${Math.ceil(waitTime / 1e3)}s.`
|
|
67473
|
+
);
|
|
67474
|
+
}
|
|
67475
|
+
return this.executeDream(duration ?? this.config.defaultDreamDurationMs);
|
|
64410
67476
|
}
|
|
64411
|
-
// ============================================================================
|
|
64412
|
-
// Intelligence Extraction
|
|
64413
|
-
// ============================================================================
|
|
64414
67477
|
/**
|
|
64415
|
-
*
|
|
67478
|
+
* Trigger a quick dream (shorter duration).
|
|
67479
|
+
*
|
|
67480
|
+
* @returns Result of the dream cycle
|
|
64416
67481
|
*/
|
|
64417
|
-
async
|
|
64418
|
-
|
|
64419
|
-
|
|
64420
|
-
|
|
64421
|
-
|
|
64422
|
-
|
|
64423
|
-
|
|
64424
|
-
|
|
64425
|
-
|
|
64426
|
-
|
|
64427
|
-
|
|
64428
|
-
|
|
64429
|
-
|
|
67482
|
+
async triggerQuickDream() {
|
|
67483
|
+
return this.triggerDream(this.config.quickDreamDurationMs);
|
|
67484
|
+
}
|
|
67485
|
+
/**
|
|
67486
|
+
* Trigger a full dream (longer duration).
|
|
67487
|
+
*
|
|
67488
|
+
* @returns Result of the dream cycle
|
|
67489
|
+
*/
|
|
67490
|
+
async triggerFullDream() {
|
|
67491
|
+
return this.triggerDream(this.config.fullDreamDurationMs);
|
|
67492
|
+
}
|
|
67493
|
+
// ==========================================================================
|
|
67494
|
+
// Experience Recording
|
|
67495
|
+
// ==========================================================================
|
|
67496
|
+
/**
|
|
67497
|
+
* Record a task experience for future dream processing.
|
|
67498
|
+
*
|
|
67499
|
+
* If experience threshold is reached and enabled, triggers a dream.
|
|
67500
|
+
*
|
|
67501
|
+
* @param experience - The experience to record
|
|
67502
|
+
*/
|
|
67503
|
+
recordExperience(experience) {
|
|
67504
|
+
this.experienceBuffer.push(experience);
|
|
67505
|
+
if (this.config.enableExperienceTrigger && this.experienceBuffer.length >= this.config.experienceThreshold && this.canDream() && !this.dreaming) {
|
|
67506
|
+
console.log(
|
|
67507
|
+
`[DreamScheduler] Experience threshold (${this.config.experienceThreshold}) reached, triggering dream`
|
|
64430
67508
|
);
|
|
64431
|
-
|
|
64432
|
-
|
|
64433
|
-
experienceCount,
|
|
64434
|
-
successRate,
|
|
64435
|
-
avgReward,
|
|
64436
|
-
patterns: [],
|
|
64437
|
-
anomalies,
|
|
64438
|
-
recommendations
|
|
67509
|
+
this.executeDream(this.config.defaultDreamDurationMs).catch((err3) => {
|
|
67510
|
+
console.error("[DreamScheduler] Experience-triggered dream failed:", err3);
|
|
64439
67511
|
});
|
|
64440
|
-
} catch (error) {
|
|
64441
|
-
return err(error instanceof Error ? error : new Error(String(error)));
|
|
64442
67512
|
}
|
|
64443
67513
|
}
|
|
64444
67514
|
/**
|
|
64445
|
-
*
|
|
67515
|
+
* Get the current experience buffer.
|
|
67516
|
+
*
|
|
67517
|
+
* @returns Copy of the experience buffer
|
|
64446
67518
|
*/
|
|
64447
|
-
|
|
67519
|
+
getExperienceBuffer() {
|
|
67520
|
+
return [...this.experienceBuffer];
|
|
67521
|
+
}
|
|
67522
|
+
/**
|
|
67523
|
+
* Clear the experience buffer.
|
|
67524
|
+
*/
|
|
67525
|
+
clearExperienceBuffer() {
|
|
67526
|
+
this.experienceBuffer = [];
|
|
67527
|
+
}
|
|
67528
|
+
// ==========================================================================
|
|
67529
|
+
// Status Methods
|
|
67530
|
+
// ==========================================================================
|
|
67531
|
+
/**
|
|
67532
|
+
* Get the current scheduler status.
|
|
67533
|
+
*
|
|
67534
|
+
* @returns Current status object
|
|
67535
|
+
*/
|
|
67536
|
+
getStatus() {
|
|
67537
|
+
const timeUntilNext = this.scheduledDreamTimer ? this.getTimeUntilScheduledDream() : null;
|
|
67538
|
+
return {
|
|
67539
|
+
initialized: this.initialized,
|
|
67540
|
+
running: this.running,
|
|
67541
|
+
dreaming: this.dreaming,
|
|
67542
|
+
experienceCount: this.experienceBuffer.length,
|
|
67543
|
+
experienceThreshold: this.config.experienceThreshold,
|
|
67544
|
+
timeUntilNextDream: timeUntilNext,
|
|
67545
|
+
totalDreamsCompleted: this.totalDreamsCompleted,
|
|
67546
|
+
lastDreamTime: this.lastDreamTime,
|
|
67547
|
+
autoSchedulingEnabled: this.running
|
|
67548
|
+
};
|
|
67549
|
+
}
|
|
67550
|
+
/**
|
|
67551
|
+
* Get the result of the last completed dream.
|
|
67552
|
+
*
|
|
67553
|
+
* @returns Last dream result or null
|
|
67554
|
+
*/
|
|
67555
|
+
getLastDreamResult() {
|
|
67556
|
+
return this.lastDreamResult;
|
|
67557
|
+
}
|
|
67558
|
+
// ==========================================================================
|
|
67559
|
+
// Private: Dream Execution
|
|
67560
|
+
// ==========================================================================
|
|
67561
|
+
/**
|
|
67562
|
+
* Execute a dream cycle with the specified duration.
|
|
67563
|
+
*/
|
|
67564
|
+
async executeDream(durationMs) {
|
|
67565
|
+
if (this.dreaming) {
|
|
67566
|
+
throw new Error("A dream is already in progress");
|
|
67567
|
+
}
|
|
67568
|
+
this.dreaming = true;
|
|
67569
|
+
console.log(`[DreamScheduler] Starting dream cycle (${durationMs}ms)`);
|
|
64448
67570
|
try {
|
|
64449
|
-
const
|
|
64450
|
-
|
|
64451
|
-
|
|
64452
|
-
|
|
64453
|
-
|
|
64454
|
-
|
|
64455
|
-
|
|
64456
|
-
|
|
64457
|
-
|
|
67571
|
+
const result = await this.dreamEngine.dream(durationMs);
|
|
67572
|
+
this.lastDreamTime = /* @__PURE__ */ new Date();
|
|
67573
|
+
this.lastDreamResult = result;
|
|
67574
|
+
this.totalDreamsCompleted++;
|
|
67575
|
+
this.clearExperienceBuffer();
|
|
67576
|
+
if (this.config.autoApplyHighConfidenceInsights) {
|
|
67577
|
+
await this.autoApplyInsights(result);
|
|
67578
|
+
}
|
|
67579
|
+
await this.publishDreamCompletedEvent(result);
|
|
67580
|
+
if (this.running) {
|
|
67581
|
+
this.scheduleNextDream();
|
|
67582
|
+
}
|
|
67583
|
+
console.log(
|
|
67584
|
+
`[DreamScheduler] Dream completed: ${result.insights.length} insights generated`
|
|
64458
67585
|
);
|
|
64459
|
-
return
|
|
64460
|
-
}
|
|
64461
|
-
|
|
67586
|
+
return result;
|
|
67587
|
+
} finally {
|
|
67588
|
+
this.dreaming = false;
|
|
64462
67589
|
}
|
|
64463
67590
|
}
|
|
64464
67591
|
/**
|
|
64465
|
-
*
|
|
67592
|
+
* Auto-apply insights that meet the confidence threshold.
|
|
64466
67593
|
*/
|
|
64467
|
-
async
|
|
64468
|
-
|
|
64469
|
-
|
|
64470
|
-
|
|
64471
|
-
|
|
64472
|
-
|
|
64473
|
-
|
|
64474
|
-
|
|
67594
|
+
async autoApplyInsights(result) {
|
|
67595
|
+
const highConfidenceInsights = result.insights.filter(
|
|
67596
|
+
(insight) => insight.actionable && insight.confidenceScore >= this.config.insightConfidenceThreshold
|
|
67597
|
+
);
|
|
67598
|
+
for (const insight of highConfidenceInsights) {
|
|
67599
|
+
try {
|
|
67600
|
+
const applyResult = await this.dreamEngine.applyInsight(insight.id);
|
|
67601
|
+
if (applyResult.success) {
|
|
67602
|
+
console.log(
|
|
67603
|
+
`[DreamScheduler] Auto-applied insight ${insight.id}: ${applyResult.patternId}`
|
|
67604
|
+
);
|
|
64475
67605
|
}
|
|
67606
|
+
} catch (err3) {
|
|
67607
|
+
console.error(`[DreamScheduler] Failed to auto-apply insight ${insight.id}:`, err3);
|
|
64476
67608
|
}
|
|
64477
|
-
milestones.sort((a, b) => b.achievedAt.getTime() - a.achievedAt.getTime());
|
|
64478
|
-
return ok(milestones.slice(0, limit));
|
|
64479
|
-
} catch (error) {
|
|
64480
|
-
return err(error instanceof Error ? error : new Error(String(error)));
|
|
64481
67609
|
}
|
|
64482
67610
|
}
|
|
64483
|
-
//
|
|
64484
|
-
// Private
|
|
64485
|
-
//
|
|
64486
|
-
|
|
64487
|
-
|
|
64488
|
-
|
|
64489
|
-
|
|
64490
|
-
|
|
64491
|
-
|
|
64492
|
-
|
|
67611
|
+
// ==========================================================================
|
|
67612
|
+
// Private: Scheduling
|
|
67613
|
+
// ==========================================================================
|
|
67614
|
+
/**
|
|
67615
|
+
* Schedule the next automatic dream.
|
|
67616
|
+
*/
|
|
67617
|
+
scheduleNextDream() {
|
|
67618
|
+
this.clearScheduledDream();
|
|
67619
|
+
if (!this.running) return;
|
|
67620
|
+
const nextDreamDelay = this.calculateNextDreamDelay();
|
|
67621
|
+
this.scheduledDreamTimer = setTimeout(async () => {
|
|
67622
|
+
if (!this.running || this.dreaming) return;
|
|
67623
|
+
try {
|
|
67624
|
+
await this.executeDream(this.config.defaultDreamDurationMs);
|
|
67625
|
+
} catch (err3) {
|
|
67626
|
+
console.error("[DreamScheduler] Scheduled dream failed:", err3);
|
|
67627
|
+
if (this.running) {
|
|
67628
|
+
this.scheduleNextDream();
|
|
67629
|
+
}
|
|
64493
67630
|
}
|
|
67631
|
+
}, nextDreamDelay);
|
|
67632
|
+
console.log(
|
|
67633
|
+
`[DreamScheduler] Next dream scheduled in ${Math.ceil(nextDreamDelay / 1e3)}s`
|
|
64494
67634
|
);
|
|
64495
67635
|
}
|
|
64496
|
-
|
|
64497
|
-
|
|
64498
|
-
|
|
64499
|
-
|
|
64500
|
-
|
|
64501
|
-
|
|
64502
|
-
|
|
64503
|
-
`production:incident:index:severity:${incident.severity}:${incident.id}`,
|
|
64504
|
-
incident.id,
|
|
64505
|
-
{ namespace: "learning-optimization", persist: true }
|
|
64506
|
-
);
|
|
64507
|
-
}
|
|
64508
|
-
async checkForAnomalies(metric) {
|
|
64509
|
-
const timeRange = TimeRange.lastNDays(7);
|
|
64510
|
-
const historyResult = await this.getMetricsHistory(
|
|
64511
|
-
metric.name,
|
|
64512
|
-
timeRange,
|
|
64513
|
-
metric.domain
|
|
64514
|
-
);
|
|
64515
|
-
if (!historyResult.success || historyResult.value.length < 10) {
|
|
64516
|
-
return;
|
|
67636
|
+
/**
|
|
67637
|
+
* Clear any scheduled dream timer.
|
|
67638
|
+
*/
|
|
67639
|
+
clearScheduledDream() {
|
|
67640
|
+
if (this.scheduledDreamTimer) {
|
|
67641
|
+
clearTimeout(this.scheduledDreamTimer);
|
|
67642
|
+
this.scheduledDreamTimer = null;
|
|
64517
67643
|
}
|
|
64518
|
-
|
|
64519
|
-
|
|
64520
|
-
|
|
64521
|
-
|
|
64522
|
-
|
|
64523
|
-
|
|
64524
|
-
|
|
64525
|
-
await this.memory.set(
|
|
64526
|
-
`production:anomaly:${uuidv441()}`,
|
|
64527
|
-
{
|
|
64528
|
-
metricId: metric.id,
|
|
64529
|
-
metricName: metric.name,
|
|
64530
|
-
value: metric.value,
|
|
64531
|
-
mean,
|
|
64532
|
-
stdDev,
|
|
64533
|
-
deviation,
|
|
64534
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
64535
|
-
},
|
|
64536
|
-
{ namespace: "learning-optimization", ttl: 86400 * 7 }
|
|
64537
|
-
);
|
|
67644
|
+
}
|
|
67645
|
+
/**
|
|
67646
|
+
* Calculate delay until next scheduled dream.
|
|
67647
|
+
*/
|
|
67648
|
+
calculateNextDreamDelay() {
|
|
67649
|
+
if (!this.lastDreamTime) {
|
|
67650
|
+
return this.config.autoScheduleIntervalMs;
|
|
64538
67651
|
}
|
|
67652
|
+
const timeSinceLastDream = Date.now() - this.lastDreamTime.getTime();
|
|
67653
|
+
const remainingTime = this.config.autoScheduleIntervalMs - timeSinceLastDream;
|
|
67654
|
+
return Math.max(remainingTime, this.config.minTimeBetweenDreamsMs);
|
|
64539
67655
|
}
|
|
64540
|
-
|
|
64541
|
-
|
|
64542
|
-
|
|
64543
|
-
|
|
64544
|
-
|
|
64545
|
-
domain: incident.domain
|
|
64546
|
-
},
|
|
64547
|
-
metrics: incident.metrics
|
|
64548
|
-
};
|
|
64549
|
-
const result = {
|
|
64550
|
-
success: false,
|
|
64551
|
-
outcome: incident.metrics,
|
|
64552
|
-
duration: 0
|
|
64553
|
-
};
|
|
64554
|
-
const experience = {
|
|
64555
|
-
id: uuidv441(),
|
|
64556
|
-
agentId: {
|
|
64557
|
-
value: "production-intel",
|
|
64558
|
-
domain: "learning-optimization",
|
|
64559
|
-
type: "analyzer"
|
|
64560
|
-
},
|
|
64561
|
-
domain: incident.domain,
|
|
64562
|
-
action: `incident-${incident.severity}`,
|
|
64563
|
-
state: state2,
|
|
64564
|
-
result,
|
|
64565
|
-
reward: this.calculateIncidentReward(incident),
|
|
64566
|
-
timestamp: incident.startedAt
|
|
64567
|
-
};
|
|
64568
|
-
await this.memory.set(
|
|
64569
|
-
`learning:experience:${experience.id}`,
|
|
64570
|
-
experience,
|
|
64571
|
-
{ namespace: "learning-optimization", ttl: 86400 * 30 }
|
|
64572
|
-
);
|
|
67656
|
+
/**
|
|
67657
|
+
* Get time until the currently scheduled dream.
|
|
67658
|
+
*/
|
|
67659
|
+
getTimeUntilScheduledDream() {
|
|
67660
|
+
return this.calculateNextDreamDelay();
|
|
64573
67661
|
}
|
|
64574
|
-
|
|
64575
|
-
|
|
64576
|
-
|
|
64577
|
-
|
|
64578
|
-
|
|
64579
|
-
|
|
64580
|
-
|
|
64581
|
-
|
|
64582
|
-
|
|
64583
|
-
|
|
64584
|
-
const duration = incident.resolvedAt.getTime() - incident.startedAt.getTime();
|
|
64585
|
-
const result = {
|
|
64586
|
-
success: true,
|
|
64587
|
-
outcome: {
|
|
64588
|
-
...incident.metrics,
|
|
64589
|
-
resolution_time_ms: duration
|
|
64590
|
-
},
|
|
64591
|
-
duration
|
|
64592
|
-
};
|
|
64593
|
-
const experience = {
|
|
64594
|
-
id: uuidv441(),
|
|
64595
|
-
agentId: {
|
|
64596
|
-
value: "production-intel",
|
|
64597
|
-
domain: "learning-optimization",
|
|
64598
|
-
type: "analyzer"
|
|
64599
|
-
},
|
|
64600
|
-
domain: incident.domain,
|
|
64601
|
-
action: `resolution-${incident.severity}`,
|
|
64602
|
-
state: state2,
|
|
64603
|
-
result,
|
|
64604
|
-
reward: 1 - this.calculateIncidentReward(incident),
|
|
64605
|
-
// Inverse - resolution is good
|
|
64606
|
-
timestamp: incident.resolvedAt
|
|
64607
|
-
};
|
|
64608
|
-
await this.memory.set(
|
|
64609
|
-
`learning:experience:${experience.id}`,
|
|
64610
|
-
experience,
|
|
64611
|
-
{ namespace: "learning-optimization", ttl: 86400 * 30 }
|
|
64612
|
-
);
|
|
67662
|
+
// ==========================================================================
|
|
67663
|
+
// Private: Dream Timing Checks
|
|
67664
|
+
// ==========================================================================
|
|
67665
|
+
/**
|
|
67666
|
+
* Check if enough time has passed since the last dream.
|
|
67667
|
+
*/
|
|
67668
|
+
canDream() {
|
|
67669
|
+
if (!this.lastDreamTime) return true;
|
|
67670
|
+
const timeSinceLastDream = Date.now() - this.lastDreamTime.getTime();
|
|
67671
|
+
return timeSinceLastDream >= this.config.minTimeBetweenDreamsMs;
|
|
64613
67672
|
}
|
|
64614
|
-
|
|
64615
|
-
|
|
64616
|
-
|
|
64617
|
-
|
|
64618
|
-
|
|
64619
|
-
|
|
64620
|
-
|
|
64621
|
-
return -(severityScores[incident.severity] || 0.5);
|
|
67673
|
+
/**
|
|
67674
|
+
* Get time until we can start a dream.
|
|
67675
|
+
*/
|
|
67676
|
+
getTimeUntilCanDream() {
|
|
67677
|
+
if (!this.lastDreamTime) return 0;
|
|
67678
|
+
const timeSinceLastDream = Date.now() - this.lastDreamTime.getTime();
|
|
67679
|
+
return Math.max(0, this.config.minTimeBetweenDreamsMs - timeSinceLastDream);
|
|
64622
67680
|
}
|
|
64623
|
-
|
|
64624
|
-
|
|
64625
|
-
|
|
64626
|
-
|
|
64627
|
-
|
|
64628
|
-
|
|
64629
|
-
|
|
64630
|
-
|
|
64631
|
-
|
|
64632
|
-
|
|
64633
|
-
|
|
64634
|
-
|
|
64635
|
-
|
|
64636
|
-
|
|
64637
|
-
|
|
67681
|
+
// ==========================================================================
|
|
67682
|
+
// Private: Event Handlers
|
|
67683
|
+
// ==========================================================================
|
|
67684
|
+
/**
|
|
67685
|
+
* Handle quality gate completion events.
|
|
67686
|
+
* Triggers a dream when a gate fails to analyze what went wrong.
|
|
67687
|
+
*/
|
|
67688
|
+
async handleQualityGateEvent(event) {
|
|
67689
|
+
if (event.payload.passed) return;
|
|
67690
|
+
if (!this.canDream() || this.dreaming) {
|
|
67691
|
+
console.log(
|
|
67692
|
+
"[DreamScheduler] Quality gate failed but cannot start dream yet"
|
|
67693
|
+
);
|
|
67694
|
+
return;
|
|
67695
|
+
}
|
|
67696
|
+
console.log("[DreamScheduler] Quality gate failed, triggering analysis dream");
|
|
67697
|
+
try {
|
|
67698
|
+
await this.executeDream(this.config.quickDreamDurationMs);
|
|
67699
|
+
} catch (err3) {
|
|
67700
|
+
console.error("[DreamScheduler] Quality gate triggered dream failed:", err3);
|
|
64638
67701
|
}
|
|
64639
|
-
return count > 0 ? totalReward / count : 0.8;
|
|
64640
67702
|
}
|
|
64641
|
-
|
|
64642
|
-
|
|
64643
|
-
|
|
64644
|
-
|
|
64645
|
-
|
|
64646
|
-
|
|
64647
|
-
|
|
67703
|
+
/**
|
|
67704
|
+
* Handle domain milestone events.
|
|
67705
|
+
* Triggers a dream to consolidate learnings after significant progress.
|
|
67706
|
+
*/
|
|
67707
|
+
async handleDomainMilestoneEvent(event) {
|
|
67708
|
+
if (!this.canDream() || this.dreaming) {
|
|
67709
|
+
console.log("[DreamScheduler] Milestone reached but cannot start dream yet");
|
|
67710
|
+
return;
|
|
64648
67711
|
}
|
|
64649
|
-
|
|
64650
|
-
|
|
64651
|
-
|
|
64652
|
-
|
|
64653
|
-
|
|
64654
|
-
recommendations.push(`${name} is declining. Review recent changes.`);
|
|
64655
|
-
}
|
|
67712
|
+
console.log("[DreamScheduler] Domain milestone reached, triggering consolidation dream");
|
|
67713
|
+
try {
|
|
67714
|
+
await this.executeDream(this.config.defaultDreamDurationMs);
|
|
67715
|
+
} catch (err3) {
|
|
67716
|
+
console.error("[DreamScheduler] Milestone triggered dream failed:", err3);
|
|
64656
67717
|
}
|
|
64657
|
-
|
|
64658
|
-
|
|
64659
|
-
|
|
64660
|
-
|
|
64661
|
-
|
|
64662
|
-
|
|
64663
|
-
|
|
64664
|
-
|
|
64665
|
-
|
|
64666
|
-
|
|
64667
|
-
|
|
64668
|
-
|
|
64669
|
-
|
|
67718
|
+
}
|
|
67719
|
+
// ==========================================================================
|
|
67720
|
+
// Private: Event Publishing
|
|
67721
|
+
// ==========================================================================
|
|
67722
|
+
/**
|
|
67723
|
+
* Publish a dream completed event.
|
|
67724
|
+
*/
|
|
67725
|
+
async publishDreamCompletedEvent(result) {
|
|
67726
|
+
try {
|
|
67727
|
+
await this.eventBus.publish({
|
|
67728
|
+
id: uuidv444(),
|
|
67729
|
+
type: "learning-optimization:dream:completed",
|
|
67730
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
67731
|
+
source: "learning-optimization",
|
|
67732
|
+
payload: {
|
|
67733
|
+
cycleId: result.cycle.id,
|
|
67734
|
+
insightsGenerated: result.insights.length,
|
|
67735
|
+
patternsCreated: result.patternsCreated,
|
|
67736
|
+
duration: result.cycle.durationMs
|
|
64670
67737
|
}
|
|
64671
|
-
}
|
|
67738
|
+
});
|
|
67739
|
+
} catch (err3) {
|
|
67740
|
+
console.error("[DreamScheduler] Failed to publish dream completed event:", err3);
|
|
64672
67741
|
}
|
|
64673
|
-
return recommendations;
|
|
64674
67742
|
}
|
|
64675
|
-
|
|
64676
|
-
|
|
64677
|
-
|
|
64678
|
-
|
|
64679
|
-
|
|
64680
|
-
|
|
64681
|
-
|
|
64682
|
-
|
|
64683
|
-
|
|
64684
|
-
|
|
64685
|
-
|
|
64686
|
-
|
|
64687
|
-
|
|
64688
|
-
|
|
67743
|
+
// ==========================================================================
|
|
67744
|
+
// Private: State Persistence
|
|
67745
|
+
// ==========================================================================
|
|
67746
|
+
/**
|
|
67747
|
+
* Save scheduler state to memory backend.
|
|
67748
|
+
*/
|
|
67749
|
+
async saveState() {
|
|
67750
|
+
if (!this.memoryBackend) return;
|
|
67751
|
+
try {
|
|
67752
|
+
await this.memoryBackend.set(
|
|
67753
|
+
"dream-scheduler:state",
|
|
67754
|
+
{
|
|
67755
|
+
lastDreamTime: this.lastDreamTime?.toISOString() ?? null,
|
|
67756
|
+
totalDreamsCompleted: this.totalDreamsCompleted,
|
|
67757
|
+
experienceBuffer: this.experienceBuffer
|
|
67758
|
+
},
|
|
67759
|
+
{ namespace: "learning-optimization", persist: true }
|
|
64689
67760
|
);
|
|
64690
|
-
|
|
64691
|
-
|
|
64692
|
-
|
|
64693
|
-
|
|
64694
|
-
|
|
64695
|
-
|
|
64696
|
-
|
|
64697
|
-
|
|
64698
|
-
|
|
64699
|
-
|
|
67761
|
+
} catch (err3) {
|
|
67762
|
+
console.error("[DreamScheduler] Failed to save state:", err3);
|
|
67763
|
+
}
|
|
67764
|
+
}
|
|
67765
|
+
/**
|
|
67766
|
+
* Restore scheduler state from memory backend.
|
|
67767
|
+
*/
|
|
67768
|
+
async restoreState() {
|
|
67769
|
+
if (!this.memoryBackend) return;
|
|
67770
|
+
try {
|
|
67771
|
+
const state2 = await this.memoryBackend.get("dream-scheduler:state");
|
|
67772
|
+
if (state2) {
|
|
67773
|
+
this.lastDreamTime = state2.lastDreamTime ? new Date(state2.lastDreamTime) : null;
|
|
67774
|
+
this.totalDreamsCompleted = state2.totalDreamsCompleted ?? 0;
|
|
67775
|
+
this.experienceBuffer = state2.experienceBuffer ?? [];
|
|
67776
|
+
console.log(
|
|
67777
|
+
`[DreamScheduler] Restored state: ${this.totalDreamsCompleted} dreams, ${this.experienceBuffer.length} experiences`
|
|
67778
|
+
);
|
|
64700
67779
|
}
|
|
67780
|
+
} catch (err3) {
|
|
67781
|
+
console.error("[DreamScheduler] Failed to restore state:", err3);
|
|
64701
67782
|
}
|
|
64702
|
-
return anomalies;
|
|
64703
67783
|
}
|
|
64704
|
-
|
|
64705
|
-
|
|
64706
|
-
|
|
64707
|
-
|
|
64708
|
-
|
|
64709
|
-
|
|
64710
|
-
|
|
64711
|
-
if (
|
|
64712
|
-
|
|
64713
|
-
|
|
67784
|
+
// ==========================================================================
|
|
67785
|
+
// Private: Validation
|
|
67786
|
+
// ==========================================================================
|
|
67787
|
+
/**
|
|
67788
|
+
* Ensure the scheduler is initialized.
|
|
67789
|
+
*/
|
|
67790
|
+
ensureInitialized() {
|
|
67791
|
+
if (!this.initialized) {
|
|
67792
|
+
throw new Error("DreamScheduler not initialized. Call initialize() first.");
|
|
67793
|
+
}
|
|
64714
67794
|
}
|
|
64715
67795
|
};
|
|
67796
|
+
function createDreamScheduler(dependencies, config) {
|
|
67797
|
+
return new DreamScheduler(dependencies, config);
|
|
67798
|
+
}
|
|
64716
67799
|
|
|
64717
67800
|
// src/domains/learning-optimization/coordinator.ts
|
|
64718
67801
|
var DEFAULT_CONFIG48 = {
|
|
@@ -64721,8 +67804,17 @@ var DEFAULT_CONFIG48 = {
|
|
|
64721
67804
|
// 2 minutes
|
|
64722
67805
|
enableAutoOptimization: true,
|
|
64723
67806
|
publishEvents: true,
|
|
64724
|
-
learningCycleIntervalMs: 36e5
|
|
67807
|
+
learningCycleIntervalMs: 36e5,
|
|
67808
|
+
// 1 hour
|
|
67809
|
+
// Dream Scheduler defaults
|
|
67810
|
+
enableDreamScheduler: true,
|
|
67811
|
+
dreamCycleIntervalMs: 36e5,
|
|
64725
67812
|
// 1 hour
|
|
67813
|
+
enableExperienceTrigger: true,
|
|
67814
|
+
experienceThreshold: 50,
|
|
67815
|
+
enableQualityGateFailureTrigger: true,
|
|
67816
|
+
autoApplyHighConfidenceInsights: false,
|
|
67817
|
+
autoApplyConfidenceThreshold: 0.8
|
|
64726
67818
|
};
|
|
64727
67819
|
var LearningOptimizationCoordinator = class {
|
|
64728
67820
|
constructor(eventBus, memory, agentCoordinator, config = {}) {
|
|
@@ -64748,6 +67840,11 @@ var LearningOptimizationCoordinator = class {
|
|
|
64748
67840
|
* Now uses PersistentSONAEngine to survive restarts
|
|
64749
67841
|
*/
|
|
64750
67842
|
sona;
|
|
67843
|
+
/**
|
|
67844
|
+
* DreamScheduler for offline pattern consolidation and insight generation
|
|
67845
|
+
* Wraps DreamEngine with automatic scheduling and trigger support
|
|
67846
|
+
*/
|
|
67847
|
+
dreamScheduler = null;
|
|
64751
67848
|
/**
|
|
64752
67849
|
* Initialize the coordinator.
|
|
64753
67850
|
* Throws if QESONA fails to initialize.
|
|
@@ -64767,6 +67864,32 @@ var LearningOptimizationCoordinator = class {
|
|
|
64767
67864
|
console.error("[LearningOptimizationCoordinator] Failed to initialize PersistentSONAEngine:", error);
|
|
64768
67865
|
throw error;
|
|
64769
67866
|
}
|
|
67867
|
+
if (this.config.enableDreamScheduler) {
|
|
67868
|
+
try {
|
|
67869
|
+
const dreamEngine = await createDreamEngine();
|
|
67870
|
+
await dreamEngine.initialize();
|
|
67871
|
+
this.dreamScheduler = createDreamScheduler(
|
|
67872
|
+
{
|
|
67873
|
+
dreamEngine,
|
|
67874
|
+
eventBus: this.eventBus,
|
|
67875
|
+
memoryBackend: this.memory
|
|
67876
|
+
},
|
|
67877
|
+
{
|
|
67878
|
+
autoScheduleIntervalMs: this.config.dreamCycleIntervalMs,
|
|
67879
|
+
enableExperienceTrigger: this.config.enableExperienceTrigger,
|
|
67880
|
+
experienceThreshold: this.config.experienceThreshold,
|
|
67881
|
+
enableQualityGateFailureTrigger: this.config.enableQualityGateFailureTrigger,
|
|
67882
|
+
autoApplyHighConfidenceInsights: this.config.autoApplyHighConfidenceInsights,
|
|
67883
|
+
insightConfidenceThreshold: this.config.autoApplyConfidenceThreshold
|
|
67884
|
+
}
|
|
67885
|
+
);
|
|
67886
|
+
await this.dreamScheduler.initialize();
|
|
67887
|
+
this.dreamScheduler.start();
|
|
67888
|
+
console.log("[LearningOptimizationCoordinator] DreamScheduler initialized and started");
|
|
67889
|
+
} catch (error) {
|
|
67890
|
+
console.warn("[LearningOptimizationCoordinator] Failed to initialize DreamScheduler:", error);
|
|
67891
|
+
}
|
|
67892
|
+
}
|
|
64770
67893
|
this.subscribeToEvents();
|
|
64771
67894
|
await this.loadWorkflowState();
|
|
64772
67895
|
this.initialized = true;
|
|
@@ -64777,6 +67900,15 @@ var LearningOptimizationCoordinator = class {
|
|
|
64777
67900
|
async dispose() {
|
|
64778
67901
|
await this.saveWorkflowState();
|
|
64779
67902
|
this.workflows.clear();
|
|
67903
|
+
if (this.dreamScheduler) {
|
|
67904
|
+
try {
|
|
67905
|
+
await this.dreamScheduler.dispose();
|
|
67906
|
+
console.log("[LearningOptimizationCoordinator] DreamScheduler disposed");
|
|
67907
|
+
} catch (error) {
|
|
67908
|
+
console.error("[LearningOptimizationCoordinator] Error disposing DreamScheduler:", error);
|
|
67909
|
+
}
|
|
67910
|
+
this.dreamScheduler = null;
|
|
67911
|
+
}
|
|
64780
67912
|
if (this.initialized && this.sona) {
|
|
64781
67913
|
try {
|
|
64782
67914
|
await this.sona.close();
|
|
@@ -64801,7 +67933,7 @@ var LearningOptimizationCoordinator = class {
|
|
|
64801
67933
|
* Run a learning cycle for a specific domain
|
|
64802
67934
|
*/
|
|
64803
67935
|
async runLearningCycle(domain) {
|
|
64804
|
-
const workflowId =
|
|
67936
|
+
const workflowId = uuidv445();
|
|
64805
67937
|
try {
|
|
64806
67938
|
this.startWorkflow(workflowId, "learning-cycle");
|
|
64807
67939
|
const agentResult = await this.spawnLearningAgent(workflowId, domain);
|
|
@@ -64885,7 +68017,7 @@ var LearningOptimizationCoordinator = class {
|
|
|
64885
68017
|
* Optimize all domain strategies
|
|
64886
68018
|
*/
|
|
64887
68019
|
async optimizeAllStrategies() {
|
|
64888
|
-
const workflowId =
|
|
68020
|
+
const workflowId = uuidv445();
|
|
64889
68021
|
try {
|
|
64890
68022
|
this.startWorkflow(workflowId, "optimization");
|
|
64891
68023
|
const byDomain = {};
|
|
@@ -64953,7 +68085,7 @@ var LearningOptimizationCoordinator = class {
|
|
|
64953
68085
|
* Share learnings across domains
|
|
64954
68086
|
*/
|
|
64955
68087
|
async shareCrossDomainLearnings() {
|
|
64956
|
-
const workflowId =
|
|
68088
|
+
const workflowId = uuidv445();
|
|
64957
68089
|
try {
|
|
64958
68090
|
this.startWorkflow(workflowId, "transfer");
|
|
64959
68091
|
let knowledgeShared = 0;
|
|
@@ -65219,11 +68351,95 @@ var LearningOptimizationCoordinator = class {
|
|
|
65219
68351
|
this.ensureInitialized();
|
|
65220
68352
|
return this.sona.verifyPerformance(iterations);
|
|
65221
68353
|
}
|
|
68354
|
+
// ============================================================================
|
|
68355
|
+
// Dream Scheduler Methods
|
|
68356
|
+
// ============================================================================
|
|
68357
|
+
/**
|
|
68358
|
+
* Trigger a dream cycle manually.
|
|
68359
|
+
* Dreams consolidate patterns and generate novel insights through spreading activation.
|
|
68360
|
+
*
|
|
68361
|
+
* @param durationMs - Optional duration override in ms
|
|
68362
|
+
* @returns Dream cycle result with generated insights
|
|
68363
|
+
* @throws Error if DreamScheduler is not initialized
|
|
68364
|
+
*/
|
|
68365
|
+
async triggerDreamCycle(durationMs) {
|
|
68366
|
+
if (!this.dreamScheduler) {
|
|
68367
|
+
throw new Error("[LearningOptimizationCoordinator] DreamScheduler not initialized");
|
|
68368
|
+
}
|
|
68369
|
+
const result = await this.dreamScheduler.triggerDream(durationMs);
|
|
68370
|
+
if (this.config.publishEvents) {
|
|
68371
|
+
await this.publishDreamCycleCompleted(
|
|
68372
|
+
result.cycle.id,
|
|
68373
|
+
result.cycle.durationMs ?? 0,
|
|
68374
|
+
result.cycle.conceptsProcessed,
|
|
68375
|
+
result.insights.map((i) => ({
|
|
68376
|
+
id: i.id,
|
|
68377
|
+
type: i.type,
|
|
68378
|
+
description: i.description,
|
|
68379
|
+
noveltyScore: i.noveltyScore,
|
|
68380
|
+
confidenceScore: i.confidenceScore,
|
|
68381
|
+
actionable: i.actionable,
|
|
68382
|
+
suggestedAction: i.suggestedAction,
|
|
68383
|
+
sourceConcepts: i.sourceConcepts
|
|
68384
|
+
})),
|
|
68385
|
+
result.patternsCreated
|
|
68386
|
+
);
|
|
68387
|
+
}
|
|
68388
|
+
return result;
|
|
68389
|
+
}
|
|
68390
|
+
/**
|
|
68391
|
+
* Get the current status of the DreamScheduler.
|
|
68392
|
+
*
|
|
68393
|
+
* @returns DreamScheduler status or null if not initialized
|
|
68394
|
+
*/
|
|
68395
|
+
getDreamStatus() {
|
|
68396
|
+
return this.dreamScheduler?.getStatus() ?? null;
|
|
68397
|
+
}
|
|
68398
|
+
/**
|
|
68399
|
+
* Check if the DreamScheduler is available and running.
|
|
68400
|
+
*
|
|
68401
|
+
* @returns True if DreamScheduler is initialized
|
|
68402
|
+
*/
|
|
68403
|
+
isDreamSchedulerAvailable() {
|
|
68404
|
+
return this.dreamScheduler !== null;
|
|
68405
|
+
}
|
|
68406
|
+
/**
|
|
68407
|
+
* Get the last dream cycle result from the scheduler.
|
|
68408
|
+
*
|
|
68409
|
+
* @returns Last dream result or null if no dreams have completed
|
|
68410
|
+
*/
|
|
68411
|
+
getLastDreamResult() {
|
|
68412
|
+
return this.dreamScheduler?.getLastDreamResult() ?? null;
|
|
68413
|
+
}
|
|
68414
|
+
/**
|
|
68415
|
+
* Trigger a quick dream cycle for rapid insight generation.
|
|
68416
|
+
*
|
|
68417
|
+
* @returns Dream cycle result
|
|
68418
|
+
* @throws Error if DreamScheduler is not initialized
|
|
68419
|
+
*/
|
|
68420
|
+
async triggerQuickDream() {
|
|
68421
|
+
if (!this.dreamScheduler) {
|
|
68422
|
+
throw new Error("[LearningOptimizationCoordinator] DreamScheduler not initialized");
|
|
68423
|
+
}
|
|
68424
|
+
return this.dreamScheduler.triggerQuickDream();
|
|
68425
|
+
}
|
|
68426
|
+
/**
|
|
68427
|
+
* Trigger a full dream cycle for comprehensive pattern consolidation.
|
|
68428
|
+
*
|
|
68429
|
+
* @returns Dream cycle result
|
|
68430
|
+
* @throws Error if DreamScheduler is not initialized
|
|
68431
|
+
*/
|
|
68432
|
+
async triggerFullDream() {
|
|
68433
|
+
if (!this.dreamScheduler) {
|
|
68434
|
+
throw new Error("[LearningOptimizationCoordinator] DreamScheduler not initialized");
|
|
68435
|
+
}
|
|
68436
|
+
return this.dreamScheduler.triggerFullDream();
|
|
68437
|
+
}
|
|
65222
68438
|
/**
|
|
65223
68439
|
* Export learned models
|
|
65224
68440
|
*/
|
|
65225
68441
|
async exportModels(domains) {
|
|
65226
|
-
const workflowId =
|
|
68442
|
+
const workflowId = uuidv445();
|
|
65227
68443
|
try {
|
|
65228
68444
|
this.startWorkflow(workflowId, "export");
|
|
65229
68445
|
const targetDomains = domains || ALL_DOMAINS;
|
|
@@ -65288,7 +68504,7 @@ var LearningOptimizationCoordinator = class {
|
|
|
65288
68504
|
* Import learned models
|
|
65289
68505
|
*/
|
|
65290
68506
|
async importModels(modelExport) {
|
|
65291
|
-
const workflowId =
|
|
68507
|
+
const workflowId = uuidv445();
|
|
65292
68508
|
try {
|
|
65293
68509
|
this.startWorkflow(workflowId, "import");
|
|
65294
68510
|
const calculatedChecksum = this.calculateChecksum(
|
|
@@ -65597,6 +68813,22 @@ var LearningOptimizationCoordinator = class {
|
|
|
65597
68813
|
`[LearningOptimizationCoordinator] Experience ${experience.id} transferred to ${relatedDomains.length} related domains`
|
|
65598
68814
|
);
|
|
65599
68815
|
}
|
|
68816
|
+
if (this.dreamScheduler) {
|
|
68817
|
+
this.dreamScheduler.recordExperience({
|
|
68818
|
+
id: experience.id,
|
|
68819
|
+
agentType: experience.agent || "unknown",
|
|
68820
|
+
domain,
|
|
68821
|
+
taskType: experience.task,
|
|
68822
|
+
success: experience.success,
|
|
68823
|
+
duration: experience.durationMs,
|
|
68824
|
+
context: {
|
|
68825
|
+
quality: experience.quality,
|
|
68826
|
+
steps: experience.steps.length,
|
|
68827
|
+
patterns: experience.patterns?.length || 0
|
|
68828
|
+
},
|
|
68829
|
+
timestamp: new Date(experience.startedAt)
|
|
68830
|
+
});
|
|
68831
|
+
}
|
|
65600
68832
|
}
|
|
65601
68833
|
// ============================================================================
|
|
65602
68834
|
// Event Publishing
|
|
@@ -65639,6 +68871,39 @@ var LearningOptimizationCoordinator = class {
|
|
|
65639
68871
|
);
|
|
65640
68872
|
await this.eventBus.publish(event);
|
|
65641
68873
|
}
|
|
68874
|
+
/**
|
|
68875
|
+
* Publish a dream cycle completion event.
|
|
68876
|
+
* This broadcasts dream insights to all interested domain coordinators.
|
|
68877
|
+
*
|
|
68878
|
+
* Called by the DreamScheduler or DreamEngine after completing a dream cycle.
|
|
68879
|
+
*
|
|
68880
|
+
* @param cycleId - Unique identifier for the dream cycle
|
|
68881
|
+
* @param durationMs - How long the dream cycle took
|
|
68882
|
+
* @param conceptsProcessed - Number of concepts processed during dreaming
|
|
68883
|
+
* @param insights - Array of insights generated during the dream cycle
|
|
68884
|
+
* @param patternsCreated - Number of patterns created from insights
|
|
68885
|
+
*/
|
|
68886
|
+
async publishDreamCycleCompleted(cycleId, durationMs, conceptsProcessed, insights, patternsCreated) {
|
|
68887
|
+
if (!this.config.publishEvents) {
|
|
68888
|
+
return;
|
|
68889
|
+
}
|
|
68890
|
+
const payload = {
|
|
68891
|
+
cycleId,
|
|
68892
|
+
durationMs,
|
|
68893
|
+
conceptsProcessed,
|
|
68894
|
+
insights,
|
|
68895
|
+
patternsCreated
|
|
68896
|
+
};
|
|
68897
|
+
const event = createEvent(
|
|
68898
|
+
LearningOptimizationEvents.DreamCycleCompleted,
|
|
68899
|
+
"learning-optimization",
|
|
68900
|
+
payload
|
|
68901
|
+
);
|
|
68902
|
+
await this.eventBus.publish(event);
|
|
68903
|
+
console.log(
|
|
68904
|
+
`[LearningOptimizationCoordinator] Published dream cycle completion: ${insights.length} insights for ${conceptsProcessed} concepts`
|
|
68905
|
+
);
|
|
68906
|
+
}
|
|
65642
68907
|
// ============================================================================
|
|
65643
68908
|
// Agent Management
|
|
65644
68909
|
// ============================================================================
|
|
@@ -66373,7 +69638,7 @@ init_types();
|
|
|
66373
69638
|
|
|
66374
69639
|
// src/coordination/workflow-orchestrator.ts
|
|
66375
69640
|
init_types();
|
|
66376
|
-
import { v4 as
|
|
69641
|
+
import { v4 as uuidv446 } from "uuid";
|
|
66377
69642
|
var WorkflowEvents = {
|
|
66378
69643
|
WorkflowStarted: "workflow.WorkflowStarted",
|
|
66379
69644
|
WorkflowCompleted: "workflow.WorkflowCompleted",
|
|
@@ -66487,7 +69752,7 @@ var WorkflowOrchestrator = class {
|
|
|
66487
69752
|
)
|
|
66488
69753
|
);
|
|
66489
69754
|
}
|
|
66490
|
-
const executionId =
|
|
69755
|
+
const executionId = uuidv446();
|
|
66491
69756
|
const startedAt = /* @__PURE__ */ new Date();
|
|
66492
69757
|
const context2 = {
|
|
66493
69758
|
input,
|
|
@@ -67999,7 +71264,7 @@ var QEKernelImpl = class {
|
|
|
67999
71264
|
|
|
68000
71265
|
// src/coordination/queen-coordinator.ts
|
|
68001
71266
|
init_types();
|
|
68002
|
-
import { v4 as
|
|
71267
|
+
import { v4 as uuidv450 } from "uuid";
|
|
68003
71268
|
|
|
68004
71269
|
// src/shared/utils/circular-buffer.ts
|
|
68005
71270
|
var CircularBuffer = class {
|
|
@@ -68210,7 +71475,7 @@ function createTaskAuditLogger(config) {
|
|
|
68210
71475
|
|
|
68211
71476
|
// src/coordination/mincut/queen-integration.ts
|
|
68212
71477
|
init_types();
|
|
68213
|
-
import { v4 as
|
|
71478
|
+
import { v4 as uuidv449 } from "uuid";
|
|
68214
71479
|
|
|
68215
71480
|
// src/coordination/mincut/swarm-graph.ts
|
|
68216
71481
|
var SwarmGraph = class _SwarmGraph {
|
|
@@ -68583,7 +71848,7 @@ function createSwarmGraph() {
|
|
|
68583
71848
|
}
|
|
68584
71849
|
|
|
68585
71850
|
// src/coordination/mincut/mincut-health-monitor.ts
|
|
68586
|
-
import { v4 as
|
|
71851
|
+
import { v4 as uuidv447 } from "uuid";
|
|
68587
71852
|
|
|
68588
71853
|
// src/coordination/mincut/mincut-calculator.ts
|
|
68589
71854
|
var MinCutCalculator = class {
|
|
@@ -69217,7 +72482,7 @@ var MinCutHealthMonitor = class {
|
|
|
69217
72482
|
return;
|
|
69218
72483
|
}
|
|
69219
72484
|
const alert = {
|
|
69220
|
-
id:
|
|
72485
|
+
id: uuidv447(),
|
|
69221
72486
|
severity,
|
|
69222
72487
|
message,
|
|
69223
72488
|
minCutValue,
|
|
@@ -69237,11 +72502,11 @@ var MinCutHealthMonitor = class {
|
|
|
69237
72502
|
emitEvent(type, minCutValue, payload) {
|
|
69238
72503
|
if (!this.eventBus) return;
|
|
69239
72504
|
const event = {
|
|
69240
|
-
id:
|
|
72505
|
+
id: uuidv447(),
|
|
69241
72506
|
type,
|
|
69242
72507
|
source: "coordination",
|
|
69243
72508
|
timestamp: /* @__PURE__ */ new Date(),
|
|
69244
|
-
correlationId:
|
|
72509
|
+
correlationId: uuidv447(),
|
|
69245
72510
|
payload: {
|
|
69246
72511
|
minCutValue,
|
|
69247
72512
|
...payload
|
|
@@ -69257,7 +72522,7 @@ function createMinCutHealthMonitor(graph, config, eventBus) {
|
|
|
69257
72522
|
}
|
|
69258
72523
|
|
|
69259
72524
|
// src/coordination/mincut/mincut-persistence.ts
|
|
69260
|
-
import { v4 as
|
|
72525
|
+
import { v4 as uuidv448 } from "uuid";
|
|
69261
72526
|
var MinCutPersistence = class {
|
|
69262
72527
|
memory;
|
|
69263
72528
|
initialized = false;
|
|
@@ -69282,7 +72547,7 @@ var MinCutPersistence = class {
|
|
|
69282
72547
|
*/
|
|
69283
72548
|
async saveSnapshot(snapshot) {
|
|
69284
72549
|
this.ensureInitialized();
|
|
69285
|
-
const id =
|
|
72550
|
+
const id = uuidv448();
|
|
69286
72551
|
const db = this.memory.getDatabase();
|
|
69287
72552
|
db.prepare(`
|
|
69288
72553
|
INSERT INTO mincut_snapshots (
|
|
@@ -69444,7 +72709,7 @@ var MinCutPersistence = class {
|
|
|
69444
72709
|
`);
|
|
69445
72710
|
const insertMany = db.transaction((vertices) => {
|
|
69446
72711
|
for (const weak of vertices) {
|
|
69447
|
-
const id =
|
|
72712
|
+
const id = uuidv448();
|
|
69448
72713
|
insert.run(
|
|
69449
72714
|
id,
|
|
69450
72715
|
weak.vertexId,
|
|
@@ -69571,7 +72836,7 @@ var MinCutPersistence = class {
|
|
|
69571
72836
|
*/
|
|
69572
72837
|
async recordHealingAction(result) {
|
|
69573
72838
|
this.ensureInitialized();
|
|
69574
|
-
const id =
|
|
72839
|
+
const id = uuidv448();
|
|
69575
72840
|
const db = this.memory.getDatabase();
|
|
69576
72841
|
db.prepare(`
|
|
69577
72842
|
INSERT INTO mincut_healing_actions (
|
|
@@ -69652,7 +72917,7 @@ var MinCutPersistence = class {
|
|
|
69652
72917
|
*/
|
|
69653
72918
|
async recordObservation(observation) {
|
|
69654
72919
|
this.ensureInitialized();
|
|
69655
|
-
const id =
|
|
72920
|
+
const id = uuidv448();
|
|
69656
72921
|
const db = this.memory.getDatabase();
|
|
69657
72922
|
let actualVsPredictedDiff = null;
|
|
69658
72923
|
if (observation.prediction) {
|
|
@@ -70233,7 +73498,7 @@ var QueenMinCutBridge = class {
|
|
|
70233
73498
|
// ==========================================================================
|
|
70234
73499
|
async reportHealthIssue(issue) {
|
|
70235
73500
|
await this.eventBus.publish({
|
|
70236
|
-
id:
|
|
73501
|
+
id: uuidv449(),
|
|
70237
73502
|
type: "MinCutHealthIssue",
|
|
70238
73503
|
source: "mincut-bridge",
|
|
70239
73504
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -71351,7 +74616,7 @@ var QueenCoordinator = class {
|
|
|
71351
74616
|
if (!this.initialized) {
|
|
71352
74617
|
return err(new Error("Queen Coordinator not initialized"));
|
|
71353
74618
|
}
|
|
71354
|
-
const taskId = `task_${
|
|
74619
|
+
const taskId = `task_${uuidv450()}`;
|
|
71355
74620
|
const task = {
|
|
71356
74621
|
...taskInput,
|
|
71357
74622
|
id: taskId,
|
|
@@ -71804,6 +75069,45 @@ var QueenCoordinator = class {
|
|
|
71804
75069
|
await this.processQueue();
|
|
71805
75070
|
}
|
|
71806
75071
|
}
|
|
75072
|
+
/**
|
|
75073
|
+
* Handle task completion callback from domain plugin
|
|
75074
|
+
* Queen-Domain Integration Fix: Direct task execution callback handler
|
|
75075
|
+
*/
|
|
75076
|
+
async handleTaskCompletion(result) {
|
|
75077
|
+
const execution = this.tasks.get(result.taskId);
|
|
75078
|
+
if (!execution) {
|
|
75079
|
+
console.warn(`[Queen] Received completion for unknown task: ${result.taskId}`);
|
|
75080
|
+
return;
|
|
75081
|
+
}
|
|
75082
|
+
const updated = {
|
|
75083
|
+
...execution,
|
|
75084
|
+
status: result.success ? "completed" : "failed",
|
|
75085
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
75086
|
+
result: result.data,
|
|
75087
|
+
error: result.error
|
|
75088
|
+
};
|
|
75089
|
+
this.tasks.set(result.taskId, updated);
|
|
75090
|
+
if (result.success) {
|
|
75091
|
+
this.tasksCompleted++;
|
|
75092
|
+
this.taskDurations.push(result.duration);
|
|
75093
|
+
this.auditLogger.logComplete(result.taskId, execution.assignedAgents[0]);
|
|
75094
|
+
} else {
|
|
75095
|
+
this.tasksFailed++;
|
|
75096
|
+
this.auditLogger.logFail(result.taskId, execution.assignedAgents[0], result.error || "Unknown error");
|
|
75097
|
+
}
|
|
75098
|
+
this.runningTaskCounter = Math.max(0, this.runningTaskCounter - 1);
|
|
75099
|
+
for (const agentId of execution.assignedAgents) {
|
|
75100
|
+
await this.agentCoordinator.stop(agentId);
|
|
75101
|
+
}
|
|
75102
|
+
await this.publishEvent(result.success ? "TaskCompleted" : "TaskFailed", {
|
|
75103
|
+
taskId: result.taskId,
|
|
75104
|
+
domain: execution.assignedDomain,
|
|
75105
|
+
result: result.data,
|
|
75106
|
+
error: result.error,
|
|
75107
|
+
duration: result.duration
|
|
75108
|
+
});
|
|
75109
|
+
await this.processQueue();
|
|
75110
|
+
}
|
|
71807
75111
|
async assignTask(task) {
|
|
71808
75112
|
const targetDomains = task.targetDomains.length > 0 ? task.targetDomains : TASK_DOMAIN_MAP[task.type] || [];
|
|
71809
75113
|
if (targetDomains.length === 0) {
|
|
@@ -71875,17 +75179,46 @@ var QueenCoordinator = class {
|
|
|
71875
75179
|
});
|
|
71876
75180
|
if (this.domainPlugins) {
|
|
71877
75181
|
const plugin = this.domainPlugins.get(domain);
|
|
75182
|
+
if (plugin?.executeTask && plugin.canHandleTask?.(task.type)) {
|
|
75183
|
+
const request = {
|
|
75184
|
+
taskId: task.id,
|
|
75185
|
+
taskType: task.type,
|
|
75186
|
+
payload: task.payload,
|
|
75187
|
+
priority: task.priority,
|
|
75188
|
+
timeout: task.timeout,
|
|
75189
|
+
correlationId: task.correlationId
|
|
75190
|
+
};
|
|
75191
|
+
const execResult = await plugin.executeTask(
|
|
75192
|
+
request,
|
|
75193
|
+
(result) => this.handleTaskCompletion(result)
|
|
75194
|
+
);
|
|
75195
|
+
if (!execResult.success) {
|
|
75196
|
+
this.tasks.set(task.id, {
|
|
75197
|
+
...execution,
|
|
75198
|
+
status: "failed",
|
|
75199
|
+
error: execResult.error.message,
|
|
75200
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
75201
|
+
});
|
|
75202
|
+
this.runningTaskCounter = Math.max(0, this.runningTaskCounter - 1);
|
|
75203
|
+
this.tasksFailed++;
|
|
75204
|
+
this.auditLogger.logFail(task.id, agentIds[0], execResult.error.message);
|
|
75205
|
+
return err(execResult.error);
|
|
75206
|
+
}
|
|
75207
|
+
return ok(task.id);
|
|
75208
|
+
}
|
|
71878
75209
|
if (plugin) {
|
|
71879
75210
|
try {
|
|
71880
75211
|
await plugin.handleEvent({
|
|
71881
|
-
id:
|
|
75212
|
+
id: uuidv450(),
|
|
71882
75213
|
type: "TaskAssigned",
|
|
71883
75214
|
timestamp: /* @__PURE__ */ new Date(),
|
|
71884
75215
|
source: "queen-coordinator",
|
|
71885
75216
|
correlationId: task.correlationId,
|
|
71886
75217
|
payload: { task }
|
|
71887
75218
|
});
|
|
75219
|
+
console.warn(`[Queen] Domain ${domain} has no executeTask handler, using event fallback`);
|
|
71888
75220
|
} catch (error) {
|
|
75221
|
+
console.warn(`[Queen] Failed to invoke domain ${domain} event handler:`, error);
|
|
71889
75222
|
}
|
|
71890
75223
|
}
|
|
71891
75224
|
}
|
|
@@ -72009,7 +75342,7 @@ var QueenCoordinator = class {
|
|
|
72009
75342
|
}
|
|
72010
75343
|
async publishEvent(type, payload) {
|
|
72011
75344
|
await this.eventBus.publish({
|
|
72012
|
-
id:
|
|
75345
|
+
id: uuidv450(),
|
|
72013
75346
|
type: `Queen${type}`,
|
|
72014
75347
|
timestamp: /* @__PURE__ */ new Date(),
|
|
72015
75348
|
source: "queen-coordinator",
|
|
@@ -72042,7 +75375,7 @@ var QueenCoordinator = class {
|
|
|
72042
75375
|
return cleaned;
|
|
72043
75376
|
}
|
|
72044
75377
|
};
|
|
72045
|
-
function createQueenCoordinator(kernel, router, protocolExecutor, workflowExecutor, config) {
|
|
75378
|
+
function createQueenCoordinator(kernel, router, protocolExecutor, workflowExecutor, domainPlugins, config) {
|
|
72046
75379
|
return new QueenCoordinator(
|
|
72047
75380
|
kernel.eventBus,
|
|
72048
75381
|
kernel.coordinator,
|
|
@@ -72050,14 +75383,14 @@ function createQueenCoordinator(kernel, router, protocolExecutor, workflowExecut
|
|
|
72050
75383
|
router,
|
|
72051
75384
|
protocolExecutor,
|
|
72052
75385
|
workflowExecutor,
|
|
72053
|
-
|
|
75386
|
+
domainPlugins,
|
|
72054
75387
|
config
|
|
72055
75388
|
);
|
|
72056
75389
|
}
|
|
72057
75390
|
|
|
72058
75391
|
// src/coordination/cross-domain-router.ts
|
|
72059
75392
|
init_types();
|
|
72060
|
-
import { v4 as
|
|
75393
|
+
import { v4 as uuidv451 } from "uuid";
|
|
72061
75394
|
var CrossDomainEventRouter = class {
|
|
72062
75395
|
constructor(eventBus, options) {
|
|
72063
75396
|
this.eventBus = eventBus;
|
|
@@ -72101,7 +75434,7 @@ var CrossDomainEventRouter = class {
|
|
|
72101
75434
|
* Subscribe to events from a specific domain
|
|
72102
75435
|
*/
|
|
72103
75436
|
subscribeToDoamin(domain, handler) {
|
|
72104
|
-
const id = `sub_domain_${
|
|
75437
|
+
const id = `sub_domain_${uuidv451()}`;
|
|
72105
75438
|
this.subscriptions.set(id, {
|
|
72106
75439
|
id,
|
|
72107
75440
|
type: "domain",
|
|
@@ -72115,7 +75448,7 @@ var CrossDomainEventRouter = class {
|
|
|
72115
75448
|
* Subscribe to specific event types
|
|
72116
75449
|
*/
|
|
72117
75450
|
subscribeToEventType(eventType, handler) {
|
|
72118
|
-
const id = `sub_type_${
|
|
75451
|
+
const id = `sub_type_${uuidv451()}`;
|
|
72119
75452
|
this.subscriptions.set(id, {
|
|
72120
75453
|
id,
|
|
72121
75454
|
type: "eventType",
|
|
@@ -72232,7 +75565,7 @@ var CrossDomainEventRouter = class {
|
|
|
72232
75565
|
eventsPerSecond: events.length > 0 ? events.length / ((windowEnd.getTime() - windowStart.getTime()) / 1e3) : 0
|
|
72233
75566
|
};
|
|
72234
75567
|
return {
|
|
72235
|
-
id:
|
|
75568
|
+
id: uuidv451(),
|
|
72236
75569
|
windowStart,
|
|
72237
75570
|
windowEnd,
|
|
72238
75571
|
events,
|
|
@@ -72360,7 +75693,7 @@ var CrossDomainEventRouter = class {
|
|
|
72360
75693
|
this.eventBus.publish({
|
|
72361
75694
|
...eventToSend,
|
|
72362
75695
|
// Add routing metadata
|
|
72363
|
-
id:
|
|
75696
|
+
id: uuidv451(),
|
|
72364
75697
|
correlationId: event.correlationId ?? event.id
|
|
72365
75698
|
})
|
|
72366
75699
|
);
|
|
@@ -72381,7 +75714,7 @@ var CrossDomainEventRouter = class {
|
|
|
72381
75714
|
|
|
72382
75715
|
// src/coordination/protocol-executor.ts
|
|
72383
75716
|
init_types();
|
|
72384
|
-
import { v4 as
|
|
75717
|
+
import { v4 as uuidv452 } from "uuid";
|
|
72385
75718
|
var ProtocolEvents = {
|
|
72386
75719
|
ProtocolStarted: "coordination.ProtocolStarted",
|
|
72387
75720
|
ProtocolCompleted: "coordination.ProtocolCompleted",
|
|
@@ -72585,7 +75918,7 @@ var DefaultProtocolExecutor = class {
|
|
|
72585
75918
|
* Execute a protocol
|
|
72586
75919
|
*/
|
|
72587
75920
|
async executeProtocol(protocol, params, triggeringEvent) {
|
|
72588
|
-
const executionId =
|
|
75921
|
+
const executionId = uuidv452();
|
|
72589
75922
|
const correlationId = triggeringEvent?.correlationId ?? executionId;
|
|
72590
75923
|
const execution = {
|
|
72591
75924
|
executionId,
|
|
@@ -73385,7 +76718,7 @@ var EarlyExitTokenOptimizer = class {
|
|
|
73385
76718
|
|
|
73386
76719
|
// src/learning/pattern-store.ts
|
|
73387
76720
|
init_types();
|
|
73388
|
-
import { v4 as
|
|
76721
|
+
import { v4 as uuidv453 } from "uuid";
|
|
73389
76722
|
var DEFAULT_PATTERN_STORE_CONFIG = {
|
|
73390
76723
|
namespace: "qe-patterns",
|
|
73391
76724
|
embeddingDimension: 128,
|
|
@@ -73620,7 +76953,7 @@ var PatternStore = class {
|
|
|
73620
76953
|
async create(options) {
|
|
73621
76954
|
const now = /* @__PURE__ */ new Date();
|
|
73622
76955
|
const pattern = {
|
|
73623
|
-
id:
|
|
76956
|
+
id: uuidv453(),
|
|
73624
76957
|
patternType: options.patternType,
|
|
73625
76958
|
qeDomain: this.detectDomainFromType(options.patternType),
|
|
73626
76959
|
domain: mapQEDomainToAQE(this.detectDomainFromType(options.patternType)),
|
|
@@ -82386,7 +85719,7 @@ function createTimedSpinner(text) {
|
|
|
82386
85719
|
}
|
|
82387
85720
|
|
|
82388
85721
|
// src/cli/handlers/task-handler.ts
|
|
82389
|
-
var
|
|
85722
|
+
var TaskHandler5 = class {
|
|
82390
85723
|
name = "task";
|
|
82391
85724
|
description = "Manage QE tasks";
|
|
82392
85725
|
cleanupAndExit;
|
|
@@ -82605,7 +85938,7 @@ Examples:
|
|
|
82605
85938
|
}
|
|
82606
85939
|
};
|
|
82607
85940
|
function createTaskHandler(cleanupAndExit2, ensureInitialized2) {
|
|
82608
|
-
return new
|
|
85941
|
+
return new TaskHandler5(cleanupAndExit2, ensureInitialized2);
|
|
82609
85942
|
}
|
|
82610
85943
|
|
|
82611
85944
|
// src/cli/handlers/agent-handler.ts
|
|
@@ -89548,7 +92881,7 @@ function createPostgresWriter(config) {
|
|
|
89548
92881
|
}
|
|
89549
92882
|
|
|
89550
92883
|
// src/sync/sync-agent.ts
|
|
89551
|
-
import { v4 as
|
|
92884
|
+
import { v4 as uuidv454 } from "uuid";
|
|
89552
92885
|
var CloudSyncAgent = class {
|
|
89553
92886
|
config;
|
|
89554
92887
|
readers = /* @__PURE__ */ new Map();
|
|
@@ -89853,7 +93186,7 @@ var CloudSyncAgent = class {
|
|
|
89853
93186
|
}
|
|
89854
93187
|
createReport(mode) {
|
|
89855
93188
|
return {
|
|
89856
|
-
syncId:
|
|
93189
|
+
syncId: uuidv454(),
|
|
89857
93190
|
startedAt: /* @__PURE__ */ new Date(),
|
|
89858
93191
|
status: "running",
|
|
89859
93192
|
environment: this.config.environment,
|
|
@@ -95691,7 +99024,7 @@ async function cleanupAndExit(code = 0) {
|
|
|
95691
99024
|
process.exit(code);
|
|
95692
99025
|
}
|
|
95693
99026
|
var program = new Command13();
|
|
95694
|
-
var VERSION = true ? "3.3.
|
|
99027
|
+
var VERSION = true ? "3.3.2" : "0.0.0-dev";
|
|
95695
99028
|
program.name("aqe").description("Agentic QE - Domain-Driven Quality Engineering").version(VERSION);
|
|
95696
99029
|
var registry = createCommandRegistry(context, cleanupAndExit, ensureInitialized);
|
|
95697
99030
|
registry.registerAll(program);
|