@siduri-x/core 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/siduri-db.js CHANGED
@@ -1,10 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SiduriDatabase = void 0;
4
+ exports.normalizeStatus = normalizeStatus;
4
5
  // eslint-disable-next-line @typescript-eslint/no-var-requires
5
6
  const crypto = require('crypto');
6
7
  // eslint-disable-next-line @typescript-eslint/no-var-requires
7
8
  const { DatabaseSync } = require('node:sqlite');
9
+ function normalizeStatus(status, defaultStatus = 'pending') {
10
+ if (!status)
11
+ return defaultStatus;
12
+ return status.toLowerCase().replace(/_/g, '-');
13
+ }
8
14
  class SiduriDatabase {
9
15
  db;
10
16
  constructor(options = {}) {
@@ -20,6 +26,7 @@ class SiduriDatabase {
20
26
  companion_id TEXT PRIMARY KEY,
21
27
  name TEXT NOT NULL,
22
28
  archetype TEXT,
29
+ role TEXT,
23
30
  origin TEXT,
24
31
  ethos TEXT,
25
32
  version TEXT NOT NULL,
@@ -41,7 +48,7 @@ class SiduriDatabase {
41
48
  companion_id TEXT NOT NULL,
42
49
  priority INTEGER DEFAULT 50,
43
50
  directive TEXT NOT NULL,
44
- status TEXT DEFAULT 'ACTIVE',
51
+ status TEXT DEFAULT 'active',
45
52
  category TEXT DEFAULT 'behavioral',
46
53
  scope_actor TEXT,
47
54
  supersedes_id TEXT,
@@ -123,7 +130,7 @@ class SiduriDatabase {
123
130
  subject TEXT NOT NULL,
124
131
  predicate TEXT NOT NULL,
125
132
  value TEXT NOT NULL,
126
- status TEXT DEFAULT 'PENDING',
133
+ status TEXT DEFAULT 'pending',
127
134
  confidence REAL DEFAULT 1.0,
128
135
  valid_from TEXT,
129
136
  valid_until TEXT,
@@ -209,6 +216,12 @@ class SiduriDatabase {
209
216
  catch {
210
217
  // Column already exists
211
218
  }
219
+ try {
220
+ this.db.exec("ALTER TABLE self_identity ADD COLUMN role TEXT");
221
+ }
222
+ catch {
223
+ // Column already exists
224
+ }
212
225
  }
213
226
  close() {
214
227
  this.db.close();
@@ -225,6 +238,7 @@ class SiduriDatabase {
225
238
  companionId: row.companion_id,
226
239
  name: row.name,
227
240
  archetype: row.archetype || undefined,
241
+ role: row.role || row.archetype || undefined,
228
242
  origin: row.origin || undefined,
229
243
  ethos: row.ethos || undefined,
230
244
  version: row.version,
@@ -232,18 +246,21 @@ class SiduriDatabase {
232
246
  };
233
247
  }
234
248
  setIdentity(identity) {
249
+ const role = identity.role || identity.archetype || null;
250
+ const archetype = identity.archetype || identity.role || null;
235
251
  const stmt = this.db.prepare(`
236
- INSERT INTO self_identity (companion_id, name, archetype, origin, ethos, version, updated_at)
237
- VALUES (?, ?, ?, ?, ?, ?, datetime('now'))
252
+ INSERT INTO self_identity (companion_id, name, archetype, role, origin, ethos, version, updated_at)
253
+ VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
238
254
  ON CONFLICT(companion_id) DO UPDATE SET
239
255
  name = excluded.name,
240
256
  archetype = excluded.archetype,
257
+ role = excluded.role,
241
258
  origin = excluded.origin,
242
259
  ethos = excluded.ethos,
243
260
  version = excluded.version,
244
261
  updated_at = datetime('now')
245
262
  `);
246
- stmt.run(identity.companionId, identity.name, identity.archetype || null, identity.origin || null, identity.ethos || null, identity.version);
263
+ stmt.run(identity.companionId, identity.name, archetype, role, identity.origin || null, identity.ethos || null, identity.version);
247
264
  }
248
265
  getPersonality(companionId) {
249
266
  const stmt = this.db.prepare('SELECT * FROM self_personality WHERE companion_id = ?');
@@ -272,30 +289,49 @@ class SiduriDatabase {
272
289
  `);
273
290
  stmt.run(companionId, traits.warmth, traits.formality, traits.sarcasm, traits.verbosity, traits.curiosity);
274
291
  }
275
- getActiveDirectives(companionId) {
276
- const stmt = this.db.prepare(`
277
- SELECT * FROM self_directives
278
- WHERE companion_id = ? AND status = 'ACTIVE'
279
- ORDER BY priority DESC, created_at ASC
280
- `);
281
- return stmt.all(companionId).map((row) => ({
292
+ rowToSelfDirective(row) {
293
+ return {
282
294
  id: row.id,
283
295
  companionId: row.companion_id,
284
296
  priority: row.priority,
285
297
  directive: row.directive,
286
- status: row.status,
298
+ status: normalizeStatus(row.status, 'active'),
287
299
  category: row.category,
288
300
  scopeActor: row.scope_actor || undefined,
289
301
  supersedesId: row.supersedes_id || undefined,
290
- createdAt: row.created_at
291
- }));
302
+ createdAt: row.created_at,
303
+ };
304
+ }
305
+ getActiveDirectives(companionId) {
306
+ const stmt = this.db.prepare(`
307
+ SELECT * FROM self_directives
308
+ WHERE companion_id = ? AND LOWER(status) = 'active'
309
+ ORDER BY priority DESC, created_at ASC
310
+ `);
311
+ return stmt.all(companionId).map((row) => this.rowToSelfDirective(row));
312
+ }
313
+ getAllDirectives(companionId) {
314
+ const stmt = this.db.prepare(`
315
+ SELECT * FROM self_directives
316
+ WHERE companion_id = ?
317
+ ORDER BY priority DESC, created_at ASC
318
+ `);
319
+ return stmt.all(companionId).map((row) => this.rowToSelfDirective(row));
292
320
  }
293
321
  commitDirective(directive) {
294
322
  const stmt = this.db.prepare(`
295
323
  INSERT INTO self_directives (id, companion_id, priority, directive, status, category, scope_actor, supersedes_id, created_at)
296
324
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
325
+ ON CONFLICT(id) DO UPDATE SET
326
+ companion_id = excluded.companion_id,
327
+ priority = excluded.priority,
328
+ directive = excluded.directive,
329
+ status = excluded.status,
330
+ category = excluded.category,
331
+ scope_actor = excluded.scope_actor,
332
+ supersedes_id = excluded.supersedes_id
297
333
  `);
298
- stmt.run(directive.id, directive.companionId, directive.priority !== undefined ? directive.priority : 50, directive.directive, directive.status, directive.category || 'behavioral', directive.scopeActor || null, directive.supersedesId || null, directive.createdAt || new Date().toISOString());
334
+ stmt.run(directive.id, directive.companionId, directive.priority !== undefined ? directive.priority : 50, directive.directive, normalizeStatus(directive.status, 'active'), directive.category || 'behavioral', directive.scopeActor || null, directive.supersedesId || null, directive.createdAt || new Date().toISOString());
299
335
  }
300
336
  getDirective(id, companionId) {
301
337
  const stmt = companionId
@@ -304,17 +340,7 @@ class SiduriDatabase {
304
340
  const row = (companionId ? stmt.get(id, companionId) : stmt.get(id));
305
341
  if (!row)
306
342
  return undefined;
307
- return {
308
- id: row.id,
309
- companionId: row.companion_id,
310
- priority: row.priority,
311
- directive: row.directive,
312
- status: row.status,
313
- category: row.category,
314
- scopeActor: row.scope_actor || undefined,
315
- supersedesId: row.supersedes_id || undefined,
316
- createdAt: row.created_at,
317
- };
343
+ return this.rowToSelfDirective(row);
318
344
  }
319
345
  approveDirective(id, companionId) {
320
346
  const findStmt = companionId
@@ -324,28 +350,31 @@ class SiduriDatabase {
324
350
  if (!row) {
325
351
  return;
326
352
  }
327
- if (row.status !== 'PENDING') {
328
- throw new Error(`Cannot approve directive '${id}': invalid transition from status '${row.status}' to 'ACTIVE' (only PENDING directives can be approved)`);
353
+ if (normalizeStatus(row.status) !== 'pending') {
354
+ if (normalizeStatus(row.status) === 'active') {
355
+ return;
356
+ }
357
+ throw new Error(`Cannot approve directive '${id}': invalid transition from status '${row.status}' to 'active' (only pending directives can be approved)`);
329
358
  }
330
- // If this directive supersedes an earlier directive, transition that prior directive to SUPERSEDED
359
+ // If this directive supersedes an earlier directive, transition that prior directive to superseded
331
360
  if (row.supersedes_id) {
332
361
  const supersededId = row.supersedes_id;
333
362
  const effectiveCompanionId = companionId || row.companion_id;
334
363
  if (effectiveCompanionId) {
335
- const supersedeStmt = this.db.prepare("UPDATE self_directives SET status = 'SUPERSEDED' WHERE id = ? AND companion_id = ?");
364
+ const supersedeStmt = this.db.prepare("UPDATE self_directives SET status = 'superseded' WHERE id = ? AND companion_id = ?");
336
365
  supersedeStmt.run(supersededId, effectiveCompanionId);
337
366
  }
338
367
  else {
339
- const supersedeStmt = this.db.prepare("UPDATE self_directives SET status = 'SUPERSEDED' WHERE id = ?");
368
+ const supersedeStmt = this.db.prepare("UPDATE self_directives SET status = 'superseded' WHERE id = ?");
340
369
  supersedeStmt.run(supersededId);
341
370
  }
342
371
  }
343
372
  if (companionId) {
344
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'ACTIVE' WHERE id = ? AND companion_id = ? AND status = 'PENDING'");
373
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'active' WHERE id = ? AND companion_id = ? AND LOWER(status) = 'pending'");
345
374
  stmt.run(id, companionId);
346
375
  }
347
376
  else {
348
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'ACTIVE' WHERE id = ? AND status = 'PENDING'");
377
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'active' WHERE id = ? AND LOWER(status) = 'pending'");
349
378
  stmt.run(id);
350
379
  }
351
380
  }
@@ -357,51 +386,53 @@ class SiduriDatabase {
357
386
  if (!row) {
358
387
  return;
359
388
  }
360
- if (row.status !== 'PENDING') {
361
- throw new Error(`Cannot reject directive '${id}': invalid transition from status '${row.status}' to 'REJECTED' (only PENDING directives can be rejected)`);
389
+ if (normalizeStatus(row.status) !== 'pending') {
390
+ throw new Error(`Cannot reject directive '${id}': invalid transition from status '${row.status}' to 'rejected' (only pending directives can be rejected)`);
362
391
  }
363
392
  if (companionId) {
364
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'REJECTED' WHERE id = ? AND companion_id = ? AND status = 'PENDING'");
393
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'rejected' WHERE id = ? AND companion_id = ? AND LOWER(status) = 'pending'");
365
394
  stmt.run(id, companionId);
366
395
  }
367
396
  else {
368
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'REJECTED' WHERE id = ? AND status = 'PENDING'");
397
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'rejected' WHERE id = ? AND LOWER(status) = 'pending'");
369
398
  stmt.run(id);
370
399
  }
371
400
  }
372
401
  revokeDirective(id, companionId) {
373
402
  if (companionId) {
374
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'REVOKED' WHERE id = ? AND companion_id = ?");
403
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'revoked' WHERE id = ? AND companion_id = ?");
375
404
  stmt.run(id, companionId);
376
405
  }
377
406
  else {
378
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'REVOKED' WHERE id = ?");
407
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'revoked' WHERE id = ?");
379
408
  stmt.run(id);
380
409
  }
381
410
  }
382
411
  expireDirective(id, companionId) {
383
412
  if (companionId) {
384
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'EXPIRED' WHERE id = ? AND companion_id = ?");
413
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'expired' WHERE id = ? AND companion_id = ?");
385
414
  stmt.run(id, companionId);
386
415
  }
387
416
  else {
388
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'EXPIRED' WHERE id = ?");
417
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'expired' WHERE id = ?");
389
418
  stmt.run(id);
390
419
  }
391
420
  }
392
421
  disableDirective(id, companionId) {
393
422
  if (companionId) {
394
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'DISABLED' WHERE id = ? AND companion_id = ?");
423
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'disabled' WHERE id = ? AND companion_id = ?");
395
424
  stmt.run(id, companionId);
396
425
  }
397
426
  else {
398
- const stmt = this.db.prepare("UPDATE self_directives SET status = 'DISABLED' WHERE id = ?");
427
+ const stmt = this.db.prepare("UPDATE self_directives SET status = 'disabled' WHERE id = ?");
399
428
  stmt.run(id);
400
429
  }
401
430
  }
402
431
  getRelationship(companionId, entityId) {
403
- const stmt = this.db.prepare('SELECT * FROM self_relationships WHERE companion_id = ? AND entity_id = ?');
404
- const row = stmt.get(companionId, entityId);
432
+ const stripped = entityId.startsWith('actor:') ? entityId.slice(6) : entityId;
433
+ const prefixed = entityId.startsWith('actor:') ? entityId : `actor:${entityId}`;
434
+ const stmt = this.db.prepare('SELECT * FROM self_relationships WHERE companion_id = ? AND (entity_id = ? OR entity_id = ? OR entity_id = ?)');
435
+ const row = stmt.get(companionId, entityId, stripped, prefixed);
405
436
  if (!row)
406
437
  return undefined;
407
438
  return {
@@ -603,20 +634,37 @@ class SiduriDatabase {
603
634
  payload: JSON.parse(row.payload)
604
635
  };
605
636
  }
637
+ rowToMemoryClaim(row) {
638
+ return {
639
+ id: row.id,
640
+ companionId: row.companion_id,
641
+ subject: row.subject,
642
+ predicate: row.predicate,
643
+ value: row.value,
644
+ status: normalizeStatus(row.status, 'pending'),
645
+ confidence: row.confidence,
646
+ validFrom: row.valid_from || undefined,
647
+ validUntil: row.valid_until || undefined,
648
+ evidence: row.evidence ? (typeof row.evidence === 'string' ? JSON.parse(row.evidence) : row.evidence) : undefined,
649
+ assertedAt: row.asserted_at,
650
+ supersedes: row.supersedes || undefined,
651
+ sourceEventId: row.source_event_id || undefined,
652
+ };
653
+ }
606
654
  proposeClaim(claim) {
607
655
  const id = claim.id || crypto.randomUUID();
608
- const status = 'PENDING';
656
+ const status = normalizeStatus(claim.status, 'pending');
609
657
  const confidence = claim.confidence ?? 1.0;
610
658
  const assertedAt = claim.assertedAt || new Date().toISOString();
611
659
  const stmt = this.db.prepare(`
612
660
  INSERT INTO memory_claims (id, companion_id, subject, predicate, value, status, confidence, valid_from, valid_until, evidence, asserted_at, supersedes, source_event_id)
613
661
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, coalesce(?, datetime('now')), ?, ?)
614
662
  `);
615
- stmt.run(id, claim.companionId, claim.subject, claim.predicate, claim.value, status, confidence, claim.validFrom || null, claim.validUntil || null, claim.evidence ? JSON.stringify(claim.evidence) : null, assertedAt || null, claim.supersedes || null, claim.sourceEventId || null);
663
+ stmt.run(id, claim.companionId || 'default', claim.subject, claim.predicate, claim.value, status, confidence, claim.validFrom || null, claim.validUntil || null, claim.evidence ? JSON.stringify(claim.evidence) : null, assertedAt || null, claim.supersedes || null, claim.sourceEventId || null);
616
664
  return {
617
665
  ...claim,
618
666
  id,
619
- status,
667
+ status: status,
620
668
  confidence,
621
669
  assertedAt,
622
670
  supersedes: claim.supersedes,
@@ -631,67 +679,158 @@ class SiduriDatabase {
631
679
  if (!row) {
632
680
  return;
633
681
  }
634
- if (row.status !== 'PENDING') {
635
- throw new Error(`Cannot approve claim '${id}': invalid transition from status '${row.status}' to 'APPROVED' (only PENDING claims can be approved)`);
682
+ if (normalizeStatus(row.status) !== 'pending') {
683
+ if (normalizeStatus(row.status) === 'approved') {
684
+ return;
685
+ }
686
+ throw new Error(`Cannot approve claim '${id}': invalid transition from status '${row.status}' to 'approved' (only pending claims can be approved)`);
636
687
  }
637
- // If this claim supersedes an earlier claim, transition that prior claim to SUPERSEDED
688
+ // If this claim supersedes an earlier claim, transition that prior claim to superseded
638
689
  if (row.supersedes) {
639
690
  const supersededId = row.supersedes;
640
691
  if (companionId) {
641
- const supersedeStmt = this.db.prepare("UPDATE memory_claims SET status = 'SUPERSEDED' WHERE id = ? AND companion_id = ?");
692
+ const supersedeStmt = this.db.prepare("UPDATE memory_claims SET status = 'superseded' WHERE id = ? AND companion_id = ?");
642
693
  supersedeStmt.run(supersededId, companionId);
643
694
  }
644
695
  else {
645
- const supersedeStmt = this.db.prepare("UPDATE memory_claims SET status = 'SUPERSEDED' WHERE id = ?");
696
+ const supersedeStmt = this.db.prepare("UPDATE memory_claims SET status = 'superseded' WHERE id = ?");
646
697
  supersedeStmt.run(supersededId);
647
698
  }
648
699
  }
649
700
  if (companionId) {
650
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'APPROVED' WHERE id = ? AND companion_id = ? AND status = 'PENDING'");
701
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'approved' WHERE id = ? AND companion_id = ? AND LOWER(status) = 'pending'");
651
702
  stmt.run(id, companionId);
652
703
  }
653
704
  else {
654
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'APPROVED' WHERE id = ? AND status = 'PENDING'");
705
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'approved' WHERE id = ? AND LOWER(status) = 'pending'");
655
706
  stmt.run(id);
656
707
  }
708
+ // Canonically promote approved claim to Self domain state (identity, role, relationships)
709
+ const approvedClaim = this.getClaim(id);
710
+ if (approvedClaim) {
711
+ this.promoteClaimToSelf(approvedClaim);
712
+ }
713
+ }
714
+ /**
715
+ * Canonically promotes a Claim into Self domain tables.
716
+ */
717
+ promoteClaimToSelf(claim) {
718
+ const companionId = claim.companionId || 'default';
719
+ const subject = (claim.subject || '').toLowerCase();
720
+ const predicate = (claim.predicate || '').toLowerCase();
721
+ const value = claim.value || '';
722
+ if (!value)
723
+ return;
724
+ // 1. Identity mutations: companion identity/role/origin/name/ethos
725
+ if (subject.startsWith('companion:') ||
726
+ subject === 'companion' ||
727
+ subject === 'siduri' ||
728
+ subject === 'self') {
729
+ const existing = this.getIdentity(companionId) || {
730
+ companionId,
731
+ name: 'Siduri',
732
+ version: '1.0.0',
733
+ updatedAt: new Date().toISOString(),
734
+ };
735
+ if (predicate === 'role' || predicate === 'archetype') {
736
+ existing.archetype = value;
737
+ existing.role = value;
738
+ this.setIdentity(existing);
739
+ this.commitDirective({
740
+ id: `dir-role-${claim.id || Date.now()}`,
741
+ companionId,
742
+ priority: 70,
743
+ directive: `Acknowledge role as ${value}`,
744
+ status: 'active',
745
+ category: 'relational',
746
+ createdAt: new Date().toISOString(),
747
+ });
748
+ }
749
+ else if (predicate === 'origin' || predicate === 'created_by') {
750
+ existing.origin = value;
751
+ this.setIdentity(existing);
752
+ }
753
+ else if (predicate === 'name') {
754
+ existing.name = value;
755
+ this.setIdentity(existing);
756
+ }
757
+ else if (predicate === 'ethos') {
758
+ existing.ethos = value;
759
+ this.setIdentity(existing);
760
+ }
761
+ return;
762
+ }
763
+ // 2. Relationship mutations: creator or user stated relationship
764
+ if (claim.claimType === 'relationship' ||
765
+ predicate === 'stated_relationship' ||
766
+ predicate === 'relationship' ||
767
+ predicate === 'relationship_to_siduri') {
768
+ const rawSubject = (claim.subject || 'actor:user').replace(/^actor:actor:/, 'actor:');
769
+ const isCreator = value.toLowerCase() === 'creator';
770
+ this.upsertRelationship({
771
+ companionId,
772
+ entityId: rawSubject,
773
+ entityType: 'human',
774
+ role: value,
775
+ stance: isCreator ? 'familiar_loyal' : 'neutral',
776
+ trustScore: isCreator ? 1.0 : 0.8,
777
+ familiarity: isCreator ? 0.9 : 0.5,
778
+ interactionConventions: isCreator
779
+ ? ['Direct communication', 'Highest administrative trust']
780
+ : [],
781
+ });
782
+ return;
783
+ }
784
+ // 3. Behavioral rule claim
785
+ if (predicate === 'behavioral_rule' || predicate === 'rule') {
786
+ this.commitDirective({
787
+ id: `dir-rule-${claim.id || Date.now()}`,
788
+ companionId,
789
+ priority: 60,
790
+ directive: value,
791
+ status: 'active',
792
+ category: 'behavioral',
793
+ createdAt: new Date().toISOString(),
794
+ });
795
+ }
657
796
  }
658
797
  rejectClaim(id, companionId) {
659
798
  if (companionId) {
660
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'REJECTED' WHERE id = ? AND companion_id = ?");
799
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'rejected' WHERE id = ? AND companion_id = ?");
661
800
  stmt.run(id, companionId);
662
801
  }
663
802
  else {
664
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'REJECTED' WHERE id = ?");
803
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'rejected' WHERE id = ?");
665
804
  stmt.run(id);
666
805
  }
667
806
  }
668
807
  revokeClaim(id, companionId) {
669
808
  if (companionId) {
670
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'REVOKED' WHERE id = ? AND companion_id = ?");
809
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'revoked' WHERE id = ? AND companion_id = ?");
671
810
  stmt.run(id, companionId);
672
811
  }
673
812
  else {
674
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'REVOKED' WHERE id = ?");
813
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'revoked' WHERE id = ?");
675
814
  stmt.run(id);
676
815
  }
677
816
  }
678
817
  expireClaim(id, companionId) {
679
818
  if (companionId) {
680
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'EXPIRED' WHERE id = ? AND companion_id = ?");
819
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'expired' WHERE id = ? AND companion_id = ?");
681
820
  stmt.run(id, companionId);
682
821
  }
683
822
  else {
684
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'EXPIRED' WHERE id = ?");
823
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'expired' WHERE id = ?");
685
824
  stmt.run(id);
686
825
  }
687
826
  }
688
827
  markClaimSessionOnly(id, companionId) {
689
828
  if (companionId) {
690
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'SESSION_ONLY' WHERE id = ? AND companion_id = ?");
829
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'session-only' WHERE id = ? AND companion_id = ?");
691
830
  stmt.run(id, companionId);
692
831
  }
693
832
  else {
694
- const stmt = this.db.prepare("UPDATE memory_claims SET status = 'SESSION_ONLY' WHERE id = ?");
833
+ const stmt = this.db.prepare("UPDATE memory_claims SET status = 'session-only' WHERE id = ?");
695
834
  stmt.run(id);
696
835
  }
697
836
  }
@@ -699,82 +838,33 @@ class SiduriDatabase {
699
838
  const stmt = this.db.prepare(`
700
839
  SELECT c.* FROM memory_claims c
701
840
  JOIN memory_search s ON c.rowid = s.rowid
702
- WHERE c.companion_id = ? AND c.status = 'APPROVED' AND memory_search MATCH ?
841
+ WHERE c.companion_id = ? AND LOWER(c.status) = 'approved' AND memory_search MATCH ?
703
842
  ORDER BY rank
704
843
  LIMIT ?
705
844
  `);
706
- return stmt.all(companionId, query, limit).map((row) => ({
707
- id: row.id,
708
- companionId: row.companion_id,
709
- subject: row.subject,
710
- predicate: row.predicate,
711
- value: row.value,
712
- status: row.status,
713
- confidence: row.confidence,
714
- validFrom: row.valid_from || undefined,
715
- validUntil: row.valid_until || undefined,
716
- evidence: row.evidence ? JSON.parse(row.evidence) : undefined,
717
- assertedAt: row.asserted_at,
718
- supersedes: row.supersedes || undefined,
719
- sourceEventId: row.source_event_id || undefined,
720
- }));
845
+ return stmt.all(companionId, query, limit).map((row) => this.rowToMemoryClaim(row));
721
846
  }
722
847
  getPendingClaims(companionId, limit = 50) {
723
- const stmt = this.db.prepare("SELECT * FROM memory_claims WHERE companion_id = ? AND status = 'PENDING' ORDER BY asserted_at DESC LIMIT ?");
724
- return stmt.all(companionId, limit).map((row) => ({
725
- id: row.id,
726
- companionId: row.companion_id,
727
- subject: row.subject,
728
- predicate: row.predicate,
729
- value: row.value,
730
- status: row.status,
731
- confidence: row.confidence,
732
- validFrom: row.valid_from || undefined,
733
- validUntil: row.valid_until || undefined,
734
- evidence: row.evidence ? JSON.parse(row.evidence) : undefined,
735
- assertedAt: row.asserted_at,
736
- supersedes: row.supersedes || undefined,
737
- sourceEventId: row.source_event_id || undefined,
738
- }));
848
+ const stmt = this.db.prepare("SELECT * FROM memory_claims WHERE companion_id = ? AND LOWER(status) = 'pending' ORDER BY asserted_at DESC LIMIT ?");
849
+ return stmt.all(companionId, limit).map((row) => this.rowToMemoryClaim(row));
739
850
  }
740
851
  getApprovedClaims(companionId, limit = 50) {
741
- const stmt = this.db.prepare("SELECT * FROM memory_claims WHERE companion_id = ? AND status = 'APPROVED' ORDER BY asserted_at DESC LIMIT ?");
742
- return stmt.all(companionId, limit).map((row) => ({
743
- id: row.id,
744
- companionId: row.companion_id,
745
- subject: row.subject,
746
- predicate: row.predicate,
747
- value: row.value,
748
- status: row.status,
749
- confidence: row.confidence,
750
- validFrom: row.valid_from || undefined,
751
- validUntil: row.valid_until || undefined,
752
- evidence: row.evidence ? JSON.parse(row.evidence) : undefined,
753
- assertedAt: row.asserted_at,
754
- supersedes: row.supersedes || undefined,
755
- sourceEventId: row.source_event_id || undefined,
756
- }));
852
+ const stmt = this.db.prepare("SELECT * FROM memory_claims WHERE companion_id = ? AND LOWER(status) = 'approved' ORDER BY asserted_at DESC LIMIT ?");
853
+ return stmt.all(companionId, limit).map((row) => this.rowToMemoryClaim(row));
854
+ }
855
+ getAllClaims(companionId, limit = 100) {
856
+ const stmt = companionId
857
+ ? this.db.prepare("SELECT * FROM memory_claims WHERE companion_id = ? ORDER BY asserted_at DESC LIMIT ?")
858
+ : this.db.prepare("SELECT * FROM memory_claims ORDER BY asserted_at DESC LIMIT ?");
859
+ const rows = companionId ? stmt.all(companionId, limit) : stmt.all(limit);
860
+ return rows.map((row) => this.rowToMemoryClaim(row));
757
861
  }
758
862
  getClaim(id) {
759
863
  const stmt = this.db.prepare("SELECT * FROM memory_claims WHERE id = ?");
760
864
  const row = stmt.get(id);
761
865
  if (!row)
762
866
  return undefined;
763
- return {
764
- id: row.id,
765
- companionId: row.companion_id,
766
- subject: row.subject,
767
- predicate: row.predicate,
768
- value: row.value,
769
- status: row.status,
770
- confidence: row.confidence,
771
- validFrom: row.valid_from || undefined,
772
- validUntil: row.valid_until || undefined,
773
- evidence: row.evidence ? JSON.parse(row.evidence) : undefined,
774
- assertedAt: row.asserted_at,
775
- supersedes: row.supersedes || undefined,
776
- sourceEventId: row.source_event_id || undefined,
777
- };
867
+ return this.rowToMemoryClaim(row);
778
868
  }
779
869
  resetMemory(companionId) {
780
870
  const deleteClaims = this.db.prepare("DELETE FROM memory_claims WHERE companion_id = ?");