linksee-memory 0.7.1 → 0.8.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.
@@ -33,11 +33,11 @@ export function runMigrations(db) {
33
33
  // v3 → v4: rebuild memories_fts with trigram tokenizer for JP/CJK support.
34
34
  // Only runs when upgrading an existing DB from schema v1-3.
35
35
  if (currentVersion > 0 && currentVersion < 4) {
36
- db.exec(`
37
- DROP TRIGGER IF EXISTS trg_memories_fts_ai;
38
- DROP TRIGGER IF EXISTS trg_memories_fts_ad;
39
- DROP TRIGGER IF EXISTS trg_memories_fts_au;
40
- DROP TABLE IF EXISTS memories_fts;
36
+ db.exec(`
37
+ DROP TRIGGER IF EXISTS trg_memories_fts_ai;
38
+ DROP TRIGGER IF EXISTS trg_memories_fts_ad;
39
+ DROP TRIGGER IF EXISTS trg_memories_fts_au;
40
+ DROP TABLE IF EXISTS memories_fts;
41
41
  `);
42
42
  }
43
43
  // v4 → v5: add normalized_name column BEFORE schema.sql runs,
@@ -81,11 +81,35 @@ export function runMigrations(db) {
81
81
  db.exec('ALTER TABLE memories ADD COLUMN thread_id TEXT');
82
82
  }
83
83
  // Backfill thread_id from content JSON session_id for existing memories
84
- db.exec(`
85
- UPDATE memories SET thread_id = json_extract(content, '$.session_id')
86
- WHERE thread_id IS NULL AND json_valid(content) AND json_extract(content, '$.session_id') IS NOT NULL
84
+ db.exec(`
85
+ UPDATE memories SET thread_id = json_extract(content, '$.session_id')
86
+ WHERE thread_id IS NULL AND json_valid(content) AND json_extract(content, '$.session_id') IS NOT NULL
87
87
  `);
88
88
  }
89
+ // v8 → v9: ProjectCoreNode — extend drift_anchors into the Current Truth Map node.
90
+ // ADDITIVE columns only (ADD COLUMN with safe defaults) — NO CHECK rebuild, so the existing
91
+ // detector/dashboard (which read the original columns + status active/retired) are unaffected.
92
+ // `lifecycle` carries the rich state; `status` stays the coarse scan-gate. New tables
93
+ // (reality_events, memory_write_candidates) are created by db.exec(sql) below (CREATE IF NOT EXISTS).
94
+ if (currentVersion > 0 && currentVersion < 9) {
95
+ const have = new Set(db.prepare('PRAGMA table_info(drift_anchors)').all().map((c) => c.name));
96
+ const addCol = (name, ddl) => {
97
+ if (!have.has(name))
98
+ db.exec(`ALTER TABLE drift_anchors ADD COLUMN ${ddl}`);
99
+ };
100
+ addCol('node_type', 'node_type TEXT');
101
+ addCol('domain', 'domain TEXT');
102
+ addCol('decision_mode', 'decision_mode TEXT');
103
+ addCol('confidence', 'confidence REAL NOT NULL DEFAULT 0.8');
104
+ addCol('lifecycle', "lifecycle TEXT NOT NULL DEFAULT 'active'");
105
+ addCol('validity_scope', "validity_scope TEXT NOT NULL DEFAULT '{}'");
106
+ addCol('card_policy', "card_policy TEXT NOT NULL DEFAULT '{}'");
107
+ addCol('reality_manifestations', "reality_manifestations TEXT NOT NULL DEFAULT '[]'");
108
+ addCol('evidence_refs', "evidence_refs TEXT NOT NULL DEFAULT '[]'");
109
+ addCol('review_after', 'review_after INTEGER');
110
+ addCol('last_confirmed_at', 'last_confirmed_at INTEGER');
111
+ addCol('owner', 'owner TEXT');
112
+ }
89
113
  db.exec(sql);
90
114
  if (currentVersion > 0 && currentVersion < 4) {
91
115
  db.exec(`INSERT INTO memories_fts(rowid, content) SELECT id, content FROM memories;`);
@@ -124,12 +148,12 @@ function migrateV5EntityNormalization(db) {
124
148
  }
125
149
  })();
126
150
  // 4. Auto-merge duplicate entities (same kind + normalized_name)
127
- const dupes = db.prepare(`
128
- SELECT kind, normalized_name, GROUP_CONCAT(id) as ids
129
- FROM entities
130
- WHERE normalized_name IS NOT NULL
131
- GROUP BY kind, normalized_name
132
- HAVING COUNT(*) > 1
151
+ const dupes = db.prepare(`
152
+ SELECT kind, normalized_name, GROUP_CONCAT(id) as ids
153
+ FROM entities
154
+ WHERE normalized_name IS NOT NULL
155
+ GROUP BY kind, normalized_name
156
+ HAVING COUNT(*) > 1
133
157
  `).all();
134
158
  if (dupes.length > 0) {
135
159
  console.log(`[linksee-memory] v5 migration: merging ${dupes.length} duplicate entity clusters`);
@@ -150,12 +174,12 @@ function mergeEntityCluster(db, ids) {
150
174
  if (ids.length < 2)
151
175
  return;
152
176
  // Score each entity: prefer most memories, then has canonical_key, then lowest id
153
- const rows = db.prepare(`
154
- SELECT e.id, e.name, e.canonical_key, COUNT(m.id) as mem_count
155
- FROM entities e LEFT JOIN memories m ON m.entity_id = e.id
156
- WHERE e.id IN (${ids.map(() => '?').join(',')})
157
- GROUP BY e.id
158
- ORDER BY mem_count DESC, (e.canonical_key IS NOT NULL) DESC, e.id ASC
177
+ const rows = db.prepare(`
178
+ SELECT e.id, e.name, e.canonical_key, COUNT(m.id) as mem_count
179
+ FROM entities e LEFT JOIN memories m ON m.entity_id = e.id
180
+ WHERE e.id IN (${ids.map(() => '?').join(',')})
181
+ GROUP BY e.id
182
+ ORDER BY mem_count DESC, (e.canonical_key IS NOT NULL) DESC, e.id ASC
159
183
  `).all(...ids);
160
184
  const keep = rows[0];
161
185
  const mergeIds = rows.slice(1).map(r => r.id);
@@ -176,16 +200,16 @@ function mergeEntityCluster(db, ids) {
176
200
  db.prepare('UPDATE events SET entity_id = ? WHERE entity_id = ?').run(keep.id, mid);
177
201
  // Reassign edges (both directions)
178
202
  // Handle UNIQUE constraint: delete duplicates first
179
- db.prepare(`
180
- DELETE FROM edges WHERE from_id = ? AND EXISTS (
181
- SELECT 1 FROM edges e2 WHERE e2.from_id = ? AND e2.to_id = edges.to_id AND e2.relation = edges.relation
182
- )
203
+ db.prepare(`
204
+ DELETE FROM edges WHERE from_id = ? AND EXISTS (
205
+ SELECT 1 FROM edges e2 WHERE e2.from_id = ? AND e2.to_id = edges.to_id AND e2.relation = edges.relation
206
+ )
183
207
  `).run(mid, keep.id);
184
208
  db.prepare('UPDATE edges SET from_id = ? WHERE from_id = ?').run(keep.id, mid);
185
- db.prepare(`
186
- DELETE FROM edges WHERE to_id = ? AND EXISTS (
187
- SELECT 1 FROM edges e2 WHERE e2.to_id = ? AND e2.from_id = edges.from_id AND e2.relation = edges.relation
188
- )
209
+ db.prepare(`
210
+ DELETE FROM edges WHERE to_id = ? AND EXISTS (
211
+ SELECT 1 FROM edges e2 WHERE e2.to_id = ? AND e2.from_id = edges.from_id AND e2.relation = edges.relation
212
+ )
189
213
  `).run(mid, keep.id);
190
214
  db.prepare('UPDATE edges SET to_id = ? WHERE to_id = ?').run(keep.id, mid);
191
215
  // Reassign consolidations