@timmeck/brain-core 2.36.23 → 2.36.25
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/command-center.html +259 -153
- package/dist/active-learning/__tests__/active-learning.test.d.ts +1 -0
- package/dist/active-learning/__tests__/active-learning.test.js +132 -0
- package/dist/active-learning/__tests__/active-learning.test.js.map +1 -0
- package/dist/active-learning/active-learner.d.ts +79 -0
- package/dist/active-learning/active-learner.js +224 -0
- package/dist/active-learning/active-learner.js.map +1 -0
- package/dist/active-learning/index.d.ts +2 -0
- package/dist/active-learning/index.js +2 -0
- package/dist/active-learning/index.js.map +1 -0
- package/dist/code-health/__tests__/code-health.test.d.ts +1 -0
- package/dist/code-health/__tests__/code-health.test.js +123 -0
- package/dist/code-health/__tests__/code-health.test.js.map +1 -0
- package/dist/code-health/health-monitor.d.ts +55 -0
- package/dist/code-health/health-monitor.js +180 -0
- package/dist/code-health/health-monitor.js.map +1 -0
- package/dist/code-health/index.d.ts +2 -0
- package/dist/code-health/index.js +2 -0
- package/dist/code-health/index.js.map +1 -0
- package/dist/consensus/__tests__/consensus.test.d.ts +1 -0
- package/dist/consensus/__tests__/consensus.test.js +159 -0
- package/dist/consensus/__tests__/consensus.test.js.map +1 -0
- package/dist/consensus/consensus-engine.d.ts +81 -0
- package/dist/consensus/consensus-engine.js +237 -0
- package/dist/consensus/consensus-engine.js.map +1 -0
- package/dist/consensus/index.d.ts +2 -0
- package/dist/consensus/index.js +2 -0
- package/dist/consensus/index.js.map +1 -0
- package/dist/feedback/__tests__/feedback-engine.test.d.ts +1 -0
- package/dist/feedback/__tests__/feedback-engine.test.js +156 -0
- package/dist/feedback/__tests__/feedback-engine.test.js.map +1 -0
- package/dist/feedback/feedback-engine.d.ts +61 -0
- package/dist/feedback/feedback-engine.js +203 -0
- package/dist/feedback/feedback-engine.js.map +1 -0
- package/dist/feedback/index.d.ts +2 -0
- package/dist/feedback/index.js +2 -0
- package/dist/feedback/index.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge-graph/__tests__/knowledge-graph.test.d.ts +1 -0
- package/dist/knowledge-graph/__tests__/knowledge-graph.test.js +215 -0
- package/dist/knowledge-graph/__tests__/knowledge-graph.test.js.map +1 -0
- package/dist/knowledge-graph/fact-extractor.d.ts +23 -0
- package/dist/knowledge-graph/fact-extractor.js +70 -0
- package/dist/knowledge-graph/fact-extractor.js.map +1 -0
- package/dist/knowledge-graph/graph-engine.d.ts +78 -0
- package/dist/knowledge-graph/graph-engine.js +276 -0
- package/dist/knowledge-graph/graph-engine.js.map +1 -0
- package/dist/knowledge-graph/index.d.ts +4 -0
- package/dist/knowledge-graph/index.js +3 -0
- package/dist/knowledge-graph/index.js.map +1 -0
- package/dist/proactive/__tests__/proactive-engine.test.d.ts +1 -0
- package/dist/proactive/__tests__/proactive-engine.test.js +183 -0
- package/dist/proactive/__tests__/proactive-engine.test.js.map +1 -0
- package/dist/proactive/index.d.ts +2 -0
- package/dist/proactive/index.js +2 -0
- package/dist/proactive/index.js.map +1 -0
- package/dist/proactive/proactive-engine.d.ts +86 -0
- package/dist/proactive/proactive-engine.js +252 -0
- package/dist/proactive/proactive-engine.js.map +1 -0
- package/dist/rag/__tests__/rag-engine.test.d.ts +1 -0
- package/dist/rag/__tests__/rag-engine.test.js +235 -0
- package/dist/rag/__tests__/rag-engine.test.js.map +1 -0
- package/dist/rag/index.d.ts +4 -0
- package/dist/rag/index.js +3 -0
- package/dist/rag/index.js.map +1 -0
- package/dist/rag/rag-engine.d.ts +98 -0
- package/dist/rag/rag-engine.js +310 -0
- package/dist/rag/rag-engine.js.map +1 -0
- package/dist/rag/rag-indexer.d.ts +52 -0
- package/dist/rag/rag-indexer.js +144 -0
- package/dist/rag/rag-indexer.js.map +1 -0
- package/dist/research/__tests__/autonomy-features.test.d.ts +1 -0
- package/dist/research/__tests__/autonomy-features.test.js +155 -0
- package/dist/research/__tests__/autonomy-features.test.js.map +1 -0
- package/dist/research/__tests__/semantic-compressor.test.d.ts +1 -0
- package/dist/research/__tests__/semantic-compressor.test.js +153 -0
- package/dist/research/__tests__/semantic-compressor.test.js.map +1 -0
- package/dist/research/semantic-compressor.d.ts +55 -0
- package/dist/research/semantic-compressor.js +227 -0
- package/dist/research/semantic-compressor.js.map +1 -0
- package/dist/teaching/__tests__/teaching.test.d.ts +1 -0
- package/dist/teaching/__tests__/teaching.test.js +151 -0
- package/dist/teaching/__tests__/teaching.test.js.map +1 -0
- package/dist/teaching/curriculum.d.ts +32 -0
- package/dist/teaching/curriculum.js +89 -0
- package/dist/teaching/curriculum.js.map +1 -0
- package/dist/teaching/index.d.ts +4 -0
- package/dist/teaching/index.js +3 -0
- package/dist/teaching/index.js.map +1 -0
- package/dist/teaching/teaching-protocol.d.ts +74 -0
- package/dist/teaching/teaching-protocol.js +164 -0
- package/dist/teaching/teaching-protocol.js.map +1 -0
- package/dist/tool-learning/__tests__/tool-learning.test.d.ts +1 -0
- package/dist/tool-learning/__tests__/tool-learning.test.js +187 -0
- package/dist/tool-learning/__tests__/tool-learning.test.js.map +1 -0
- package/dist/tool-learning/index.d.ts +4 -0
- package/dist/tool-learning/index.js +3 -0
- package/dist/tool-learning/index.js.map +1 -0
- package/dist/tool-learning/tool-patterns.d.ts +47 -0
- package/dist/tool-learning/tool-patterns.js +125 -0
- package/dist/tool-learning/tool-patterns.js.map +1 -0
- package/dist/tool-learning/tool-tracker.d.ts +58 -0
- package/dist/tool-learning/tool-tracker.js +135 -0
- package/dist/tool-learning/tool-tracker.js.map +1 -0
- package/dist/user-model/__tests__/user-model.test.d.ts +1 -0
- package/dist/user-model/__tests__/user-model.test.js +142 -0
- package/dist/user-model/__tests__/user-model.test.js.map +1 -0
- package/dist/user-model/adaptive-context.d.ts +18 -0
- package/dist/user-model/adaptive-context.js +46 -0
- package/dist/user-model/adaptive-context.js.map +1 -0
- package/dist/user-model/index.d.ts +4 -0
- package/dist/user-model/index.js +3 -0
- package/dist/user-model/index.js.map +1 -0
- package/dist/user-model/user-model.d.ts +53 -0
- package/dist/user-model/user-model.js +204 -0
- package/dist/user-model/user-model.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { getLogger } from '../utils/logger.js';
|
|
2
|
+
// ── Migration ───────────────────────────────────────────
|
|
3
|
+
export function runConsensusMigration(db) {
|
|
4
|
+
db.exec(`
|
|
5
|
+
CREATE TABLE IF NOT EXISTS consensus_proposals (
|
|
6
|
+
id INTEGER PRIMARY KEY,
|
|
7
|
+
type TEXT NOT NULL,
|
|
8
|
+
description TEXT NOT NULL,
|
|
9
|
+
options TEXT NOT NULL,
|
|
10
|
+
context TEXT,
|
|
11
|
+
status TEXT DEFAULT 'open' CHECK(status IN ('open','resolved','timeout')),
|
|
12
|
+
result TEXT,
|
|
13
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
14
|
+
resolved_at TEXT
|
|
15
|
+
);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_consensus_status ON consensus_proposals(status);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS consensus_votes (
|
|
19
|
+
id INTEGER PRIMARY KEY,
|
|
20
|
+
proposal_id INTEGER NOT NULL REFERENCES consensus_proposals(id),
|
|
21
|
+
voter TEXT NOT NULL,
|
|
22
|
+
chosen_option TEXT NOT NULL,
|
|
23
|
+
confidence REAL DEFAULT 0.5,
|
|
24
|
+
reasoning TEXT,
|
|
25
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
26
|
+
UNIQUE(proposal_id, voter)
|
|
27
|
+
);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_consensus_votes_proposal ON consensus_votes(proposal_id);
|
|
29
|
+
`);
|
|
30
|
+
}
|
|
31
|
+
// ── Engine ──────────────────────────────────────────────
|
|
32
|
+
export class ConsensusEngine {
|
|
33
|
+
db;
|
|
34
|
+
config;
|
|
35
|
+
log = getLogger();
|
|
36
|
+
ts = null;
|
|
37
|
+
// Prepared statements
|
|
38
|
+
stmtInsertProposal;
|
|
39
|
+
stmtGetProposal;
|
|
40
|
+
stmtUpdateProposalStatus;
|
|
41
|
+
stmtUpsertVote;
|
|
42
|
+
stmtGetVotes;
|
|
43
|
+
stmtListProposals;
|
|
44
|
+
stmtListByStatus;
|
|
45
|
+
stmtTotalProposals;
|
|
46
|
+
stmtOpenCount;
|
|
47
|
+
stmtResolvedCount;
|
|
48
|
+
stmtAvgVotesPerProposal;
|
|
49
|
+
constructor(db, config) {
|
|
50
|
+
this.db = db;
|
|
51
|
+
this.config = {
|
|
52
|
+
brainName: config.brainName,
|
|
53
|
+
timeoutMs: config.timeoutMs ?? 60000,
|
|
54
|
+
requiredMajority: config.requiredMajority ?? 0.5,
|
|
55
|
+
vetoThreshold: config.vetoThreshold ?? 0.67,
|
|
56
|
+
};
|
|
57
|
+
runConsensusMigration(db);
|
|
58
|
+
this.stmtInsertProposal = db.prepare('INSERT INTO consensus_proposals (type, description, options, context) VALUES (?, ?, ?, ?)');
|
|
59
|
+
this.stmtGetProposal = db.prepare('SELECT * FROM consensus_proposals WHERE id = ?');
|
|
60
|
+
this.stmtUpdateProposalStatus = db.prepare('UPDATE consensus_proposals SET status = ?, result = ?, resolved_at = datetime(\'now\') WHERE id = ?');
|
|
61
|
+
this.stmtUpsertVote = db.prepare(`INSERT INTO consensus_votes (proposal_id, voter, chosen_option, confidence, reasoning)
|
|
62
|
+
VALUES (?, ?, ?, ?, ?)
|
|
63
|
+
ON CONFLICT(proposal_id, voter) DO UPDATE SET
|
|
64
|
+
chosen_option = excluded.chosen_option,
|
|
65
|
+
confidence = excluded.confidence,
|
|
66
|
+
reasoning = excluded.reasoning`);
|
|
67
|
+
this.stmtGetVotes = db.prepare('SELECT * FROM consensus_votes WHERE proposal_id = ? ORDER BY id ASC');
|
|
68
|
+
this.stmtListProposals = db.prepare('SELECT * FROM consensus_proposals ORDER BY id DESC LIMIT ?');
|
|
69
|
+
this.stmtListByStatus = db.prepare('SELECT * FROM consensus_proposals WHERE status = ? ORDER BY id DESC LIMIT ?');
|
|
70
|
+
this.stmtTotalProposals = db.prepare('SELECT COUNT(*) as cnt FROM consensus_proposals');
|
|
71
|
+
this.stmtOpenCount = db.prepare("SELECT COUNT(*) as cnt FROM consensus_proposals WHERE status = 'open'");
|
|
72
|
+
this.stmtResolvedCount = db.prepare("SELECT COUNT(*) as cnt FROM consensus_proposals WHERE status = 'resolved'");
|
|
73
|
+
this.stmtAvgVotesPerProposal = db.prepare(`SELECT AVG(vote_count) as avg FROM (
|
|
74
|
+
SELECT proposal_id, COUNT(*) as vote_count FROM consensus_votes GROUP BY proposal_id
|
|
75
|
+
)`);
|
|
76
|
+
this.log.debug(`[ConsensusEngine] Initialized for ${this.config.brainName}`);
|
|
77
|
+
}
|
|
78
|
+
// ── Setters ──────────────────────────────────────────
|
|
79
|
+
setThoughtStream(stream) {
|
|
80
|
+
this.ts = stream;
|
|
81
|
+
}
|
|
82
|
+
// ── Core: Propose ────────────────────────────────────
|
|
83
|
+
propose(decision) {
|
|
84
|
+
const info = this.stmtInsertProposal.run(decision.type, decision.description, JSON.stringify(decision.options), decision.context ?? null);
|
|
85
|
+
const id = Number(info.lastInsertRowid);
|
|
86
|
+
this.ts?.emit('consensus', 'reflecting', `New proposal: ${decision.description.substring(0, 60)} (${decision.options.length} options)`, 'notable');
|
|
87
|
+
this.log.debug(`[ConsensusEngine] Proposal #${id}: ${decision.type}`);
|
|
88
|
+
return { id, type: decision.type, status: 'open' };
|
|
89
|
+
}
|
|
90
|
+
// ── Core: Vote ───────────────────────────────────────
|
|
91
|
+
vote(proposalId, option, confidence, reasoning) {
|
|
92
|
+
this.stmtUpsertVote.run(proposalId, this.config.brainName, option, confidence, reasoning ?? null);
|
|
93
|
+
this.ts?.emit('consensus', 'reflecting', `Voted on proposal #${proposalId}: ${option} (confidence=${confidence.toFixed(2)})`, 'routine');
|
|
94
|
+
this.log.debug(`[ConsensusEngine] Vote on #${proposalId}: ${option} (${confidence.toFixed(2)})`);
|
|
95
|
+
return {
|
|
96
|
+
proposalId,
|
|
97
|
+
voter: this.config.brainName,
|
|
98
|
+
chosenOption: option,
|
|
99
|
+
confidence,
|
|
100
|
+
reasoning,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ── Core: Resolve ────────────────────────────────────
|
|
104
|
+
resolve(proposalId) {
|
|
105
|
+
const proposal = this.getProposal(proposalId);
|
|
106
|
+
if (!proposal) {
|
|
107
|
+
return { winner: null, votes: [], vetoed: false };
|
|
108
|
+
}
|
|
109
|
+
const votes = proposal.votes;
|
|
110
|
+
if (votes.length === 0) {
|
|
111
|
+
return { winner: null, votes: [], vetoed: false };
|
|
112
|
+
}
|
|
113
|
+
// Determine majority requirement
|
|
114
|
+
const isSelfmod = proposal.type === 'selfmod_approval';
|
|
115
|
+
const requiredMajority = isSelfmod ? 2 / 3 : this.config.requiredMajority;
|
|
116
|
+
// Count votes per option
|
|
117
|
+
const voteCounts = new Map();
|
|
118
|
+
for (const v of votes) {
|
|
119
|
+
const entry = voteCounts.get(v.chosenOption) ?? { count: 0, totalConfidence: 0, voters: [] };
|
|
120
|
+
entry.count++;
|
|
121
|
+
entry.totalConfidence += v.confidence;
|
|
122
|
+
entry.voters.push(v.voter);
|
|
123
|
+
voteCounts.set(v.chosenOption, entry);
|
|
124
|
+
}
|
|
125
|
+
// Check for veto: single dissenter with high confidence
|
|
126
|
+
let vetoed = false;
|
|
127
|
+
if (votes.length > 1) {
|
|
128
|
+
for (const v of votes) {
|
|
129
|
+
const entry = voteCounts.get(v.chosenOption);
|
|
130
|
+
// This voter is the only one for their option and has high confidence
|
|
131
|
+
if (entry.count === 1 && v.confidence > this.config.vetoThreshold) {
|
|
132
|
+
// Check if all other votes agree on a different option
|
|
133
|
+
const otherVotes = votes.filter(ov => ov.voter !== v.voter);
|
|
134
|
+
const otherOptions = new Set(otherVotes.map(ov => ov.chosenOption));
|
|
135
|
+
if (otherOptions.size === 1) {
|
|
136
|
+
vetoed = true;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Find winner
|
|
143
|
+
let winner = null;
|
|
144
|
+
let maxCount = 0;
|
|
145
|
+
for (const [option, entry] of voteCounts) {
|
|
146
|
+
if (entry.count > maxCount) {
|
|
147
|
+
maxCount = entry.count;
|
|
148
|
+
winner = option;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Check if majority reached
|
|
152
|
+
if (winner && maxCount / votes.length < requiredMajority) {
|
|
153
|
+
winner = null; // Not enough votes for majority
|
|
154
|
+
}
|
|
155
|
+
// Update proposal status
|
|
156
|
+
const status = vetoed ? 'resolved' : (winner ? 'resolved' : 'open');
|
|
157
|
+
if (status === 'resolved') {
|
|
158
|
+
const resultText = vetoed ? `VETOED (proposed: ${winner})` : winner;
|
|
159
|
+
this.stmtUpdateProposalStatus.run('resolved', resultText, proposalId);
|
|
160
|
+
}
|
|
161
|
+
this.ts?.emit('consensus', 'discovering', `Proposal #${proposalId} ${vetoed ? 'VETOED' : (winner ? `resolved: ${winner}` : 'no majority')}`, vetoed ? 'breakthrough' : 'notable');
|
|
162
|
+
return { winner: vetoed ? null : winner, votes, vetoed };
|
|
163
|
+
}
|
|
164
|
+
// ── Core: Get Proposal ───────────────────────────────
|
|
165
|
+
getProposal(id) {
|
|
166
|
+
const row = this.stmtGetProposal.get(id);
|
|
167
|
+
if (!row)
|
|
168
|
+
return null;
|
|
169
|
+
const votes = this.loadVotes(id);
|
|
170
|
+
return this.toProposal(row, votes);
|
|
171
|
+
}
|
|
172
|
+
// ── Core: History ────────────────────────────────────
|
|
173
|
+
getHistory(status, limit = 20) {
|
|
174
|
+
const rows = status
|
|
175
|
+
? this.stmtListByStatus.all(status, limit)
|
|
176
|
+
: this.stmtListProposals.all(limit);
|
|
177
|
+
return rows.map(r => {
|
|
178
|
+
const votes = this.loadVotes(r.id);
|
|
179
|
+
return this.toProposal(r, votes);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// ── Core: Status ─────────────────────────────────────
|
|
183
|
+
getStatus() {
|
|
184
|
+
const totalProposals = this.stmtTotalProposals.get().cnt;
|
|
185
|
+
const openCount = this.stmtOpenCount.get().cnt;
|
|
186
|
+
const resolvedCount = this.stmtResolvedCount.get().cnt;
|
|
187
|
+
const avgRow = this.stmtAvgVotesPerProposal.get();
|
|
188
|
+
const avgParticipation = avgRow.avg ?? 0;
|
|
189
|
+
return { totalProposals, openCount, resolvedCount, avgParticipation };
|
|
190
|
+
}
|
|
191
|
+
// ── Core: Timeout ────────────────────────────────────
|
|
192
|
+
timeoutProposal(proposalId) {
|
|
193
|
+
const proposal = this.getProposal(proposalId);
|
|
194
|
+
if (!proposal || proposal.status !== 'open')
|
|
195
|
+
return false;
|
|
196
|
+
this.stmtUpdateProposalStatus.run('timeout', null, proposalId);
|
|
197
|
+
this.ts?.emit('consensus', 'reflecting', `Proposal #${proposalId} timed out`, 'routine');
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
// ── Private: Vote Loading ────────────────────────────
|
|
201
|
+
loadVotes(proposalId) {
|
|
202
|
+
const rows = this.stmtGetVotes.all(proposalId);
|
|
203
|
+
return rows.map(r => this.toVote(r));
|
|
204
|
+
}
|
|
205
|
+
// ── Private: Row Mapping ─────────────────────────────
|
|
206
|
+
toProposal(row, votes) {
|
|
207
|
+
let options = [];
|
|
208
|
+
try {
|
|
209
|
+
options = JSON.parse(row.options || '[]');
|
|
210
|
+
}
|
|
211
|
+
catch { /* ignore */ }
|
|
212
|
+
return {
|
|
213
|
+
id: row.id,
|
|
214
|
+
type: row.type,
|
|
215
|
+
description: row.description,
|
|
216
|
+
options,
|
|
217
|
+
context: row.context ?? undefined,
|
|
218
|
+
status: row.status,
|
|
219
|
+
result: row.result ?? undefined,
|
|
220
|
+
votes,
|
|
221
|
+
createdAt: row.created_at,
|
|
222
|
+
resolvedAt: row.resolved_at ?? undefined,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
toVote(row) {
|
|
226
|
+
return {
|
|
227
|
+
id: row.id,
|
|
228
|
+
proposalId: row.proposal_id,
|
|
229
|
+
voter: row.voter,
|
|
230
|
+
chosenOption: row.chosen_option,
|
|
231
|
+
confidence: row.confidence,
|
|
232
|
+
reasoning: row.reasoning ?? undefined,
|
|
233
|
+
createdAt: row.created_at,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=consensus-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consensus-engine.js","sourceRoot":"","sources":["../../src/consensus/consensus-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/consensus/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import Database from 'better-sqlite3';
|
|
3
|
+
vi.mock('../../utils/logger.js', () => ({
|
|
4
|
+
getLogger: () => ({
|
|
5
|
+
info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(),
|
|
6
|
+
}),
|
|
7
|
+
}));
|
|
8
|
+
import { FeedbackEngine, runFeedbackMigration } from '../feedback-engine.js';
|
|
9
|
+
// ── Helpers ──────────────────────────────────────────────────
|
|
10
|
+
function createTestDb() {
|
|
11
|
+
return new Database(':memory:');
|
|
12
|
+
}
|
|
13
|
+
// ── Tests ───────────────────────────────────────────────────
|
|
14
|
+
describe('FeedbackEngine', () => {
|
|
15
|
+
let db;
|
|
16
|
+
let engine;
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
db = createTestDb();
|
|
19
|
+
engine = new FeedbackEngine(db, { brainName: 'test' });
|
|
20
|
+
});
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
try {
|
|
23
|
+
db.close();
|
|
24
|
+
}
|
|
25
|
+
catch { /* ignore */ }
|
|
26
|
+
});
|
|
27
|
+
it('creates feedback tables on migration', () => {
|
|
28
|
+
const signalTable = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='feedback_signals'").all();
|
|
29
|
+
const correctionTable = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='feedback_corrections'").all();
|
|
30
|
+
expect(signalTable).toHaveLength(1);
|
|
31
|
+
expect(correctionTable).toHaveLength(1);
|
|
32
|
+
});
|
|
33
|
+
it('migration is idempotent', () => {
|
|
34
|
+
runFeedbackMigration(db);
|
|
35
|
+
runFeedbackMigration(db);
|
|
36
|
+
const signalTable = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='feedback_signals'").all();
|
|
37
|
+
expect(signalTable).toHaveLength(1);
|
|
38
|
+
});
|
|
39
|
+
it('records positive feedback', () => {
|
|
40
|
+
const record = engine.recordFeedback('insight', 1, 'positive', 'Great insight');
|
|
41
|
+
expect(record.signal).toBe('positive');
|
|
42
|
+
expect(record.reward_score).toBe(1.0);
|
|
43
|
+
expect(record.target_type).toBe('insight');
|
|
44
|
+
expect(record.target_id).toBe(1);
|
|
45
|
+
expect(record.detail).toBe('Great insight');
|
|
46
|
+
});
|
|
47
|
+
it('records negative feedback', () => {
|
|
48
|
+
const record = engine.recordFeedback('prediction', 2, 'negative', 'Incorrect prediction');
|
|
49
|
+
expect(record.signal).toBe('negative');
|
|
50
|
+
expect(record.reward_score).toBe(-1.0);
|
|
51
|
+
});
|
|
52
|
+
it('records correction feedback', () => {
|
|
53
|
+
const record = engine.recordFeedback('rule', 3, 'correction');
|
|
54
|
+
expect(record.signal).toBe('correction');
|
|
55
|
+
expect(record.reward_score).toBe(-0.5);
|
|
56
|
+
expect(record.detail).toBeNull();
|
|
57
|
+
});
|
|
58
|
+
it('calculates reward score from multiple signals', () => {
|
|
59
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
60
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
61
|
+
engine.recordFeedback('insight', 1, 'negative');
|
|
62
|
+
const score = engine.getRewardScore('insight', 1);
|
|
63
|
+
// (1 + 1 + -1) / 3 = 0.333...
|
|
64
|
+
expect(score).toBeCloseTo(1 / 3, 2);
|
|
65
|
+
});
|
|
66
|
+
it('clamps reward score to [-1, 1]', () => {
|
|
67
|
+
// All positive -> should be exactly 1.0
|
|
68
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
69
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
70
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
71
|
+
const positiveScore = engine.getRewardScore('insight', 1);
|
|
72
|
+
expect(positiveScore).toBe(1.0);
|
|
73
|
+
// All negative -> should be exactly -1.0
|
|
74
|
+
engine.recordFeedback('prediction', 2, 'negative');
|
|
75
|
+
engine.recordFeedback('prediction', 2, 'negative');
|
|
76
|
+
const negativeScore = engine.getRewardScore('prediction', 2);
|
|
77
|
+
expect(negativeScore).toBe(-1.0);
|
|
78
|
+
});
|
|
79
|
+
it('returns 0 for target with no feedback', () => {
|
|
80
|
+
const score = engine.getRewardScore('nonexistent', 999);
|
|
81
|
+
expect(score).toBe(0);
|
|
82
|
+
});
|
|
83
|
+
it('learns from correction', () => {
|
|
84
|
+
const correction = engine.learnFromCorrection('X causes Y', 'X correlates with Y', 'fact', 10);
|
|
85
|
+
expect(correction.original).toBe('X causes Y');
|
|
86
|
+
expect(correction.correction).toBe('X correlates with Y');
|
|
87
|
+
expect(correction.target_type).toBe('fact');
|
|
88
|
+
expect(correction.target_id).toBe(10);
|
|
89
|
+
expect(correction.applied).toBe(0);
|
|
90
|
+
// Should also have created a correction feedback signal
|
|
91
|
+
const history = engine.getFeedbackHistory('fact', 10);
|
|
92
|
+
expect(history).toHaveLength(1);
|
|
93
|
+
expect(history[0].signal).toBe('correction');
|
|
94
|
+
});
|
|
95
|
+
it('returns correct stats', () => {
|
|
96
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
97
|
+
engine.recordFeedback('insight', 2, 'positive');
|
|
98
|
+
engine.recordFeedback('prediction', 1, 'negative');
|
|
99
|
+
engine.recordFeedback('rule', 1, 'correction');
|
|
100
|
+
const stats = engine.getStats();
|
|
101
|
+
expect(stats.totalFeedback).toBe(4);
|
|
102
|
+
expect(stats.positiveCount).toBe(2);
|
|
103
|
+
expect(stats.negativeCount).toBe(1);
|
|
104
|
+
expect(stats.correctionCount).toBe(1);
|
|
105
|
+
// avg: (1 + 1 + -1 + -0.5) / 4 = 0.125
|
|
106
|
+
expect(stats.avgRewardScore).toBeCloseTo(0.125, 2);
|
|
107
|
+
});
|
|
108
|
+
it('returns feedback history for a target', () => {
|
|
109
|
+
engine.recordFeedback('insight', 1, 'positive', 'good');
|
|
110
|
+
engine.recordFeedback('insight', 1, 'negative', 'bad');
|
|
111
|
+
engine.recordFeedback('insight', 1, 'positive', 'better');
|
|
112
|
+
engine.recordFeedback('insight', 2, 'positive', 'other target');
|
|
113
|
+
const history = engine.getFeedbackHistory('insight', 1);
|
|
114
|
+
expect(history).toHaveLength(3);
|
|
115
|
+
// Should not include target_id=2
|
|
116
|
+
expect(history.every(h => h.target_id === 1)).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
it('limits feedback history results', () => {
|
|
119
|
+
for (let i = 0; i < 10; i++) {
|
|
120
|
+
engine.recordFeedback('insight', 1, 'positive', `feedback ${i}`);
|
|
121
|
+
}
|
|
122
|
+
const history = engine.getFeedbackHistory('insight', 1, 5);
|
|
123
|
+
expect(history).toHaveLength(5);
|
|
124
|
+
});
|
|
125
|
+
it('handles multiple signals for same target in reward calculation', () => {
|
|
126
|
+
// 3 positive, 2 negative, 1 correction
|
|
127
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
128
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
129
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
130
|
+
engine.recordFeedback('insight', 1, 'negative');
|
|
131
|
+
engine.recordFeedback('insight', 1, 'negative');
|
|
132
|
+
engine.recordFeedback('insight', 1, 'correction');
|
|
133
|
+
const score = engine.getRewardScore('insight', 1);
|
|
134
|
+
// (3*1 + 2*-1 + 1*-0.5) / 6 = 0.5 / 6 = 0.0833...
|
|
135
|
+
expect(score).toBeCloseTo(0.5 / 6, 2);
|
|
136
|
+
});
|
|
137
|
+
it('calls synapse manager strengthen/weaken in applyRewards', () => {
|
|
138
|
+
const mockSynapseManager = {
|
|
139
|
+
strengthen: vi.fn(),
|
|
140
|
+
weaken: vi.fn(),
|
|
141
|
+
find: vi.fn().mockReturnValue({ id: 1, weight: 0.5 }),
|
|
142
|
+
};
|
|
143
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
144
|
+
engine.recordFeedback('prediction', 2, 'negative');
|
|
145
|
+
engine.applyRewards(mockSynapseManager);
|
|
146
|
+
expect(mockSynapseManager.strengthen).toHaveBeenCalled();
|
|
147
|
+
expect(mockSynapseManager.find).toHaveBeenCalled();
|
|
148
|
+
expect(mockSynapseManager.weaken).toHaveBeenCalled();
|
|
149
|
+
});
|
|
150
|
+
it('skips applyRewards without synapse manager', () => {
|
|
151
|
+
engine.recordFeedback('insight', 1, 'positive');
|
|
152
|
+
// Should not throw
|
|
153
|
+
expect(() => engine.applyRewards()).not.toThrow();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=feedback-engine.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback-engine.test.js","sourceRoot":"","sources":["../../../src/feedback/__tests__/feedback-engine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { ThoughtStream } from '../consciousness/thought-stream.js';
|
|
3
|
+
import type { BaseSynapseManager } from '../synapses/synapse-manager.js';
|
|
4
|
+
export interface FeedbackEngineConfig {
|
|
5
|
+
brainName: string;
|
|
6
|
+
/** Reward adjustment per positive signal. Default: 0.1 */
|
|
7
|
+
positiveRewardDelta?: number;
|
|
8
|
+
/** Reward adjustment per negative signal. Default: 0.1 */
|
|
9
|
+
negativeRewardDelta?: number;
|
|
10
|
+
}
|
|
11
|
+
export type FeedbackSignal = 'positive' | 'negative' | 'correction';
|
|
12
|
+
export interface FeedbackRecord {
|
|
13
|
+
id?: number;
|
|
14
|
+
target_type: string;
|
|
15
|
+
target_id: number;
|
|
16
|
+
signal: FeedbackSignal;
|
|
17
|
+
detail: string | null;
|
|
18
|
+
reward_score: number;
|
|
19
|
+
created_at: string;
|
|
20
|
+
}
|
|
21
|
+
export interface FeedbackCorrection {
|
|
22
|
+
id?: number;
|
|
23
|
+
target_type: string;
|
|
24
|
+
target_id: number;
|
|
25
|
+
original: string;
|
|
26
|
+
correction: string;
|
|
27
|
+
applied: number;
|
|
28
|
+
created_at: string;
|
|
29
|
+
}
|
|
30
|
+
export interface FeedbackStats {
|
|
31
|
+
totalFeedback: number;
|
|
32
|
+
positiveCount: number;
|
|
33
|
+
negativeCount: number;
|
|
34
|
+
correctionCount: number;
|
|
35
|
+
avgRewardScore: number;
|
|
36
|
+
}
|
|
37
|
+
export declare function runFeedbackMigration(db: Database.Database): void;
|
|
38
|
+
export declare class FeedbackEngine {
|
|
39
|
+
private readonly db;
|
|
40
|
+
private readonly config;
|
|
41
|
+
private readonly log;
|
|
42
|
+
private ts;
|
|
43
|
+
private readonly stmtInsertFeedback;
|
|
44
|
+
private readonly stmtGetFeedback;
|
|
45
|
+
private readonly stmtGetFeedbackHistory;
|
|
46
|
+
private readonly stmtCountBySignal;
|
|
47
|
+
private readonly stmtTotalFeedback;
|
|
48
|
+
private readonly stmtAvgReward;
|
|
49
|
+
private readonly stmtInsertCorrection;
|
|
50
|
+
private readonly stmtGetCorrections;
|
|
51
|
+
private readonly stmtDistinctTargets;
|
|
52
|
+
private readonly stmtGetRewardComponents;
|
|
53
|
+
constructor(db: Database.Database, config: FeedbackEngineConfig);
|
|
54
|
+
setThoughtStream(ts: ThoughtStream): void;
|
|
55
|
+
recordFeedback(type: string, targetId: number, signal: FeedbackSignal, detail?: string): FeedbackRecord;
|
|
56
|
+
getRewardScore(type: string, targetId: number): number;
|
|
57
|
+
applyRewards(synapseManager?: BaseSynapseManager): void;
|
|
58
|
+
learnFromCorrection(original: string, correction: string, targetType: string, targetId: number): FeedbackCorrection;
|
|
59
|
+
getStats(): FeedbackStats;
|
|
60
|
+
getFeedbackHistory(type: string, targetId: number, limit?: number): FeedbackRecord[];
|
|
61
|
+
}
|