@soleri/core 2.5.0 → 2.6.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 (81) 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 +164 -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 +49 -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 +32 -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 +48 -99
  16. package/dist/curator/curator.js.map +1 -1
  17. package/dist/governance/governance.d.ts +1 -0
  18. package/dist/governance/governance.d.ts.map +1 -1
  19. package/dist/governance/governance.js +51 -68
  20. package/dist/governance/governance.js.map +1 -1
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/persistence/index.d.ts +2 -1
  26. package/dist/persistence/index.d.ts.map +1 -1
  27. package/dist/persistence/index.js +1 -0
  28. package/dist/persistence/index.js.map +1 -1
  29. package/dist/persistence/postgres-provider.d.ts +46 -0
  30. package/dist/persistence/postgres-provider.d.ts.map +1 -0
  31. package/dist/persistence/postgres-provider.js +115 -0
  32. package/dist/persistence/postgres-provider.js.map +1 -0
  33. package/dist/persistence/sqlite-provider.d.ts +5 -2
  34. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  35. package/dist/persistence/sqlite-provider.js +39 -1
  36. package/dist/persistence/sqlite-provider.js.map +1 -1
  37. package/dist/persistence/types.d.ts +23 -1
  38. package/dist/persistence/types.d.ts.map +1 -1
  39. package/dist/project/project-registry.d.ts +4 -4
  40. package/dist/project/project-registry.d.ts.map +1 -1
  41. package/dist/project/project-registry.js +25 -50
  42. package/dist/project/project-registry.js.map +1 -1
  43. package/dist/runtime/admin-extra-ops.d.ts +3 -3
  44. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  45. package/dist/runtime/admin-extra-ops.js +29 -3
  46. package/dist/runtime/admin-extra-ops.js.map +1 -1
  47. package/dist/runtime/core-ops.d.ts +4 -4
  48. package/dist/runtime/core-ops.js +4 -4
  49. package/dist/runtime/runtime.js +1 -1
  50. package/dist/runtime/runtime.js.map +1 -1
  51. package/dist/runtime/vault-extra-ops.d.ts +3 -2
  52. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  53. package/dist/runtime/vault-extra-ops.js +40 -2
  54. package/dist/runtime/vault-extra-ops.js.map +1 -1
  55. package/dist/vault/vault.d.ts +21 -0
  56. package/dist/vault/vault.d.ts.map +1 -1
  57. package/dist/vault/vault.js +99 -0
  58. package/dist/vault/vault.js.map +1 -1
  59. package/package.json +4 -2
  60. package/src/__tests__/admin-extra-ops.test.ts +2 -2
  61. package/src/__tests__/core-ops.test.ts +8 -2
  62. package/src/__tests__/persistence.test.ts +66 -0
  63. package/src/__tests__/postgres-provider.test.ts +58 -0
  64. package/src/__tests__/vault-extra-ops.test.ts +2 -2
  65. package/src/__tests__/vault.test.ts +184 -0
  66. package/src/brain/intelligence.ts +258 -307
  67. package/src/control/identity-manager.ts +77 -75
  68. package/src/control/intent-router.ts +55 -57
  69. package/src/curator/curator.ts +124 -145
  70. package/src/governance/governance.ts +90 -107
  71. package/src/index.ts +2 -0
  72. package/src/persistence/index.ts +2 -0
  73. package/src/persistence/postgres-provider.ts +157 -0
  74. package/src/persistence/sqlite-provider.ts +55 -2
  75. package/src/persistence/types.ts +31 -1
  76. package/src/project/project-registry.ts +69 -74
  77. package/src/runtime/admin-extra-ops.ts +36 -3
  78. package/src/runtime/core-ops.ts +4 -4
  79. package/src/runtime/runtime.ts +1 -1
  80. package/src/runtime/vault-extra-ops.ts +42 -2
  81. 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,7 @@ 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 = ?", [sessionId]);
413
412
  return {
414
413
  sessionId,
415
414
  proposals,
@@ -417,29 +416,21 @@ export class BrainIntelligence {
417
416
  };
418
417
  }
419
418
  resetExtracted(options) {
420
- const db = this.vault.getDb();
421
419
  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);
420
+ const info = this.provider.run('UPDATE brain_sessions SET extracted_at = NULL WHERE id = ? AND extracted_at IS NOT NULL', [options.sessionId]);
425
421
  return { reset: info.changes };
426
422
  }
427
423
  if (options?.since) {
428
- const info = db
429
- .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at >= ?')
430
- .run(options.since);
424
+ const info = this.provider.run('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at >= ?', [options.since]);
431
425
  return { reset: info.changes };
432
426
  }
433
427
  if (options?.all) {
434
- const info = db
435
- .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at IS NOT NULL')
436
- .run();
428
+ const info = this.provider.run('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at IS NOT NULL');
437
429
  return { reset: info.changes };
438
430
  }
439
431
  return { reset: 0 };
440
432
  }
441
433
  getProposals(options) {
442
- const db = this.vault.getDb();
443
434
  const conditions = [];
444
435
  const values = [];
445
436
  if (options?.sessionId) {
@@ -453,19 +444,16 @@ export class BrainIntelligence {
453
444
  const where = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
454
445
  const limit = options?.limit ?? 50;
455
446
  values.push(limit);
456
- const rows = db
457
- .prepare(`SELECT * FROM brain_proposals ${where} ORDER BY created_at DESC LIMIT ?`)
458
- .all(...values);
447
+ const rows = this.provider.all(`SELECT * FROM brain_proposals ${where} ORDER BY created_at DESC LIMIT ?`, values);
459
448
  return rows.map((r) => this.rowToProposal(r));
460
449
  }
461
450
  promoteProposals(proposalIds, governanceGate, projectPath) {
462
- const db = this.vault.getDb();
463
451
  let promoted = 0;
464
452
  const failed = [];
465
453
  const gated = [];
466
454
  const pp = projectPath ?? '.';
467
455
  for (const id of proposalIds) {
468
- const row = db.prepare('SELECT * FROM brain_proposals WHERE id = ?').get(id);
456
+ const row = this.provider.get('SELECT * FROM brain_proposals WHERE id = ?', [id]);
469
457
  if (!row) {
470
458
  failed.push(id);
471
459
  continue;
@@ -512,7 +500,7 @@ export class BrainIntelligence {
512
500
  description: row.description,
513
501
  tags: ['auto-extracted', row.rule],
514
502
  });
515
- db.prepare('UPDATE brain_proposals SET promoted = 1 WHERE id = ?').run(id);
503
+ this.provider.run('UPDATE brain_proposals SET promoted = 1 WHERE id = ?', [id]);
516
504
  promoted++;
517
505
  }
518
506
  return { promoted, failed, gated };
@@ -532,10 +520,7 @@ export class BrainIntelligence {
532
520
  };
533
521
  }
534
522
  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);
523
+ const rows = this.provider.all('SELECT * FROM brain_global_registry ORDER BY total_strength DESC LIMIT ?', [limit]);
539
524
  return rows.map((r) => ({
540
525
  pattern: r.pattern,
541
526
  domains: JSON.parse(r.domains),
@@ -545,8 +530,7 @@ export class BrainIntelligence {
545
530
  }));
546
531
  }
547
532
  getDomainProfile(domain) {
548
- const db = this.vault.getDb();
549
- const row = db.prepare('SELECT * FROM brain_domain_profiles WHERE domain = ?').get(domain);
533
+ const row = this.provider.get('SELECT * FROM brain_domain_profiles WHERE domain = ?', [domain]);
550
534
  if (!row)
551
535
  return null;
552
536
  return {
@@ -559,15 +543,13 @@ export class BrainIntelligence {
559
543
  }
560
544
  // ─── Data Management ──────────────────────────────────────────────
561
545
  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;
546
+ const strengths = (this.provider.get('SELECT COUNT(*) as c FROM brain_strengths')).c;
547
+ const sessions = (this.provider.get('SELECT COUNT(*) as c FROM brain_sessions')).c;
548
+ const activeSessions = (this.provider.get('SELECT COUNT(*) as c FROM brain_sessions WHERE ended_at IS NULL')).c;
549
+ const proposals = (this.provider.get('SELECT COUNT(*) as c FROM brain_proposals')).c;
550
+ const promotedProposals = (this.provider.get('SELECT COUNT(*) as c FROM brain_proposals WHERE promoted = 1')).c;
551
+ const globalPatterns = (this.provider.get('SELECT COUNT(*) as c FROM brain_global_registry')).c;
552
+ const domainProfiles = (this.provider.get('SELECT COUNT(*) as c FROM brain_domain_profiles')).c;
571
553
  return {
572
554
  strengths,
573
555
  sessions,
@@ -579,15 +561,12 @@ export class BrainIntelligence {
579
561
  };
580
562
  }
581
563
  exportData() {
582
- const db = this.vault.getDb();
583
564
  const strengths = this.getStrengths({ limit: 10000 });
584
- const sessionRows = db
585
- .prepare('SELECT * FROM brain_sessions ORDER BY started_at DESC')
586
- .all();
565
+ const sessionRows = this.provider.all('SELECT * FROM brain_sessions ORDER BY started_at DESC');
587
566
  const sessions = sessionRows.map((r) => this.rowToSession(r));
588
567
  const proposals = this.getProposals({ limit: 10000 });
589
568
  const globalPatterns = this.getGlobalPatterns(10000);
590
- const profileRows = db.prepare('SELECT * FROM brain_domain_profiles').all();
569
+ const profileRows = this.provider.all('SELECT * FROM brain_domain_profiles');
591
570
  const domainProfiles = profileRows.map((r) => ({
592
571
  domain: r.domain,
593
572
  topPatterns: JSON.parse(r.top_patterns),
@@ -605,62 +584,99 @@ export class BrainIntelligence {
605
584
  };
606
585
  }
607
586
  importData(data) {
608
- const db = this.vault.getDb();
609
587
  const result = {
610
588
  imported: { strengths: 0, sessions: 0, proposals: 0, globalPatterns: 0, domainProfiles: 0 },
611
589
  };
612
- const tx = db.transaction(() => {
590
+ this.provider.transaction(() => {
613
591
  // 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
592
  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);
593
+ this.provider.run(`INSERT OR REPLACE INTO brain_strengths
594
+ (pattern, domain, strength, usage_score, spread_score, success_score, recency_score,
595
+ usage_count, unique_contexts, success_rate, last_used, updated_at)
596
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))`, [
597
+ s.pattern,
598
+ s.domain,
599
+ s.strength,
600
+ s.usageScore,
601
+ s.spreadScore,
602
+ s.successScore,
603
+ s.recencyScore,
604
+ s.usageCount,
605
+ s.uniqueContexts,
606
+ s.successRate,
607
+ s.lastUsed,
608
+ ]);
620
609
  result.imported.strengths++;
621
610
  }
622
611
  // 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
612
  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);
613
+ const changes = this.provider.run(`INSERT OR IGNORE INTO brain_sessions
614
+ (id, started_at, ended_at, domain, context, tools_used, files_modified, plan_id, plan_outcome, extracted_at)
615
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
616
+ s.id,
617
+ s.startedAt,
618
+ s.endedAt,
619
+ s.domain,
620
+ s.context,
621
+ JSON.stringify(s.toolsUsed),
622
+ JSON.stringify(s.filesModified),
623
+ s.planId,
624
+ s.planOutcome,
625
+ s.extractedAt ?? null,
626
+ ]);
628
627
  if (changes.changes > 0)
629
628
  result.imported.sessions++;
630
629
  }
631
630
  // 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
631
  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);
632
+ const changes = this.provider.run(`INSERT OR IGNORE INTO brain_proposals
633
+ (id, session_id, rule, type, title, description, confidence, promoted, created_at)
634
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
635
+ p.id,
636
+ p.sessionId,
637
+ p.rule,
638
+ p.type,
639
+ p.title,
640
+ p.description,
641
+ p.confidence,
642
+ p.promoted ? 1 : 0,
643
+ p.createdAt,
644
+ ]);
637
645
  if (changes.changes > 0)
638
646
  result.imported.proposals++;
639
647
  }
640
648
  // 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
649
  for (const g of data.globalPatterns) {
645
- insertGlobal.run(g.pattern, JSON.stringify(g.domains), g.totalStrength, g.avgStrength, g.domainCount);
650
+ this.provider.run(`INSERT OR REPLACE INTO brain_global_registry
651
+ (pattern, domains, total_strength, avg_strength, domain_count, updated_at)
652
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [
653
+ g.pattern,
654
+ JSON.stringify(g.domains),
655
+ g.totalStrength,
656
+ g.avgStrength,
657
+ g.domainCount,
658
+ ]);
646
659
  result.imported.globalPatterns++;
647
660
  }
648
661
  // 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
662
  for (const d of data.domainProfiles) {
653
- insertProfile.run(d.domain, JSON.stringify(d.topPatterns), d.sessionCount, d.avgSessionDuration, d.lastActivity);
663
+ this.provider.run(`INSERT OR REPLACE INTO brain_domain_profiles
664
+ (domain, top_patterns, session_count, avg_session_duration, last_activity, updated_at)
665
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [
666
+ d.domain,
667
+ JSON.stringify(d.topPatterns),
668
+ d.sessionCount,
669
+ d.avgSessionDuration,
670
+ d.lastActivity,
671
+ ]);
654
672
  result.imported.domainProfiles++;
655
673
  }
656
674
  });
657
- tx();
658
675
  return result;
659
676
  }
660
677
  // ─── Private Helpers ──────────────────────────────────────────────
661
678
  getSession(id) {
662
- const db = this.vault.getDb();
663
- const row = db.prepare('SELECT * FROM brain_sessions WHERE id = ?').get(id);
679
+ const row = this.provider.get('SELECT * FROM brain_sessions WHERE id = ?', [id]);
664
680
  if (!row)
665
681
  return null;
666
682
  return this.rowToSession(row);
@@ -692,10 +708,10 @@ export class BrainIntelligence {
692
708
  createdAt: row.created_at,
693
709
  };
694
710
  }
695
- createProposal(db, sessionId, rule, type, data) {
711
+ createProposal(sessionId, rule, type, data) {
696
712
  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);
713
+ this.provider.run(`INSERT INTO brain_proposals (id, session_id, rule, type, title, description, confidence)
714
+ VALUES (?, ?, ?, ?, ?, ?, ?)`, [id, sessionId, rule, type, data.title, data.description, data.confidence]);
699
715
  return {
700
716
  id,
701
717
  sessionId,
@@ -709,7 +725,6 @@ export class BrainIntelligence {
709
725
  };
710
726
  }
711
727
  buildGlobalRegistry(strengths) {
712
- const db = this.vault.getDb();
713
728
  // Group strengths by pattern
714
729
  const patternMap = new Map();
715
730
  for (const s of strengths) {
@@ -717,22 +732,20 @@ export class BrainIntelligence {
717
732
  list.push(s);
718
733
  patternMap.set(s.pattern, list);
719
734
  }
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'))`);
735
+ this.provider.run('DELETE FROM brain_global_registry');
724
736
  let count = 0;
725
737
  for (const [pattern, entries] of patternMap) {
726
738
  const domains = [...new Set(entries.map((e) => e.domain))];
727
739
  const totalStrength = entries.reduce((sum, e) => sum + e.strength, 0);
728
740
  const avgStrength = totalStrength / entries.length;
729
- insert.run(pattern, JSON.stringify(domains), totalStrength, avgStrength, domains.length);
741
+ this.provider.run(`INSERT INTO brain_global_registry
742
+ (pattern, domains, total_strength, avg_strength, domain_count, updated_at)
743
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [pattern, JSON.stringify(domains), totalStrength, avgStrength, domains.length]);
730
744
  count++;
731
745
  }
732
746
  return count;
733
747
  }
734
748
  buildDomainProfiles(strengths) {
735
- const db = this.vault.getDb();
736
749
  // Group strengths by domain
737
750
  const domainMap = new Map();
738
751
  for (const s of strengths) {
@@ -740,10 +753,7 @@ export class BrainIntelligence {
740
753
  list.push(s);
741
754
  domainMap.set(s.domain, list);
742
755
  }
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'))`);
756
+ this.provider.run('DELETE FROM brain_domain_profiles');
747
757
  let count = 0;
748
758
  for (const [domain, entries] of domainMap) {
749
759
  entries.sort((a, b) => b.strength - a.strength);
@@ -752,17 +762,23 @@ export class BrainIntelligence {
752
762
  strength: e.strength,
753
763
  }));
754
764
  // Count sessions for this domain
755
- const sessionCount = db.prepare('SELECT COUNT(*) as c FROM brain_sessions WHERE domain = ?').get(domain).c;
765
+ const sessionCount = (this.provider.get('SELECT COUNT(*) as c FROM brain_sessions WHERE domain = ?', [domain])).c;
756
766
  // 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);
767
+ const durationRow = this.provider.get(`SELECT AVG(
768
+ (julianday(ended_at) - julianday(started_at)) * 1440
769
+ ) as avg_min
770
+ FROM brain_sessions
771
+ WHERE domain = ? AND ended_at IS NOT NULL`, [domain]);
764
772
  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());
773
+ this.provider.run(`INSERT INTO brain_domain_profiles
774
+ (domain, top_patterns, session_count, avg_session_duration, last_activity, updated_at)
775
+ VALUES (?, ?, ?, ?, ?, datetime('now'))`, [
776
+ domain,
777
+ JSON.stringify(topPatterns),
778
+ sessionCount,
779
+ durationRow.avg_min ?? 0,
780
+ lastActivity || new Date().toISOString(),
781
+ ]);
766
782
  count++;
767
783
  }
768
784
  return count;