diff --git a/CHANGELOG.md b/CHANGELOG.md index ed9cb09..94af9fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). Versions follow --- +## [0.2.6] - 2026-03-27 + +### Fixed + +- Self-merge bug in `consolidateDuplicates`: prevent `mergedFrom` from pointing to own ID when records have identical timestamps (issue #25). + +--- + ## [0.2.5] - 2026-03-27 ### Added diff --git a/package-lock.json b/package-lock.json index 02f9a35..a5e9b32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lancedb-opencode-pro", - "version": "0.2.4", + "version": "0.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lancedb-opencode-pro", - "version": "0.2.4", + "version": "0.2.5", "license": "MIT", "dependencies": { "@lancedb/lancedb": "^0.27.1", diff --git a/package.json b/package.json index c90832b..e1bc68e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lancedb-opencode-pro", - "version": "0.2.5", + "version": "0.2.6", "description": "LanceDB-backed long-term memory provider for OpenCode", "type": "module", "main": "dist/index.js", diff --git a/test/foundation/foundation.test.ts b/test/foundation/foundation.test.ts index c3c1fda..3dae6c2 100644 --- a/test/foundation/foundation.test.ts +++ b/test/foundation/foundation.test.ts @@ -726,3 +726,66 @@ test("consolidateDuplicates does not merge records with very low cosine similari await cleanupDbPath(dbPath); } }); + +test("consolidateDuplicates skips self-merge when older.id === newer.id (issue #25)", async () => { + const { store, dbPath } = await createTestStore(); + try { + const scope = "project:self-merge-test"; + const testId = "ebb542a9-dfd2-4d77-aab8-cbecbe2e8998"; + const now = Date.now(); + + await store.put(createTestRecord({ + id: testId, + scope, + text: "test content", + vector: createVector(384, 0.5), + timestamp: now, + lastRecalled: 0, + metadataJson: JSON.stringify({}) + })); + + const result = await store.consolidateDuplicates(scope, 0.95); + + assert.equal(result.mergedPairs, 0, "should not merge self"); + assert.equal(result.updatedRecords, 0, "should not update any records"); + } finally { + await cleanupDbPath(dbPath); + } +}); + +test("consolidateDuplicates merges two similar records correctly after self-merge fix", async () => { + const { store, dbPath } = await createTestStore(); + try { + const scope = "project:merge-test"; + const now = Date.now(); + const sharedText = "This is a test content for duplicate detection"; + const vec = createVector(384, 0.5); + + await store.put(createTestRecord({ + id: "record-old", + scope, + text: sharedText, + vector: vec, + timestamp: now - 10_000, + lastRecalled: 0, + metadataJson: JSON.stringify({}) + })); + + await store.put(createTestRecord({ + id: "record-new", + scope, + text: sharedText, + vector: vec, + timestamp: now, + lastRecalled: 0, + metadataJson: JSON.stringify({}) + })); + + const result = await store.consolidateDuplicates(scope, 0.95); + + assert.equal(result.mergedPairs, 1, "should merge one pair"); + assert.equal(result.updatedRecords, 2, "should update both records"); + } finally { + await cleanupDbPath(dbPath); + } +});