@indigoai-us/cq 0.0.1

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 (177) hide show
  1. package/dist/__tests__/integration.test.d.ts +8 -0
  2. package/dist/__tests__/integration.test.d.ts.map +1 -0
  3. package/dist/__tests__/integration.test.js +233 -0
  4. package/dist/__tests__/integration.test.js.map +1 -0
  5. package/dist/budget/__tests__/budget.test.d.ts +2 -0
  6. package/dist/budget/__tests__/budget.test.d.ts.map +1 -0
  7. package/dist/budget/__tests__/budget.test.js +238 -0
  8. package/dist/budget/__tests__/budget.test.js.map +1 -0
  9. package/dist/budget/__tests__/token-tracker.test.d.ts +2 -0
  10. package/dist/budget/__tests__/token-tracker.test.d.ts.map +1 -0
  11. package/dist/budget/__tests__/token-tracker.test.js +292 -0
  12. package/dist/budget/__tests__/token-tracker.test.js.map +1 -0
  13. package/dist/budget/index.d.ts +38 -0
  14. package/dist/budget/index.d.ts.map +1 -0
  15. package/dist/budget/index.js +192 -0
  16. package/dist/budget/index.js.map +1 -0
  17. package/dist/budget/token-tracker.d.ts +62 -0
  18. package/dist/budget/token-tracker.d.ts.map +1 -0
  19. package/dist/budget/token-tracker.js +152 -0
  20. package/dist/budget/token-tracker.js.map +1 -0
  21. package/dist/budget/types.d.ts +41 -0
  22. package/dist/budget/types.d.ts.map +1 -0
  23. package/dist/budget/types.js +5 -0
  24. package/dist/budget/types.js.map +1 -0
  25. package/dist/confidence/__tests__/confidence.test.d.ts +2 -0
  26. package/dist/confidence/__tests__/confidence.test.d.ts.map +1 -0
  27. package/dist/confidence/__tests__/confidence.test.js +336 -0
  28. package/dist/confidence/__tests__/confidence.test.js.map +1 -0
  29. package/dist/confidence/erosion.d.ts +33 -0
  30. package/dist/confidence/erosion.d.ts.map +1 -0
  31. package/dist/confidence/erosion.js +42 -0
  32. package/dist/confidence/erosion.js.map +1 -0
  33. package/dist/confidence/index.d.ts +42 -0
  34. package/dist/confidence/index.d.ts.map +1 -0
  35. package/dist/confidence/index.js +168 -0
  36. package/dist/confidence/index.js.map +1 -0
  37. package/dist/confidence/types.d.ts +29 -0
  38. package/dist/confidence/types.d.ts.map +1 -0
  39. package/dist/confidence/types.js +5 -0
  40. package/dist/confidence/types.js.map +1 -0
  41. package/dist/curiosity/__tests__/curiosity.test.d.ts +2 -0
  42. package/dist/curiosity/__tests__/curiosity.test.d.ts.map +1 -0
  43. package/dist/curiosity/__tests__/curiosity.test.js +280 -0
  44. package/dist/curiosity/__tests__/curiosity.test.js.map +1 -0
  45. package/dist/curiosity/dedup.d.ts +29 -0
  46. package/dist/curiosity/dedup.d.ts.map +1 -0
  47. package/dist/curiosity/dedup.js +64 -0
  48. package/dist/curiosity/dedup.js.map +1 -0
  49. package/dist/curiosity/index.d.ts +56 -0
  50. package/dist/curiosity/index.d.ts.map +1 -0
  51. package/dist/curiosity/index.js +163 -0
  52. package/dist/curiosity/index.js.map +1 -0
  53. package/dist/curiosity/types.d.ts +29 -0
  54. package/dist/curiosity/types.d.ts.map +1 -0
  55. package/dist/curiosity/types.js +5 -0
  56. package/dist/curiosity/types.js.map +1 -0
  57. package/dist/index.d.ts +25 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +16 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/index.test.d.ts +2 -0
  62. package/dist/index.test.d.ts.map +1 -0
  63. package/dist/index.test.js +7 -0
  64. package/dist/index.test.js.map +1 -0
  65. package/dist/init.d.ts +17 -0
  66. package/dist/init.d.ts.map +1 -0
  67. package/dist/init.js +153 -0
  68. package/dist/init.js.map +1 -0
  69. package/dist/knowledge-tree/__tests__/knowledge-tree.test.d.ts +2 -0
  70. package/dist/knowledge-tree/__tests__/knowledge-tree.test.d.ts.map +1 -0
  71. package/dist/knowledge-tree/__tests__/knowledge-tree.test.js +317 -0
  72. package/dist/knowledge-tree/__tests__/knowledge-tree.test.js.map +1 -0
  73. package/dist/knowledge-tree/format.d.ts +17 -0
  74. package/dist/knowledge-tree/format.d.ts.map +1 -0
  75. package/dist/knowledge-tree/format.js +48 -0
  76. package/dist/knowledge-tree/format.js.map +1 -0
  77. package/dist/knowledge-tree/index.d.ts +33 -0
  78. package/dist/knowledge-tree/index.d.ts.map +1 -0
  79. package/dist/knowledge-tree/index.js +182 -0
  80. package/dist/knowledge-tree/index.js.map +1 -0
  81. package/dist/knowledge-tree/types.d.ts +37 -0
  82. package/dist/knowledge-tree/types.d.ts.map +1 -0
  83. package/dist/knowledge-tree/types.js +5 -0
  84. package/dist/knowledge-tree/types.js.map +1 -0
  85. package/dist/metadata/__tests__/metadata.test.d.ts +2 -0
  86. package/dist/metadata/__tests__/metadata.test.d.ts.map +1 -0
  87. package/dist/metadata/__tests__/metadata.test.js +196 -0
  88. package/dist/metadata/__tests__/metadata.test.js.map +1 -0
  89. package/dist/metadata/__tests__/search.test.d.ts +2 -0
  90. package/dist/metadata/__tests__/search.test.d.ts.map +1 -0
  91. package/dist/metadata/__tests__/search.test.js +227 -0
  92. package/dist/metadata/__tests__/search.test.js.map +1 -0
  93. package/dist/metadata/index.d.ts +29 -0
  94. package/dist/metadata/index.d.ts.map +1 -0
  95. package/dist/metadata/index.js +108 -0
  96. package/dist/metadata/index.js.map +1 -0
  97. package/dist/metadata/schema.d.ts +8 -0
  98. package/dist/metadata/schema.d.ts.map +1 -0
  99. package/dist/metadata/schema.js +31 -0
  100. package/dist/metadata/schema.js.map +1 -0
  101. package/dist/metadata/search.d.ts +27 -0
  102. package/dist/metadata/search.d.ts.map +1 -0
  103. package/dist/metadata/search.js +57 -0
  104. package/dist/metadata/search.js.map +1 -0
  105. package/dist/metadata/types.d.ts +17 -0
  106. package/dist/metadata/types.d.ts.map +1 -0
  107. package/dist/metadata/types.js +5 -0
  108. package/dist/metadata/types.js.map +1 -0
  109. package/dist/orchestrator/__tests__/orchestrator.test.d.ts +2 -0
  110. package/dist/orchestrator/__tests__/orchestrator.test.d.ts.map +1 -0
  111. package/dist/orchestrator/__tests__/orchestrator.test.js +354 -0
  112. package/dist/orchestrator/__tests__/orchestrator.test.js.map +1 -0
  113. package/dist/orchestrator/index.d.ts +23 -0
  114. package/dist/orchestrator/index.d.ts.map +1 -0
  115. package/dist/orchestrator/index.js +302 -0
  116. package/dist/orchestrator/index.js.map +1 -0
  117. package/dist/orchestrator/scheduler.d.ts +32 -0
  118. package/dist/orchestrator/scheduler.d.ts.map +1 -0
  119. package/dist/orchestrator/scheduler.js +102 -0
  120. package/dist/orchestrator/scheduler.js.map +1 -0
  121. package/dist/orchestrator/types.d.ts +90 -0
  122. package/dist/orchestrator/types.d.ts.map +1 -0
  123. package/dist/orchestrator/types.js +5 -0
  124. package/dist/orchestrator/types.js.map +1 -0
  125. package/dist/pipeline/__tests__/pipeline.test.d.ts +2 -0
  126. package/dist/pipeline/__tests__/pipeline.test.d.ts.map +1 -0
  127. package/dist/pipeline/__tests__/pipeline.test.js +320 -0
  128. package/dist/pipeline/__tests__/pipeline.test.js.map +1 -0
  129. package/dist/pipeline/index.d.ts +23 -0
  130. package/dist/pipeline/index.d.ts.map +1 -0
  131. package/dist/pipeline/index.js +212 -0
  132. package/dist/pipeline/index.js.map +1 -0
  133. package/dist/pipeline/types.d.ts +41 -0
  134. package/dist/pipeline/types.d.ts.map +1 -0
  135. package/dist/pipeline/types.js +5 -0
  136. package/dist/pipeline/types.js.map +1 -0
  137. package/dist/providers/__tests__/providers.test.d.ts +2 -0
  138. package/dist/providers/__tests__/providers.test.d.ts.map +1 -0
  139. package/dist/providers/__tests__/providers.test.js +195 -0
  140. package/dist/providers/__tests__/providers.test.js.map +1 -0
  141. package/dist/providers/claude-model.d.ts +17 -0
  142. package/dist/providers/claude-model.d.ts.map +1 -0
  143. package/dist/providers/claude-model.js +119 -0
  144. package/dist/providers/claude-model.js.map +1 -0
  145. package/dist/providers/index.d.ts +22 -0
  146. package/dist/providers/index.d.ts.map +1 -0
  147. package/dist/providers/index.js +38 -0
  148. package/dist/providers/index.js.map +1 -0
  149. package/dist/providers/openai-search.d.ts +14 -0
  150. package/dist/providers/openai-search.d.ts.map +1 -0
  151. package/dist/providers/openai-search.js +97 -0
  152. package/dist/providers/openai-search.js.map +1 -0
  153. package/dist/providers/types.d.ts +42 -0
  154. package/dist/providers/types.d.ts.map +1 -0
  155. package/dist/providers/types.js +5 -0
  156. package/dist/providers/types.js.map +1 -0
  157. package/dist/types.d.ts +122 -0
  158. package/dist/types.d.ts.map +1 -0
  159. package/dist/types.js +5 -0
  160. package/dist/types.js.map +1 -0
  161. package/dist/vetter/__tests__/vetter.test.d.ts +2 -0
  162. package/dist/vetter/__tests__/vetter.test.d.ts.map +1 -0
  163. package/dist/vetter/__tests__/vetter.test.js +224 -0
  164. package/dist/vetter/__tests__/vetter.test.js.map +1 -0
  165. package/dist/vetter/index.d.ts +23 -0
  166. package/dist/vetter/index.d.ts.map +1 -0
  167. package/dist/vetter/index.js +177 -0
  168. package/dist/vetter/index.js.map +1 -0
  169. package/dist/vetter/resource-tracker.d.ts +49 -0
  170. package/dist/vetter/resource-tracker.d.ts.map +1 -0
  171. package/dist/vetter/resource-tracker.js +183 -0
  172. package/dist/vetter/resource-tracker.js.map +1 -0
  173. package/dist/vetter/types.d.ts +44 -0
  174. package/dist/vetter/types.d.ts.map +1 -0
  175. package/dist/vetter/types.js +5 -0
  176. package/dist/vetter/types.js.map +1 -0
  177. package/package.json +72 -0
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Knowledge Tree type definitions.
3
+ */
4
+ /** Frontmatter metadata stored in YAML at the top of each .md file. */
5
+ export interface KnowledgeFrontmatter {
6
+ title: string;
7
+ tags: string[];
8
+ source?: string;
9
+ created: string;
10
+ updated: string;
11
+ }
12
+ /** A fully-parsed knowledge entry (frontmatter + body content). */
13
+ export interface KnowledgeEntry {
14
+ category: string;
15
+ slug: string;
16
+ title: string;
17
+ tags: string[];
18
+ source?: string;
19
+ created: string;
20
+ updated: string;
21
+ content: string;
22
+ }
23
+ /** Input for creating/updating an entry. */
24
+ export interface WriteEntryInput {
25
+ category: string;
26
+ slug?: string;
27
+ title: string;
28
+ content: string;
29
+ tags?: string[];
30
+ source?: string;
31
+ }
32
+ /** Summary of a category directory. */
33
+ export interface CategoryInfo {
34
+ name: string;
35
+ entryCount: number;
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/knowledge-tree/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Knowledge Tree type definitions.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/knowledge-tree/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=metadata.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.test.d.ts","sourceRoot":"","sources":["../../../src/metadata/__tests__/metadata.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,196 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { initMetadataDb, closeDb, getDb, indexEntry, removeFromIndex, getMetadata, getStaleEntries, } from "../index.js";
6
+ function makeEntry(overrides = {}) {
7
+ return {
8
+ category: "science",
9
+ slug: "quantum-basics",
10
+ title: "Quantum Computing Basics",
11
+ tags: ["quantum"],
12
+ created: "2025-01-01T00:00:00.000Z",
13
+ updated: "2025-06-01T00:00:00.000Z",
14
+ content: "Qubits are the fundamental unit of quantum computing.",
15
+ ...overrides,
16
+ };
17
+ }
18
+ beforeEach(() => {
19
+ initMetadataDb(":memory:");
20
+ });
21
+ afterEach(() => {
22
+ closeDb();
23
+ });
24
+ // ---------------------------------------------------------------------------
25
+ // initMetadataDb
26
+ // ---------------------------------------------------------------------------
27
+ describe("initMetadataDb", () => {
28
+ it("creates database with WAL journaling on disk", () => {
29
+ // WAL mode only applies to on-disk databases, not :memory:
30
+ closeDb();
31
+ const tmpDir = mkdtempSync(join(tmpdir(), "cq-meta-"));
32
+ const dbPath = join(tmpDir, "test.db");
33
+ initMetadataDb(dbPath);
34
+ const db = getDb();
35
+ const result = db.pragma("journal_mode");
36
+ expect(result[0].journal_mode).toBe("wal");
37
+ closeDb();
38
+ rmSync(tmpDir, { recursive: true, force: true });
39
+ // Re-init :memory: for remaining tests
40
+ initMetadataDb(":memory:");
41
+ });
42
+ it("is idempotent — can be called twice on the same path", () => {
43
+ // beforeEach already called once; calling again should not throw
44
+ closeDb();
45
+ initMetadataDb(":memory:");
46
+ initMetadataDb(":memory:");
47
+ });
48
+ });
49
+ // ---------------------------------------------------------------------------
50
+ // indexEntry
51
+ // ---------------------------------------------------------------------------
52
+ describe("indexEntry", () => {
53
+ it("inserts a new metadata row", () => {
54
+ const entry = makeEntry();
55
+ indexEntry(entry);
56
+ const meta = getMetadata("science", "quantum-basics");
57
+ expect(meta).toBeDefined();
58
+ expect(meta.title).toBe("Quantum Computing Basics");
59
+ expect(meta.category).toBe("science");
60
+ expect(meta.slug).toBe("quantum-basics");
61
+ expect(meta.confidence).toBe(1.0);
62
+ expect(meta.erosion_rate).toBe(0.0);
63
+ });
64
+ it("estimates token count from content (~4 chars per token)", () => {
65
+ const content = "A".repeat(100); // 100 chars → 25 tokens
66
+ indexEntry(makeEntry({ content }));
67
+ const meta = getMetadata("science", "quantum-basics");
68
+ expect(meta.token_count).toBe(25);
69
+ });
70
+ it("counts sources — 1 if source present, 0 otherwise", () => {
71
+ indexEntry(makeEntry({ source: "https://example.com" }));
72
+ expect(getMetadata("science", "quantum-basics").source_count).toBe(1);
73
+ // Overwrite without source
74
+ indexEntry(makeEntry({ source: undefined }));
75
+ expect(getMetadata("science", "quantum-basics").source_count).toBe(0);
76
+ });
77
+ it("upserts on conflict — updates existing row", () => {
78
+ indexEntry(makeEntry());
79
+ indexEntry(makeEntry({ title: "Quantum Updated" }));
80
+ const meta = getMetadata("science", "quantum-basics");
81
+ expect(meta.title).toBe("Quantum Updated");
82
+ });
83
+ it("preserves created_at from the entry on upsert", () => {
84
+ indexEntry(makeEntry());
85
+ const first = getMetadata("science", "quantum-basics");
86
+ indexEntry(makeEntry({ title: "Updated" }));
87
+ const second = getMetadata("science", "quantum-basics");
88
+ // created_at comes from entry.created, not current time
89
+ expect(second.created_at).toBe(first.created_at);
90
+ });
91
+ it("sets updated_at and last_verified_at to current time", () => {
92
+ const before = new Date().toISOString();
93
+ indexEntry(makeEntry());
94
+ const after = new Date().toISOString();
95
+ const meta = getMetadata("science", "quantum-basics");
96
+ expect(meta.updated_at >= before).toBe(true);
97
+ expect(meta.updated_at <= after).toBe(true);
98
+ expect(meta.last_verified_at >= before).toBe(true);
99
+ expect(meta.last_verified_at <= after).toBe(true);
100
+ });
101
+ it("throws if db not initialised", () => {
102
+ closeDb();
103
+ expect(() => indexEntry(makeEntry())).toThrow("Metadata DB not initialised");
104
+ });
105
+ });
106
+ // ---------------------------------------------------------------------------
107
+ // removeFromIndex
108
+ // ---------------------------------------------------------------------------
109
+ describe("removeFromIndex", () => {
110
+ it("removes an existing metadata row", () => {
111
+ indexEntry(makeEntry());
112
+ expect(getMetadata("science", "quantum-basics")).toBeDefined();
113
+ removeFromIndex("science", "quantum-basics");
114
+ expect(getMetadata("science", "quantum-basics")).toBeUndefined();
115
+ });
116
+ it("is a no-op for non-existent entries", () => {
117
+ // Should not throw
118
+ removeFromIndex("nonexistent", "nope");
119
+ });
120
+ it("throws if db not initialised", () => {
121
+ closeDb();
122
+ expect(() => removeFromIndex("a", "b")).toThrow("Metadata DB not initialised");
123
+ });
124
+ });
125
+ // ---------------------------------------------------------------------------
126
+ // getMetadata
127
+ // ---------------------------------------------------------------------------
128
+ describe("getMetadata", () => {
129
+ it("returns undefined for non-existent entry", () => {
130
+ expect(getMetadata("missing", "nothing")).toBeUndefined();
131
+ });
132
+ it("returns the full metadata row", () => {
133
+ indexEntry(makeEntry());
134
+ const meta = getMetadata("science", "quantum-basics");
135
+ expect(meta.slug).toBe("quantum-basics");
136
+ expect(meta.category).toBe("science");
137
+ expect(meta.title).toBe("Quantum Computing Basics");
138
+ expect(typeof meta.confidence).toBe("number");
139
+ expect(typeof meta.created_at).toBe("string");
140
+ expect(typeof meta.updated_at).toBe("string");
141
+ expect(typeof meta.last_verified_at).toBe("string");
142
+ expect(typeof meta.erosion_rate).toBe("number");
143
+ expect(typeof meta.token_count).toBe("number");
144
+ expect(typeof meta.source_count).toBe("number");
145
+ });
146
+ it("throws if db not initialised", () => {
147
+ closeDb();
148
+ expect(() => getMetadata("a", "b")).toThrow("Metadata DB not initialised");
149
+ });
150
+ });
151
+ // ---------------------------------------------------------------------------
152
+ // getStaleEntries
153
+ // ---------------------------------------------------------------------------
154
+ describe("getStaleEntries", () => {
155
+ it("returns entries at or below confidence threshold", () => {
156
+ // Index three entries
157
+ indexEntry(makeEntry({ category: "a", slug: "high" }));
158
+ indexEntry(makeEntry({ category: "a", slug: "low" }));
159
+ indexEntry(makeEntry({ category: "b", slug: "medium" }));
160
+ // Manually lower confidence for testing
161
+ const db = getDb();
162
+ db.prepare("UPDATE knowledge_meta SET confidence = 0.3 WHERE slug = 'low'").run();
163
+ db.prepare("UPDATE knowledge_meta SET confidence = 0.5 WHERE slug = 'medium'").run();
164
+ const stale = getStaleEntries(0.5);
165
+ expect(stale).toHaveLength(2);
166
+ expect(stale[0].slug).toBe("low"); // lowest first
167
+ expect(stale[1].slug).toBe("medium");
168
+ });
169
+ it("returns empty array when no entries are stale", () => {
170
+ indexEntry(makeEntry());
171
+ const stale = getStaleEntries(0.5);
172
+ expect(stale).toHaveLength(0);
173
+ });
174
+ it("returns all entries when threshold is 1.0", () => {
175
+ indexEntry(makeEntry({ category: "a", slug: "one" }));
176
+ indexEntry(makeEntry({ category: "b", slug: "two" }));
177
+ const stale = getStaleEntries(1.0);
178
+ expect(stale).toHaveLength(2);
179
+ });
180
+ it("results are ordered by confidence ascending", () => {
181
+ indexEntry(makeEntry({ category: "a", slug: "x" }));
182
+ indexEntry(makeEntry({ category: "a", slug: "y" }));
183
+ indexEntry(makeEntry({ category: "a", slug: "z" }));
184
+ const db = getDb();
185
+ db.prepare("UPDATE knowledge_meta SET confidence = 0.1 WHERE slug = 'z'").run();
186
+ db.prepare("UPDATE knowledge_meta SET confidence = 0.5 WHERE slug = 'y'").run();
187
+ db.prepare("UPDATE knowledge_meta SET confidence = 0.3 WHERE slug = 'x'").run();
188
+ const stale = getStaleEntries(1.0);
189
+ expect(stale.map((e) => e.slug)).toEqual(["z", "x", "y"]);
190
+ });
191
+ it("throws if db not initialised", () => {
192
+ closeDb();
193
+ expect(() => getStaleEntries(0.5)).toThrow("Metadata DB not initialised");
194
+ });
195
+ });
196
+ //# sourceMappingURL=metadata.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.test.js","sourceRoot":"","sources":["../../../src/metadata/__tests__/metadata.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../../src/metadata/__tests__/search.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,227 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { initMetadataDb, closeDb, getDb, indexEntry, removeFromIndex, } from "../index.js";
3
+ import { search, rebuildIndex } from "../search.js";
4
+ function makeEntry(overrides = {}) {
5
+ return {
6
+ category: "science",
7
+ slug: "quantum-basics",
8
+ title: "Quantum Computing Basics",
9
+ tags: ["quantum", "computing"],
10
+ created: "2025-01-01T00:00:00.000Z",
11
+ updated: "2025-06-01T00:00:00.000Z",
12
+ content: "Qubits are the fundamental unit of quantum computing.",
13
+ ...overrides,
14
+ };
15
+ }
16
+ beforeEach(() => {
17
+ initMetadataDb(":memory:");
18
+ });
19
+ afterEach(() => {
20
+ closeDb();
21
+ });
22
+ // ---------------------------------------------------------------------------
23
+ // FTS5 table creation
24
+ // ---------------------------------------------------------------------------
25
+ describe("FTS5 table", () => {
26
+ it("is created by initMetadataDb", () => {
27
+ const db = getDb();
28
+ const tables = db
29
+ .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'knowledge_fts'")
30
+ .all();
31
+ expect(tables).toHaveLength(1);
32
+ expect(tables[0].name).toBe("knowledge_fts");
33
+ });
34
+ });
35
+ // ---------------------------------------------------------------------------
36
+ // indexEntry → FTS sync
37
+ // ---------------------------------------------------------------------------
38
+ describe("indexEntry FTS sync", () => {
39
+ it("writes to knowledge_fts when indexing an entry", () => {
40
+ indexEntry(makeEntry());
41
+ const results = search("quantum");
42
+ expect(results).toHaveLength(1);
43
+ expect(results[0].category).toBe("science");
44
+ expect(results[0].slug).toBe("quantum-basics");
45
+ expect(results[0].title).toBe("Quantum Computing Basics");
46
+ });
47
+ it("updates FTS on re-index (upsert)", () => {
48
+ indexEntry(makeEntry());
49
+ indexEntry(makeEntry({
50
+ title: "Updated Title",
51
+ content: "Classical bits versus qubits.",
52
+ }));
53
+ // Should still be one result, not duplicated
54
+ const results = search("qubits");
55
+ expect(results).toHaveLength(1);
56
+ expect(results[0].title).toBe("Updated Title");
57
+ });
58
+ it("stores tags as JSON in FTS", () => {
59
+ indexEntry(makeEntry({ tags: ["physics", "computing"] }));
60
+ // Tags are searchable
61
+ const results = search("physics");
62
+ expect(results).toHaveLength(1);
63
+ });
64
+ });
65
+ // ---------------------------------------------------------------------------
66
+ // removeFromIndex → FTS sync
67
+ // ---------------------------------------------------------------------------
68
+ describe("removeFromIndex FTS sync", () => {
69
+ it("removes from knowledge_fts when removing from index", () => {
70
+ indexEntry(makeEntry());
71
+ expect(search("quantum")).toHaveLength(1);
72
+ removeFromIndex("science", "quantum-basics");
73
+ expect(search("quantum")).toHaveLength(0);
74
+ });
75
+ it("is a no-op for non-existent FTS entries", () => {
76
+ // Should not throw
77
+ removeFromIndex("nonexistent", "nope");
78
+ });
79
+ });
80
+ // ---------------------------------------------------------------------------
81
+ // search
82
+ // ---------------------------------------------------------------------------
83
+ describe("search", () => {
84
+ it("returns results ranked by BM25 relevance", () => {
85
+ // Entry with "quantum" in title AND content should rank higher
86
+ indexEntry(makeEntry({
87
+ category: "science",
88
+ slug: "quantum-deep",
89
+ title: "Quantum Quantum Quantum",
90
+ content: "Quantum mechanics is about quantum states and quantum entanglement.",
91
+ tags: ["quantum"],
92
+ }));
93
+ // Entry with "quantum" only once in content
94
+ indexEntry(makeEntry({
95
+ category: "misc",
96
+ slug: "general-physics",
97
+ title: "General Physics",
98
+ content: "Physics covers many areas including quantum mechanics.",
99
+ tags: ["physics"],
100
+ }));
101
+ const results = search("quantum");
102
+ expect(results).toHaveLength(2);
103
+ // The entry with more quantum mentions should rank first (lower BM25 = better)
104
+ expect(results[0].slug).toBe("quantum-deep");
105
+ expect(results[1].slug).toBe("general-physics");
106
+ });
107
+ it("returns snippet with markers", () => {
108
+ indexEntry(makeEntry({
109
+ content: "The quantum computer uses qubits to perform calculations at incredible speed.",
110
+ }));
111
+ const results = search("qubits");
112
+ expect(results).toHaveLength(1);
113
+ expect(results[0].snippet).toContain("<mark>");
114
+ expect(results[0].snippet).toContain("</mark>");
115
+ });
116
+ it("respects the limit parameter", () => {
117
+ for (let i = 0; i < 5; i++) {
118
+ indexEntry(makeEntry({
119
+ category: "cat",
120
+ slug: `entry-${i}`,
121
+ content: `Quantum computing entry number ${i}`,
122
+ }));
123
+ }
124
+ const results = search("quantum", 3);
125
+ expect(results).toHaveLength(3);
126
+ });
127
+ it("defaults limit to 10", () => {
128
+ for (let i = 0; i < 15; i++) {
129
+ indexEntry(makeEntry({
130
+ category: "cat",
131
+ slug: `entry-${i}`,
132
+ content: `Quantum computing entry number ${i}`,
133
+ }));
134
+ }
135
+ const results = search("quantum");
136
+ expect(results).toHaveLength(10);
137
+ });
138
+ it("returns empty array for no matches", () => {
139
+ indexEntry(makeEntry());
140
+ const results = search("nonexistent");
141
+ expect(results).toHaveLength(0);
142
+ });
143
+ it("includes rank as a number", () => {
144
+ indexEntry(makeEntry());
145
+ const results = search("quantum");
146
+ expect(results).toHaveLength(1);
147
+ expect(typeof results[0].rank).toBe("number");
148
+ });
149
+ it("supports FTS5 prefix queries", () => {
150
+ indexEntry(makeEntry({ content: "Computational chemistry is fascinating." }));
151
+ const results = search("comput*");
152
+ expect(results).toHaveLength(1);
153
+ });
154
+ it("supports FTS5 phrase queries", () => {
155
+ indexEntry(makeEntry({
156
+ category: "tech",
157
+ slug: "qc-intro",
158
+ title: "Introduction",
159
+ tags: [],
160
+ content: "Quantum computing is the future of technology.",
161
+ }));
162
+ indexEntry(makeEntry({
163
+ category: "other",
164
+ slug: "unrelated",
165
+ title: "Classical Algorithms",
166
+ tags: ["math"],
167
+ content: "The power of classical algorithms is immense.",
168
+ }));
169
+ const results = search('"quantum computing"');
170
+ expect(results).toHaveLength(1);
171
+ expect(results[0].slug).toBe("qc-intro");
172
+ });
173
+ it("throws if db not initialised", () => {
174
+ closeDb();
175
+ expect(() => search("test")).toThrow("Metadata DB not initialised");
176
+ });
177
+ });
178
+ // ---------------------------------------------------------------------------
179
+ // rebuildIndex
180
+ // ---------------------------------------------------------------------------
181
+ describe("rebuildIndex", () => {
182
+ it("rebuilds FTS from a list of entries", () => {
183
+ const entries = [
184
+ makeEntry({ category: "a", slug: "one", content: "Alpha content" }),
185
+ makeEntry({ category: "b", slug: "two", content: "Beta content" }),
186
+ makeEntry({ category: "c", slug: "three", content: "Gamma content" }),
187
+ ];
188
+ rebuildIndex(entries);
189
+ expect(search("alpha")).toHaveLength(1);
190
+ expect(search("beta")).toHaveLength(1);
191
+ expect(search("gamma")).toHaveLength(1);
192
+ expect(search("content")).toHaveLength(3);
193
+ });
194
+ it("clears previous FTS data before rebuilding", () => {
195
+ // Index an entry normally
196
+ indexEntry(makeEntry({
197
+ category: "old",
198
+ slug: "stale",
199
+ content: "This is old stale content.",
200
+ }));
201
+ expect(search("stale")).toHaveLength(1);
202
+ // Rebuild with different entries — old data should be gone
203
+ rebuildIndex([
204
+ makeEntry({ category: "new", slug: "fresh", content: "Fresh new data." }),
205
+ ]);
206
+ expect(search("stale")).toHaveLength(0);
207
+ expect(search("fresh")).toHaveLength(1);
208
+ });
209
+ it("handles empty entries array", () => {
210
+ indexEntry(makeEntry());
211
+ expect(search("quantum")).toHaveLength(1);
212
+ rebuildIndex([]);
213
+ expect(search("quantum")).toHaveLength(0);
214
+ });
215
+ it("preserves tags in rebuilt index", () => {
216
+ rebuildIndex([
217
+ makeEntry({ tags: ["deeplearning", "ai"] }),
218
+ ]);
219
+ const results = search("deeplearning");
220
+ expect(results).toHaveLength(1);
221
+ });
222
+ it("throws if db not initialised", () => {
223
+ closeDb();
224
+ expect(() => rebuildIndex([])).toThrow("Metadata DB not initialised");
225
+ });
226
+ });
227
+ //# sourceMappingURL=search.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../../src/metadata/__tests__/search.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Metadata Store — SQLite-backed metadata tracking for knowledge entries.
3
+ *
4
+ * Tracks confidence scores, token counts, erosion rates, and timestamps
5
+ * alongside the knowledge tree.
6
+ */
7
+ import Database from "better-sqlite3";
8
+ import type { KnowledgeMetadata } from "./types.js";
9
+ import type { KnowledgeEntry } from "../knowledge-tree/types.js";
10
+ export type { KnowledgeMetadata } from "./types.js";
11
+ /** Initialise (or open) the metadata SQLite database with WAL journaling. */
12
+ export declare function initMetadataDb(dbPath: string): Database.Database;
13
+ /** Close the database connection. */
14
+ export declare function closeDb(): void;
15
+ /** Return the current database instance (mainly for testing). */
16
+ export declare function getDb(): Database.Database | null;
17
+ /**
18
+ * Index (upsert) a KnowledgeEntry into the metadata store.
19
+ *
20
+ * Sets confidence to 1.0 and resets last_verified_at on every write.
21
+ */
22
+ export declare function indexEntry(entry: KnowledgeEntry): void;
23
+ /** Remove metadata for a specific entry. */
24
+ export declare function removeFromIndex(category: string, slug: string): void;
25
+ /** Retrieve metadata for a specific entry, or undefined if not found. */
26
+ export declare function getMetadata(category: string, slug: string): KnowledgeMetadata | undefined;
27
+ /** Return all entries with confidence at or below the given threshold. */
28
+ export declare function getStaleEntries(threshold: number): KnowledgeMetadata[];
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metadata/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAQpD,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAMhE;AAED,qCAAqC;AACrC,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED,iEAAiE;AACjE,wBAAgB,KAAK,IAAI,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAEhD;AAoBD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CA6CtD;AAED,4CAA4C;AAC5C,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAUpE;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,iBAAiB,GAAG,SAAS,CAQ/B;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAOtE"}