@timmeck/brain-core 2.36.60 → 2.36.61

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.
@@ -93,9 +93,11 @@ export class ResearchOrchestrator {
93
93
  brainName;
94
94
  feedbackTimer = null;
95
95
  cycleCount = 0;
96
+ lastDesireActuationCycle = 0;
96
97
  distillEvery;
97
98
  agendaEvery;
98
99
  reflectEvery;
100
+ minCycleDurationMs;
99
101
  log = getLogger();
100
102
  /** Tracks how many times each suggestion key has been emitted without being resolved. */
101
103
  suggestionHistory = new Map();
@@ -113,6 +115,7 @@ export class ResearchOrchestrator {
113
115
  this.distillEvery = config.distillEvery ?? 5;
114
116
  this.agendaEvery = config.agendaEvery ?? 3;
115
117
  this.reflectEvery = config.reflectEvery ?? 10;
118
+ this.minCycleDurationMs = config.minCycleDurationMs ?? 5000;
116
119
  this.causalGraph = causalGraph ?? null;
117
120
  this.selfObserver = new SelfObserver(db, { brainName: config.brainName });
118
121
  this.adaptiveStrategy = new AdaptiveStrategyEngine(db, { brainName: config.brainName });
@@ -277,6 +280,12 @@ export class ResearchOrchestrator {
277
280
  setCreativeEngine(engine) { this.creativeEngine = engine; }
278
281
  /** Set the ActionBridgeEngine — risk-assessed action execution. */
279
282
  setActionBridge(bridge) { this.actionBridge = bridge; }
283
+ /** Register outcome handler — called when actions complete/fail. */
284
+ setActionOutcomeHandler(handler) {
285
+ if (this.actionBridge) {
286
+ this.actionBridge.onOutcome((action, outcome) => handler(action, outcome));
287
+ }
288
+ }
280
289
  /** Set the CrossBrainSignalRouter — bidirectional signal routing. */
281
290
  setSignalRouter(router) { this.signalRouter = router; }
282
291
  /** Set the ContentForge — autonomous content pipeline. */
@@ -380,6 +389,16 @@ export class ResearchOrchestrator {
380
389
  this.cycleCount++;
381
390
  const start = Date.now();
382
391
  const ts = this.thoughtStream;
392
+ const stepTimings = [];
393
+ const profileStep = (name, fn) => {
394
+ const t0 = Date.now();
395
+ fn();
396
+ const elapsed = Date.now() - t0;
397
+ if (elapsed > 1000) {
398
+ stepTimings.push({ step: name, ms: elapsed });
399
+ this.log.warn(`[orchestrator] Slow step: ${name} took ${elapsed}ms`);
400
+ }
401
+ };
383
402
  this.log.info(`[orchestrator] ─── Feedback Cycle #${this.cycleCount} ───`);
384
403
  // Fix 6: Auto-instrument research cycles with TraceCollector
385
404
  let traceId;
@@ -2426,6 +2445,8 @@ export class ResearchOrchestrator {
2426
2445
  // Step 58: CreativeEngine — cross-pollination (every 20 cycles)
2427
2446
  if (this.creativeEngine && this.cycleCount % 20 === 0) {
2428
2447
  try {
2448
+ const debugInfo = this.creativeEngine.getDebugInfo();
2449
+ this.log.debug(`[orchestrator] Step 58: ${debugInfo.principlesCount} principles, domains: ${JSON.stringify(debugInfo.domains)}`);
2429
2450
  ts?.emit('creative', 'discovering', 'Step 58: Cross-pollinating ideas...', 'routine');
2430
2451
  const insights = this.creativeEngine.crossPollinate();
2431
2452
  if (insights.length > 0) {
@@ -2441,6 +2462,9 @@ export class ResearchOrchestrator {
2441
2462
  data: { insightCount: insights.length, converted },
2442
2463
  });
2443
2464
  }
2465
+ else {
2466
+ ts?.emit('creative', 'reflecting', `Step 58: 0 insights (${debugInfo.principlesCount} principles, ${Object.keys(debugInfo.domains).length} domains)`, 'notable');
2467
+ }
2444
2468
  }
2445
2469
  catch (err) {
2446
2470
  this.log.warn(`[orchestrator] Step 58 (creative) error: ${err.message}`);
@@ -2591,6 +2615,92 @@ export class ResearchOrchestrator {
2591
2615
  this.log.warn(`[orchestrator] Step 63 (signal emission) error: ${err.message}`);
2592
2616
  }
2593
2617
  }
2618
+ // Step 64: DesireActuator — convert top desire to action (every 15 cycles)
2619
+ if (this.actionBridge && this.cycleCount - this.lastDesireActuationCycle >= 15) {
2620
+ try {
2621
+ const desires = this.getDesires();
2622
+ const topDesire = desires.find(d => d.priority >= 5);
2623
+ if (topDesire) {
2624
+ ts?.emit('desire', 'analyzing', `Step 64: Actuating desire "${topDesire.key}" (P${topDesire.priority})...`, 'notable');
2625
+ // Map desire key → action type
2626
+ let actionType = 'create_goal';
2627
+ if (topDesire.key.startsWith('contradiction_')) {
2628
+ actionType = 'start_mission';
2629
+ }
2630
+ else if (topDesire.key.startsWith('no_predictions') || topDesire.key.startsWith('low_accuracy')) {
2631
+ actionType = 'adjust_parameter';
2632
+ }
2633
+ const actionId = this.actionBridge.propose({
2634
+ source: 'desire',
2635
+ type: actionType,
2636
+ title: `Desire: ${topDesire.suggestion.substring(0, 80)}`,
2637
+ description: topDesire.suggestion,
2638
+ confidence: Math.min(topDesire.priority / 10, 0.9),
2639
+ payload: { desireKey: topDesire.key, priority: topDesire.priority, alternatives: topDesire.alternatives },
2640
+ });
2641
+ if (actionId > 0) {
2642
+ this.log.info(`[orchestrator] Step 64: Desire "${topDesire.key}" → Action #${actionId} (${actionType})`);
2643
+ this.journal.write({
2644
+ title: `Desire Actuation: ${topDesire.key}`,
2645
+ content: `Converted desire (P${topDesire.priority}) to ${actionType} action #${actionId}: ${topDesire.suggestion}`,
2646
+ type: 'insight',
2647
+ significance: 'notable',
2648
+ tags: [this.brainName, 'desire', 'actuation'],
2649
+ references: [],
2650
+ data: { desireKey: topDesire.key, actionId, actionType },
2651
+ });
2652
+ }
2653
+ this.lastDesireActuationCycle = this.cycleCount;
2654
+ }
2655
+ }
2656
+ catch (err) {
2657
+ this.log.warn(`[orchestrator] Step 64 (desire actuation) error: ${err.message}`);
2658
+ }
2659
+ }
2660
+ // Step 65: Action-Outcome Review (every 20 cycles)
2661
+ if (this.actionBridge && this.cycleCount % 20 === 0) {
2662
+ try {
2663
+ const history = this.actionBridge.getHistory(10);
2664
+ const recentCompleted = history.filter(a => a.status === 'completed' && a.outcome?.success);
2665
+ const recentFailed = history.filter(a => a.status === 'failed' || (a.outcome && !a.outcome.success));
2666
+ if (recentCompleted.length > 0 || recentFailed.length > 0) {
2667
+ ts?.emit('orchestrator', 'reflecting', `Step 65: Reviewing ${recentCompleted.length} successes, ${recentFailed.length} failures`, 'routine');
2668
+ // Success → journal lesson learned
2669
+ for (const action of recentCompleted.slice(0, 3)) {
2670
+ const lesson = action.outcome?.learnedLesson ?? `Action "${action.title}" succeeded`;
2671
+ this.journal.write({
2672
+ title: `Action Outcome: ${action.title}`,
2673
+ content: `${action.type} from ${action.source} succeeded. Lesson: ${lesson}`,
2674
+ type: 'insight',
2675
+ significance: 'routine',
2676
+ tags: [this.brainName, 'action-outcome', 'success'],
2677
+ references: [],
2678
+ data: { actionId: action.id, type: action.type, source: action.source },
2679
+ });
2680
+ }
2681
+ // Failure → journal + hypothesis rejection
2682
+ for (const action of recentFailed.slice(0, 3)) {
2683
+ this.journal.write({
2684
+ title: `Action Failed: ${action.title}`,
2685
+ content: `${action.type} from ${action.source} failed: ${action.outcome?.result ?? 'unknown'}`,
2686
+ type: 'anomaly',
2687
+ significance: 'notable',
2688
+ tags: [this.brainName, 'action-outcome', 'failure'],
2689
+ references: [],
2690
+ data: { actionId: action.id, type: action.type, source: action.source },
2691
+ });
2692
+ }
2693
+ if (this.metaCognitionLayer) {
2694
+ this.metaCognitionLayer.recordStep('action_outcome_review', this.cycleCount, {
2695
+ insights: recentCompleted.length + recentFailed.length,
2696
+ });
2697
+ }
2698
+ }
2699
+ }
2700
+ catch (err) {
2701
+ this.log.warn(`[orchestrator] Step 65 (outcome review) error: ${err.message}`);
2702
+ }
2703
+ }
2594
2704
  const duration = Date.now() - start;
2595
2705
  ts?.emit('orchestrator', 'reflecting', `Feedback Cycle #${this.cycleCount} complete (${duration}ms)`);
2596
2706
  this.log.info(`[orchestrator] ─── Feedback Cycle #${this.cycleCount} complete (${duration}ms) ───`);
@@ -2616,6 +2726,15 @@ export class ResearchOrchestrator {
2616
2726
  }
2617
2727
  catch { /* checkpoint save should never break the cycle */ }
2618
2728
  }
2729
+ // Step-profiling summary: log slow steps if any
2730
+ if (stepTimings.length > 0) {
2731
+ this.log.warn(`[orchestrator] Cycle #${this.cycleCount} slow steps: ${stepTimings.map(s => `${s.step}(${s.ms}ms)`).join(', ')}`);
2732
+ }
2733
+ // Cycle-pacing: ensure minimum cycle duration to prevent tight-looping
2734
+ const remaining = this.minCycleDurationMs - duration;
2735
+ if (remaining > 0) {
2736
+ await new Promise(resolve => setTimeout(resolve, remaining));
2737
+ }
2619
2738
  }
2620
2739
  /** Analyze Brain's own state and generate concrete improvement suggestions.
2621
2740
  * Tracks suggestion history — if a suggestion repeats 3+ times without resolution,