@timmeck/brain-core 2.36.56 → 2.36.58

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.
Files changed (152) hide show
  1. package/README.md +6 -0
  2. package/command-center.html +133 -2
  3. package/dist/action/__tests__/action-bridge.test.d.ts +1 -0
  4. package/dist/action/__tests__/action-bridge.test.js +145 -0
  5. package/dist/action/__tests__/action-bridge.test.js.map +1 -0
  6. package/dist/action/__tests__/content-handler.test.d.ts +1 -0
  7. package/dist/action/__tests__/content-handler.test.js +100 -0
  8. package/dist/action/__tests__/content-handler.test.js.map +1 -0
  9. package/dist/action/__tests__/trade-handler.test.d.ts +1 -0
  10. package/dist/action/__tests__/trade-handler.test.js +165 -0
  11. package/dist/action/__tests__/trade-handler.test.js.map +1 -0
  12. package/dist/action/action-bridge.d.ts +95 -0
  13. package/dist/action/action-bridge.js +242 -0
  14. package/dist/action/action-bridge.js.map +1 -0
  15. package/dist/action/handlers/content-handler.d.ts +23 -0
  16. package/dist/action/handlers/content-handler.js +30 -0
  17. package/dist/action/handlers/content-handler.js.map +1 -0
  18. package/dist/action/handlers/index.d.ts +4 -0
  19. package/dist/action/handlers/index.js +3 -0
  20. package/dist/action/handlers/index.js.map +1 -0
  21. package/dist/action/handlers/trade-handler.d.ts +43 -0
  22. package/dist/action/handlers/trade-handler.js +43 -0
  23. package/dist/action/handlers/trade-handler.js.map +1 -0
  24. package/dist/action/index.d.ts +4 -0
  25. package/dist/action/index.js +3 -0
  26. package/dist/action/index.js.map +1 -0
  27. package/dist/agent-training/__tests__/agent-trainer.test.d.ts +1 -0
  28. package/dist/agent-training/__tests__/agent-trainer.test.js +158 -0
  29. package/dist/agent-training/__tests__/agent-trainer.test.js.map +1 -0
  30. package/dist/agent-training/__tests__/sub-agent-factory.test.d.ts +1 -0
  31. package/dist/agent-training/__tests__/sub-agent-factory.test.js +100 -0
  32. package/dist/agent-training/__tests__/sub-agent-factory.test.js.map +1 -0
  33. package/dist/agent-training/__tests__/sub-agent.test.d.ts +1 -0
  34. package/dist/agent-training/__tests__/sub-agent.test.js +102 -0
  35. package/dist/agent-training/__tests__/sub-agent.test.js.map +1 -0
  36. package/dist/agent-training/index.d.ts +4 -0
  37. package/dist/agent-training/index.js +2 -0
  38. package/dist/agent-training/index.js.map +1 -1
  39. package/dist/agent-training/sub-agent-factory.d.ts +36 -0
  40. package/dist/agent-training/sub-agent-factory.js +128 -0
  41. package/dist/agent-training/sub-agent-factory.js.map +1 -0
  42. package/dist/agent-training/sub-agent.d.ts +57 -0
  43. package/dist/agent-training/sub-agent.js +135 -0
  44. package/dist/agent-training/sub-agent.js.map +1 -0
  45. package/dist/chat/__tests__/chat-engine.test.d.ts +1 -0
  46. package/dist/chat/__tests__/chat-engine.test.js +128 -0
  47. package/dist/chat/__tests__/chat-engine.test.js.map +1 -0
  48. package/dist/chat/chat-engine.d.ts +55 -0
  49. package/dist/chat/chat-engine.js +186 -0
  50. package/dist/chat/chat-engine.js.map +1 -0
  51. package/dist/chat/index.d.ts +2 -0
  52. package/dist/chat/index.js +2 -0
  53. package/dist/chat/index.js.map +1 -0
  54. package/dist/codegen/__tests__/code-forge.test.d.ts +1 -0
  55. package/dist/codegen/__tests__/code-forge.test.js +105 -0
  56. package/dist/codegen/__tests__/code-forge.test.js.map +1 -0
  57. package/dist/codegen/code-forge.d.ts +87 -0
  58. package/dist/codegen/code-forge.js +211 -0
  59. package/dist/codegen/code-forge.js.map +1 -0
  60. package/dist/codegen/index.d.ts +2 -0
  61. package/dist/codegen/index.js +1 -0
  62. package/dist/codegen/index.js.map +1 -1
  63. package/dist/content/__tests__/auto-publisher.test.d.ts +1 -0
  64. package/dist/content/__tests__/auto-publisher.test.js +125 -0
  65. package/dist/content/__tests__/auto-publisher.test.js.map +1 -0
  66. package/dist/content/__tests__/content-forge.test.d.ts +1 -0
  67. package/dist/content/__tests__/content-forge.test.js +117 -0
  68. package/dist/content/__tests__/content-forge.test.js.map +1 -0
  69. package/dist/content/auto-publisher.d.ts +51 -0
  70. package/dist/content/auto-publisher.js +147 -0
  71. package/dist/content/auto-publisher.js.map +1 -0
  72. package/dist/content/content-forge.d.ts +106 -0
  73. package/dist/content/content-forge.js +232 -0
  74. package/dist/content/content-forge.js.map +1 -0
  75. package/dist/content/index.d.ts +4 -0
  76. package/dist/content/index.js +3 -0
  77. package/dist/content/index.js.map +1 -0
  78. package/dist/creative/__tests__/creative-engine.test.d.ts +1 -0
  79. package/dist/creative/__tests__/creative-engine.test.js +151 -0
  80. package/dist/creative/__tests__/creative-engine.test.js.map +1 -0
  81. package/dist/cross-brain/__tests__/signal-router.test.d.ts +1 -0
  82. package/dist/cross-brain/__tests__/signal-router.test.js +159 -0
  83. package/dist/cross-brain/__tests__/signal-router.test.js.map +1 -0
  84. package/dist/cross-brain/signal-router.d.ts +57 -0
  85. package/dist/cross-brain/signal-router.js +148 -0
  86. package/dist/cross-brain/signal-router.js.map +1 -0
  87. package/dist/dashboard/__tests__/command-center-server.test.js +31 -0
  88. package/dist/dashboard/__tests__/command-center-server.test.js.map +1 -1
  89. package/dist/dashboard/command-center-server.d.ts +11 -0
  90. package/dist/dashboard/command-center-server.js +72 -0
  91. package/dist/dashboard/command-center-server.js.map +1 -1
  92. package/dist/dream/__tests__/dream-engine.test.d.ts +1 -0
  93. package/dist/dream/__tests__/dream-engine.test.js +184 -0
  94. package/dist/dream/__tests__/dream-engine.test.js.map +1 -0
  95. package/dist/feedback/__tests__/feedback-router.test.d.ts +1 -0
  96. package/dist/feedback/__tests__/feedback-router.test.js +173 -0
  97. package/dist/feedback/__tests__/feedback-router.test.js.map +1 -0
  98. package/dist/feedback/feedback-router.d.ts +53 -0
  99. package/dist/feedback/feedback-router.js +193 -0
  100. package/dist/feedback/feedback-router.js.map +1 -0
  101. package/dist/feedback/index.d.ts +2 -0
  102. package/dist/feedback/index.js +1 -0
  103. package/dist/feedback/index.js.map +1 -1
  104. package/dist/goals/__tests__/goal-engine.test.d.ts +1 -0
  105. package/dist/goals/__tests__/goal-engine.test.js +203 -0
  106. package/dist/goals/__tests__/goal-engine.test.js.map +1 -0
  107. package/dist/guardrails/__tests__/guardrail-engine.test.d.ts +1 -0
  108. package/dist/guardrails/__tests__/guardrail-engine.test.js +343 -0
  109. package/dist/guardrails/__tests__/guardrail-engine.test.js.map +1 -0
  110. package/dist/index.d.ts +16 -0
  111. package/dist/index.js +13 -0
  112. package/dist/index.js.map +1 -1
  113. package/dist/metacognition/__tests__/auto-experiment-engine.test.d.ts +1 -0
  114. package/dist/metacognition/__tests__/auto-experiment-engine.test.js +218 -0
  115. package/dist/metacognition/__tests__/auto-experiment-engine.test.js.map +1 -0
  116. package/dist/metacognition/__tests__/evolution-engine.test.d.ts +1 -0
  117. package/dist/metacognition/__tests__/evolution-engine.test.js +473 -0
  118. package/dist/metacognition/__tests__/evolution-engine.test.js.map +1 -0
  119. package/dist/metacognition/__tests__/parameter-registry.test.d.ts +1 -0
  120. package/dist/metacognition/__tests__/parameter-registry.test.js +223 -0
  121. package/dist/metacognition/__tests__/parameter-registry.test.js.map +1 -0
  122. package/dist/prediction/__tests__/prediction-engine.test.d.ts +1 -0
  123. package/dist/prediction/__tests__/prediction-engine.test.js +244 -0
  124. package/dist/prediction/__tests__/prediction-engine.test.js.map +1 -0
  125. package/dist/research/research-orchestrator.d.ts +12 -0
  126. package/dist/research/research-orchestrator.js +109 -0
  127. package/dist/research/research-orchestrator.js.map +1 -1
  128. package/dist/sandbox/__tests__/code-sandbox.test.d.ts +1 -0
  129. package/dist/sandbox/__tests__/code-sandbox.test.js +182 -0
  130. package/dist/sandbox/__tests__/code-sandbox.test.js.map +1 -0
  131. package/dist/scanner/__tests__/signal-scanner.test.d.ts +1 -0
  132. package/dist/scanner/__tests__/signal-scanner.test.js +142 -0
  133. package/dist/scanner/__tests__/signal-scanner.test.js.map +1 -0
  134. package/dist/self-modification/__tests__/self-modification-engine.test.d.ts +1 -0
  135. package/dist/self-modification/__tests__/self-modification-engine.test.js +255 -0
  136. package/dist/self-modification/__tests__/self-modification-engine.test.js.map +1 -0
  137. package/dist/strategy/__tests__/strategy-forge.test.d.ts +1 -0
  138. package/dist/strategy/__tests__/strategy-forge.test.js +190 -0
  139. package/dist/strategy/__tests__/strategy-forge.test.js.map +1 -0
  140. package/dist/strategy/__tests__/strategy-mutator.test.d.ts +1 -0
  141. package/dist/strategy/__tests__/strategy-mutator.test.js +141 -0
  142. package/dist/strategy/__tests__/strategy-mutator.test.js.map +1 -0
  143. package/dist/strategy/index.d.ts +4 -0
  144. package/dist/strategy/index.js +3 -0
  145. package/dist/strategy/index.js.map +1 -0
  146. package/dist/strategy/strategy-forge.d.ts +114 -0
  147. package/dist/strategy/strategy-forge.js +296 -0
  148. package/dist/strategy/strategy-forge.js.map +1 -0
  149. package/dist/strategy/strategy-mutator.d.ts +42 -0
  150. package/dist/strategy/strategy-mutator.js +140 -0
  151. package/dist/strategy/strategy-mutator.js.map +1 -0
  152. package/package.json +1 -1
@@ -0,0 +1,184 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import Database from 'better-sqlite3';
3
+ vi.mock('../../utils/logger.js', () => ({
4
+ getLogger: () => ({ info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }),
5
+ }));
6
+ import { DreamEngine, runDreamMigration } from '../dream-engine.js';
7
+ describe('DreamEngine', () => {
8
+ let db;
9
+ beforeEach(() => {
10
+ db = new Database(':memory:');
11
+ });
12
+ afterEach(() => {
13
+ db.close();
14
+ });
15
+ // ── 1. Creation ────────────────────────────────────────
16
+ it('creates an instance and runs migration', () => {
17
+ const engine = new DreamEngine(db, { brainName: 'test' });
18
+ expect(engine).toBeDefined();
19
+ // Migration should have created the tables
20
+ const tables = db.prepare(`
21
+ SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('dream_history', 'dream_state', 'dream_retrospective')
22
+ ORDER BY name
23
+ `).all();
24
+ expect(tables.map(t => t.name)).toEqual(['dream_history', 'dream_retrospective', 'dream_state']);
25
+ });
26
+ // ── 2. getStatus (initial) ─────────────────────────────
27
+ it('returns initial status with zero counters', () => {
28
+ const engine = new DreamEngine(db, { brainName: 'test' });
29
+ const status = engine.getStatus();
30
+ expect(status.running).toBe(false);
31
+ expect(status.totalCycles).toBe(0);
32
+ expect(status.lastDreamAt).toBeNull();
33
+ expect(status.totals.memoriesConsolidated).toBe(0);
34
+ expect(status.totals.synapsesPruned).toBe(0);
35
+ expect(status.totals.memoriesArchived).toBe(0);
36
+ });
37
+ // ── 3. recordActivity ─────────────────────────────────
38
+ it('recordActivity updates the last activity timestamp', () => {
39
+ const engine = new DreamEngine(db, { brainName: 'test' });
40
+ const before = Date.now();
41
+ engine.recordActivity();
42
+ const after = Date.now();
43
+ // Access private field via cast — recordActivity should have set lastActivityTimestamp
44
+ // We verify indirectly: start + timer callback should NOT trigger if just recorded activity
45
+ // Direct test: engine should not throw and should update internal state
46
+ expect(() => engine.recordActivity()).not.toThrow();
47
+ // Verify the engine is still functional after recording activity
48
+ const status = engine.getStatus();
49
+ expect(status.running).toBe(false);
50
+ });
51
+ // ── 4. consolidate (basic) ────────────────────────────
52
+ it('runs a consolidation cycle and persists history', () => {
53
+ const engine = new DreamEngine(db, { brainName: 'test' });
54
+ const report = engine.consolidate('manual');
55
+ expect(report.cycleId).toMatch(/^dream-test-/);
56
+ expect(report.trigger).toBe('manual');
57
+ expect(report.duration).toBeGreaterThanOrEqual(0);
58
+ expect(report.replay.memoriesReplayed).toBe(0); // no memories table
59
+ expect(report.pruning.synapsesPruned).toBe(0); // no synapses table
60
+ expect(report.compression.memoriesConsolidated).toBe(0);
61
+ expect(report.decay.memoriesDecayed).toBe(0);
62
+ expect(report.principlesDiscovered).toBe(0);
63
+ expect(report.journalEntryId).toBeNull();
64
+ // Status should reflect one cycle
65
+ const status = engine.getStatus();
66
+ expect(status.totalCycles).toBe(1);
67
+ expect(status.lastDreamAt).toBeGreaterThan(0);
68
+ });
69
+ // ── 5. consolidate with synapses ──────────────────────
70
+ it('prunes weak synapses during consolidation', () => {
71
+ // Create synapses table so the consolidator can interact with it
72
+ db.exec(`
73
+ CREATE TABLE synapses (
74
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
75
+ source_type TEXT NOT NULL,
76
+ source_id TEXT NOT NULL,
77
+ target_type TEXT NOT NULL,
78
+ target_id TEXT NOT NULL,
79
+ weight REAL NOT NULL DEFAULT 0.5,
80
+ last_activated_at TEXT,
81
+ created_at TEXT DEFAULT (datetime('now'))
82
+ );
83
+ `);
84
+ // Insert a weak synapse (below default threshold 0.15)
85
+ db.prepare(`INSERT INTO synapses (source_type, source_id, target_type, target_id, weight) VALUES (?, ?, ?, ?, ?)`).run('memory', '1', 'memory', '2', 0.05);
86
+ // Insert a strong synapse (above threshold)
87
+ db.prepare(`INSERT INTO synapses (source_type, source_id, target_type, target_id, weight) VALUES (?, ?, ?, ?, ?)`).run('memory', '3', 'memory', '4', 0.8);
88
+ const engine = new DreamEngine(db, { brainName: 'test' });
89
+ const report = engine.consolidate('manual');
90
+ expect(report.pruning.synapsesPruned).toBe(1);
91
+ // Only the strong synapse should remain
92
+ const remaining = db.prepare('SELECT COUNT(*) as cnt FROM synapses').get();
93
+ expect(remaining.cnt).toBe(1);
94
+ });
95
+ // ── 6. getHistory ─────────────────────────────────────
96
+ it('returns dream history ordered by timestamp descending', () => {
97
+ const engine = new DreamEngine(db, { brainName: 'test' });
98
+ engine.consolidate('manual');
99
+ engine.consolidate('idle');
100
+ engine.consolidate('auto');
101
+ const history = engine.getHistory();
102
+ expect(history).toHaveLength(3);
103
+ // Most recent first
104
+ expect(history[0].trigger).toBe('auto');
105
+ expect(history[1].trigger).toBe('idle');
106
+ expect(history[2].trigger).toBe('manual');
107
+ });
108
+ it('respects the limit parameter for getHistory', () => {
109
+ const engine = new DreamEngine(db, { brainName: 'test' });
110
+ engine.consolidate('manual');
111
+ engine.consolidate('idle');
112
+ engine.consolidate('auto');
113
+ const history = engine.getHistory(2);
114
+ expect(history).toHaveLength(2);
115
+ });
116
+ // ── 7. getPruningEfficiency ───────────────────────────
117
+ it('returns default pruning efficiency when no retrospective data', () => {
118
+ const engine = new DreamEngine(db, { brainName: 'test' });
119
+ const efficiency = engine.getPruningEfficiency();
120
+ expect(efficiency.totalPruned).toBe(0);
121
+ expect(efficiency.totalReappeared).toBe(0);
122
+ expect(efficiency.avgRegretScore).toBe(0);
123
+ expect(efficiency.efficiencyRate).toBe(1);
124
+ });
125
+ it('calculates pruning efficiency from retrospective records', () => {
126
+ const engine = new DreamEngine(db, { brainName: 'test' });
127
+ // Manually insert retrospective records with known regret scores
128
+ db.prepare(`
129
+ INSERT INTO dream_retrospective (dream_cycle_id, pruned_items, reappeared_count, regret_score, lesson)
130
+ VALUES (?, ?, ?, ?, ?)
131
+ `).run('cycle-1', JSON.stringify([{ synapseId: 1, weight: 0.1 }, { synapseId: 2, weight: 0.12 }]), 1, 0.5, 'test lesson');
132
+ db.prepare(`
133
+ INSERT INTO dream_retrospective (dream_cycle_id, pruned_items, reappeared_count, regret_score, lesson)
134
+ VALUES (?, ?, ?, ?, ?)
135
+ `).run('cycle-2', JSON.stringify([{ synapseId: 3, weight: 0.08 }]), 0, 0.0, 'no regret');
136
+ const efficiency = engine.getPruningEfficiency();
137
+ // Only records with regret_score > 0 OR reappeared_count > 0 are included (cycle-1 matches)
138
+ expect(efficiency.totalPruned).toBeGreaterThanOrEqual(1);
139
+ expect(efficiency.efficiencyRate).toBeLessThanOrEqual(1);
140
+ expect(efficiency.efficiencyRate).toBe(1 - efficiency.avgRegretScore);
141
+ });
142
+ // ── 8. analyzeRetrospective ───────────────────────────
143
+ it('analyzes retrospective and produces regret scores', () => {
144
+ const engine = new DreamEngine(db, { brainName: 'test' });
145
+ // Insert a retrospective record with pruned items
146
+ const prunedItems = [{ synapseId: 100, weight: 0.1 }, { synapseId: 101, weight: 0.12 }];
147
+ db.prepare(`
148
+ INSERT INTO dream_retrospective (dream_cycle_id, pruned_items)
149
+ VALUES (?, ?)
150
+ `).run('dream-test-retro-1', JSON.stringify(prunedItems));
151
+ const results = engine.analyzeRetrospective(5);
152
+ expect(results).toHaveLength(1);
153
+ expect(results[0].dreamCycleId).toBe('dream-test-retro-1');
154
+ expect(results[0].prunedItems).toHaveLength(2);
155
+ expect(typeof results[0].regretScore).toBe('number');
156
+ expect(results[0].lesson).toBeTruthy();
157
+ });
158
+ // ── 9. start and stop ─────────────────────────────────
159
+ it('start sets running to true, stop resets it', () => {
160
+ const engine = new DreamEngine(db, { brainName: 'test', intervalMs: 60_000 });
161
+ expect(engine.getStatus().running).toBe(false);
162
+ engine.start();
163
+ expect(engine.getStatus().running).toBe(true);
164
+ // Starting again should be a no-op (no duplicate timers)
165
+ engine.start();
166
+ expect(engine.getStatus().running).toBe(true);
167
+ engine.stop();
168
+ expect(engine.getStatus().running).toBe(false);
169
+ // Stopping again should be safe
170
+ engine.stop();
171
+ expect(engine.getStatus().running).toBe(false);
172
+ });
173
+ // ── 10. runDreamMigration is idempotent ───────────────
174
+ it('runDreamMigration can be called multiple times safely', () => {
175
+ runDreamMigration(db);
176
+ runDreamMigration(db);
177
+ runDreamMigration(db);
178
+ // Tables should still exist with correct structure
179
+ const state = db.prepare('SELECT * FROM dream_state WHERE id = 1').get();
180
+ expect(state).toBeDefined();
181
+ expect(state.total_cycles).toBe(0);
182
+ });
183
+ });
184
+ //# sourceMappingURL=dream-engine.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dream-engine.test.js","sourceRoot":"","sources":["../../../src/dream/__tests__/dream-engine.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,173 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import Database from 'better-sqlite3';
3
+ vi.mock('../../utils/logger.js', () => ({
4
+ getLogger: () => ({ info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }),
5
+ }));
6
+ import { FeedbackRouter } from '../feedback-router.js';
7
+ describe('FeedbackRouter', () => {
8
+ let db;
9
+ beforeEach(() => { db = new Database(':memory:'); });
10
+ afterEach(() => { db.close(); });
11
+ it('creates with empty state', () => {
12
+ const router = new FeedbackRouter(db);
13
+ const status = router.getStatus();
14
+ expect(status.sources).toBe(0);
15
+ expect(status.totalProcessed).toBe(0);
16
+ expect(status.totalActions).toBe(0);
17
+ });
18
+ it('registers sources', () => {
19
+ const router = new FeedbackRouter(db);
20
+ router.addSource({ name: 'test', fetch: () => [] });
21
+ router.addSource({ name: 'test2', fetch: () => [] });
22
+ expect(router.getStatus().sources).toBe(2);
23
+ });
24
+ it('processes AB test winner', async () => {
25
+ const router = new FeedbackRouter(db);
26
+ const actions = [];
27
+ router.setActionHandler(async (a) => { actions.push(a); });
28
+ router.addSource({
29
+ name: 'ab-test',
30
+ fetch: () => [{
31
+ source: 'ab-test',
32
+ type: 'ab_winner',
33
+ data: { winner: 'b', metric: 'click_rate', testId: 42 },
34
+ confidence: 0.85,
35
+ }],
36
+ });
37
+ const result = await router.processAll();
38
+ expect(result.items).toBe(1);
39
+ expect(result.actions).toBe(1);
40
+ expect(actions[0].type).toBe('adjust_parameter');
41
+ expect(actions[0].payload.value).toBe('b');
42
+ });
43
+ it('skips low-confidence AB winners', async () => {
44
+ const router = new FeedbackRouter(db);
45
+ const actions = [];
46
+ router.setActionHandler(async (a) => { actions.push(a); });
47
+ router.addSource({
48
+ name: 'ab-test',
49
+ fetch: () => [{
50
+ source: 'ab-test',
51
+ type: 'ab_winner',
52
+ data: { winner: 'a' },
53
+ confidence: 0.3,
54
+ }],
55
+ });
56
+ await router.processAll();
57
+ expect(actions).toHaveLength(0);
58
+ });
59
+ it('processes competitor insights with topic seed', async () => {
60
+ const router = new FeedbackRouter(db);
61
+ const actions = [];
62
+ router.setActionHandler(async (a) => { actions.push(a); });
63
+ router.addSource({
64
+ name: 'competitor',
65
+ fetch: () => [{
66
+ source: 'competitor',
67
+ type: 'competitor_insight',
68
+ data: { verdict: 'Competitor posts more frequently', topicSeed: 'AI trends', competitorId: 5 },
69
+ confidence: 0.7,
70
+ }],
71
+ });
72
+ await router.processAll();
73
+ expect(actions).toHaveLength(2); // frequency + topic seed
74
+ expect(actions[0].type).toBe('adjust_parameter');
75
+ expect(actions[1].type).toBe('creative_seed');
76
+ });
77
+ it('processes user patterns', async () => {
78
+ const router = new FeedbackRouter(db);
79
+ const actions = [];
80
+ router.setActionHandler(async (a) => { actions.push(a); });
81
+ router.addSource({
82
+ name: 'user-model',
83
+ fetch: () => [{
84
+ source: 'user-model',
85
+ type: 'user_pattern',
86
+ data: { activeHours: [9, 10, 14, 15, 16] },
87
+ confidence: 0.6,
88
+ }],
89
+ });
90
+ await router.processAll();
91
+ expect(actions).toHaveLength(1);
92
+ expect(actions[0].payload.parameter).toBe('optimal_posting_hours');
93
+ });
94
+ it('processes engagement feedback', async () => {
95
+ const router = new FeedbackRouter(db);
96
+ const actions = [];
97
+ router.setActionHandler(async (a) => { actions.push(a); });
98
+ router.addSource({
99
+ name: 'engagement',
100
+ fetch: () => [{
101
+ source: 'engagement',
102
+ type: 'engagement_feedback',
103
+ data: { avgEngagement: 42.5 },
104
+ confidence: 0.9,
105
+ }],
106
+ });
107
+ await router.processAll();
108
+ expect(actions).toHaveLength(1);
109
+ expect(actions[0].payload.value).toBe(42.5);
110
+ });
111
+ it('handles source errors gracefully', async () => {
112
+ const router = new FeedbackRouter(db);
113
+ router.addSource({
114
+ name: 'broken',
115
+ fetch: () => { throw new Error('DB locked'); },
116
+ });
117
+ const result = await router.processAll();
118
+ expect(result.items).toBe(0);
119
+ });
120
+ it('handles action handler errors gracefully', async () => {
121
+ const router = new FeedbackRouter(db);
122
+ router.setActionHandler(async () => { throw new Error('handler fail'); });
123
+ router.addSource({
124
+ name: 'test',
125
+ fetch: () => [{ source: 'test', type: 'engagement_feedback', data: { avgEngagement: 10 }, confidence: 0.9 }],
126
+ });
127
+ const result = await router.processAll();
128
+ expect(result.actions).toBe(1); // action counted even if handler fails
129
+ });
130
+ it('processes multiple sources in one run', async () => {
131
+ const router = new FeedbackRouter(db);
132
+ const actions = [];
133
+ router.setActionHandler(async (a) => { actions.push(a); });
134
+ router.addSource({ name: 'src1', fetch: () => [{ source: 'src1', type: 'engagement_feedback', data: { avgEngagement: 10 }, confidence: 0.9 }] });
135
+ router.addSource({ name: 'src2', fetch: () => [{ source: 'src2', type: 'user_pattern', data: { activeHours: [8] }, confidence: 0.6 }] });
136
+ const result = await router.processAll();
137
+ expect(result.items).toBe(2);
138
+ expect(result.actions).toBe(2);
139
+ });
140
+ it('logs items without actions', async () => {
141
+ const router = new FeedbackRouter(db);
142
+ router.addSource({
143
+ name: 'test',
144
+ fetch: () => [{ source: 'test', type: 'custom', data: { foo: 'bar' }, confidence: 0.3 }],
145
+ });
146
+ await router.processAll();
147
+ const status = router.getStatus();
148
+ expect(status.totalProcessed).toBe(1);
149
+ expect(status.totalActions).toBe(0);
150
+ });
151
+ it('passes custom items with high confidence and actionType', async () => {
152
+ const router = new FeedbackRouter(db);
153
+ const actions = [];
154
+ router.setActionHandler(async (a) => { actions.push(a); });
155
+ router.addSource({
156
+ name: 'custom',
157
+ fetch: () => [{ source: 'custom', type: 'custom', data: { actionType: 'special_action', key: 'val' }, confidence: 0.9 }],
158
+ });
159
+ await router.processAll();
160
+ expect(actions).toHaveLength(1);
161
+ expect(actions[0].type).toBe('special_action');
162
+ });
163
+ it('updates status after processing', async () => {
164
+ const router = new FeedbackRouter(db);
165
+ router.addSource({ name: 's', fetch: () => [{ source: 's', type: 'engagement_feedback', data: { avgEngagement: 5 }, confidence: 0.8 }] });
166
+ router.setActionHandler(async () => { });
167
+ await router.processAll();
168
+ const status = router.getStatus();
169
+ expect(status.totalProcessed).toBeGreaterThan(0);
170
+ expect(status.lastRunAt).toBeTruthy();
171
+ });
172
+ });
173
+ //# sourceMappingURL=feedback-router.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback-router.test.js","sourceRoot":"","sources":["../../../src/feedback/__tests__/feedback-router.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type Database from 'better-sqlite3';
2
+ export interface FeedbackSource {
3
+ name: string;
4
+ /** Fetch actionable items from this source */
5
+ fetch: () => FeedbackItem[] | Promise<FeedbackItem[]>;
6
+ }
7
+ export interface FeedbackItem {
8
+ source: string;
9
+ type: 'ab_winner' | 'competitor_insight' | 'user_pattern' | 'engagement_feedback' | 'custom';
10
+ data: Record<string, unknown>;
11
+ confidence: number;
12
+ }
13
+ export interface FeedbackAction {
14
+ type: string;
15
+ payload: Record<string, unknown>;
16
+ source: string;
17
+ confidence: number;
18
+ }
19
+ export interface FeedbackRouterStatus {
20
+ sources: number;
21
+ totalProcessed: number;
22
+ totalActions: number;
23
+ lastRunAt: string | null;
24
+ }
25
+ type ActionHandler = (action: FeedbackAction) => void | Promise<void>;
26
+ export declare function runFeedbackRouterMigration(db: Database.Database): void;
27
+ /**
28
+ * FeedbackRouter — collects feedback from multiple sources (ABTest, Competitor, UserModel, etc.)
29
+ * and generates ActionBridge proposals or direct engine adjustments.
30
+ */
31
+ export declare class FeedbackRouter {
32
+ private readonly db;
33
+ private readonly sources;
34
+ private actionHandler;
35
+ private readonly stmtInsert;
36
+ private readonly stmtCount;
37
+ private readonly stmtLastRun;
38
+ constructor(db: Database.Database);
39
+ /** Register a feedback source */
40
+ addSource(source: FeedbackSource): void;
41
+ /** Set handler for generated actions (typically ActionBridge.propose) */
42
+ setActionHandler(handler: ActionHandler): void;
43
+ /** Process all sources and generate actions */
44
+ processAll(): Promise<{
45
+ items: number;
46
+ actions: number;
47
+ }>;
48
+ /** Get status */
49
+ getStatus(): FeedbackRouterStatus;
50
+ /** Route a feedback item to concrete actions */
51
+ private routeItem;
52
+ }
53
+ export {};
@@ -0,0 +1,193 @@
1
+ import { getLogger } from '../utils/logger.js';
2
+ // ── Migration ──────────────────────────────────────────────
3
+ export function runFeedbackRouterMigration(db) {
4
+ db.exec(`
5
+ CREATE TABLE IF NOT EXISTS feedback_router_log (
6
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
7
+ source TEXT NOT NULL,
8
+ type TEXT NOT NULL,
9
+ action_type TEXT,
10
+ payload TEXT DEFAULT '{}',
11
+ confidence REAL DEFAULT 0,
12
+ timestamp INTEGER NOT NULL
13
+ );
14
+ CREATE INDEX IF NOT EXISTS idx_frl_source ON feedback_router_log(source);
15
+ CREATE INDEX IF NOT EXISTS idx_frl_timestamp ON feedback_router_log(timestamp);
16
+ `);
17
+ }
18
+ // ── Router ──────────────────────────────────────────────────
19
+ const log = getLogger();
20
+ /**
21
+ * FeedbackRouter — collects feedback from multiple sources (ABTest, Competitor, UserModel, etc.)
22
+ * and generates ActionBridge proposals or direct engine adjustments.
23
+ */
24
+ export class FeedbackRouter {
25
+ db;
26
+ sources = [];
27
+ actionHandler = null;
28
+ stmtInsert;
29
+ stmtCount;
30
+ stmtLastRun;
31
+ constructor(db) {
32
+ this.db = db;
33
+ runFeedbackRouterMigration(db);
34
+ this.stmtInsert = db.prepare(`INSERT INTO feedback_router_log (source, type, action_type, payload, confidence, timestamp) VALUES (?, ?, ?, ?, ?, ?)`);
35
+ this.stmtCount = db.prepare(`SELECT COUNT(*) as count FROM feedback_router_log`);
36
+ this.stmtLastRun = db.prepare(`SELECT MAX(timestamp) as ts FROM feedback_router_log`);
37
+ }
38
+ /** Register a feedback source */
39
+ addSource(source) {
40
+ this.sources.push(source);
41
+ }
42
+ /** Set handler for generated actions (typically ActionBridge.propose) */
43
+ setActionHandler(handler) {
44
+ this.actionHandler = handler;
45
+ }
46
+ /** Process all sources and generate actions */
47
+ async processAll() {
48
+ let totalItems = 0;
49
+ let totalActions = 0;
50
+ for (const source of this.sources) {
51
+ try {
52
+ const items = await source.fetch();
53
+ totalItems += items.length;
54
+ for (const item of items) {
55
+ const actions = this.routeItem(item);
56
+ for (const action of actions) {
57
+ this.stmtInsert.run(item.source, item.type, action.type, JSON.stringify(action.payload), action.confidence, Date.now());
58
+ if (this.actionHandler) {
59
+ try {
60
+ await this.actionHandler(action);
61
+ }
62
+ catch (err) {
63
+ log.warn(`[feedback-router] Action handler error: ${err.message}`);
64
+ }
65
+ }
66
+ totalActions++;
67
+ }
68
+ // Log items that didn't produce actions
69
+ if (actions.length === 0) {
70
+ this.stmtInsert.run(item.source, item.type, null, JSON.stringify(item.data), item.confidence, Date.now());
71
+ }
72
+ }
73
+ }
74
+ catch (err) {
75
+ log.warn(`[feedback-router] Source "${source.name}" error: ${err.message}`);
76
+ }
77
+ }
78
+ log.info(`[feedback-router] Processed ${totalItems} items → ${totalActions} actions`);
79
+ return { items: totalItems, actions: totalActions };
80
+ }
81
+ /** Get status */
82
+ getStatus() {
83
+ const count = this.stmtCount.get().count;
84
+ const lastTs = this.stmtLastRun.get().ts;
85
+ const actionCount = this.db.prepare(`SELECT COUNT(*) as count FROM feedback_router_log WHERE action_type IS NOT NULL`).get().count;
86
+ return {
87
+ sources: this.sources.length,
88
+ totalProcessed: count,
89
+ totalActions: actionCount,
90
+ lastRunAt: lastTs ? new Date(lastTs).toISOString() : null,
91
+ };
92
+ }
93
+ // ── Private ──────────────────────────────────────────────
94
+ /** Route a feedback item to concrete actions */
95
+ routeItem(item) {
96
+ const actions = [];
97
+ switch (item.type) {
98
+ case 'ab_winner': {
99
+ // AB test winner → adjust content parameters
100
+ const winner = item.data.winner;
101
+ const metric = item.data.metric;
102
+ if (winner && item.confidence >= 0.7) {
103
+ actions.push({
104
+ type: 'adjust_parameter',
105
+ payload: {
106
+ parameter: metric ?? 'content_template',
107
+ value: winner,
108
+ reason: `AB test winner: variant ${winner}`,
109
+ testId: item.data.testId,
110
+ },
111
+ source: item.source,
112
+ confidence: item.confidence,
113
+ });
114
+ }
115
+ break;
116
+ }
117
+ case 'competitor_insight': {
118
+ // Competitor insight → creative seed or frequency adjustment
119
+ const verdict = item.data.verdict;
120
+ if (verdict && item.confidence >= 0.5) {
121
+ actions.push({
122
+ type: 'adjust_parameter',
123
+ payload: {
124
+ parameter: 'posting_frequency',
125
+ reason: `Competitor analysis: ${verdict}`,
126
+ competitorId: item.data.competitorId,
127
+ },
128
+ source: item.source,
129
+ confidence: item.confidence,
130
+ });
131
+ }
132
+ if (item.data.topicSeed) {
133
+ actions.push({
134
+ type: 'creative_seed',
135
+ payload: {
136
+ topic: item.data.topicSeed,
137
+ reason: 'Trending competitor topic',
138
+ },
139
+ source: item.source,
140
+ confidence: item.confidence,
141
+ });
142
+ }
143
+ break;
144
+ }
145
+ case 'user_pattern': {
146
+ // User model pattern → schedule optimization
147
+ const activeHours = item.data.activeHours;
148
+ if (activeHours && activeHours.length > 0) {
149
+ actions.push({
150
+ type: 'adjust_parameter',
151
+ payload: {
152
+ parameter: 'optimal_posting_hours',
153
+ value: activeHours,
154
+ reason: 'User activity pattern',
155
+ },
156
+ source: item.source,
157
+ confidence: item.confidence,
158
+ });
159
+ }
160
+ break;
161
+ }
162
+ case 'engagement_feedback': {
163
+ // Engagement data → content strategy adjustment
164
+ const avgEngagement = item.data.avgEngagement;
165
+ if (typeof avgEngagement === 'number') {
166
+ actions.push({
167
+ type: 'adjust_parameter',
168
+ payload: {
169
+ parameter: 'engagement_baseline',
170
+ value: avgEngagement,
171
+ reason: 'Engagement trend update',
172
+ },
173
+ source: item.source,
174
+ confidence: item.confidence,
175
+ });
176
+ }
177
+ break;
178
+ }
179
+ default:
180
+ // Custom items pass through if high confidence
181
+ if (item.confidence >= 0.8 && item.data.actionType) {
182
+ actions.push({
183
+ type: item.data.actionType,
184
+ payload: item.data,
185
+ source: item.source,
186
+ confidence: item.confidence,
187
+ });
188
+ }
189
+ }
190
+ return actions;
191
+ }
192
+ }
193
+ //# sourceMappingURL=feedback-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback-router.js","sourceRoot":"","sources":["../../src/feedback/feedback-router.ts"],"names":[],"mappings":"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"}