claude-memory-layer 1.0.0 → 1.0.2

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 (37) hide show
  1. package/.claude/settings.local.json +15 -0
  2. package/.history/package_20260201114632.json +46 -0
  3. package/dist/cli/index.js +360 -154
  4. package/dist/cli/index.js.map +4 -4
  5. package/dist/core/index.js +337 -161
  6. package/dist/core/index.js.map +3 -3
  7. package/dist/hooks/session-end.js +320 -130
  8. package/dist/hooks/session-end.js.map +4 -4
  9. package/dist/hooks/session-start.js +331 -138
  10. package/dist/hooks/session-start.js.map +4 -4
  11. package/dist/hooks/stop.js +320 -130
  12. package/dist/hooks/stop.js.map +4 -4
  13. package/dist/hooks/user-prompt-submit.js +320 -130
  14. package/dist/hooks/user-prompt-submit.js.map +4 -4
  15. package/dist/services/memory-service.js +349 -128
  16. package/dist/services/memory-service.js.map +4 -4
  17. package/package.json +1 -1
  18. package/src/cli/index.ts +84 -23
  19. package/src/core/consolidated-store.ts +33 -18
  20. package/src/core/continuity-manager.ts +12 -7
  21. package/src/core/db-wrapper.ts +112 -0
  22. package/src/core/edge-repo.ts +22 -13
  23. package/src/core/entity-repo.ts +23 -14
  24. package/src/core/event-store.ts +98 -72
  25. package/src/core/task/blocker-resolver.ts +17 -9
  26. package/src/core/task/task-matcher.ts +8 -6
  27. package/src/core/task/task-projector.ts +29 -16
  28. package/src/core/task/task-resolver.ts +17 -9
  29. package/src/core/vector-outbox.ts +29 -16
  30. package/src/core/vector-store.ts +23 -12
  31. package/src/core/vector-worker.ts +7 -4
  32. package/src/core/working-set-store.ts +31 -18
  33. package/src/hooks/session-end.ts +3 -2
  34. package/src/hooks/session-start.ts +12 -8
  35. package/src/hooks/stop.ts +3 -2
  36. package/src/hooks/user-prompt-submit.ts +3 -2
  37. package/src/services/memory-service.ts +158 -6
@@ -572,12 +572,94 @@ function parseEntityCanonicalKey(canonicalKey) {
572
572
  }
573
573
 
574
574
  // src/core/event-store.ts
575
- import { Database } from "duckdb";
576
575
  import { randomUUID } from "crypto";
576
+
577
+ // src/core/db-wrapper.ts
578
+ import duckdb from "duckdb";
579
+ function convertBigInts(obj) {
580
+ if (obj === null || obj === void 0)
581
+ return obj;
582
+ if (typeof obj === "bigint")
583
+ return Number(obj);
584
+ if (obj instanceof Date)
585
+ return obj;
586
+ if (Array.isArray(obj))
587
+ return obj.map(convertBigInts);
588
+ if (typeof obj === "object") {
589
+ const result = {};
590
+ for (const [key, value] of Object.entries(obj)) {
591
+ result[key] = convertBigInts(value);
592
+ }
593
+ return result;
594
+ }
595
+ return obj;
596
+ }
597
+ function toDate(value) {
598
+ if (value instanceof Date)
599
+ return value;
600
+ if (typeof value === "string")
601
+ return new Date(value);
602
+ if (typeof value === "number")
603
+ return new Date(value);
604
+ return new Date(String(value));
605
+ }
606
+ function createDatabase(path) {
607
+ return new duckdb.Database(path);
608
+ }
609
+ function dbRun(db, sql, params = []) {
610
+ return new Promise((resolve, reject) => {
611
+ if (params.length === 0) {
612
+ db.run(sql, (err) => {
613
+ if (err)
614
+ reject(err);
615
+ else
616
+ resolve();
617
+ });
618
+ } else {
619
+ db.run(sql, ...params, (err) => {
620
+ if (err)
621
+ reject(err);
622
+ else
623
+ resolve();
624
+ });
625
+ }
626
+ });
627
+ }
628
+ function dbAll(db, sql, params = []) {
629
+ return new Promise((resolve, reject) => {
630
+ if (params.length === 0) {
631
+ db.all(sql, (err, rows) => {
632
+ if (err)
633
+ reject(err);
634
+ else
635
+ resolve(convertBigInts(rows || []));
636
+ });
637
+ } else {
638
+ db.all(sql, ...params, (err, rows) => {
639
+ if (err)
640
+ reject(err);
641
+ else
642
+ resolve(convertBigInts(rows || []));
643
+ });
644
+ }
645
+ });
646
+ }
647
+ function dbClose(db) {
648
+ return new Promise((resolve, reject) => {
649
+ db.close((err) => {
650
+ if (err)
651
+ reject(err);
652
+ else
653
+ resolve();
654
+ });
655
+ });
656
+ }
657
+
658
+ // src/core/event-store.ts
577
659
  var EventStore = class {
578
660
  constructor(dbPath) {
579
661
  this.dbPath = dbPath;
580
- this.db = new Database(dbPath);
662
+ this.db = createDatabase(dbPath);
581
663
  }
582
664
  db;
583
665
  initialized = false;
@@ -587,7 +669,7 @@ var EventStore = class {
587
669
  async initialize() {
588
670
  if (this.initialized)
589
671
  return;
590
- await this.db.run(`
672
+ await dbRun(this.db, `
591
673
  CREATE TABLE IF NOT EXISTS events (
592
674
  id VARCHAR PRIMARY KEY,
593
675
  event_type VARCHAR NOT NULL,
@@ -599,14 +681,14 @@ var EventStore = class {
599
681
  metadata JSON
600
682
  )
601
683
  `);
602
- await this.db.run(`
684
+ await dbRun(this.db, `
603
685
  CREATE TABLE IF NOT EXISTS event_dedup (
604
686
  dedupe_key VARCHAR PRIMARY KEY,
605
687
  event_id VARCHAR NOT NULL,
606
688
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
607
689
  )
608
690
  `);
609
- await this.db.run(`
691
+ await dbRun(this.db, `
610
692
  CREATE TABLE IF NOT EXISTS sessions (
611
693
  id VARCHAR PRIMARY KEY,
612
694
  started_at TIMESTAMP NOT NULL,
@@ -616,7 +698,7 @@ var EventStore = class {
616
698
  tags JSON
617
699
  )
618
700
  `);
619
- await this.db.run(`
701
+ await dbRun(this.db, `
620
702
  CREATE TABLE IF NOT EXISTS insights (
621
703
  id VARCHAR PRIMARY KEY,
622
704
  insight_type VARCHAR NOT NULL,
@@ -628,7 +710,7 @@ var EventStore = class {
628
710
  last_updated TIMESTAMP
629
711
  )
630
712
  `);
631
- await this.db.run(`
713
+ await dbRun(this.db, `
632
714
  CREATE TABLE IF NOT EXISTS embedding_outbox (
633
715
  id VARCHAR PRIMARY KEY,
634
716
  event_id VARCHAR NOT NULL,
@@ -640,7 +722,7 @@ var EventStore = class {
640
722
  error_message TEXT
641
723
  )
642
724
  `);
643
- await this.db.run(`
725
+ await dbRun(this.db, `
644
726
  CREATE TABLE IF NOT EXISTS projection_offsets (
645
727
  projection_name VARCHAR PRIMARY KEY,
646
728
  last_event_id VARCHAR,
@@ -648,14 +730,14 @@ var EventStore = class {
648
730
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
649
731
  )
650
732
  `);
651
- await this.db.run(`
733
+ await dbRun(this.db, `
652
734
  CREATE TABLE IF NOT EXISTS memory_levels (
653
735
  event_id VARCHAR PRIMARY KEY,
654
736
  level VARCHAR NOT NULL DEFAULT 'L0',
655
737
  promoted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
656
738
  )
657
739
  `);
658
- await this.db.run(`
740
+ await dbRun(this.db, `
659
741
  CREATE TABLE IF NOT EXISTS entries (
660
742
  entry_id VARCHAR PRIMARY KEY,
661
743
  created_ts TIMESTAMP NOT NULL,
@@ -671,7 +753,7 @@ var EventStore = class {
671
753
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
672
754
  )
673
755
  `);
674
- await this.db.run(`
756
+ await dbRun(this.db, `
675
757
  CREATE TABLE IF NOT EXISTS entities (
676
758
  entity_id VARCHAR PRIMARY KEY,
677
759
  entity_type VARCHAR NOT NULL,
@@ -686,7 +768,7 @@ var EventStore = class {
686
768
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
687
769
  )
688
770
  `);
689
- await this.db.run(`
771
+ await dbRun(this.db, `
690
772
  CREATE TABLE IF NOT EXISTS entity_aliases (
691
773
  entity_type VARCHAR NOT NULL,
692
774
  canonical_key VARCHAR NOT NULL,
@@ -696,7 +778,7 @@ var EventStore = class {
696
778
  PRIMARY KEY(entity_type, canonical_key)
697
779
  )
698
780
  `);
699
- await this.db.run(`
781
+ await dbRun(this.db, `
700
782
  CREATE TABLE IF NOT EXISTS edges (
701
783
  edge_id VARCHAR PRIMARY KEY,
702
784
  src_type VARCHAR NOT NULL,
@@ -708,7 +790,7 @@ var EventStore = class {
708
790
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
709
791
  )
710
792
  `);
711
- await this.db.run(`
793
+ await dbRun(this.db, `
712
794
  CREATE TABLE IF NOT EXISTS vector_outbox (
713
795
  job_id VARCHAR PRIMARY KEY,
714
796
  item_kind VARCHAR NOT NULL,
@@ -722,7 +804,7 @@ var EventStore = class {
722
804
  UNIQUE(item_kind, item_id, embedding_version)
723
805
  )
724
806
  `);
725
- await this.db.run(`
807
+ await dbRun(this.db, `
726
808
  CREATE TABLE IF NOT EXISTS build_runs (
727
809
  build_id VARCHAR PRIMARY KEY,
728
810
  started_at TIMESTAMP NOT NULL,
@@ -737,7 +819,7 @@ var EventStore = class {
737
819
  error VARCHAR
738
820
  )
739
821
  `);
740
- await this.db.run(`
822
+ await dbRun(this.db, `
741
823
  CREATE TABLE IF NOT EXISTS pipeline_metrics (
742
824
  id VARCHAR PRIMARY KEY,
743
825
  ts TIMESTAMP NOT NULL,
@@ -748,7 +830,7 @@ var EventStore = class {
748
830
  session_id VARCHAR
749
831
  )
750
832
  `);
751
- await this.db.run(`
833
+ await dbRun(this.db, `
752
834
  CREATE TABLE IF NOT EXISTS working_set (
753
835
  id VARCHAR PRIMARY KEY,
754
836
  event_id VARCHAR NOT NULL,
@@ -758,7 +840,7 @@ var EventStore = class {
758
840
  expires_at TIMESTAMP
759
841
  )
760
842
  `);
761
- await this.db.run(`
843
+ await dbRun(this.db, `
762
844
  CREATE TABLE IF NOT EXISTS consolidated_memories (
763
845
  memory_id VARCHAR PRIMARY KEY,
764
846
  summary TEXT NOT NULL,
@@ -770,7 +852,7 @@ var EventStore = class {
770
852
  access_count INTEGER DEFAULT 0
771
853
  )
772
854
  `);
773
- await this.db.run(`
855
+ await dbRun(this.db, `
774
856
  CREATE TABLE IF NOT EXISTS continuity_log (
775
857
  log_id VARCHAR PRIMARY KEY,
776
858
  from_context_id VARCHAR,
@@ -780,26 +862,26 @@ var EventStore = class {
780
862
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
781
863
  )
782
864
  `);
783
- await this.db.run(`
865
+ await dbRun(this.db, `
784
866
  CREATE TABLE IF NOT EXISTS endless_config (
785
867
  key VARCHAR PRIMARY KEY,
786
868
  value JSON,
787
869
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
788
870
  )
789
871
  `);
790
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(entry_type)`);
791
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entries_stage ON entries(stage)`);
792
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entries_canonical ON entries(canonical_key)`);
793
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entities_type_key ON entities(entity_type, canonical_key)`);
794
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status)`);
795
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src_id, rel_type)`);
796
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst_id, rel_type)`);
797
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_edges_rel ON edges(rel_type)`);
798
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_outbox_status ON vector_outbox(status)`);
799
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_working_set_expires ON working_set(expires_at)`);
800
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_working_set_relevance ON working_set(relevance_score DESC)`);
801
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence DESC)`);
802
- await this.db.run(`CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at)`);
872
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entries_type ON entries(entry_type)`);
873
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entries_stage ON entries(stage)`);
874
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entries_canonical ON entries(canonical_key)`);
875
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entities_type_key ON entities(entity_type, canonical_key)`);
876
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_entities_status ON entities(status)`);
877
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_edges_src ON edges(src_id, rel_type)`);
878
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_edges_dst ON edges(dst_id, rel_type)`);
879
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_edges_rel ON edges(rel_type)`);
880
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_outbox_status ON vector_outbox(status)`);
881
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_working_set_expires ON working_set(expires_at)`);
882
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_working_set_relevance ON working_set(relevance_score DESC)`);
883
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence DESC)`);
884
+ await dbRun(this.db, `CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at)`);
803
885
  this.initialized = true;
804
886
  }
805
887
  /**
@@ -810,7 +892,8 @@ var EventStore = class {
810
892
  await this.initialize();
811
893
  const canonicalKey = makeCanonicalKey(input.content);
812
894
  const dedupeKey = makeDedupeKey(input.content, input.sessionId);
813
- const existing = await this.db.all(
895
+ const existing = await dbAll(
896
+ this.db,
814
897
  `SELECT event_id FROM event_dedup WHERE dedupe_key = ?`,
815
898
  [dedupeKey]
816
899
  );
@@ -824,7 +907,8 @@ var EventStore = class {
824
907
  const id = randomUUID();
825
908
  const timestamp = input.timestamp.toISOString();
826
909
  try {
827
- await this.db.run(
910
+ await dbRun(
911
+ this.db,
828
912
  `INSERT INTO events (id, event_type, session_id, timestamp, content, canonical_key, dedupe_key, metadata)
829
913
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
830
914
  [
@@ -838,11 +922,13 @@ var EventStore = class {
838
922
  JSON.stringify(input.metadata || {})
839
923
  ]
840
924
  );
841
- await this.db.run(
925
+ await dbRun(
926
+ this.db,
842
927
  `INSERT INTO event_dedup (dedupe_key, event_id) VALUES (?, ?)`,
843
928
  [dedupeKey, id]
844
929
  );
845
- await this.db.run(
930
+ await dbRun(
931
+ this.db,
846
932
  `INSERT INTO memory_levels (event_id, level) VALUES (?, 'L0')`,
847
933
  [id]
848
934
  );
@@ -859,7 +945,8 @@ var EventStore = class {
859
945
  */
860
946
  async getSessionEvents(sessionId) {
861
947
  await this.initialize();
862
- const rows = await this.db.all(
948
+ const rows = await dbAll(
949
+ this.db,
863
950
  `SELECT * FROM events WHERE session_id = ? ORDER BY timestamp ASC`,
864
951
  [sessionId]
865
952
  );
@@ -870,7 +957,8 @@ var EventStore = class {
870
957
  */
871
958
  async getRecentEvents(limit = 100) {
872
959
  await this.initialize();
873
- const rows = await this.db.all(
960
+ const rows = await dbAll(
961
+ this.db,
874
962
  `SELECT * FROM events ORDER BY timestamp DESC LIMIT ?`,
875
963
  [limit]
876
964
  );
@@ -881,7 +969,8 @@ var EventStore = class {
881
969
  */
882
970
  async getEvent(id) {
883
971
  await this.initialize();
884
- const rows = await this.db.all(
972
+ const rows = await dbAll(
973
+ this.db,
885
974
  `SELECT * FROM events WHERE id = ?`,
886
975
  [id]
887
976
  );
@@ -894,12 +983,14 @@ var EventStore = class {
894
983
  */
895
984
  async upsertSession(session) {
896
985
  await this.initialize();
897
- const existing = await this.db.all(
986
+ const existing = await dbAll(
987
+ this.db,
898
988
  `SELECT id FROM sessions WHERE id = ?`,
899
989
  [session.id]
900
990
  );
901
991
  if (existing.length === 0) {
902
- await this.db.run(
992
+ await dbRun(
993
+ this.db,
903
994
  `INSERT INTO sessions (id, started_at, project_path, tags)
904
995
  VALUES (?, ?, ?, ?)`,
905
996
  [
@@ -926,7 +1017,8 @@ var EventStore = class {
926
1017
  }
927
1018
  if (updates.length > 0) {
928
1019
  values.push(session.id);
929
- await this.db.run(
1020
+ await dbRun(
1021
+ this.db,
930
1022
  `UPDATE sessions SET ${updates.join(", ")} WHERE id = ?`,
931
1023
  values
932
1024
  );
@@ -938,7 +1030,8 @@ var EventStore = class {
938
1030
  */
939
1031
  async getSession(id) {
940
1032
  await this.initialize();
941
- const rows = await this.db.all(
1033
+ const rows = await dbAll(
1034
+ this.db,
942
1035
  `SELECT * FROM sessions WHERE id = ?`,
943
1036
  [id]
944
1037
  );
@@ -947,8 +1040,8 @@ var EventStore = class {
947
1040
  const row = rows[0];
948
1041
  return {
949
1042
  id: row.id,
950
- startedAt: new Date(row.started_at),
951
- endedAt: row.ended_at ? new Date(row.ended_at) : void 0,
1043
+ startedAt: toDate(row.started_at),
1044
+ endedAt: row.ended_at ? toDate(row.ended_at) : void 0,
952
1045
  projectPath: row.project_path,
953
1046
  summary: row.summary,
954
1047
  tags: row.tags ? JSON.parse(row.tags) : void 0
@@ -960,7 +1053,8 @@ var EventStore = class {
960
1053
  async enqueueForEmbedding(eventId, content) {
961
1054
  await this.initialize();
962
1055
  const id = randomUUID();
963
- await this.db.run(
1056
+ await dbRun(
1057
+ this.db,
964
1058
  `INSERT INTO embedding_outbox (id, event_id, content, status, retry_count)
965
1059
  VALUES (?, ?, ?, 'pending', 0)`,
966
1060
  [id, eventId, content]
@@ -972,25 +1066,30 @@ var EventStore = class {
972
1066
  */
973
1067
  async getPendingOutboxItems(limit = 32) {
974
1068
  await this.initialize();
975
- const rows = await this.db.all(
976
- `UPDATE embedding_outbox
977
- SET status = 'processing'
978
- WHERE id IN (
979
- SELECT id FROM embedding_outbox
980
- WHERE status = 'pending'
981
- ORDER BY created_at
982
- LIMIT ?
983
- )
984
- RETURNING *`,
1069
+ const pending = await dbAll(
1070
+ this.db,
1071
+ `SELECT * FROM embedding_outbox
1072
+ WHERE status = 'pending'
1073
+ ORDER BY created_at
1074
+ LIMIT ?`,
985
1075
  [limit]
986
1076
  );
987
- return rows.map((row) => ({
1077
+ if (pending.length === 0)
1078
+ return [];
1079
+ const ids = pending.map((r) => r.id);
1080
+ const placeholders = ids.map(() => "?").join(",");
1081
+ await dbRun(
1082
+ this.db,
1083
+ `UPDATE embedding_outbox SET status = 'processing' WHERE id IN (${placeholders})`,
1084
+ ids
1085
+ );
1086
+ return pending.map((row) => ({
988
1087
  id: row.id,
989
1088
  eventId: row.event_id,
990
1089
  content: row.content,
991
- status: row.status,
1090
+ status: "processing",
992
1091
  retryCount: row.retry_count,
993
- createdAt: new Date(row.created_at),
1092
+ createdAt: toDate(row.created_at),
994
1093
  errorMessage: row.error_message
995
1094
  }));
996
1095
  }
@@ -1001,7 +1100,8 @@ var EventStore = class {
1001
1100
  if (ids.length === 0)
1002
1101
  return;
1003
1102
  const placeholders = ids.map(() => "?").join(",");
1004
- await this.db.run(
1103
+ await dbRun(
1104
+ this.db,
1005
1105
  `DELETE FROM embedding_outbox WHERE id IN (${placeholders})`,
1006
1106
  ids
1007
1107
  );
@@ -1013,7 +1113,8 @@ var EventStore = class {
1013
1113
  if (ids.length === 0)
1014
1114
  return;
1015
1115
  const placeholders = ids.map(() => "?").join(",");
1016
- await this.db.run(
1116
+ await dbRun(
1117
+ this.db,
1017
1118
  `UPDATE embedding_outbox
1018
1119
  SET status = CASE WHEN retry_count >= 3 THEN 'failed' ELSE 'pending' END,
1019
1120
  retry_count = retry_count + 1,
@@ -1027,7 +1128,8 @@ var EventStore = class {
1027
1128
  */
1028
1129
  async updateMemoryLevel(eventId, level) {
1029
1130
  await this.initialize();
1030
- await this.db.run(
1131
+ await dbRun(
1132
+ this.db,
1031
1133
  `UPDATE memory_levels SET level = ?, promoted_at = CURRENT_TIMESTAMP WHERE event_id = ?`,
1032
1134
  [level, eventId]
1033
1135
  );
@@ -1037,7 +1139,8 @@ var EventStore = class {
1037
1139
  */
1038
1140
  async getLevelStats() {
1039
1141
  await this.initialize();
1040
- const rows = await this.db.all(
1142
+ const rows = await dbAll(
1143
+ this.db,
1041
1144
  `SELECT level, COUNT(*) as count FROM memory_levels GROUP BY level`
1042
1145
  );
1043
1146
  return rows;
@@ -1056,7 +1159,8 @@ var EventStore = class {
1056
1159
  */
1057
1160
  async getEndlessConfig(key) {
1058
1161
  await this.initialize();
1059
- const rows = await this.db.all(
1162
+ const rows = await dbAll(
1163
+ this.db,
1060
1164
  `SELECT value FROM endless_config WHERE key = ?`,
1061
1165
  [key]
1062
1166
  );
@@ -1069,7 +1173,8 @@ var EventStore = class {
1069
1173
  */
1070
1174
  async setEndlessConfig(key, value) {
1071
1175
  await this.initialize();
1072
- await this.db.run(
1176
+ await dbRun(
1177
+ this.db,
1073
1178
  `INSERT OR REPLACE INTO endless_config (key, value, updated_at)
1074
1179
  VALUES (?, ?, CURRENT_TIMESTAMP)`,
1075
1180
  [key, JSON.stringify(value)]
@@ -1080,13 +1185,14 @@ var EventStore = class {
1080
1185
  */
1081
1186
  async getAllSessions() {
1082
1187
  await this.initialize();
1083
- const rows = await this.db.all(
1188
+ const rows = await dbAll(
1189
+ this.db,
1084
1190
  `SELECT * FROM sessions ORDER BY started_at DESC`
1085
1191
  );
1086
1192
  return rows.map((row) => ({
1087
1193
  id: row.id,
1088
- startedAt: new Date(row.started_at),
1089
- endedAt: row.ended_at ? new Date(row.ended_at) : void 0,
1194
+ startedAt: toDate(row.started_at),
1195
+ endedAt: row.ended_at ? toDate(row.ended_at) : void 0,
1090
1196
  projectPath: row.project_path,
1091
1197
  summary: row.summary,
1092
1198
  tags: row.tags ? JSON.parse(row.tags) : void 0
@@ -1096,7 +1202,7 @@ var EventStore = class {
1096
1202
  * Close database connection
1097
1203
  */
1098
1204
  async close() {
1099
- await this.db.close();
1205
+ await dbClose(this.db);
1100
1206
  }
1101
1207
  /**
1102
1208
  * Convert database row to MemoryEvent
@@ -1106,7 +1212,7 @@ var EventStore = class {
1106
1212
  id: row.id,
1107
1213
  eventType: row.event_type,
1108
1214
  sessionId: row.session_id,
1109
- timestamp: new Date(row.timestamp),
1215
+ timestamp: toDate(row.timestamp),
1110
1216
  content: row.content,
1111
1217
  canonicalKey: row.canonical_key,
1112
1218
  dedupeKey: row.dedupe_key,
@@ -1132,7 +1238,8 @@ var EntityRepo = class {
1132
1238
  const titleNorm = input.title.toLowerCase().trim();
1133
1239
  const searchText = `${input.title} ${JSON.stringify(input.currentJson)}`;
1134
1240
  const now = /* @__PURE__ */ new Date();
1135
- await this.db.run(
1241
+ await dbRun(
1242
+ this.db,
1136
1243
  `INSERT INTO entities (
1137
1244
  entity_id, entity_type, canonical_key, title, stage, status,
1138
1245
  current_json, title_norm, search_text, created_at, updated_at
@@ -1151,7 +1258,8 @@ var EntityRepo = class {
1151
1258
  now.toISOString()
1152
1259
  ]
1153
1260
  );
1154
- await this.db.run(
1261
+ await dbRun(
1262
+ this.db,
1155
1263
  `INSERT INTO entity_aliases (entity_type, canonical_key, entity_id, is_primary)
1156
1264
  VALUES (?, ?, ?, TRUE)
1157
1265
  ON CONFLICT (entity_type, canonical_key) DO NOTHING`,
@@ -1175,7 +1283,8 @@ var EntityRepo = class {
1175
1283
  * Find entity by ID
1176
1284
  */
1177
1285
  async findById(entityId) {
1178
- const rows = await this.db.all(
1286
+ const rows = await dbAll(
1287
+ this.db,
1179
1288
  `SELECT * FROM entities WHERE entity_id = ?`,
1180
1289
  [entityId]
1181
1290
  );
@@ -1187,7 +1296,8 @@ var EntityRepo = class {
1187
1296
  * Find entity by canonical key
1188
1297
  */
1189
1298
  async findByCanonicalKey(entityType, canonicalKey) {
1190
- const rows = await this.db.all(
1299
+ const rows = await dbAll(
1300
+ this.db,
1191
1301
  `SELECT * FROM entities
1192
1302
  WHERE entity_type = ? AND canonical_key = ?`,
1193
1303
  [entityType, canonicalKey]
@@ -1238,7 +1348,8 @@ var EntityRepo = class {
1238
1348
  updates.push("updated_at = ?");
1239
1349
  values.push((/* @__PURE__ */ new Date()).toISOString());
1240
1350
  values.push(entityId);
1241
- await this.db.run(
1351
+ await dbRun(
1352
+ this.db,
1242
1353
  `UPDATE entities SET ${updates.join(", ")} WHERE entity_id = ?`,
1243
1354
  values
1244
1355
  );
@@ -1263,7 +1374,7 @@ var EntityRepo = class {
1263
1374
  query += ` OFFSET ?`;
1264
1375
  params.push(options.offset);
1265
1376
  }
1266
- const rows = await this.db.all(query, params);
1377
+ const rows = await dbAll(this.db, query, params);
1267
1378
  return rows.map((row) => this.rowToEntity(row));
1268
1379
  }
1269
1380
  /**
@@ -1282,14 +1393,15 @@ var EntityRepo = class {
1282
1393
  sql += ` LIMIT ?`;
1283
1394
  params.push(options.limit);
1284
1395
  }
1285
- const rows = await this.db.all(sql, params);
1396
+ const rows = await dbAll(this.db, sql, params);
1286
1397
  return rows.map((row) => this.rowToEntity(row));
1287
1398
  }
1288
1399
  /**
1289
1400
  * Get tasks by status
1290
1401
  */
1291
1402
  async getTasksByStatus(status) {
1292
- const rows = await this.db.all(
1403
+ const rows = await dbAll(
1404
+ this.db,
1293
1405
  `SELECT * FROM entities
1294
1406
  WHERE entity_type = 'task'
1295
1407
  AND json_extract(current_json, '$.status') = ?
@@ -1306,7 +1418,8 @@ var EntityRepo = class {
1306
1418
  const tasks = await this.getTasksByStatus("blocked");
1307
1419
  const results = [];
1308
1420
  for (const task of tasks) {
1309
- const blockerEdges = await this.db.all(
1421
+ const blockerEdges = await dbAll(
1422
+ this.db,
1310
1423
  `SELECT e.dst_id, ent.entity_type, ent.title
1311
1424
  FROM edges e
1312
1425
  JOIN entities ent ON ent.entity_id = e.dst_id
@@ -1328,7 +1441,8 @@ var EntityRepo = class {
1328
1441
  * Add alias for entity
1329
1442
  */
1330
1443
  async addAlias(entityType, canonicalKey, entityId) {
1331
- await this.db.run(
1444
+ await dbRun(
1445
+ this.db,
1332
1446
  `INSERT INTO entity_aliases (entity_type, canonical_key, entity_id, is_primary)
1333
1447
  VALUES (?, ?, ?, FALSE)
1334
1448
  ON CONFLICT (entity_type, canonical_key) DO NOTHING`,
@@ -1339,7 +1453,8 @@ var EntityRepo = class {
1339
1453
  * Find entity by alias
1340
1454
  */
1341
1455
  async findByAlias(entityType, canonicalKey) {
1342
- const rows = await this.db.all(
1456
+ const rows = await dbAll(
1457
+ this.db,
1343
1458
  `SELECT e.* FROM entities e
1344
1459
  JOIN entity_aliases a ON e.entity_id = a.entity_id
1345
1460
  WHERE a.entity_type = ? AND a.canonical_key = ?`,
@@ -1363,8 +1478,8 @@ var EntityRepo = class {
1363
1478
  currentJson: typeof row.current_json === "string" ? JSON.parse(row.current_json) : row.current_json,
1364
1479
  titleNorm: row.title_norm,
1365
1480
  searchText: row.search_text,
1366
- createdAt: new Date(row.created_at),
1367
- updatedAt: new Date(row.updated_at)
1481
+ createdAt: toDate(row.created_at),
1482
+ updatedAt: toDate(row.updated_at)
1368
1483
  };
1369
1484
  }
1370
1485
  };
@@ -1381,7 +1496,8 @@ var EdgeRepo = class {
1381
1496
  async create(input) {
1382
1497
  const edgeId = randomUUID3();
1383
1498
  const now = /* @__PURE__ */ new Date();
1384
- await this.db.run(
1499
+ await dbRun(
1500
+ this.db,
1385
1501
  `INSERT INTO edges (edge_id, src_type, src_id, rel_type, dst_type, dst_id, meta_json, created_at)
1386
1502
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
1387
1503
  ON CONFLICT DO NOTHING`,
@@ -1419,7 +1535,8 @@ var EdgeRepo = class {
1419
1535
  input.dstId
1420
1536
  );
1421
1537
  if (existing) {
1422
- await this.db.run(
1538
+ await dbRun(
1539
+ this.db,
1423
1540
  `UPDATE edges SET meta_json = ? WHERE edge_id = ?`,
1424
1541
  [JSON.stringify(input.metaJson ?? {}), existing.edgeId]
1425
1542
  );
@@ -1431,7 +1548,8 @@ var EdgeRepo = class {
1431
1548
  * Find edge by endpoints
1432
1549
  */
1433
1550
  async findByEndpoints(srcType, srcId, relType, dstType, dstId) {
1434
- const rows = await this.db.all(
1551
+ const rows = await dbAll(
1552
+ this.db,
1435
1553
  `SELECT * FROM edges
1436
1554
  WHERE src_type = ? AND src_id = ? AND rel_type = ?
1437
1555
  AND dst_type = ? AND dst_id = ?`,
@@ -1452,7 +1570,7 @@ var EdgeRepo = class {
1452
1570
  params.push(relType);
1453
1571
  }
1454
1572
  query += ` ORDER BY created_at DESC`;
1455
- const rows = await this.db.all(query, params);
1573
+ const rows = await dbAll(this.db, query, params);
1456
1574
  return rows.map((row) => this.rowToEdge(row));
1457
1575
  }
1458
1576
  /**
@@ -1466,7 +1584,7 @@ var EdgeRepo = class {
1466
1584
  params.push(relType);
1467
1585
  }
1468
1586
  query += ` ORDER BY created_at DESC`;
1469
- const rows = await this.db.all(query, params);
1587
+ const rows = await dbAll(this.db, query, params);
1470
1588
  return rows.map((row) => this.rowToEdge(row));
1471
1589
  }
1472
1590
  /**
@@ -1481,7 +1599,8 @@ var EdgeRepo = class {
1481
1599
  * Delete edge by ID
1482
1600
  */
1483
1601
  async delete(edgeId) {
1484
- const result = await this.db.run(
1602
+ await dbRun(
1603
+ this.db,
1485
1604
  `DELETE FROM edges WHERE edge_id = ?`,
1486
1605
  [edgeId]
1487
1606
  );
@@ -1491,7 +1610,8 @@ var EdgeRepo = class {
1491
1610
  * Delete edges by source and relation type
1492
1611
  */
1493
1612
  async deleteBySrcAndRel(srcId, relType) {
1494
- await this.db.run(
1613
+ await dbRun(
1614
+ this.db,
1495
1615
  `DELETE FROM edges WHERE src_id = ? AND rel_type = ?`,
1496
1616
  [srcId, relType]
1497
1617
  );
@@ -1501,7 +1621,8 @@ var EdgeRepo = class {
1501
1621
  * Delete edges by destination and relation type
1502
1622
  */
1503
1623
  async deleteByDstAndRel(dstId, relType) {
1504
- await this.db.run(
1624
+ await dbRun(
1625
+ this.db,
1505
1626
  `DELETE FROM edges WHERE dst_id = ? AND rel_type = ?`,
1506
1627
  [dstId, relType]
1507
1628
  );
@@ -1535,7 +1656,8 @@ var EdgeRepo = class {
1535
1656
  const blockerEdges = await this.findBySrc(taskId, "blocked_by");
1536
1657
  const results = [];
1537
1658
  for (const edge of blockerEdges) {
1538
- const resolvesTo = await this.db.all(
1659
+ const resolvesTo = await dbAll(
1660
+ this.db,
1539
1661
  `SELECT dst_id FROM edges
1540
1662
  WHERE src_id = ? AND rel_type = 'resolves_to'
1541
1663
  LIMIT 1`,
@@ -1561,7 +1683,8 @@ var EdgeRepo = class {
1561
1683
  * Find 2-hop related entries (Entry → Entity → Entry)
1562
1684
  */
1563
1685
  async findRelatedEntries(entryId) {
1564
- const rows = await this.db.all(
1686
+ const rows = await dbAll(
1687
+ this.db,
1565
1688
  `WITH first_hop AS (
1566
1689
  SELECT e1.dst_id AS entity_id
1567
1690
  FROM edges e1
@@ -1590,7 +1713,8 @@ var EdgeRepo = class {
1590
1713
  * Count edges by relation type
1591
1714
  */
1592
1715
  async countByRelType() {
1593
- const rows = await this.db.all(
1716
+ const rows = await dbAll(
1717
+ this.db,
1594
1718
  `SELECT rel_type, COUNT(*) as count FROM edges GROUP BY rel_type`
1595
1719
  );
1596
1720
  return rows.map((row) => ({
@@ -1610,7 +1734,7 @@ var EdgeRepo = class {
1610
1734
  dstType: row.dst_type,
1611
1735
  dstId: row.dst_id,
1612
1736
  metaJson: typeof row.meta_json === "string" ? JSON.parse(row.meta_json) : row.meta_json,
1613
- createdAt: new Date(row.created_at)
1737
+ createdAt: toDate(row.created_at)
1614
1738
  };
1615
1739
  }
1616
1740
  };
@@ -1699,23 +1823,28 @@ var VectorStore = class {
1699
1823
  return [];
1700
1824
  }
1701
1825
  const { limit = 5, minScore = 0.7, sessionId } = options;
1702
- let query = this.table.search(queryVector).limit(limit * 2);
1826
+ let query = this.table.search(queryVector).distanceType("cosine").limit(limit * 2);
1703
1827
  if (sessionId) {
1704
1828
  query = query.where(`sessionId = '${sessionId}'`);
1705
1829
  }
1706
1830
  const results = await query.toArray();
1707
1831
  return results.filter((r) => {
1708
- const score = 1 - (r._distance || 0);
1832
+ const distance = r._distance || 0;
1833
+ const score = 1 - distance / 2;
1709
1834
  return score >= minScore;
1710
- }).slice(0, limit).map((r) => ({
1711
- id: r.id,
1712
- eventId: r.eventId,
1713
- content: r.content,
1714
- score: 1 - (r._distance || 0),
1715
- sessionId: r.sessionId,
1716
- eventType: r.eventType,
1717
- timestamp: r.timestamp
1718
- }));
1835
+ }).slice(0, limit).map((r) => {
1836
+ const distance = r._distance || 0;
1837
+ const score = 1 - distance / 2;
1838
+ return {
1839
+ id: r.id,
1840
+ eventId: r.eventId,
1841
+ content: r.content,
1842
+ score,
1843
+ sessionId: r.sessionId,
1844
+ eventType: r.eventType,
1845
+ timestamp: r.timestamp
1846
+ };
1847
+ });
1719
1848
  }
1720
1849
  /**
1721
1850
  * Delete vector by event ID
@@ -1859,7 +1988,8 @@ var VectorOutbox = class {
1859
1988
  const version = embeddingVersion ?? this.config.embeddingVersion;
1860
1989
  const jobId = randomUUID4();
1861
1990
  const now = (/* @__PURE__ */ new Date()).toISOString();
1862
- await this.db.run(
1991
+ await dbRun(
1992
+ this.db,
1863
1993
  `INSERT INTO vector_outbox (
1864
1994
  job_id, item_kind, item_id, embedding_version, status, retry_count, created_at, updated_at
1865
1995
  ) VALUES (?, ?, ?, ?, 'pending', 0, ?, ?)
@@ -1873,7 +2003,8 @@ var VectorOutbox = class {
1873
2003
  */
1874
2004
  async claimJobs(limit = 32) {
1875
2005
  const now = (/* @__PURE__ */ new Date()).toISOString();
1876
- const rows = await this.db.all(
2006
+ const rows = await dbAll(
2007
+ this.db,
1877
2008
  `UPDATE vector_outbox
1878
2009
  SET status = 'processing', updated_at = ?
1879
2010
  WHERE job_id IN (
@@ -1891,7 +2022,8 @@ var VectorOutbox = class {
1891
2022
  * Mark job as done
1892
2023
  */
1893
2024
  async markDone(jobId) {
1894
- await this.db.run(
2025
+ await dbRun(
2026
+ this.db,
1895
2027
  `UPDATE vector_outbox
1896
2028
  SET status = 'done', updated_at = ?
1897
2029
  WHERE job_id = ?`,
@@ -1903,7 +2035,8 @@ var VectorOutbox = class {
1903
2035
  */
1904
2036
  async markFailed(jobId, error) {
1905
2037
  const now = (/* @__PURE__ */ new Date()).toISOString();
1906
- const rows = await this.db.all(
2038
+ const rows = await dbAll(
2039
+ this.db,
1907
2040
  `SELECT retry_count FROM vector_outbox WHERE job_id = ?`,
1908
2041
  [jobId]
1909
2042
  );
@@ -1911,7 +2044,8 @@ var VectorOutbox = class {
1911
2044
  return;
1912
2045
  const retryCount = rows[0].retry_count;
1913
2046
  const newStatus = retryCount >= this.config.maxRetries - 1 ? "failed" : "pending";
1914
- await this.db.run(
2047
+ await dbRun(
2048
+ this.db,
1915
2049
  `UPDATE vector_outbox
1916
2050
  SET status = ?, error = ?, retry_count = retry_count + 1, updated_at = ?
1917
2051
  WHERE job_id = ?`,
@@ -1922,7 +2056,8 @@ var VectorOutbox = class {
1922
2056
  * Get job by ID
1923
2057
  */
1924
2058
  async getJob(jobId) {
1925
- const rows = await this.db.all(
2059
+ const rows = await dbAll(
2060
+ this.db,
1926
2061
  `SELECT * FROM vector_outbox WHERE job_id = ?`,
1927
2062
  [jobId]
1928
2063
  );
@@ -1934,7 +2069,8 @@ var VectorOutbox = class {
1934
2069
  * Get jobs by status
1935
2070
  */
1936
2071
  async getJobsByStatus(status, limit = 100) {
1937
- const rows = await this.db.all(
2072
+ const rows = await dbAll(
2073
+ this.db,
1938
2074
  `SELECT * FROM vector_outbox
1939
2075
  WHERE status = ?
1940
2076
  ORDER BY created_at ASC
@@ -1949,21 +2085,24 @@ var VectorOutbox = class {
1949
2085
  async reconcile() {
1950
2086
  const now = /* @__PURE__ */ new Date();
1951
2087
  const stuckThreshold = new Date(now.getTime() - this.config.stuckThresholdMs);
1952
- const recoveredResult = await this.db.run(
2088
+ await dbRun(
2089
+ this.db,
1953
2090
  `UPDATE vector_outbox
1954
2091
  SET status = 'pending', updated_at = ?
1955
2092
  WHERE status = 'processing'
1956
2093
  AND updated_at < ?`,
1957
2094
  [now.toISOString(), stuckThreshold.toISOString()]
1958
2095
  );
1959
- const retriedResult = await this.db.run(
2096
+ await dbRun(
2097
+ this.db,
1960
2098
  `UPDATE vector_outbox
1961
2099
  SET status = 'pending', updated_at = ?
1962
2100
  WHERE status = 'failed'
1963
2101
  AND retry_count < ?`,
1964
2102
  [now.toISOString(), this.config.maxRetries]
1965
2103
  );
1966
- const recoveredRows = await this.db.all(
2104
+ const recoveredRows = await dbAll(
2105
+ this.db,
1967
2106
  `SELECT COUNT(*) as count FROM vector_outbox
1968
2107
  WHERE status = 'pending' AND updated_at = ?`,
1969
2108
  [now.toISOString()]
@@ -1981,7 +2120,8 @@ var VectorOutbox = class {
1981
2120
  async cleanup() {
1982
2121
  const threshold = /* @__PURE__ */ new Date();
1983
2122
  threshold.setDate(threshold.getDate() - this.config.cleanupDays);
1984
- await this.db.run(
2123
+ await dbRun(
2124
+ this.db,
1985
2125
  `DELETE FROM vector_outbox
1986
2126
  WHERE status = 'done'
1987
2127
  AND updated_at < ?`,
@@ -1993,12 +2133,14 @@ var VectorOutbox = class {
1993
2133
  * Get metrics
1994
2134
  */
1995
2135
  async getMetrics() {
1996
- const statusCounts = await this.db.all(
2136
+ const statusCounts = await dbAll(
2137
+ this.db,
1997
2138
  `SELECT status, COUNT(*) as count
1998
2139
  FROM vector_outbox
1999
2140
  GROUP BY status`
2000
2141
  );
2001
- const oldestPending = await this.db.all(
2142
+ const oldestPending = await dbAll(
2143
+ this.db,
2002
2144
  `SELECT created_at FROM vector_outbox
2003
2145
  WHERE status = 'pending'
2004
2146
  ORDER BY created_at ASC
@@ -2057,8 +2199,8 @@ var VectorOutbox = class {
2057
2199
  status: row.status,
2058
2200
  retryCount: row.retry_count,
2059
2201
  error: row.error,
2060
- createdAt: new Date(row.created_at),
2061
- updatedAt: new Date(row.updated_at)
2202
+ createdAt: toDate(row.created_at),
2203
+ updatedAt: toDate(row.updated_at)
2062
2204
  };
2063
2205
  }
2064
2206
  };
@@ -2210,7 +2352,8 @@ var DefaultContentProvider = class {
2210
2352
  }
2211
2353
  }
2212
2354
  async getEntryContent(entryId) {
2213
- const rows = await this.db.all(
2355
+ const rows = await dbAll(
2356
+ this.db,
2214
2357
  `SELECT title, content_json, entry_type FROM entries WHERE entry_id = ?`,
2215
2358
  [entryId]
2216
2359
  );
@@ -2228,7 +2371,8 @@ ${JSON.stringify(contentJson)}`,
2228
2371
  };
2229
2372
  }
2230
2373
  async getTaskTitleContent(taskId) {
2231
- const rows = await this.db.all(
2374
+ const rows = await dbAll(
2375
+ this.db,
2232
2376
  `SELECT title, search_text, current_json FROM entities
2233
2377
  WHERE entity_id = ? AND entity_type = 'task'`,
2234
2378
  [taskId]
@@ -2245,7 +2389,8 @@ ${JSON.stringify(contentJson)}`,
2245
2389
  };
2246
2390
  }
2247
2391
  async getEventContent(eventId) {
2248
- const rows = await this.db.all(
2392
+ const rows = await dbAll(
2393
+ this.db,
2249
2394
  `SELECT content, event_type, session_id FROM events WHERE id = ?`,
2250
2395
  [eventId]
2251
2396
  );
@@ -3388,7 +3533,8 @@ var TaskMatcher = class {
3388
3533
  */
3389
3534
  async findExact(title, project) {
3390
3535
  const canonicalKey = makeEntityCanonicalKey("task", title, { project });
3391
- const rows = await this.db.all(
3536
+ const rows = await dbAll(
3537
+ this.db,
3392
3538
  `SELECT * FROM entities
3393
3539
  WHERE entity_type = 'task' AND canonical_key = ?
3394
3540
  AND status = 'active'`,
@@ -3403,7 +3549,8 @@ var TaskMatcher = class {
3403
3549
  */
3404
3550
  async findByAlias(title, project) {
3405
3551
  const canonicalKey = makeEntityCanonicalKey("task", title, { project });
3406
- const rows = await this.db.all(
3552
+ const rows = await dbAll(
3553
+ this.db,
3407
3554
  `SELECT e.* FROM entities e
3408
3555
  JOIN entity_aliases a ON e.entity_id = a.entity_id
3409
3556
  WHERE a.entity_type = 'task' AND a.canonical_key = ?
@@ -3439,7 +3586,7 @@ var TaskMatcher = class {
3439
3586
  }
3440
3587
  sql += ` ORDER BY match_score DESC, updated_at DESC LIMIT ?`;
3441
3588
  params.push(this.config.maxCandidates);
3442
- const rows = await this.db.all(sql, params);
3589
+ const rows = await dbAll(this.db, sql, params);
3443
3590
  return rows.map((row) => ({
3444
3591
  entity: this.rowToEntity(row),
3445
3592
  score: row.match_score
@@ -3535,8 +3682,8 @@ var TaskMatcher = class {
3535
3682
  currentJson: typeof row.current_json === "string" ? JSON.parse(row.current_json) : row.current_json,
3536
3683
  titleNorm: row.title_norm,
3537
3684
  searchText: row.search_text,
3538
- createdAt: new Date(row.created_at),
3539
- updatedAt: new Date(row.updated_at)
3685
+ createdAt: toDate(row.created_at),
3686
+ updatedAt: toDate(row.updated_at)
3540
3687
  };
3541
3688
  }
3542
3689
  };
@@ -3608,7 +3755,8 @@ var BlockerResolver = class {
3608
3755
  return null;
3609
3756
  }
3610
3757
  const canonicalKey = makeArtifactKey(text);
3611
- const existing = await this.db.all(
3758
+ const existing = await dbAll(
3759
+ this.db,
3612
3760
  `SELECT entity_id FROM entities
3613
3761
  WHERE entity_type = 'artifact' AND canonical_key = ?`,
3614
3762
  [canonicalKey]
@@ -3630,7 +3778,8 @@ var BlockerResolver = class {
3630
3778
  * Try to resolve as explicit task ID
3631
3779
  */
3632
3780
  async tryResolveAsTaskId(taskId) {
3633
- const rows = await this.db.all(
3781
+ const rows = await dbAll(
3782
+ this.db,
3634
3783
  `SELECT entity_id FROM entities
3635
3784
  WHERE entity_type = 'task' AND canonical_key = ?
3636
3785
  AND status = 'active'`,
@@ -3653,7 +3802,8 @@ var BlockerResolver = class {
3653
3802
  const canonicalKey = makeEntityCanonicalKey("condition", text, {
3654
3803
  project: this.config.project
3655
3804
  });
3656
- const existing = await this.db.all(
3805
+ const existing = await dbAll(
3806
+ this.db,
3657
3807
  `SELECT entity_id FROM entities
3658
3808
  WHERE entity_type = 'condition' AND canonical_key = ?`,
3659
3809
  [canonicalKey]
@@ -3686,7 +3836,8 @@ var BlockerResolver = class {
3686
3836
  title: c.title
3687
3837
  }))
3688
3838
  };
3689
- await this.db.run(
3839
+ await dbRun(
3840
+ this.db,
3690
3841
  `INSERT INTO entities (
3691
3842
  entity_id, entity_type, canonical_key, title, stage, status,
3692
3843
  current_json, title_norm, search_text, created_at, updated_at
@@ -3705,7 +3856,8 @@ var BlockerResolver = class {
3705
3856
  now
3706
3857
  ]
3707
3858
  );
3708
- await this.db.run(
3859
+ await dbRun(
3860
+ this.db,
3709
3861
  `INSERT INTO entity_aliases (entity_type, canonical_key, entity_id, is_primary)
3710
3862
  VALUES (?, ?, ?, TRUE)
3711
3863
  ON CONFLICT (entity_type, canonical_key) DO NOTHING`,
@@ -3731,7 +3883,8 @@ var BlockerResolver = class {
3731
3883
  identifier,
3732
3884
  artifactType
3733
3885
  };
3734
- await this.db.run(
3886
+ await dbRun(
3887
+ this.db,
3735
3888
  `INSERT INTO entities (
3736
3889
  entity_id, entity_type, canonical_key, title, stage, status,
3737
3890
  current_json, title_norm, search_text, created_at, updated_at
@@ -3750,7 +3903,8 @@ var BlockerResolver = class {
3750
3903
  now
3751
3904
  ]
3752
3905
  );
3753
- await this.db.run(
3906
+ await dbRun(
3907
+ this.db,
3754
3908
  `INSERT INTO entity_aliases (entity_type, canonical_key, entity_id, is_primary)
3755
3909
  VALUES (?, ?, ?, TRUE)
3756
3910
  ON CONFLICT (entity_type, canonical_key) DO NOTHING`,
@@ -3765,7 +3919,8 @@ var BlockerResolver = class {
3765
3919
  async createUnknownPlaceholder(taskTitle) {
3766
3920
  const text = `Unknown blocker for: ${taskTitle}`;
3767
3921
  const ref = await this.createConditionBlocker(text);
3768
- await this.db.run(
3922
+ await dbRun(
3923
+ this.db,
3769
3924
  `UPDATE entities
3770
3925
  SET current_json = json_set(current_json, '$.auto_placeholder', true)
3771
3926
  WHERE entity_id = ?`,
@@ -3869,7 +4024,8 @@ var TaskResolver = class {
3869
4024
  description: extracted.description,
3870
4025
  project: extracted.project ?? this.config.project
3871
4026
  };
3872
- await this.db.run(
4027
+ await dbRun(
4028
+ this.db,
3873
4029
  `INSERT INTO entities (
3874
4030
  entity_id, entity_type, canonical_key, title, stage, status,
3875
4031
  current_json, title_norm, search_text, created_at, updated_at
@@ -3888,7 +4044,8 @@ var TaskResolver = class {
3888
4044
  now.toISOString()
3889
4045
  ]
3890
4046
  );
3891
- await this.db.run(
4047
+ await dbRun(
4048
+ this.db,
3892
4049
  `INSERT INTO entity_aliases (entity_type, canonical_key, entity_id, is_primary)
3893
4050
  VALUES (?, ?, ?, TRUE)
3894
4051
  ON CONFLICT (entity_type, canonical_key) DO NOTHING`,
@@ -3941,7 +4098,8 @@ var TaskResolver = class {
3941
4098
  fromStatus: currentStatus,
3942
4099
  toStatus: newStatus
3943
4100
  });
3944
- await this.db.run(
4101
+ await dbRun(
4102
+ this.db,
3945
4103
  `UPDATE entities
3946
4104
  SET current_json = json_set(current_json, '$.status', ?),
3947
4105
  updated_at = ?
@@ -3964,7 +4122,8 @@ var TaskResolver = class {
3964
4122
  fromPriority: currentPriority,
3965
4123
  toPriority: newPriority
3966
4124
  });
3967
- await this.db.run(
4125
+ await dbRun(
4126
+ this.db,
3968
4127
  `UPDATE entities
3969
4128
  SET current_json = json_set(current_json, '$.priority', ?),
3970
4129
  updated_at = ?
@@ -4011,14 +4170,16 @@ var TaskResolver = class {
4011
4170
  this.config.sessionId,
4012
4171
  JSON.stringify(payload)
4013
4172
  );
4014
- const existing = await this.db.all(
4173
+ const existing = await dbAll(
4174
+ this.db,
4015
4175
  `SELECT event_id FROM event_dedup WHERE dedupe_key = ?`,
4016
4176
  [dedupeKey]
4017
4177
  );
4018
4178
  if (existing.length > 0) {
4019
4179
  return existing[0].event_id;
4020
4180
  }
4021
- await this.db.run(
4181
+ await dbRun(
4182
+ this.db,
4022
4183
  `INSERT INTO events (
4023
4184
  id, event_type, session_id, timestamp, content,
4024
4185
  canonical_key, dedupe_key, metadata
@@ -4034,7 +4195,8 @@ var TaskResolver = class {
4034
4195
  JSON.stringify({ source: "task_resolver" })
4035
4196
  ]
4036
4197
  );
4037
- await this.db.run(
4198
+ await dbRun(
4199
+ this.db,
4038
4200
  `INSERT INTO event_dedup (dedupe_key, event_id)
4039
4201
  VALUES (?, ?)
4040
4202
  ON CONFLICT DO NOTHING`,
@@ -4053,7 +4215,8 @@ var TaskResolver = class {
4053
4215
  entityId: taskId
4054
4216
  }
4055
4217
  });
4056
- await this.db.run(
4218
+ await dbRun(
4219
+ this.db,
4057
4220
  `INSERT INTO edges (edge_id, src_type, src_id, rel_type, dst_type, dst_id, meta_json)
4058
4221
  VALUES (?, 'entity', ?, 'resolves_to', 'entity', ?, ?)
4059
4222
  ON CONFLICT DO NOTHING`,
@@ -4082,7 +4245,8 @@ var TaskProjector = class {
4082
4245
  * Get current projection offset
4083
4246
  */
4084
4247
  async getOffset() {
4085
- const rows = await this.db.all(
4248
+ const rows = await dbAll(
4249
+ this.db,
4086
4250
  `SELECT last_event_id, last_timestamp
4087
4251
  FROM projection_offsets
4088
4252
  WHERE projection_name = ?`,
@@ -4100,7 +4264,8 @@ var TaskProjector = class {
4100
4264
  * Update projection offset
4101
4265
  */
4102
4266
  async updateOffset(eventId, timestamp) {
4103
- await this.db.run(
4267
+ await dbRun(
4268
+ this.db,
4104
4269
  `INSERT INTO projection_offsets (projection_name, last_event_id, last_timestamp, updated_at)
4105
4270
  VALUES (?, ?, ?, CURRENT_TIMESTAMP)
4106
4271
  ON CONFLICT (projection_name) DO UPDATE SET
@@ -4130,12 +4295,12 @@ var TaskProjector = class {
4130
4295
  }
4131
4296
  query += ` ORDER BY timestamp ASC, id ASC LIMIT ?`;
4132
4297
  params.push(limit);
4133
- const rows = await this.db.all(query, params);
4298
+ const rows = await dbAll(this.db, query, params);
4134
4299
  return rows.map((row) => ({
4135
4300
  id: row.id,
4136
4301
  eventType: row.event_type,
4137
4302
  sessionId: row.session_id,
4138
- timestamp: new Date(row.timestamp),
4303
+ timestamp: toDate(row.timestamp),
4139
4304
  content: typeof row.content === "string" ? JSON.parse(row.content) : row.content
4140
4305
  }));
4141
4306
  }
@@ -4195,12 +4360,14 @@ var TaskProjector = class {
4195
4360
  async handleStatusChanged(event) {
4196
4361
  const { taskId, toStatus } = event.content;
4197
4362
  if (toStatus === "done") {
4198
- await this.db.run(
4363
+ await dbRun(
4364
+ this.db,
4199
4365
  `DELETE FROM edges
4200
4366
  WHERE src_id = ? AND rel_type IN ('blocked_by', 'blocked_by_suggested')`,
4201
4367
  [taskId]
4202
4368
  );
4203
- await this.db.run(
4369
+ await dbRun(
4370
+ this.db,
4204
4371
  `UPDATE entities
4205
4372
  SET current_json = json_remove(json_remove(current_json, '$.blockers'), '$.blockerSuggestions'),
4206
4373
  updated_at = CURRENT_TIMESTAMP
@@ -4215,7 +4382,8 @@ var TaskProjector = class {
4215
4382
  async handleBlockersSet(event) {
4216
4383
  const { taskId, mode, blockers } = event.content;
4217
4384
  if (mode === "replace") {
4218
- await this.db.run(
4385
+ await dbRun(
4386
+ this.db,
4219
4387
  `DELETE FROM edges WHERE src_id = ? AND rel_type = 'blocked_by'`,
4220
4388
  [taskId]
4221
4389
  );
@@ -4223,7 +4391,8 @@ var TaskProjector = class {
4223
4391
  await this.createBlockerEdge(taskId, blocker, "blocked_by");
4224
4392
  }
4225
4393
  const blockerIds = blockers.map((b) => b.entityId);
4226
- await this.db.run(
4394
+ await dbRun(
4395
+ this.db,
4227
4396
  `UPDATE entities
4228
4397
  SET current_json = json_set(current_json, '$.blockers', ?),
4229
4398
  updated_at = CURRENT_TIMESTAMP
@@ -4231,7 +4400,8 @@ var TaskProjector = class {
4231
4400
  [JSON.stringify(blockerIds), taskId]
4232
4401
  );
4233
4402
  } else {
4234
- await this.db.run(
4403
+ await dbRun(
4404
+ this.db,
4235
4405
  `DELETE FROM edges WHERE src_id = ? AND rel_type = 'blocked_by_suggested'`,
4236
4406
  [taskId]
4237
4407
  );
@@ -4239,7 +4409,8 @@ var TaskProjector = class {
4239
4409
  await this.createBlockerEdge(taskId, blocker, "blocked_by_suggested");
4240
4410
  }
4241
4411
  const suggestionIds = blockers.map((b) => b.entityId);
4242
- await this.db.run(
4412
+ await dbRun(
4413
+ this.db,
4243
4414
  `UPDATE entities
4244
4415
  SET current_json = json_set(current_json, '$.blockerSuggestions', ?),
4245
4416
  updated_at = CURRENT_TIMESTAMP
@@ -4253,7 +4424,8 @@ var TaskProjector = class {
4253
4424
  */
4254
4425
  async createBlockerEdge(taskId, blocker, relType) {
4255
4426
  const edgeId = randomUUID7();
4256
- await this.db.run(
4427
+ await dbRun(
4428
+ this.db,
4257
4429
  `INSERT INTO edges (edge_id, src_type, src_id, rel_type, dst_type, dst_id, meta_json, created_at)
4258
4430
  VALUES (?, 'entity', ?, ?, 'entity', ?, ?, CURRENT_TIMESTAMP)
4259
4431
  ON CONFLICT DO NOTHING`,
@@ -4276,7 +4448,8 @@ var TaskProjector = class {
4276
4448
  */
4277
4449
  async handleConditionResolved(event) {
4278
4450
  const { conditionId, resolvedTo } = event.content;
4279
- await this.db.run(
4451
+ await dbRun(
4452
+ this.db,
4280
4453
  `UPDATE entities
4281
4454
  SET current_json = json_set(json_set(current_json, '$.resolved', true), '$.resolvedTo', ?),
4282
4455
  updated_at = CURRENT_TIMESTAMP
@@ -4290,7 +4463,8 @@ var TaskProjector = class {
4290
4463
  async enqueueForVectorization(itemId, itemKind) {
4291
4464
  const jobId = randomUUID7();
4292
4465
  const embeddingVersion = "v1";
4293
- await this.db.run(
4466
+ await dbRun(
4467
+ this.db,
4294
4468
  `INSERT INTO vector_outbox (job_id, item_kind, item_id, embedding_version, status, retry_count)
4295
4469
  VALUES (?, ?, ?, ?, 'pending', 0)
4296
4470
  ON CONFLICT (item_kind, item_id, embedding_version) DO NOTHING`,
@@ -4302,10 +4476,12 @@ var TaskProjector = class {
4302
4476
  * WARNING: This clears all edges and rebuilds from events
4303
4477
  */
4304
4478
  async rebuild() {
4305
- await this.db.run(
4479
+ await dbRun(
4480
+ this.db,
4306
4481
  `DELETE FROM edges WHERE rel_type IN ('blocked_by', 'blocked_by_suggested', 'resolves_to')`
4307
4482
  );
4308
- await this.db.run(
4483
+ await dbRun(
4484
+ this.db,
4309
4485
  `DELETE FROM projection_offsets WHERE projection_name = ?`,
4310
4486
  [PROJECTOR_NAME]
4311
4487
  );