@timmeck/brain-core 2.36.67 → 2.36.69
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/dist/chat/chat-engine.d.ts +6 -0
- package/dist/chat/chat-engine.js +52 -0
- package/dist/chat/chat-engine.js.map +1 -1
- package/dist/chat/index.d.ts +2 -0
- package/dist/chat/index.js +1 -0
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/multi-brain-router.d.ts +25 -0
- package/dist/chat/multi-brain-router.js +88 -0
- package/dist/chat/multi-brain-router.js.map +1 -0
- package/dist/debate/debate-engine.d.ts +2 -0
- package/dist/debate/debate-engine.js +5 -7
- package/dist/debate/debate-engine.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/research/adaptive-scheduler.d.ts +53 -0
- package/dist/research/adaptive-scheduler.js +122 -0
- package/dist/research/adaptive-scheduler.js.map +1 -0
- package/dist/research/knowledge-distiller.d.ts +4 -0
- package/dist/research/knowledge-distiller.js +17 -0
- package/dist/research/knowledge-distiller.js.map +1 -1
- package/dist/research/research-orchestrator.d.ts +42 -0
- package/dist/research/research-orchestrator.js +301 -29
- package/dist/research/research-orchestrator.js.map +1 -1
- package/dist/strategy/index.d.ts +4 -0
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/index.js.map +1 -1
- package/dist/strategy/strategy-exporter.d.ts +26 -0
- package/dist/strategy/strategy-exporter.js +47 -0
- package/dist/strategy/strategy-exporter.js.map +1 -0
- package/dist/strategy/strategy-forge.d.ts +2 -0
- package/dist/strategy/strategy-forge.js +4 -0
- package/dist/strategy/strategy-forge.js.map +1 -1
- package/dist/strategy/strategy-importer.d.ts +15 -0
- package/dist/strategy/strategy-importer.js +69 -0
- package/dist/strategy/strategy-importer.js.map +1 -0
- package/package.json +1 -1
|
@@ -89,6 +89,7 @@ export class ResearchOrchestrator {
|
|
|
89
89
|
runtimeInfluenceTracker = null;
|
|
90
90
|
loopDetector = null;
|
|
91
91
|
governanceLayer = null;
|
|
92
|
+
adaptiveScheduler = null;
|
|
92
93
|
lastAutoMissionTime = 0;
|
|
93
94
|
lastGoalMissionTime = 0;
|
|
94
95
|
roadmapBootstrapped = false;
|
|
@@ -113,6 +114,13 @@ export class ResearchOrchestrator {
|
|
|
113
114
|
lastSuggestionsCycle = -1;
|
|
114
115
|
/** Recent debate topic keys to prevent repeating the same debate. */
|
|
115
116
|
recentDebateTopics = [];
|
|
117
|
+
// ── Desire Feedback Tracking ──────────────────────────────
|
|
118
|
+
/** Tracks outcomes per desire key: successes, failures, last result. */
|
|
119
|
+
desireOutcomes = new Map();
|
|
120
|
+
/** Category-level success rates for adaptive confidence. */
|
|
121
|
+
desireCategoryRates = new Map();
|
|
122
|
+
/** Desire keys currently being actuated by other brains (received via cross-brain). */
|
|
123
|
+
crossBrainActiveDesires = new Map();
|
|
116
124
|
constructor(db, config, causalGraph) {
|
|
117
125
|
this.db = db;
|
|
118
126
|
this.brainName = config.brainName;
|
|
@@ -139,6 +147,14 @@ export class ResearchOrchestrator {
|
|
|
139
147
|
setOnSuggestion(callback) {
|
|
140
148
|
this.onSuggestionCallback = callback;
|
|
141
149
|
}
|
|
150
|
+
/** Set the AdaptiveScheduler for dynamic cycle intervals. */
|
|
151
|
+
setAdaptiveScheduler(scheduler) {
|
|
152
|
+
this.adaptiveScheduler = scheduler;
|
|
153
|
+
}
|
|
154
|
+
/** Get the AdaptiveScheduler instance. */
|
|
155
|
+
getAdaptiveScheduler() {
|
|
156
|
+
return this.adaptiveScheduler;
|
|
157
|
+
}
|
|
142
158
|
/** Set the DataMiner instance for DB-driven engine feeding. */
|
|
143
159
|
setDataMiner(miner) {
|
|
144
160
|
this.dataMiner = miner;
|
|
@@ -326,20 +342,31 @@ export class ResearchOrchestrator {
|
|
|
326
342
|
start(intervalMs = 300_000) {
|
|
327
343
|
if (this.feedbackTimer)
|
|
328
344
|
return;
|
|
329
|
-
this.
|
|
345
|
+
this.startIntervalMs = intervalMs;
|
|
346
|
+
this.scheduleNextCycle(intervalMs);
|
|
347
|
+
this.log.info(`[orchestrator] Research orchestrator started (feedback every ${intervalMs}ms)`);
|
|
348
|
+
}
|
|
349
|
+
/** Schedule the next feedback cycle (supports adaptive intervals). */
|
|
350
|
+
scheduleNextCycle(intervalMs) {
|
|
351
|
+
if (this.feedbackTimer)
|
|
352
|
+
clearTimeout(this.feedbackTimer);
|
|
353
|
+
this.feedbackTimer = setTimeout(async () => {
|
|
330
354
|
try {
|
|
331
|
-
|
|
355
|
+
await this.runFeedbackCycle();
|
|
332
356
|
}
|
|
333
357
|
catch (err) {
|
|
334
358
|
this.log.error('[orchestrator] Feedback cycle error', { error: err.message });
|
|
335
359
|
}
|
|
360
|
+
// Re-schedule with adaptive or base interval
|
|
361
|
+
const nextInterval = this.adaptiveScheduler?.getNextInterval() ?? this.startIntervalMs;
|
|
362
|
+
this.scheduleNextCycle(nextInterval);
|
|
336
363
|
}, intervalMs);
|
|
337
|
-
this.log.info(`[orchestrator] Research orchestrator started (feedback every ${intervalMs}ms)`);
|
|
338
364
|
}
|
|
365
|
+
startIntervalMs = 300_000;
|
|
339
366
|
/** Stop the feedback loop. */
|
|
340
367
|
stop() {
|
|
341
368
|
if (this.feedbackTimer) {
|
|
342
|
-
|
|
369
|
+
clearTimeout(this.feedbackTimer);
|
|
343
370
|
this.feedbackTimer = null;
|
|
344
371
|
}
|
|
345
372
|
this.dreamEngine?.stop();
|
|
@@ -365,6 +392,44 @@ export class ResearchOrchestrator {
|
|
|
365
392
|
onCrossBrainEvent(sourceBrain, eventType, data = {}) {
|
|
366
393
|
this.crossDomain.recordEvent(sourceBrain, eventType, data);
|
|
367
394
|
this.anomalyDetective.recordMetric(`cross:${sourceBrain}:${eventType}`, 1);
|
|
395
|
+
// Handle cross-brain desire coordination signals
|
|
396
|
+
if (eventType === 'desire_active' && data.desireKey) {
|
|
397
|
+
this.onCrossBrainDesireSignal(sourceBrain, data.desireKey, data.priority ?? 0);
|
|
398
|
+
}
|
|
399
|
+
// Handle cross-brain debate perspective requests
|
|
400
|
+
if (eventType === 'debate_perspective_request' && data.question && this.debateEngine) {
|
|
401
|
+
try {
|
|
402
|
+
const perspective = this.debateEngine.generatePerspective(data.question);
|
|
403
|
+
// Send perspective back via signal
|
|
404
|
+
if (this.signalRouter) {
|
|
405
|
+
this.signalRouter.emit({
|
|
406
|
+
targetBrain: sourceBrain,
|
|
407
|
+
signalType: 'debate_perspective_response',
|
|
408
|
+
payload: {
|
|
409
|
+
debateId: data.debateId,
|
|
410
|
+
perspective: { brainName: perspective.brainName, position: perspective.position, confidence: perspective.confidence, relevance: perspective.relevance, arguments: perspective.arguments },
|
|
411
|
+
},
|
|
412
|
+
confidence: perspective.confidence,
|
|
413
|
+
}).catch(() => { });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch { /* debate engine not ready */ }
|
|
417
|
+
}
|
|
418
|
+
// Handle incoming debate perspective response — add to our debate
|
|
419
|
+
if (eventType === 'debate_perspective_response' && data.debateId && data.perspective && this.debateEngine) {
|
|
420
|
+
try {
|
|
421
|
+
const p = data.perspective;
|
|
422
|
+
this.debateEngine.addPerspective(data.debateId, {
|
|
423
|
+
brainName: p.brainName ?? sourceBrain,
|
|
424
|
+
position: p.position ?? '',
|
|
425
|
+
confidence: p.confidence ?? 0,
|
|
426
|
+
relevance: p.relevance ?? 0,
|
|
427
|
+
arguments: p.arguments ?? [],
|
|
428
|
+
});
|
|
429
|
+
this.log.info(`[orchestrator] Added cross-brain perspective from ${sourceBrain} to debate #${data.debateId}`);
|
|
430
|
+
}
|
|
431
|
+
catch { /* debate may not exist */ }
|
|
432
|
+
}
|
|
368
433
|
}
|
|
369
434
|
/**
|
|
370
435
|
* Hook into AutonomousResearchScheduler cycle completion.
|
|
@@ -1245,6 +1310,11 @@ export class ResearchOrchestrator {
|
|
|
1245
1310
|
const kSummary = this.knowledgeDistiller.getSummary();
|
|
1246
1311
|
this.hypothesisEngine.observe({ source: this.brainName, type: 'internal:distillation_throughput', value: kSummary.principles + kSummary.antiPatterns + kSummary.strategies, timestamp: now, metadata: { principles: kSummary.principles, avgConfidence: kSummary.avgConfidence } });
|
|
1247
1312
|
}
|
|
1313
|
+
else if (topic.includes('dream') || topic.includes('consolidat')) {
|
|
1314
|
+
const dStatus = this.dreamEngine?.getStatus();
|
|
1315
|
+
const totals = dStatus?.totals;
|
|
1316
|
+
this.hypothesisEngine.observe({ source: this.brainName, type: 'internal:dream_consolidation_count', value: (totals?.memoriesConsolidated ?? 0), timestamp: now });
|
|
1317
|
+
}
|
|
1248
1318
|
}
|
|
1249
1319
|
catch { /* internal observation non-critical */ }
|
|
1250
1320
|
}
|
|
@@ -1389,25 +1459,57 @@ export class ResearchOrchestrator {
|
|
|
1389
1459
|
this.log.error(`[orchestrator] Emergence step error: ${err.message}`);
|
|
1390
1460
|
}
|
|
1391
1461
|
}
|
|
1392
|
-
// 20. Internal Debate:
|
|
1462
|
+
// 20. Internal + Cross-Brain Debate: debate key findings, solicit cross-brain perspectives
|
|
1393
1463
|
if (this.debateEngine && this.cycleCount % this.reflectEvery === 0) {
|
|
1394
|
-
ts?.emit('reflecting', 'reflecting', 'Initiating
|
|
1464
|
+
ts?.emit('reflecting', 'reflecting', 'Initiating debate on recent findings...');
|
|
1395
1465
|
try {
|
|
1396
|
-
// Pick a debate topic from recent attention or agenda
|
|
1397
1466
|
const topic = this.pickDebateTopic();
|
|
1398
1467
|
if (topic) {
|
|
1399
1468
|
const debate = this.debateEngine.startDebate(topic);
|
|
1469
|
+
// Solicit cross-brain perspectives via SignalRouter
|
|
1470
|
+
if (this.signalRouter) {
|
|
1471
|
+
const peers = ['brain', 'trading-brain', 'marketing-brain'].filter(b => b !== this.brainName);
|
|
1472
|
+
for (const peer of peers) {
|
|
1473
|
+
try {
|
|
1474
|
+
this.signalRouter.emit({
|
|
1475
|
+
targetBrain: peer,
|
|
1476
|
+
signalType: 'debate_perspective_request',
|
|
1477
|
+
payload: { debateId: debate.id, question: topic },
|
|
1478
|
+
confidence: 0.7,
|
|
1479
|
+
}).catch(() => { });
|
|
1480
|
+
}
|
|
1481
|
+
catch { /* peer offline */ }
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1400
1484
|
const synthesis = this.debateEngine.synthesize(debate.id);
|
|
1401
|
-
if (synthesis
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1485
|
+
if (synthesis) {
|
|
1486
|
+
// Journal the debate
|
|
1487
|
+
if (synthesis.conflicts.length > 0) {
|
|
1488
|
+
this.journal.write({
|
|
1489
|
+
type: 'discovery',
|
|
1490
|
+
title: `Debate: ${topic.substring(0, 80)}`,
|
|
1491
|
+
content: `Debate with ${synthesis.participantCount} perspective(s). ${synthesis.conflicts.length} conflict(s). Resolution: ${synthesis.resolution}`,
|
|
1492
|
+
tags: [this.brainName, 'debate', 'synthesis'],
|
|
1493
|
+
references: [],
|
|
1494
|
+
significance: synthesis.conflicts.length > 2 ? 'notable' : 'routine',
|
|
1495
|
+
data: { debate: { question: topic, synthesis } },
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
// Convert recommendations to ActionBridge proposals
|
|
1499
|
+
if (this.actionBridge && synthesis.recommendations.length > 0) {
|
|
1500
|
+
for (const rec of synthesis.recommendations.slice(0, 2)) {
|
|
1501
|
+
this.actionBridge.propose({
|
|
1502
|
+
source: 'research',
|
|
1503
|
+
type: 'create_goal',
|
|
1504
|
+
title: `Debate recommendation: ${rec.substring(0, 70)}`,
|
|
1505
|
+
description: `From debate "${topic.substring(0, 80)}": ${rec}`,
|
|
1506
|
+
confidence: synthesis.confidence,
|
|
1507
|
+
payload: { debateId: debate.id, recommendation: rec },
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
// Auto-close the debate after synthesis
|
|
1512
|
+
this.debateEngine.closeDebate(debate.id);
|
|
1411
1513
|
}
|
|
1412
1514
|
ts?.emit('reflecting', 'reflecting', `Debate on "${topic.substring(0, 40)}...": ${synthesis?.conflicts.length ?? 0} conflicts, confidence=${((synthesis?.confidence ?? 0) * 100).toFixed(0)}%`, synthesis && synthesis.conflicts.length > 0 ? 'notable' : 'routine');
|
|
1413
1515
|
}
|
|
@@ -1561,14 +1663,16 @@ export class ResearchOrchestrator {
|
|
|
1561
1663
|
this.log.warn(`[orchestrator] Step 24 error: ${err.message}`);
|
|
1562
1664
|
}
|
|
1563
1665
|
}
|
|
1564
|
-
// Step 25: Advocatus Diaboli — challenge
|
|
1666
|
+
// Step 25: Advocatus Diaboli — challenge weakest principle + adjust confidence (every 10 cycles)
|
|
1565
1667
|
if (this.debateEngine && this.cycleCount % 10 === 0) {
|
|
1566
1668
|
try {
|
|
1567
1669
|
ts?.emit('orchestrator', 'reflecting', 'Step 25: Challenging a principle...', 'routine');
|
|
1568
1670
|
const principles = this.knowledgeDistiller.getPrinciples(undefined, 20);
|
|
1569
1671
|
if (principles.length > 0) {
|
|
1570
|
-
|
|
1571
|
-
const
|
|
1672
|
+
// Target weakest principles first (lowest confidence), not random
|
|
1673
|
+
const sorted = [...principles].sort((a, b) => a.confidence - b.confidence);
|
|
1674
|
+
const targetPrinciple = sorted[0];
|
|
1675
|
+
const challenge = this.debateEngine.challenge(targetPrinciple.statement);
|
|
1572
1676
|
this.journal.write({
|
|
1573
1677
|
type: 'reflection',
|
|
1574
1678
|
title: `Principle challenged: resilience=${(challenge.resilienceScore * 100).toFixed(0)}% → ${challenge.outcome}`,
|
|
@@ -1578,6 +1682,24 @@ export class ResearchOrchestrator {
|
|
|
1578
1682
|
significance: challenge.outcome === 'disproved' ? 'notable' : 'routine',
|
|
1579
1683
|
data: { challenge },
|
|
1580
1684
|
});
|
|
1685
|
+
// Actually adjust principle confidence based on challenge outcome
|
|
1686
|
+
if (challenge.principleId !== null) {
|
|
1687
|
+
const principleIdStr = String(challenge.principleId);
|
|
1688
|
+
if (challenge.outcome === 'disproved') {
|
|
1689
|
+
// Disproved → remove principle entirely
|
|
1690
|
+
this.knowledgeDistiller.removePrinciple(principleIdStr);
|
|
1691
|
+
this.log.info(`[orchestrator] Step 25: Principle "${targetPrinciple.statement.substring(0, 50)}" REMOVED (disproved)`);
|
|
1692
|
+
}
|
|
1693
|
+
else if (challenge.outcome === 'weakened') {
|
|
1694
|
+
// Weakened → reduce confidence by 30%
|
|
1695
|
+
this.knowledgeDistiller.adjustPrincipleConfidence(principleIdStr, 0.7);
|
|
1696
|
+
this.log.info(`[orchestrator] Step 25: Principle confidence reduced by 30% (weakened)`);
|
|
1697
|
+
}
|
|
1698
|
+
else if (challenge.outcome === 'survived') {
|
|
1699
|
+
// Survived → slight boost (+10%)
|
|
1700
|
+
this.knowledgeDistiller.adjustPrincipleConfidence(principleIdStr, 1.1);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1581
1703
|
}
|
|
1582
1704
|
if (this.metaCognitionLayer)
|
|
1583
1705
|
this.metaCognitionLayer.recordStep('advocatus_diaboli', this.cycleCount, { insights: 1 });
|
|
@@ -2768,12 +2890,42 @@ export class ResearchOrchestrator {
|
|
|
2768
2890
|
}
|
|
2769
2891
|
}
|
|
2770
2892
|
// Step 64: DesireActuator — convert top desire to action (every 15 cycles)
|
|
2893
|
+
// Fix 1: Feedback-loop — deprioritize failed desires, boost successful ones
|
|
2894
|
+
// Fix 2: Cross-brain coordination — skip desires already active in other brains
|
|
2895
|
+
// Fix 3: Adaptive confidence — use category success rate instead of static priority/10
|
|
2771
2896
|
if (this.actionBridge && this.cycleCount - this.lastDesireActuationCycle >= 15) {
|
|
2772
2897
|
try {
|
|
2773
2898
|
const desires = this.getDesires();
|
|
2774
|
-
|
|
2899
|
+
// Apply feedback adjustments to priorities
|
|
2900
|
+
const adjusted = desires.map(d => {
|
|
2901
|
+
const outcome = this.desireOutcomes.get(d.key);
|
|
2902
|
+
let adjustedPriority = d.priority;
|
|
2903
|
+
if (outcome) {
|
|
2904
|
+
// Deprioritize desires that keep failing (−2 per failure, +1 per success, floor 0)
|
|
2905
|
+
adjustedPriority = Math.max(0, d.priority + outcome.successes - outcome.failures * 2);
|
|
2906
|
+
// If failed 3+ times consecutively, hard suppress below threshold
|
|
2907
|
+
if (outcome.failures >= 3 && outcome.lastResult === 'failure') {
|
|
2908
|
+
adjustedPriority = Math.min(adjustedPriority, 2);
|
|
2909
|
+
this.log.info(`[orchestrator] Step 64: Desire "${d.key}" suppressed (${outcome.failures} consecutive failures)`);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
return { ...d, adjustedPriority };
|
|
2913
|
+
});
|
|
2914
|
+
// Re-sort by adjusted priority
|
|
2915
|
+
adjusted.sort((a, b) => b.adjustedPriority - a.adjustedPriority);
|
|
2916
|
+
// Find top desire that passes threshold AND isn't already active in another brain
|
|
2917
|
+
const topDesire = adjusted.find(d => {
|
|
2918
|
+
if (d.adjustedPriority < 5)
|
|
2919
|
+
return false;
|
|
2920
|
+
const crossActive = this.crossBrainActiveDesires.get(d.key);
|
|
2921
|
+
if (crossActive && this.cycleCount - crossActive.cycle < 30) {
|
|
2922
|
+
this.log.info(`[orchestrator] Step 64: Skipping "${d.key}" — active in ${crossActive.brain}`);
|
|
2923
|
+
return false;
|
|
2924
|
+
}
|
|
2925
|
+
return true;
|
|
2926
|
+
});
|
|
2775
2927
|
if (topDesire) {
|
|
2776
|
-
ts?.emit('desire', 'analyzing', `Step 64: Actuating desire "${topDesire.key}" (P${topDesire.
|
|
2928
|
+
ts?.emit('desire', 'analyzing', `Step 64: Actuating desire "${topDesire.key}" (P${topDesire.adjustedPriority})...`, 'notable');
|
|
2777
2929
|
// Map desire key → action type
|
|
2778
2930
|
let actionType = 'create_goal';
|
|
2779
2931
|
if (topDesire.key.startsWith('contradiction_')) {
|
|
@@ -2782,25 +2934,50 @@ export class ResearchOrchestrator {
|
|
|
2782
2934
|
else if (topDesire.key.startsWith('no_predictions') || topDesire.key.startsWith('low_accuracy')) {
|
|
2783
2935
|
actionType = 'adjust_parameter';
|
|
2784
2936
|
}
|
|
2937
|
+
// Adaptive confidence: use category success rate if available
|
|
2938
|
+
const category = this.desireKeyToCategory(topDesire.key);
|
|
2939
|
+
const categoryRate = this.desireCategoryRates.get(category);
|
|
2940
|
+
let confidence;
|
|
2941
|
+
if (categoryRate && categoryRate.total >= 3) {
|
|
2942
|
+
// Blend: 60% category success rate + 40% priority-based
|
|
2943
|
+
const rateComponent = categoryRate.successes / categoryRate.total;
|
|
2944
|
+
const priorityComponent = Math.min(topDesire.adjustedPriority / 10, 0.9);
|
|
2945
|
+
confidence = Math.min(rateComponent * 0.6 + priorityComponent * 0.4, 0.9);
|
|
2946
|
+
}
|
|
2947
|
+
else {
|
|
2948
|
+
confidence = Math.min(topDesire.adjustedPriority / 10, 0.9);
|
|
2949
|
+
}
|
|
2785
2950
|
const actionId = this.actionBridge.propose({
|
|
2786
2951
|
source: 'desire',
|
|
2787
2952
|
type: actionType,
|
|
2788
2953
|
title: `Desire: ${topDesire.suggestion.substring(0, 80)}`,
|
|
2789
2954
|
description: topDesire.suggestion,
|
|
2790
|
-
confidence
|
|
2791
|
-
payload: { desireKey: topDesire.key, priority: topDesire.
|
|
2955
|
+
confidence,
|
|
2956
|
+
payload: { desireKey: topDesire.key, priority: topDesire.adjustedPriority, category, alternatives: topDesire.alternatives },
|
|
2792
2957
|
});
|
|
2793
2958
|
if (actionId > 0) {
|
|
2794
|
-
this.log.info(`[orchestrator] Step 64: Desire "${topDesire.key}" → Action #${actionId} (${actionType})`);
|
|
2959
|
+
this.log.info(`[orchestrator] Step 64: Desire "${topDesire.key}" → Action #${actionId} (${actionType}, conf=${confidence.toFixed(2)})`);
|
|
2795
2960
|
this.journal.write({
|
|
2796
2961
|
title: `Desire Actuation: ${topDesire.key}`,
|
|
2797
|
-
content: `Converted desire (P${topDesire.
|
|
2962
|
+
content: `Converted desire (P${topDesire.adjustedPriority}, conf=${confidence.toFixed(2)}) to ${actionType} action #${actionId}: ${topDesire.suggestion}`,
|
|
2798
2963
|
type: 'insight',
|
|
2799
2964
|
significance: 'notable',
|
|
2800
2965
|
tags: [this.brainName, 'desire', 'actuation'],
|
|
2801
2966
|
references: [],
|
|
2802
|
-
data: { desireKey: topDesire.key, actionId, actionType },
|
|
2967
|
+
data: { desireKey: topDesire.key, actionId, actionType, adjustedPriority: topDesire.adjustedPriority, confidence },
|
|
2803
2968
|
});
|
|
2969
|
+
// Broadcast to other brains that we're working on this desire
|
|
2970
|
+
if (this.signalRouter) {
|
|
2971
|
+
const peers = ['brain', 'trading-brain', 'marketing-brain'].filter(b => b !== this.brainName);
|
|
2972
|
+
for (const peer of peers) {
|
|
2973
|
+
this.signalRouter.emit({
|
|
2974
|
+
targetBrain: peer,
|
|
2975
|
+
signalType: 'desire_active',
|
|
2976
|
+
payload: { desireKey: topDesire.key, priority: topDesire.adjustedPriority },
|
|
2977
|
+
confidence,
|
|
2978
|
+
}).catch(() => { });
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2804
2981
|
}
|
|
2805
2982
|
this.lastDesireActuationCycle = this.cycleCount;
|
|
2806
2983
|
}
|
|
@@ -2810,6 +2987,7 @@ export class ResearchOrchestrator {
|
|
|
2810
2987
|
}
|
|
2811
2988
|
}
|
|
2812
2989
|
// Step 65: Action-Outcome Review (every 20 cycles)
|
|
2990
|
+
// Enhanced: Feed desire outcomes back into desireOutcomes + desireCategoryRates
|
|
2813
2991
|
if (this.actionBridge && this.cycleCount % 20 === 0) {
|
|
2814
2992
|
try {
|
|
2815
2993
|
const history = this.actionBridge.getHistory(10);
|
|
@@ -2817,7 +2995,7 @@ export class ResearchOrchestrator {
|
|
|
2817
2995
|
const recentFailed = history.filter(a => a.status === 'failed' || (a.outcome && !a.outcome.success));
|
|
2818
2996
|
if (recentCompleted.length > 0 || recentFailed.length > 0) {
|
|
2819
2997
|
ts?.emit('orchestrator', 'reflecting', `Step 65: Reviewing ${recentCompleted.length} successes, ${recentFailed.length} failures`, 'routine');
|
|
2820
|
-
// Success → journal lesson learned
|
|
2998
|
+
// Success → journal lesson learned + desire feedback
|
|
2821
2999
|
for (const action of recentCompleted.slice(0, 3)) {
|
|
2822
3000
|
const lesson = action.outcome?.learnedLesson ?? `Action "${action.title}" succeeded`;
|
|
2823
3001
|
this.journal.write({
|
|
@@ -2829,8 +3007,19 @@ export class ResearchOrchestrator {
|
|
|
2829
3007
|
references: [],
|
|
2830
3008
|
data: { actionId: action.id, type: action.type, source: action.source },
|
|
2831
3009
|
});
|
|
3010
|
+
// Feed success back into desire tracking
|
|
3011
|
+
if (action.source === 'desire') {
|
|
3012
|
+
const desireKey = action.payload.desireKey;
|
|
3013
|
+
const category = action.payload.category;
|
|
3014
|
+
if (desireKey) {
|
|
3015
|
+
this.recordDesireOutcome(desireKey, 'success');
|
|
3016
|
+
}
|
|
3017
|
+
if (category) {
|
|
3018
|
+
this.recordDesireCategoryOutcome(category, true);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
2832
3021
|
}
|
|
2833
|
-
// Failure → journal +
|
|
3022
|
+
// Failure → journal + desire feedback
|
|
2834
3023
|
for (const action of recentFailed.slice(0, 3)) {
|
|
2835
3024
|
this.journal.write({
|
|
2836
3025
|
title: `Action Failed: ${action.title}`,
|
|
@@ -2841,6 +3030,17 @@ export class ResearchOrchestrator {
|
|
|
2841
3030
|
references: [],
|
|
2842
3031
|
data: { actionId: action.id, type: action.type, source: action.source },
|
|
2843
3032
|
});
|
|
3033
|
+
// Feed failure back into desire tracking
|
|
3034
|
+
if (action.source === 'desire') {
|
|
3035
|
+
const desireKey = action.payload.desireKey;
|
|
3036
|
+
const category = action.payload.category;
|
|
3037
|
+
if (desireKey) {
|
|
3038
|
+
this.recordDesireOutcome(desireKey, 'failure');
|
|
3039
|
+
}
|
|
3040
|
+
if (category) {
|
|
3041
|
+
this.recordDesireCategoryOutcome(category, false);
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
2844
3044
|
}
|
|
2845
3045
|
if (this.metaCognitionLayer) {
|
|
2846
3046
|
this.metaCognitionLayer.recordStep('action_outcome_review', this.cycleCount, {
|
|
@@ -2934,6 +3134,15 @@ export class ResearchOrchestrator {
|
|
|
2934
3134
|
}
|
|
2935
3135
|
catch { /* checkpoint save should never break the cycle */ }
|
|
2936
3136
|
}
|
|
3137
|
+
// Adaptive Scheduling: record cycle outcome for interval optimization
|
|
3138
|
+
if (this.adaptiveScheduler) {
|
|
3139
|
+
this.adaptiveScheduler.recordOutcome({
|
|
3140
|
+
insightsFound: insights.length,
|
|
3141
|
+
rulesLearned: 0, // rules come from external learning engines
|
|
3142
|
+
anomaliesDetected: anomalies.length,
|
|
3143
|
+
durationMs: duration,
|
|
3144
|
+
});
|
|
3145
|
+
}
|
|
2937
3146
|
// Step-profiling summary: log slow steps if any
|
|
2938
3147
|
if (stepTimings.length > 0) {
|
|
2939
3148
|
this.log.warn(`[orchestrator] Cycle #${this.cycleCount} slow steps: ${stepTimings.map(s => `${s.step}(${s.ms}ms)`).join(', ')}`);
|
|
@@ -3337,6 +3546,69 @@ export class ResearchOrchestrator {
|
|
|
3337
3546
|
}
|
|
3338
3547
|
return result;
|
|
3339
3548
|
}
|
|
3549
|
+
// ── Desire Feedback Helpers ──────────────────────────────
|
|
3550
|
+
/** Record a desire outcome (success or failure) for feedback-loop. */
|
|
3551
|
+
recordDesireOutcome(desireKey, result) {
|
|
3552
|
+
const existing = this.desireOutcomes.get(desireKey) ?? { successes: 0, failures: 0, lastResult: result, lastCycle: 0 };
|
|
3553
|
+
if (result === 'success') {
|
|
3554
|
+
existing.successes++;
|
|
3555
|
+
}
|
|
3556
|
+
else {
|
|
3557
|
+
existing.failures++;
|
|
3558
|
+
}
|
|
3559
|
+
existing.lastResult = result;
|
|
3560
|
+
existing.lastCycle = this.cycleCount;
|
|
3561
|
+
this.desireOutcomes.set(desireKey, existing);
|
|
3562
|
+
this.log.info(`[orchestrator] Desire feedback: "${desireKey}" → ${result} (${existing.successes}S/${existing.failures}F)`);
|
|
3563
|
+
}
|
|
3564
|
+
/** Record category-level outcome for adaptive confidence. */
|
|
3565
|
+
recordDesireCategoryOutcome(category, success) {
|
|
3566
|
+
const existing = this.desireCategoryRates.get(category) ?? { successes: 0, total: 0 };
|
|
3567
|
+
existing.total++;
|
|
3568
|
+
if (success)
|
|
3569
|
+
existing.successes++;
|
|
3570
|
+
this.desireCategoryRates.set(category, existing);
|
|
3571
|
+
}
|
|
3572
|
+
/** Map a desire key to a broad category for confidence tracking. */
|
|
3573
|
+
desireKeyToCategory(key) {
|
|
3574
|
+
if (key.startsWith('no_predictions') || key.startsWith('low_accuracy'))
|
|
3575
|
+
return 'prediction';
|
|
3576
|
+
if (key.startsWith('contradiction_'))
|
|
3577
|
+
return 'contradiction';
|
|
3578
|
+
if (key.startsWith('curiosity_gap_'))
|
|
3579
|
+
return 'curiosity';
|
|
3580
|
+
if (key.startsWith('no_knowledge'))
|
|
3581
|
+
return 'knowledge';
|
|
3582
|
+
if (key.startsWith('pending_transfers') || key.startsWith('want_cross_brain'))
|
|
3583
|
+
return 'cross_brain';
|
|
3584
|
+
if (key.startsWith('deep_dive_'))
|
|
3585
|
+
return 'deep_dive';
|
|
3586
|
+
return 'general';
|
|
3587
|
+
}
|
|
3588
|
+
/** Handle incoming cross-brain desire signal. */
|
|
3589
|
+
onCrossBrainDesireSignal(brain, desireKey, priority) {
|
|
3590
|
+
this.crossBrainActiveDesires.set(desireKey, { brain, priority, cycle: this.cycleCount });
|
|
3591
|
+
this.log.info(`[orchestrator] Cross-brain desire received: "${desireKey}" from ${brain} (P${priority})`);
|
|
3592
|
+
// Clean up stale entries (older than 60 cycles)
|
|
3593
|
+
for (const [key, entry] of this.crossBrainActiveDesires) {
|
|
3594
|
+
if (this.cycleCount - entry.cycle > 60) {
|
|
3595
|
+
this.crossBrainActiveDesires.delete(key);
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
/** Get desire feedback stats for monitoring. */
|
|
3600
|
+
getDesireFeedbackStats() {
|
|
3601
|
+
const outcomes = [...this.desireOutcomes.entries()].map(([key, v]) => ({
|
|
3602
|
+
key, successes: v.successes, failures: v.failures, lastResult: v.lastResult,
|
|
3603
|
+
}));
|
|
3604
|
+
const categoryRates = [...this.desireCategoryRates.entries()].map(([category, v]) => ({
|
|
3605
|
+
category, successRate: v.total > 0 ? v.successes / v.total : 0, total: v.total,
|
|
3606
|
+
}));
|
|
3607
|
+
const crossBrainActive = [...this.crossBrainActiveDesires.entries()].map(([key, v]) => ({
|
|
3608
|
+
key, brain: v.brain, priority: v.priority,
|
|
3609
|
+
}));
|
|
3610
|
+
return { outcomes, categoryRates, crossBrainActive };
|
|
3611
|
+
}
|
|
3340
3612
|
/** Get structured self-improvement desires with priority and alternatives. */
|
|
3341
3613
|
getDesires() {
|
|
3342
3614
|
const raw = [];
|