@timmeck/brain-core 2.25.1 → 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.
@@ -0,0 +1,212 @@
1
+ import { getLogger } from '../utils/logger.js';
2
+ // ── Migration ───────────────────────────────────────────
3
+ export function runMetaCognitionMigration(db) {
4
+ db.exec(`
5
+ CREATE TABLE IF NOT EXISTS engine_metrics (
6
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
7
+ engine TEXT NOT NULL,
8
+ cycle INTEGER NOT NULL,
9
+ insights INTEGER NOT NULL DEFAULT 0,
10
+ journal_entries INTEGER NOT NULL DEFAULT 0,
11
+ anomalies INTEGER NOT NULL DEFAULT 0,
12
+ predictions INTEGER NOT NULL DEFAULT 0,
13
+ thoughts INTEGER NOT NULL DEFAULT 0,
14
+ errors INTEGER NOT NULL DEFAULT 0,
15
+ duration_ms INTEGER NOT NULL DEFAULT 0,
16
+ created_at TEXT DEFAULT (datetime('now'))
17
+ );
18
+ CREATE INDEX IF NOT EXISTS idx_engine_metrics_engine ON engine_metrics(engine, cycle);
19
+
20
+ CREATE TABLE IF NOT EXISTS engine_report_cards (
21
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ engine TEXT NOT NULL,
23
+ grade TEXT NOT NULL,
24
+ health_score REAL NOT NULL,
25
+ value_score REAL NOT NULL,
26
+ signal_to_noise REAL NOT NULL,
27
+ combined_score REAL NOT NULL,
28
+ evaluated_at TEXT DEFAULT (datetime('now'))
29
+ );
30
+ CREATE INDEX IF NOT EXISTS idx_report_cards_engine ON engine_report_cards(engine);
31
+
32
+ CREATE TABLE IF NOT EXISTS cycle_frequency_adjustments (
33
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
34
+ engine TEXT NOT NULL,
35
+ old_frequency INTEGER NOT NULL,
36
+ new_frequency INTEGER NOT NULL,
37
+ reason TEXT NOT NULL,
38
+ created_at TEXT DEFAULT (datetime('now'))
39
+ );
40
+ `);
41
+ }
42
+ // ── MetaCognition Layer ─────────────────────────────────
43
+ export class MetaCognitionLayer {
44
+ db;
45
+ log = getLogger();
46
+ /** Current frequency multiplier per engine: 1 = every cycle, 2 = every 2 cycles, etc. */
47
+ engineFrequencies = new Map();
48
+ constructor(db) {
49
+ this.db = db;
50
+ runMetaCognitionMigration(db);
51
+ }
52
+ /** Record metrics for a single engine step in a cycle. */
53
+ recordStep(engine, cycle, metrics) {
54
+ // Upsert: if we already recorded this engine+cycle, add to it
55
+ const existing = this.db.prepare('SELECT id, insights, journal_entries, anomalies, predictions, thoughts, errors, duration_ms FROM engine_metrics WHERE engine = ? AND cycle = ?').get(engine, cycle);
56
+ if (existing) {
57
+ this.db.prepare(`
58
+ UPDATE engine_metrics SET
59
+ insights = insights + ?, journal_entries = journal_entries + ?, anomalies = anomalies + ?,
60
+ predictions = predictions + ?, thoughts = thoughts + ?, errors = errors + ?,
61
+ duration_ms = duration_ms + ?
62
+ WHERE id = ?
63
+ `).run(metrics.insights ?? 0, metrics.journal_entries ?? 0, metrics.anomalies ?? 0, metrics.predictions ?? 0, metrics.thoughts ?? 0, metrics.errors ?? 0, metrics.duration_ms ?? 0, existing.id);
64
+ }
65
+ else {
66
+ this.db.prepare(`
67
+ INSERT INTO engine_metrics (engine, cycle, insights, journal_entries, anomalies, predictions, thoughts, errors, duration_ms)
68
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
69
+ `).run(engine, cycle, metrics.insights ?? 0, metrics.journal_entries ?? 0, metrics.anomalies ?? 0, metrics.predictions ?? 0, metrics.thoughts ?? 0, metrics.errors ?? 0, metrics.duration_ms ?? 0);
70
+ }
71
+ }
72
+ /** Evaluate all engines based on recent metrics. Returns report cards. */
73
+ evaluate(windowCycles = 10) {
74
+ // Get all engines that have metrics in the last windowCycles
75
+ const engines = this.db.prepare(`
76
+ SELECT DISTINCT engine FROM engine_metrics
77
+ WHERE cycle > (SELECT COALESCE(MAX(cycle), 0) FROM engine_metrics) - ?
78
+ `).all(windowCycles);
79
+ const cards = [];
80
+ for (const { engine } of engines) {
81
+ const metrics = this.db.prepare(`
82
+ SELECT insights, journal_entries, anomalies, predictions, thoughts, errors, duration_ms
83
+ FROM engine_metrics WHERE engine = ?
84
+ ORDER BY cycle DESC LIMIT ?
85
+ `).all(engine, windowCycles);
86
+ if (metrics.length === 0)
87
+ continue;
88
+ // Health Score: low errors, reasonable duration
89
+ const avgErrors = metrics.reduce((s, m) => s + m.errors, 0) / metrics.length;
90
+ const avgDuration = metrics.reduce((s, m) => s + m.duration_ms, 0) / metrics.length;
91
+ const healthScore = Math.max(0, Math.min(1, (1 - Math.min(avgErrors / 3, 1)) * 0.6 + // fewer errors = healthier
92
+ (1 - Math.min(avgDuration / 5000, 1)) * 0.4));
93
+ // Value Score: producing useful outputs (insights, journal entries, predictions)
94
+ const avgInsights = metrics.reduce((s, m) => s + m.insights, 0) / metrics.length;
95
+ const avgJournal = metrics.reduce((s, m) => s + m.journal_entries, 0) / metrics.length;
96
+ const avgPredictions = metrics.reduce((s, m) => s + m.predictions, 0) / metrics.length;
97
+ const valueScore = Math.min(1, (avgInsights * 0.4 + avgJournal * 0.3 + avgPredictions * 0.3));
98
+ // Signal-to-Noise: useful outputs / total thoughts
99
+ const avgThoughts = metrics.reduce((s, m) => s + m.thoughts, 0) / metrics.length;
100
+ const signalToNoise = avgThoughts > 0
101
+ ? Math.min(1, (avgInsights + avgJournal + avgPredictions) / avgThoughts)
102
+ : 0;
103
+ // Combined Score
104
+ const combinedScore = healthScore * 0.3 + valueScore * 0.5 + signalToNoise * 0.2;
105
+ // Grade
106
+ const grade = this.scoreToGrade(combinedScore);
107
+ const card = {
108
+ engine, grade, health_score: healthScore, value_score: valueScore,
109
+ signal_to_noise: signalToNoise, combined_score: combinedScore,
110
+ };
111
+ cards.push(card);
112
+ // Persist
113
+ this.db.prepare(`
114
+ INSERT INTO engine_report_cards (engine, grade, health_score, value_score, signal_to_noise, combined_score)
115
+ VALUES (?, ?, ?, ?, ?, ?)
116
+ `).run(engine, grade, healthScore, valueScore, signalToNoise, combinedScore);
117
+ }
118
+ return cards;
119
+ }
120
+ /** Adjust engine frequencies based on report cards. A=more often, D/F=less often. */
121
+ adjustFrequencies(cards) {
122
+ const adjustments = [];
123
+ for (const card of cards) {
124
+ const currentFreq = this.engineFrequencies.get(card.engine) ?? 1;
125
+ let newFreq = currentFreq;
126
+ if (card.grade === 'A' && currentFreq > 1) {
127
+ newFreq = currentFreq - 1; // Run more often
128
+ }
129
+ else if (card.grade === 'D' || card.grade === 'F') {
130
+ newFreq = Math.min(currentFreq + 1, 10); // Run less often, cap at 10
131
+ }
132
+ // B and C: keep current frequency
133
+ if (newFreq !== currentFreq) {
134
+ this.engineFrequencies.set(card.engine, newFreq);
135
+ const adjustment = {
136
+ engine: card.engine,
137
+ old_frequency: currentFreq,
138
+ new_frequency: newFreq,
139
+ reason: `Grade ${card.grade}: combined=${card.combined_score.toFixed(2)}`,
140
+ };
141
+ adjustments.push(adjustment);
142
+ this.db.prepare(`
143
+ INSERT INTO cycle_frequency_adjustments (engine, old_frequency, new_frequency, reason)
144
+ VALUES (?, ?, ?, ?)
145
+ `).run(card.engine, currentFreq, newFreq, adjustment.reason);
146
+ this.log.info(`[metacognition] ${card.engine}: freq ${currentFreq} → ${newFreq} (grade ${card.grade})`);
147
+ }
148
+ }
149
+ return adjustments;
150
+ }
151
+ /** Check if an engine should run this cycle based on its frequency. */
152
+ shouldRun(engine, cycle) {
153
+ const freq = this.engineFrequencies.get(engine) ?? 1;
154
+ return cycle % freq === 0;
155
+ }
156
+ /** Get engine frequency. */
157
+ getFrequency(engine) {
158
+ return this.engineFrequencies.get(engine) ?? 1;
159
+ }
160
+ /** Get report card for a specific engine. */
161
+ getReportCard(engine) {
162
+ const row = this.db.prepare(`
163
+ SELECT engine, grade, health_score, value_score, signal_to_noise, combined_score, evaluated_at
164
+ FROM engine_report_cards WHERE engine = ? ORDER BY id DESC LIMIT 1
165
+ `).get(engine);
166
+ return row;
167
+ }
168
+ /** Get all latest report cards. */
169
+ getLatestReportCards() {
170
+ return this.db.prepare(`
171
+ SELECT r.engine, r.grade, r.health_score, r.value_score, r.signal_to_noise, r.combined_score, r.evaluated_at
172
+ FROM engine_report_cards r
173
+ INNER JOIN (SELECT engine, MAX(id) as max_id FROM engine_report_cards GROUP BY engine) latest
174
+ ON r.id = latest.max_id
175
+ ORDER BY r.combined_score DESC
176
+ `).all();
177
+ }
178
+ /** Get trend for an engine over time. */
179
+ getTrend(engine, limit = 10) {
180
+ return this.db.prepare(`
181
+ SELECT engine, grade, health_score, value_score, signal_to_noise, combined_score, evaluated_at
182
+ FROM engine_report_cards WHERE engine = ? ORDER BY id DESC LIMIT ?
183
+ `).all(engine, limit);
184
+ }
185
+ /** Get status summary. */
186
+ getStatus() {
187
+ const cards = this.getLatestReportCards();
188
+ const recentAdj = this.db.prepare(`
189
+ SELECT engine, old_frequency, new_frequency, reason, created_at
190
+ FROM cycle_frequency_adjustments ORDER BY id DESC LIMIT 10
191
+ `).all();
192
+ const totalMetrics = this.db.prepare('SELECT COUNT(*) as c FROM engine_metrics').get().c;
193
+ return {
194
+ totalEngines: cards.length,
195
+ reportCards: cards,
196
+ recentAdjustments: recentAdj,
197
+ cycleMetrics: totalMetrics,
198
+ };
199
+ }
200
+ scoreToGrade(score) {
201
+ if (score >= 0.8)
202
+ return 'A';
203
+ if (score >= 0.6)
204
+ return 'B';
205
+ if (score >= 0.4)
206
+ return 'C';
207
+ if (score >= 0.2)
208
+ return 'D';
209
+ return 'F';
210
+ }
211
+ }
212
+ //# sourceMappingURL=meta-cognition-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-cognition-layer.js","sourceRoot":"","sources":["../../src/metacognition/meta-cognition-layer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA2C/C,2DAA2D;AAE3D,MAAM,UAAU,yBAAyB,CAAC,EAAqB;IAC7D,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCP,CAAC,CAAC;AACL,CAAC;AAED,2DAA2D;AAE3D,MAAM,OAAO,kBAAkB;IACrB,EAAE,CAAoB;IACtB,GAAG,GAAG,SAAS,EAAE,CAAC;IAC1B,yFAAyF;IACjF,iBAAiB,GAAwB,IAAI,GAAG,EAAE,CAAC;IAE3D,YAAY,EAAqB;QAC/B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,0DAA0D;IAC1D,UAAU,CAAC,MAAc,EAAE,KAAa,EAAE,OAAwD;QAChG,8DAA8D;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC9B,gJAAgJ,CACjJ,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAyK,CAAC;QAE7L,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;OAMf,CAAC,CAAC,GAAG,CACJ,OAAO,CAAC,QAAQ,IAAI,CAAC,EAAE,OAAO,CAAC,eAAe,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,EAC3E,OAAO,CAAC,WAAW,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,EACpE,OAAO,CAAC,WAAW,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CACtC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;OAGf,CAAC,CAAC,GAAG,CACJ,MAAM,EAAE,KAAK,EACb,OAAO,CAAC,QAAQ,IAAI,CAAC,EAAE,OAAO,CAAC,eAAe,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,EAC3E,OAAO,CAAC,WAAW,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,EACpE,OAAO,CAAC,WAAW,IAAI,CAAC,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,GAAG,EAAE;QACxB,6DAA6D;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG/B,CAAC,CAAC,GAAG,CAAC,YAAY,CAAyB,CAAC;QAE7C,MAAM,KAAK,GAAuB,EAAE,CAAC;QAErC,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;OAI/B,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAmB,CAAC;YAE/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEnC,gDAAgD;YAChD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YAC7E,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACpF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EACxC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,2BAA2B;gBACpE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAC5C,CAAC,CAAC;YAEH,iFAAiF;YACjF,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACjF,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACvF,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACvF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAC3B,CAAC,WAAW,GAAG,GAAG,GAAG,UAAU,GAAG,GAAG,GAAG,cAAc,GAAG,GAAG,CAAC,CAC9D,CAAC;YAEF,mDAAmD;YACnD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YACjF,MAAM,aAAa,GAAG,WAAW,GAAG,CAAC;gBACnC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC,GAAG,WAAW,CAAC;gBACxE,CAAC,CAAC,CAAC,CAAC;YAEN,iBAAiB;YACjB,MAAM,aAAa,GAAG,WAAW,GAAG,GAAG,GAAG,UAAU,GAAG,GAAG,GAAG,aAAa,GAAG,GAAG,CAAC;YAEjF,QAAQ;YACR,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YAE/C,MAAM,IAAI,GAAqB;gBAC7B,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU;gBACjE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa;aAC9D,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEjB,UAAU;YACV,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;OAGf,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,qFAAqF;IACrF,iBAAiB,CAAC,KAAyB;QACzC,MAAM,WAAW,GAA0B,EAAE,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACjE,IAAI,OAAO,GAAG,WAAW,CAAC;YAE1B,IAAI,IAAI,CAAC,KAAK,KAAK,GAAG,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC1C,OAAO,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,iBAAiB;YAC9C,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,GAAG,EAAE,CAAC;gBACpD,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,4BAA4B;YACvE,CAAC;YACD,kCAAkC;YAElC,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;gBAC5B,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBACjD,MAAM,UAAU,GAAwB;oBACtC,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,aAAa,EAAE,WAAW;oBAC1B,aAAa,EAAE,OAAO;oBACtB,MAAM,EAAE,SAAS,IAAI,CAAC,KAAK,cAAc,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;iBAC1E,CAAC;gBACF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAE7B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;SAGf,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;gBAE7D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,MAAM,UAAU,WAAW,MAAM,OAAO,WAAW,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;YAC1G,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,uEAAuE;IACvE,SAAS,CAAC,MAAc,EAAE,KAAa;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,OAAO,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,4BAA4B;IAC5B,YAAY,CAAC,MAAc;QACzB,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,6CAA6C;IAC7C,aAAa,CAAC,MAAc;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG3B,CAAC,CAAC,GAAG,CAAC,MAAM,CAAiC,CAAC;QAC/C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,mCAAmC;IACnC,oBAAoB;QAClB,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;KAMtB,CAAC,CAAC,GAAG,EAAwB,CAAC;IACjC,CAAC;IAED,yCAAyC;IACzC,QAAQ,CAAC,MAAc,EAAE,KAAK,GAAG,EAAE;QACjC,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGtB,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAuB,CAAC;IAC9C,CAAC;IAED,0BAA0B;IAC1B,SAAS;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGjC,CAAC,CAAC,GAAG,EAA2B,CAAC;QAClC,MAAM,YAAY,GAAI,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,EAAoB,CAAC,CAAC,CAAC;QAE5G,OAAO;YACL,YAAY,EAAE,KAAK,CAAC,MAAM;YAC1B,WAAW,EAAE,KAAK;YAClB,iBAAiB,EAAE,SAAS;YAC5B,YAAY,EAAE,YAAY;SAC3B,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,KAAa;QAChC,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QAC7B,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QAC7B,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QAC7B,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
@@ -0,0 +1,71 @@
1
+ import type Database from 'better-sqlite3';
2
+ export interface ParameterDefinition {
3
+ engine: string;
4
+ name: string;
5
+ value: number;
6
+ min: number;
7
+ max: number;
8
+ description: string;
9
+ category?: string;
10
+ }
11
+ export interface ParameterChange {
12
+ id?: number;
13
+ engine: string;
14
+ name: string;
15
+ old_value: number;
16
+ new_value: number;
17
+ changed_by: string;
18
+ reason: string;
19
+ created_at?: string;
20
+ }
21
+ export interface ParameterSnapshot {
22
+ id?: number;
23
+ label: string;
24
+ data_json: string;
25
+ created_at?: string;
26
+ }
27
+ export interface RegisteredParameter {
28
+ engine: string;
29
+ name: string;
30
+ value: number;
31
+ min: number;
32
+ max: number;
33
+ description: string;
34
+ category: string;
35
+ }
36
+ export declare function runParameterRegistryMigration(db: Database.Database): void;
37
+ export declare class ParameterRegistry {
38
+ private db;
39
+ private log;
40
+ constructor(db: Database.Database);
41
+ /** Register a tunable parameter. Inserts if new, does NOT overwrite existing values. */
42
+ register(def: ParameterDefinition): void;
43
+ /** Register multiple parameters at once. */
44
+ registerAll(defs: ParameterDefinition[]): void;
45
+ /** Get current value. Returns undefined if not registered. */
46
+ get(engine: string, name: string): number | undefined;
47
+ /** Get full parameter definition. */
48
+ getDefinition(engine: string, name: string): RegisteredParameter | undefined;
49
+ /** Set a parameter value with bounds validation and change tracking. */
50
+ set(engine: string, name: string, value: number, changedBy: string, reason: string): boolean;
51
+ /** List all parameters, optionally filtered by engine. */
52
+ list(engine?: string): RegisteredParameter[];
53
+ /** Get change history for a parameter. */
54
+ getHistory(engine: string, name: string, limit?: number): ParameterChange[];
55
+ /** Get all recent changes across all parameters. */
56
+ getRecentChanges(limit?: number): ParameterChange[];
57
+ /** Create a snapshot of all current parameter values. */
58
+ snapshot(label: string): number;
59
+ /** Restore parameters from a snapshot. */
60
+ restore(snapshotId: number, changedBy?: string): number;
61
+ /** List all snapshots. */
62
+ listSnapshots(limit?: number): ParameterSnapshot[];
63
+ /** Get summary stats. */
64
+ getStatus(): {
65
+ totalParameters: number;
66
+ totalChanges: number;
67
+ totalSnapshots: number;
68
+ engines: string[];
69
+ recentChanges: ParameterChange[];
70
+ };
71
+ }
@@ -0,0 +1,162 @@
1
+ import { getLogger } from '../utils/logger.js';
2
+ // ── Migration ───────────────────────────────────────────
3
+ export function runParameterRegistryMigration(db) {
4
+ db.exec(`
5
+ CREATE TABLE IF NOT EXISTS parameter_registry (
6
+ engine TEXT NOT NULL,
7
+ name TEXT NOT NULL,
8
+ value REAL NOT NULL,
9
+ min_value REAL NOT NULL,
10
+ max_value REAL NOT NULL,
11
+ description TEXT NOT NULL DEFAULT '',
12
+ category TEXT NOT NULL DEFAULT 'general',
13
+ updated_at TEXT DEFAULT (datetime('now')),
14
+ PRIMARY KEY (engine, name)
15
+ );
16
+
17
+ CREATE TABLE IF NOT EXISTS parameter_changes (
18
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
19
+ engine TEXT NOT NULL,
20
+ name TEXT NOT NULL,
21
+ old_value REAL NOT NULL,
22
+ new_value REAL NOT NULL,
23
+ changed_by TEXT NOT NULL,
24
+ reason TEXT NOT NULL DEFAULT '',
25
+ created_at TEXT DEFAULT (datetime('now'))
26
+ );
27
+ CREATE INDEX IF NOT EXISTS idx_param_changes_engine ON parameter_changes(engine, name);
28
+
29
+ CREATE TABLE IF NOT EXISTS parameter_snapshots (
30
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
31
+ label TEXT NOT NULL,
32
+ data_json TEXT NOT NULL,
33
+ created_at TEXT DEFAULT (datetime('now'))
34
+ );
35
+ `);
36
+ }
37
+ // ── Registry ───────────────────────────────────────────
38
+ export class ParameterRegistry {
39
+ db;
40
+ log = getLogger();
41
+ constructor(db) {
42
+ this.db = db;
43
+ runParameterRegistryMigration(db);
44
+ }
45
+ /** Register a tunable parameter. Inserts if new, does NOT overwrite existing values. */
46
+ register(def) {
47
+ const existing = this.db.prepare('SELECT value FROM parameter_registry WHERE engine = ? AND name = ?').get(def.engine, def.name);
48
+ if (existing)
49
+ return; // Already registered — keep current value
50
+ this.db.prepare(`
51
+ INSERT INTO parameter_registry (engine, name, value, min_value, max_value, description, category)
52
+ VALUES (?, ?, ?, ?, ?, ?, ?)
53
+ `).run(def.engine, def.name, def.value, def.min, def.max, def.description, def.category ?? 'general');
54
+ }
55
+ /** Register multiple parameters at once. */
56
+ registerAll(defs) {
57
+ for (const def of defs)
58
+ this.register(def);
59
+ }
60
+ /** Get current value. Returns undefined if not registered. */
61
+ get(engine, name) {
62
+ const row = this.db.prepare('SELECT value FROM parameter_registry WHERE engine = ? AND name = ?').get(engine, name);
63
+ return row?.value;
64
+ }
65
+ /** Get full parameter definition. */
66
+ getDefinition(engine, name) {
67
+ const row = this.db.prepare('SELECT engine, name, value, min_value, max_value, description, category FROM parameter_registry WHERE engine = ? AND name = ?').get(engine, name);
68
+ if (!row)
69
+ return undefined;
70
+ return { engine: row.engine, name: row.name, value: row.value, min: row.min_value, max: row.max_value, description: row.description, category: row.category };
71
+ }
72
+ /** Set a parameter value with bounds validation and change tracking. */
73
+ set(engine, name, value, changedBy, reason) {
74
+ const current = this.db.prepare('SELECT value, min_value, max_value FROM parameter_registry WHERE engine = ? AND name = ?').get(engine, name);
75
+ if (!current) {
76
+ this.log.warn(`[parameter-registry] Parameter not found: ${engine}.${name}`);
77
+ return false;
78
+ }
79
+ // Clamp to bounds
80
+ const clamped = Math.max(current.min_value, Math.min(current.max_value, value));
81
+ if (clamped === current.value)
82
+ return false; // No change
83
+ // Record change
84
+ this.db.prepare(`
85
+ INSERT INTO parameter_changes (engine, name, old_value, new_value, changed_by, reason)
86
+ VALUES (?, ?, ?, ?, ?, ?)
87
+ `).run(engine, name, current.value, clamped, changedBy, reason);
88
+ // Update value
89
+ this.db.prepare(`
90
+ UPDATE parameter_registry SET value = ?, updated_at = datetime('now') WHERE engine = ? AND name = ?
91
+ `).run(clamped, engine, name);
92
+ this.log.info(`[parameter-registry] ${engine}.${name}: ${current.value} → ${clamped} (by ${changedBy}: ${reason})`);
93
+ return true;
94
+ }
95
+ /** List all parameters, optionally filtered by engine. */
96
+ list(engine) {
97
+ const query = engine
98
+ ? 'SELECT engine, name, value, min_value, max_value, description, category FROM parameter_registry WHERE engine = ? ORDER BY engine, name'
99
+ : 'SELECT engine, name, value, min_value, max_value, description, category FROM parameter_registry ORDER BY engine, name';
100
+ const rows = (engine ? this.db.prepare(query).all(engine) : this.db.prepare(query).all());
101
+ return rows.map(r => ({ engine: r.engine, name: r.name, value: r.value, min: r.min_value, max: r.max_value, description: r.description, category: r.category }));
102
+ }
103
+ /** Get change history for a parameter. */
104
+ getHistory(engine, name, limit = 20) {
105
+ return this.db.prepare(`
106
+ SELECT id, engine, name, old_value, new_value, changed_by, reason, created_at
107
+ FROM parameter_changes WHERE engine = ? AND name = ?
108
+ ORDER BY id DESC LIMIT ?
109
+ `).all(engine, name, limit);
110
+ }
111
+ /** Get all recent changes across all parameters. */
112
+ getRecentChanges(limit = 50) {
113
+ return this.db.prepare(`
114
+ SELECT id, engine, name, old_value, new_value, changed_by, reason, created_at
115
+ FROM parameter_changes ORDER BY id DESC LIMIT ?
116
+ `).all(limit);
117
+ }
118
+ /** Create a snapshot of all current parameter values. */
119
+ snapshot(label) {
120
+ const params = this.list();
121
+ const data = {};
122
+ for (const p of params) {
123
+ if (!data[p.engine])
124
+ data[p.engine] = {};
125
+ data[p.engine][p.name] = p.value;
126
+ }
127
+ const result = this.db.prepare(`
128
+ INSERT INTO parameter_snapshots (label, data_json) VALUES (?, ?)
129
+ `).run(label, JSON.stringify(data));
130
+ return result.lastInsertRowid;
131
+ }
132
+ /** Restore parameters from a snapshot. */
133
+ restore(snapshotId, changedBy = 'snapshot_restore') {
134
+ const row = this.db.prepare('SELECT data_json FROM parameter_snapshots WHERE id = ?').get(snapshotId);
135
+ if (!row)
136
+ return 0;
137
+ const data = JSON.parse(row.data_json);
138
+ let count = 0;
139
+ for (const [engine, params] of Object.entries(data)) {
140
+ for (const [name, value] of Object.entries(params)) {
141
+ if (this.set(engine, name, value, changedBy, `Restored from snapshot #${snapshotId}`)) {
142
+ count++;
143
+ }
144
+ }
145
+ }
146
+ return count;
147
+ }
148
+ /** List all snapshots. */
149
+ listSnapshots(limit = 20) {
150
+ return this.db.prepare('SELECT id, label, data_json, created_at FROM parameter_snapshots ORDER BY id DESC LIMIT ?').all(limit);
151
+ }
152
+ /** Get summary stats. */
153
+ getStatus() {
154
+ const totalParams = this.db.prepare('SELECT COUNT(*) as c FROM parameter_registry').get().c;
155
+ const totalChanges = this.db.prepare('SELECT COUNT(*) as c FROM parameter_changes').get().c;
156
+ const totalSnapshots = this.db.prepare('SELECT COUNT(*) as c FROM parameter_snapshots').get().c;
157
+ const engines = this.db.prepare('SELECT DISTINCT engine FROM parameter_registry ORDER BY engine').all().map(r => r.engine);
158
+ const recentChanges = this.getRecentChanges(10);
159
+ return { totalParameters: totalParams, totalChanges, totalSnapshots, engines, recentChanges };
160
+ }
161
+ }
162
+ //# sourceMappingURL=parameter-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parameter-registry.js","sourceRoot":"","sources":["../../src/metacognition/parameter-registry.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,9 @@ import type { NarrativeEngine } from '../narrative/narrative-engine.js';
24
24
  import type { CuriosityEngine } from '../curiosity/curiosity-engine.js';
25
25
  import type { EmergenceEngine } from '../emergence/emergence-engine.js';
26
26
  import type { DebateEngine } from '../debate/debate-engine.js';
27
+ import type { ParameterRegistry } from '../metacognition/parameter-registry.js';
28
+ import type { MetaCognitionLayer } from '../metacognition/meta-cognition-layer.js';
29
+ import type { AutoExperimentEngine } from '../metacognition/auto-experiment-engine.js';
27
30
  import { AutoResponder } from './auto-responder.js';
28
31
  export interface ResearchOrchestratorConfig {
29
32
  brainName: string;
@@ -61,6 +64,9 @@ export declare class ResearchOrchestrator {
61
64
  private curiosityEngine;
62
65
  private emergenceEngine;
63
66
  private debateEngine;
67
+ private parameterRegistry;
68
+ private metaCognitionLayer;
69
+ private autoExperimentEngine;
64
70
  private brainName;
65
71
  private feedbackTimer;
66
72
  private cycleCount;
@@ -72,6 +78,8 @@ export declare class ResearchOrchestrator {
72
78
  private suggestionHistory;
73
79
  /** Max repeats before trying an alternative. */
74
80
  private readonly stalledThreshold;
81
+ /** Hash of last written suggestions to prevent duplicate file writes. */
82
+ private lastSuggestionsHash;
75
83
  constructor(db: Database.Database, config: ResearchOrchestratorConfig, causalGraph?: CausalGraph);
76
84
  /** Set the DataMiner instance for DB-driven engine feeding. */
77
85
  setDataMiner(miner: DataMiner): void;
@@ -96,6 +104,12 @@ export declare class ResearchOrchestrator {
96
104
  /** Set the EmergenceEngine — tracks emergent behaviors and complexity metrics. */
97
105
  setEmergenceEngine(engine: EmergenceEngine): void;
98
106
  setDebateEngine(engine: DebateEngine): void;
107
+ /** Set the ParameterRegistry — central tunable parameter store. */
108
+ setParameterRegistry(registry: ParameterRegistry): void;
109
+ /** Set the MetaCognitionLayer — engine evaluation and frequency adjustment. */
110
+ setMetaCognitionLayer(layer: MetaCognitionLayer): void;
111
+ /** Set the AutoExperimentEngine — autonomous parameter tuning. */
112
+ setAutoExperimentEngine(engine: AutoExperimentEngine): void;
99
113
  /** Set the PredictionEngine — wires journal into it. */
100
114
  setPredictionEngine(engine: PredictionEngine): void;
101
115
  /** Start the autonomous feedback loop timer. */
@@ -132,7 +146,8 @@ export declare class ResearchOrchestrator {
132
146
  private proposeAutoExperiment;
133
147
  /** Feed cycle measurements into running experiments. */
134
148
  private feedExperimentMeasurements;
135
- /** Append improvement suggestions to ~/.brain/improvement-requests.md */
149
+ /** Append improvement suggestions to ~/.brain/improvement-requests.md.
150
+ * Skips writing if suggestions are identical to the last write (dedup). */
136
151
  private writeSuggestionsToFile;
137
152
  /** Get a comprehensive research summary for dashboards/API. */
138
153
  getSummary(): Record<string, unknown>;