@timmeck/brain-core 2.36.68 → 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/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/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 +33 -0
- package/dist/research/research-orchestrator.js +263 -25
- package/dist/research/research-orchestrator.js.map +1 -1
- package/package.json +1 -1
|
@@ -114,6 +114,13 @@ export class ResearchOrchestrator {
|
|
|
114
114
|
lastSuggestionsCycle = -1;
|
|
115
115
|
/** Recent debate topic keys to prevent repeating the same debate. */
|
|
116
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();
|
|
117
124
|
constructor(db, config, causalGraph) {
|
|
118
125
|
this.db = db;
|
|
119
126
|
this.brainName = config.brainName;
|
|
@@ -385,6 +392,44 @@ export class ResearchOrchestrator {
|
|
|
385
392
|
onCrossBrainEvent(sourceBrain, eventType, data = {}) {
|
|
386
393
|
this.crossDomain.recordEvent(sourceBrain, eventType, data);
|
|
387
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
|
+
}
|
|
388
433
|
}
|
|
389
434
|
/**
|
|
390
435
|
* Hook into AutonomousResearchScheduler cycle completion.
|
|
@@ -1414,25 +1459,57 @@ export class ResearchOrchestrator {
|
|
|
1414
1459
|
this.log.error(`[orchestrator] Emergence step error: ${err.message}`);
|
|
1415
1460
|
}
|
|
1416
1461
|
}
|
|
1417
|
-
// 20. Internal Debate:
|
|
1462
|
+
// 20. Internal + Cross-Brain Debate: debate key findings, solicit cross-brain perspectives
|
|
1418
1463
|
if (this.debateEngine && this.cycleCount % this.reflectEvery === 0) {
|
|
1419
|
-
ts?.emit('reflecting', 'reflecting', 'Initiating
|
|
1464
|
+
ts?.emit('reflecting', 'reflecting', 'Initiating debate on recent findings...');
|
|
1420
1465
|
try {
|
|
1421
|
-
// Pick a debate topic from recent attention or agenda
|
|
1422
1466
|
const topic = this.pickDebateTopic();
|
|
1423
1467
|
if (topic) {
|
|
1424
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
|
+
}
|
|
1425
1484
|
const synthesis = this.debateEngine.synthesize(debate.id);
|
|
1426
|
-
if (synthesis
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
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);
|
|
1436
1513
|
}
|
|
1437
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');
|
|
1438
1515
|
}
|
|
@@ -1586,14 +1663,16 @@ export class ResearchOrchestrator {
|
|
|
1586
1663
|
this.log.warn(`[orchestrator] Step 24 error: ${err.message}`);
|
|
1587
1664
|
}
|
|
1588
1665
|
}
|
|
1589
|
-
// Step 25: Advocatus Diaboli — challenge
|
|
1666
|
+
// Step 25: Advocatus Diaboli — challenge weakest principle + adjust confidence (every 10 cycles)
|
|
1590
1667
|
if (this.debateEngine && this.cycleCount % 10 === 0) {
|
|
1591
1668
|
try {
|
|
1592
1669
|
ts?.emit('orchestrator', 'reflecting', 'Step 25: Challenging a principle...', 'routine');
|
|
1593
1670
|
const principles = this.knowledgeDistiller.getPrinciples(undefined, 20);
|
|
1594
1671
|
if (principles.length > 0) {
|
|
1595
|
-
|
|
1596
|
-
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);
|
|
1597
1676
|
this.journal.write({
|
|
1598
1677
|
type: 'reflection',
|
|
1599
1678
|
title: `Principle challenged: resilience=${(challenge.resilienceScore * 100).toFixed(0)}% → ${challenge.outcome}`,
|
|
@@ -1603,6 +1682,24 @@ export class ResearchOrchestrator {
|
|
|
1603
1682
|
significance: challenge.outcome === 'disproved' ? 'notable' : 'routine',
|
|
1604
1683
|
data: { challenge },
|
|
1605
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
|
+
}
|
|
1606
1703
|
}
|
|
1607
1704
|
if (this.metaCognitionLayer)
|
|
1608
1705
|
this.metaCognitionLayer.recordStep('advocatus_diaboli', this.cycleCount, { insights: 1 });
|
|
@@ -2793,12 +2890,42 @@ export class ResearchOrchestrator {
|
|
|
2793
2890
|
}
|
|
2794
2891
|
}
|
|
2795
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
|
|
2796
2896
|
if (this.actionBridge && this.cycleCount - this.lastDesireActuationCycle >= 15) {
|
|
2797
2897
|
try {
|
|
2798
2898
|
const desires = this.getDesires();
|
|
2799
|
-
|
|
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
|
+
});
|
|
2800
2927
|
if (topDesire) {
|
|
2801
|
-
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');
|
|
2802
2929
|
// Map desire key → action type
|
|
2803
2930
|
let actionType = 'create_goal';
|
|
2804
2931
|
if (topDesire.key.startsWith('contradiction_')) {
|
|
@@ -2807,25 +2934,50 @@ export class ResearchOrchestrator {
|
|
|
2807
2934
|
else if (topDesire.key.startsWith('no_predictions') || topDesire.key.startsWith('low_accuracy')) {
|
|
2808
2935
|
actionType = 'adjust_parameter';
|
|
2809
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
|
+
}
|
|
2810
2950
|
const actionId = this.actionBridge.propose({
|
|
2811
2951
|
source: 'desire',
|
|
2812
2952
|
type: actionType,
|
|
2813
2953
|
title: `Desire: ${topDesire.suggestion.substring(0, 80)}`,
|
|
2814
2954
|
description: topDesire.suggestion,
|
|
2815
|
-
confidence
|
|
2816
|
-
payload: { desireKey: topDesire.key, priority: topDesire.
|
|
2955
|
+
confidence,
|
|
2956
|
+
payload: { desireKey: topDesire.key, priority: topDesire.adjustedPriority, category, alternatives: topDesire.alternatives },
|
|
2817
2957
|
});
|
|
2818
2958
|
if (actionId > 0) {
|
|
2819
|
-
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)})`);
|
|
2820
2960
|
this.journal.write({
|
|
2821
2961
|
title: `Desire Actuation: ${topDesire.key}`,
|
|
2822
|
-
content: `Converted desire (P${topDesire.
|
|
2962
|
+
content: `Converted desire (P${topDesire.adjustedPriority}, conf=${confidence.toFixed(2)}) to ${actionType} action #${actionId}: ${topDesire.suggestion}`,
|
|
2823
2963
|
type: 'insight',
|
|
2824
2964
|
significance: 'notable',
|
|
2825
2965
|
tags: [this.brainName, 'desire', 'actuation'],
|
|
2826
2966
|
references: [],
|
|
2827
|
-
data: { desireKey: topDesire.key, actionId, actionType },
|
|
2967
|
+
data: { desireKey: topDesire.key, actionId, actionType, adjustedPriority: topDesire.adjustedPriority, confidence },
|
|
2828
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
|
+
}
|
|
2829
2981
|
}
|
|
2830
2982
|
this.lastDesireActuationCycle = this.cycleCount;
|
|
2831
2983
|
}
|
|
@@ -2835,6 +2987,7 @@ export class ResearchOrchestrator {
|
|
|
2835
2987
|
}
|
|
2836
2988
|
}
|
|
2837
2989
|
// Step 65: Action-Outcome Review (every 20 cycles)
|
|
2990
|
+
// Enhanced: Feed desire outcomes back into desireOutcomes + desireCategoryRates
|
|
2838
2991
|
if (this.actionBridge && this.cycleCount % 20 === 0) {
|
|
2839
2992
|
try {
|
|
2840
2993
|
const history = this.actionBridge.getHistory(10);
|
|
@@ -2842,7 +2995,7 @@ export class ResearchOrchestrator {
|
|
|
2842
2995
|
const recentFailed = history.filter(a => a.status === 'failed' || (a.outcome && !a.outcome.success));
|
|
2843
2996
|
if (recentCompleted.length > 0 || recentFailed.length > 0) {
|
|
2844
2997
|
ts?.emit('orchestrator', 'reflecting', `Step 65: Reviewing ${recentCompleted.length} successes, ${recentFailed.length} failures`, 'routine');
|
|
2845
|
-
// Success → journal lesson learned
|
|
2998
|
+
// Success → journal lesson learned + desire feedback
|
|
2846
2999
|
for (const action of recentCompleted.slice(0, 3)) {
|
|
2847
3000
|
const lesson = action.outcome?.learnedLesson ?? `Action "${action.title}" succeeded`;
|
|
2848
3001
|
this.journal.write({
|
|
@@ -2854,8 +3007,19 @@ export class ResearchOrchestrator {
|
|
|
2854
3007
|
references: [],
|
|
2855
3008
|
data: { actionId: action.id, type: action.type, source: action.source },
|
|
2856
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
|
+
}
|
|
2857
3021
|
}
|
|
2858
|
-
// Failure → journal +
|
|
3022
|
+
// Failure → journal + desire feedback
|
|
2859
3023
|
for (const action of recentFailed.slice(0, 3)) {
|
|
2860
3024
|
this.journal.write({
|
|
2861
3025
|
title: `Action Failed: ${action.title}`,
|
|
@@ -2866,6 +3030,17 @@ export class ResearchOrchestrator {
|
|
|
2866
3030
|
references: [],
|
|
2867
3031
|
data: { actionId: action.id, type: action.type, source: action.source },
|
|
2868
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
|
+
}
|
|
2869
3044
|
}
|
|
2870
3045
|
if (this.metaCognitionLayer) {
|
|
2871
3046
|
this.metaCognitionLayer.recordStep('action_outcome_review', this.cycleCount, {
|
|
@@ -3371,6 +3546,69 @@ export class ResearchOrchestrator {
|
|
|
3371
3546
|
}
|
|
3372
3547
|
return result;
|
|
3373
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
|
+
}
|
|
3374
3612
|
/** Get structured self-improvement desires with priority and alternatives. */
|
|
3375
3613
|
getDesires() {
|
|
3376
3614
|
const raw = [];
|