gnosys-mcp 0.1.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.
- package/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +927 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1092 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/bootstrap.d.ts +56 -0
- package/dist/lib/bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap.js +163 -0
- package/dist/lib/bootstrap.js.map +1 -0
- package/dist/lib/history.d.ts +39 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +86 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/ingest.d.ts +47 -0
- package/dist/lib/ingest.d.ts.map +1 -0
- package/dist/lib/ingest.js +134 -0
- package/dist/lib/ingest.js.map +1 -0
- package/dist/lib/lensing.d.ts +35 -0
- package/dist/lib/lensing.d.ts.map +1 -0
- package/dist/lib/lensing.js +85 -0
- package/dist/lib/lensing.js.map +1 -0
- package/dist/lib/resolver.d.ts +84 -0
- package/dist/lib/resolver.d.ts.map +1 -0
- package/dist/lib/resolver.js +269 -0
- package/dist/lib/resolver.js.map +1 -0
- package/dist/lib/search.d.ts +50 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +166 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/store.d.ts +67 -0
- package/dist/lib/store.d.ts.map +1 -0
- package/dist/lib/store.js +168 -0
- package/dist/lib/store.js.map +1 -0
- package/dist/lib/tags.d.ts +26 -0
- package/dist/lib/tags.d.ts.map +1 -0
- package/dist/lib/tags.js +109 -0
- package/dist/lib/tags.js.map +1 -0
- package/dist/lib/timeline.d.ts +34 -0
- package/dist/lib/timeline.d.ts.map +1 -0
- package/dist/lib/timeline.js +116 -0
- package/dist/lib/timeline.js.map +1 -0
- package/dist/lib/wikilinks.d.ts +63 -0
- package/dist/lib/wikilinks.d.ts.map +1 -0
- package/dist/lib/wikilinks.js +146 -0
- package/dist/lib/wikilinks.js.map +1 -0
- package/dist/test/bootstrap.test.d.ts +2 -0
- package/dist/test/bootstrap.test.d.ts.map +1 -0
- package/dist/test/bootstrap.test.js +208 -0
- package/dist/test/bootstrap.test.js.map +1 -0
- package/dist/test/history.test.d.ts +2 -0
- package/dist/test/history.test.d.ts.map +1 -0
- package/dist/test/history.test.js +141 -0
- package/dist/test/history.test.js.map +1 -0
- package/dist/test/ingest.test.d.ts +2 -0
- package/dist/test/ingest.test.d.ts.map +1 -0
- package/dist/test/ingest.test.js +132 -0
- package/dist/test/ingest.test.js.map +1 -0
- package/dist/test/lensing.test.d.ts +2 -0
- package/dist/test/lensing.test.d.ts.map +1 -0
- package/dist/test/lensing.test.js +154 -0
- package/dist/test/lensing.test.js.map +1 -0
- package/dist/test/search.test.d.ts +2 -0
- package/dist/test/search.test.d.ts.map +1 -0
- package/dist/test/search.test.js +129 -0
- package/dist/test/search.test.js.map +1 -0
- package/dist/test/store.test.d.ts +2 -0
- package/dist/test/store.test.d.ts.map +1 -0
- package/dist/test/store.test.js +152 -0
- package/dist/test/store.test.js.map +1 -0
- package/dist/test/tags.test.d.ts +2 -0
- package/dist/test/tags.test.d.ts.map +1 -0
- package/dist/test/tags.test.js +81 -0
- package/dist/test/tags.test.js.map +1 -0
- package/dist/test/timeline.test.d.ts +2 -0
- package/dist/test/timeline.test.d.ts.map +1 -0
- package/dist/test/timeline.test.js +127 -0
- package/dist/test/timeline.test.js.map +1 -0
- package/dist/test/wikilinks.test.d.ts +2 -0
- package/dist/test/wikilinks.test.d.ts.map +1 -0
- package/dist/test/wikilinks.test.js +178 -0
- package/dist/test/wikilinks.test.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import { GnosysStore } from "../lib/store.js";
|
|
7
|
+
import { getFileHistory, getFileAtCommit, rollbackToCommit, hasGitHistory, getFileDiff, } from "../lib/history.js";
|
|
8
|
+
let tmpDir;
|
|
9
|
+
let store;
|
|
10
|
+
function makeFrontmatter(overrides = {}) {
|
|
11
|
+
return {
|
|
12
|
+
id: "test-001",
|
|
13
|
+
title: "Test Memory",
|
|
14
|
+
category: "decisions",
|
|
15
|
+
tags: { domain: ["testing"], type: ["decision"] },
|
|
16
|
+
relevance: "test history rollback versioning",
|
|
17
|
+
author: "human",
|
|
18
|
+
authority: "declared",
|
|
19
|
+
confidence: 0.8,
|
|
20
|
+
created: "2026-03-01",
|
|
21
|
+
modified: "2026-03-01",
|
|
22
|
+
status: "active",
|
|
23
|
+
supersedes: null,
|
|
24
|
+
...overrides,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
beforeEach(async () => {
|
|
28
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "gnosys-history-"));
|
|
29
|
+
store = new GnosysStore(tmpDir);
|
|
30
|
+
await store.init();
|
|
31
|
+
// Configure git user for commits in this temp directory
|
|
32
|
+
execSync('git config user.email "test@gnosys.dev"', { cwd: tmpDir, stdio: "pipe" });
|
|
33
|
+
execSync('git config user.name "Gnosys Test"', { cwd: tmpDir, stdio: "pipe" });
|
|
34
|
+
});
|
|
35
|
+
afterEach(async () => {
|
|
36
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
37
|
+
});
|
|
38
|
+
describe("hasGitHistory", () => {
|
|
39
|
+
it("returns true for a git-initialized store", () => {
|
|
40
|
+
expect(hasGitHistory(tmpDir)).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
it("returns false for a non-git directory", async () => {
|
|
43
|
+
const plainDir = await fs.mkdtemp(path.join(os.tmpdir(), "no-git-"));
|
|
44
|
+
expect(hasGitHistory(plainDir)).toBe(false);
|
|
45
|
+
await fs.rm(plainDir, { recursive: true, force: true });
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe("getFileHistory", () => {
|
|
49
|
+
it("returns history after write and update", async () => {
|
|
50
|
+
const fm = makeFrontmatter();
|
|
51
|
+
await store.writeMemory("decisions", "auth.md", fm, "# Auth\n\nVersion 1");
|
|
52
|
+
// Update the memory
|
|
53
|
+
await store.updateMemory("decisions/auth.md", { title: "Auth Updated", confidence: 0.9 });
|
|
54
|
+
const history = getFileHistory(tmpDir, "decisions/auth.md");
|
|
55
|
+
expect(history.length).toBeGreaterThanOrEqual(2);
|
|
56
|
+
expect(history[0].message).toContain("Update memory");
|
|
57
|
+
expect(history[1].message).toContain("Add memory");
|
|
58
|
+
});
|
|
59
|
+
it("returns empty array for non-existent file", () => {
|
|
60
|
+
const history = getFileHistory(tmpDir, "no/such/file.md");
|
|
61
|
+
expect(history).toEqual([]);
|
|
62
|
+
});
|
|
63
|
+
it("respects the limit parameter", async () => {
|
|
64
|
+
const fm = makeFrontmatter();
|
|
65
|
+
await store.writeMemory("decisions", "multi.md", fm, "# V1");
|
|
66
|
+
await store.updateMemory("decisions/multi.md", { title: "V2" });
|
|
67
|
+
await store.updateMemory("decisions/multi.md", { title: "V3" });
|
|
68
|
+
await store.updateMemory("decisions/multi.md", { title: "V4" });
|
|
69
|
+
const limited = getFileHistory(tmpDir, "decisions/multi.md", 2);
|
|
70
|
+
expect(limited).toHaveLength(2);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe("getFileAtCommit", () => {
|
|
74
|
+
it("retrieves file content at a specific commit", async () => {
|
|
75
|
+
const fm = makeFrontmatter({ title: "Original Title" });
|
|
76
|
+
await store.writeMemory("decisions", "version.md", fm, "# Original\n\nOriginal content");
|
|
77
|
+
// Get the first commit hash
|
|
78
|
+
const history1 = getFileHistory(tmpDir, "decisions/version.md");
|
|
79
|
+
const firstHash = history1[0].commitHash;
|
|
80
|
+
// Update
|
|
81
|
+
await store.updateMemory("decisions/version.md", { title: "Changed Title" });
|
|
82
|
+
// Retrieve original version
|
|
83
|
+
const original = getFileAtCommit(tmpDir, "decisions/version.md", firstHash);
|
|
84
|
+
expect(original).toBeTruthy();
|
|
85
|
+
expect(original).toContain("Original Title");
|
|
86
|
+
});
|
|
87
|
+
it("returns null for invalid commit hash", () => {
|
|
88
|
+
const result = getFileAtCommit(tmpDir, "decisions/version.md", "0000000000");
|
|
89
|
+
expect(result).toBeNull();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe("getFileDiff", () => {
|
|
93
|
+
it("shows diff between two commits", async () => {
|
|
94
|
+
const fm = makeFrontmatter({ title: "First" });
|
|
95
|
+
await store.writeMemory("decisions", "diff.md", fm, "# First\n\nContent A");
|
|
96
|
+
const history1 = getFileHistory(tmpDir, "decisions/diff.md");
|
|
97
|
+
const hash1 = history1[0].commitHash;
|
|
98
|
+
await store.updateMemory("decisions/diff.md", { title: "Second" }, "# Second\n\nContent B");
|
|
99
|
+
const history2 = getFileHistory(tmpDir, "decisions/diff.md");
|
|
100
|
+
const hash2 = history2[0].commitHash;
|
|
101
|
+
const diff = getFileDiff(tmpDir, "decisions/diff.md", hash1, hash2);
|
|
102
|
+
expect(diff).toBeTruthy();
|
|
103
|
+
expect(diff).toContain("First");
|
|
104
|
+
expect(diff).toContain("Second");
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe("rollbackToCommit", () => {
|
|
108
|
+
it("reverts a memory to a prior version", async () => {
|
|
109
|
+
const fm = makeFrontmatter({ title: "Original" });
|
|
110
|
+
await store.writeMemory("decisions", "rollback.md", fm, "# Original\n\nOriginal content");
|
|
111
|
+
const historyBefore = getFileHistory(tmpDir, "decisions/rollback.md");
|
|
112
|
+
const originalHash = historyBefore[0].commitHash;
|
|
113
|
+
// Update to new version
|
|
114
|
+
await store.updateMemory("decisions/rollback.md", { title: "Changed" }, "# Changed\n\nNew content");
|
|
115
|
+
// Verify it changed
|
|
116
|
+
const current = await store.readMemory("decisions/rollback.md");
|
|
117
|
+
expect(current?.frontmatter.title).toBe("Changed");
|
|
118
|
+
// Rollback
|
|
119
|
+
const success = rollbackToCommit(tmpDir, "decisions/rollback.md", originalHash);
|
|
120
|
+
expect(success).toBe(true);
|
|
121
|
+
// Verify it reverted
|
|
122
|
+
const reverted = await store.readMemory("decisions/rollback.md");
|
|
123
|
+
expect(reverted?.frontmatter.title).toBe("Original");
|
|
124
|
+
expect(reverted?.content).toContain("Original content");
|
|
125
|
+
});
|
|
126
|
+
it("creates a new commit for the rollback", async () => {
|
|
127
|
+
const fm = makeFrontmatter({ title: "Start" });
|
|
128
|
+
await store.writeMemory("decisions", "rb2.md", fm, "# Start");
|
|
129
|
+
const h1 = getFileHistory(tmpDir, "decisions/rb2.md");
|
|
130
|
+
await store.updateMemory("decisions/rb2.md", { title: "Middle" });
|
|
131
|
+
rollbackToCommit(tmpDir, "decisions/rb2.md", h1[0].commitHash);
|
|
132
|
+
const finalHistory = getFileHistory(tmpDir, "decisions/rb2.md");
|
|
133
|
+
expect(finalHistory.length).toBeGreaterThanOrEqual(3); // write, update, rollback
|
|
134
|
+
expect(finalHistory[0].message).toContain("Rollback");
|
|
135
|
+
});
|
|
136
|
+
it("returns false for invalid commit hash", () => {
|
|
137
|
+
const result = rollbackToCommit(tmpDir, "decisions/nope.md", "0000000");
|
|
138
|
+
expect(result).toBe(false);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
//# sourceMappingURL=history.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.test.js","sourceRoot":"","sources":["../../src/test/history.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.test.d.ts","sourceRoot":"","sources":["../../src/test/ingest.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for GnosysIngestion — structured ingestion (no LLM required).
|
|
3
|
+
* LLM-based ingest() is tested via integration tests only.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
import { GnosysStore } from "../lib/store.js";
|
|
10
|
+
import { GnosysTagRegistry } from "../lib/tags.js";
|
|
11
|
+
import { GnosysIngestion } from "../lib/ingest.js";
|
|
12
|
+
let tmpDir;
|
|
13
|
+
let store;
|
|
14
|
+
let tagRegistry;
|
|
15
|
+
let ingestion;
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "gnosys-ingest-test-"));
|
|
18
|
+
store = new GnosysStore(tmpDir);
|
|
19
|
+
await store.init();
|
|
20
|
+
// Seed tags
|
|
21
|
+
const defaultTags = {
|
|
22
|
+
domain: ["architecture", "auth", "testing"],
|
|
23
|
+
type: ["decision", "concept"],
|
|
24
|
+
concern: ["dx", "scalability"],
|
|
25
|
+
};
|
|
26
|
+
await fs.writeFile(path.join(tmpDir, "tags.json"), JSON.stringify(defaultTags, null, 2), "utf-8");
|
|
27
|
+
tagRegistry = new GnosysTagRegistry(tmpDir);
|
|
28
|
+
await tagRegistry.load();
|
|
29
|
+
ingestion = new GnosysIngestion(store, tagRegistry);
|
|
30
|
+
});
|
|
31
|
+
afterEach(async () => {
|
|
32
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
33
|
+
});
|
|
34
|
+
describe("GnosysIngestion", () => {
|
|
35
|
+
describe("isLLMAvailable", () => {
|
|
36
|
+
it("reports false when no API key is set", () => {
|
|
37
|
+
// In test environment, ANTHROPIC_API_KEY is typically not set
|
|
38
|
+
// Unless it is — in which case this test is still valid
|
|
39
|
+
// The property just reports whether the client was initialized
|
|
40
|
+
expect(typeof ingestion.isLLMAvailable).toBe("boolean");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("createStructured", () => {
|
|
44
|
+
it("creates a structured IngestResult with all fields", () => {
|
|
45
|
+
const result = ingestion.createStructured({
|
|
46
|
+
title: "Auth Decision",
|
|
47
|
+
category: "decisions",
|
|
48
|
+
tags: { domain: ["auth"], type: ["decision"] },
|
|
49
|
+
relevance: "auth JWT session OAuth login",
|
|
50
|
+
content: "We chose JWT for authentication.",
|
|
51
|
+
author: "human",
|
|
52
|
+
authority: "declared",
|
|
53
|
+
confidence: 0.95,
|
|
54
|
+
});
|
|
55
|
+
expect(result.title).toBe("Auth Decision");
|
|
56
|
+
expect(result.category).toBe("decisions");
|
|
57
|
+
expect(result.tags.domain).toEqual(["auth"]);
|
|
58
|
+
expect(result.relevance).toBe("auth JWT session OAuth login");
|
|
59
|
+
expect(result.content).toBe("We chose JWT for authentication.");
|
|
60
|
+
expect(result.confidence).toBe(0.95);
|
|
61
|
+
expect(result.filename).toBe("auth-decision");
|
|
62
|
+
});
|
|
63
|
+
it("generates kebab-case filename from title", () => {
|
|
64
|
+
const result = ingestion.createStructured({
|
|
65
|
+
title: "My Complex Title With CAPS",
|
|
66
|
+
category: "concepts",
|
|
67
|
+
tags: {},
|
|
68
|
+
content: "Content",
|
|
69
|
+
});
|
|
70
|
+
expect(result.filename).toBe("my-complex-title-with-caps");
|
|
71
|
+
});
|
|
72
|
+
it("truncates filename to 60 characters", () => {
|
|
73
|
+
const longTitle = "A".repeat(100);
|
|
74
|
+
const result = ingestion.createStructured({
|
|
75
|
+
title: longTitle,
|
|
76
|
+
category: "concepts",
|
|
77
|
+
tags: {},
|
|
78
|
+
content: "Content",
|
|
79
|
+
});
|
|
80
|
+
expect(result.filename.length).toBeLessThanOrEqual(60);
|
|
81
|
+
});
|
|
82
|
+
it("provides defaults for optional fields", () => {
|
|
83
|
+
const result = ingestion.createStructured({
|
|
84
|
+
title: "Minimal",
|
|
85
|
+
category: "concepts",
|
|
86
|
+
tags: {},
|
|
87
|
+
content: "Minimal content",
|
|
88
|
+
});
|
|
89
|
+
expect(result.relevance).toBe("");
|
|
90
|
+
expect(result.confidence).toBe(0.8);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe("end-to-end structured write", () => {
|
|
94
|
+
it("creates a valid memory file from structured input", async () => {
|
|
95
|
+
const result = ingestion.createStructured({
|
|
96
|
+
title: "E2E Test Memory",
|
|
97
|
+
category: "decisions",
|
|
98
|
+
tags: { domain: ["testing"], type: ["decision"] },
|
|
99
|
+
relevance: "e2e integration test structured ingestion",
|
|
100
|
+
content: "This memory was created via structured ingestion.",
|
|
101
|
+
confidence: 0.85,
|
|
102
|
+
});
|
|
103
|
+
const id = await store.generateId(result.category);
|
|
104
|
+
const today = new Date().toISOString().split("T")[0];
|
|
105
|
+
const frontmatter = {
|
|
106
|
+
id,
|
|
107
|
+
title: result.title,
|
|
108
|
+
category: result.category,
|
|
109
|
+
tags: result.tags,
|
|
110
|
+
relevance: result.relevance,
|
|
111
|
+
author: "ai",
|
|
112
|
+
authority: "observed",
|
|
113
|
+
confidence: result.confidence,
|
|
114
|
+
created: today,
|
|
115
|
+
modified: today,
|
|
116
|
+
last_reviewed: today,
|
|
117
|
+
status: "active",
|
|
118
|
+
supersedes: null,
|
|
119
|
+
};
|
|
120
|
+
const content = `# ${result.title}\n\n${result.content}`;
|
|
121
|
+
const relPath = await store.writeMemory(result.category, `${result.filename}.md`, frontmatter, content);
|
|
122
|
+
// Verify the file was written correctly
|
|
123
|
+
const memory = await store.readMemory(relPath);
|
|
124
|
+
expect(memory).not.toBeNull();
|
|
125
|
+
expect(memory.frontmatter.title).toBe("E2E Test Memory");
|
|
126
|
+
expect(memory.frontmatter.relevance).toBe("e2e integration test structured ingestion");
|
|
127
|
+
expect(memory.frontmatter.last_reviewed).toBe(today);
|
|
128
|
+
expect(memory.content).toContain("This memory was created via structured ingestion.");
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
//# sourceMappingURL=ingest.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.test.js","sourceRoot":"","sources":["../../src/test/ingest.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lensing.test.d.ts","sourceRoot":"","sources":["../../src/test/lensing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { applyLens, applyCompoundLens } from "../lib/lensing.js";
|
|
3
|
+
function makeMem(overrides = {}) {
|
|
4
|
+
const { content: body, ...fmOverrides } = overrides;
|
|
5
|
+
const frontmatter = {
|
|
6
|
+
id: "test-001",
|
|
7
|
+
title: "Test Memory",
|
|
8
|
+
category: "decisions",
|
|
9
|
+
tags: { domain: ["auth"], type: ["decision"] },
|
|
10
|
+
relevance: "test",
|
|
11
|
+
author: "human",
|
|
12
|
+
authority: "declared",
|
|
13
|
+
confidence: 0.8,
|
|
14
|
+
created: "2026-02-15",
|
|
15
|
+
modified: "2026-02-20",
|
|
16
|
+
status: "active",
|
|
17
|
+
supersedes: null,
|
|
18
|
+
...fmOverrides,
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
frontmatter,
|
|
22
|
+
content: body ?? "# Test",
|
|
23
|
+
filePath: `/tmp/test/${frontmatter.category}/${frontmatter.id}.md`,
|
|
24
|
+
relativePath: `${frontmatter.category}/${frontmatter.id}.md`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const memories = [
|
|
28
|
+
makeMem({ id: "d1", title: "Auth Decision", category: "decisions", tags: { domain: ["auth", "security"], type: ["decision"] }, confidence: 0.9, author: "human", authority: "declared", created: "2026-01-10", modified: "2026-01-15", status: "active" }),
|
|
29
|
+
makeMem({ id: "d2", title: "DB Choice", category: "decisions", tags: { domain: ["database"], type: ["decision"] }, confidence: 0.85, author: "human+ai", authority: "declared", created: "2026-02-01", modified: "2026-02-10", status: "active" }),
|
|
30
|
+
makeMem({ id: "a1", title: "Three Layers", category: "architecture", tags: { domain: ["backend"], type: ["concept"] }, confidence: 0.7, author: "ai", authority: "observed", created: "2026-02-15", modified: "2026-03-01", status: "active" }),
|
|
31
|
+
makeMem({ id: "c1", title: "Old Concept", category: "concepts", tags: { domain: ["frontend"], type: ["observation"] }, confidence: 0.5, author: "ai", authority: "inferred", created: "2025-12-01", modified: "2025-12-15", status: "superseded" }),
|
|
32
|
+
makeMem({ id: "a2", title: "Archived Arch", category: "architecture", tags: { domain: ["devops"], type: ["convention"] }, confidence: 0.6, author: "human", authority: "declared", created: "2026-01-20", modified: "2026-02-01", status: "archived" }),
|
|
33
|
+
];
|
|
34
|
+
describe("applyLens — single filters", () => {
|
|
35
|
+
it("filters by category", () => {
|
|
36
|
+
const result = applyLens(memories, { category: "decisions" });
|
|
37
|
+
expect(result).toHaveLength(2);
|
|
38
|
+
expect(result.map((m) => m.frontmatter.id)).toEqual(["d1", "d2"]);
|
|
39
|
+
});
|
|
40
|
+
it("filters by status", () => {
|
|
41
|
+
const result = applyLens(memories, { status: ["active"] });
|
|
42
|
+
expect(result).toHaveLength(3);
|
|
43
|
+
});
|
|
44
|
+
it("filters by multiple statuses", () => {
|
|
45
|
+
const result = applyLens(memories, { status: ["archived", "superseded"] });
|
|
46
|
+
expect(result).toHaveLength(2);
|
|
47
|
+
});
|
|
48
|
+
it("filters by tag (any mode)", () => {
|
|
49
|
+
const result = applyLens(memories, { tags: ["auth", "database"] });
|
|
50
|
+
expect(result).toHaveLength(2);
|
|
51
|
+
expect(result.map((m) => m.frontmatter.id)).toEqual(["d1", "d2"]);
|
|
52
|
+
});
|
|
53
|
+
it("filters by tag (all mode)", () => {
|
|
54
|
+
const result = applyLens(memories, { tags: ["auth", "security"], tagMatchMode: "all" });
|
|
55
|
+
expect(result).toHaveLength(1);
|
|
56
|
+
expect(result[0].frontmatter.id).toBe("d1");
|
|
57
|
+
});
|
|
58
|
+
it("filters by confidence range", () => {
|
|
59
|
+
const result = applyLens(memories, { minConfidence: 0.8, maxConfidence: 0.9 });
|
|
60
|
+
expect(result).toHaveLength(2);
|
|
61
|
+
});
|
|
62
|
+
it("filters by author", () => {
|
|
63
|
+
const result = applyLens(memories, { author: ["ai"] });
|
|
64
|
+
expect(result).toHaveLength(2);
|
|
65
|
+
});
|
|
66
|
+
it("filters by authority", () => {
|
|
67
|
+
const result = applyLens(memories, { authority: ["observed", "inferred"] });
|
|
68
|
+
expect(result).toHaveLength(2);
|
|
69
|
+
});
|
|
70
|
+
it("filters by created date range", () => {
|
|
71
|
+
const result = applyLens(memories, { createdAfter: "2026-02-01", createdBefore: "2026-03-01" });
|
|
72
|
+
expect(result).toHaveLength(2); // d2 and a1
|
|
73
|
+
});
|
|
74
|
+
it("filters by modified date range", () => {
|
|
75
|
+
const result = applyLens(memories, { modifiedAfter: "2026-02-01" });
|
|
76
|
+
expect(result).toHaveLength(3); // d2, a1, a2
|
|
77
|
+
});
|
|
78
|
+
it("empty filter returns all memories", () => {
|
|
79
|
+
const result = applyLens(memories, {});
|
|
80
|
+
expect(result).toHaveLength(5);
|
|
81
|
+
});
|
|
82
|
+
it("combines multiple criteria in one filter", () => {
|
|
83
|
+
const result = applyLens(memories, {
|
|
84
|
+
category: "decisions",
|
|
85
|
+
minConfidence: 0.85,
|
|
86
|
+
status: ["active"],
|
|
87
|
+
});
|
|
88
|
+
expect(result).toHaveLength(2); // d1 (0.9) and d2 (0.85)
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("applyCompoundLens", () => {
|
|
92
|
+
it("AND: all filters must match", () => {
|
|
93
|
+
const compound = {
|
|
94
|
+
operator: "AND",
|
|
95
|
+
filters: [
|
|
96
|
+
{ category: "decisions" },
|
|
97
|
+
{ minConfidence: 0.88 },
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
const result = applyCompoundLens(memories, compound);
|
|
101
|
+
expect(result).toHaveLength(1);
|
|
102
|
+
expect(result[0].frontmatter.id).toBe("d1");
|
|
103
|
+
});
|
|
104
|
+
it("OR: any filter can match", () => {
|
|
105
|
+
const compound = {
|
|
106
|
+
operator: "OR",
|
|
107
|
+
filters: [
|
|
108
|
+
{ category: "concepts" },
|
|
109
|
+
{ category: "architecture" },
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
const result = applyCompoundLens(memories, compound);
|
|
113
|
+
expect(result).toHaveLength(3); // a1, c1, a2
|
|
114
|
+
});
|
|
115
|
+
it("AND with no overlap returns empty", () => {
|
|
116
|
+
const compound = {
|
|
117
|
+
operator: "AND",
|
|
118
|
+
filters: [
|
|
119
|
+
{ category: "decisions" },
|
|
120
|
+
{ category: "architecture" },
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
const result = applyCompoundLens(memories, compound);
|
|
124
|
+
expect(result).toHaveLength(0);
|
|
125
|
+
});
|
|
126
|
+
it("OR deduplicates results", () => {
|
|
127
|
+
const compound = {
|
|
128
|
+
operator: "OR",
|
|
129
|
+
filters: [
|
|
130
|
+
{ status: ["active"] },
|
|
131
|
+
{ category: "decisions" }, // d1 and d2 are already in active
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
const result = applyCompoundLens(memories, compound);
|
|
135
|
+
expect(result).toHaveLength(3); // d1, d2, a1 — no duplicates
|
|
136
|
+
});
|
|
137
|
+
it("empty filters array returns all", () => {
|
|
138
|
+
const result = applyCompoundLens(memories, { operator: "AND", filters: [] });
|
|
139
|
+
expect(result).toHaveLength(5);
|
|
140
|
+
});
|
|
141
|
+
it("complex compound: decisions AND high-confidence AND recent", () => {
|
|
142
|
+
const compound = {
|
|
143
|
+
operator: "AND",
|
|
144
|
+
filters: [
|
|
145
|
+
{ category: "decisions" },
|
|
146
|
+
{ minConfidence: 0.85 },
|
|
147
|
+
{ createdAfter: "2026-01-01" },
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
const result = applyCompoundLens(memories, compound);
|
|
151
|
+
expect(result).toHaveLength(2); // d1 and d2
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=lensing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lensing.test.js","sourceRoot":"","sources":["../../src/test/lensing.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../src/test/search.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for GnosysSearch — FTS5 index, search, and discover operations.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
5
|
+
import fs from "fs/promises";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import os from "os";
|
|
8
|
+
import { GnosysStore } from "../lib/store.js";
|
|
9
|
+
import { GnosysSearch } from "../lib/search.js";
|
|
10
|
+
let tmpDir;
|
|
11
|
+
let store;
|
|
12
|
+
let search;
|
|
13
|
+
function makeFrontmatter(overrides = {}) {
|
|
14
|
+
return {
|
|
15
|
+
id: "test-001",
|
|
16
|
+
title: "Test Memory",
|
|
17
|
+
category: "decisions",
|
|
18
|
+
tags: { domain: ["testing"], type: ["decision"] },
|
|
19
|
+
relevance: "test unit testing vitest search",
|
|
20
|
+
author: "human",
|
|
21
|
+
authority: "declared",
|
|
22
|
+
confidence: 0.9,
|
|
23
|
+
created: "2026-03-06",
|
|
24
|
+
modified: "2026-03-06",
|
|
25
|
+
last_reviewed: "2026-03-06",
|
|
26
|
+
status: "active",
|
|
27
|
+
supersedes: null,
|
|
28
|
+
...overrides,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
beforeEach(async () => {
|
|
32
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "gnosys-search-test-"));
|
|
33
|
+
store = new GnosysStore(tmpDir);
|
|
34
|
+
await store.init();
|
|
35
|
+
search = new GnosysSearch(tmpDir);
|
|
36
|
+
});
|
|
37
|
+
afterEach(async () => {
|
|
38
|
+
search.close();
|
|
39
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
40
|
+
});
|
|
41
|
+
describe("GnosysSearch", () => {
|
|
42
|
+
describe("reindex + search", () => {
|
|
43
|
+
it("indexes memories and finds them by keyword", async () => {
|
|
44
|
+
await store.writeMemory("decisions", "auth.md", makeFrontmatter({
|
|
45
|
+
id: "deci-001",
|
|
46
|
+
title: "Authentication Decision",
|
|
47
|
+
relevance: "auth JWT tokens login session OAuth",
|
|
48
|
+
}), "# Authentication Decision\n\nWe use JWT tokens for auth.");
|
|
49
|
+
await store.writeMemory("concepts", "caching.md", makeFrontmatter({
|
|
50
|
+
id: "conc-001",
|
|
51
|
+
title: "Caching Strategy",
|
|
52
|
+
category: "concepts",
|
|
53
|
+
relevance: "cache Redis in-memory TTL invalidation",
|
|
54
|
+
}), "# Caching Strategy\n\nRedis is used for caching.");
|
|
55
|
+
await search.reindex(store);
|
|
56
|
+
const results = search.search("JWT tokens", 10);
|
|
57
|
+
expect(results.length).toBeGreaterThan(0);
|
|
58
|
+
expect(results[0].title).toBe("Authentication Decision");
|
|
59
|
+
});
|
|
60
|
+
it("returns empty array for no matches", async () => {
|
|
61
|
+
await search.reindex(store);
|
|
62
|
+
const results = search.search("nonexistent-query-xyz", 10);
|
|
63
|
+
expect(results).toEqual([]);
|
|
64
|
+
});
|
|
65
|
+
it("handles empty query", async () => {
|
|
66
|
+
const results = search.search("", 10);
|
|
67
|
+
expect(results).toEqual([]);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe("discover", () => {
|
|
71
|
+
it("discovers memories via relevance keyword cloud", async () => {
|
|
72
|
+
await store.writeMemory("decisions", "auth.md", makeFrontmatter({
|
|
73
|
+
id: "deci-001",
|
|
74
|
+
title: "Authentication Decision",
|
|
75
|
+
relevance: "auth JWT tokens login session OAuth SSO identity credentials",
|
|
76
|
+
}), "# Auth\n\nBasic content.");
|
|
77
|
+
await store.writeMemory("decisions", "db.md", makeFrontmatter({
|
|
78
|
+
id: "deci-002",
|
|
79
|
+
title: "Database Choice",
|
|
80
|
+
relevance: "database PostgreSQL SQL schema migration ORM",
|
|
81
|
+
}), "# DB\n\nBasic content.");
|
|
82
|
+
await search.reindex(store);
|
|
83
|
+
const results = search.discover("OAuth login", 10);
|
|
84
|
+
expect(results.length).toBeGreaterThan(0);
|
|
85
|
+
expect(results[0].title).toBe("Authentication Decision");
|
|
86
|
+
expect(results[0].relevance).toContain("OAuth");
|
|
87
|
+
});
|
|
88
|
+
it("falls back to full-text when column filter finds nothing", async () => {
|
|
89
|
+
await store.writeMemory("decisions", "hidden.md", makeFrontmatter({
|
|
90
|
+
id: "deci-001",
|
|
91
|
+
title: "Unrelated Title",
|
|
92
|
+
relevance: "unrelated keywords",
|
|
93
|
+
}), "# Unrelated\n\nThis content mentions PostgreSQL deep inside.");
|
|
94
|
+
await search.reindex(store);
|
|
95
|
+
// "PostgreSQL" is in content, not in relevance/title/tags
|
|
96
|
+
const results = search.discover("PostgreSQL", 10);
|
|
97
|
+
expect(results.length).toBeGreaterThan(0);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe("multi-store indexing", () => {
|
|
101
|
+
it("indexes multiple stores with label prefixes", async () => {
|
|
102
|
+
// Create a second store
|
|
103
|
+
const tmpDir2 = await fs.mkdtemp(path.join(os.tmpdir(), "gnosys-search-test2-"));
|
|
104
|
+
const store2 = new GnosysStore(tmpDir2);
|
|
105
|
+
await store2.init();
|
|
106
|
+
await store.writeMemory("decisions", "a.md", makeFrontmatter({ id: "deci-001", title: "Store 1 Memory" }), "# Store 1\n\nContent");
|
|
107
|
+
await store2.writeMemory("decisions", "b.md", makeFrontmatter({ id: "deci-002", title: "Store 2 Memory" }), "# Store 2\n\nContent");
|
|
108
|
+
search.clearIndex();
|
|
109
|
+
await search.addStoreMemories(store, "project");
|
|
110
|
+
await search.addStoreMemories(store2, "personal");
|
|
111
|
+
const results = search.search("Memory", 10);
|
|
112
|
+
expect(results.length).toBe(2);
|
|
113
|
+
const paths = results.map((r) => r.relative_path);
|
|
114
|
+
expect(paths.some((p) => p.startsWith("project:"))).toBe(true);
|
|
115
|
+
expect(paths.some((p) => p.startsWith("personal:"))).toBe(true);
|
|
116
|
+
await fs.rm(tmpDir2, { recursive: true, force: true });
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe("clearIndex", () => {
|
|
120
|
+
it("removes all entries from the index", async () => {
|
|
121
|
+
await store.writeMemory("decisions", "a.md", makeFrontmatter({ id: "deci-001" }), "# A\n\nContent");
|
|
122
|
+
await search.reindex(store);
|
|
123
|
+
expect(search.search("Content", 10).length).toBeGreaterThan(0);
|
|
124
|
+
search.clearIndex();
|
|
125
|
+
expect(search.search("Content", 10).length).toBe(0);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
//# sourceMappingURL=search.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../src/test/search.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../src/test/store.test.ts"],"names":[],"mappings":""}
|