@timmeck/brain-core 2.34.1 → 2.35.1
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/concept-abstraction/concept-abstraction.d.ts +139 -0
- package/dist/concept-abstraction/concept-abstraction.js +534 -0
- package/dist/concept-abstraction/concept-abstraction.js.map +1 -0
- package/dist/concept-abstraction/index.d.ts +2 -0
- package/dist/concept-abstraction/index.js +2 -0
- package/dist/concept-abstraction/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/memory-palace/memory-palace.d.ts +2 -2
- package/dist/memory-palace/memory-palace.js.map +1 -1
- package/dist/research/bootstrap-service.js +48 -34
- package/dist/research/bootstrap-service.js.map +1 -1
- package/dist/research/research-orchestrator.d.ts +5 -0
- package/dist/research/research-orchestrator.js +201 -4
- package/dist/research/research-orchestrator.js.map +1 -1
- package/package.json +1 -1
|
@@ -55,6 +55,8 @@ export class ResearchOrchestrator {
|
|
|
55
55
|
selfScanner = null;
|
|
56
56
|
selfModificationEngine = null;
|
|
57
57
|
bootstrapService = null;
|
|
58
|
+
conceptAbstraction = null;
|
|
59
|
+
db;
|
|
58
60
|
brainName;
|
|
59
61
|
feedbackTimer = null;
|
|
60
62
|
cycleCount = 0;
|
|
@@ -69,6 +71,7 @@ export class ResearchOrchestrator {
|
|
|
69
71
|
/** Hash of last written suggestions to prevent duplicate file writes. */
|
|
70
72
|
lastSuggestionsHash = '';
|
|
71
73
|
constructor(db, config, causalGraph) {
|
|
74
|
+
this.db = db;
|
|
72
75
|
this.brainName = config.brainName;
|
|
73
76
|
this.distillEvery = config.distillEvery ?? 5;
|
|
74
77
|
this.agendaEvery = config.agendaEvery ?? 3;
|
|
@@ -86,7 +89,7 @@ export class ResearchOrchestrator {
|
|
|
86
89
|
this.autoResponder = new AutoResponder(db, { brainName: config.brainName });
|
|
87
90
|
this.autoResponder.setAdaptiveStrategy(this.adaptiveStrategy);
|
|
88
91
|
this.autoResponder.setJournal(this.journal);
|
|
89
|
-
this.hypothesisEngine = new HypothesisEngine(db, { minEvidence:
|
|
92
|
+
this.hypothesisEngine = new HypothesisEngine(db, { minEvidence: 3, confirmThreshold: 0.05, rejectThreshold: 0.5 });
|
|
90
93
|
}
|
|
91
94
|
/** Set the DataMiner instance for DB-driven engine feeding. */
|
|
92
95
|
setDataMiner(miner) {
|
|
@@ -124,6 +127,8 @@ export class ResearchOrchestrator {
|
|
|
124
127
|
/** Set the TransferEngine — cross-domain knowledge transfer. */
|
|
125
128
|
setTransferEngine(engine) {
|
|
126
129
|
this.transferEngine = engine;
|
|
130
|
+
// Register own distiller as peer for self-analysis and transfer proposals
|
|
131
|
+
engine.registerPeerDistiller(this.brainName + '_self', this.knowledgeDistiller);
|
|
127
132
|
}
|
|
128
133
|
/** Set the NarrativeEngine — brain explains itself in natural language. */
|
|
129
134
|
setNarrativeEngine(engine) {
|
|
@@ -175,6 +180,8 @@ export class ResearchOrchestrator {
|
|
|
175
180
|
setSelfModificationEngine(engine) { this.selfModificationEngine = engine; }
|
|
176
181
|
/** Set the BootstrapService — seeds initial data on first cycle. */
|
|
177
182
|
setBootstrapService(service) { this.bootstrapService = service; }
|
|
183
|
+
/** Set the ConceptAbstraction — clusters knowledge into abstract concepts. */
|
|
184
|
+
setConceptAbstraction(engine) { this.conceptAbstraction = engine; }
|
|
178
185
|
/** Set the PredictionEngine — wires journal into it. */
|
|
179
186
|
setPredictionEngine(engine) {
|
|
180
187
|
this.predictionEngine = engine;
|
|
@@ -350,6 +357,73 @@ export class ResearchOrchestrator {
|
|
|
350
357
|
this.hypothesisEngine.observe({ source: this.brainName, type: `anomaly:${a.metric}`, value: a.deviation, timestamp: now, metadata: { severity: a.severity } });
|
|
351
358
|
}
|
|
352
359
|
}
|
|
360
|
+
// 2e. Accumulate evidence for hypotheses based on cycle observations
|
|
361
|
+
{
|
|
362
|
+
const pendingHypotheses = this.hypothesisEngine.list('proposed', 50)
|
|
363
|
+
.concat(this.hypothesisEngine.list('testing', 50));
|
|
364
|
+
for (const hyp of pendingHypotheses) {
|
|
365
|
+
if (!hyp.id)
|
|
366
|
+
continue;
|
|
367
|
+
const vars = hyp.variables ?? [];
|
|
368
|
+
const statement = hyp.statement.toLowerCase();
|
|
369
|
+
let evidenceType = null;
|
|
370
|
+
let reason = '';
|
|
371
|
+
// Check if cycle metrics match hypothesis variables
|
|
372
|
+
if (vars.includes('journal_entries') || statement.includes('journal')) {
|
|
373
|
+
const journalStats = this.journal.getSummary();
|
|
374
|
+
const entries = journalStats.total_entries ?? 0;
|
|
375
|
+
if (entries > this.cycleCount) {
|
|
376
|
+
evidenceType = 'for';
|
|
377
|
+
reason = `journal_entries=${entries} growing (cycle ${this.cycleCount})`;
|
|
378
|
+
}
|
|
379
|
+
else if (this.cycleCount > 5 && entries < 3) {
|
|
380
|
+
evidenceType = 'against';
|
|
381
|
+
reason = `journal_entries=${entries} stagnant after ${this.cycleCount} cycles`;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else if (vars.includes('anomaly_count') || statement.includes('anomal')) {
|
|
385
|
+
if (anomalies.length > 0) {
|
|
386
|
+
evidenceType = 'for';
|
|
387
|
+
reason = `${anomalies.length} anomalies detected this cycle`;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (vars.includes('insight_count') || vars.includes('observation_type_count') || statement.includes('observation')) {
|
|
391
|
+
if (insights.length > 0) {
|
|
392
|
+
evidenceType = 'for';
|
|
393
|
+
reason = `${insights.length} insights from observations this cycle`;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else if (statement.includes('dream') || statement.includes('memor')) {
|
|
397
|
+
// Dream-related: check if dream engine produced output
|
|
398
|
+
if (this.dreamEngine) {
|
|
399
|
+
const dStatus = this.dreamEngine.getStatus();
|
|
400
|
+
const totals = dStatus.totals;
|
|
401
|
+
if ((totals?.memoriesConsolidated ?? 0) > 0) {
|
|
402
|
+
evidenceType = 'for';
|
|
403
|
+
reason = `dream consolidated ${totals?.memoriesConsolidated} memories`;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
else if (statement.includes('attention') || statement.includes('focus')) {
|
|
408
|
+
if (this.attentionEngine) {
|
|
409
|
+
const topTopics = this.attentionEngine.getTopTopics(1);
|
|
410
|
+
if (topTopics.length > 0) {
|
|
411
|
+
evidenceType = 'for';
|
|
412
|
+
reason = `attention active: top topic "${topTopics[0].topic}" (score=${topTopics[0].score.toFixed(1)})`;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (evidenceType && hyp.id) {
|
|
417
|
+
try {
|
|
418
|
+
const col = evidenceType === 'for' ? 'evidence_for' : 'evidence_against';
|
|
419
|
+
this.db.prepare(`UPDATE hypotheses SET ${col} = ${col} + 1 WHERE id = ?`).run(hyp.id);
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
// Hypothesis table might not have these columns yet — skip
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
353
427
|
// 2d. Attention Engine: decay scores, compute engine weights, persist focus
|
|
354
428
|
if (this.attentionEngine) {
|
|
355
429
|
ts?.emit('attention', 'focusing', 'Updating attention scores and engine weights...');
|
|
@@ -497,18 +571,45 @@ export class ResearchOrchestrator {
|
|
|
497
571
|
this.journal.reflect();
|
|
498
572
|
ts?.emit('journal', 'reflecting', 'Reflection complete', 'notable');
|
|
499
573
|
}
|
|
500
|
-
// 8b. Cycle-end journal entry — guarantees journal grows every cycle
|
|
574
|
+
// 8b. Cycle-end journal entry — guarantees journal grows every cycle (enriched with engine state)
|
|
501
575
|
{
|
|
502
576
|
const cycleDuration = Date.now() - start;
|
|
503
577
|
const journalStats = this.journal.getSummary();
|
|
578
|
+
const hypSummary = this.hypothesisEngine.getSummary();
|
|
579
|
+
const predAccuracy = (() => {
|
|
580
|
+
try {
|
|
581
|
+
const predSummary = this.predictionEngine?.getSummary();
|
|
582
|
+
const domains = (predSummary?.by_domain ?? []);
|
|
583
|
+
if (domains.length > 0)
|
|
584
|
+
return Math.round((domains[0]?.accuracy_rate ?? 0) * 100);
|
|
585
|
+
}
|
|
586
|
+
catch { /* */ }
|
|
587
|
+
return 0;
|
|
588
|
+
})();
|
|
589
|
+
const attTopics = (() => {
|
|
590
|
+
try {
|
|
591
|
+
return this.attentionEngine?.getTopTopics?.(3) ?? [];
|
|
592
|
+
}
|
|
593
|
+
catch {
|
|
594
|
+
return [];
|
|
595
|
+
}
|
|
596
|
+
})();
|
|
597
|
+
const focusStr = attTopics.length > 0
|
|
598
|
+
? attTopics.map((t) => t.topic).join(', ')
|
|
599
|
+
: 'none';
|
|
504
600
|
this.journal.write({
|
|
505
601
|
type: 'insight',
|
|
506
602
|
title: `Cycle #${this.cycleCount} summary`,
|
|
507
|
-
content: `Completed feedback cycle #${this.cycleCount} in ${cycleDuration}ms. ${insights.length} insights, ${anomalies.length} anomalies detected.
|
|
603
|
+
content: `Completed feedback cycle #${this.cycleCount} in ${cycleDuration}ms. ${insights.length} insights, ${anomalies.length} anomalies detected. Hypotheses: ${hypSummary.proposed} pending, ${hypSummary.confirmed} confirmed. Predictions: accuracy ${predAccuracy}%. Focus: ${focusStr}. Journal: ${journalStats.total_entries ?? 0} entries.`,
|
|
508
604
|
tags: [this.brainName, 'cycle-summary'],
|
|
509
605
|
references: [],
|
|
510
606
|
significance: 'routine',
|
|
511
|
-
data: {
|
|
607
|
+
data: {
|
|
608
|
+
cycle: this.cycleCount, duration_ms: cycleDuration,
|
|
609
|
+
insights: insights.length, anomalies: anomalies.length,
|
|
610
|
+
hypotheses_confirmed: hypSummary.confirmed, hypotheses_total: hypSummary.total,
|
|
611
|
+
prediction_accuracy: predAccuracy, focus: focusStr,
|
|
612
|
+
},
|
|
512
613
|
});
|
|
513
614
|
}
|
|
514
615
|
// 9. Prediction Engine: resolve pending + auto-predict
|
|
@@ -551,6 +652,15 @@ export class ResearchOrchestrator {
|
|
|
551
652
|
if (this.autoExperimentEngine && this.cycleCount > 3 && this.cycleCount % 5 === 0) {
|
|
552
653
|
ts?.emit('auto_experiment', 'experimenting', 'Processing auto-experiments...');
|
|
553
654
|
try {
|
|
655
|
+
// Ensure MetaCognition has fresh report cards before AutoExperiment discovers candidates
|
|
656
|
+
if (this.metaCognitionLayer) {
|
|
657
|
+
try {
|
|
658
|
+
this.metaCognitionLayer.evaluate();
|
|
659
|
+
}
|
|
660
|
+
catch (mcErr) {
|
|
661
|
+
this.log.warn(`[orchestrator] MetaCog pre-eval for AutoExp: ${mcErr.message}`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
554
664
|
// Feed measurements
|
|
555
665
|
this.autoExperimentEngine.feedMeasurement('insight_count', insights.length);
|
|
556
666
|
this.autoExperimentEngine.feedMeasurement('anomaly_count', anomalies.length);
|
|
@@ -584,6 +694,28 @@ export class ResearchOrchestrator {
|
|
|
584
694
|
}
|
|
585
695
|
// 13. Periodic Dream Consolidation: don't wait for idle, consolidate every 10 cycles
|
|
586
696
|
if (this.dreamEngine && this.cycleCount % 10 === 0) {
|
|
697
|
+
ts?.emit('dream', 'dreaming', 'Feeding knowledge into memories for consolidation...');
|
|
698
|
+
try {
|
|
699
|
+
// Feed current knowledge into memories table so consolidation has material
|
|
700
|
+
const principles = this.knowledgeDistiller.getPrinciples(undefined, 50);
|
|
701
|
+
const journalEntries = this.journal.search('', 30);
|
|
702
|
+
const insertMemory = this.db.prepare(`
|
|
703
|
+
INSERT OR IGNORE INTO memories (category, key, content, importance, source, tags, active)
|
|
704
|
+
VALUES (?, ?, ?, ?, 'orchestrator_feed', ?, 1)
|
|
705
|
+
`);
|
|
706
|
+
for (const p of principles) {
|
|
707
|
+
insertMemory.run('principle', `principle:${p.id ?? p.statement.substring(0, 50)}`, p.statement, Math.min(1, (p.confidence ?? 0.5) + 0.3), JSON.stringify(['principle', this.brainName]));
|
|
708
|
+
}
|
|
709
|
+
for (const j of journalEntries) {
|
|
710
|
+
if (j.significance === 'breakthrough' || j.significance === 'notable') {
|
|
711
|
+
insertMemory.run('journal', `journal:${j.id ?? j.title.substring(0, 50)}`, `${j.title}: ${j.content?.substring(0, 200) ?? ''}`, j.significance === 'breakthrough' ? 0.9 : 0.6, JSON.stringify(['journal', j.type, this.brainName]));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
ts?.emit('dream', 'dreaming', `Fed ${principles.length} principles + ${journalEntries.filter(j => j.significance === 'breakthrough' || j.significance === 'notable').length} journal entries into memories`);
|
|
715
|
+
}
|
|
716
|
+
catch (feedErr) {
|
|
717
|
+
this.log.warn(`[orchestrator] Dream memory feed error: ${feedErr.message}`);
|
|
718
|
+
}
|
|
587
719
|
ts?.emit('dream', 'dreaming', 'Scheduled consolidation starting (every 10 cycles)...');
|
|
588
720
|
try {
|
|
589
721
|
this.dreamEngine.consolidate('auto');
|
|
@@ -867,6 +999,29 @@ export class ResearchOrchestrator {
|
|
|
867
999
|
this.log.error(`[orchestrator] MetaCognition error: ${err.message}`);
|
|
868
1000
|
}
|
|
869
1001
|
}
|
|
1002
|
+
// 21b. Adaptive Strategy: adjust parameters for poorly performing engines
|
|
1003
|
+
if (this.metaCognitionLayer && this.cycleCount % this.reflectEvery === 0) {
|
|
1004
|
+
try {
|
|
1005
|
+
const cards = this.metaCognitionLayer.getLatestReportCards();
|
|
1006
|
+
const poorCards = cards.filter(c => c.grade === 'D' || c.grade === 'F');
|
|
1007
|
+
for (const card of poorCards.slice(0, 3)) {
|
|
1008
|
+
// Try adapting the engine's research strategy parameters
|
|
1009
|
+
const strategyDomains = ['research', 'learning'];
|
|
1010
|
+
for (const domain of strategyDomains) {
|
|
1011
|
+
const currentVal = this.adaptiveStrategy.getParam(domain, card.engine);
|
|
1012
|
+
if (currentVal !== null) {
|
|
1013
|
+
const direction = card.grade === 'F' ? 0.2 : 0.1;
|
|
1014
|
+
this.adaptiveStrategy.adapt(domain, card.engine, currentVal * (1 + direction), `MetaCog grade ${card.grade} — boosting ${card.engine}`, { reportCard: card });
|
|
1015
|
+
ts?.emit('adaptive_strategy', 'discovering', `Adapted ${domain}.${card.engine}: grade ${card.grade} → boost ${(direction * 100).toFixed(0)}%`, 'routine');
|
|
1016
|
+
break; // Only adapt one domain per engine
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
catch (err) {
|
|
1022
|
+
this.log.warn(`[orchestrator] Step 21b AdaptiveStrategy error: ${err.message}`);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
870
1025
|
// 22. Parameter Registry: refresh orchestrator params from registry
|
|
871
1026
|
if (this.parameterRegistry) {
|
|
872
1027
|
const distill = this.parameterRegistry.get('orchestrator', 'distillEvery');
|
|
@@ -1328,6 +1483,48 @@ export class ResearchOrchestrator {
|
|
|
1328
1483
|
this.log.warn(`[orchestrator] Step 40 error: ${err.message}`);
|
|
1329
1484
|
}
|
|
1330
1485
|
}
|
|
1486
|
+
// Step 41: ConceptAbstraction — cluster knowledge into abstract concepts (every 10 cycles)
|
|
1487
|
+
if (this.conceptAbstraction && this.cycleCount % 10 === 0) {
|
|
1488
|
+
try {
|
|
1489
|
+
ts?.emit('concept_abstraction', 'analyzing', 'Step 41: Forming abstract concepts...', 'routine');
|
|
1490
|
+
const result = this.conceptAbstraction.formConcepts();
|
|
1491
|
+
if (result.totalConcepts > 0) {
|
|
1492
|
+
this.journal.write({
|
|
1493
|
+
title: `Concept Formation: ${result.totalConcepts} concepts across ${Object.keys(result.levels).length} levels`,
|
|
1494
|
+
type: 'discovery',
|
|
1495
|
+
content: `Formed ${result.totalConcepts} concepts (L0: ${result.levels[0] ?? 0}, L1: ${result.levels[1] ?? 0}, L2: ${result.levels[2] ?? 0})`,
|
|
1496
|
+
tags: [this.brainName, 'concept-abstraction', 'knowledge-organization'],
|
|
1497
|
+
references: [],
|
|
1498
|
+
significance: result.newConcepts > 0 ? 'notable' : 'routine',
|
|
1499
|
+
data: result,
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
// Register concepts in MemoryPalace
|
|
1503
|
+
if (this.memoryPalace && result.totalConcepts > 0) {
|
|
1504
|
+
try {
|
|
1505
|
+
this.conceptAbstraction.registerInPalace(this.memoryPalace);
|
|
1506
|
+
}
|
|
1507
|
+
catch (palaceErr) {
|
|
1508
|
+
this.log.warn(`[orchestrator] Step 41 palace registration error: ${palaceErr.message}`);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
// Feed transferable concepts into TransferEngine
|
|
1512
|
+
if (this.transferEngine && result.totalConcepts > 0) {
|
|
1513
|
+
try {
|
|
1514
|
+
const transferable = this.conceptAbstraction.getTransferableConcepts(0.3);
|
|
1515
|
+
if (transferable.length > 0) {
|
|
1516
|
+
ts?.emit('concept_abstraction', 'discovering', `${transferable.length} cross-domain concepts available for transfer`, 'notable');
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
catch { /* not critical */ }
|
|
1520
|
+
}
|
|
1521
|
+
if (this.metaCognitionLayer)
|
|
1522
|
+
this.metaCognitionLayer.recordStep('concept_abstraction', this.cycleCount, { insights: result.newConcepts });
|
|
1523
|
+
}
|
|
1524
|
+
catch (err) {
|
|
1525
|
+
this.log.warn(`[orchestrator] Step 41 error: ${err.message}`);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1331
1528
|
const duration = Date.now() - start;
|
|
1332
1529
|
ts?.emit('orchestrator', 'reflecting', `Feedback Cycle #${this.cycleCount} complete (${duration}ms)`);
|
|
1333
1530
|
this.log.info(`[orchestrator] ─── Feedback Cycle #${this.cycleCount} complete (${duration}ms) ───`);
|