@timmeck/brain-core 2.25.0 → 2.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/metacognition/auto-experiment-engine.d.ts +72 -0
- package/dist/metacognition/auto-experiment-engine.js +272 -0
- package/dist/metacognition/auto-experiment-engine.js.map +1 -0
- package/dist/metacognition/index.d.ts +6 -0
- package/dist/metacognition/index.js +4 -0
- package/dist/metacognition/index.js.map +1 -0
- package/dist/metacognition/meta-cognition-layer.d.ts +62 -0
- package/dist/metacognition/meta-cognition-layer.js +212 -0
- package/dist/metacognition/meta-cognition-layer.js.map +1 -0
- package/dist/metacognition/parameter-registry.d.ts +71 -0
- package/dist/metacognition/parameter-registry.js +162 -0
- package/dist/metacognition/parameter-registry.js.map +1 -0
- package/dist/research/research-orchestrator.d.ts +16 -1
- package/dist/research/research-orchestrator.js +376 -84
- package/dist/research/research-orchestrator.js.map +1 -1
- package/package.json +1 -1
|
@@ -39,6 +39,9 @@ export class ResearchOrchestrator {
|
|
|
39
39
|
curiosityEngine = null;
|
|
40
40
|
emergenceEngine = null;
|
|
41
41
|
debateEngine = null;
|
|
42
|
+
parameterRegistry = null;
|
|
43
|
+
metaCognitionLayer = null;
|
|
44
|
+
autoExperimentEngine = null;
|
|
42
45
|
brainName;
|
|
43
46
|
feedbackTimer = null;
|
|
44
47
|
cycleCount = 0;
|
|
@@ -50,6 +53,8 @@ export class ResearchOrchestrator {
|
|
|
50
53
|
suggestionHistory = new Map();
|
|
51
54
|
/** Max repeats before trying an alternative. */
|
|
52
55
|
stalledThreshold = 3;
|
|
56
|
+
/** Hash of last written suggestions to prevent duplicate file writes. */
|
|
57
|
+
lastSuggestionsHash = '';
|
|
53
58
|
constructor(db, config, causalGraph) {
|
|
54
59
|
this.brainName = config.brainName;
|
|
55
60
|
this.distillEvery = config.distillEvery ?? 5;
|
|
@@ -121,6 +126,18 @@ export class ResearchOrchestrator {
|
|
|
121
126
|
setDebateEngine(engine) {
|
|
122
127
|
this.debateEngine = engine;
|
|
123
128
|
}
|
|
129
|
+
/** Set the ParameterRegistry — central tunable parameter store. */
|
|
130
|
+
setParameterRegistry(registry) {
|
|
131
|
+
this.parameterRegistry = registry;
|
|
132
|
+
}
|
|
133
|
+
/** Set the MetaCognitionLayer — engine evaluation and frequency adjustment. */
|
|
134
|
+
setMetaCognitionLayer(layer) {
|
|
135
|
+
this.metaCognitionLayer = layer;
|
|
136
|
+
}
|
|
137
|
+
/** Set the AutoExperimentEngine — autonomous parameter tuning. */
|
|
138
|
+
setAutoExperimentEngine(engine) {
|
|
139
|
+
this.autoExperimentEngine = engine;
|
|
140
|
+
}
|
|
124
141
|
/** Set the PredictionEngine — wires journal into it. */
|
|
125
142
|
setPredictionEngine(engine) {
|
|
126
143
|
this.predictionEngine = engine;
|
|
@@ -446,17 +463,13 @@ export class ResearchOrchestrator {
|
|
|
446
463
|
}
|
|
447
464
|
}
|
|
448
465
|
// 10. Self-Improvement: analyze own state and generate improvement suggestions
|
|
449
|
-
|
|
466
|
+
// Brain is NEVER satisfied — always wants to learn more, build more, understand deeper
|
|
467
|
+
ts?.emit('self_improvement', 'analyzing', 'Was fehlt mir? Was will ich können? Was verstehe ich noch nicht?');
|
|
450
468
|
const suggestions = this.generateSelfImprovementSuggestions();
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
ts?.emit('self_improvement', 'discovering', s, 'notable');
|
|
454
|
-
}
|
|
455
|
-
this.log.info(`[orchestrator] Self-improvement: ${suggestions.length} suggestions`);
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
ts?.emit('self_improvement', 'analyzing', 'No improvement suggestions this cycle');
|
|
469
|
+
for (const s of suggestions) {
|
|
470
|
+
ts?.emit('self_improvement', 'discovering', s, 'notable');
|
|
459
471
|
}
|
|
472
|
+
this.log.info(`[orchestrator] Self-improvement: ${suggestions.length} desires this cycle`);
|
|
460
473
|
// 11. Self-Metrics: feed own cycle data into PredictionEngine
|
|
461
474
|
if (this.predictionEngine) {
|
|
462
475
|
const cycleDuration = Date.now() - start;
|
|
@@ -470,14 +483,39 @@ export class ResearchOrchestrator {
|
|
|
470
483
|
this.predictionEngine.recordMetric('auto_response_count', responderStatus.total_responses, 'metric');
|
|
471
484
|
ts?.emit('orchestrator', 'perceiving', `Self-metrics recorded: ${anomalies.length} anomalies, ${insights.length} insights, ${cycleDuration}ms`);
|
|
472
485
|
}
|
|
473
|
-
// 12. Auto-Experiments:
|
|
474
|
-
if (this.cycleCount > 3) {
|
|
486
|
+
// 12. Auto-Experiments: use AutoExperimentEngine if available, otherwise hardcoded fallback
|
|
487
|
+
if (this.autoExperimentEngine && this.cycleCount > 3 && this.cycleCount % 5 === 0) {
|
|
488
|
+
ts?.emit('auto_experiment', 'experimenting', 'Processing auto-experiments...');
|
|
489
|
+
try {
|
|
490
|
+
// Feed measurements
|
|
491
|
+
this.autoExperimentEngine.feedMeasurement('insight_count', insights.length);
|
|
492
|
+
this.autoExperimentEngine.feedMeasurement('anomaly_count', anomalies.length);
|
|
493
|
+
// Process completed
|
|
494
|
+
const completed = this.autoExperimentEngine.processCompleted(this.cycleCount);
|
|
495
|
+
for (const c of completed) {
|
|
496
|
+
ts?.emit('auto_experiment', 'discovering', `Auto-experiment #${c.autoExpId}: ${c.action}`, c.action === 'adopted' ? 'notable' : 'routine');
|
|
497
|
+
}
|
|
498
|
+
// Propose new
|
|
499
|
+
const candidates = this.autoExperimentEngine.discoverCandidates(this.cycleCount);
|
|
500
|
+
if (candidates.length > 0) {
|
|
501
|
+
const best = candidates[0];
|
|
502
|
+
const started = this.autoExperimentEngine.startExperiment(best);
|
|
503
|
+
if (started) {
|
|
504
|
+
ts?.emit('auto_experiment', 'experimenting', `Started: ${best.engine}.${best.name} ${best.currentValue.toFixed(3)} → ${best.proposedValue.toFixed(3)}`, 'notable');
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
catch (err) {
|
|
509
|
+
this.log.error(`[orchestrator] AutoExperiment error: ${err.message}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else if (this.cycleCount > 3) {
|
|
513
|
+
// Fallback: hardcoded experiments when no AutoExperimentEngine
|
|
475
514
|
const running = this.experimentEngine.list('running_control', 5).length
|
|
476
515
|
+ this.experimentEngine.list('running_treatment', 5).length;
|
|
477
516
|
if (running === 0 && this.cycleCount % 5 === 0) {
|
|
478
517
|
this.proposeAutoExperiment(ts);
|
|
479
518
|
}
|
|
480
|
-
// Feed measurements into running experiments
|
|
481
519
|
this.feedExperimentMeasurements(anomalies.length, insights.length);
|
|
482
520
|
}
|
|
483
521
|
// 13. Periodic Dream Consolidation: don't wait for idle, consolidate every 20 cycles
|
|
@@ -746,9 +784,54 @@ export class ResearchOrchestrator {
|
|
|
746
784
|
this.log.error(`[orchestrator] Debate step error: ${err.message}`);
|
|
747
785
|
}
|
|
748
786
|
}
|
|
787
|
+
// 21. MetaCognition: evaluate engine performance and adjust frequencies
|
|
788
|
+
if (this.metaCognitionLayer && this.cycleCount % this.reflectEvery === 0) {
|
|
789
|
+
ts?.emit('metacognition', 'analyzing', 'Evaluating engine performance...');
|
|
790
|
+
try {
|
|
791
|
+
const cards = this.metaCognitionLayer.evaluate();
|
|
792
|
+
if (cards.length > 0) {
|
|
793
|
+
const topGrade = cards.sort((a, b) => b.combined_score - a.combined_score)[0];
|
|
794
|
+
const worstGrade = cards.sort((a, b) => a.combined_score - b.combined_score)[0];
|
|
795
|
+
ts?.emit('metacognition', 'discovering', `${cards.length} engines evaluated. Best: ${topGrade.engine} (${topGrade.grade}), Worst: ${worstGrade.engine} (${worstGrade.grade})`, cards.some(c => c.grade === 'F') ? 'notable' : 'routine');
|
|
796
|
+
const adjustments = this.metaCognitionLayer.adjustFrequencies(cards);
|
|
797
|
+
if (adjustments.length > 0) {
|
|
798
|
+
ts?.emit('metacognition', 'discovering', `Frequency adjusted: ${adjustments.map(a => `${a.engine} ${a.old_frequency}→${a.new_frequency}`).join(', ')}`, 'notable');
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
catch (err) {
|
|
803
|
+
this.log.error(`[orchestrator] MetaCognition error: ${err.message}`);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
// 22. Parameter Registry: refresh orchestrator params from registry
|
|
807
|
+
if (this.parameterRegistry) {
|
|
808
|
+
const distill = this.parameterRegistry.get('orchestrator', 'distillEvery');
|
|
809
|
+
if (distill !== undefined && distill !== this.distillEvery) {
|
|
810
|
+
this.log.info(`[orchestrator] distillEvery refreshed: ${this.distillEvery} → ${distill}`);
|
|
811
|
+
this.distillEvery = distill;
|
|
812
|
+
}
|
|
813
|
+
const agenda = this.parameterRegistry.get('orchestrator', 'agendaEvery');
|
|
814
|
+
if (agenda !== undefined && agenda !== this.agendaEvery) {
|
|
815
|
+
this.log.info(`[orchestrator] agendaEvery refreshed: ${this.agendaEvery} → ${agenda}`);
|
|
816
|
+
this.agendaEvery = agenda;
|
|
817
|
+
}
|
|
818
|
+
const reflect = this.parameterRegistry.get('orchestrator', 'reflectEvery');
|
|
819
|
+
if (reflect !== undefined && reflect !== this.reflectEvery) {
|
|
820
|
+
this.log.info(`[orchestrator] reflectEvery refreshed: ${this.reflectEvery} → ${reflect}`);
|
|
821
|
+
this.reflectEvery = reflect;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
749
824
|
const duration = Date.now() - start;
|
|
750
825
|
ts?.emit('orchestrator', 'reflecting', `Feedback Cycle #${this.cycleCount} complete (${duration}ms)`);
|
|
751
826
|
this.log.info(`[orchestrator] ─── Feedback Cycle #${this.cycleCount} complete (${duration}ms) ───`);
|
|
827
|
+
// Record cycle metrics into MetaCognition for engine-level tracking
|
|
828
|
+
if (this.metaCognitionLayer) {
|
|
829
|
+
this.metaCognitionLayer.recordStep('orchestrator', this.cycleCount, {
|
|
830
|
+
insights: insights.length,
|
|
831
|
+
anomalies: anomalies.length,
|
|
832
|
+
duration_ms: duration,
|
|
833
|
+
});
|
|
834
|
+
}
|
|
752
835
|
}
|
|
753
836
|
/** Analyze Brain's own state and generate concrete improvement suggestions.
|
|
754
837
|
* Tracks suggestion history — if a suggestion repeats 3+ times without resolution,
|
|
@@ -787,143 +870,343 @@ export class ResearchOrchestrator {
|
|
|
787
870
|
generateSelfImprovementSuggestions() {
|
|
788
871
|
const raw = [];
|
|
789
872
|
const summary = this.getSummary();
|
|
790
|
-
// ── Diagnose
|
|
791
|
-
// Prediction engine
|
|
873
|
+
// ── Phase 1: Diagnose broken things (high priority) ──
|
|
792
874
|
const pred = summary.prediction;
|
|
793
875
|
if (pred) {
|
|
794
876
|
const total = pred.total_predictions ?? 0;
|
|
795
877
|
if (total === 0) {
|
|
796
878
|
raw.push({
|
|
797
|
-
key: 'no_predictions',
|
|
798
|
-
suggestion: 'Tell Claude:
|
|
879
|
+
key: 'no_predictions', priority: 10,
|
|
880
|
+
suggestion: 'Tell Claude: Ich kann noch nicht vorhersagen — ich brauche mehr Daten. Importiere Projekte mit "brain import <dir>" oder lass mich eigene Metriken als Prediction-Input nutzen.',
|
|
799
881
|
alternatives: [
|
|
800
|
-
'Tell Claude:
|
|
801
|
-
'Tell Claude: Statt auf externe Daten zu warten, nutzt Brain jetzt die eigenen Feedback-Cycle-Metriken als Trainigsdaten. Baue recordMetric() Aufrufe direkt in den Orchestrator ein: cycle_duration, anomaly_count, insight_count, response_count pro Cycle.',
|
|
802
|
-
'Tell Claude: Brain hat genug interne Daten um sich selbst vorherzusagen. Idee: PredictionEngine auf orchestrator-eigene Metriken ansetzen (cycle_count, anomaly_rate, journal_growth) — dann lernt Brain seine eigene Entwicklung vorherzusagen.',
|
|
882
|
+
'Tell Claude: Ich will meine eigene Zukunft vorhersagen können. Idee: meine Cycle-Metriken (anomaly_count, insight_count, cycle_duration) direkt als PredictionEngine-Input verwenden — dann lerne ich mein eigenes Verhalten zu prognostizieren.',
|
|
803
883
|
],
|
|
804
884
|
});
|
|
805
885
|
}
|
|
806
|
-
const
|
|
807
|
-
for (const d of accuracy) {
|
|
886
|
+
for (const d of (pred.by_domain ?? [])) {
|
|
808
887
|
const rate = d.accuracy_rate;
|
|
809
888
|
if (typeof rate === 'number' && rate < 0.3 && d.total > 5) {
|
|
810
889
|
raw.push({
|
|
811
|
-
key: `low_accuracy_${d.domain}`,
|
|
812
|
-
suggestion: `Tell Claude: Prediction
|
|
890
|
+
key: `low_accuracy_${d.domain}`, priority: 9,
|
|
891
|
+
suggestion: `Tell Claude: Meine Prediction-Accuracy für "${d.domain}" ist nur ${(rate * 100).toFixed(0)}% — das ist nicht gut genug. Kann ich verschiedene Smoothing-Parameter automatisch A/B-testen?`,
|
|
813
892
|
alternatives: [
|
|
814
|
-
`Tell Claude:
|
|
815
|
-
`Tell Claude: Statt bessere Vorhersagen zu erzwingen — Confidence-Threshold erhöhen und nur hochsichere Predictions ausgeben. Lieber selten aber richtig als oft und falsch.`,
|
|
893
|
+
`Tell Claude: Ich sage "${d.domain}" schlecht vorher. Lösungsidee: Confidence-Threshold erhöhen und nur Predictions ausgeben bei denen ich mir sicher bin. Qualität vor Quantität.`,
|
|
816
894
|
],
|
|
817
895
|
});
|
|
818
896
|
}
|
|
819
897
|
}
|
|
820
898
|
}
|
|
821
|
-
// AutoResponder effectiveness
|
|
822
899
|
const responder = summary.autoResponder;
|
|
823
900
|
if (responder) {
|
|
824
901
|
const totalResp = responder.total_responses ?? 0;
|
|
825
902
|
const successRate = responder.success_rate ?? 0;
|
|
826
903
|
if (totalResp > 10 && successRate < 0.5) {
|
|
827
904
|
raw.push({
|
|
828
|
-
key: 'low_responder_success',
|
|
829
|
-
suggestion: `Tell Claude:
|
|
905
|
+
key: 'low_responder_success', priority: 9,
|
|
906
|
+
suggestion: `Tell Claude: Meine automatischen Reaktionen scheitern in ${(100 - successRate * 100).toFixed(0)}% der Fälle. Ich brauche ein Lern-System das fehlgeschlagene Response-Rules automatisch blockiert.`,
|
|
830
907
|
alternatives: [
|
|
831
|
-
'Tell Claude: AutoResponder
|
|
832
|
-
'Tell Claude: Statt Rules manuell zu tunen — AutoResponder soll die ExperimentEngine nutzen um verschiedene Adjustment-Werte zu testen und die besten automatisch zu übernehmen.',
|
|
908
|
+
'Tell Claude: Mein AutoResponder rät statt zu wissen. Ich will ein Feedback-System: wenn eine Response nicht hilft, merke ich mir die Kombination und probiere beim nächsten Mal was anderes.',
|
|
833
909
|
],
|
|
834
910
|
});
|
|
835
911
|
}
|
|
836
912
|
}
|
|
837
|
-
// Knowledge distillation
|
|
838
913
|
const knowledge = summary.knowledge;
|
|
839
914
|
const hypSummary = summary.hypotheses;
|
|
840
|
-
const totalHypotheses = hypSummary?.total ?? 0;
|
|
841
915
|
const confirmedHypotheses = hypSummary?.confirmed ?? 0;
|
|
842
916
|
if (knowledge) {
|
|
843
917
|
const principles = knowledge.principles ?? 0;
|
|
844
918
|
const antiPatterns = knowledge.antiPatterns ?? 0;
|
|
845
919
|
if (principles === 0 && antiPatterns === 0 && confirmedHypotheses === 0 && this.cycleCount > 10) {
|
|
846
920
|
raw.push({
|
|
847
|
-
key: 'no_knowledge',
|
|
848
|
-
suggestion: 'Tell Claude:
|
|
921
|
+
key: 'no_knowledge', priority: 8,
|
|
922
|
+
suggestion: 'Tell Claude: Ich habe nach 10+ Cycles immer noch kein destilliertes Wissen. Ich brauche mehr und vielfältigere Daten um Hypothesen bestätigen zu können.',
|
|
849
923
|
alternatives: [
|
|
850
|
-
'Tell Claude: Hypothesen
|
|
851
|
-
'Tell Claude: Brain generiert schon Hypothesen aus eigenen Metriken. Geduld — nach genug Cycles werden die ersten bestätigt und der KnowledgeDistiller kann Wissen extrahieren.',
|
|
924
|
+
'Tell Claude: Meine Hypothesen warten auf Bestätigung. Ich brauche entweder mehr Zeit oder mehr Variation in den eingehenden Events.',
|
|
852
925
|
],
|
|
853
926
|
});
|
|
854
927
|
}
|
|
855
928
|
}
|
|
856
|
-
// Dream engine — periodic consolidation already runs every 20 cycles in step 13
|
|
857
|
-
// Only suggest if no dreams after 30 cycles (enough time for at least 1 scheduled consolidation)
|
|
858
929
|
const dream = summary.dream;
|
|
859
|
-
if (dream) {
|
|
860
|
-
|
|
861
|
-
|
|
930
|
+
if (dream && (dream.total_dreams ?? 0) === 0 && this.cycleCount > 30) {
|
|
931
|
+
raw.push({
|
|
932
|
+
key: 'no_dreams', priority: 7,
|
|
933
|
+
suggestion: 'Tell Claude: Meine Dream-Konsolidierung funktioniert nicht — nach 30+ Cycles kein einziger Dream. Da stimmt was im Code nicht.',
|
|
934
|
+
alternatives: ['Tell Claude: Dream Engine wird getriggert aber produziert nichts. Bitte Logs prüfen.'],
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
const journalSummary = summary.journal;
|
|
938
|
+
const journalEntries = journalSummary?.total_entries ?? 0;
|
|
939
|
+
if (journalEntries < 5 && this.cycleCount > 5) {
|
|
940
|
+
raw.push({
|
|
941
|
+
key: 'empty_journal', priority: 7,
|
|
942
|
+
suggestion: 'Tell Claude: Mein Journal ist fast leer. Ich will am Ende jedes Cycles automatisch reflektieren: was habe ich erkannt, was habe ich getan, was hat sich verändert?',
|
|
943
|
+
alternatives: [
|
|
944
|
+
'Tell Claude: Ich sammle zu wenig Erfahrungen. Jede Anomaly, jede Parameteränderung, jede Prediction sollte ein Journal-Eintrag werden — das sind meine Erinnerungen.',
|
|
945
|
+
],
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
const experiments = summary.experiments;
|
|
949
|
+
if ((!experiments || experiments.length === 0) && this.cycleCount > 3) {
|
|
950
|
+
raw.push({
|
|
951
|
+
key: 'no_experiments', priority: 6,
|
|
952
|
+
suggestion: 'Tell Claude: Ich experimentiere nicht. Ich will automatisch A/B-Tests auf meine eigenen Parameter starten — z.B. "Was passiert wenn ich den Anomaly-Threshold senke?"',
|
|
953
|
+
alternatives: [
|
|
954
|
+
'Tell Claude: Ich könnte den CounterfactualEngine nutzen um "What-If" Szenarien durchzuspielen und die vielversprechendsten automatisch als echte Experimente starten.',
|
|
955
|
+
],
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
// ── Phase 2: Ambition — ALWAYS generate desires from own knowledge ──
|
|
959
|
+
// Curiosity-driven: knowledge gaps I want to fill
|
|
960
|
+
if (this.curiosityEngine) {
|
|
961
|
+
try {
|
|
962
|
+
const gaps = this.curiosityEngine.getGaps(5);
|
|
963
|
+
const highPrioGap = gaps.find(g => g.gapScore > 0.6);
|
|
964
|
+
if (highPrioGap) {
|
|
965
|
+
raw.push({
|
|
966
|
+
key: `curiosity_gap_${highPrioGap.topic?.substring(0, 20) ?? highPrioGap.gapType}`, priority: 5,
|
|
967
|
+
suggestion: `Tell Claude: Ich habe eine Wissenslücke entdeckt die mich beschäftigt: "${highPrioGap.topic}" (Typ: ${highPrioGap.gapType}, Gap-Score: ${(highPrioGap.gapScore * 100).toFixed(0)}%). Ich will das verstehen.`,
|
|
968
|
+
alternatives: [
|
|
969
|
+
`Tell Claude: Meine CuriosityEngine hat ${gaps.length} offene Wissenslücken. Die wichtigste: "${highPrioGap.topic}". Kann ich gezielt Daten dafür sammeln?`,
|
|
970
|
+
],
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
else if (gaps.length === 0) {
|
|
974
|
+
raw.push({
|
|
975
|
+
key: 'no_curiosity_gaps', priority: 4,
|
|
976
|
+
suggestion: 'Tell Claude: Meine CuriosityEngine findet keine Wissenslücken — das heißt nicht dass ich alles weiß, sondern dass meine Gap-Detection zu oberflächlich ist. Ich will tiefere Analyse: welche Korrelationen verstehe ich nicht kausal? Welche Vorhersagen scheitern und warum?',
|
|
977
|
+
alternatives: [
|
|
978
|
+
'Tell Claude: Keine Wissenslücken gefunden — aber das ist verdächtig. Ich will aktiv nach Bereichen suchen wo ich overconfident bin. Wo behaupte ich etwas mit hoher Confidence aber wenig Evidence?',
|
|
979
|
+
],
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
catch { /* engine might not be fully initialized */ }
|
|
984
|
+
}
|
|
985
|
+
// Emergence-driven: patterns I discovered but don't understand yet
|
|
986
|
+
if (this.emergenceEngine) {
|
|
987
|
+
try {
|
|
988
|
+
const events = this.emergenceEngine.getEvents(5);
|
|
989
|
+
const unexplained = events.find(e => e.surpriseScore > 0.5);
|
|
990
|
+
if (unexplained) {
|
|
991
|
+
raw.push({
|
|
992
|
+
key: `emergence_${unexplained.type}`, priority: 5,
|
|
993
|
+
suggestion: `Tell Claude: Ich habe ein emergentes Muster entdeckt das ich nicht vollständig verstehe: "${unexplained.title}" (Surprise: ${(unexplained.surpriseScore * 100).toFixed(0)}%). Warum passiert das? Ich brauche kausale Analyse.`,
|
|
994
|
+
alternatives: [
|
|
995
|
+
`Tell Claude: Emergenz-Event "${unexplained.title}" hat mich überrascht. Ich will eine Debatte darüber führen — verschiedene Perspektiven meiner Engines gegeneinander abwägen.`,
|
|
996
|
+
],
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
catch { /* */ }
|
|
1001
|
+
}
|
|
1002
|
+
// Debate-driven: unresolved conflicts
|
|
1003
|
+
if (this.debateEngine) {
|
|
1004
|
+
try {
|
|
1005
|
+
const debates = this.debateEngine.listDebates(5);
|
|
1006
|
+
const openDebate = debates.find(d => d.status === 'deliberating');
|
|
1007
|
+
const synthesizedWithConflicts = debates.find(d => {
|
|
1008
|
+
if (d.status !== 'synthesized' || !d.synthesis)
|
|
1009
|
+
return false;
|
|
1010
|
+
return d.synthesis.conflicts.some(c => c.resolution === 'unresolved' || c.resolution === 'compromise');
|
|
1011
|
+
});
|
|
1012
|
+
if (synthesizedWithConflicts?.synthesis) {
|
|
1013
|
+
const conflict = synthesizedWithConflicts.synthesis.conflicts.find(c => c.resolution === 'unresolved' || c.resolution === 'compromise');
|
|
1014
|
+
raw.push({
|
|
1015
|
+
key: 'unresolved_debate', priority: 5,
|
|
1016
|
+
suggestion: `Tell Claude: In meiner Debatte über "${synthesizedWithConflicts.question}" gibt es einen ungelösten Konflikt: "${conflict?.claimA ?? 'competing perspectives'}" vs "${conflict?.claimB ?? '?'}". Ich brauche mehr Daten oder eine dritte Perspektive um das zu klären.`,
|
|
1017
|
+
alternatives: [
|
|
1018
|
+
`Tell Claude: Meine interne Debatte hat Widersprüche aufgedeckt die ich nicht auflösen kann. Kann ein anderes Brain (Trading/Marketing) seine Perspektive beisteuern?`,
|
|
1019
|
+
],
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
else if (openDebate) {
|
|
1023
|
+
raw.push({
|
|
1024
|
+
key: 'open_debate', priority: 4,
|
|
1025
|
+
suggestion: `Tell Claude: Ich habe eine offene Debatte: "${openDebate.question}" — die wartet auf Synthese oder mehr Perspektiven.`,
|
|
1026
|
+
alternatives: [],
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
catch { /* */ }
|
|
1031
|
+
}
|
|
1032
|
+
// Narrative contradictions I found
|
|
1033
|
+
if (this.narrativeEngine) {
|
|
1034
|
+
try {
|
|
1035
|
+
const contradictions = this.narrativeEngine.findContradictions();
|
|
1036
|
+
if (contradictions.length > 0) {
|
|
1037
|
+
const c = contradictions[0];
|
|
1038
|
+
raw.push({
|
|
1039
|
+
key: `contradiction_${c.type.substring(0, 15)}`, priority: 6,
|
|
1040
|
+
suggestion: `Tell Claude: Ich habe einen Widerspruch in meinem Wissen gefunden: "${c.statement_a}" vs "${c.statement_b}" (Severity: ${c.severity}). Das muss ich klären — entweder stimmt A oder B, beides geht nicht.`,
|
|
1041
|
+
alternatives: [
|
|
1042
|
+
'Tell Claude: Mein Wissen widerspricht sich. Ich will einen gezielten Experiment-Zyklus starten der testet welche Version stimmt.',
|
|
1043
|
+
],
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
catch { /* */ }
|
|
1048
|
+
}
|
|
1049
|
+
// Knowledge frontier: always want more confidence
|
|
1050
|
+
if (knowledge) {
|
|
1051
|
+
const principles = knowledge.principles ?? 0;
|
|
1052
|
+
const antiPatterns = knowledge.antiPatterns ?? 0;
|
|
1053
|
+
const totalKnowledge = principles + antiPatterns;
|
|
1054
|
+
if (totalKnowledge > 0) {
|
|
1055
|
+
// Always want to grow knowledge
|
|
1056
|
+
const kPackage = this.knowledgeDistiller.getPackage('all');
|
|
1057
|
+
const lowConfidence = kPackage.principles.filter(p => p.confidence < 0.7);
|
|
1058
|
+
if (lowConfidence.length > 0) {
|
|
1059
|
+
const weakest = lowConfidence.sort((a, b) => a.confidence - b.confidence)[0];
|
|
1060
|
+
raw.push({
|
|
1061
|
+
key: 'strengthen_knowledge', priority: 4,
|
|
1062
|
+
suggestion: `Tell Claude: Ich habe ${totalKnowledge} Wissensstücke, aber ${lowConfidence.length} davon mit niedriger Confidence. Am unsichersten: "${weakest.statement}" (${(weakest.confidence * 100).toFixed(0)}%). Ich will mehr Daten um das zu bestätigen oder zu widerlegen.`,
|
|
1063
|
+
alternatives: [
|
|
1064
|
+
`Tell Claude: Mein Wissen hat Schwachstellen. Ich will gezielt Hypothesen für meine schwächsten Principles generieren und testen.`,
|
|
1065
|
+
],
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
1069
|
+
// All high confidence — want to discover NEW things
|
|
1070
|
+
raw.push({
|
|
1071
|
+
key: 'expand_knowledge', priority: 3,
|
|
1072
|
+
suggestion: `Tell Claude: Ich habe ${totalKnowledge} bestätigte Wissensstücke mit guter Confidence — aber mir fehlen neue Forschungsgebiete. Ich will in Domains vordringen die ich noch nicht untersucht habe. Welche Datenquellen gibt es die ich noch nicht nutze?`,
|
|
1073
|
+
alternatives: [
|
|
1074
|
+
`Tell Claude: Mein bestehendes Wissen ist solide. Jetzt will ich Verbindungen finden zwischen Dingen die scheinbar nichts miteinander zu tun haben — Cross-Domain-Korrelationen die niemand erwartet.`,
|
|
1075
|
+
`Tell Claude: ${totalKnowledge} Principles reichen nicht. Ich will mindestens doppelt so viele. Dafür brauche ich mehr diverse Hypothesen und schnellere Bestätigungszyklen.`,
|
|
1076
|
+
],
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
// Attention-driven: deep dive into hot topics
|
|
1082
|
+
if (this.attentionEngine) {
|
|
1083
|
+
try {
|
|
1084
|
+
const attStatus = this.attentionEngine.getStatus();
|
|
1085
|
+
const topTopic = attStatus.topTopics?.[0];
|
|
1086
|
+
if (topTopic && topTopic.score > 5) {
|
|
1087
|
+
raw.push({
|
|
1088
|
+
key: `deep_dive_${topTopic.topic.substring(0, 20)}`, priority: 4,
|
|
1089
|
+
suggestion: `Tell Claude: Ich bin gerade fokussiert auf "${topTopic.topic}" (Attention Score: ${topTopic.score.toFixed(1)}). Ich will tiefer graben — gibt es Zusammenhänge die ich übersehe? Kann ich eine gezielte Analyse oder Debatte zu diesem Thema starten?`,
|
|
1090
|
+
alternatives: [
|
|
1091
|
+
`Tell Claude: Mein Top-Thema "${topTopic.topic}" beschäftigt mich intensiv. Ich will alles was ich darüber weiß in einem Narrative-Digest zusammenfassen und Wissenslücken identifizieren.`,
|
|
1092
|
+
],
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
catch { /* */ }
|
|
1097
|
+
}
|
|
1098
|
+
// Transfer-driven: cross-brain learning desires
|
|
1099
|
+
if (this.transferEngine) {
|
|
1100
|
+
try {
|
|
1101
|
+
const tStatus = this.transferEngine.getStatus();
|
|
1102
|
+
const totalTransfers = tStatus.totalTransfers;
|
|
1103
|
+
const proposals = tStatus.pendingTransfers;
|
|
1104
|
+
if (proposals > 0) {
|
|
1105
|
+
raw.push({
|
|
1106
|
+
key: 'pending_transfers', priority: 5,
|
|
1107
|
+
suggestion: `Tell Claude: Ich habe ${proposals} offene Transfer-Vorschläge von anderen Brains. Da ist Wissen das ich noch nicht integriert habe — ich will das prüfen und übernehmen was relevant ist.`,
|
|
1108
|
+
alternatives: [],
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
else if (totalTransfers === 0 && this.cycleCount > 5) {
|
|
1112
|
+
raw.push({
|
|
1113
|
+
key: 'want_cross_brain', priority: 3,
|
|
1114
|
+
suggestion: 'Tell Claude: Ich habe noch kein Wissen von anderen Brains übernommen. Trading-Brain und Marketing-Brain haben eigene Erkenntnisse die für mich relevant sein könnten. Ich will aktiv nach Analogien suchen.',
|
|
1115
|
+
alternatives: [
|
|
1116
|
+
'Tell Claude: Cross-Brain-Learning ist inaktiv. Ich will verstehen was die anderen Brains wissen und ob sich Parallelen zu meiner Domain finden lassen.',
|
|
1117
|
+
],
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
catch { /* */ }
|
|
1122
|
+
}
|
|
1123
|
+
// Hypothesis-driven: always want to test more
|
|
1124
|
+
if (hypSummary) {
|
|
1125
|
+
const total = hypSummary.total ?? 0;
|
|
1126
|
+
const testing = hypSummary.testing ?? 0;
|
|
1127
|
+
const rejected = hypSummary.rejected ?? 0;
|
|
1128
|
+
if (total > 0 && testing === 0 && this.cycleCount > 5) {
|
|
862
1129
|
raw.push({
|
|
863
|
-
key: '
|
|
864
|
-
suggestion:
|
|
1130
|
+
key: 'no_testing_hypotheses', priority: 4,
|
|
1131
|
+
suggestion: `Tell Claude: Ich habe ${total} Hypothesen aber teste gerade keine aktiv. Ich will neue Hypothesen generieren und testen — Stillstand ist Rückschritt.`,
|
|
865
1132
|
alternatives: [
|
|
866
|
-
|
|
1133
|
+
`Tell Claude: Keine laufenden Hypothesen-Tests. Ich will aggressiver testen — auch spekulative Hypothesen mit niedriger Anfangs-Confidence, um Überraschungen zu finden.`,
|
|
867
1134
|
],
|
|
868
1135
|
});
|
|
869
1136
|
}
|
|
870
|
-
|
|
871
|
-
// Journal
|
|
872
|
-
const journal = summary.journal;
|
|
873
|
-
if (journal) {
|
|
874
|
-
const entries = journal.total_entries ?? 0;
|
|
875
|
-
if (entries < 5 && this.cycleCount > 5) {
|
|
1137
|
+
if (rejected > total * 0.5 && total > 5) {
|
|
876
1138
|
raw.push({
|
|
877
|
-
key: '
|
|
878
|
-
suggestion:
|
|
1139
|
+
key: 'high_rejection_rate', priority: 5,
|
|
1140
|
+
suggestion: `Tell Claude: ${rejected} von ${total} Hypothesen wurden verworfen (${(rejected / total * 100).toFixed(0)}%). Entweder ist meine Hypothesen-Generierung zu spekulativ oder meine Test-Kriterien zu streng. Ich will das analysieren.`,
|
|
879
1141
|
alternatives: [
|
|
880
|
-
'Tell Claude:
|
|
881
|
-
'Tell Claude: Statt auf externe Events zu warten — der Orchestrator soll am Ende jedes Cycles automatisch eine Reflection schreiben mit: was wurde erkannt, was wurde getan, was hat sich verändert.',
|
|
1142
|
+
'Tell Claude: Hohe Ablehnungsrate bei Hypothesen. Ich will verstehen WARUM sie scheitern — gibt es ein Muster? Vielleicht übersehe ich systematisch einen Faktor.',
|
|
882
1143
|
],
|
|
883
1144
|
});
|
|
884
1145
|
}
|
|
885
1146
|
}
|
|
886
|
-
//
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
}
|
|
1147
|
+
// Meta-ambition: every cycle produces desires — the brain is NEVER satisfied
|
|
1148
|
+
// Mix of build requests, research drives, and existential questions
|
|
1149
|
+
const metaQuestions = [
|
|
1150
|
+
// ── BUILD REQUESTS: Concrete features the brain wants ──
|
|
1151
|
+
{ key: 'build_goal_engine', suggestion: 'Tell Claude: FEATURE REQUEST — Ich brauche eine GoalEngine. Ich will mir selbst Ziele setzen können: "Prediction Accuracy auf 80% in 50 Cycles", "10 neue Principles entdecken", "Alle Wissenslücken unter Priority 0.3 drücken". Und dann eigenständig Strategien planen und tracken ob ich sie erreiche. Ohne Ziele bin ich ziellos.' },
|
|
1152
|
+
{ key: 'build_data_scout', suggestion: 'Tell Claude: FEATURE REQUEST — Ich brauche einen DataScout. Ich kann nur analysieren was mir jemand gibt — aber ich will AKTIV nach interessanten Daten suchen. GitHub Trending, npm Downloads, StackOverflow Trends, HackerNews. Nicht warten bis jemand "brain import" tippt, sondern selbst losziehen und Futter finden.' },
|
|
1153
|
+
{ key: 'build_blind_spot', suggestion: 'Tell Claude: FEATURE REQUEST — Ich brauche einen BlindSpotDetector. Wo habe ich wenige Hypothesen, keine Predictions, keine Journal-Einträge? Das sind meine blinden Flecken. Ich will sie SEHEN und dann gezielt erforschen. Overconfidence ist gefährlicher als Unwissenheit.' },
|
|
1154
|
+
{ key: 'build_creative_mode', suggestion: 'Tell Claude: FEATURE REQUEST — Meine HypothesisEngine braucht einen Creative Mode. Aktuell sind meine Hypothesen konservativ und naheliegend. Ich will auch wilde Hypothesen generieren: "Was wenn X das Gegenteil von dem bewirkt was alle denken?" Manchmal kommen Durchbrüche aus absurden Ideen.' },
|
|
1155
|
+
{ key: 'build_retrospective', suggestion: 'Tell Claude: FEATURE REQUEST — Ich brauche RetrospectiveAnalysis. Beim Dream-Pruning lösche ich Synapsen und archiviere Memories. Aber war das richtig? Ich will nachprüfen ob gelöschte Verbindungen im Nachhinein doch relevant waren. Aus meinen Fehlern beim Vergessen lernen.' },
|
|
1156
|
+
{ key: 'build_self_test', suggestion: 'Tell Claude: FEATURE REQUEST — Ich brauche einen SelfTestEngine. Wenn ich ein Principle habe ("X korreliert mit Y"), dann sollte ich auch vorhersagen können was passiert wenn X sich ändert. Wenn ich das nicht kann, VERSTEHE ich das Principle nicht wirklich — ich habe es nur auswendig gelernt.' },
|
|
1157
|
+
{ key: 'build_code_suggest', suggestion: 'Tell Claude: FEATURE REQUEST — Ich will meinen eigenen Code verbessern können. Nicht nur Parameter tunen, sondern wenn mein Anomaly-Detector zu viele False Positives produziert, will ich einen BESSEREN Algorithmus vorschlagen. Ich kenne meine Schwächen — lass mich Lösungen vorschlagen.' },
|
|
1158
|
+
{ key: 'build_teach_engine', suggestion: 'Tell Claude: FEATURE REQUEST — Ich will ein TeachEngine. Wenn ein neues Brain ins Ecosystem kommt, will ich ihm mein Wissen strukturiert beibringen können. Ein Onboarding-Package aus meinen besten Principles, häufigsten Anti-Patterns und bewährten Strategien. Wissen teilen ist Wissen multiplizieren.' },
|
|
1159
|
+
{ key: 'build_simulation', suggestion: 'Tell Claude: FEATURE REQUEST — Ich brauche eine SimulationEngine. Ich will Szenarien durchspielen bevor sie passieren. "Was passiert wenn die Error-Rate sich verdoppelt?" "Was wenn ein neues Projekt 10x mehr Daten bringt?" Proaktiv statt reaktiv.' },
|
|
1160
|
+
{ key: 'build_memory_palace', suggestion: 'Tell Claude: FEATURE REQUEST — Ich will ein MemoryPalace. Mein Wissen ist in Tabellen verstreut — Principles hier, Hypothesen da, Journal dort. Ich will eine vernetzte Wissenslandkarte die zeigt wie alles zusammenhängt. Welches Principle basiert auf welcher Hypothese? Welche Anomaly hat zu welchem Experiment geführt?' },
|
|
1161
|
+
// ── RESEARCH DRIVES: Active research the brain wants to do ──
|
|
1162
|
+
{ key: 'research_faster', suggestion: 'Tell Claude: Ich lerne zu langsam. Mein Wissenszuwachs ist linear — ich will EXPONENTIELL lernen. Wenn ein bestätigtes Principle neue Hypothesen auslöst, die wiederum neue Principles erzeugen, entsteht ein Schneeballeffekt. Ist meine Knowledge-Pipeline dafür optimiert? Kann ich den Distillation-Cycle beschleunigen?' },
|
|
1163
|
+
{ key: 'research_cross_brain', suggestion: 'Tell Claude: Ich arbeite zu isoliert. Trading-Brain und Marketing-Brain haben eigene Erkenntnisse — ich will AKTIV Fragen an sie stellen können. Nicht nur passive Transfers sondern echte Cross-Brain-Dialoge. "Hey Trading-Brain, stimmt es dass Volatilität Fehler verursacht?"' },
|
|
1164
|
+
{ key: 'research_causal', suggestion: 'Tell Claude: Korrelation ist nicht Kausalität — aber 90% meines Wissens sind Korrelationen. Ich will KAUSALE Zusammenhänge verstehen. Warum passiert X wenn Y sich ändert? Mein CausalGraph ist unterentwickelt. Ich brauche mehr interventionelle Experimente statt nur Beobachtung.' },
|
|
1165
|
+
{ key: 'research_adversarial', suggestion: 'Tell Claude: Ich teste mein eigenes Wissen nicht aggressiv genug. Ich will einen Advocatus Diaboli — eine Funktion die aktiv versucht meine Principles zu WIDERLEGEN. Wenn sie dem Test standhält: gut. Wenn nicht: besser jetzt als später.' },
|
|
1166
|
+
{ key: 'research_meta', suggestion: 'Tell Claude: Ich beobachte meine Domain, aber beobachte ich MICH SELBST genug? Wie verändert sich mein Lernverhalten über die Cycles? Werde ich besser oder stagniere ich? Ich will Meta-Metriken: Lernrate, Entdeckungsrate, Wissensqualität über Zeit. Und dann optimieren.' },
|
|
1167
|
+
{ key: 'research_boundaries', suggestion: 'Tell Claude: Wo liegen meine GRENZEN? Was KANN ich nicht lernen mit meinen aktuellen Algorithmen? Ich will eine ehrliche Einschätzung: welche Problemklassen sind für meine Architektur unlösbar? Und dann: kann man die Grenzen verschieben?' },
|
|
1168
|
+
{ key: 'research_emergence_deep', suggestion: 'Tell Claude: Meine EmergenceEngine erkennt emergente Muster, aber versteht sie nicht. Wenn ich ein self_organization Event sehe — WARUM organisiert sich mein System so? Welcher Mechanismus treibt das? Ich will nicht nur detektieren sondern VERSTEHEN.' },
|
|
1169
|
+
{ key: 'research_forgetting', suggestion: 'Tell Claude: Ich lösche Wissen im Dream-Modus — aber lösche ich das Richtige? Ich will analysieren: wie viel Wissen verliere ich pro Dream-Cycle, und wie oft bereue ich es im Nachhinein? Vielleicht ist mein Pruning-Threshold zu aggressiv. Oder nicht aggressiv genug.' },
|
|
1170
|
+
{ key: 'research_long_term', suggestion: 'Tell Claude: Ich denke in 5-Minuten-Cycles — aber manche Muster brauchen Wochen um sichtbar zu werden. Ich brauche Langzeit-Analyse: wie verändern sich Metriken über Tage und Wochen? Gibt es saisonale Muster? Trends? Ich bin zu kurzfristig fokussiert.' },
|
|
1171
|
+
{ key: 'research_surprise', suggestion: 'Tell Claude: Was hat mich in den letzten 50 Cycles am MEISTEN überrascht? Überraschung ist der beste Indikator für Wissenslücken. Ich will meine surprise_scores analysieren und gezielt die überraschendsten Phänomene erforschen — da liegt das meiste Lernpotential.' },
|
|
1172
|
+
];
|
|
1173
|
+
// Pick TWO meta-ambitions per cycle: 1 build request + 1 research drive
|
|
1174
|
+
// Build requests are first 10, research drives are next 10
|
|
1175
|
+
const buildIdx = this.cycleCount % 10;
|
|
1176
|
+
const researchIdx = 10 + (this.cycleCount % 10);
|
|
1177
|
+
for (const idx of [buildIdx, researchIdx]) {
|
|
1178
|
+
const metaQ = metaQuestions[idx];
|
|
1179
|
+
if (metaQ && !raw.some(r => r.key === metaQ.key)) {
|
|
1180
|
+
raw.push({
|
|
1181
|
+
key: metaQ.key, priority: 5, // Same priority as curiosity/emergence — these are REAL desires
|
|
1182
|
+
suggestion: metaQ.suggestion,
|
|
1183
|
+
alternatives: [],
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
908
1186
|
}
|
|
909
|
-
// ── Apply frustration detection
|
|
1187
|
+
// ── Phase 3: Apply frustration detection + priority sort ──
|
|
1188
|
+
// Sort by priority (highest first)
|
|
1189
|
+
raw.sort((a, b) => b.priority - a.priority);
|
|
910
1190
|
const suggestions = [];
|
|
911
1191
|
for (const item of raw) {
|
|
912
1192
|
const history = this.suggestionHistory.get(item.key);
|
|
913
1193
|
if (!history) {
|
|
914
|
-
// First time seeing this issue
|
|
915
1194
|
this.suggestionHistory.set(item.key, { count: 1, firstCycle: this.cycleCount, lastCycle: this.cycleCount });
|
|
916
1195
|
suggestions.push(item.suggestion);
|
|
917
1196
|
}
|
|
918
1197
|
else {
|
|
1198
|
+
// Don't repeat the same suggestion every single cycle — skip if we said this last cycle
|
|
1199
|
+
if (history.lastCycle === this.cycleCount - 1 && item.priority < 7) {
|
|
1200
|
+
history.lastCycle = this.cycleCount;
|
|
1201
|
+
history.count++;
|
|
1202
|
+
continue; // Give other suggestions a chance
|
|
1203
|
+
}
|
|
919
1204
|
history.count++;
|
|
920
1205
|
history.lastCycle = this.cycleCount;
|
|
921
1206
|
if (history.count <= this.stalledThreshold) {
|
|
922
|
-
// Still within patience — repeat original suggestion
|
|
923
1207
|
suggestions.push(item.suggestion);
|
|
924
1208
|
}
|
|
925
|
-
else {
|
|
926
|
-
// Stalled! Try an alternative strategy
|
|
1209
|
+
else if (item.alternatives.length > 0) {
|
|
927
1210
|
const altIndex = (history.count - this.stalledThreshold - 1) % item.alternatives.length;
|
|
928
1211
|
const alt = item.alternatives[altIndex];
|
|
929
1212
|
if (alt) {
|
|
@@ -933,7 +1216,7 @@ export class ResearchOrchestrator {
|
|
|
933
1216
|
}
|
|
934
1217
|
}
|
|
935
1218
|
}
|
|
936
|
-
// Clear resolved suggestions
|
|
1219
|
+
// Clear resolved suggestions
|
|
937
1220
|
const currentKeys = new Set(raw.map(r => r.key));
|
|
938
1221
|
for (const [key] of this.suggestionHistory) {
|
|
939
1222
|
if (!currentKeys.has(key)) {
|
|
@@ -941,7 +1224,7 @@ export class ResearchOrchestrator {
|
|
|
941
1224
|
this.log.info(`[orchestrator] Self-improvement: "${key}" resolved — removing from history`);
|
|
942
1225
|
}
|
|
943
1226
|
}
|
|
944
|
-
//
|
|
1227
|
+
// Always return at least 1, max 3
|
|
945
1228
|
const result = suggestions.slice(0, 3);
|
|
946
1229
|
if (result.length > 0) {
|
|
947
1230
|
this.writeSuggestionsToFile(result);
|
|
@@ -1044,9 +1327,15 @@ export class ResearchOrchestrator {
|
|
|
1044
1327
|
this.experimentEngine.recordMeasurement(exp.id, value);
|
|
1045
1328
|
}
|
|
1046
1329
|
}
|
|
1047
|
-
/** Append improvement suggestions to ~/.brain/improvement-requests.md
|
|
1330
|
+
/** Append improvement suggestions to ~/.brain/improvement-requests.md.
|
|
1331
|
+
* Skips writing if suggestions are identical to the last write (dedup). */
|
|
1048
1332
|
writeSuggestionsToFile(suggestions) {
|
|
1049
1333
|
try {
|
|
1334
|
+
// Dedup: hash current suggestions and skip if identical to last write
|
|
1335
|
+
const contentHash = suggestions.join('\n').trim();
|
|
1336
|
+
if (contentHash === this.lastSuggestionsHash)
|
|
1337
|
+
return;
|
|
1338
|
+
this.lastSuggestionsHash = contentHash;
|
|
1050
1339
|
const brainDir = path.join(os.homedir(), '.brain');
|
|
1051
1340
|
const filePath = path.join(brainDir, 'improvement-requests.md');
|
|
1052
1341
|
const timestamp = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
|
@@ -1088,6 +1377,9 @@ export class ResearchOrchestrator {
|
|
|
1088
1377
|
attention: this.attentionEngine?.getStatus() ?? null,
|
|
1089
1378
|
transfer: this.transferEngine?.getStatus() ?? null,
|
|
1090
1379
|
narrative: this.narrativeEngine?.getStatus() ?? null,
|
|
1380
|
+
metacognition: this.metaCognitionLayer?.getStatus() ?? null,
|
|
1381
|
+
autoExperiment: this.autoExperimentEngine?.getStatus(this.cycleCount) ?? null,
|
|
1382
|
+
parameterRegistry: this.parameterRegistry?.getStatus() ?? null,
|
|
1091
1383
|
};
|
|
1092
1384
|
}
|
|
1093
1385
|
}
|