@soleri/core 2.5.0 → 2.7.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.
Files changed (84) hide show
  1. package/dist/brain/intelligence.d.ts +1 -0
  2. package/dist/brain/intelligence.d.ts.map +1 -1
  3. package/dist/brain/intelligence.js +160 -148
  4. package/dist/brain/intelligence.js.map +1 -1
  5. package/dist/control/identity-manager.d.ts +3 -1
  6. package/dist/control/identity-manager.d.ts.map +1 -1
  7. package/dist/control/identity-manager.js +53 -51
  8. package/dist/control/identity-manager.js.map +1 -1
  9. package/dist/control/intent-router.d.ts +1 -0
  10. package/dist/control/intent-router.d.ts.map +1 -1
  11. package/dist/control/intent-router.js +41 -32
  12. package/dist/control/intent-router.js.map +1 -1
  13. package/dist/curator/curator.d.ts +1 -0
  14. package/dist/curator/curator.d.ts.map +1 -1
  15. package/dist/curator/curator.js +58 -99
  16. package/dist/curator/curator.js.map +1 -1
  17. package/dist/facades/facade-factory.js +1 -1
  18. package/dist/facades/facade-factory.js.map +1 -1
  19. package/dist/governance/governance.d.ts +1 -0
  20. package/dist/governance/governance.d.ts.map +1 -1
  21. package/dist/governance/governance.js +51 -68
  22. package/dist/governance/governance.js.map +1 -1
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +1 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/persistence/index.d.ts +2 -1
  28. package/dist/persistence/index.d.ts.map +1 -1
  29. package/dist/persistence/index.js +1 -0
  30. package/dist/persistence/index.js.map +1 -1
  31. package/dist/persistence/postgres-provider.d.ts +46 -0
  32. package/dist/persistence/postgres-provider.d.ts.map +1 -0
  33. package/dist/persistence/postgres-provider.js +115 -0
  34. package/dist/persistence/postgres-provider.js.map +1 -0
  35. package/dist/persistence/sqlite-provider.d.ts +5 -2
  36. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  37. package/dist/persistence/sqlite-provider.js +37 -1
  38. package/dist/persistence/sqlite-provider.js.map +1 -1
  39. package/dist/persistence/types.d.ts +23 -1
  40. package/dist/persistence/types.d.ts.map +1 -1
  41. package/dist/project/project-registry.d.ts +4 -4
  42. package/dist/project/project-registry.d.ts.map +1 -1
  43. package/dist/project/project-registry.js +32 -50
  44. package/dist/project/project-registry.js.map +1 -1
  45. package/dist/runtime/admin-extra-ops.d.ts +3 -3
  46. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  47. package/dist/runtime/admin-extra-ops.js +33 -3
  48. package/dist/runtime/admin-extra-ops.js.map +1 -1
  49. package/dist/runtime/core-ops.d.ts +4 -4
  50. package/dist/runtime/core-ops.js +4 -4
  51. package/dist/runtime/runtime.js +1 -1
  52. package/dist/runtime/runtime.js.map +1 -1
  53. package/dist/runtime/vault-extra-ops.d.ts +3 -2
  54. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  55. package/dist/runtime/vault-extra-ops.js +40 -2
  56. package/dist/runtime/vault-extra-ops.js.map +1 -1
  57. package/dist/vault/vault.d.ts +21 -0
  58. package/dist/vault/vault.d.ts.map +1 -1
  59. package/dist/vault/vault.js +99 -0
  60. package/dist/vault/vault.js.map +1 -1
  61. package/package.json +4 -2
  62. package/src/__tests__/admin-extra-ops.test.ts +2 -2
  63. package/src/__tests__/core-ops.test.ts +8 -2
  64. package/src/__tests__/persistence.test.ts +66 -0
  65. package/src/__tests__/postgres-provider.test.ts +58 -0
  66. package/src/__tests__/vault-extra-ops.test.ts +2 -2
  67. package/src/__tests__/vault.test.ts +184 -0
  68. package/src/brain/intelligence.ts +258 -307
  69. package/src/control/identity-manager.ts +77 -75
  70. package/src/control/intent-router.ts +55 -57
  71. package/src/curator/curator.ts +124 -145
  72. package/src/facades/facade-factory.ts +1 -1
  73. package/src/governance/governance.ts +90 -107
  74. package/src/index.ts +2 -0
  75. package/src/persistence/index.ts +2 -0
  76. package/src/persistence/postgres-provider.ts +157 -0
  77. package/src/persistence/sqlite-provider.ts +55 -2
  78. package/src/persistence/types.ts +31 -1
  79. package/src/project/project-registry.ts +69 -74
  80. package/src/runtime/admin-extra-ops.ts +36 -3
  81. package/src/runtime/core-ops.ts +4 -4
  82. package/src/runtime/runtime.ts +1 -1
  83. package/src/runtime/vault-extra-ops.ts +42 -2
  84. package/src/vault/vault.ts +118 -0
@@ -11,6 +11,7 @@ import type { PatternStrength, StrengthsQuery, BrainSession, SessionLifecycleInp
11
11
  export declare class BrainIntelligence {
12
12
  private vault;
13
13
  private brain;
14
+ private provider;
14
15
  constructor(vault: Vault, brain: Brain);
15
16
  private initializeTables;
16
17
  lifecycle(input: SessionLifecycleInput): BrainSession;
@@ -1 +1 @@
1
- {"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../../src/brain/intelligence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../../src/brain/intelligence.ts"],"names":[],"mappings":"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"}
@@ -18,15 +18,16 @@ const EXTRACTION_HIGH_FEEDBACK_RATIO = 0.8;
18
18
  export class BrainIntelligence {
19
19
  vault;
20
20
  brain;
21
+ provider;
21
22
  constructor(vault, brain) {
22
23
  this.vault = vault;
23
24
  this.brain = brain;
25
+ this.provider = vault.getProvider();
24
26
  this.initializeTables();
25
27
  }
26
28
  // ─── Table Initialization ─────────────────────────────────────────
27
29
  initializeTables() {
28
- const db = this.vault.getDb();
29
- db.exec(`
30
+ this.provider.execSql(`
30
31
  CREATE TABLE IF NOT EXISTS brain_strengths (
31
32
  pattern TEXT NOT NULL,
32
33
  domain TEXT NOT NULL,
@@ -90,11 +91,17 @@ export class BrainIntelligence {
90
91
  }
91
92
  // ─── Session Lifecycle ────────────────────────────────────────────
92
93
  lifecycle(input) {
93
- const db = this.vault.getDb();
94
94
  if (input.action === 'start') {
95
95
  const id = input.sessionId ?? randomUUID();
96
- db.prepare(`INSERT INTO brain_sessions (id, domain, context, tools_used, files_modified, plan_id)
97
- VALUES (?, ?, ?, ?, ?, ?)`).run(id, input.domain ?? null, input.context ?? null, JSON.stringify(input.toolsUsed ?? []), JSON.stringify(input.filesModified ?? []), input.planId ?? null);
96
+ this.provider.run(`INSERT INTO brain_sessions (id, domain, context, tools_used, files_modified, plan_id)
97
+ VALUES (?, ?, ?, ?, ?, ?)`, [
98
+ id,
99
+ input.domain ?? null,
100
+ input.context ?? null,
101
+ JSON.stringify(input.toolsUsed ?? []),
102
+ JSON.stringify(input.filesModified ?? []),
103
+ input.planId ?? null,
104
+ ]);
98
105
  return this.getSession(id);
99
106
  }
100
107
  // action === 'end'
@@ -120,7 +127,7 @@ export class BrainIntelligence {
120
127
  values.push(input.planOutcome);
121
128
  }
122
129
  values.push(sessionId);
123
- db.prepare(`UPDATE brain_sessions SET ${updates.join(', ')} WHERE id = ?`).run(...values);
130
+ this.provider.run(`UPDATE brain_sessions SET ${updates.join(', ')} WHERE id = ?`, values);
124
131
  // Auto-extract knowledge if session has enough signal
125
132
  this.autoExtractIfReady(this.getSession(sessionId));
126
133
  // Return fresh session (extractedAt may have been set by auto-extract)
@@ -147,10 +154,7 @@ export class BrainIntelligence {
147
154
  }
148
155
  }
149
156
  getSessionContext(limit = 10) {
150
- const db = this.vault.getDb();
151
- const rows = db
152
- .prepare('SELECT * FROM brain_sessions ORDER BY started_at DESC LIMIT ?')
153
- .all(limit);
157
+ const rows = this.provider.all('SELECT * FROM brain_sessions ORDER BY started_at DESC LIMIT ?', [limit]);
154
158
  const sessions = rows.map((r) => this.rowToSession(r));
155
159
  // Aggregate tool frequency
156
160
  const toolCounts = new Map();
@@ -172,33 +176,25 @@ export class BrainIntelligence {
172
176
  return { recentSessions: sessions, toolFrequency, fileFrequency };
173
177
  }
174
178
  archiveSessions(olderThanDays = 30) {
175
- const db = this.vault.getDb();
176
- const result = db
177
- .prepare(`DELETE FROM brain_sessions
178
- WHERE ended_at IS NOT NULL
179
- AND started_at < datetime('now', '-' || ? || ' days')`)
180
- .run(olderThanDays);
179
+ const result = this.provider.run(`DELETE FROM brain_sessions
180
+ WHERE ended_at IS NOT NULL
181
+ AND started_at < datetime('now', '-' || ? || ' days')`, [olderThanDays]);
181
182
  return { archived: result.changes };
182
183
  }
183
184
  // ─── Strength Scoring ─────────────────────────────────────────────
184
185
  computeStrengths() {
185
- const db = this.vault.getDb();
186
186
  // Gather feedback data grouped by entry_id
187
- const feedbackRows = db
188
- .prepare(`SELECT entry_id,
189
- COUNT(*) as total,
190
- SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
191
- SUM(CASE WHEN action = 'dismissed' THEN 1 ELSE 0 END) as dismissed,
192
- SUM(CASE WHEN action = 'modified' THEN 1 ELSE 0 END) as modified,
193
- SUM(CASE WHEN action = 'failed' THEN 1 ELSE 0 END) as failed,
194
- MAX(created_at) as last_used
195
- FROM brain_feedback
196
- GROUP BY entry_id`)
197
- .all();
187
+ const feedbackRows = this.provider.all(`SELECT entry_id,
188
+ COUNT(*) as total,
189
+ SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
190
+ SUM(CASE WHEN action = 'dismissed' THEN 1 ELSE 0 END) as dismissed,
191
+ SUM(CASE WHEN action = 'modified' THEN 1 ELSE 0 END) as modified,
192
+ SUM(CASE WHEN action = 'failed' THEN 1 ELSE 0 END) as failed,
193
+ MAX(created_at) as last_used
194
+ FROM brain_feedback
195
+ GROUP BY entry_id`);
198
196
  // Count unique session domains as spread proxy
199
- const sessionRows = db
200
- .prepare('SELECT DISTINCT domain FROM brain_sessions WHERE domain IS NOT NULL')
201
- .all();
197
+ const sessionRows = this.provider.all('SELECT DISTINCT domain FROM brain_sessions WHERE domain IS NOT NULL');
202
198
  const uniqueDomains = new Set(sessionRows.map((r) => r.domain));
203
199
  const now = Date.now();
204
200
  const strengths = [];
@@ -237,15 +233,26 @@ export class BrainIntelligence {
237
233
  };
238
234
  strengths.push(ps);
239
235
  // Persist
240
- db.prepare(`INSERT OR REPLACE INTO brain_strengths
236
+ this.provider.run(`INSERT OR REPLACE INTO brain_strengths
241
237
  (pattern, domain, strength, usage_score, spread_score, success_score, recency_score,
242
238
  usage_count, unique_contexts, success_rate, last_used, updated_at)
243
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`).run(ps.pattern, ps.domain, ps.strength, ps.usageScore, ps.spreadScore, ps.successScore, ps.recencyScore, ps.usageCount, ps.uniqueContexts, ps.successRate, ps.lastUsed);
239
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`, [
240
+ ps.pattern,
241
+ ps.domain,
242
+ ps.strength,
243
+ ps.usageScore,
244
+ ps.spreadScore,
245
+ ps.successScore,
246
+ ps.recencyScore,
247
+ ps.usageCount,
248
+ ps.uniqueContexts,
249
+ ps.successRate,
250
+ ps.lastUsed,
251
+ ]);
244
252
  }
245
253
  return strengths;
246
254
  }
247
255
  getStrengths(query) {
248
- const db = this.vault.getDb();
249
256
  const conditions = [];
250
257
  const values = [];
251
258
  if (query?.domain) {
@@ -259,9 +266,7 @@ export class BrainIntelligence {
259
266
  const where = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
260
267
  const limit = query?.limit ?? 50;
261
268
  values.push(limit);
262
- const rows = db
263
- .prepare(`SELECT * FROM brain_strengths ${where} ORDER BY strength DESC LIMIT ?`)
264
- .all(...values);
269
+ const rows = this.provider.all(`SELECT * FROM brain_strengths ${where} ORDER BY strength DESC LIMIT ?`, values);
265
270
  return rows.map((r) => ({
266
271
  pattern: r.pattern,
267
272
  domain: r.domain,
@@ -297,16 +302,13 @@ export class BrainIntelligence {
297
302
  }
298
303
  // Boost patterns with high source-specific acceptance rates
299
304
  if (context.source) {
300
- const db = this.vault.getDb();
301
305
  for (const s of strengths) {
302
- const row = db
303
- .prepare(`SELECT COUNT(*) as total,
304
- SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
305
- SUM(CASE WHEN action = 'modified' THEN 1 ELSE 0 END) as modified
306
- FROM brain_feedback
307
- WHERE entry_id = (SELECT id FROM entries WHERE title = ? LIMIT 1)
308
- AND source = ?`)
309
- .get(s.pattern, context.source);
306
+ const row = this.provider.get(`SELECT COUNT(*) as total,
307
+ SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
308
+ SUM(CASE WHEN action = 'modified' THEN 1 ELSE 0 END) as modified
309
+ FROM brain_feedback
310
+ WHERE entry_id = (SELECT id FROM entries WHERE title = ? LIMIT 1)
311
+ AND source = ?`, [s.pattern, context.source]);
310
312
  if (row.total >= 3) {
311
313
  const sourceRate = (row.accepted + row.modified * 0.5) / row.total;
312
314
  // Boost up to +10 points for high source-specific acceptance
@@ -324,7 +326,6 @@ export class BrainIntelligence {
324
326
  throw new Error('Session not found: ' + sessionId);
325
327
  const proposals = [];
326
328
  const rulesApplied = [];
327
- const db = this.vault.getDb();
328
329
  // Rule 1: Repeated tool usage (3+ same tool)
329
330
  const toolCounts = new Map();
330
331
  for (const t of session.toolsUsed) {
@@ -333,7 +334,7 @@ export class BrainIntelligence {
333
334
  for (const [tool, count] of toolCounts) {
334
335
  if (count >= EXTRACTION_TOOL_THRESHOLD) {
335
336
  rulesApplied.push('repeated_tool_usage');
336
- proposals.push(this.createProposal(db, sessionId, 'repeated_tool_usage', 'pattern', {
337
+ proposals.push(this.createProposal(sessionId, 'repeated_tool_usage', 'pattern', {
337
338
  title: `Frequent use of ${tool}`,
338
339
  description: `Tool ${tool} was used ${count} times in session. Consider automating or abstracting this workflow.`,
339
340
  confidence: Math.min(0.9, 0.5 + count * 0.1),
@@ -343,7 +344,7 @@ export class BrainIntelligence {
343
344
  // Rule 2: Multi-file edits (3+ files)
344
345
  if (session.filesModified.length >= EXTRACTION_FILE_THRESHOLD) {
345
346
  rulesApplied.push('multi_file_edit');
346
- proposals.push(this.createProposal(db, sessionId, 'multi_file_edit', 'pattern', {
347
+ proposals.push(this.createProposal(sessionId, 'multi_file_edit', 'pattern', {
347
348
  title: `Multi-file change pattern (${session.filesModified.length} files)`,
348
349
  description: `Session modified ${session.filesModified.length} files: ${session.filesModified.slice(0, 5).join(', ')}${session.filesModified.length > 5 ? '...' : ''}. This may indicate an architectural pattern.`,
349
350
  confidence: Math.min(0.8, 0.4 + session.filesModified.length * 0.05),
@@ -355,7 +356,7 @@ export class BrainIntelligence {
355
356
  const durationMin = durationMs / 60000;
356
357
  if (durationMin > EXTRACTION_LONG_SESSION_MINUTES) {
357
358
  rulesApplied.push('long_session');
358
- proposals.push(this.createProposal(db, sessionId, 'long_session', 'anti-pattern', {
359
+ proposals.push(this.createProposal(sessionId, 'long_session', 'anti-pattern', {
359
360
  title: `Long session (${Math.round(durationMin)} minutes)`,
360
361
  description: `Session lasted ${Math.round(durationMin)} minutes. Consider breaking complex tasks into smaller steps or improving automation.`,
361
362
  confidence: 0.5,
@@ -365,7 +366,7 @@ export class BrainIntelligence {
365
366
  // Rule 4: Plan completed
366
367
  if (session.planId && session.planOutcome === 'completed') {
367
368
  rulesApplied.push('plan_completed');
368
- proposals.push(this.createProposal(db, sessionId, 'plan_completed', 'workflow', {
369
+ proposals.push(this.createProposal(sessionId, 'plan_completed', 'workflow', {
369
370
  title: `Successful plan: ${session.planId}`,
370
371
  description: `Plan ${session.planId} completed successfully. This workflow can be reused for similar tasks.`,
371
372
  confidence: 0.8,
@@ -374,26 +375,24 @@ export class BrainIntelligence {
374
375
  // Rule 5: Plan abandoned
375
376
  if (session.planId && session.planOutcome === 'abandoned') {
376
377
  rulesApplied.push('plan_abandoned');
377
- proposals.push(this.createProposal(db, sessionId, 'plan_abandoned', 'anti-pattern', {
378
+ proposals.push(this.createProposal(sessionId, 'plan_abandoned', 'anti-pattern', {
378
379
  title: `Abandoned plan: ${session.planId}`,
379
380
  description: `Plan ${session.planId} was abandoned. Review what went wrong to avoid repeating in future sessions.`,
380
381
  confidence: 0.7,
381
382
  }));
382
383
  }
383
384
  // Rule 6: High feedback ratio (>80% accept or dismiss)
384
- const feedbackRow = db
385
- .prepare(`SELECT COUNT(*) as total,
386
- SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
387
- SUM(CASE WHEN action = 'dismissed' THEN 1 ELSE 0 END) as dismissed
388
- FROM brain_feedback
389
- WHERE created_at >= ? AND created_at <= ?`)
390
- .get(session.startedAt, session.endedAt ?? new Date().toISOString());
385
+ const feedbackRow = this.provider.get(`SELECT COUNT(*) as total,
386
+ SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
387
+ SUM(CASE WHEN action = 'dismissed' THEN 1 ELSE 0 END) as dismissed
388
+ FROM brain_feedback
389
+ WHERE created_at >= ? AND created_at <= ?`, [session.startedAt, session.endedAt ?? new Date().toISOString()]);
391
390
  if (feedbackRow.total >= 3) {
392
391
  const acceptRate = feedbackRow.accepted / feedbackRow.total;
393
392
  const dismissRate = feedbackRow.dismissed / feedbackRow.total;
394
393
  if (acceptRate >= EXTRACTION_HIGH_FEEDBACK_RATIO) {
395
394
  rulesApplied.push('high_accept_ratio');
396
- proposals.push(this.createProposal(db, sessionId, 'high_accept_ratio', 'pattern', {
395
+ proposals.push(this.createProposal(sessionId, 'high_accept_ratio', 'pattern', {
397
396
  title: `High search acceptance rate (${Math.round(acceptRate * 100)}%)`,
398
397
  description: `Search results were accepted ${Math.round(acceptRate * 100)}% of the time. Brain scoring is well-calibrated for this type of work.`,
399
398
  confidence: 0.7,
@@ -401,7 +400,7 @@ export class BrainIntelligence {
401
400
  }
402
401
  else if (dismissRate >= EXTRACTION_HIGH_FEEDBACK_RATIO) {
403
402
  rulesApplied.push('high_dismiss_ratio');
404
- proposals.push(this.createProposal(db, sessionId, 'high_dismiss_ratio', 'anti-pattern', {
403
+ proposals.push(this.createProposal(sessionId, 'high_dismiss_ratio', 'anti-pattern', {
405
404
  title: `High search dismissal rate (${Math.round(dismissRate * 100)}%)`,
406
405
  description: `Search results were dismissed ${Math.round(dismissRate * 100)}% of the time. Brain scoring may need recalibration for this domain.`,
407
406
  confidence: 0.7,
@@ -409,7 +408,9 @@ export class BrainIntelligence {
409
408
  }
410
409
  }
411
410
  // Mark session as extracted
412
- db.prepare("UPDATE brain_sessions SET extracted_at = datetime('now') WHERE id = ?").run(sessionId);
411
+ this.provider.run("UPDATE brain_sessions SET extracted_at = datetime('now') WHERE id = ?", [
412
+ sessionId,
413
+ ]);
413
414
  return {
414
415
  sessionId,
415
416
  proposals,
@@ -417,29 +418,21 @@ export class BrainIntelligence {
417
418
  };
418
419
  }
419
420
  resetExtracted(options) {
420
- const db = this.vault.getDb();
421
421
  if (options?.sessionId) {
422
- const info = db
423
- .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE id = ? AND extracted_at IS NOT NULL')
424
- .run(options.sessionId);
422
+ const info = this.provider.run('UPDATE brain_sessions SET extracted_at = NULL WHERE id = ? AND extracted_at IS NOT NULL', [options.sessionId]);
425
423
  return { reset: info.changes };
426
424
  }
427
425
  if (options?.since) {
428
- const info = db
429
- .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at >= ?')
430
- .run(options.since);
426
+ const info = this.provider.run('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at >= ?', [options.since]);
431
427
  return { reset: info.changes };
432
428
  }
433
429
  if (options?.all) {
434
- const info = db
435
- .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at IS NOT NULL')
436
- .run();
430
+ const info = this.provider.run('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at IS NOT NULL');
437
431
  return { reset: info.changes };
438
432
  }
439
433
  return { reset: 0 };
440
434
  }
441
435
  getProposals(options) {
442
- const db = this.vault.getDb();
443
436
  const conditions = [];
444
437
  const values = [];
445
438
  if (options?.sessionId) {
@@ -453,19 +446,16 @@ export class BrainIntelligence {
453
446
  const where = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
454
447
  const limit = options?.limit ?? 50;
455
448
  values.push(limit);
456
- const rows = db
457
- .prepare(`SELECT * FROM brain_proposals ${where} ORDER BY created_at DESC LIMIT ?`)
458
- .all(...values);
449
+ const rows = this.provider.all(`SELECT * FROM brain_proposals ${where} ORDER BY created_at DESC LIMIT ?`, values);
459
450
  return rows.map((r) => this.rowToProposal(r));
460
451
  }
461
452
  promoteProposals(proposalIds, governanceGate, projectPath) {
462
- const db = this.vault.getDb();
463
453
  let promoted = 0;
464
454
  const failed = [];
465
455
  const gated = [];
466
456
  const pp = projectPath ?? '.';
467
457
  for (const id of proposalIds) {
468
- const row = db.prepare('SELECT * FROM brain_proposals WHERE id = ?').get(id);
458
+ const row = this.provider.get('SELECT * FROM brain_proposals WHERE id = ?', [id]);
469
459
  if (!row) {
470
460
  failed.push(id);
471
461
  continue;
@@ -512,7 +502,7 @@ export class BrainIntelligence {
512
502
  description: row.description,
513
503
  tags: ['auto-extracted', row.rule],
514
504
  });
515
- db.prepare('UPDATE brain_proposals SET promoted = 1 WHERE id = ?').run(id);
505
+ this.provider.run('UPDATE brain_proposals SET promoted = 1 WHERE id = ?', [id]);
516
506
  promoted++;
517
507
  }
518
508
  return { promoted, failed, gated };
@@ -532,10 +522,7 @@ export class BrainIntelligence {
532
522
  };
533
523
  }
534
524
  getGlobalPatterns(limit = 20) {
535
- const db = this.vault.getDb();
536
- const rows = db
537
- .prepare('SELECT * FROM brain_global_registry ORDER BY total_strength DESC LIMIT ?')
538
- .all(limit);
525
+ const rows = this.provider.all('SELECT * FROM brain_global_registry ORDER BY total_strength DESC LIMIT ?', [limit]);
539
526
  return rows.map((r) => ({
540
527
  pattern: r.pattern,
541
528
  domains: JSON.parse(r.domains),
@@ -545,8 +532,7 @@ export class BrainIntelligence {
545
532
  }));
546
533
  }
547
534
  getDomainProfile(domain) {
548
- const db = this.vault.getDb();
549
- const row = db.prepare('SELECT * FROM brain_domain_profiles WHERE domain = ?').get(domain);
535
+ const row = this.provider.get('SELECT * FROM brain_domain_profiles WHERE domain = ?', [domain]);
550
536
  if (!row)
551
537
  return null;
552
538
  return {
@@ -559,15 +545,13 @@ export class BrainIntelligence {
559
545
  }
560
546
  // ─── Data Management ──────────────────────────────────────────────
561
547
  getStats() {
562
- const db = this.vault.getDb();
563
- const strengths = db.prepare('SELECT COUNT(*) as c FROM brain_strengths').get().c;
564
- const sessions = db.prepare('SELECT COUNT(*) as c FROM brain_sessions').get()
565
- .c;
566
- const activeSessions = db.prepare('SELECT COUNT(*) as c FROM brain_sessions WHERE ended_at IS NULL').get().c;
567
- const proposals = db.prepare('SELECT COUNT(*) as c FROM brain_proposals').get().c;
568
- const promotedProposals = db.prepare('SELECT COUNT(*) as c FROM brain_proposals WHERE promoted = 1').get().c;
569
- const globalPatterns = db.prepare('SELECT COUNT(*) as c FROM brain_global_registry').get().c;
570
- const domainProfiles = db.prepare('SELECT COUNT(*) as c FROM brain_domain_profiles').get().c;
548
+ const strengths = this.provider.get('SELECT COUNT(*) as c FROM brain_strengths').c;
549
+ const sessions = this.provider.get('SELECT COUNT(*) as c FROM brain_sessions').c;
550
+ const activeSessions = this.provider.get('SELECT COUNT(*) as c FROM brain_sessions WHERE ended_at IS NULL').c;
551
+ const proposals = this.provider.get('SELECT COUNT(*) as c FROM brain_proposals').c;
552
+ const promotedProposals = this.provider.get('SELECT COUNT(*) as c FROM brain_proposals WHERE promoted = 1').c;
553
+ const globalPatterns = this.provider.get('SELECT COUNT(*) as c FROM brain_global_registry').c;
554
+ const domainProfiles = this.provider.get('SELECT COUNT(*) as c FROM brain_domain_profiles').c;
571
555
  return {
572
556
  strengths,
573
557
  sessions,
@@ -579,15 +563,12 @@ export class BrainIntelligence {
579
563
  };
580
564
  }
581
565
  exportData() {
582
- const db = this.vault.getDb();
583
566
  const strengths = this.getStrengths({ limit: 10000 });
584
- const sessionRows = db
585
- .prepare('SELECT * FROM brain_sessions ORDER BY started_at DESC')
586
- .all();
567
+ const sessionRows = this.provider.all('SELECT * FROM brain_sessions ORDER BY started_at DESC');
587
568
  const sessions = sessionRows.map((r) => this.rowToSession(r));
588
569
  const proposals = this.getProposals({ limit: 10000 });
589
570
  const globalPatterns = this.getGlobalPatterns(10000);
590
- const profileRows = db.prepare('SELECT * FROM brain_domain_profiles').all();
571
+ const profileRows = this.provider.all('SELECT * FROM brain_domain_profiles');
591
572
  const domainProfiles = profileRows.map((r) => ({
592
573
  domain: r.domain,
593
574
  topPatterns: JSON.parse(r.top_patterns),
@@ -605,62 +586,93 @@ export class BrainIntelligence {
605
586
  };
606
587
  }
607
588
  importData(data) {
608
- const db = this.vault.getDb();
609
589
  const result = {
610
590
  imported: { strengths: 0, sessions: 0, proposals: 0, globalPatterns: 0, domainProfiles: 0 },
611
591
  };
612
- const tx = db.transaction(() => {
592
+ this.provider.transaction(() => {
613
593
  // Import strengths
614
- const insertStrength = db.prepare(`INSERT OR REPLACE INTO brain_strengths
615
- (pattern, domain, strength, usage_score, spread_score, success_score, recency_score,
616
- usage_count, unique_contexts, success_rate, last_used, updated_at)
617
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`);
618
594
  for (const s of data.strengths) {
619
- insertStrength.run(s.pattern, s.domain, s.strength, s.usageScore, s.spreadScore, s.successScore, s.recencyScore, s.usageCount, s.uniqueContexts, s.successRate, s.lastUsed);
595
+ this.provider.run(`INSERT OR REPLACE INTO brain_strengths
596
+ (pattern, domain, strength, usage_score, spread_score, success_score, recency_score,
597
+ usage_count, unique_contexts, success_rate, last_used, updated_at)
598
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`, [
599
+ s.pattern,
600
+ s.domain,
601
+ s.strength,
602
+ s.usageScore,
603
+ s.spreadScore,
604
+ s.successScore,
605
+ s.recencyScore,
606
+ s.usageCount,
607
+ s.uniqueContexts,
608
+ s.successRate,
609
+ s.lastUsed,
610
+ ]);
620
611
  result.imported.strengths++;
621
612
  }
622
613
  // Import sessions
623
- const insertSession = db.prepare(`INSERT OR IGNORE INTO brain_sessions
624
- (id, started_at, ended_at, domain, context, tools_used, files_modified, plan_id, plan_outcome, extracted_at)
625
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
626
614
  for (const s of data.sessions) {
627
- const changes = insertSession.run(s.id, s.startedAt, s.endedAt, s.domain, s.context, JSON.stringify(s.toolsUsed), JSON.stringify(s.filesModified), s.planId, s.planOutcome, s.extractedAt ?? null);
615
+ const changes = this.provider.run(`INSERT OR IGNORE INTO brain_sessions
616
+ (id, started_at, ended_at, domain, context, tools_used, files_modified, plan_id, plan_outcome, extracted_at)
617
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
618
+ s.id,
619
+ s.startedAt,
620
+ s.endedAt,
621
+ s.domain,
622
+ s.context,
623
+ JSON.stringify(s.toolsUsed),
624
+ JSON.stringify(s.filesModified),
625
+ s.planId,
626
+ s.planOutcome,
627
+ s.extractedAt ?? null,
628
+ ]);
628
629
  if (changes.changes > 0)
629
630
  result.imported.sessions++;
630
631
  }
631
632
  // Import proposals
632
- const insertProposal = db.prepare(`INSERT OR IGNORE INTO brain_proposals
633
- (id, session_id, rule, type, title, description, confidence, promoted, created_at)
634
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`);
635
633
  for (const p of data.proposals) {
636
- const changes = insertProposal.run(p.id, p.sessionId, p.rule, p.type, p.title, p.description, p.confidence, p.promoted ? 1 : 0, p.createdAt);
634
+ const changes = this.provider.run(`INSERT OR IGNORE INTO brain_proposals
635
+ (id, session_id, rule, type, title, description, confidence, promoted, created_at)
636
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
637
+ p.id,
638
+ p.sessionId,
639
+ p.rule,
640
+ p.type,
641
+ p.title,
642
+ p.description,
643
+ p.confidence,
644
+ p.promoted ? 1 : 0,
645
+ p.createdAt,
646
+ ]);
637
647
  if (changes.changes > 0)
638
648
  result.imported.proposals++;
639
649
  }
640
650
  // Import global patterns
641
- const insertGlobal = db.prepare(`INSERT OR REPLACE INTO brain_global_registry
642
- (pattern, domains, total_strength, avg_strength, domain_count, updated_at)
643
- VALUES (?, ?, ?, ?, ?, datetime('now'))`);
644
651
  for (const g of data.globalPatterns) {
645
- insertGlobal.run(g.pattern, JSON.stringify(g.domains), g.totalStrength, g.avgStrength, g.domainCount);
652
+ this.provider.run(`INSERT OR REPLACE INTO brain_global_registry
653
+ (pattern, domains, total_strength, avg_strength, domain_count, updated_at)
654
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [g.pattern, JSON.stringify(g.domains), g.totalStrength, g.avgStrength, g.domainCount]);
646
655
  result.imported.globalPatterns++;
647
656
  }
648
657
  // Import domain profiles
649
- const insertProfile = db.prepare(`INSERT OR REPLACE INTO brain_domain_profiles
650
- (domain, top_patterns, session_count, avg_session_duration, last_activity, updated_at)
651
- VALUES (?, ?, ?, ?, ?, datetime('now'))`);
652
658
  for (const d of data.domainProfiles) {
653
- insertProfile.run(d.domain, JSON.stringify(d.topPatterns), d.sessionCount, d.avgSessionDuration, d.lastActivity);
659
+ this.provider.run(`INSERT OR REPLACE INTO brain_domain_profiles
660
+ (domain, top_patterns, session_count, avg_session_duration, last_activity, updated_at)
661
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [
662
+ d.domain,
663
+ JSON.stringify(d.topPatterns),
664
+ d.sessionCount,
665
+ d.avgSessionDuration,
666
+ d.lastActivity,
667
+ ]);
654
668
  result.imported.domainProfiles++;
655
669
  }
656
670
  });
657
- tx();
658
671
  return result;
659
672
  }
660
673
  // ─── Private Helpers ──────────────────────────────────────────────
661
674
  getSession(id) {
662
- const db = this.vault.getDb();
663
- const row = db.prepare('SELECT * FROM brain_sessions WHERE id = ?').get(id);
675
+ const row = this.provider.get('SELECT * FROM brain_sessions WHERE id = ?', [id]);
664
676
  if (!row)
665
677
  return null;
666
678
  return this.rowToSession(row);
@@ -692,10 +704,10 @@ export class BrainIntelligence {
692
704
  createdAt: row.created_at,
693
705
  };
694
706
  }
695
- createProposal(db, sessionId, rule, type, data) {
707
+ createProposal(sessionId, rule, type, data) {
696
708
  const id = randomUUID();
697
- db.prepare(`INSERT INTO brain_proposals (id, session_id, rule, type, title, description, confidence)
698
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(id, sessionId, rule, type, data.title, data.description, data.confidence);
709
+ this.provider.run(`INSERT INTO brain_proposals (id, session_id, rule, type, title, description, confidence)
710
+ VALUES (?, ?, ?, ?, ?, ?, ?)`, [id, sessionId, rule, type, data.title, data.description, data.confidence]);
699
711
  return {
700
712
  id,
701
713
  sessionId,
@@ -709,7 +721,6 @@ export class BrainIntelligence {
709
721
  };
710
722
  }
711
723
  buildGlobalRegistry(strengths) {
712
- const db = this.vault.getDb();
713
724
  // Group strengths by pattern
714
725
  const patternMap = new Map();
715
726
  for (const s of strengths) {
@@ -717,22 +728,20 @@ export class BrainIntelligence {
717
728
  list.push(s);
718
729
  patternMap.set(s.pattern, list);
719
730
  }
720
- db.prepare('DELETE FROM brain_global_registry').run();
721
- const insert = db.prepare(`INSERT INTO brain_global_registry
722
- (pattern, domains, total_strength, avg_strength, domain_count, updated_at)
723
- VALUES (?, ?, ?, ?, ?, datetime('now'))`);
731
+ this.provider.run('DELETE FROM brain_global_registry');
724
732
  let count = 0;
725
733
  for (const [pattern, entries] of patternMap) {
726
734
  const domains = [...new Set(entries.map((e) => e.domain))];
727
735
  const totalStrength = entries.reduce((sum, e) => sum + e.strength, 0);
728
736
  const avgStrength = totalStrength / entries.length;
729
- insert.run(pattern, JSON.stringify(domains), totalStrength, avgStrength, domains.length);
737
+ this.provider.run(`INSERT INTO brain_global_registry
738
+ (pattern, domains, total_strength, avg_strength, domain_count, updated_at)
739
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [pattern, JSON.stringify(domains), totalStrength, avgStrength, domains.length]);
730
740
  count++;
731
741
  }
732
742
  return count;
733
743
  }
734
744
  buildDomainProfiles(strengths) {
735
- const db = this.vault.getDb();
736
745
  // Group strengths by domain
737
746
  const domainMap = new Map();
738
747
  for (const s of strengths) {
@@ -740,10 +749,7 @@ export class BrainIntelligence {
740
749
  list.push(s);
741
750
  domainMap.set(s.domain, list);
742
751
  }
743
- db.prepare('DELETE FROM brain_domain_profiles').run();
744
- const insert = db.prepare(`INSERT INTO brain_domain_profiles
745
- (domain, top_patterns, session_count, avg_session_duration, last_activity, updated_at)
746
- VALUES (?, ?, ?, ?, ?, datetime('now'))`);
752
+ this.provider.run('DELETE FROM brain_domain_profiles');
747
753
  let count = 0;
748
754
  for (const [domain, entries] of domainMap) {
749
755
  entries.sort((a, b) => b.strength - a.strength);
@@ -752,17 +758,23 @@ export class BrainIntelligence {
752
758
  strength: e.strength,
753
759
  }));
754
760
  // Count sessions for this domain
755
- const sessionCount = db.prepare('SELECT COUNT(*) as c FROM brain_sessions WHERE domain = ?').get(domain).c;
761
+ const sessionCount = this.provider.get('SELECT COUNT(*) as c FROM brain_sessions WHERE domain = ?', [domain]).c;
756
762
  // Average session duration (in minutes)
757
- const durationRow = db
758
- .prepare(`SELECT AVG(
759
- (julianday(ended_at) - julianday(started_at)) * 1440
760
- ) as avg_min
761
- FROM brain_sessions
762
- WHERE domain = ? AND ended_at IS NOT NULL`)
763
- .get(domain);
763
+ const durationRow = this.provider.get(`SELECT AVG(
764
+ (julianday(ended_at) - julianday(started_at)) * 1440
765
+ ) as avg_min
766
+ FROM brain_sessions
767
+ WHERE domain = ? AND ended_at IS NOT NULL`, [domain]);
764
768
  const lastActivity = entries.reduce((latest, e) => (e.lastUsed > latest ? e.lastUsed : latest), '');
765
- insert.run(domain, JSON.stringify(topPatterns), sessionCount, durationRow.avg_min ?? 0, lastActivity || new Date().toISOString());
769
+ this.provider.run(`INSERT INTO brain_domain_profiles
770
+ (domain, top_patterns, session_count, avg_session_duration, last_activity, updated_at)
771
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [
772
+ domain,
773
+ JSON.stringify(topPatterns),
774
+ sessionCount,
775
+ durationRow.avg_min ?? 0,
776
+ lastActivity || new Date().toISOString(),
777
+ ]);
766
778
  count++;
767
779
  }
768
780
  return count;